# Format reference — Business Rules Catalog

Formato exacto y obligatorio del catálogo. Para racionalidad de las decisiones
y workflow de uso, ver `docs/business-rules/README.md` y `workflow.md`.

---

## Layout del archivo

```
cliter/<bounded-context>/business-rules/<aggregate>.md
```

- Un archivo por agregado.
- Si una regla afecta a varios agregados o BCs, **vive en UN único archivo**:
  el del agregado donde está su invariante final. Los otros agregados/BCs
  llevan apuntadores cortos sin contenido duplicado.

---

## Frontmatter file-level (obligatorio)

```yaml
---
bounded_contexts:
  - production-planning            # kebab-minúsculas
aggregates:
  - production-planning/production-order-header
  - production-planning/production-order-position-event
last_updated: 2026-05-03            # ISO YYYY-MM-DD
keywords:
  - cabecera de orden                # bilingüe deliberado
  - production order header
  - cascada de revert
  - revert cascade
paths:
  - backend/src/@app/production-planning/production-order-header/**
  - frontend/src/app/modules/admin/apps/production-planning/production-order-header/**
---
```

Campos:

| Campo              | Tipo         | Notas                                                                |
| ------------------ | ------------ | -------------------------------------------------------------------- |
| `bounded_contexts` | string[]     | Plural. Reglas cross-BC listan varios. Coincide con `boundedContextName` del aurora.yaml. |
| `aggregates`       | string[]     | Plural. Cada uno como `<bc>/<aggregate>` en kebab-minúsculas.        |
| `last_updated`     | string (date)| Formato `YYYY-MM-DD`. Refrescar tras cualquier cambio significativo. |
| `keywords`         | string[]     | Bilingüe deliberado (español + inglés). Usado por inject hook + audit.|
| `paths`            | string[]     | Globs respecto a la raíz del repo. Top-level: `backend/`, `frontend/`, `cliter/`, `scripts/`, `docs/`. |

Validado contra `docs/business-rules/_schema.json` por `pnpm br:validate`.

---

## Encabezado humano

Bajo el frontmatter, antes de las reglas:

```markdown
# Reglas de <Aggregate Humano>

> **Glosario**:
>
> - **<concepto>**: <breve definición>
> - **<concepto>**: <breve definición>

> **Estados de los agregados involucrados** (opcional, recomendado):
>
> | Agregado | Estados                                    |
> | -------- | ------------------------------------------ |
> | Foo      | `STATE_A`, `STATE_B`                       |

---
```

---

## Sección por regla (canónica)

Cada regla sigue este orden estricto:

```markdown
## BR-<BC>-<AGG>-<NNN> — <Título corto en español>

| Campo      | Valor                                                                  |
| ---------- | ---------------------------------------------------------------------- |
| Estado     | `active` \| `derogated` \| `proposed`                                  |
| Severidad  | `blocking` \| `informational`                                          |
| Origen     | retro-documentada \| openspec/changes/archive/<archive-name>/spec.md   |
| Trigger en | <agregado origen, opcional, en formato bc/aggregate>                   |
| Efecto en  | <agregado destino + campos afectados, opcional>                        |

### Enunciado

<Una o dos frases en español describiendo la regla.>

### Diagrama de cascada
<!-- opcional, solo si la regla describe efectos que se propagan. -->
<!-- omitir si es una validación o un invariante derivado simple. -->


```
trigger
  │
  ▼
condición
  │
  ▼ sí
efecto
```

### Casos exhaustivos

| # | <columna 1> | <columna 2> | ... | Resultado |
| - | ----------- | ----------- | --- | --------- |
| 1 | ...         | ...         | ... | ...       |

### Asunciones a verificar
<!-- opcional -->

- **[VERIFICAR caso N]**: <qué falta confirmar>
- **[ASUNCIÓN]**: <hipótesis que asumimos cierta y por qué>

### Implementa

- `backend/src/@app/<bc>/<agg>/.../<file>.ts:<line>` — <qué hace en el flujo>

### Tests

- `backend/test/.../<file>.spec.ts:'<test name>'`

### Reglas relacionadas

- **BR-XXX-YYY-NNN** — <relación>

### Derogación
<!-- SOLO si Estado: derogated. Añadida por /business-rules:promote o a mano. -->

Derogada el <YYYY-MM-DD> a partir del cambio archivado
`openspec/changes/archive/<name>/`. Reemplazada por **BR-NEW-NNN**.
Razón breve: <motivo>.
```

