# Regla: Registro obligatorio de componentes nuevos en manifiestos

Esta regla es OBLIGATORIA para el proyecto **@saulwade/swl-ses**. Aplica
cuando se agrega cualquier componente nuevo al sistema (agente, skill,
comando, hook, regla, schema, plantilla). El registro debe hacerse en el
mismo commit que introduce el componente — nunca en commit posterior.

Sin registro, el componente existe en disco pero **no es descubrible** por
los runtimes consumidores (Claude Code, Cursor, Codex, Copilot, OpenCode,
Gemini). El instalador no lo propaga al destino del usuario. El sistema
funciona localmente pero la distribución pública del paquete entrega un
artefacto roto.

Esta regla es la versión enforceable y específica de la sección "Mapa de
propagación de cambios" del `CLAUDE.md` del proyecto.

---

## Principio

> Todo componente nuevo del sistema SWL DEBE registrarse, en el mismo commit
> que lo crea, en **todos los archivos de manifiesto correspondientes** según
> su tipo. La regla `arreglar-al-detectar.md` exige que la deuda silenciosa
> no exista — un componente sin registrar ES deuda silenciosa que destapa
> producción.

El costo de registrar es ~30 segundos por componente (3 archivos a editar
+ un comando de regeneración). El costo de no registrar es: instalador roto
para usuarios del paquete público, `npm run test:all` falla, `/swl:salud`
reporta degradación, deuda acumulada difícil de detectar tras varios commits.

---

## Cómo aplicar — tabla de propagación obligatoria

Cuando agregas un componente nuevo, edita en el **mismo commit** los archivos
listados según el tipo:

| Tipo de componente | Archivos a actualizar | Comando de regeneración |
|---|---|---|
| **Agente** (`agentes/X-swl.md`) | `plugin.json` (array `agents`), `manifiestos/modulos.json` (módulo del dominio), `AGENTS.md` (catálogo), `INVENTARIO.md` (regenerar), `SALUD.md` (regenerar) | `node scripts/generar-inventario.js` |
| **Skill** (`habilidades/X/SKILL.md`) | `plugin.json` (array `skills`), `manifiestos/modulos.json` (módulo del dominio), `INVENTARIO.md` (regenerar), `CLAUDE.md` § "Sistema de habilidades" si aplica al dominio | `node scripts/generar-inventario.js` |
| **Comando** (`comandos/swl/X.md`) | `plugin.json` (array `commands` si existe), `manifiestos/modulos.json`, `COMANDOS.md` (descripción), `CLAUDE.md` § tabla de comandos `/swl:*`, `INVENTARIO.md` (regenerar) | `node scripts/generar-inventario.js` |
| **Hook** (`hooks/X.js`) | `plugin.json` (array `hooks` si existe), `.claude/settings.json` (event+matcher), `manifiestos/hooks-config.json` (event+matcher+blocking), `manifiestos/modulos.json` (ruta del archivo), `INVENTARIO.md`, `SALUD.md` | `node scripts/generar-inventario.js` |
| **Regla** (`reglas/X.md`) | `CLAUDE.md` § tabla de reglas (matcher), `INVENTARIO.md`, `SALUD.md` | `node scripts/generar-inventario.js` |
| **Schema** (`schemas/X.schema.json`) | `INVENTARIO.md`, `SALUD.md`. Si valida frontmatter de algún componente, actualizar `scripts/validar.js` para que lo use | `node scripts/generar-inventario.js` |
| **Plantilla** (`plantillas/X.md`) | `manifiestos/modulos.json` si la copia el instalador, `INVENTARIO.md` | `node scripts/generar-inventario.js` |
| **Bump de versión** (`package.json`) | 15+ ubicaciones — usar checklist en `/swl:release` paso 6, ejecutar `node scripts/verificar-release.js` para verificar sincronización | `node scripts/verificar-release.js` |
| **Cifras en `description` de manifiestos** (cualquier cambio de conteo de agentes / skills / comandos / reglas / hooks) | **Ambos** `package.json#description` Y `plugin.json#description` con cifras nuevas. **NO tocar uno sin tocar el otro.** Adicionalmente: la frase "60 agentes + N habilidades + M comandos + K reglas + L hooks" en `README.md`, `CLAUDE.md`, `MANUAL_USO.md`, `COMANDOS.md`, `INSTALACION.md`, `MAPEO_SKILLS_AGENTES.md` debe actualizarse con las cifras nuevas. | `node scripts/verificar-release.js` (gate "description" detecta drift cross-manifest + drift vs INVENTARIO.md) |

