---
name: doc-sync
description: Sincronización de documentación con el estado actual del código. Detecta documentos desactualizados (README, ADRs, docstrings, comentarios de API), genera un changelog estructurado de los cambios relevantes, y mantiene los Architecture Decision Records (ADRs) actualizados con las decisiones tomadas durante el desarrollo.
version: "1.3.0"
evolved: true
evolved-from: "1.2.0"
evolved-at: "2026-05-16"
evolved-by: "aprender"
evolved-note: "v1.3.0 (MINOR): sección nueva 'Protocolo proactivo: qué hacer al modificar componentes SWL' con sub-secciones por tipo (agente, skill, comando, hook, regla, variable de entorno, ADR, dependencia opt-in). Cierra el gap entre detección post-hoc (verificadores) y guía prescriptiva proactiva. Origen: feedback usuario 2026-05-16 — la información del flujo operativo estaba dispersa en 5 archivos (registro-componentes-nuevos.md + CLAUDE.md § Mapa + verificadores + reglas) sin un punto único invocable."
herramientasPermitidas: [Read, Bash, Glob, Grep]
exclusiones:
  - "No cargar para crear documentación nueva desde cero — este skill sincroniza documentación existente con el código actual; para crear documentación de feature nueva usar `documentador-swl` o escribir el README/ADR directamente."
  - "No cargar para mantener al día la documentación interna SWL (INVENTARIO.md, CLAUDE.md, manifiestos) — esa sincronización sigue la tabla de propagación de cambios de CLAUDE.md y no es responsabilidad de este skill."
  - "No cargar cuando no hay releases ni cambios significativos en los últimos 30 días — el costo del inventario y comparación es alto; si el proyecto está en pausa, la documentación no necesita sincronización."
  - "No cargar para validar la integridad del sistema SWL (frontmatter, exit codes de hooks) — eso es `validacion-ci-sistema`; este skill sincroniza documentación de usuario (README, ADRs, docstrings, OpenAPI)."
evolvable: true  # default para skill estandar
---
# Habilidad: Sincronización de Documentación con Código

## Propósito

La documentación que miente es peor que la documentación que no existe.
Un README con instrucciones de instalación obsoletas, un ADR que describe
una decisión revertida hace meses, o una API con docstrings que contradicen
el comportamiento real — todos estos son bugs de documentación que generan
desconfianza y pérdida de tiempo. Esta habilidad los detecta y los corrige.

## Cuándo activar

- Al completar una fase de desarrollo antes de marcar como "done"
- Al incorporar un colaborador nuevo que reporta confusión con la documentación
- Trimestralmente como revisión de mantenimiento
- Cuando el usuario reporta que "la documentación dice X pero el código hace Y"
- Antes de publicar una release o versión

---

## Paso 1 — Inventario de documentación existente

Identificar todos los artefactos de documentación en el proyecto:

```bash
# Todos los archivos de documentación
find . -name "*.md" -not -path "*/node_modules/*" -not -path "*/.git/*" | sort

# Docstrings en Python (verificar que existen)
grep -rn '"""' --include="*.py" -l

# JSDoc en TypeScript
grep -rn '/\*\*' --include="*.ts" -l

# OpenAPI / Swagger
find . -name "openapi.json" -o -name "openapi.yaml" -o -name "swagger.json" 2>/dev/null

# ADRs
find . -name "ADR-*.md" -o -path "*/adr/*.md" -o -path "*/decisions/*.md" | sort
```

Construir un mapa de documentación:

| Documento | Ruta | Última modificación | Última modificación del código relacionado |
|-----------|------|--------------------|--------------------------------------------|
| README.md | / | [fecha] | [fecha] |
| ADR-001.md | docs/adr/ | [fecha] | N/A (decisiones históricas) |
| API docs | docs/ | [fecha] | [fecha router modificado] |

---

## Paso 2 — Detectar desincronización

### README.md — Verificar secciones críticas

**Instalación y setup**:
```bash
# Probar las instrucciones de instalación desde cero (en directorio limpio)
# ¿Funcionan los comandos listados?
# ¿Faltan pasos que se añadieron al proceso?
```

Items a verificar:
- [ ] Versiones de runtime mencionadas (Python 3.X, Node X.Y) coinciden con `.python-version`, `package.json` engines
- [ ] Comandos de instalación funcionan como están escritos
- [ ] Variables de entorno en README coinciden con `.env.example`
- [ ] Comandos de ejecución del servidor son correctos
- [ ] Comandos de tests coinciden con la configuración actual (`pytest.ini`, `jest.config.*`)
- [ ] URLs de la API corresponden al router actual

