tawasuyu

sergio/takana

> Una distribución Linux construida con un laboratorio funcional y hermético en el > sótano, y una terminal mutable, clásica y anárquica en el piso de arriba — diseñada > desde el suelo para que una IA programadora entienda, modifique y co…

TOML 1483Shell 181Rust 107Markdown 963619 Sutichaykuna

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.

28d98dc5f9f016b9dbe2894c0d45104dec43fecd · ruwaq Sergio · (1 killa ñawpaq) · tayta e8ca74011 · kay commitpi sach'ata qhaway

Semántico sayk'uy · 1

scripts/drenar.py

3 qillqakuna · +51 −3

diff --git a/docs/state/drenaje.json b/docs/state/drenaje.json
index 9426b856..f476c9a8 100644
--- a/docs/state/drenaje.json
+++ b/docs/state/drenaje.json
@@ -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": []
 }
diff --git a/scripts/drenar.py b/scripts/drenar.py
index b4a2eb9f..1385a5ba 100755
--- a/scripts/drenar.py
+++ b/scripts/drenar.py
@@ -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
 
 
diff --git a/scripts/farm/cosecha-cron.sh b/scripts/farm/cosecha-cron.sh
index c3b0f935..716d421a 100755
--- a/scripts/farm/cosecha-cron.sh
+++ b/scripts/farm/cosecha-cron.sh
@@ -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