docs(metodo): re-estampar el linter — A6 (check_ids ve, y parte el veredicto) + A7 (palabra == rc)
check_ids admite la comilla invertida (veía 0 ids donde hay 130/118), parte el veredicto en rojo-de-esquema-nuevo vs nota-con-conteo-legacy, y DICE cuántos ids vio por fichero (anti-ceguera, con detector agnóstico de prefijo). El veredicto final deriva palabra y rc del mismo número y IMPRIME el rc al lado de la palabra, para que una tubería no se lo coma. Copia vendorizada: aquí NO se edita. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
a901586bab
commit
d2df969153
@ -1,2 +1,2 @@
|
|||||||
140cf44bc4d8e9eff08cd4f6466df22c897efa2c6c6f83662a747e3348a4f2bd metodo.md
|
140cf44bc4d8e9eff08cd4f6466df22c897efa2c6c6f83662a747e3348a4f2bd metodo.md
|
||||||
bf2144db0bb987bd32ce7eb8d99021ca0d29cb7b6a48d30a8ffd0fe723ca2a3f bin/metodo
|
d469ed0f661c56e3137953f880f5a7dfc51e0b74e49ae7616ac5d88bf6d91b99 bin/metodo
|
||||||
|
|||||||
@ -35,12 +35,13 @@ _write_checksums() { # $1 = dir .metodo del destino
|
|||||||
}
|
}
|
||||||
_is_matriz() { [ -f "$SELF_ROOT/constitucion-de-facto.md" ]; } # marca inequívoca de la matriz
|
_is_matriz() { [ -f "$SELF_ROOT/constitucion-de-facto.md" ]; } # marca inequívoca de la matriz
|
||||||
|
|
||||||
# --- veredictos (los cinco colores del check) ---
|
# --- veredictos (los cinco colores) + 'info', que es CENSO y no veredicto ---
|
||||||
hdr() { printf '\n\033[1m== %s ==\033[0m\n' "$*"; }
|
hdr() { printf '\n\033[1m== %s ==\033[0m\n' "$*"; }
|
||||||
ok() { printf ' \033[32mok \033[0m %s\n' "$*"; }
|
ok() { printf ' \033[32mok \033[0m %s\n' "$*"; }
|
||||||
bad() { printf ' \033[31mAVISO\033[0m %s\n' "$*"; FAILS=$((FAILS+1)); }
|
bad() { printf ' \033[31mAVISO\033[0m %s\n' "$*"; FAILS=$((FAILS+1)); }
|
||||||
skip() { printf ' \033[33mSKIP\033[0m %s\n' "$*"; }
|
skip() { printf ' \033[33mSKIP\033[0m %s\n' "$*"; }
|
||||||
warn() { printf ' \033[33mnota\033[0m %s\n' "$*"; WARNS=$((WARNS+1)); }
|
warn() { printf ' \033[33mnota\033[0m %s\n' "$*"; WARNS=$((WARNS+1)); }
|
||||||
|
info() { printf ' \033[36minfo\033[0m %s\n' "$*"; } # censo, NO veredicto: no mueve ningún contador
|
||||||
|
|
||||||
# ── Check 1 · integridad de la copia vendorizada (C11) ───────────────────────
|
# ── Check 1 · integridad de la copia vendorizada (C11) ───────────────────────
|
||||||
# El máster vive en OTRO repo (la matriz), así que el testigo no es el máster sino el
|
# El máster vive en OTRO repo (la matriz), así que el testigo no es el máster sino el
|
||||||
@ -72,26 +73,85 @@ check_drift() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# ── Check 2 · colisión de ids en los ficheros de estado (C17) ────────────────
|
# ── Check 2 · colisión de ids en los ficheros de estado (C17) ────────────────
|
||||||
|
# ⚠️ Este check estuvo CIEGO del 2026-08-08 al 2026-08-22 (`A6`): su regex de «id DEFINIDO» no
|
||||||
|
# admitía la COMILLA INVERTIDA, y los dos corpus más grandes del árbol escriben así sus
|
||||||
|
# decisiones — ``- **`D1` (técnica)** — …``. Veía **0** ids donde hay **130** y **118**, y con
|
||||||
|
# ellos **46 duplicados que nunca reportó**, incluidas las 18 `D1` que son la cicatriz de `D6`.
|
||||||
|
# El arreglo tiene TRES piezas, y la tercera es la que importa:
|
||||||
|
# (1) La vista se ENSANCHA: se admite cualquier adorno de markdown antes del id (`*` negrita,
|
||||||
|
# `~` tachado y la comilla invertida que faltaba).
|
||||||
|
# (2) El veredicto se PARTE, porque no todo duplicado es cerrable y un gate incerrable acaba
|
||||||
|
# apagado:
|
||||||
|
# · esquema NUEVO (nº ≥ 100, o id definido en doc/decisiones.md) → ROJO que mueve el rc.
|
||||||
|
# Es real y CERRABLE: el contador del repo es único y monótono, no debe pasar jamás.
|
||||||
|
# · legacy en backlog.md → UNA nota con el CONTEO. Renumerar está PROHIBIDO (C17) y la
|
||||||
|
# migración conserva el id como `fase·Dn` ⇒ una lista por-id sería una alarma que su
|
||||||
|
# dueño no puede cerrar. Es un MEDIDOR que drena a 0 con cada migración (D6).
|
||||||
|
# · AVISOS.md no entra en el reparto: sus ids son un contador único del repo, ahí un
|
||||||
|
# duplicado SÍ se cierra fusionando, y sigue en ROJO como hasta hoy.
|
||||||
|
# (3) ANTI-CEGUERA, que es la causa raíz y no el regex: el check DICE cuántos ids VIO por
|
||||||
|
# fichero —«vistos: 0» fue indistinguible de «no hay» durante dos semanas— y si un fichero
|
||||||
|
# tiene líneas con FORMA de id y 0 parseados, saca nota de posible ceguera. Es el
|
||||||
|
# gate-sin-sujeto aplicado al propio linter.
|
||||||
|
_IDPFX='(D|A|G|H|C|R|F|E|P)'
|
||||||
|
# id DEFINIDO = al principio de una fila de tabla (|) o item de lista (-*), con el adorno que
|
||||||
|
# sea. Así una MENCIÓN inline ("ver D5") no cuenta como definición (evita falsos positivos).
|
||||||
|
_RE_ID_DEF="^[[:space:]]*[|*_-]+[[:space:]]*[*~\`]*${_IDPFX}[0-9]+"
|
||||||
|
# LAXO: la MISMA posición de definición, pero con CUALQUIER adorno (hasta 12 caracteres no
|
||||||
|
# alfanuméricos: casillas `- [ ]`, emoji, comillas…) y —esto es lo que importa— con CUALQUIER
|
||||||
|
# PREFIJO de letra, no los de `_IDPFX`. Un detector de ceguera construido sobre el vocabulario
|
||||||
|
# que audita sólo sabe cazar la ceguera de ADORNO, jamás la de PREFIJO: sería el gate-sin-sujeto
|
||||||
|
# un piso más arriba. Medido el 2026-08-22: con `_IDPFX` no veía los nueve `B` de hermes-sitad.
|
||||||
|
# Es a propósito más ancho que el estricto y mucho más estrecho que «el id en cualquier sitio de
|
||||||
|
# la línea» — una mención en mitad de una frase no tiene forma de definición. Sólo se usa cuando
|
||||||
|
# el estricto ha visto 0: es el detector de «el sujeto está y no lo veo», no un criterio de id.
|
||||||
|
# La casilla de markdown (`- [ ]` / `- [x]` / `- [~]`) se salta APARTE: lleva un alfanumérico
|
||||||
|
# dentro y un item CERRADO define tanto como uno abierto.
|
||||||
|
_RE_ID_LOOSE="^[[:space:]]*[|*_-][[:space:]]*(\[.\])?[^[:alnum:]]{0,12}[A-Z]{1,2}[0-9]+"
|
||||||
|
_ids_def() { grep -oE "$_RE_ID_DEF" "$1" | grep -oE "${_IDPFX}[0-9]+"; }
|
||||||
|
|
||||||
check_ids() {
|
check_ids() {
|
||||||
hdr "colisión de ids en los ficheros de estado (C17)"
|
hdr "colisión de ids en los ficheros de estado (C17)"
|
||||||
local statefiles=( "$ROOT/doc/AVISOS.md" "$ROOT/doc/backlog.md" )
|
# Ids del esquema NUEVO que ya viven en la cuarta capa: un duplicado suyo es rojo aunque su
|
||||||
local any=0 f dups id
|
# número sea < 100 (un legacy MIGRADO ya tiene dueño que puede cerrarlo).
|
||||||
for f in "${statefiles[@]}"; do
|
local dec="$ROOT/doc/decisiones.md" nuevos_dec=""
|
||||||
|
[ -f "$dec" ] && nuevos_dec=$(awk '/^### /{ s=$0; gsub(/[*`]/,"",s); split(s,a,"[ \t]+"); if (a[2]!="") print a[2] }' "$dec")
|
||||||
|
local any=0 f base ids vistos sueltos dups id num rojos legacy
|
||||||
|
for f in "$ROOT/doc/AVISOS.md" "$ROOT/doc/backlog.md"; do
|
||||||
[ -f "$f" ] || continue
|
[ -f "$f" ] || continue
|
||||||
any=1
|
any=1; base=$(basename "$f")
|
||||||
# id DEFINIDO = al principio de una fila de tabla (|) o item de lista (-*) en negrita.
|
ids=$(_ids_def "$f")
|
||||||
# Así una MENCIÓN inline ("ver D5") no cuenta como definición (evita falsos positivos).
|
vistos=$(printf '%s\n' "$ids" | grep -c '[^[:space:]]')
|
||||||
dups=$(grep -oE '^[[:space:]]*[|*_-]+[[:space:]]*\**~*\**(D|A|G|H|C|R|F|E|P)[0-9]+' "$f" \
|
if [ "$vistos" -eq 0 ]; then
|
||||||
| grep -oE '(D|A|G|H|C|R|F|E|P)[0-9]+' | sort | uniq -d)
|
sueltos=$(grep -cE "$_RE_ID_LOOSE" "$f")
|
||||||
|
if [ "${sueltos:-0}" -gt 0 ]; then
|
||||||
|
warn "$base: 0 ids DEFINIDOS parseados pero ${sueltos} línea(s) con forma de id — posible CEGUERA del regex (A6): el verde de este fichero no prueba nada, compruébalo a mano"
|
||||||
|
else
|
||||||
|
info "$base: 0 ids definidos y 0 líneas con forma de id — no hay sujeto que medir"
|
||||||
|
fi
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
info "$base: ${vistos} id(s) DEFINIDOS vistos"
|
||||||
|
rojos=0; legacy=0
|
||||||
|
dups=$(printf '%s\n' "$ids" | sort | uniq -d)
|
||||||
if [ -n "$dups" ]; then
|
if [ -n "$dups" ]; then
|
||||||
while IFS= read -r id; do
|
while IFS= read -r id; do
|
||||||
[ -n "$id" ] && bad "id duplicado en $(basename "$f"): $id — renombra o fusiona (C17)"
|
[ -n "$id" ] || continue
|
||||||
|
num=${id#[A-Z]}
|
||||||
|
if { [ "${num:-0}" -ge 100 ] 2>/dev/null; } || printf '%s\n' "$nuevos_dec" | grep -qxF "$id"; then
|
||||||
|
bad "id duplicado en $base: $id — id de ESQUEMA NUEVO: citar uno gobierna con el otro (C17); renumera el nuevo desde el contador del repo"; rojos=$((rojos+1))
|
||||||
|
elif [ "$base" = "backlog.md" ]; then
|
||||||
|
legacy=$((legacy+1))
|
||||||
|
else
|
||||||
|
bad "id duplicado en $base: $id — renombra o fusiona (C17)"; rojos=$((rojos+1))
|
||||||
|
fi
|
||||||
done <<< "$dups"
|
done <<< "$dups"
|
||||||
else
|
|
||||||
ok "$(basename "$f"): sin ids duplicados"
|
|
||||||
fi
|
fi
|
||||||
|
[ "$legacy" -gt 0 ] && warn "$base: ${legacy} id(s) legacy duplicados (de ${vistos} vistos) — se resuelven MIGRANDO a doc/decisiones.md y citando \`fase·Dn\`, NUNCA renumerando (C17 · D6); es un medidor que drena, no una alarma"
|
||||||
|
[ "$rojos" -eq 0 ] && [ "$legacy" -eq 0 ] && ok "$base: sin ids duplicados"
|
||||||
done
|
done
|
||||||
[ "$any" -eq 0 ] && skip "sin doc/AVISOS.md ni doc/backlog.md (repo sin corpus de estado)"
|
[ "$any" -eq 0 ] && skip "sin doc/AVISOS.md ni doc/backlog.md (repo sin corpus de estado)"
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
# ── Check 3 · encabezados sin marca de estado (C16) ──────────────────────────
|
# ── Check 3 · encabezados sin marca de estado (C16) ──────────────────────────
|
||||||
@ -459,6 +519,13 @@ cmd_update() {
|
|||||||
echo "metodo update: $tgt actualizado al máster $mver (metodo.md + linter, byte a byte); realimentacion.md y adopted_commit preservados."
|
echo "metodo update: $tgt actualizado al máster $mver (metodo.md + linter, byte a byte); realimentacion.md y adopted_commit preservados."
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# El veredicto final (`A7`, 2026-08-22). Regla: **la palabra y el `rc` se derivan del MISMO
|
||||||
|
# número**, así que no hay camino por el que puedan discrepar. Y el `rc` se IMPRIME al lado de
|
||||||
|
# la palabra, porque la única forma medida de ver «NO pasa» con rc=0 es leer esta salida por
|
||||||
|
# una TUBERÍA (`… | tail`), que se come el exit code del script y deja el texto como único
|
||||||
|
# testigo. Un testigo que no sobrevive a cómo se le lee no es un testigo.
|
||||||
|
# Vocabulario, que es la mitad del arreglo: `AVISO` GATEA (mueve el rc) · `nota` es
|
||||||
|
# informativa y NO gatea · `info` es censo · `SKIP` es fallo benigno · `ok` es verde.
|
||||||
cmd_check() {
|
cmd_check() {
|
||||||
printf 'metodo check — %s\n' "$ROOT"
|
printf 'metodo check — %s\n' "$ROOT"
|
||||||
check_drift
|
check_drift
|
||||||
@ -470,15 +537,19 @@ cmd_check() {
|
|||||||
check_decisiones_en_backlog
|
check_decisiones_en_backlog
|
||||||
check_pointer
|
check_pointer
|
||||||
hdr "resultado"
|
hdr "resultado"
|
||||||
local nota=""
|
local rc=0
|
||||||
[ "$WARNS" -gt 0 ] && nota=$(printf ' · %d nota(s) — no mueven el código de salida, pero se cuentan' "$WARNS")
|
[ "$FAILS" -gt 0 ] && rc=1
|
||||||
if [ "$FAILS" -eq 0 ]; then
|
if [ "$rc" -ne 0 ]; then
|
||||||
printf ' \033[32mPASA el Método\033[0m (0 avisos%s)\n' "$nota"; exit 0
|
printf ' \033[31mNO pasa el Método — %d aviso(s) que GATEAN\033[0m (y %d nota(s) que no) · rc=%d\n' \
|
||||||
|
"$FAILS" "$WARNS" "$rc"
|
||||||
|
elif [ "$WARNS" -gt 0 ]; then
|
||||||
|
printf ' \033[32mPASA el Método\033[0m con %d nota(s) informativa(s) — 0 avisos que gateen; las notas se cuentan y NO mueven el rc · rc=%d\n' \
|
||||||
|
"$WARNS" "$rc"
|
||||||
else
|
else
|
||||||
printf ' \033[31m%d aviso(s) — el Método NO pasa\033[0m%s\n' "$FAILS" "$nota"; exit 1
|
printf ' \033[32mPASA el Método\033[0m (0 avisos, 0 notas) · rc=%d\n' "$rc"
|
||||||
fi
|
fi
|
||||||
|
exit "$rc"
|
||||||
}
|
}
|
||||||
|
|
||||||
case "${1:-}" in
|
case "${1:-}" in
|
||||||
check) ROOT="${2:-.}"; cmd_check ;;
|
check) ROOT="${2:-.}"; cmd_check ;;
|
||||||
init) cmd_init "${2:-.}" ;;
|
init) cmd_init "${2:-.}" ;;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user