**Señales de desincronización**:
```bash
# Variables de entorno usadas en el código vs documentadas
grep -rn "os\.getenv\|process\.env\." --include="*.py" --include="*.ts" \
  | grep -o '"[A-Z_]*"' | sort | uniq > env_en_codigo.txt
grep "^[A-Z_]*=" .env.example | cut -d= -f1 | sort > env_documentadas.txt
diff env_en_codigo.txt env_documentadas.txt

# Endpoints en el router vs documentados en README
grep -rn "@router\.\|app\.[get|post|put|delete]" --include="*.py" \
  | grep -o '"[/a-z_{}]*"' | sort > endpoints_reales.txt
grep -oE '/api/v[0-9]+/[a-z_/{}]*' README.md | sort > endpoints_readme.txt
diff endpoints_reales.txt endpoints_readme.txt
```

### Docstrings y comentarios de código

```bash
# Funciones públicas sin docstring (Python)
grep -rn "^def \|^    def " --include="*.py" -A1 | grep -v '"""' | grep "def " | head -30

# Docstrings que mencionan parámetros que ya no existen
# Revisión manual: comparar firma actual con docstring

# Comentarios TODO sin ticket
grep -rn "TODO\|FIXME" --include="*.py" --include="*.ts" | head -20
```

### OpenAPI / Swagger desactualizado

```bash
# FastAPI genera el schema automáticamente — verificar que coincide
# con la versión commiteada en docs/ (si la hay)
curl http://localhost:8000/openapi.json | python -m json.tool > /tmp/openapi_actual.json
diff docs/openapi.json /tmp/openapi_actual.json

# Si hay diferencias, actualizar el schema commiteado
```

---

## Paso 3 — Generar Changelog

El changelog documenta QUÉ cambió y POR QUÉ, no solo el listado de commits.

### Formato de CHANGELOG.md (Keep a Changelog)

```markdown
# CHANGELOG.md

Todos los cambios notables se documentan aquí.
Formato basado en [Keep a Changelog](https://keepachangelog.com/es/1.0.0/).

## [Sin publicar] — En desarrollo

## [2.1.0] — 2026-03-25

### Añadido
- Endpoint `GET /api/v1/reportes` con filtrado por fecha y usuario
- Autenticación con MFA para cuentas con rol ADMIN
- Soporte para exportación de datos en formato Excel

### Cambiado
- `POST /api/v1/pedidos` ahora requiere campo `bodega_id` (antes opcional)
- Tiempo de expiración de tokens JWT reducido de 24h a 8h

### Deprecado
- `GET /api/v1/usuarios/lista` — usar `GET /api/v1/usuarios` con paginación

### Eliminado
- Endpoint `POST /api/v1/auth/refresh-all` eliminado por riesgo de seguridad

### Corregido
- Error al calcular descuentos para clientes con múltiples contratos activos
- Timeout en exportaciones de más de 10,000 registros

### Seguridad
- CVE-2026-XXXXX: actualizado [paquete] de v1.2.3 a v1.2.4
```

### Cómo generar el changelog desde git

```bash
# Ver commits desde el último tag
git log $(git describe --tags --abbrev=0)..HEAD \
  --pretty=format:"- %s (%h)" --no-merges

# Ver qué archivos cambiaron en la última release
git diff $(git describe --tags --abbrev=0)..HEAD --name-only | sort

# Commits por tipo (si usan Conventional Commits)
git log --pretty=format:"%s" | grep "^feat:" | head -20
git log --pretty=format:"%s" | grep "^fix:" | head -20
git log --pretty=format:"%s" | grep "^security:" | head -20
```

---

## Paso 4 — Mantener ADRs vigentes

Un Architecture Decision Record (ADR) documenta una decisión de arquitectura:
qué se decidió, por qué, y cuáles eran las alternativas.

### Plantilla de ADR

```markdown
# ADR-[NNN]: [Título de la decisión]

**Estado**: Propuesto | Aceptado | Obsoleto | Reemplazado por ADR-[NNN]
**Fecha**: [YYYY-MM-DD]
**Decidido por**: [nombres o roles]

## Contexto

[Describir la situación que requirió una decisión. Qué problema existe,
qué restricciones aplican, qué opciones se consideraron.]

## Decisión

[La decisión tomada, en tiempo presente: "Usaremos X", "Adoptaremos Y".]

## Consecuencias

**Positivas**:
- [beneficio 1]
- [beneficio 2]

**Negativas / trade-offs**:
- [costo o limitación 1]
- [costo o limitación 2]

## Alternativas consideradas

### Alternativa A: [nombre]
- Ventajas: [lista]
- Desventajas: [lista]
- Razón de rechazo: [explicación]

### Alternativa B: [nombre]
- [ídem]

## Referencias
- [Link a issue, PR o documento relevante]
```

### Cuándo crear un ADR nuevo

