# Audit reference — Business Rules Catalog

Interpretación del output de `/business-rules:audit` y resolución de hallazgos.

> El audit tiene **dos partes** que corren en la misma sesión cuando se
> invoca vía `/business-rules:audit`:
>
> 1. **Estructural** — `scripts/business-rules/audit.ts` (Node, sin LLM).
> 2. **Semántica** — Claude continúa la sesión leyendo el catálogo y
>    detectando tensiones entre reglas (sin SDK, sin API key, sin routine).
>
> El script `audit.ts` **no se expone como `pnpm br:*`**: el output
> útil es el integrado, y un alias para la parte estructural sola sería
> un sub-producto bajo el mismo nombre. Para tooling externo o
> debugging, se invoca directamente con
> `npx tsx scripts/business-rules/audit.ts` (con `--json` para output
> machine-consumable).

---

## Anatomía del reporte

```
=== Business rules — audit ===
Generado: <ISO timestamp>

A) SALUD                  ← health metrics + size bucket
B) DRIFT                  ← catalog ↔ code consistency
C) ASUNCIONES PENDIENTES  ← old [VERIFICAR] / [ASUNCIÓN] markers
D) CROSS-BC POINTERS      ← cross-BC rules with missing apuntadores

(si se invocó vía /business-rules:audit)
E) TENSIONES SEMÁNTICAS   ← pares de reglas con tensión latente
```

Exit codes (parte estructural):

- `0` — clean.
- `2` — warnings present (drift, assumptions, missing pointers, size warnings).

---

## Sección A — SALUD

```
Reglas activas:    47
Reglas derogadas:  3
Reglas propuestas: 2
Total:             52 en 14 archivos
BCs cubiertos:     production-planning, iam, business-partner-portal
Tamaño estimado:   ~36,400 tokens
Bucket de tamaño:  OK
```

### Buckets y acciones

| Bucket          | Activas    | Acción recomendada                                                |
| --------------- | ---------- | ----------------------------------------------------------------- |
| `OK`            | < 150      | Operación normal. Sweep semántico completo viable.                |
| `INFO`          | 150–249    | Sweep semántico completo viable; valorar scoping si es ruidoso.   |
| `WARN`          | 250–499    | Empezar filtrado por BC en sweep semántico (preguntar al user).   |
| `SOFT_ERROR`    | 500–999    | Filtrado por BC obligatorio. Sweep completo solo con opt-in.      |
| `REARCHITECT`   | ≥ 1000     | Pairwise no escala; replantear (RAG / sub-catálogos / embeddings). |

`Tamaño estimado` usa la heurística de ~700 tokens por regla. Útil para
decidir cuánto del catálogo cabe en el contexto del análisis semántico.

---

## Sección B — DRIFT

### Paths inexistentes en `Implementa`

```
⚠ Paths inexistentes (3):
  - [BR-PROD-EVENT-002] backend/src/.../old-service.ts
```

**Causas posibles**:

- El código se renombró/movió.
- El servicio se eliminó completamente.
- El path nunca fue correcto.

**Resolución**:

1. Buscar el código actual: `rg -l "<descriptive symbol from rule>"`.
2. Si existe en otro path → editar la regla en sitio (esto es un path-fix,
   no requiere derogar).
3. Si el código se eliminó:
   - Si la regla sigue vigente → marcar `[VERIFICAR]` para reescribir el
     `Implementa` con el nuevo flujo.
   - Si la regla quedó obsoleta → derogar (ver Workflow C en
     `workflow.md`).

### Citaciones huérfanas

```
⚠ Citaciones huérfanas (1):
  - BR-INVENT-XXX-001 en backend/src/.../foo.ts:42
```

**Causa**: el código cita un identificador que no existe en el catálogo.

**Resolución**:

1. Verificar la cita en el código.
2. Si fue typo → corregir la cita.
3. Si la regla existe pero con otro ID → corregir la cita.
4. Si la regla genuinamente falta documentación → ejecutar
   `/business-rules:document <bc>/<aggregate>` y escribirla.

### Reglas zombi

```
⚠ Reglas zombi (1):
  - BR-IAM-ROLE-003 (90 días sin citas)
```

**Causa**: la regla está `active` pero ningún código tiene `@rule BR-IAM-ROLE-003`
hace 30+ días.

**Resolución (no urgente)**:

- Las citas son opcionales. Que una regla sea "zombi" significa solo que
  ningún `@rule` apunta a ella.
- Si la regla **debería estar implementada**, abre el código relevante y añade
  la cita.
- Si la regla **no se usa en código** (por ejemplo, una policy que vive como
  configuración o documento operativo), está bien que sea zombi. Considera
  marcarla en el catálogo con una nota explicativa.

---

## Sección C — ASUNCIONES PENDIENTES

```
⚠ Marcadores con > 30 días (2):
  - [BR-PROD-HEADER-007] [VERIFICAR caso 4] (47 días) en cliter/production-planning/business-rules/production-order-header.md
  - [BR-PROD-POSITION-003] [ASUNCIÓN] (35 días) en ...
```

**Resolución**:

1. Para cada marcador, identificar la pregunta concreta que necesita respuesta.
2. Llevarla a la persona indicada (producto, dominio, ingeniería).
3. Una vez resuelta:
   - Sustituir `[VERIFICAR caso N]` en la tabla por el valor confirmado.
   - Quitar (o resumir) la entrada en "Asunciones a verificar".
   - Refrescar `last_updated`.
