drenaje: medía 5 de 7 imágenes y las otras 2 desaparecían en silencio

targets.toml declara 7 perfiles; drenaje.json listaba 5. escritorio-cosmic (cola
incoming-cosmic) y escritorio-sway (cola incoming-wlr) declaraban una cola que
ningún grafo de GRAFOS contenía, así que cargar() devolvía None y --todos hacía
`continue` pelado. Dos imágenes enteras fuera del artefacto sin dejar rastro, y
los dos números —5 medidos, 7 declarados— no se cruzaban en ningún lado.

Mismo olvido que ya costó 17 días de build-state-wlr.json congelado: la lista de
grafos crece a mano y se queda atrás cuando se abre una cola.

Tres cambios:
- GRAFOS suma los grafos de cosmic y wlr.
- Un perfil sin medir se anota en el artefacto (`sin_medir`), se grita por stdout
  y drenar.py sale 1. Regla 3 del repo: un ausente falla ruidosamente.
- cosecha-cron deja de tragarse la salida; filtra las líneas ⚠ al log, que si no
  llegaban como un "falló" mudo que no dice cuál imagen falta.

Medido: las 2 imágenes que nadie miraba estaban limpias, 0 en deuda. Ahora son
7/7 verificadas en vez de 5 verificadas y 2 supuestas.
This commit is contained in:
Sergio
2026-09-04 14:26:04 +00:00
parent e8ca740119
commit 28d98dc5f9
3 changed files with 51 additions and 3 deletions
+20 -1
View File
@@ -20,6 +20,15 @@
"construibles_ya": [],
"olas": []
},
"escritorio-cosmic": {
"grafo": "docs/state/build-state-cosmic.json",
"nodos": 134,
"en_deuda": 0,
"ondas": 0,
"profundidad": 0,
"construibles_ya": [],
"olas": []
},
"escritorio-gnome": {
"grafo": "docs/state/build-state-gnome.json",
"nodos": 158,
@@ -46,6 +55,16 @@
"profundidad": 0,
"construibles_ya": [],
"olas": []
},
"escritorio-sway": {
"grafo": "docs/state/build-state-wlr.json",
"nodos": 174,
"en_deuda": 0,
"ondas": 0,
"profundidad": 0,
"construibles_ya": [],
"olas": []
}
}
},
"sin_medir": []
}
+22 -1
View File
@@ -28,8 +28,15 @@ import json, sys
from pathlib import Path
ROOT = Path(__file__).resolve().parent.parent
# UNA LÍNEA POR GRAFO, Y SE OLVIDAN (2026-09-04). Esta lista nació con corpus+kde+gnome y se quedó
# ahí mientras se abrían dos escritorios más: `escritorio-cosmic` (cola `incoming-cosmic`) y
# `escritorio-sway` (cola `incoming-wlr`) declaraban una cola que ningún grafo de la lista contenía,
# así que `cargar()` devolvía None y `--todos` los saltaba EN SILENCIO — 2 de las 7 imágenes fuera
# del drenaje sin que nada lo dijera. Es el mismo olvido que ya costó 17 días de
# build-state-wlr.json congelado (ver cosecha-cron.sh). Al abrir una cola nueva, se agrega ACÁ.
GRAFOS = ["docs/state/build-state.json", "docs/state/build-state-kde.json",
"docs/state/build-state-gnome.json"]
"docs/state/build-state-gnome.json", "docs/state/build-state-cosmic.json",
"docs/state/build-state-wlr.json"]
SEMILLA = ROOT / "docs/state/seed-edges.json"
EN_DEUDA = ("debt", "never", "unhashable", "wanted")
@@ -109,9 +116,18 @@ def todos_los_perfiles():
doc = {"schema": "hammer-drenaje/1",
"nota": "DERIVADO del grafo de estado por scripts/drenar.py — no editar a mano.",
"perfiles": {}}
sin_medir = []
for p in sorted(targets_mod.load()):
ondas, deuda, ambito, cual = ondas_de(p)
# UN PERFIL QUE NO SE PUEDE MEDIR NO SE SALTA EN SILENCIO. Antes esto era un `continue` pelado
# y por eso dos imágenes enteras faltaban del artefacto sin dejar rastro: el JSON listaba 5
# perfiles, targets.toml declaraba 7, y los dos números no se cruzaban en ningún lado. Ahora
# queda escrito EN el artefacto (`sin_medir`) y gritado por stdout — regla 3 del repo: un
# ausente falla ruidosamente, un vacío llega hasta el final diciendo que todo fue bien.
if ondas is None:
sin_medir.append(p)
print(f"{p:20} SIN MEDIR: ningún grafo de GRAFOS contiene su cola "
f"(¿falta build-state.py --<cola> o la línea en GRAFOS?)")
continue
doc["perfiles"][p] = dict(
grafo=cual, nodos=len(ambito), en_deuda=len(deuda), ondas=len(ondas),
@@ -119,9 +135,14 @@ def todos_los_perfiles():
olas=[{"n": i + 1, "recetas": o} for i, o in enumerate(ondas)])
print(f" {p:20} {len(deuda):3} en deuda · {len(ondas):2} ondas · "
f"onda 1 = {len(ondas[0]) if ondas else 0}")
doc["sin_medir"] = sin_medir
salida = ROOT / "docs/state/drenaje.json"
salida.write_text(json.dumps(doc, indent=1, ensure_ascii=False) + "\n")
print(f"{salida.relative_to(ROOT)}")
if sin_medir:
print(f"{len(sin_medir)} de {len(targets_mod.load())} imágenes SIN MEDIR: "
f"{' '.join(sin_medir)}")
return 1
return 0
+9 -1
View File
@@ -202,7 +202,15 @@ if [ -x "$HAMMER" ]; then
# Cola DERIVADA del grafo (P4): el orden de masticado por imagen, en ondas topológicas. No lanza
# ningún build — sólo deja escrito qué conviene moler primero, para que la cola deje de ser una
# lista escrita a mano. Barato (lee JSON, no hashea).
scripts/drenar.py --todos >/dev/null 2>&1 && echo " drenaje.json ✓" || echo " ⚠ drenar.py falló"
# NO se traga la salida entera: drenar.py sale 1 cuando alguna imagen quedó SIN MEDIR (una cola
# nueva sin su línea en GRAFOS), y con `>/dev/null 2>&1` eso llegaba al log como un "falló" mudo
# que no dice cuál. Se filtran las líneas ⚠, que son las únicas accionables.
if drenaje_out="$(scripts/drenar.py --todos 2>&1)"; then
echo " drenaje.json ✓"
else
echo " ⚠ drenar.py falló"
echo "$drenaje_out" | grep '⚠' | sed 's/^/ /'
fi
# VIGÍA DE FUENTES (ADR 0013 §3). Desde que el mirror propio se consulta ANTES que upstream,
# `hammer build` deja de avisar cuando una URL de terceros muere: sirve los bytes del mirror y
# sigue. Eso es lo correcto para construir y sería CIEGO sin este contrapeso — las URLs se irían