Crear un ADR cuando se toma una decisión que:
- Afecta a más de un módulo o equipo
- Sería difícil o costosa de revertir
- Un desarrollador futuro podría cuestionar ("¿por qué hicieron esto?")
- Involucra un trade-off no obvio entre opciones razonables

### Cuándo marcar un ADR como "Obsoleto" o "Reemplazado"

Cuando el código ya no refleja lo que el ADR dice, actualizar el ADR:
```markdown
**Estado**: Reemplazado por ADR-012
**Nota**: La decisión de usar Redis como cache fue reemplazada por
Memcached en 2026-01 por restricciones de licencia del cliente.
```

NUNCA eliminar ADRs — son historia del proyecto.

---

## Checklist de sincronización completa

- [ ] README.md — instrucciones de instalación verificadas (funcionan paso a paso)
- [ ] README.md — variables de entorno en `.env.example` coinciden con el código
- [ ] README.md — comandos de ejecución y tests son correctos
- [ ] CHANGELOG.md — tiene entrada para todos los cambios de la fase actual
- [ ] Docstrings — funciones públicas documentadas y descripción coincide con firma
- [ ] OpenAPI — schema actualizado si se añadieron/modificaron endpoints
- [ ] ADRs — nuevas decisiones de arquitectura documentadas
- [ ] ADRs obsoletos — marcados con estado "Obsoleto" o "Reemplazado"
- [ ] TODOs con ticket — todos los `TODO` en código tienen referencia a issue

---

## Verificador automatizado doc-vs-código

Para proyectos con documentación extensa (>3 archivos `.md` activos) y
componentes inventariables (skills, comandos, agentes, flags, schemas), un
verificador automatizado **detecta drift sistemático** entre los archivos
de doc y el estado real del código. Es complementario al checklist manual.

### Patrón de los 5 checks portables

| # | Check | Qué verifica | FAIL vs WARN |
|---|---|---|---|
| **1** | **Contadores** | Cifras en `INVENTARIO.md` / `README.md` (60 agentes, 162 skills, etc.) vs conteo real en disco | FAIL si difiere |
| **2** | **Comandos / componentes en disco vs docs** | Cada componente con archivo en `comandos/`, `agentes/`, etc. tiene mención en `COMANDOS.md` y `MANUAL_USO.md` | WARN (deuda preexistente OK) |
| **3** | **Flags del parser vs `--help` y docs** | Booleanas declaradas en `scripts/lib/parsear-opciones.js` (o equivalente) aparecen en `bin --help` y tabla de opciones | FAIL para flags críticos |
| **4** | **Versión `package.json` vs encabezados** | Primera línea de cada `.md` canónico (`README`, `CLAUDE.md`, etc.) menciona la versión actual | FAIL |
| **5** | **Componentes UI vs docs** | Cada archivo en `scripts/tui/pantallas/` (o equivalente UI) tiene al menos una mención en `MANUAL_USO.md` | FAIL |

### Estructura recomendada del script

```javascript
// scripts/verificar-docs-vs-codigo.js — esqueleto portable
const fs = require('fs');
const path = require('path');
const RAIZ = path.resolve(__dirname, '..');

function leerArchivo(rel) { /* ... */ }
const resultados = [];
function reportar(check, etiqueta, ok, detalle) { /* OK / FAIL / WARN */ }

// Cada check es una función pura que llama reportar() N veces
function check1Contadores() { /* INVENTARIO.md tabla vs disco */ }
function check2Comandos()   { /* archivos en disco vs docs (WARN para deuda) */ }
function check3Flags()      { /* parser BOOLEANAS vs --help + docs */ }
function check4Versiones()  { /* package.json vs encabezados de .md */ }
function check5UIComponents() { /* archivos UI vs MANUAL_USO.md */ }

function main() {
  check1Contadores(); check2Comandos(); check3Flags();
  check4Versiones(); check5UIComponents();
  const fails = resultados.filter(r => !r.ok).length;
  process.exit(fails === 0 ? 0 : 1);
}
```

### Reglas operativas

- **WARN no falla CI** (deuda preexistente): use WARN para checks que
  detectan gaps de adopción incremental (ej: comandos viejos sin
  documentar). Si fuera FAIL, bloquearía el merge cuando lo correcto es
  documentar incrementalmente.
- **FAIL bloquea CI** (drift de release): use FAIL solo para checks que
  invalidarían el release (contadores incorrectos, versión incorrecta,
  flags críticos sin documentar).
- **Soporta flags `--check N` y `--quiet`**: permite ejecutar un check
  específico durante triage y suprimir output OK durante CI.
- **Integrado en `npm run test:all`**: el verificador corre tras los
  validadores estructurales (`validar.js`, `validar-manifest.js`) para
  que un PR con drift de docs falle CI antes del merge.
