---
name: swl:salud
description: Diagnóstico completo de salud del sistema SWL. Verifica integridad de agentes, skills, comandos, reglas y hooks. Genera un reporte con score por componente y detecta agentes sin versión, skills huérfanos, comandos rotos y reglas contradictorias.
allowed_tools: ["Read", "Write", "Bash", "Glob", "Grep"]
---

# /swl:salud — Diagnóstico de salud del sistema SWL

Inspector de salud del sistema SWL. Verifica integridad de todos los componentes
usando **verificaciones deterministas** (conteos, existencia de campos, sintaxis).
Genera SALUD.md con score objetivo y reproducible.

**Carga**: `Skill("validacion-ci-sistema")` — contiene las reglas de validación por componente (agentes, skills, hooks, comandos, reglas), tabla de exit codes para hooks y checklist de integridad. Delega toda lógica de verificación al skill.

Este comando es de **solo lectura**. No modifica archivos — solo genera SALUD.md. Para corregir problemas, usar `swl:evolucionar`.

## Cuándo usar

- Antes de iniciar proyecto nuevo con SWL
- Después de agregar o modificar agentes/skills manualmente
- Cuando un agente produce outputs inesperados
- Después de merge o pull de cambios al repositorio
- Periódicamente como mantenimiento (mensual)

## Paso 0 — Inventario con Bash (determinista)

```bash
echo "=== INVENTARIO ===" && \
echo "Agentes: $(ls agentes/*.md 2>/dev/null | wc -l)" && \
echo "Skills: $(ls -d habilidades/*/ 2>/dev/null | wc -l)" && \
echo "Comandos: $(ls comandos/swl/*.md 2>/dev/null | wc -l)" && \
echo "Reglas: $(ls reglas/*.md 2>/dev/null | wc -l)" && \
echo "Hooks: $(ls hooks/*.js 2>/dev/null | wc -l)"
```

## Paso 1 — Diagnóstico de agentes (determinista)

Ejecutar script Bash que verifica cada agente mecánicamente:

```bash
errors=0; warns=0; ok=0
for f in agentes/*.md; do
  name=$(basename "$f" .md)
  has_name=$(head -30 "$f" | grep -c "^name:")
  has_desc=$(head -30 "$f" | grep -c "^description:")
  has_version=$(head -30 "$f" | grep -c "^version:")
  has_riesgo=$(head -30 "$f" | grep -c "^nivelRiesgo:")
  placeholders=$(grep -cE '\[TODO\]|\[COMPLETAR\]|\[TBD\]' "$f" || true)

  if [ "$has_name" -eq 0 ] || [ "$has_desc" -eq 0 ]; then
    echo "ERROR: $name — falta name o description"
    errors=$((errors+1))
  elif [ "$has_version" -eq 0 ] || [ "$has_riesgo" -eq 0 ]; then
    echo "ADVERTENCIA: $name — falta version o nivelRiesgo"
    warns=$((warns+1))
  elif [ "$placeholders" -gt 0 ]; then
    echo "ADVERTENCIA: $name — placeholders sin reemplazar"
    warns=$((warns+1))
  else
    ok=$((ok+1))
  fi
done
echo "Agentes: $ok OK, $warns advertencias, $errors errores"
```

Score de agentes = `(ok / total) * 100`

## Paso 2 — Diagnóstico de skills (determinista)

```bash
errors=0; warns=0; ok=0
for d in habilidades/*/; do
  name=$(basename "$d")
  skill="$d/SKILL.md"
  if [ ! -f "$skill" ]; then
    echo "ERROR: $name — sin SKILL.md"
    errors=$((errors+1)); continue
  fi
  lines=$(wc -l < "$skill")
  has_name=$(head -10 "$skill" | grep -c "^name:")
  has_desc=$(head -10 "$skill" | grep -c "^description:")
  content_chars=$(sed -n '/^---$/,/^---$/d; p' "$skill" | wc -c)
  abs_paths=$(grep -cE 'C:\\|/home/|/Users/' "$skill" || true)

  if [ "$has_name" -eq 0 ] || [ "$has_desc" -eq 0 ]; then
    echo "ERROR: $name — frontmatter sin name o description"
    errors=$((errors+1))
  elif [ "$lines" -gt 300 ]; then
    echo "ADVERTENCIA: $name — $lines lineas (max 300)"
    warns=$((warns+1))
  elif [ "$content_chars" -lt 500 ]; then
    echo "ADVERTENCIA: $name — contenido muy corto ($content_chars chars)"
    warns=$((warns+1))
  elif [ "$abs_paths" -gt 0 ]; then
    echo "ADVERTENCIA: $name — paths absolutos detectados"
    warns=$((warns+1))
  else
    ok=$((ok+1))
  fi
done
echo "Skills: $ok OK, $warns advertencias, $errors errores"
```

Detectar skills huérfanos (no referenciados):

```bash
grep -r "Skill(" agentes/ comandos/ 2>/dev/null | grep -o '"[^"]*"' | sort | uniq
```

