#!/usr/bin/env bash
#
# verificar-convenciones-sync.sh
#
# Avisa cuando una convención se pierde entre `CONVENCIONES-CLAUDE.md` (este archivo del
# repo, el que lee el equipo) y lo que de verdad cargan las ventanas de Claude en la Mac
# de Manuel: `~/.claude/CLAUDE.md` más sus skills en `~/.claude/skills/`.
#
# ⚠️ Hasta el 13-ago-2026 esto comparaba los dos archivos con `diff`, porque la convención
# pedía que fueran idénticos. Ese día se midió el costo —el archivo más la memoria eran
# ~38 KB reenviados en CADA petición de CADA ventana— y tres bloques operativos se
# movieron a skills, que se cargan sólo cuando la tarea las toca. Desde entonces los dos
# archivos difieren A PROPÓSITO y un `diff` fallaría siempre.
#
# Lo que NO cambió es el motivo de la regla: que no se pierda una convención sin que nadie
# se entere. Por eso esto no es "confiar", es una comprobación de cobertura: cada sección
# del archivo del repo tiene que seguir existiendo en el CLAUDE.md local o en una skill.
#
# El archivo del repo es la fuente de verdad y NO se recorta nunca — las demás máquinas
# no tienen las skills de Manuel.
#
# Corre en el pre-commit de mbinv, y también a mano.
#
# Salida:
#   0  = todo cubierto, o NO APLICA (no es la Mac: falta ~/.claude/CLAUDE.md)
#   1  = falta al menos una sección (la nombra)
#
set -u

LOCAL="$HOME/.claude/CLAUDE.md"
SKILLS="$HOME/.claude/skills"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)"
REPO="$SCRIPT_DIR/CONVENCIONES-CLAUDE.md"

# No es la Mac de Manuel (u otra máquina sin el archivo local): el chequeo no aplica.
[ -f "$LOCAL" ] || exit 0
[ -f "$REPO" ]  || exit 0

SUPERFICIE=$(mktemp) || exit 0
trap 'rm -f "$SUPERFICIE"' EXIT
cat "$LOCAL" > "$SUPERFICIE"
[ -d "$SKILLS" ] && find "$SKILLS" -name "SKILL.md" -exec cat {} \; >> "$SUPERFICIE" 2>/dev/null

REPO="$REPO" SUPERFICIE="$SUPERFICIE" python3 - <<'PY'
import os, re, sys

repo = open(os.environ["REPO"], encoding="utf-8").read().split("\n")
superficie = open(os.environ["SUPERFICIE"], encoding="utf-8").read()


def normal(s):
    """Quita el formato de markdown y aplasta espacios, para comparar el contenido
    y no la presentación: una regla que se movió a una skill puede quedar con otro
    nivel de encabezado o sin las negritas, y sigue siendo la misma regla."""
    s = re.sub(r"[*`>_#\[\]()]", "", s)
    return re.sub(r"\s+", " ", s).strip().lower()


sup = normal(superficie)

secciones, actual = [], None
for linea in repo:
    if linea.startswith("## "):
        actual = (linea[3:].strip(), [])
        secciones.append(actual)
    elif actual is not None:
        actual[1].append(linea)

# Se comprueba CADA frase larga de cada sección, no una muestra.
#
# ⚠️ La primera versión de esto miraba sólo las 3 frases más largas por sección. La
# prueba negativa la tumbó: se le borraron tres renglones a una regla en medio de una
# sección —el de nombrar los respaldos con fecha— y el chequeo pasó igual, porque las
# 3 frases más largas seguían ahí. Un chequeo que confirma que la sección "existe" no
# es lo mismo que uno que confirma que está completa, y el primero da una falsa
# tranquilidad que es peor que no tener nada.
faltantes = []
for titulo, cuerpo in secciones:
    frases = [normal(l) for l in cuerpo if len(normal(l)) > 45]
    if not frases:
        continue  # sección sin frases largas: no hay nada que comprobar
    perdidas = [f for f in frases if f not in sup]
    if perdidas:
        faltantes.append((titulo, perdidas[0], len(perdidas), len(frases)))

if faltantes:
    print("", file=sys.stderr)
    print("⚠️  SE PERDIÓ UNA CONVENCIÓN", file=sys.stderr)
    print("   Estas secciones de CONVENCIONES-CLAUDE.md no están ni en", file=sys.stderr)
    print("   ~/.claude/CLAUDE.md ni en ninguna skill de ~/.claude/skills/:", file=sys.stderr)
    print("", file=sys.stderr)
    for titulo, frase, cuantas, total in faltantes:
        print(f"     • {titulo}  ({cuantas} de {total} frases)", file=sys.stderr)
        print(f'       falta: "{frase[:80]}..."', file=sys.stderr)
    print("", file=sys.stderr)
    print("   Arreglar: copiar esa sección al CLAUDE.md local, o a la skill que", file=sys.stderr)
    print("   corresponda (trabajo-en-repos / pruebas-y-evidencia / claves-y-credenciales).", file=sys.stderr)
    print("", file=sys.stderr)
    sys.exit(1)

sys.exit(0)
PY