- **Exit codes 0/1/2**: 0 todo OK; 1 ≥1 FAIL; 2 error de invocación
  (archivo no existe, regex inválido).

### Origen del patrón

Aplicado en swl-ses v1.6.0 (`scripts/verificar-docs-vs-codigo.js`,
425 LOC). Detectó: 5 comandos `/swl:*` sin documentar (WARN, resuelto
incrementalmente), 0 drift de contadores, 0 drift de versiones, 1
pantalla TUI sin mención (resuelto en mismo commit). Tras integrar a
`npm run test:all`, drift futuro será bloqueado automáticamente.

**Portabilidad**: el patrón aplica a cualquier proyecto con `INVENTARIO`
+ docs + componentes inventariables. Adaptar las rutas y los regex de
extracción al stack del proyecto destino.

---

## Auditorías estructurales vs cosméticas

Un verificador automático que reporta "N/N checks OK" **no es prueba** de
que la documentación esté sincronizada — solo prueba que pasaron los
checks que ese verificador concretamente mide. La diferencia entre
**auditoría cosmética** y **auditoría estructural** es la dimensión más
importante de este skill.

### Diferencia operativa

| Dimensión | Auditoría cosmética | Auditoría estructural |
|---|---|---|
| **Métrica** | "¿aparece la palabra X?" | "¿está documentada con profundidad ≥ N?" |
| **Cobertura** | Muestra (whitelist hardcodeada) | Universo (catálogo completo cross-archivo) |
| **WARN treatment** | "WARN no falla, paso a OK" | "WARN es deuda visible que cuento separado" |
| **Reporte al usuario** | "N/N checks OK ✓" | "N/N gate formal OK + sondeo manual: X gaps detectados" |
| **Skip treatment** | "✓ skip" sumado al conteo positivo | "skip" reportado aparte, no como pass |

### Anti-patrones específicos a detectar

- **Verificador que cuenta "1 mención" como "documentado"**: bug grave.
  Un comando complejo con flags y dependencias externas necesita al
  menos 4 menciones (TOC + encabezado + uso + ejemplo). El gate debe
  exigir profundidad, no solo presencia.
- **Whitelist hardcodeada en check de flags**: "estas 7 flags
  críticas" deja fuera el universo real (todas las booleanas del
  parser). Cruzar contra `BOOLEANAS` completo o explicitar las
  excepciones.
- **WARN convertido en OK**: agregar `WARN no falla el verificador`
  al detalle pero seguir contando como OK en el agregado. Usuario
  ve "verde" y la deuda se acumula.
- **Reportar verde sin sondeo manual**: aceptar el output del
  verificador como prueba sin tomar 2-3 ítems del dominio y
  verificar profundidad real.
- **No detectar drift de catálogo**: variables de entorno, ADRs,
  skills nuevos — todos pueden aparecer en código sin entrar al
  catálogo documental si no hay gate de cobertura completa.

### Gates de profundidad obligatorios (referencia)

Para sistemas tipo SWL con catálogo formal de componentes:

| Dimensión | Métrica | Gate FAIL si... |
|---|---|---|
| Comandos `/swl:*` | Menciones en MANUAL_USO | <4 menciones para comando no trivial |
| Variables de entorno `SWL_*` | Cobertura en `docs/variables-entorno.md` | Cualquier variable en código sin entrada en catálogo |
| ADRs | Referencias en MANUAL_USO + CHANGELOG | ADR que cambia comportamiento sin referencia |
| Integraciones opt-in | Estructura mínima de 8 secciones | Cualquier dependencia documentada solo con instalación |

### Patrón de reporte al usuario (correcto)

```
Verificador docs-vs-código: 10/10 OK formal.
  - Check #1 contadores: 5/5 OK
  - Check #2 comandos: 44/44 con profundidad >= 4 (o triviales)
  - Check #3 flags: 7/7 críticas
  - Check #4 versiones: 6/6
  - Check #5 pantallas TUI: 8/8
  - Check #6 variables SWL_*: 55/58 (3 huérfanas restantes — TIPO B documentar)

Sondeo manual estructural:
  - ADRs no referenciados: 0/22 (todos vinculados en MANUAL_USO)
  - Integraciones opt-in con estructura completa: 7/7
  - Comandos infra-documentados detectados por gate: 0 (cerrados en mismo commit)

Conclusión: docs sincronizadas a profundidad estructural.
```

### Patrón de reporte al usuario (INCORRECTO — evitar)

```
Verificador: 9/9 OK. ✓ Docs alineadas con código.
```

Sin desglose de qué mide cada check, sin sondeo manual, sin enumerar
qué NO mide el verificador. Es lo que el usuario detectó como
"auditoría minimizada" en sesión 2026-05-16.

### Cómo aplicar este patrón a otros proyectos