---

## Reglas estilísticas

- **Heading de regla**: `## BR-<...> — <título>`. El separador entre ID y
  título es siempre el guión largo `—` (U+2014), no `-`. El parser
  (`scripts/business-rules/parse-catalog.ts`) lo usa para identificar reglas.
- **Tabla de metadatos**: las dos primeras filas son cabecera (`| Campo | Valor |`)
  y separador. Los valores enum van entre backticks (`` `active` ``); los
  textos libres (`Origen`, `Trigger en`, `Efecto en`) van sin backticks.
- **Tablas de casos**: una columna por dimensión que cambia. La última
  columna debe ser `Resultado` o equivalente. **No aceptar tablas con menos
  de dos casos**.
- **Marcadores de asunción**: siempre dentro de corchetes,
  `[VERIFICAR]` o `[VERIFICAR caso N]` y `[ASUNCIÓN]`. El audit los detecta
  por regex.

---

## Apuntadores en archivos no-dueños (cross-aggregate / cross-BC)

Cuando una regla vive en un archivo (el del agregado del invariante final)
pero afecta a otros agregados o BCs, **los archivos de los otros agregados/BCs
llevan apuntadores**.

Plantilla en agregado origen del trigger (cuando `Trigger en` aplica):

```markdown
## Cascadas que dispara este agregado

- **`<acción>(<entity>)`** → ver **BR-<...>** (<título corto>; vive en
  [`<aggregate>.md`](./<aggregate>.md)).
```

Plantilla en agregado intermedio (cuando es paso medio):

```markdown
## Cascadas que afectan a este agregado

- ← **BR-<...>** (atómica, vive aquí)
- ← **BR-<...>** (vive en [`<other-aggregate>.md`](./<other-aggregate>.md), este es punto medio).
```

Plantilla cross-BC (apuntador desde otro bounded context):

```markdown
## Excepciones por <concepto> que afectan a otros BCs

- <Trigger> → ver **BR-<...>** (<título corto> en
  `<bc-owner>/business-rules/<aggregate>.md`).
```

---

## Secciones obligatorias y opcionales

- **Obligatorias** en toda regla: tabla de metadata (Estado/Severidad/Origen),
  `### Enunciado`, `### Casos exhaustivos`, `### Implementa`.
- **Opcionales**, según naturaleza de la regla:
  - `Trigger en` y `Efecto en` (filas de la tabla): cuando hay un trigger
    explícito y/o efecto en otro agregado.
  - `### Diagrama de cascada`: cuando la regla describe efectos que se
    propagan a través de varios agregados.
  - `### Asunciones a verificar`: cuando hay casos `[VERIFICAR]` o
    `[ASUNCIÓN]` no resueltos.
  - `### Tests`: cuando hay tests linkeables.
  - `### Reglas relacionadas`: cuando hay reglas con relación semántica.
  - `### Derogación`: cuando `Estado: derogated`.

---

## Errores comunes y cómo evitarlos

| Error                                                       | Síntoma                                       | Solución                                    |
| ----------------------------------------------------------- | --------------------------------------------- | ------------------------------------------- |
| Heading con `-` en vez de `—`                               | El parser no detecta la regla; audit no la lista | Usar siempre `—` (alt+shift+- en macOS).   |
| ID con minúsculas o sin guiones                             | Validador rechaza el archivo                  | `BR-PROD-EVENT-005`, no `Br-prod-event-5`.  |
| Cascada descrita en prosa sin diagrama                      | Lectura confusa para humanos y LLM            | Añadir `### Diagrama de cascada` con ASCII. |
| Tabla de casos con un solo caso                             | Pierde valor (ese era el caso obvio)          | Añadir al menos un caso límite o negativo.  |
| `last_updated` no actualizado tras cambio                   | Audit lo cuenta como antiguo                  | Refrescar al guardar.                       |
| `paths` faltando frontend cuando aplica                     | Inyección de contexto pierde activación       | Añadir glob de frontend si la regla la usa. |
| Apuntador en lugar de regla completa por error de copy/paste| Regla "huérfana" en el archivo destino        | Apuntadores SOLO referencian, no duplican.  |