Score de skills = `((total - errors*10 - warns*2) / total) * 100`, mínimo 0

## Paso 3 — Diagnóstico de comandos (determinista)

```bash
errors=0; warns=0; ok=0
for f in comandos/swl/*.md; do
  name=$(basename "$f" .md)
  lines=$(wc -l < "$f")
  has_name=$(head -10 "$f" | grep -c "^name:")
  has_desc=$(head -10 "$f" | grep -c "^description:")
  desc_len=$(head -5 "$f" | grep "^description:" | wc -c)

  if [ "$has_name" -eq 0 ] || [ "$has_desc" -eq 0 ]; then
    echo "ERROR: $name — frontmatter sin name o description"
    errors=$((errors+1))
  elif [ "$desc_len" -lt 30 ]; then
    echo "ADVERTENCIA: $name — description muy breve"
    warns=$((warns+1))
  elif [ "$lines" -gt 300 ]; then
    echo "ADVERTENCIA: $name — $lines lineas (considerar delegar a skill)"
    warns=$((warns+1))
  else
    ok=$((ok+1))
  fi
done
echo "Comandos: $ok OK, $warns advertencias, $errors errores"
```

## Paso 4 — Diagnóstico de reglas (determinista)

```bash
errors=0; warns=0; ok=0
for f in reglas/*.md; do
  name=$(basename "$f" .md)
  lines=$(wc -l < "$f")
  has_h1=$(grep -c "^# " "$f" || true)
  has_checklist=$(grep -c "\- \[ \]" "$f" || true)

  if [ "$lines" -lt 20 ]; then
    echo "ERROR: $name — regla muy corta ($lines lineas)"
    errors=$((errors+1))
  elif [ "$has_h1" -eq 0 ]; then
    echo "ADVERTENCIA: $name — sin titulo H1"
    warns=$((warns+1))
  elif [ "$has_checklist" -eq 0 ]; then
    echo "ADVERTENCIA: $name — sin checklist"
    warns=$((warns+1))
  else
    ok=$((ok+1))
  fi
done
echo "Reglas: $ok OK, $warns advertencias, $errors errores"
```

## Paso 5 — Diagnóstico de hooks (determinista)

```bash
errors=0; warns=0; ok=0
for f in hooks/*.js; do
  name=$(basename "$f")
  if node --check "$f" 2>/dev/null; then
    if grep -q "$name" .claude/settings.json 2>/dev/null; then
      ok=$((ok+1))
    else
      echo "ADVERTENCIA: $name — no registrado en settings.json"
      warns=$((warns+1))
    fi
  else
    echo "ERROR: $name — error de sintaxis Node.js"
    errors=$((errors+1))
  fi
done
echo "Hooks: $ok OK, $warns advertencias, $errors errores"
```

## Paso 5b — Auditoría opcional de skills (opt-in)

Si la variable de entorno `SWL_AUDIT_SKILLS=1` está presente, ejecutar:

```bash
bash scripts/audit-skills.sh
```

Este paso es **no bloqueante**: si el comando falla por cualquier causa (red,
dependencia faltante, paquete no publicado), el diagnóstico continúa normalmente.

**Qué detecta**:
- Prompt injection en contenido de SKILL.md (instrucciones que intentan manipular el modelo).
- Secretos hardcodeados (API keys, tokens, contraseñas en ejemplos).
- URLs sospechosas embebidas en los skills.
- Estructura inválida de SKILL.md (frontmatter incompleto, ausencia de secciones requeridas).

**Requisito**: `pip install uv` (o `pipx install uv`) antes de activar.

**Activación manual**:
```bash
SWL_AUDIT_SKILLS=1 bash scripts/audit-skills.sh
```

Si `SWL_AUDIT_SKILLS` no está definida, el script imprime instrucciones y sale
con código 0 — no afecta el score ni el diagnóstico general.

## Paso 6 — Score global ponderado

```
Score = agentes x 0.30 + skills x 0.25 + comandos x 0.20 + reglas x 0.15 + hooks x 0.10

90-100: Excelente
75-89:  Saludable con mejoras menores
60-74:  Funcional con problemas
<60:    Estado crítico
```

## Paso 5c — Reporte de cobertura de frameworks de seguridad (opt-in)

Si la variable de entorno `SWL_AUDIT_FRAMEWORKS=1` está presente, ejecutar el
auditor de cobertura:

```bash
node scripts/auditar-cobertura-frameworks.js --resumen
```

Propósito: reportar cuántos skills declaran mapeos a los 5 frameworks de
seguridad (NIST CSF 2.0, NIST AI RMF 1.0, MITRE ATLAS v5.4, ATT&CK v18,
D3FEND v1.3) y qué controles están cubiertos. Útil para:

- Verificar que los skills de dominio seguridad declaran mapeos antes de un
  audit de compliance
- Detectar gaps en la cobertura (ej: ningún skill cubre `PR.DS-11` — data
  integrity — si eso importa para el proyecto)
- Producir evidencia para auditores (SOC 2, ISO 27001) sobre controles
  implementados