**Ambos manifiestos cuando aplique** son obligatorios. Si un hook se registra
solo en `.claude/settings.json` pero no en `manifiestos/hooks-config.json`, el
instalador no lo propaga al destino y los usuarios del paquete público no
reciben el hook. Y viceversa.

---

## Gate de CI que hace cumplir la regla

`npm run test:manifest` ejecuta `node scripts/validar-manifest.js` que verifica:

- `comandos/swl/*.md` (disco) ↔ entradas en `manifiestos/modulos.json`.
- `hooks/*.js` ejecutables (disco) ↔ entradas en `manifiestos/modulos.json`.
- `agentes/*.md` (disco) ↔ entradas en `manifiestos/modulos.json`.
- `habilidades/*/` (disco) ↔ entradas en `manifiestos/modulos.json`.
- `reglas/*.md` (disco) ↔ entradas en `manifiestos/modulos.json`.
- `hooks-config.json` (event+matcher) ↔ `hooks/*.js` ejecutables.
- `perfiles.json` ↔ todos los módulos de `modulos.json` deben aparecer en al menos un perfil (o tener `opt_in: true`).

Falla `npm run test:all` → PR bloqueado → merge bloqueado.

`node scripts/verificar-release.js` adiciona verificaciones cruzadas de
versiones (15+ ubicaciones) y conteos entre `plugin.json` y disco. Ejecutar
antes de cada `npm publish`.

---

## Protocolo de verificación pre-commit

Antes de hacer commit de un componente nuevo, ejecutar en orden:

```bash
# 1. Regenerar índices automáticos
node scripts/generar-inventario.js

# 2. Verificar sincronización de manifiestos
npm run test:manifest

# 3. Suite completa (tests Node + manifiestos + validación estructural)
npm run test:all

# 4. Solo si vas a publicar a npm: verificación de versiones
node scripts/verificar-release.js
```

Si cualquiera de los 3 primeros pasos falla, **NO commitear**. Corregir
primero. El paso 4 solo aplica a releases.

---

## Anti-patrones

### "Lo registro en el siguiente commit"

Prohibido. Crea ventana donde el commit del componente nuevo deja la suite
roja. Otros desarrolladores que pulleen quedan con CI rojo sin causa propia.
Aunque trabajes solo, el commit "queda sucio" en el historial y reverter es
más caro.

### "El instalador lo recoge automáticamente desde disco"

Falso. El instalador (`scripts/instalador.js`) lee `manifiestos/modulos.json`
para saber qué propagar. Lo que está en disco pero no en el manifiesto es
invisible para el instalador. Bug histórico v1.4.1 → v1.4.2: el módulo
`auditoria-profunda` estaba en `modulos.json` pero NO en perfiles → 16
archivos no llegaban al destino. Mismo patrón.

### "Solo lo uso localmente, no necesito propagarlo"

Falso. swl-ses se distribuye como paquete npm público. Cualquier componente
sin registrar no llega a usuarios del paquete. Si genuinamente es local,
ponlo en `_userland/` (gitignored) — pero NUNCA en `agentes/`, `habilidades/`,
etc. principales sin registro.

### "Es solo una skill auxiliar"

Falso. La tabla de propagación aplica a TODOS los componentes nuevos sin
excepción de "tamaño" o "importancia". Una skill auxiliar de 10 líneas sigue
necesitando su entrada en `plugin.json` y en el módulo de `modulos.json`.

### "Voy a esperar a hacer el commit final"

Falso. La regla `git-workflow.md` exige commits atómicos. Un componente
nuevo + su registro = un commit atómico. Mezclar varios componentes nuevos
en un commit es violación separada.

### Description stale de un manifiesto que el otro sí actualizó

Olvidar editar `package.json#description` cuando se actualizó
`plugin.json#description` (o viceversa). Origen del bug v1.6.4: el commit del
ADR-0028 actualizó `plugin.json#description` con cifras nuevas (171 skills, 69
reglas, 42 hooks, ADR-0028) pero dejó `package.json#description` con valores
de v1.6.2 (162/67/41, ADR-0025). El gate de versión no lo detectó porque solo
chequea `version`; el gate de contadores no lo detectó porque solo escanea
`.md`. Ahora hay gate dedicado (`ejecutarGateDescription` en
`scripts/verificar-release.js`) que detecta drift cross-manifest. Antes de
commitear cualquier cambio que afecte conteos, ejecutar
`node scripts/verificar-release.js` y mirar la sección "Gate de description".

### Confiar en `node -e` para validar conteos sin re-leer manifiestos