El skeleton `scripts/verificar-docs-vs-codigo.js` de swl-ses (~425 LOC
con 6 checks) es portable a cualquier proyecto Node.js con manifiestos.
Adaptaciones típicas por proyecto:

1. **Check de comandos** → equivalente al de "endpoints documentados",
   "componentes UI documentados", "hooks documentados".
2. **Check de variables de entorno** → universal, mismo patrón.
3. **Check de ADRs/Decisiones** → si el proyecto trackea decisiones.
4. **Gates de profundidad** → ajustar `PROFUNDIDAD_MINIMA` según el
   dominio (4 para CLIs, 6-8 para endpoints HTTP con OpenAPI).

Origen del patrón: regla local `reglas/auditorias-documentales-estructurales.md`
en swl-ses + ADR-0023.

---

## Protocolo proactivo — qué hacer al modificar componentes SWL

Esta sección es **prescriptiva**: dice qué archivos tocar, qué comandos
ejecutar y qué verificar **cuando agregas o modificas** un componente
del sistema SWL. Cierra el gap entre detección post-hoc (verificadores)
y guía proactiva (no esperar a que el gate falle).

**Cuándo cargar este skill como protocolo**: el agente debe invocar
`Skill("doc-sync")` ANTES de hacer commits cuando ha modificado
componentes estructurales del sistema. CLAUDE.md § Mapa de propagación
de cambios tiene la tabla rápida y apunta aquí para el detalle.

### Principios generales que aplican a TODOS los tipos

1. **Registro en mismo commit**: cualquier componente nuevo/modificado se registra en sus manifiestos en el MISMO commit. Nunca diferir al siguiente. Origen: `reglas/registro-componentes-nuevos.md`.
2. **Profundidad ≥4 menciones**: para componentes con interfaz al usuario (comandos `/swl:*`, integraciones opt-in). Origen: `reglas/auditorias-documentales-estructurales.md`.
3. **Catálogo formal único**: variables de entorno en `docs/variables-entorno.md`, ADRs en `.planning/adrs/README.md`, componentes en `INVENTARIO.md`. NO duplicar entre archivos.
4. **Regenerar inventario al final**: `node scripts/generar-inventario.js` actualiza `INVENTARIO.md` y `SALUD.md`. Hacerlo antes del commit final.
5. **Gate antes de commit**: `npm run test:all` (incluye `verificar-docs-vs-codigo.js`). Si falla, NO commitear hasta corregir.

### Tipo 1 — Agente nuevo o modificado (`agentes/*.md`)

**Crear nuevo `agentes/X-swl.md`:**

| Archivo | Acción | Por qué |
|---|---|---|
| `agentes/X-swl.md` | Crear con frontmatter completo (`name`, `description`, `version`, `nivelRiesgo`, `tools`, `exclusiones`, `model` si aplica) | Componente principal |
| `plugin.json` | Agregar a array `agents` | Plugin descriptor para runtimes Claude Code |
| `manifiestos/modulos.json` | Agregar al módulo del dominio (backend/frontend/calidad/etc.) | Instalador propaga al destino |
| `AGENTS.md` | Agregar entrada al catálogo con capacidades | Documentación humana del catálogo |
| `INVENTARIO.md` | Regenerar con `node scripts/generar-inventario.js` | Contador oficial |
| `SALUD.md` | Regenerar (mismo script) | Health check |

**Modificar agente existente:**

- Si cambias `model`: verificar que la asignación respeta la tabla de Model-Tier del CLAUDE.md (crítico=Opus, estándar=Sonnet, ligero=Haiku).
- Si cambias `tools`: si declaras `skillsInvocables: [...]` Y usas `Skill(...)` en el cuerpo, debe incluir `Skill` en `tools:` (regla CLAUDE.md).
- Si agregas/quitas fragmentos: declarar `fragmentos: [_nombre]` en frontmatter (regla `fragmentos-compartidos.md`).

**Comando a ejecutar al final**: `npm run test:all`. El gate valida frontmatter, manifiestos y permisos.

### Tipo 2 — Skill nuevo o modificado (`habilidades/X/SKILL.md`)

**Crear nuevo `habilidades/X/SKILL.md`:**

| Archivo | Acción | Por qué |
|---|---|---|
| `habilidades/X/SKILL.md` | Crear con frontmatter (`name`, `description`, `version`, `evolved: false`, `herramientasPermitidas`, `exclusiones`) y prefijo de dominio en el nombre (backend-/frontend-/mobile-/datos-/etc.) | Componente principal |
| `plugin.json` | Agregar a array `skills` | Plugin descriptor |
| `manifiestos/modulos.json` | Agregar al módulo del dominio | Instalador |
| `manifiestos/skills-lock.json` | (auto-generado al ejecutar inventario) | Lock de versión por skill |
| `INVENTARIO.md` + `SALUD.md` | Regenerar | Contador oficial |
| `CLAUDE.md` § Sistema de habilidades | Solo si aplica al dominio principal | Discoverability |

