# Business Rules — Migration Guide

> Cómo llevar este sistema a otro repo Aurora **sin que sea un parto**.

---

## Precondiciones del repo destino

El sistema asume:

- ✅ Monorepo pnpm con `package.json` raíz.
- ✅ Estructura `cliter/<bounded-context>/` para el dominio (Aurora estándar).
- ✅ Husky configurado (`.husky/` existe).
- ✅ OpenSpec instalado y `openspec/config.yaml` presente (opcional —
  el sistema funciona sin OpenSpec, solo pierdes la integración con propose).
- ✅ Claude Code instalado (`.claude/` existe).
- ✅ GitHub Actions disponible (para el CI estructural).
- ✅ Node 24+.

Si falta cualquiera, el sistema NO aplica tal cual; necesitarías adaptarlo.

---

## TL;DR — checklist de migración

```
□ 1. Copiar archivos NUEVOS (sin tocar nada existente del repo)
□ 2. Patch package.json (scripts + devDependencies)
□ 3. pnpm install
□ 4. Patch .husky/pre-commit (append bloque)
□ 5. Patch .claude/settings.json (añadir hook UserPromptSubmit)
□ 6. Patch openspec/config.yaml (añadir context + rules)  [opcional]
□ 7. Patch CLAUDE.md raíz (añadir sección Business rules + fila skills)
□ 8. Regenerar índice de skills (corre solo en SessionStart, o manual)
□ 9. Smoke test: pnpm br:generate, pnpm br:validate
     (audit completo: invocar /business-rules:audit desde Claude Code)
```

Tiempo estimado: **15-20 minutos**.

> El sistema NO incluye job nocturno automatizado para detección semántica.
> Esa dimensión se cubre preventivamente en `/opsx:propose` (vía
> `openspec/config.yaml`) e integrada en `/business-rules:audit` siguiendo
> el patrón **script + LLM continuation** (script estructural + Claude
> continúa la sesión con análisis pairwise).

---

## Lista exhaustiva de archivos

### Archivos NUEVOS (copiar tal cual)

```
docs/business-rules/README.md                         ← guía operativa
docs/business-rules/ARCHITECTURE.md                   ← documento técnico
docs/business-rules/MIGRATION.md                      ← este archivo
docs/business-rules/_schema.json                      ← JSON Schema del frontmatter

scripts/business-rules/types.ts                       ← interfaces compartidas
scripts/business-rules/parse-catalog.ts               ← parser
scripts/business-rules/generate-index.ts              ← generador de índice
scripts/business-rules/validate-catalog.ts            ← validador estructural
scripts/business-rules/validate-citations.ts          ← validador de @rule
scripts/business-rules/audit.ts                       ← reporte estructural
scripts/business-rules/promote.ts                     ← cristaliza desde archive
scripts/business-rules/document.ts                    ← bootstrap retroactivo
scripts/business-rules/check.ts                       ← validación dirigida

.claude/hooks/inject-rules-context.ts                 ← UserPromptSubmit hook

.claude/commands/business-rules/promote.md            ← /business-rules:promote
.claude/commands/business-rules/document.md           ← /business-rules:document
.claude/commands/business-rules/audit.md              ← /business-rules:audit
.claude/commands/business-rules/check.md              ← /business-rules:check

.claude/skills/business-rules-guard/SKILL.md          ← entry skill
.claude/skills/business-rules-guard/references/format.md
.claude/skills/business-rules-guard/references/workflow.md
.claude/skills/business-rules-guard/references/audit.md

.github/workflows/business-rules-check.yml            ← CI estructural
```

### Archivos MODIFICADOS (patches a aplicar)

```
package.json                                          ← scripts + devDependencies
.husky/pre-commit                                     ← append bloque
.claude/settings.json                                 ← append hook
openspec/config.yaml                                  ← append context + rules  [opcional]
CLAUDE.md                                             ← append sección + fila tabla
```

### Archivos GENERADOS (no copiar; aparecen al ejecutar)

```
cliter/business-rules-index.json                      ← pnpm br:generate
docs/business-rules/INDEX.md                          ← pnpm br:generate
```

### Archivos ESPECÍFICOS del repo origen (NO copiar)

```
cliter/<bc>/business-rules/<aggregate>.md             ← son las REGLAS del
                                                        catálogo origen, no
                                                        del sistema. El repo
                                                        destino tendrá sus
                                                        propias reglas.
openspec/changes/add-business-rules-system/           ← cambio OpenSpec con
                                                        proposal/design/specs/
                                                        tasks específicos del
                                                        repo origen
```

---

## Procedimiento paso a paso

### Paso 1 — Copiar archivos NUEVOS

