---
name: checkpoints-verificacion
description: Sistema de checkpoints del GSD para control de flujo entre agentes. Cubre los 3 tipos (human-verify, decision, human-action), formato XML, auto-mode, notificaciones y session snapshots atómicos para persistencia y reanudación. Incluye estructura completa de snapshot con mensajes, actividades, archivos modificados y último veredicto.
version: "1.1.0"
herramientasPermitidas: [Read, Write, Edit, Bash, Glob, Grep]
exclusiones:
  - "No cargar para pausar la ejecución por razones de incertidumbre del agente — los checkpoints son puntos de gobernanza definidos en el plan, no válvulas de escape ante duda."
  - "No cargar para crear más de un checkpoint `decision` por oleada; si hay múltiples bifurcaciones, consolidarlas en una decisión con opciones o escalar con `ejecutar-fase` Desviación Mayor."
  - "No cargar si la decisión ya está especificada en el PLAN.md o CONTEXTO.md — un checkpoint `decision` sobre algo ya resuelto es ruido de gobernanza."
  - "No cargar para registrar el estado de sesión entre agentes; para eso usar `execution-state.js` directamente."
evolvable: true  # default para skill estandar
---
# Checkpoints de Verificación GSD

## Cuándo NO cargar

- El agente quiere pausar porque no está seguro de cómo implementar algo — eso no es un checkpoint, es una Desviación Mayor en `ejecutar-fase`. Escalar a `arquitecto-swl` si el bloqueo es técnico.
- La decisión ya está en PLAN.md o CONTEXTO.md; ejecutar el plan sin pausa adicional.
- Se quiere registrar el estado entre agentes para serialización y reanudación; usar `execution-state.js` de `hooks/lib/` directamente — los checkpoints son para gobernanza, no para persistencia técnica.
- La bifurcación es claramente inferior en una opción; usar `human-verify` con recomendación, no `decision`.

## Concepto

Un **checkpoint** es un punto de pausa controlada en el flujo de ejecución del sistema GSD.

> **Si Claude PUEDE automatizar una decisión, DEBE automatizarla.**
> Solo se pausa cuando la decisión requiere juicio humano genuino, acción fuera del
> alcance del agente, o verificación de calidad que el agente no puede hacer por sí solo.

| Tipo | Frecuencia | Cuándo |
|------|-----------|--------|
| human-verify | ~90% | El agente termina, el humano confirma calidad |
| decision | ~9% | El agente necesita elegir entre caminos ambiguos |
| human-action | ~1% | El agente necesita algo que solo el humano puede hacer |

---

## 1. Tipo: human-verify

El agente completó una tarea y presenta resultados para revisión.

**Cuándo usar**: Al finalizar una fase, generar un documento importante, completar un slice vertical, o detectar una anomalía menor.

**Comportamiento**: Presentar checkpoint con toda la información, NO continuar hasta recibir respuesta (salvo `auto_advance: true`), registrar resultado en ESTADO.md.

Para templates XML completos y ejemplos concretos, ver [recursos/checkpoint-templates.md](recursos/checkpoint-templates.md).

---

## 2. Tipo: decision

El agente encontró una bifurcación donde ambos caminos son válidos pero con implicaciones distintas de negocio, riesgo o prioridad.

**Cuándo usar**: Tecnología A vs B no especificada en spec, migración big-bang vs incremental, dos normalizaciones igualmente válidas.

**Cuándo NO usar**: La spec ya especifica la decisión, una opción es claramente inferior, la decisión es fácilmente reversible.

**Regla de recomendación**: El agente SIEMPRE indica su recomendación con justificación técnica. No es neutral: tiene opinión fundamentada.

Para templates XML con pros/contras y ejemplos de migración, ver [recursos/checkpoint-templates.md](recursos/checkpoint-templates.md).

---

## 3. Tipo: human-action

El agente necesita que el humano realice una acción fuera de su alcance: configurar credenciales, aprobar gastos, ejecutar en sistemas restringidos.

**Cuándo usar**: Configurar secretos, aprobar cargos/licencias, ejecutar en producción con acceso restringido, contactar proveedor externo, aprobar PR con protección de rama.

Para templates XML con acciones numeradas y ejemplos de AWS Secrets Manager, ver [recursos/checkpoint-templates.md](recursos/checkpoint-templates.md).

---

## 4. Auto-Mode (auto_advance: true)

`auto_advance: true` se usa cuando el checkpoint es informativo: el agente reporta progreso pero no necesita confirmación para continuar.