El reporte NO marca skills sin mapeos como error — solo skills de dominio
seguridad necesitan declararlos. Ver `reglas/skills-estandar.md` sección
"Mapeo a frameworks de seguridad (REC-C01)" para criterios de cuándo declarar
cada framework.

**Filtrado por framework**:

```bash
SWL_AUDIT_FRAMEWORKS=1 node scripts/auditar-cobertura-frameworks.js --framework=nist_ai_rmf --resumen
```

**Persistir snapshot**:

```bash
node scripts/auditar-cobertura-frameworks.js --save
```

Persiste en `.planning/evolucion/cobertura-frameworks.json` para comparación
histórica tras incorporar nuevos skills de seguridad.

Si `SWL_AUDIT_FRAMEWORKS` no está definida, este paso se omite sin mensaje
— los reportes son opt-in por diseño (CLAUDE.md: "Variables de entorno
opt-in para integraciones enterprise").

## Paso 5d — Auditoría SAP-Agents (opt-in)

Si la variable de entorno `SWL_AUDIT_AGENTES=1` está presente, ejecutar el
auditor de agentes:

```bash
node scripts/auditar-agentes-gaps.js --resumen
```

Propósito: reportar cuántos agentes carecen de Exclusion Clause (campo
`exclusiones` o sección `## Cuándo NO invocarme`) y Gotchas explícitos.
Previene agent hijacking por activación tangencial de agentes por similitud
superficial en `description`.

El reporte incluye conteo de excepciones documentadas por ADR (si las hay)
para separar gaps reales de excepciones por diseño.

Si `SWL_AUDIT_AGENTES` no está definida, este paso se omite — los reportes
son opt-in por diseño (CLAUDE.md: "Variables de entorno opt-in para
integraciones enterprise").

## Paso 6b — Formato de salida enriquecido (HealthRow)

El módulo `scripts/lib/health-row.js` genera filas de salud con formato visual enriquecido
para la salida de terminal. Cada fila sigue el patrón:

```
Label              valor/max |████████████████████| indicador
```

Ejemplo visual (modo con color ANSI):

```
Agentes              59/59 |████████████████████| ✓ ok
Skills               52/55 |███████████████████░| ✓ ok
Comandos             37/38 |███████████████████░| ✓ ok
Reglas               18/18 |████████████████████| ✓ ok
Hooks                22/25 |█████████████████░░░| ⚠ warn
Score Global         88/100 |█████████████████░░░| ✓ ok
```

### Umbrales automáticos

| Rango de porcentaje | Estado | Color ANSI  |
|---------------------|--------|-------------|
| >= 80%              | good   | Verde `\x1b[32m` |
| >= 50% y < 80%      | warn   | Amarillo `\x1b[33m` |
| < 50%               | bad    | Rojo `\x1b[31m` |

Respetar `NO_COLOR` (https://no-color.org) y la variable `SWL_ASCII_SIMPLE=1`
para entornos sin soporte Unicode.

### Uso para generar el bloque de salud

```javascript
const { formatearBloqueHealth } = require('./scripts/lib/health-row');

const filas = [
  { label: 'Agentes',      valor: 59,  maximo: 59  },
  { label: 'Skills',       valor: 52,  maximo: 55  },
  { label: 'Comandos',     valor: 37,  maximo: 38  },
  { label: 'Reglas',       valor: 18,  maximo: 18  },
  { label: 'Hooks',        valor: 22,  maximo: 25  },
  { label: 'Score Global', valor: 88,  maximo: 100 },
];

console.log(formatearBloqueHealth(filas));
```

Para override de estado (forzar bad aunque el valor sea alto):

```javascript
const { formatearHealthRow } = require('./scripts/lib/health-row');
const fila = formatearHealthRow({ label: 'Seguridad', valor: 100, maximo: 100, estado: 'bad' });
```

La integración real del formato en la ejecución del comando se implementará en el
código de salida de `/swl:salud`. Este paso solo define la API disponible y la muestra visual.

## Paso 7 — Generar SALUD.md

Escribe el reporte con tabla resumen, errores, advertencias y recomendaciones. Usa los datos exactos de los scripts. Si el script dice 73%, reportar 73%.

## Paso 8 — Resumen en terminal

Presenta resumen con los problemas más críticos. Si hay errores, listarlos todos. Si solo advertencias, listar las top 5.

## Reglas de comportamiento

- SOLO LECTURA. NUNCA modifica archivos excepto SALUD.md.
- Las verificaciones de Pasos 1-5 son scripts Bash deterministas. NO usar juicio subjetivo.
- Los scripts miden: existencia de campos, conteo de líneas, sintaxis. NO miden calidad de redacción.
- Si un check requiere juicio (contradicciones entre reglas), documentar como "requiere revisión manual".
- Los scores son aritmética pura. No ajustar el score "porque parece un sistema sano".
- Si no hay git, omitir verificaciones dependientes y notar la omisión.
- Si detectas un patrón sistémico (mismo error en múltiples componentes), mencionarlo en recomendaciones.