4. `pnpm br:generate && pnpm br:validate` (o lo hace la pre-commit hook al
   commitear).

> Esto es edit en sitio sin derogar (cubre una laguna, no cambia significado).

---

## Sección D — CROSS-BC POINTERS

```
⚠ Apuntadores faltantes (1):
  - BR-PROD-EVENT-006 no aparece en cliter/iam/business-rules/<some-aggregate>.md
```

**Causa**: la regla declara varios `bounded_contexts` en su frontmatter, pero
no existe un apuntador en el archivo del BC adicional.

**Resolución**:

1. Identificar el agregado relevante en el BC mencionado (p. ej. el agregado
   del rol/permission afectado en `iam`).
2. Editar `cliter/iam/business-rules/<aggregate>.md` añadiendo una sección
   apuntador (ver plantilla en `format.md`):

   ```markdown
   ## Excepciones por <concepto> que afectan a otros BCs
   - <Trigger> → ver **BR-PROD-EVENT-006** (<título corto> en
     `cliter/production-planning/business-rules/production-order-position-event.md`).
   ```

3. `pnpm br:generate && pnpm br:validate` (o lo hace la pre-commit hook).

> Si el archivo del BC adicional **no existe todavía**, créalo con frontmatter
> mínimo (solo el BC y el agregado relevante en plural, keywords y paths
> apropiados). Las reglas atómicas del agregado se documentarán cuando proceda.

---

## Sección E — TENSIONES SEMÁNTICAS (la rellena Claude tras el script estructural)

Solo aparece cuando el audit se invoca vía `/business-rules:audit`. La
parte estructural (A–D) la genera el script; esta sección la rellena
Claude continuando la sesión con análisis pairwise.

```
E) TENSIONES SEMÁNTICAS
  Pares analizados:    24
  Pares reportados:    2  (contradicciones 1, needs-review 1, extensiones dudosas 0)

  - [BR-PROD-EVENT-005] vs [BR-PROD-HEADER-002] — contradiction (0.85)
    BR-PROD-EVENT-005 prohíbe borrar eventos en estado IN_PROGRESS, pero
    BR-PROD-HEADER-002 describe un revert basado en el borrado del último
    evento sin distinguir el estado del evento borrado.

  - [BR-IAM-ROLE-001] vs [BR-IAM-PERMISSION-003] — needs-review (0.55)
    Ambas reglas tocan el reseteo de roles pero la cascada exacta no queda
    clara desde la lectura del cuerpo.
```

### Cómo se generan los pares

Claude empareja reglas que comparten al menos uno de:
- `bounded_contexts` (frontmatter en plural)
- `aggregates`
- una entrada de `keywords`

No compara todo contra todo (explosión cuadrática). El heurístico
"comparten atributo" captura los pares que pueden tener tensión.

### Verdicts

- `contradiction` — las reglas no pueden coexistir sin que una derogue
  o exceptúe a la otra. Se reporta siempre.
- `extension` — una regla extiende a la otra (caso más específico).
  Se reporta solo si la confianza < 0.7 (i.e. dudoso si es extensión
  limpia o tensión oculta).
- `orthogonal` — preocupaciones independientes. NO se reporta.
- `needs-review` — demasiado ambiguo para clasificar automáticamente.
  Se reporta.

### Resolución por verdict

- **`contradiction`** → Workflow C en `workflow.md`: derogar una de las
  reglas y crear una nueva. Si es excepción legítima no declarada,
  añadir referencia cruzada en "Reglas relacionadas" de ambas reglas.
- **`needs-review`** → llevar el par a producto/dominio. El LLM no tiene
  certeza; el humano decide.
- **`extension` con confianza baja** → verificar; si es extensión real,
  documentar la relación.

### Cuándo Claude se salta esta sección

- Catálogo vacío (sin reglas activas ni propuestas).
- Solo hay reglas en estado `proposed` (scaffolds sin contenido para comparar).
- El usuario pidió explícitamente solo el audit estructural
  (`--structural-only` o lo dice en el prompt).
- El bucket es `WARN`/`SOFT_ERROR` y el usuario no aprueba sweep completo
  → Claude pregunta y filtra por BC.

---

## Workflow recomendado tras un audit

```
1. /business-rules:audit                 → reporte completo (estructural + semántico)
   o npx tsx scripts/business-rules/audit.ts → solo estructural (tooling/debugging)

2. Listar findings y atender:
   - Drift / asunciones / pointers       → secciones B/C/D.
   - Tensiones                           → sección E (si aparece).

3. Para cada finding, elegir acción:
   - Edit en sitio (path-fix, asunción resuelta, formato).
   - Derogar + crear nueva (cambio semántico, contradicción).
   - Añadir cita @rule en código.
   - Añadir apuntador cross-BC.
   - Añadir referencia cruzada en "Reglas relacionadas".

4. Aplicar cambios, regenerar:
   pnpm br:generate && pnpm br:validate
   (o la pre-commit hook al commitear)

5. Commit con prefijo focalizado:
   chore(business-rules): resolver findings del audit YYYY-MM-DD
```

---

## Cuándo NO ejecutar el audit

- Justo después de un `/business-rules:promote` masivo: el catálogo cambió;
  los findings reflejarán transiciones temporales.
- En medio de una sesión de `/business-rules:document`: las reglas están
  todavía en draft con `[VERIFICAR]` recientes; los reportará como antiguos
  solo si `last_updated` está mal puesto.
- Justo antes de un release: el reporte puede generar trabajo distractor.
  Mejor antes de empezar el siguiente sprint.