**Modificar skill existente con cambio de contenido:**

Aplica el bump SemVer y los metadatos `evolved`:

```bash
# 1. Detectar tipo de cambio
# - Gotcha nuevo, regla nueva, fix redacción: PATCH (X.Y.Z → X.Y.Z+1)
# - Sección nueva, alcance ampliado: MINOR (X.Y.0 → X.Y+1.0)
# - Redefinición incompatible: MAJOR (X.0.0 → X+1.0.0)

# 2. Editar frontmatter del skill:
#    version: "1.X.Y"  (bump según tipo)
#    evolved: true
#    evolved-from: "<versión-anterior>"
#    evolved-at: "YYYY-MM-DD"
#    evolved-by: "aprender" (o "evolucionar", "manual")
#    evolved-note: "<descripción breve>"

# 3. Verificar antes de commit
node bin/swl-ses.js verify-evolution --changed --since=HEAD
```

**Comando a ejecutar al final**: `npm run test:all` + `npx swl-ses verify-evolution --changed --since=HEAD`. La verificación de evolución es gate obligatorio (regla `gobernanza.md` G8).

### Tipo 3 — Comando `/swl:*` nuevo o modificado (`comandos/swl/X.md`)

**Crear nuevo `comandos/swl/X.md`:**

| Archivo | Acción | Por qué |
|---|---|---|
| `comandos/swl/X.md` | Crear archivo del slash command con frontmatter y cuerpo de instrucciones | Componente principal |
| `manifiestos/modulos.json` | Agregar a módulo del dominio | Instalador |
| `COMANDOS.md` | Agregar entrada con flags, descripción, ejemplo | Catálogo de referencia |
| `CLAUDE.md` § tabla de comandos `/swl:*` | Agregar línea con propósito | Discovery rápida |
| `MANUAL_USO.md` | Agregar sección dedicada con **mínimo 4 menciones del comando** (TOC + encabezado + Uso + ejemplo) | **Gate Check #2 endurecido** |
| `INVENTARIO.md` | Regenerar | Contador oficial |

**Estructura mínima obligatoria en MANUAL_USO.md** (gate de profundidad):

```markdown
### `/swl:nombre-comando`

**Uso:** `/swl:nombre-comando [flags y argumentos]`

**¿Qué hace?**
Descripción funcional en 2-3 oraciones.

**Cuándo usarlo:**
- Caso de uso 1
- Caso de uso 2

**Ejemplos concretos**:
\`\`\`bash
/swl:nombre-comando                  # caso default
/swl:nombre-comando --flag valor     # con argumentos
\`\`\`

**Troubleshooting** (si tiene dependencias externas):
Problemas frecuentes y soluciones.
```

Los comandos triviales (`ayuda`, `salud`, `modelo`, `contexto`, `dashboard`, `sesiones`, `instintos`, `metricas`, `mcp-status`) están exentos del gate ≥4 menciones (lista hardcodeada en `scripts/verificar-docs-vs-codigo.js`).

**Comando a ejecutar al final**: `npm run test:all`.

### Tipo 4 — Hook nuevo o modificado (`hooks/X.js`)

**Crear nuevo `hooks/X.js`:**

| Archivo | Acción | Por qué |
|---|---|---|
| `hooks/X.js` | Crear con zero-deps (importar solo de `hooks/lib/`) y exit code 0 (regla seguridad-agentes) | Componente principal |
| `plugin.json` | Agregar a array `hooks` (si aplica) | Plugin descriptor |
| `.claude/settings.json` | Agregar event + matcher (`PreToolUse`, `PostToolUse`, `Stop`, etc.) | Settings local |
| `manifiestos/hooks-config.json` | Agregar `event` + `matcher` + `blocking` | Instalador propaga la config |
| `manifiestos/modulos.json` | Agregar ruta del archivo al módulo | Instalador copia el archivo |
| `INVENTARIO.md` + `SALUD.md` | Regenerar | Contador oficial |

**Punto crítico — AMBOS manifiestos son obligatorios**: si solo agregas a `.claude/settings.json` pero no a `manifiestos/hooks-config.json`, el hook NO se propaga al destino del instalador. Y viceversa.

**Si el hook usa variable de entorno opt-in `SWL_*`**:
- Documentarla en `docs/variables-entorno.md` en sección apropiada (Auditoría / Notificaciones / Drift / Daemon / etc.) en el MISMO commit.
- Gate Check #6 falla si la variable existe en código pero no en catálogo.

**Comando a ejecutar al final**: `npm run test:manifest` (valida ambos manifiestos) + `npm run test:all`.