Desde el repo origen (este), ejecutar:

```bash
# Definir destino
TARGET=/path/to/target/repo

# Crear estructura de directorios
mkdir -p "$TARGET"/{scripts/business-rules,.claude/{hooks,commands/business-rules,skills/business-rules-guard/references},.github/workflows,docs/business-rules}

# Copiar archivos
cp scripts/business-rules/*.ts "$TARGET"/scripts/business-rules/
cp .claude/hooks/inject-rules-context.ts "$TARGET"/.claude/hooks/
cp .claude/commands/business-rules/*.md "$TARGET"/.claude/commands/business-rules/
cp .claude/skills/business-rules-guard/SKILL.md "$TARGET"/.claude/skills/business-rules-guard/
cp .claude/skills/business-rules-guard/references/*.md "$TARGET"/.claude/skills/business-rules-guard/references/
cp .github/workflows/business-rules-check.yml "$TARGET"/.github/workflows/
cp docs/business-rules/{README,ARCHITECTURE,MIGRATION}.md "$TARGET"/docs/business-rules/
cp docs/business-rules/_schema.json "$TARGET"/docs/business-rules/
```

> **NO copies** los archivos del catálogo (`cliter/<bc>/business-rules/<agg>.md`)
> ni el cambio OpenSpec (`openspec/changes/add-business-rules-system/`). Esos
> son contenido específico del repo origen.

### Paso 2 — Patch `package.json`

En el `package.json` raíz del destino, añade:

**`scripts`** (mergear con los existentes):

```json
{
  "scripts": {
    // ... los existentes ...
    "br:generate": "tsx scripts/business-rules/generate-index.ts",
    "br:validate": "tsx scripts/business-rules/validate-catalog.ts",
    "br:validate:citations": "tsx scripts/business-rules/validate-citations.ts",
    "br:check": "tsx scripts/business-rules/check.ts"
  }
}
```

> **`br:audit`, `br:promote` y `br:document` NO se exponen como aliases**:
> los tres scripts siguen el patrón **script + LLM continuation** y se
> invocan exclusivamente desde sus slash commands respectivos en Claude
> Code (`/business-rules:audit`, `/business-rules:promote`,
> `/business-rules:document`), que ejecutan el script con
> `npx tsx scripts/business-rules/<script>.ts` y continúan la sesión con
> Claude para la parte que requiere razonamiento. Exponerlos como `pnpm
> br:*` daría feedback parcial bajo el mismo nombre que la versión
> completa integrada y confundiría al developer.

**`devDependencies`** (mergear con las existentes):

```json
{
  "devDependencies": {
    // ... las existentes ...
    "@types/node": "^25.9.1",
    "ajv": "^8.20.0",
    "ajv-formats": "^3.0.1",
    "fast-glob": "^3.3.3",
    "gray-matter": "^4.0.3",
    "tsx": "^4.19.2"
  }
}
```

### Paso 3 — `pnpm install`

```bash
cd "$TARGET"
pnpm install
```

### Paso 4 — Patch `.husky/pre-commit`

Si NO existe `.husky/pre-commit`, créalo. Si existe, **APPEND** al final:

```sh
# Business rules: regenerate the index AND validate the catalog when catalog
# files change. Generate keeps cliter/business-rules-index.json in sync with the
# source markdown; validate catches semantic errors (invalid Estado/Severidad,
# missing Implementa paths, etc.) that generate alone does not catch.
# If either step fails, the commit is aborted with a clear error.
catalog_changed=$(git diff --cached --name-only --diff-filter=ACMR | grep -E '^cliter/[^/]+/business-rules/.*\.md$' || true)

if [ -n "$catalog_changed" ]; then
  echo "› business-rules: detectados cambios en el catálogo, regenerando índice…"
  if ! pnpm --silent br:generate; then
    echo "✗ business-rules: la regeneración del índice falló."
    echo "  Revisa los errores anteriores y corrige el catálogo antes de volver a commitear."
    exit 1
  fi
  git add cliter/business-rules-index.json docs/business-rules/INDEX.md
  echo "✓ business-rules: índice regenerado y añadido al commit."

  echo "› business-rules: validando catálogo…"
  validate_exit=0
  pnpm --silent br:validate || validate_exit=$?
  if [ "$validate_exit" = "1" ]; then
    echo "✗ business-rules: validación falló con errores estructurales."
    echo "  Corrige los errores reportados arriba y vuelve a commitear."
    exit 1
  fi
  echo "✓ business-rules: catálogo válido."
fi
```

```bash
chmod +x "$TARGET/.husky/pre-commit"
```

### Paso 5 — Patch `.claude/settings.json`