**Reglas estrictas**:
- `auto_advance: true` SOLO para checkpoints de tipo `human-verify`
- NUNCA `auto_advance: true` en `decision` o `human-action`
- Valor por defecto: `false`

---

## 5. Integración con Notificaciones

Cada checkpoint emite notificación al canal configurado:

```javascript
const PRIORIDAD = {
  'human-action': 'urgente',    // notificación inmediata, todos los canales
  'decision':     'alta',       // notificación inmediata, canal principal
  'human-verify': 'normal',     // notificación normal, canal principal
};
```

---

## 6. Registro en ESTADO.md

Todo checkpoint resuelto se registra:

```markdown
| ID | Tipo | Estado | Resolución | Fecha |
|----|------|--------|-----------|-------|
| verify-plan-fase2 | human-verify | resuelto | aprobado | 2024-03-20 |
| decision-db-engine | decision | resuelto | opción-B | 2024-03-21 |
```

---

## Reglas de selección de tipo

| Situación | Tipo correcto |
|-----------|--------------|
| Agente terminó tarea, quiere confirmación | `human-verify` |
| Lint/tests pasan, reportar sin bloquear | `human-verify` con `auto_advance="true"` |
| Dos opciones igualmente válidas con distinto impacto | `decision` |
| Una opción claramente superior | `human-verify` con recomendación (NO `decision`) |
| Necesita credenciales, accesos o aprobaciones | `human-action` |

---

## Gotchas / Errores comunes no obvios

- **`auto_advance: true` en checkpoint `decision`**: el agente marca una decisión de bifurcación real como auto-advance porque "ya tiene preferencia". Causa: se confunde la recomendación del agente con la decisión del usuario. Solución: `auto_advance: true` es exclusivo de `human-verify`; cualquier `decision` o `human-action` siempre espera respuesta explícita del usuario — la regla no tiene excepciones.
- **Snapshot de sesión escrito con `fs.writeFileSync` en lugar de `atomicWriteJSON`**: si el proceso se interrumpe durante la escritura del snapshot, el archivo queda corrupto y la reanudación falla. Causa: se usa escritura directa por simplicidad. Solución: usar `atomicWriteJSON` de `hooks/lib/atomic-write.js` — escribe a `.tmp` primero y renombra, garantizando atomicidad.
- **Checkpoint sin `consecuencias_de_espera` en tipo `decision`**: el usuario no sabe cuánto tiempo puede esperar para decidir. Causa: campo omitido como opcional cuando en realidad es crítico para decisiones bloqueantes. Solución: siempre incluir `consecuencias_de_espera` especificando qué tareas quedan bloqueadas si el usuario no responde en N horas.
- **Session stale reanudada automáticamente después de 24 h**: el agente lee el snapshot con `updated_at` de 2 días antes y reanuda sin verificar. Causa: no se aplicó la detección de sesión stale. Solución: comparar `updated_at` con la hora actual; si hay más de 24 h y `status` es `active`, marcar como `stalled` y emitir `human-verify` antes de continuar.

## Anti-patrones

- Checkpoint sin `id` único (dificulta trazabilidad en ESTADO.md)
- `auto_advance: true` en `decision` o `human-action`
- Más de 4 opciones en un `decision` (sobrecarga cognitiva)
- `human-action` para algo que el agente puede hacer con sus herramientas
- `decision` sin campo `recomendacion`
- Omitir `consecuencias_de_espera` en `decision`

---

## 7. Estado de ejecución serializable — execution-state.json

Cuando un plan multi-agente se pausa (checkpoint) o un agente completa su trabajo,
registrar el estado en `.planning/execution-state.json` usando `hooks/lib/execution-state.js`.

Este archivo permite reanudar planes con estado preciso, sin reconstrucción de contexto
a partir de texto libre. Inspirado en el patrón ExecutionSnapshot de Sim Studio.

### Al completar un agente

```javascript
const es = require('./hooks/lib/execution-state');
es.completarAgente(process.cwd(), 'implementador-swl', 'api-endpoints', {
  archivosCreados:    ['src/api.py', 'tests/test_api.py'],
  archivosModificados: ['src/config.py'],
  resumen:            'API REST implementada con FastAPI, 4 endpoints, tests unitarios',
});
es.actualizarContexto(process.cwd(), {
  archivosModificados: ['src/api.py', 'tests/test_api.py'],
  testsStatus:         'passing',
  decisiones:          ['FastAPI por rendimiento', 'Pydantic v2 para validación'],
});
```

