chore(metodo): re-estampado 2026-08-23 (A43: el > de blockquote · D102: la casilla) + bloque eol=lf acotado
This commit is contained in:
parent
0979e5bb51
commit
be753157cf
12
.gitattributes
vendored
Normal file
12
.gitattributes
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# >>> metodo:eol
|
||||||
|
# Gestionado por `metodo init/update` — NO editar a mano (se re-estampa).
|
||||||
|
# ACOTADO a los dos globs que el linter recorre: los `*.md` de RAÍZ y `doc/*.md` (glob de shell,
|
||||||
|
# sólo hijos directos). Es HIGIENE, no una avería: medido el 2026-08-23 en hermes-hub con dos
|
||||||
|
# worktrees a la misma profundidad —uno con 14 ficheros en CRLF y otro con 0—, `metodo check`
|
||||||
|
# da EXACTAMENTE la misma salida. Se fija el EOL para que el árbol no dependa de cómo se hizo
|
||||||
|
# cada checkout, no porque el linter se rompa.
|
||||||
|
# ⛔ Nunca `* text=auto` aquí: hay repos con binarios en LFS y con PDF versionados — ESO sí es
|
||||||
|
# destructivo y está medido.
|
||||||
|
/*.md text eol=lf
|
||||||
|
doc/*.md text eol=lf
|
||||||
|
# <<< metodo:eol
|
||||||
@ -1,2 +1,2 @@
|
|||||||
140cf44bc4d8e9eff08cd4f6466df22c897efa2c6c6f83662a747e3348a4f2bd metodo.md
|
a0a8a9cb931436c37973ea2d882294c2dcbe79af713528488506c749f9b6ad21 metodo.md
|
||||||
09189db5840b85e18a71aad9073b0642c9845dbcab08eccda2c83494d521d994 bin/metodo
|
502f5a70de21a41c2a1fee1f149bcab7767d277469282884273f5c98c2b4db41 bin/metodo
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
# Copia vendorizada del Método (raíl C11). Gestionada por 'metodo init/update'.
|
# Copia vendorizada del Método (raíl C11). Gestionada por 'metodo init/update'.
|
||||||
master: metodo
|
master: metodo
|
||||||
version: 2026-08-22
|
version: 2026-08-23
|
||||||
estado: vendored
|
estado: vendored
|
||||||
adopted_commit: 6a10eab342a477846ab5f3e67f8ab17169f12807
|
adopted_commit: 6a10eab342a477846ab5f3e67f8ab17169f12807
|
||||||
|
|||||||
@ -101,33 +101,64 @@ _IDPFX='D|A|B|G|H|C|M|R|F|E|P'
|
|||||||
|
|
||||||
# ── el reconocedor de ids ────────────────────────────────────────────────────
|
# ── el reconocedor de ids ────────────────────────────────────────────────────
|
||||||
# ⚠️ Está en **awk y no en un `grep -oE` encadenado**, y el motivo es el LÍMITE POR LA DERECHA
|
# ⚠️ Está en **awk y no en un `grep -oE` encadenado**, y el motivo es el LÍMITE POR LA DERECHA
|
||||||
# (`D100`): no se puede expresar sin lookahead. Se intentó con un segundo `grep -vE` y el filtro
|
# (`D101`): no se puede expresar sin lookahead. Se intentó con un segundo `grep -vE` y el filtro
|
||||||
# casaba `D1` + `7` dentro de `D17` ⇒ **declaraba sub-id a todo id de dos cifras**. Aquí el id y su
|
# casaba `D1` + `7` dentro de `D17` ⇒ **declaraba sub-id a todo id de dos cifras**. Aquí el id y su
|
||||||
# cola se miran POR SEPARADO, que es la única forma de que la pregunta sea la que parece.
|
# cola se miran POR SEPARADO, que es la única forma de que la pregunta sea la que parece.
|
||||||
#
|
#
|
||||||
# modo `def` → **id DEFINIDO**: posición de definición (fila de tabla `|` o item de lista `-*`,
|
# modo `def` → **id DEFINIDO**: POSICIÓN de definición + adorno (negrita, tachado, comilla
|
||||||
# con su adorno: negrita, tachado y comilla invertida) + prefijo de `_IDPFX`. Así
|
# invertida) + prefijo de `_IDPFX`. Así una MENCIÓN inline («ver D5») no define
|
||||||
# una MENCIÓN inline («ver D5») no define nada y no da falsos positivos.
|
# nada y no da falsos positivos. Las posiciones, y de dónde salió cada una:
|
||||||
# modo `forma` → **¿tiene esta línea FORMA de definición?**, con CUALQUIER prefijo de letra y
|
# · `|` fila de tabla · `-`/`*`/`_` item de lista (desde el día uno)
|
||||||
# CUALQUIER adorno (casilla `- [ ]`/`- [x]` incluida — un item cerrado define tanto
|
# · `[ ]`/`[x]`/`[~]` **casilla de ítem** — `D102`, disparada el 2026-08-23:
|
||||||
# como uno abierto). Es a propósito agnóstico de `_IDPFX`: un detector de ceguera
|
# `- [ ] **M5.1**` define un id tan real como el de una decisión, y eran
|
||||||
# construido sobre el vocabulario que audita sólo caza la ceguera de ADORNO, jamás
|
# **403 líneas** del árbol sin auditar.
|
||||||
# la de PREFIJO, que es el gate-sin-sujeto un piso más arriba. Sólo se usa cuando
|
# · `>` **blockquote** — `A43` del edge, 2026-08-23: tres decisiones de USUARIO
|
||||||
# el estricto ha visto 0.
|
# de Xavier (`D23`/`D24`/`D25`) vivían ahí y **ningún censo las vio nunca**;
|
||||||
|
# peor, `check_decisiones_en_backlog` declaraba `ok` sobre ellas.
|
||||||
|
# ⛔ **Un `>` a secas NO basta, y esto es lo que separa la señal del ruido**: en
|
||||||
|
# markdown el `>` va en **TODAS** las líneas de un párrafo citado, así que una
|
||||||
|
# línea de continuación que empieza por un id («> `D6` del Método):*») no define
|
||||||
|
# nada. Medido en el árbol: admitirlo a secas metía **4 falsos positivos**
|
||||||
|
# (asgard `H33`, hub `R9`, JISR `G9`, medusa `A2`) y **3 más** en el propio
|
||||||
|
# fichero del edge (`D6`, `P11`, `D3`).
|
||||||
|
# ⇒ cuando la posición es SÓLO `>` se exige **negrita**; si el `>` viene con un
|
||||||
|
# marcador de lista o tabla detrás (`> - **D5**`), manda ése y no hace falta.
|
||||||
|
# Con la regla: 3/3 las tres `D` de `A43`, 0 falsos positivos en todo el árbol.
|
||||||
|
# modo `forma` → **¿tiene esta línea FORMA de definición?**, con CUALQUIER prefijo de letra,
|
||||||
|
# CUALQUIER adorno y `>` **a secas** (sin exigir negrita). Es a propósito agnóstico
|
||||||
|
# de `_IDPFX`, del adorno, del límite y **de la restricción de posición**: un
|
||||||
|
# detector de ceguera construido sobre el criterio que audita sólo caza la ceguera
|
||||||
|
# que ya se le ha quitado. Es la **cuarta cara** de la misma familia —prefijo
|
||||||
|
# (`gate-sin-sujeto`), adorno, límite, y ahora POSICIÓN—, y es literalmente por
|
||||||
|
# qué `A43` no saltó: las tres líneas de blockquote salían **0** también aquí
|
||||||
|
# (medido: 0/3 antes, 3/3 después), así que no estaban ni en la nota ni en el
|
||||||
|
# `no adm.` del censo. Estaban en ningún sitio.
|
||||||
#
|
#
|
||||||
# El LÍMITE POR LA DERECHA vale para los dos: `P9b`/`P9c` NO son `P9`, `E8.a` NO es `E8` y
|
# El LÍMITE POR LA DERECHA vale sólo para el estricto: `P9b`/`P9c` NO son `P9`, `E8.a` NO es `E8` y
|
||||||
# `R5-bis` NO es `R5` —son **sub-ids**, no colisiones, y contarlos como el padre fabricaba
|
# `R5-bis` NO es `R5` —son **sub-ids**, no colisiones, y contarlos como el padre fabricaba
|
||||||
# duplicados que no existen—; y `E2E` («end-to-end») no es un id en absoluto. Ninguno de los dos
|
# duplicados que no existen—; y `E2E` («end-to-end») no es un id en absoluto. Ninguno de los dos
|
||||||
# casos se puede distinguir del otro por su forma, así que ninguno cuenta como definición.
|
# casos se puede distinguir del otro por su forma, así que ninguno cuenta como definición.
|
||||||
_id_scan() { # $1 = fichero · $2 = def|forma
|
_id_scan() { # $1 = fichero · $2 = def|defnr|subid|forma
|
||||||
awk -v pfx="$_IDPFX" -v modo="$2" '
|
awk -v pfx="$_IDPFX" -v modo="$2" '
|
||||||
{ if (modo != "forma") { if (match($0, "^[[:space:]]*[|*_-]+[[:space:]]*[*~`]*") == 0) next }
|
{ if (modo != "forma") { if (match($0, "^[[:space:]]*(>[[:space:]]*)*[|*_-]*[[:space:]]*([[].[]][[:space:]]*)?[*~`]*") == 0) next }
|
||||||
else { if (match($0, "^[[:space:]]*[|*_-][[:space:]]*([[].[]])?[^[:alnum:]]*") == 0) next }
|
# ⚠️ El laxo NO lleva el grupo `(>[[:space:]]*)*` del estricto, y NO es un olvido: su adorno
|
||||||
|
# es `[^[:alnum:]]*`, que ya se traga el `>`. Se midió — con el grupo puesto, su mutación
|
||||||
|
# NO mataba ni una cara, o sea era código que no se puede romper. Quien deja aquí la
|
||||||
|
# capacidad de ver el blockquote es la GUARDA de abajo, y por eso su clase lleva el `>`.
|
||||||
|
else { if (match($0, "^[[:space:]]*[|*_-]?[[:space:]]*([[].[]])?[^[:alnum:]]*") == 0) next }
|
||||||
|
pre = substr($0, 1, RLENGTH)
|
||||||
|
# Con todo opcional, el patrón casa la cadena VACÍA en cualquier línea ⇒ hace falta exigir
|
||||||
|
# que se haya visto AL MENOS un marcador de posición. Sin esto, una frase que empieza por
|
||||||
|
# un id sería una definición.
|
||||||
|
if (pre !~ /[|*>_-]/) next
|
||||||
|
# ⛔ El `>` de markdown NO marca «aquí empieza algo»: marca «esta línea está citada», y va en
|
||||||
|
# todas las del párrafo. Sólo cuenta como posición si trae NEGRITA (o un marcador de lista).
|
||||||
|
if (modo != "forma" && pre ~ /^[[:space:]]*>/ && pre !~ /[|_-]/ && pre !~ /\*\*/) next
|
||||||
rest = substr($0, RLENGTH + 1)
|
rest = substr($0, RLENGTH + 1)
|
||||||
re = (modo == "forma") ? "^[A-Z][A-Z]?[0-9]+" : "^(" pfx ")[0-9]+"
|
re = (modo == "forma") ? "^[A-Z][A-Z]?[0-9]+" : "^(" pfx ")[0-9]+"
|
||||||
if (match(rest, re) == 0) next
|
if (match(rest, re) == 0) next
|
||||||
id = substr(rest, 1, RLENGTH); cola = substr(rest, RLENGTH + 1)
|
id = substr(rest, 1, RLENGTH); cola = substr(rest, RLENGTH + 1)
|
||||||
# ⚠️ El LÍMITE POR LA DERECHA (`D100`) NO se aplica al modo `forma`: ese es el detector de
|
# ⚠️ El LÍMITE POR LA DERECHA (`D101`) NO se aplica al modo `forma`: ese es el detector de
|
||||||
# «el sujeto está y no lo veo», y un detector que descarta lo mismo que el criterio deja de
|
# «el sujeto está y no lo veo», y un detector que descarta lo mismo que el criterio deja de
|
||||||
# detectar nada. Se midió: con el límite puesto, medusa decía 12 líneas con forma de id
|
# detectar nada. Se midió: con el límite puesto, medusa decía 12 líneas con forma de id
|
||||||
# donde hay 49. Es la MISMA lección que ya obligó a hacerlo agnóstico de prefijo.
|
# donde hay 49. Es la MISMA lección que ya obligó a hacerlo agnóstico de prefijo.
|
||||||
@ -382,6 +413,56 @@ check_decisiones_en_backlog() {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# ── Check 9 · decisiones con forma de PROSA, sin id (nota) ───────────────────
|
||||||
|
# `A43`(c), 2026-08-23. ⛔ **El linter NO intenta leer prosa**: reconocer decisiones por su
|
||||||
|
# contenido es un pozo, y la decisión (superadmin) fue explícita en no bajar ahí. Esto no lee
|
||||||
|
# prosa — mira un **marcador que el autor ya escribió**, en MAYÚSCULAS, y pregunta una sola cosa:
|
||||||
|
# ¿hay un id de registro cerca? Si no lo hay, saca **nota**. Señala, no gatea.
|
||||||
|
#
|
||||||
|
# La cicatriz: `I11.14` del hub —decisión de XAVIER, con dueño y fecha en su propia ficha— nunca
|
||||||
|
# tuvo id. Camino del registro se resumió, y el resumen **invertía el sujeto** («al edge le
|
||||||
|
# consta» por «a este hub le consta») y **perdía la mitad estrecha** («de ese llamante»): habría
|
||||||
|
# entrado en el registro mintiendo desde la primera línea. Un id no es burocracia — es lo que
|
||||||
|
# ata una decisión a **su texto**.
|
||||||
|
#
|
||||||
|
# ⚠️ La forma canónica sigue siendo UNA (`D6`): una entrada en `doc/decisiones.md` con id. Esta
|
||||||
|
# nota sólo dice *«aquí hay una decisión escrita a mano y sin número»*; **quién le pone el número
|
||||||
|
# es su dueño**, no una sesión de paso y desde luego no el linter.
|
||||||
|
_PROSA_MARCA='DECISI' # MAYÚSCULAS a propósito: «la decisión de X» en prosa corriente no es marca
|
||||||
|
_PROSA_CERCA=2 # líneas arriba/abajo donde vale un id de registro para dar por citada
|
||||||
|
_PROSA_TOPE=5 # tope de notas por fichero — y lo que caiga fuera se DICE, no se calla
|
||||||
|
check_decisiones_en_prosa() {
|
||||||
|
hdr "decisiones con forma de prosa, sin id (D6 · A43)"
|
||||||
|
local any=0 f base out n total line txt
|
||||||
|
for f in "$ROOT/doc/backlog.md" "$ROOT/doc/AVISOS.md"; do
|
||||||
|
[ -f "$f" ] || continue
|
||||||
|
any=1; base=$(basename "$f")
|
||||||
|
# El id "cerca" se busca como `D<n>` —el vocabulario del REGISTRO— y no como id cualquiera:
|
||||||
|
# `I11.14` es el id del ÍTEM, y tenerlo al lado es justo el caso que hay que denunciar.
|
||||||
|
out=$(awk -v M="$_PROSA_MARCA" -v N="$_PROSA_CERCA" '
|
||||||
|
{ L[NR]=$0 }
|
||||||
|
END { for (i=1;i<=NR;i++) {
|
||||||
|
if (L[i] !~ M) continue
|
||||||
|
cerca=0
|
||||||
|
for (j=i-N; j<=i+N; j++) if (j>=1 && j<=NR && L[j] ~ /D[0-9]+/) cerca=1
|
||||||
|
if (!cerca) print i "\t" substr(L[i], 1, 110) } }' "$f")
|
||||||
|
total=$(printf '%s\n' "$out" | grep -c '[^[:space:]]')
|
||||||
|
if [ "$total" -eq 0 ]; then
|
||||||
|
ok "$base: ningún marcador de decisión sin id de registro cerca"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
n=0
|
||||||
|
while IFS=$'\t' read -r line txt; do
|
||||||
|
[ -n "$line" ] || continue
|
||||||
|
n=$((n+1)); [ "$n" -gt "$_PROSA_TOPE" ] && continue
|
||||||
|
warn "decisión con forma de prosa, sin id — $base:$line · ${txt} … ⇒ si es una decisión, va a doc/decisiones.md con id y su TEXTO ÍNTEGRO (D6); si no lo es, baja el marcador a minúsculas"
|
||||||
|
done <<< "$out"
|
||||||
|
[ "$total" -gt "$_PROSA_TOPE" ] && warn "$base: y ${total} en total — sólo se listan las primeras ${_PROSA_TOPE} (el tope se dice, no se calla)"
|
||||||
|
done
|
||||||
|
[ "$any" -eq 0 ] && skip "sin doc/backlog.md ni doc/AVISOS.md (repo sin corpus de estado)"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
# ── plantillas de doc/ (sólo se crean si faltan — brownfield: no pisar) ───────
|
# ── plantillas de doc/ (sólo se crean si faltan — brownfield: no pisar) ───────
|
||||||
_scaffold_docs() { # $1 = repo destino
|
_scaffold_docs() { # $1 = repo destino
|
||||||
# La casa de docs es UNA y se llama doc/ (el linter ancla ahí el corpus de estado).
|
# La casa de docs es UNA y se llama doc/ (el linter ancla ahí el corpus de estado).
|
||||||
@ -462,6 +543,98 @@ EOF
|
|||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# ── el `.gitattributes` de RAÍZ (bloque gestionado) ──────────────────────────
|
||||||
|
# ⚰️ **OJO CON EL MOTIVO: el que se escribió primero era FALSO y está medido como tal.** Se dijo
|
||||||
|
# —y lo decía ya el ítem de partida— que un `git worktree add` limpio hacía que `metodo check`
|
||||||
|
# contara **el doble** (299 avisos contra 123). Es cierto que los cuenta, pero **no por el EOL**:
|
||||||
|
# medido el 2026-08-23 con dos worktrees del hub **a la misma profundidad**, uno con 14 ficheros
|
||||||
|
# en CRLF y otro con 0, la salida del linter es **IDÉNTICA** —mismos 123 avisos, mismas 6 notas,
|
||||||
|
# mismos 19 enlaces rotos—. Los 176 de más eran **enlaces relativos que salen del repo**
|
||||||
|
# (`../../../workflows/…`), que sólo resuelven desde el árbol de trabajo: se estaba midiendo la
|
||||||
|
# UBICACIÓN del checkout, no su final de línea. Y el mecanismo que se le atribuía tampoco existe:
|
||||||
|
# `check_links` captura hasta el `)` y el `\r` va **después**, al final de la línea.
|
||||||
|
#
|
||||||
|
# ⇒ **`metodo check` es EOL-independiente, y eso ya es un resultado**: retira una hipótesis que
|
||||||
|
# estaba a punto de convertirse en doctrina. Es la TERCERA vez que un mecanismo del CRLF se cae
|
||||||
|
# al carearlo con su consumidor real (antes: `kubectl` normalizando el `\r` en dos de las cinco
|
||||||
|
# mordidas registradas).
|
||||||
|
#
|
||||||
|
# ⇒ Entonces **por qué se estampa igual**, dicho sin inflarlo: por **higiene y uniformidad**, y
|
||||||
|
# porque el principio *«lo que un gate o un instrumento lee se fija en LF»* ya estaba aprobado por
|
||||||
|
# Xavier para los SUJETOS de los arneses —donde sí hay cicatriz medida: un `sed` anclado en `$`
|
||||||
|
# se apaga—. Aquí **no hay cicatriz**: el coste es cero y el beneficio es que el árbol deja de
|
||||||
|
# depender de cómo se hizo cada checkout. ⚠️ Si algún día estorba, se quita sin perder nada.
|
||||||
|
#
|
||||||
|
# ⛔ **ACOTADO, y NUNCA `* text=auto`.** Esto sí está medido, y en el sentido destructivo: en
|
||||||
|
# `Solidaria` hay **15 PDF** bajo `app/templates/`, y un `text` sobre ellos les reescribe en cada
|
||||||
|
# checkout los bytes que parezcan finales de línea; `hermes-hub` tiene binarios en LFS y su propio
|
||||||
|
# `.gitattributes` documenta por qué no la pone. Aquí se declaran **exactamente los dos globs que
|
||||||
|
# el linter recorre** — los `*.md` de RAÍZ y `doc/*.md` — y ni un patrón más.
|
||||||
|
#
|
||||||
|
# ⚠️ **Declarar NO es refrescar, y renormalizar el ÍNDICE tampoco**: `git add --renormalize` deja
|
||||||
|
# el worktree en CRLF (`i/lf w/crlf`), y `git checkout --` a secas **salta** los ficheros que el
|
||||||
|
# caché de `stat` da por al día. Hay que **borrarlos y volver a sacarlos**. Por eso el estampado
|
||||||
|
# **mide** (`git ls-files --eol`) y lo dice en voz alta.
|
||||||
|
_GA_OPEN='# >>> metodo:eol'
|
||||||
|
_GA_CLOSE='# <<< metodo:eol'
|
||||||
|
|
||||||
|
_ga_block() { # el bloque COMPLETO (marcadores incluidos) por stdout
|
||||||
|
cat <<'GAB'
|
||||||
|
# >>> metodo:eol
|
||||||
|
# Gestionado por `metodo init/update` — NO editar a mano (se re-estampa).
|
||||||
|
# ACOTADO a los dos globs que el linter recorre: los `*.md` de RAÍZ y `doc/*.md` (glob de shell,
|
||||||
|
# sólo hijos directos). Es HIGIENE, no una avería: medido el 2026-08-23 en hermes-hub con dos
|
||||||
|
# worktrees a la misma profundidad —uno con 14 ficheros en CRLF y otro con 0—, `metodo check`
|
||||||
|
# da EXACTAMENTE la misma salida. Se fija el EOL para que el árbol no dependa de cómo se hizo
|
||||||
|
# cada checkout, no porque el linter se rompa.
|
||||||
|
# ⛔ Nunca `* text=auto` aquí: hay repos con binarios en LFS y con PDF versionados — ESO sí es
|
||||||
|
# destructivo y está medido.
|
||||||
|
/*.md text eol=lf
|
||||||
|
doc/*.md text eol=lf
|
||||||
|
# <<< metodo:eol
|
||||||
|
GAB
|
||||||
|
}
|
||||||
|
|
||||||
|
_stamp_gitattributes() { # $1 = repo destino
|
||||||
|
local ga="$1/.gitattributes" blk tmp a b
|
||||||
|
blk=$(mktemp); _ga_block > "$blk"; tmp=$(mktemp)
|
||||||
|
if [ ! -f "$ga" ]; then
|
||||||
|
cat "$blk" > "$ga"; rm -f "$blk" "$tmp"; echo " .gitattributes creado con el bloque eol (*.md de raíz · doc/*.md)"; return
|
||||||
|
fi
|
||||||
|
a=$(grep -nxF "$_GA_OPEN" "$ga" | head -1 | cut -d: -f1)
|
||||||
|
b=$(grep -nxF "$_GA_CLOSE" "$ga" | head -1 | cut -d: -f1)
|
||||||
|
if [ -n "$a" ] && [ -n "$b" ] && [ "$b" -ge "$a" ]; then
|
||||||
|
# ⛔ Se sustituye SÓLO el bloque, y con `head`/`tail`, NO con `awk`/`sed`. Medido el
|
||||||
|
# 2026-08-23 en Git Bash: **awk y sed abren en modo texto y se comen el `\r`** ⇒ reescribir el
|
||||||
|
# fichero entero con ellos NORMALIZA en silencio los bytes de un fichero que no es nuestro
|
||||||
|
# (`hermes-hub`, `kubernetes` y `mcp-edge` tienen su `.gitattributes` en CRLF o mixto).
|
||||||
|
# `head`/`tail` cortan por línea sin tocar los bytes que no atraviesan.
|
||||||
|
{ head -n $((a-1)) "$ga"; cat "$blk"; tail -n +$((b+1)) "$ga"; } > "$tmp" && mv "$tmp" "$ga"
|
||||||
|
rm -f "$blk"; echo " .gitattributes: bloque eol re-estampado (sólo el bloque; el resto, byte a byte)"; return
|
||||||
|
fi
|
||||||
|
# Existe y no lo lleva: se AÑADE AL FINAL. En gitattributes gana la última regla que casa, así
|
||||||
|
# que el bloque no puede quedar tapado por lo que el repo ya declarara para `.md`.
|
||||||
|
{ [ -s "$ga" ] && printf '\n'; cat "$blk"; } >> "$ga"
|
||||||
|
rm -f "$blk" "$tmp"; echo " .gitattributes: bloque eol añadido al final (lo de antes, intacto)"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ⚠️ Los dos pathspec llevan `:(glob)` a propósito: sin él, el `*` de git cruza `/` y `doc/*.md`
|
||||||
|
# se tragaría `doc/img/README.md`, que el linter NO lee. La verificación tiene que mirar el
|
||||||
|
# MISMO conjunto que declara el bloque — si mira otro, es un gate sin sujeto.
|
||||||
|
_GA_SUJETOS=":(glob)*.md :(glob)doc/*.md"
|
||||||
|
_ga_verifica() { # $1 = repo destino — «declarar NO es refrescar»: se MIDE el worktree
|
||||||
|
local tgt="$1" crlf
|
||||||
|
git -C "$tgt" rev-parse --git-dir >/dev/null 2>&1 || return 0
|
||||||
|
crlf=$(git -C "$tgt" ls-files --eol -- $_GA_SUJETOS 2>/dev/null | awk '$2=="w/crlf"' | wc -l)
|
||||||
|
if [ "${crlf:-0}" -gt 0 ]; then
|
||||||
|
echo " ⚠ .gitattributes declarado pero el worktree NO está refrescado: ${crlf} fichero(s) en CRLF."
|
||||||
|
echo " ⇒ git -C $tgt add --renormalize -- $_GA_SUJETOS (y commitea)"
|
||||||
|
echo " Sin esto el linter sigue midiendo el CHECKOUT y no el repo."
|
||||||
|
else
|
||||||
|
echo " eol verificado: *.md de raíz y doc/*.md en LF en el worktree (git ls-files --eol)"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
# ── el PUNTERO de enrutado (bloque gestionado en CLAUDE.md) ──────────────────
|
# ── el PUNTERO de enrutado (bloque gestionado en CLAUDE.md) ──────────────────
|
||||||
# Por qué en CLAUDE.md y sólo ahí: es el ÚNICO fichero que el harness carga solo en toda sesión
|
# Por qué en CLAUDE.md y sólo ahí: es el ÚNICO fichero que el harness carga solo en toda sesión
|
||||||
# sobre el repo. Un puntero en cualquier otro sitio reproduce la enfermedad que viene a curar
|
# sobre el repo. Un puntero en cualquier otro sitio reproduce la enfermedad que viene a curar
|
||||||
@ -550,6 +723,8 @@ Etiquetas: [NUEVA-REGLA] · [REFINA Cn] · [Cn-NO-ENCAJA] · [FALSA]. Se cosecha
|
|||||||
---
|
---
|
||||||
EOF
|
EOF
|
||||||
_scaffold_docs "$tgt"
|
_scaffold_docs "$tgt"
|
||||||
|
_stamp_gitattributes "$tgt"
|
||||||
|
_ga_verifica "$tgt"
|
||||||
_stamp_pointer "$tgt"
|
_stamp_pointer "$tgt"
|
||||||
echo "metodo init: $tgt inicializado — .metodo/ (máster $mver) + doc/ de CUATRO capas (backlog · decisiones · AVISOS · bitácora)."
|
echo "metodo init: $tgt inicializado — .metodo/ (máster $mver) + doc/ de CUATRO capas (backlog · decisiones · AVISOS · bitácora)."
|
||||||
echo " siguiente: siembra doc/backlog.md con el trabajo abierto de hoy y corre 'metodo check .'"
|
echo " siguiente: siembra doc/backlog.md con el trabajo abierto de hoy y corre 'metodo check .'"
|
||||||
@ -571,6 +746,8 @@ cmd_update() {
|
|||||||
[ -n "$adopt" ] && echo "adopted_commit: $adopt"; } > "$md/VERSION"
|
[ -n "$adopt" ] && echo "adopted_commit: $adopt"; } > "$md/VERSION"
|
||||||
_write_checksums "$md" || echo " (aviso: sin sha256 → CHECKSUMS no escrito)"
|
_write_checksums "$md" || echo " (aviso: sin sha256 → CHECKSUMS no escrito)"
|
||||||
printf '* text eol=lf\n' > "$md/.gitattributes"
|
printf '* text eol=lf\n' > "$md/.gitattributes"
|
||||||
|
_stamp_gitattributes "$tgt"
|
||||||
|
_ga_verifica "$tgt"
|
||||||
_stamp_pointer "$tgt"
|
_stamp_pointer "$tgt"
|
||||||
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."
|
||||||
}
|
}
|
||||||
@ -591,6 +768,7 @@ cmd_check() {
|
|||||||
check_commits
|
check_commits
|
||||||
check_decisiones
|
check_decisiones
|
||||||
check_decisiones_en_backlog
|
check_decisiones_en_backlog
|
||||||
|
check_decisiones_en_prosa
|
||||||
check_pointer
|
check_pointer
|
||||||
hdr "resultado"
|
hdr "resultado"
|
||||||
local rc=0
|
local rc=0
|
||||||
|
|||||||
@ -85,16 +85,18 @@ en su sector**. Y es esto, dicho por él:
|
|||||||
|
|
||||||
⛔ **Regla operativa**: antes de escribir *«pero si te comprometen X…»*, pregúntate **contra qué lo
|
⛔ **Regla operativa**: antes de escribir *«pero si te comprometen X…»*, pregúntate **contra qué lo
|
||||||
comparas**. Si la alternativa real que Xavier tiene hoy es peor, la propuesta no mejora nada — solo
|
comparas**. Si la alternativa real que Xavier tiene hoy es peor, la propuesta no mejora nada — solo
|
||||||
añade dificultad, y eso lo prohíbe `D23`.
|
añade dificultad, y eso lo prohíbe `I11·D23` (de `hermes-hub`: «la vara de medir es el COSTE
|
||||||
|
PARA EL OPERADOR»).
|
||||||
|
|
||||||
|
|
||||||
⇒ ⛔ **Y el error que esto evita, cometido CUATRO veces el 2026-08-18: una decisión lleva ÁMBITO DE
|
⇒ ⛔ **Y el error que esto evita, cometido CUATRO veces el 2026-08-18: una decisión lleva ÁMBITO DE
|
||||||
AMENAZA, y leerla fuera de su ámbito la hace parecer mala.** *(Xavier, ordenando: «no estoy diciendo
|
AMENAZA, y leerla fuera de su ámbito la hace parecer mala.** *(Xavier, ordenando: «no estoy diciendo
|
||||||
que no valore la captura de un hub — lo pondremos en el backlog por detrás, con su apartado. Ahora
|
que no valore la captura de un hub — lo pondremos en el backlog por detrás, con su apartado. Ahora
|
||||||
estamos en el apartado de **“y si capturan un edge”**, y para eso hay una CRL y unos procedimientos
|
estamos en el apartado de **“y si capturan un edge”**, y para eso hay una CRL y unos procedimientos
|
||||||
que mis equipos de hoy **ni tienen**».)* La orquestadora evaluó `D25` —del apartado del **edge**—
|
que mis equipos de hoy **ni tienen**».)* La orquestadora evaluó `D25` —del **edge**, apartado
|
||||||
contra la captura de un **hub**, y la decisión salía mal cuatro veces seguidas. **No estaba mal: se
|
`E14`; ⚠️ **sigue sin entrada en su registro**, ver `A43` de `hermes-edge/doc/AVISOS.md`, así que
|
||||||
estaba midiendo con la vara de otra sección.**
|
esta cita no se puede calificar todavía— contra la captura de un **hub**, y la decisión salía mal
|
||||||
|
cuatro veces seguidas. **No estaba mal: se estaba midiendo con la vara de otra sección.**
|
||||||
⇒ **Regla**: antes de objetar, pregúntate **de qué apartado es la decisión**. Si tu objeción vive en
|
⇒ **Regla**: antes de objetar, pregúntate **de qué apartado es la decisión**. Si tu objeción vive en
|
||||||
otro, no es una objeción: es una **entrada para ese otro apartado** — y se escribe allí, no aquí.
|
otro, no es una objeción: es una **entrada para ese otro apartado** — y se escribe allí, no aquí.
|
||||||
⭐ Y el corolario que lo hace útil en vez de burocrático: **objetar sigue siendo bienvenido**. Lo que
|
⭐ Y el corolario que lo hace útil en vez de burocrático: **objetar sigue siendo bienvenido**. Lo que
|
||||||
@ -499,8 +501,9 @@ mismo valor da el nombre público **y** direcciona secretos, rutas o etiquetas,
|
|||||||
visible **re-direcciona lo invisible**, y en silencio. *(Cicatriz 2026-07-31, cazada antes de
|
visible **re-direcciona lo invisible**, y en silencio. *(Cicatriz 2026-07-31, cazada antes de
|
||||||
aplicar: `hubName` gobernaba también los **paths de Vault** — con `hermes.hub` el `trimSuffix "-hub"`
|
aplicar: `hubName` gobernaba también los **paths de Vault** — con `hermes.hub` el `trimSuffix "-hub"`
|
||||||
no recortaba nada y el hub habría ido a buscar su clave WireGuard y su **clave Rosenpass** —la que
|
no recortaba nada y el hub habría ido a buscar su clave WireGuard y su **clave Rosenpass** —la que
|
||||||
`D10` prohíbe regenerar— a rutas inexistentes. La sesión partió **identidad** de **nombre público**
|
`hermes-hub`·`D100` prohíbe regenerar; era `F13·D10` hasta que el 2026-08-22 se renumeró al
|
||||||
antes de tocar nada.)*
|
contador del hub, precisamente porque el id chocaba con el del edge— a rutas inexistentes. La
|
||||||
|
sesión partió **identidad** de **nombre público** antes de tocar nada.)*
|
||||||
⇒ Antes de renombrar, **escribe qué se deriva de ese valor**. Lo que dice quién eres y lo que dice
|
⇒ Antes de renombrar, **escribe qué se deriva de ese valor**. Lo que dice quién eres y lo que dice
|
||||||
dónde están tus cosas tienen que ser campos distintos, aunque hoy coincidan. Y donde el derivado
|
dónde están tus cosas tienen que ser campos distintos, aunque hoy coincidan. Y donde el derivado
|
||||||
tenga formato obligado (una etiqueta de kernel, un path), **que la plantilla falle al renderizar** —
|
tenga formato obligado (una etiqueta de kernel, un path), **que la plantilla falle al renderizar** —
|
||||||
@ -634,8 +637,9 @@ la suite sale verde sobre un cableado roto. Dos veces en la misma semana (2026-0
|
|||||||
- `GET /links` —el endpoint del panel— llamaba a `LNK.status` con un `cfg` **declarado y sin
|
- `GET /links` —el endpoint del panel— llamaba a `LNK.status` con un `cfg` **declarado y sin
|
||||||
asignar**, así que el peldaño de identidad llegaba **vacío**. Los tests pasaban **porque le pasan
|
asignar**, así que el peldaño de identidad llegaba **vacío**. Los tests pasaban **porque le pasan
|
||||||
`cfg` a mano**.
|
`cfg` a mano**.
|
||||||
- Un mutante que derivaba el sufijo de una LAN del dominio del router —la invención que `D8`
|
- Un mutante que derivaba el sufijo de una LAN del dominio del router —la invención que `F11·D8`
|
||||||
prohíbe— **no rompió ni una aserción**, porque los tests de `D8` **no pasaban registro de router**.
|
de `hermes-edge` prohíbe— **no rompió ni una aserción**, porque sus tests **no pasaban registro
|
||||||
|
de router**.
|
||||||
⇒ Pregunta por cada test que pasa: **¿de dónde sale ese argumento en producción?** Si lo fabrica el
|
⇒ Pregunta por cada test que pasa: **¿de dónde sale ese argumento en producción?** Si lo fabrica el
|
||||||
test, ahí no hay cobertura — hay una simulación de que la hay. El testigo tiene que **entrar por
|
test, ahí no hay cobertura — hay una simulación de que la hay. El testigo tiene que **entrar por
|
||||||
donde entra el usuario**.
|
donde entra el usuario**.
|
||||||
@ -998,11 +1002,11 @@ servicio funciona: dice que alguna de ellas funciona.**
|
|||||||
|
|
||||||
⛔ **Y su hermano, que es el que nadie busca: la ABUNDANCIA de recursos esconde el derroche.** Medir
|
⛔ **Y su hermano, que es el que nadie busca: la ABUNDANCIA de recursos esconde el derroche.** Medir
|
||||||
siempre en el aparato más holgado no certifica nada del más apretado — y el defecto no está latente,
|
siempre en el aparato más holgado no certifica nada del más apretado — y el defecto no está latente,
|
||||||
está **ocurriendo**, solo que sobra sitio para pagarlo. *(Cicatriz `P12`, 2026-08-02: con `D10` un
|
está **ocurriendo**, solo que sobra sitio para pagarlo. *(Cicatriz `P12`, 2026-08-02: con `F13·D10`
|
||||||
edge **sin binario de Rosenpass** seguía bajándose la pubkey del hub —**524.160 B**— en el bucle de
|
—la del **edge**, «PQ siempre que se pueda»— un edge **sin binario de Rosenpass** seguía bajándose
|
||||||
20 s **y por cada hub**. En un Brume 2 (6,8 GB de overlay) no se nota **jamás**; en un GL-AR300M eran
|
la pubkey del hub —**524.160 B**— en el bucle de 20 s **y por cada hub**. En un Brume 2 (6,8 GB de
|
||||||
**1 MB sobre 212 KB libres**. Se descubrió porque el aparato pequeño lo hizo visible, no porque
|
overlay) no se nota **jamás**; en un GL-AR300M eran **1 MB sobre 212 KB libres**. Se descubrió
|
||||||
alguien lo buscara.)*
|
porque el aparato pequeño lo hizo visible, no porque alguien lo buscara.)*
|
||||||
⇒ Pregunta cuando una medida salga limpia: **¿en qué aparato la he tomado, y qué le sobraba?** Disco,
|
⇒ Pregunta cuando una medida salga limpia: **¿en qué aparato la he tomado, y qué le sobraba?** Disco,
|
||||||
RAM, CPU y ancho de banda son todos amortiguadores que convierten un fallo en una estadística que
|
RAM, CPU y ancho de banda son todos amortiguadores que convierten un fallo en una estadística que
|
||||||
nadie mira. La flota real se parece al más pobre, no al banco.
|
nadie mira. La flota real se parece al más pobre, no al banco.
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user