Añadir el hook `UserPromptSubmit`. Si el archivo no tiene la sección
`hooks`, créala:

```json
{
  "hooks": {
    "UserPromptSubmit": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "npx tsx \"$CLAUDE_PROJECT_DIR/.claude/hooks/inject-rules-context.ts\"",
            "timeout": 5
          }
        ]
      }
    ]
  }
}
```

Si ya tienes `hooks.UserPromptSubmit`, mergear en el array.

### Paso 6 — Patch `openspec/config.yaml` (opcional)

> Solo si el repo destino usa OpenSpec. Si no, salta este paso.

Añade los siguientes bloques al `config.yaml`. Si ya existen `context` o
`rules`, mergea con cuidado (no sobrescribas tu config existente).

El contenido exacto está en el `openspec/config.yaml` del repo origen.
Cópialo entero o adáptalo si tienes context/rules propios.

### Paso 7 — Patch `CLAUDE.md`

Añadir sección "Business rules" entre "Bounded Context Documentation" y
"Skills (Auto-invoke based on context)". Texto exacto en el `CLAUDE.md`
del repo origen.

Añadir fila a la tabla "Skills (Auto-invoke based on context)":

```
| Business rules catalog: add/derogate rules, modify domain code with active rules, /business-rules:* | `.claude/skills/business-rules-guard/SKILL.md` |
```

El bloque entre `<!-- SKILLS-INDEX-START -->` y `<!-- SKILLS-INDEX-END -->`
se regenera automáticamente; no lo edites a mano.

### Paso 8 — Regenerar índice de skills

```bash
npx tsx "$TARGET/.claude/scripts/generate-skills-index.ts"
```

(O simplemente abre Claude Code en el repo destino; el SessionStart hook
lo regenera.)

### Paso 9 — Smoke tests

```bash
cd "$TARGET"

# Sin reglas todavía: el índice queda vacío pero el sistema funciona
pnpm br:generate
# → ✓ Índice regenerado: 0 reglas (0 activas, 0 derogadas, 0 propuestas) en 0 archivos.

pnpm br:validate
# → Resumen: 0 archivos analizados, 0 errores, 0 warnings.

# Para el audit completo (estructural + semántico) abre Claude Code y ejecuta:
#   /business-rules:audit
# (El script audit.ts no se expone como pnpm; el reporte útil es el
#  integrado, que solo el slash command produce.)
```

Si todo verde, el sistema está instalado correctamente.

> **No hay configuración externa adicional**. La detección de tensiones
> semánticas se hace preventivamente en `/opsx:propose` y a demanda
> invocando `/business-rules:audit` (script + Claude continúa la sesión
> dentro de Claude Code).

---

## Detección de tensiones semánticas

El sistema NO incluye un job nocturno automatizado para detectar
contradicciones semánticas entre reglas. La cobertura se hace en dos
planos sin infraestructura externa:

- **Preventivo (en cada cambio)**: `/opsx:propose` está extendido vía
  `openspec/config.yaml` para que Claude consulte el catálogo y detecte
  conflictos antes de archivar el cambio. Es la principal red de
  seguridad.
- **Integrado en el slash command `/business-rules:audit`**: el comando
  sigue el patrón **script + LLM continuation** (mismo que
  `/business-rules:promote`):
  1. Paso 1 — `npx tsx scripts/business-rules/audit.ts` corre la parte
     estructural (Salud, Drift, Asunciones, Cross-BC pointers).
  2. Paso 2 — Claude continúa la sesión: lee el índice, empareja reglas
     que comparten BC/aggregate/keyword, lee el body de cada par,
     clasifica como `contradiction | extension | orthogonal |
     needs-review` con confianza 0–1, y añade la sección E al reporte.

  Sin SDK, sin API key, sin routine, sin GitHub App. El análisis usa
  los tokens de la suscripción de Claude Code abierta. El script
  `audit.ts` **no se expone como `pnpm br:*`**: su output sin sección
  E es un sub-producto, y dar el mismo nombre a un reporte parcial
  crearía confusión.

**Cuándo invocar `/business-rules:audit`**:

- Tras una sesión de bootstrap masivo (`:document` aplicado a varios
  agregados seguidos).
- Cuando el catálogo crezca más allá de 50 reglas activas y haga tiempo
  que no se revise la coherencia global.
- Tras un merge grande en main que tocó varios BCs.

> Para tooling externo o debugging existe `npx tsx
> scripts/business-rules/audit.ts` (con `--json` para output
> machine-consumable); la sección E aparece únicamente cuando el
> audit se invoca vía el slash command.

---

## Cuando vayas a hacer el merge en este repo

Esto es lo que tienes ahora **en stage** que pertenece al sistema:

```
docs/business-rules/                                  (nuevo dir, 5 archivos)
cliter/production-planning/business-rules/            (nuevo, 3 archivos — REGLAS, no sistema)
cliter/business-rules-index.json                      (nuevo, generado)
scripts/business-rules/                               (nuevo dir, 10 archivos)
.claude/hooks/inject-rules-context.ts                 (nuevo)
.claude/commands/business-rules/                      (nuevo dir, 4 archivos)
.claude/skills/business-rules-guard/                  (nuevo dir, 4 archivos)
.github/workflows/business-rules-check.yml            (nuevo)
openspec/changes/add-business-rules-system/           (nuevo dir, OpenSpec change)
package.json                                          (modificado: +scripts, +devDeps)
.husky/pre-commit                                     (nuevo o modificado)
.claude/settings.json                                 (modificado: +UserPromptSubmit)
openspec/config.yaml                                  (modificado: +context, +rules)
CLAUDE.md                                             (modificado: +sección, +fila skills,
                                                       +índice automático regenerado)
```

**Sugerencia de commits** (para no perder la trazabilidad):

```bash
# Commit 1 — Sistema (todo lo del sistema, sin reglas piloto)
git add docs/business-rules/ scripts/business-rules/ \
        .claude/hooks/inject-rules-context.ts \
        .claude/commands/business-rules/ \
        .claude/skills/business-rules-guard/ \
        .github/workflows/business-rules-check.yml \
        package.json pnpm-lock.yaml \
        .husky/pre-commit .claude/settings.json \
        openspec/config.yaml CLAUDE.md
git commit -m "feat(business-rules): add catalog system with tooling, hooks, CI and skill"

# Commit 2 — Catálogo piloto (las reglas reales)
git add cliter/production-planning/business-rules/ \
        cliter/business-rules-index.json \
        docs/business-rules/INDEX.md
git commit -m "feat(business-rules): bootstrap pilot catalog for production-planning"

# Commit 3 — OpenSpec change (registro del proceso)
git add openspec/changes/add-business-rules-system/
git commit -m "feat(openspec): record add-business-rules-system change"
```

Esos 3 commits son auto-explicativos y separan **sistema** (portable a
otros repos) de **datos** (específico de este repo).

---

## Variantes posibles de migración

### Variante A — Solo el sistema, sin reglas

Para un repo que aún no tiene reglas pero quiere preparar el terreno:

- Sigue todo el procedimiento.
- En el paso 9 verás `0 reglas`.
- A medida que el dominio crezca, los devs ejecutarán
  `/business-rules:document <bc>/<aggregate>` cuando proceda.

### Variante B — Sistema + bootstrap inmediato de un agregado

Para un repo con dominio maduro que quiera empezar con reglas YA:

- Sigue todo el procedimiento.
- Adicionalmente, abre Claude Code y ejecuta `/business-rules:document
  <bc>/<aggregate>` en una sesión guiada con dominio. Documenta 1-3
  reglas conservativas (con `[VERIFICAR]` en lo dudoso).
- Iterar.

### Variante C — Sin OpenSpec

Para un repo que NO usa OpenSpec:

- Salta el paso 6 (`openspec/config.yaml`).
- Pierdes la inyección automática de business rules awareness en
  `/opsx:propose`.
- El resto del sistema funciona igual: `:document`, `:promote` (lee
  `proposal.md` por path explícito o de un sistema equivalente),
  `:audit`, `:check`, hook UserPromptSubmit.

### Variante D — Sin GitHub Actions (GitLab, otro)

Para un repo en GitLab CI o equivalente:

- Adapta `business-rules-check.yml` al CI tool del destino. Es un YAML
  simple (3 pasos: validate, generate+diff, validate-citations).
- La detección de tensiones semánticas no depende del CI: se hace
  preventivamente en `/opsx:propose` y on-demand vía Claude Code (ver
  sección "Detección de tensiones semánticas on-demand" arriba).

---

## Mantenimiento del sistema en multi-repo

Cuando hagas un cambio al sistema (nueva feature, fix), tienes dos rutas:

**Opción 1 — Distribución manual**: aplicas el cambio al repo origen, y
cada repo destino lo cherry-pickea cuando le toque. Bajo overhead, alto
drift potencial.

**Opción 2 — NPM package**: extraes `scripts/business-rules/` a un paquete
publicado (`@aurora/business-rules` o similar) y los repos lo consumen.
Los scripts pnpm pasarían a invocar el binario del paquete. Más overhead
inicial, pero updates triviales (`pnpm update`).

Para 1-3 repos, opción 1 es razonable. Para >5 repos, considera opción 2.