### Tipo 5 — Regla nueva o modificada (`reglas/X.md`)

**Crear nueva `reglas/X.md`:**

| Archivo | Acción | Por qué |
|---|---|---|
| `reglas/X.md` | Crear archivo con título, principio, cómo aplicar, anti-patrones, origen | Componente principal |
| `CLAUDE.md` § tabla de reglas | Agregar línea con matcher | Discovery + carga automática |
| `manifiestos/modulos.json` | Agregar al módulo correspondiente | Instalador |
| `INVENTARIO.md` + `SALUD.md` | Regenerar | Contador oficial |

**Si la regla es transversal a múltiples proyectos del usuario**:
- Considerar promoverla a `~/.claude/rules/X.md` (regla global) en lugar de local del proyecto.
- Las globales se cargan automáticamente en TODOS los proyectos del usuario.

**Regla obligatoria nueva**: si declaras la regla como obligatoria para todos los agentes, es un cambio **MAJOR** del sistema (regla `gobernanza.md`). Requiere ADR + período de revisión.

**Comando a ejecutar al final**: `npm run test:all`.

### Tipo 6 — Variable de entorno opt-in `SWL_*` nueva o modificada

**Agregar variable nueva `SWL_NUEVA_VAR` en hook o script:**

| Archivo | Acción | Por qué |
|---|---|---|
| `hooks/X.js` o `scripts/Y.js` | Código que usa `process.env.SWL_NUEVA_VAR` con patrón `if (!process.env.X) return` | Componente principal |
| `docs/variables-entorno.md` | Agregar entrada en sección apropiada con: nombre, default, archivo que la consume, qué activa, cómo desactivar | **Catálogo formal único — gate Check #6** |
| `MANUAL_USO.md` | (opcional) Mención si es relevante al flujo del usuario final | Discovery |

**Sección apropiada en `docs/variables-entorno.md`** según el dominio:
- Auditoría y observabilidad
- Mission Control externo
- Calidad de CLAUDE.md
- Drift y auto-evolución
- Clasificador y monitor de contexto
- Webhook entrante HTTP local
- Protección de rutas
- Daemon SWL
- MCP server
- Notificaciones y output
- Captura de feedback y perfil de usuario
- Update check y release
- Hooks: control de wrapper y paths
- Telemetría y registro de turnos
- Workflows y herramientas inferidas
- Filtros de extracción
- Debug y desarrollo del propio SWL

Si tu variable no encaja en ninguna, **NO** crees sección nueva por una sola variable — agregar a la más cercana con nota o consultar al maintainer.

**Comando a ejecutar al final**: `node scripts/verificar-docs-vs-codigo.js --check 6`. Falla si la variable está en código pero no en el catálogo.

### Tipo 7 — ADR nuevo (`.planning/adrs/NNNN-titulo.md`)

**Crear nuevo ADR:**

| Archivo | Acción | Por qué |
|---|---|---|
| `.planning/adrs/NNNN-titulo.md` | Crear con frontmatter (fecha, estado, decisores, relacionado) y secciones obligatorias (Contexto, Decisión, Por qué, Alternativas, Consecuencias, Origen) | Componente principal |
| `.planning/adrs/README.md` | Agregar fila a la tabla "Estado de cada ADR" con número, título corto, estado, fecha | **Índice obligatorio (regla `arquitectura.md`)** |
| `MANUAL_USO.md` | Referenciar el ADR en la sección del feature que materializa, **si cambia comportamiento observable** | Discovery del usuario |
| `CHANGELOG.md` | Mencionar en la versión que lo introduce | Trazabilidad |

**Estado del ADR**:
- `Propuesto`: en discusión, NO implementado. Debe tener fecha de reevaluación 6-12 meses y criterios de disparo.
- `Aceptado`: decisión final, implementación en curso o completada.
- `Deprecado`: sigue vigente pero se anticipa reemplazo.
- `Reemplazado por ADR NNN`: superado por otro ADR.
- `Descartado`: se evaluó y se decidió NO adoptar.

**Numeración estricta**: el ADR nuevo recibe el siguiente número secuencial. NUNCA reutilizar un número, ni siquiera de ADRs descartados.

**Comando a ejecutar al final**: ninguno automatizado. La validez del ADR es revisión humana.

### Tipo 8 — Dependencia externa opt-in nueva

**Documentar nueva dependencia opt-in (markitdown, agent-browser, code-review-graph, etc.):**

`MANUAL_USO.md § Dependencias externas — referencia detallada` con **estructura mínima de 8 secciones** obligatorias (regla `auditorias-documentales-estructurales.md`):

