# Anti-patrones y leyes de diseño de skills

Complemento a `SKILL.md` de `meta-skills-estandar`. Contiene ejemplos MAL/BIEN
detallados para cada anti-patrón y ley. Referenciado desde el skill principal.

## Contenido

- [Anti-patrón 1: description pasiva](#anti-patrón-1-description-que-solo-describe-no-activa)
- [Anti-patrón 2: SKILL.md como dump](#anti-patrón-2-skillmd-como-dump-de-documentación)
- [Anti-patrón 3: scripts embebidos](#anti-patrón-3-scripts-dentro-de-skillmd)
- [Anti-patrón 4: paths absolutos](#anti-patrón-4-paths-absolutos-que-rompen-portabilidad)
- [Anti-patrón 5: skill con 1-2 reglas](#anti-patrón-5-skill-con-solo-1-2-reglas)
- [Anti-patrón 6: directivas sin justificación](#anti-patrón-6-directivas-sin-justificación)
- [Ley 1: description como trigger](#ley-1-la-description-es-un-trigger-no-un-resumen)
- [Ley 2: Gotchas como mayor señal](#ley-2-la-sección-gotchas-es-el-contenido-de-mayor-señal)
- [Ley 3: no declarar lo obvio](#ley-3-no-declarar-lo-obvio)
- [Ley 4: objetivos + restricciones](#ley-4-dar-objetivos-y-restricciones-no-pasos)
- [Ley 5: CLAUDE_PLUGIN_DATA](#ley-5-usar-claude_plugin_data-para-datos-persistentes-entre-sesiones)
- [Ley 6: hooks bajo demanda](#ley-6-hooks-bajo-demanda-no-permanentes)

---

## Anti-patrones comunes al crear skills

### Anti-patrón 1: Description que solo describe, no activa

```yaml
# MAL — solo describe, no dice cuándo usar
description: Skill sobre autenticación con JWT y manejo de tokens en APIs.

# BIEN — dice qué hace y cuándo cargar
description: >
  Patrones de autenticación JWT para APIs FastAPI: generación, validación,
  refresh tokens y revocación. Cargar cuando se implementen endpoints de
  login/logout, middleware de autenticación o manejo de sesiones con tokens.
```

### Anti-patrón 2: SKILL.md como dump de documentación

Un SKILL.md que lista 200 endpoints de una API externa no es una skill, es
una copia de documentación. Las skills contienen instrucciones de comportamiento,
no documentación raw. La documentación raw va en `recursos/`.

### Anti-patrón 3: Scripts dentro de SKILL.md

```markdown
# MAL — script embebido en SKILL.md (satura el contexto)
## Script de validación
```python
#!/usr/bin/env python3
# ... 80 líneas de código ...
```

# BIEN — referencia al script externo
Para validar el frontmatter antes de guardar:
`python scripts/validar-frontmatter.py archivo.md`
```

### Anti-patrón 4: Paths absolutos que rompen portabilidad

```markdown
# MAL
Ver la referencia en D:\Python\mi-proyecto\habilidades\mi-skill\recursos\ref.md

# BIEN
Ver la referencia en [recursos/ref.md](recursos/ref.md)
```

### Anti-patrón 5: Skill con solo 1-2 reglas

Una skill con menos de 3 reglas concretas no justifica un directorio separado.
Agregar ese conocimiento al skill más cercano en dominio.

### Anti-patrón 6: Directivas sin justificación

Las directivas en mayúsculas (MUST, NEVER, ALWAYS, NUNCA, SIEMPRE) sin
justificación son obedecidas pero no generalizables — el modelo sigue la regla
en el caso exacto documentado, pero no puede aplicar el principio a variantes
no anticipadas.

```markdown
# MAL — directiva sin justificación
NUNCA usar `lazy="select"` en SQLAlchemy async.

# BIEN — directiva con justificación
NUNCA usar `lazy="select"` en SQLAlchemy async — lanza MissingGreenlet
en contexto async sin aviso claro porque el ORM intenta resolver la
relación fuera de la sesión activa.
```

**Regla**: toda directiva absoluta DEBE incluir en la misma línea o en la
siguiente una frase que comience con "porque", "ya que", "para evitar",
"si no". Si no cabe en una línea, usar formato de lista:

```markdown
NUNCA usar `pickle.loads()` con datos externos.
  — Razón: permite ejecución arbitraria de código; los datos externos no son
    de confianza por definición. Usar `json.loads()` con schema validado.
```

El evaluador `evaluar-skill` detecta ausencia de justificaciones con W009
(-8 en `output_quality`).

---

## Leyes de diseño de skills de alta señal

### Ley 1: La description es un TRIGGER, no un resumen

La description es la señal que el modelo usa para decidir si debe cargar la
skill. Redactar como condición de activación:

```yaml
# MAL — resumen pasivo
description: Conocimiento sobre caching en aplicaciones web.

# BIEN — trigger con situaciones concretas
description: >
  Estrategias de caching (Redis, CDN, HTTP cache, in-memory) para APIs REST.
  Cargar cuando el tiempo de respuesta de un endpoint supere 200ms, cuando se
  diseñe invalidación de caché, o cuando se configure un CDN.
```

### Ley 2: La sección Gotchas es el contenido de mayor señal

Los errores no obvios que un desarrollador experimentado comete son el contenido
más valioso de una skill. Toda skill de implementación DEBE incluir `## Gotchas`
o `## Errores comunes no obvios`:

```markdown
## Gotchas

- `selectinload` en SQLAlchemy async es OBLIGATORIO — `lazy="select"` lanza
  `MissingGreenlet` en contexto async sin aviso claro
- `Depends()` en FastAPI crea UNA instancia por request — no es singleton
- `response_model` valida la SALIDA, no la entrada — usar `Body()` para input
```

Si la skill no tiene gotchas documentados, probablemente no aporta valor
diferencial sobre lo que el modelo ya sabe.

### Ley 3: No declarar lo obvio

El modelo ya sabe qué es React, FastAPI o cómo funciona un for loop. Una skill
que repite conocimiento general del training data desperdicia tokens. El
contenido de una skill debe ser:

- Lo que el modelo hace **mal** sin la skill (gotchas, anti-patrones).
- Lo que el modelo **no sabe** por ser reciente o específico del proyecto.
- Las **decisiones de diseño** que el equipo ya tomó (no re-evaluar cada vez).

### Ley 4: Dar objetivos y restricciones, no pasos

El modelo razona mejor cuando recibe QUÉ lograr y QUÉ evitar, no una lista
de pasos. Los pasos rígidos fallan cuando el contexto cambia:

```markdown
# MAL — pasos rígidos
1. Crear archivo en src/api/
2. Importar FastAPI
3. Definir router
4. Agregar endpoint GET

# BIEN — objetivo + restricciones
## Objetivo
Implementar endpoints CRUD que cumplan el contrato OpenAPI del proyecto.

## Restricciones
- Usar `APIRouter` con prefix y tags (no montar en app directamente)
- Validación de input con Pydantic v2 `model_validator`
- Responses tipadas con `response_model` para auto-documentación
- Tests de integración con httpx antes de marcar como completado
```

### Ley 5: Usar `${CLAUDE_PLUGIN_DATA}` para datos persistentes entre sesiones

Cuando una skill necesita recordar estado entre sesiones (métricas acumuladas,
configuración del usuario, caché de resultados), usar el directorio de datos
persistentes del plugin en lugar de paths hardcodeados:

```markdown
Guardar métricas acumuladas en `${CLAUDE_PLUGIN_DATA}/metricas.json`.
Este directorio persiste entre sesiones y es exclusivo de esta skill.
```

No usar `.planning/` ni directorios del proyecto para datos internos de la skill.

### Ley 6: Hooks bajo demanda, no permanentes

Si una skill necesita comportamiento event-driven, definir el hook en el
frontmatter con `hooks` en lugar de registrarlo en `settings.json`:

```yaml
---
name: mi-skill
hooks:
  PostToolUse:
    - matcher: "Write"
      command: "node ${CLAUDE_SKILL_DIR}/scripts/validar.js"
---
```

Ventaja: el hook no consume recursos cuando la skill no está activa. Reservar
`settings.json` para hooks que SIEMPRE deben ejecutarse (seguridad global,
auditoría, formateo).