### Al pausar (checkpoint humano)

```javascript
// Registrar el próximo agente pendiente
es.establecerProximo(process.cwd(), 'revisor-codigo-swl', 'revision-api');
// El archivo execution-state.json persiste entre sesiones
```

### Al reanudar desde checkpoint

```javascript
// Leer el estado para saber dónde continuar
const estado = es.leer(process.cwd());
console.log(es.formatearResumen(process.cwd()));
// → "Plan: plan-x — Fase: implementacion
//    Agentes completados:
//      ✓ implementador-swl / api-endpoints
//    → revisor-codigo-swl / revision-api (próximo)"
```

### Referencias en prompts con variable-resolver

Los outputs registrados pueden referenciarse en prompts del orquestador:

```
Implementa los endpoints listados en {{planificador-swl.output.archivosACrear}}.
Decisiones ya tomadas: {{contexto.decisiones}}.
Tests actuales: {{contexto.testsStatus}}.
```

Resolver con `hooks/lib/variable-resolver.js`:

```javascript
const vr = require('./hooks/lib/variable-resolver');
const promptResuelto = vr.resolver(promptTemplate, process.cwd());
```

---

## 8. Session Snapshots — Persistencia atómica para reanudación

Cuando una sesión multi-agente se pausa o interrumpe, el snapshot captura el estado
completo para reanudar sin pérdida de contexto. Complementa `execution-state.json`
con información de actividad y veredictos.

### Estructura del snapshot

```json
{
  "metadata": {
    "session_id": "ses_abc123",
    "plan_id": "plan-modulo-pagos",
    "spec": "Implementar módulo de pagos con Stripe",
    "status": "paused | active | completed | failed",
    "iterations": 3,
    "created_at": "2026-04-12T10:00:00Z",
    "updated_at": "2026-04-12T14:30:00Z"
  },
  "state": {
    "current_phase": "implementacion",
    "activities": [
      {
        "agent": "implementador-swl",
        "task": "api-endpoints",
        "phase": "completed",
        "duration_ms": 45000
      },
      {
        "agent": "revisor-codigo-swl",
        "task": "revision-api",
        "phase": "in_progress",
        "duration_ms": null
      }
    ],
    "modified_files": [
      "src/api/pagos.py",
      "src/services/stripe_service.py",
      "tests/test_pagos.py"
    ],
    "git_tracking": {
      "branch": "feat/modulo-pagos",
      "commits_ahead": 3,
      "last_commit": "abc1234"
    }
  },
  "context": {
    "decisions": ["Stripe Checkout por simplicidad", "Webhooks async"],
    "tests_status": "passing",
    "pending_checkpoints": ["verify-integracion-stripe"]
  },
  "last_verdict": {
    "verdict": "Fail",
    "risk": "Medium",
    "score": 0.75,
    "failures": [{"artifact": "src/services/stripe_service.py", "level": "DATOS_FLUYEN", "reason": "Webhook no procesa evento checkout.session.completed"}],
    "nextStep": {"action": "Fix", "instructions": ["Implementar handler para checkout.session.completed en webhook endpoint"]}
  }
}
```

### Persistencia atómica

Escribir snapshots con el patrón write-tmp-rename para evitar corrupción:

```javascript
const { atomicWriteJSON } = require('./hooks/lib/atomic-write');
// Escribe a .tmp primero, luego renombra — si el proceso muere a mitad
// de escritura, el archivo original permanece intacto
atomicWriteJSON(path.join(planningDir, 'session-snapshot.json'), snapshot);
```

NUNCA escribir directamente al archivo de snapshot — una interrupción a mitad
de escritura corrompe el estado y pierde la capacidad de reanudación.

### Reanudación desde snapshot

Al reanudar una sesión pausada:

1. Leer `session-snapshot.json` con `execution-state.js`.
2. Verificar `last_verdict` — si fue `Fail`, las `nextStep.instructions` son la
   primera tarea del ejecutor.
3. Verificar `modified_files` contra el estado actual de git para detectar cambios
   externos durante la pausa.
4. Restaurar `context.decisions` para que los agentes no re-debatan decisiones ya tomadas.
5. Continuar desde `state.current_phase` con el siguiente agente pendiente.

### Detección de sesión stale

Si `updated_at` tiene más de 24 horas y `status` es `active`:

- Marcar como `stalled` en el snapshot.
- Emitir checkpoint `human-verify` para confirmar si se debe continuar o descartar.
- No reanudar automáticamente sesiones stale — pueden tener contexto desactualizado.