1. **Marcador obligatorio**: "NO es dependencia técnica de swl-ses" (regla CLAUDE.md sobre dependencias educativas opt-in).
2. **Qué es** y **por qué existe la integración** (no solo instalación).
3. **Beneficio cuantificado** vs alternativas (tokens, espacio, tiempo — números, no adjetivos).
4. **Cuándo vale la pena** vs **cuándo NO instalarlo**.
5. **Cómo lo usa el sistema** internamente (qué agente/skill/comando lo invoca — tabla).
6. **Comportamiento si NO está instalado** (debe degradar funcionalmente sin fallar — regla `arreglar-al-detectar`).
7. **Limitaciones conocidas**.
8. **Origen** (ADR, sesión, paper, repo).

Si la dependencia se distribuye via `npx`, **validar costo de tarball** con `npm view <paquete> dist.unpackedSize` antes de aceptar (regla global `analisis-previo-tareas-grandes.md § Validar costo real de deps`).

**Comando a ejecutar al final**: `npm run test:all` (Check #2 valida mención mínima).

---

### Checklist único antes de cualquier commit estructural

Ejecuta en orden:

```bash
# 1. Regenerar inventario (single source of truth de contadores)
node scripts/generar-inventario.js

# 2. Verificar manifiestos coherentes
npm run test:manifest

# 3. Si modificaste skill o agente: verificar evolución
npx swl-ses verify-evolution --changed --since=HEAD

# 4. Verificar docs-vs-código (10 checks)
node scripts/verificar-docs-vs-codigo.js

# 5. Suite completa
npm run test:all

# 6. (solo antes de release) Gate pre-publish
node scripts/verificar-release.js
```

Si CUALQUIER paso falla, **no commitees**. Corregir primero. La regla
`arreglar-al-detectar.md` exige resolver en mismo turno, no diferir.

---

## Regla de cierre

Ninguna fase se marca como "completada" si la documentación contradice
el código implementado. La doc desactualizada es deuda técnica de primer nivel.

## Cuándo NO cargar

- No hay documentación existente que sincronizar — este skill compara docs existentes con el código; si el proyecto no tiene README, ADRs ni docstrings, crear esos artefactos primero con `documentador-swl`.
- Los únicos artefactos que necesitan actualización son manifiestos SWL internos (INVENTARIO.md, CLAUDE.md, plugin.json) — esa actualización sigue la tabla de propagación de cambios de CLAUDE.md, no el flujo de 4 pasos de este skill.
- El proyecto lleva más de 30 días sin commits — si no hay cambios en el código, la documentación no puede estar desactualizada respecto al código; el checklist de sincronización no aplica.
- Se necesita validar integridad estructural del sistema SWL — eso es `validacion-ci-sistema`; este skill valida coherencia entre documentación de usuario y código, no frontmatter de agentes ni exit codes de hooks.

## Gotchas / Errores comunes no obvios

- **README marcado como desactualizado porque `grep` encontró un nombre de variable cambiado en un comentario**: el Paso 2 busca variables de entorno que aparezcan en el código pero no en `.env.example`, y el agente concluye que el README está obsoleto. Causa: el grep de variables detecta comentarios y strings de ejemplo, no solo declaraciones reales. Solución: al comparar variables de entorno, filtrar por el patrón de uso real (`os.getenv`, `process.env`, `os.environ`) y excluir archivos de ejemplo y tests.
- **ADR marcado como "Obsoleto" en lugar de "Reemplazado por ADR-NNN"**: el agente marca decisiones revertidas como obsoletas sin crear el ADR de reemplazo primero. Causa: el estado "Obsoleto" se usa cuando no hay decisión sustituta; "Reemplazado" requiere que el ADR sustituto ya exista. Solución: si la decisión fue reemplazada por otra (no solo abandonada), crear el ADR de reemplazo en el mismo commit y referenciar el número — nunca marcar como "Reemplazado por ADR-NNN" si ese ADR no existe aún.
- **Changelog generado desde `git log` incluye commits de fix de typo y WIP que no son relevantes para usuarios**: el changelog resultante tiene 40 entradas de "fix: typo" y "wip: progress". Causa: `git log --pretty=format:"- %s"` incluye todos los commits sin filtrar. Solución: usar `git log` con filtros por tipo de commit convencional (`feat:`, `fix:`, `security:`, `BREAKING CHANGE:`) y excluir commits de WIP, typo y refactor — el changelog es para consumidores del paquete, no para el historial interno.
- **OpenAPI diff muestra diferencias por orden de campos en JSON**: `diff docs/openapi.json /tmp/openapi_actual.json` reporta diferencias aunque la API no cambió. Causa: `python -m json.tool` formatea el JSON pero no garantiza orden consistente de campos. Solución: normalizar ambos JSONs con `jq --sort-keys` antes del diff, o comparar solo los paths y schemas con una herramienta de diff semántico de OpenAPI en lugar de diff de texto.