Falso. `node -e "console.log(require('./plugin.json').skills.length)"`
muestra cuántas entradas hay, no si esas entradas corresponden al disco.
El script canónico es `scripts/generar-inventario.js` que cruza ambas
fuentes y `validar-manifest.js` que falla en discrepancia.

---

## Excepciones legítimas (raras)

1. **Componentes en `_userland/`**: gitignored, no se distribuyen. Pueden
   existir en disco sin estar en manifiestos. Es el repositorio personal del
   usuario, separado del sistema base.
2. **Schemas privados de validación interna**: si un schema solo lo consume
   un script interno (`scripts/lib/`) y nunca se expone al usuario, el registro
   en manifiestos es opcional. Documentar la decisión en comentario del schema.
3. **Plantillas de prueba en `tests/` fixtures**: las plantillas usadas solo
   por tests viven en `tests/` y no se distribuyen. Sin necesidad de manifest.

Cualquier excepción a esta regla DEBE documentarse explícitamente con
comentario en el archivo del componente y mención en el commit message.

---

## Origen de esta regla

Sesión 2026-05-16, durante implementación del ADR-0021 (Nemesis evaluator-optimizer).
Un revisor externo emitió el hallazgo: *"Two new skills were added but are not
listed in plugin.json, manifiestos/modulos.json, or INVENTARIO.md"*. La
verificación contra el filesystem demostró que el hallazgo era **falso
positivo** — los skills SÍ estaban registrados en los tres archivos. Sin embargo,
el caso reveló dos cosas:

1. El patrón de auditoría que emite afirmaciones de no-existencia sin
   verificar es recurrente (regla global `verificar-citas-normativas.md`
   Familia 2 ya lo cubre).
2. La regla del registro obligatorio vive solo en `CLAUDE.md § Mapa de
   propagación` como tabla — falta un archivo dedicado con detalle, gates
   de CI explícitos y anti-patrones específicos. Esta regla cubre ese gap.

Adicionalmente, durante la verificación se descubrió **deuda preexistente**:
2 skills (`ejecutar-task-iterativo`, `protocolo-revision-swl`) existen en
`habilidades/` pero NO están en `plugin.json`. Esa deuda se cierra en un
commit separado del fix actual.

---

## Citas a módulos de manifest en ADRs y docs

Cuando un ADR o documento del sistema cita un nombre de módulo de
`manifiestos/modulos.json`, `manifiestos/hooks-config.json` o
`manifiestos/perfiles.json`, **el nombre DEBE verificarse contra el
archivo real antes de persistir el ADR/doc**. Citas redactadas "de
memoria" tienden a inventar nombres plausibles que no existen.

**Patrón verificador**:

```bash
# Verificar en qué módulo está registrado un componente específico
node -e "
const m = require('./manifiestos/modulos.json');
for (const [k, v] of Object.entries(m.modulos || m)) {
  if (v.archivos && v.archivos.includes('hooks/<NOMBRE>.js')) {
    console.log('Módulo real:', k);
  }
}
"

# Listar todos los nombres de módulos disponibles
node -e "console.log(Object.keys(require('./manifiestos/modulos.json').modulos))"
```

**Caso de regresión histórico**: ADR-0027 (2026-05-18) inicialmente decía
"`manifiestos/modulos.json` en módulo `hooks-evolucion-instintos`" —
módulo **inexistente**. El hook real quedó en `hooks-core`. Pasó la
primera revisión porque el ADR se redactó de memoria. Fix retrospectivo
en commit `6919b01`.

**Aplicación**: la regla global `~/.claude/rules/verificar-citas-normativas.md
§ Familia 2` cubre "citas archivo:línea" — esta regla extiende el patrón
al dominio interno del proyecto: citas a nombres de módulos en manifiestos.

---

## Checklist antes de commitear un componente nuevo

- [ ] El archivo del componente está en el directorio correcto (`agentes/`, `habilidades/`, `comandos/swl/`, etc.).
- [ ] Cada archivo de la columna "Archivos a actualizar" según el tipo está editado en el commit actual.
- [ ] `node scripts/generar-inventario.js` se ejecutó y los cambios en `INVENTARIO.md` + `SALUD.md` están staged.
- [ ] `npm run test:manifest` pasa sin errores.
- [ ] `npm run test:all` pasa sin errores.
- [ ] Si es release: `node scripts/verificar-release.js` pasa sin discrepancias.
- [ ] El commit message menciona qué componente se agrega y, si aplica, en qué módulo.
- [ ] Si el ADR/doc cita un módulo de manifest, el nombre se verificó con `node -e` o `grep` contra el archivo real (no escrito "de memoria").
