From 5d16b55e1416ee7a10dee056c855086a3d023de7 Mon Sep 17 00:00:00 2001
From: Sergio
Date: Thu, 17 Sep 2026 21:00:40 +0000
Subject: [PATCH] =?UTF-8?q?el=20visor=20del=20grafo=20reventaba=20con=20un?=
=?UTF-8?q?=20estado=20que=20no=20conoc=C3=ADa?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
`build-state-view.py` traía los cuatro estados del corpus cableados (sealed/debt/never/unhashable) y
contaba TODOS los nodos contra ese diccionario. `build-state.py` emite dos más —`wanted` (hueco
declarado en targets.toml, sin receta) y `ajeno` (imagen de qorpa, que no se construye desde
fuente)—, así que el visor moría con `KeyError: 'ajeno'` y el tablero HTML llevaba sin poder
generarse. O sea: agregar un estado nuevo rompía el tablero entero, en silencio para quien no lo
corriera.
Ahora los de fuera del corpus se cuentan aparte y se NOMBRAN en la leyenda —no se cuelan a la barra,
que es sobre `totals["recipes"]` y pasaría del 100 %—, y cualquier estado que aparezca mañana cae en
esa misma rama en vez de tumbar el visor.
De paso, el grafo regenerado: 930 selladas, 2 en deuda, 5 nunca, 3 ajenas; git ya figura sellado en
su hash nuevo (b3:215742cb…) y no arrastró a nadie, como decía el radio.
Co-Authored-By: Claude Opus 5 (1M context)
---
docs/state/build-state.html | 156 +++++++++++-------------------------
docs/state/build-state.json | 49 +++++------
scripts/build-state-view.py | 17 +++-
3 files changed, 90 insertions(+), 132 deletions(-)
diff --git a/docs/state/build-state.html b/docs/state/build-state.html
index a0f39943..ce7f8206 100644
--- a/docs/state/build-state.html
+++ b/docs/state/build-state.html
@@ -102,6 +102,7 @@ td{padding:10px 14px;border-bottom:1px solid var(--line);vertical-align:top}
.chip.s-debt{background:var(--debt-bg);color:var(--debt);border-color:var(--debt)}
.chip.s-never{background:var(--never-bg);color:var(--never);border-color:var(--never)}
.chip.s-unhashable{background:var(--unhashable-bg);color:var(--unhashable);border-color:var(--unhashable)}
+.chip.s-wanted,.chip.s-ajeno{background:var(--panel);color:var(--ink-2);border-color:var(--line)}
.chip.empty{color:var(--ink-2);font-style:italic}
.hint{color:var(--ink-2);font-size:.82rem;margin:0 0 14px}
.count{color:var(--ink-2);font-size:.82rem;margin-left:auto;font-family:ui-monospace,monospace}
@@ -113,31 +114,32 @@ footer .mono{color:var(--ink)}
estado del build · hammer
- 768 recetas · grafo cierra sin ciclos · grafo cerrado · 2026-07-22 21:43 UTC
+ 937 recetas · grafo cierra sin ciclos · grafo cerrado · 2026-09-17 21:00 UTC
avance del corpus
-
+
- 752 sellado al día
- 14 deuda de rebuild
- 2 nunca construida
+ 933 sellado al día
+ 1 deuda de rebuild
+ 3 nunca construida
+ 3 imagen ajena (qorpa) (fuera del corpus)
-
752
+
933
sellado al día
-
97.9%
+
99.6%
-
14
+
1
deuda de rebuild
-
1.8%
+
0.1%
-
2
+
3
nunca construida
0.3%
@@ -151,34 +153,34 @@ footer .mono{color:var(--ink)}
dónde está la deuda
+
+
+
+
@@ -188,96 +190,36 @@ footer .mono{color:var(--ink)}
lista tiene todas sus deps al día ⇒ se puede construir ya;
el pastilla ↑N es cuántas otras en deuda desbloquea (ordenadas por
ahí: construí primero las de más impacto). Una espera N depende
- de N recetas que también están en deuda. 8 listas ahora.
+ de N recetas que también están en deuda. 3 listas ahora.
- todas Rust (1) C (3) GUI (12)
+ todas C (2) Rust (1) kernel (1)
sólo listas
- 16 en deuda
+ 4 en deuda
receta clase estado deps de build
-
- gtk4 4.18.6
- GUI
- lista ↑6
- meson samurai python3 pkgconf glib cairo pango gdk-pixbuf graphene libepoxy wayland wayland-protocols libxkbcommon libdrm fontconfig harfbuzz fribidi libpng pixman freetype expat libffi pcre2 zlib libjpeg-turbo libtiff mesa
-
- fcft 3.3.3
- GUI
+
+ linux-firmware 20260910
+ kernel
lista ↑1
- tllist utf8proc freetype fontconfig harfbuzz pixman libpng zlib expat meson samurai python3 pkgconf linux-headers
-
- libinput 1.27.1
- GUI
- lista ↑1
- meson samurai python3 pkgconf libudev-zero libevdev mtdev
-
- dwarves 1.30
+ busybox
+
+ zsh 5.9
C
lista
- busybox make cmake elfutils zlib
-
- llimphi-counter 0.1.0
- C
- lista
- sin deps de build
-
- mesa-llvmpipe 24.0.9
- GUI
- lista
- llvm18 meson samurai python3 pkgconf flex bison mako markupsafe packaging libdrm wayland wayland-protocols expat zlib zstd libffi
-
- mesa-swrast 24.0.9
- GUI
- lista
- meson samurai python3 pkgconf flex bison mako markupsafe packaging libdrm wayland wayland-protocols expat zlib zstd libffi
-
- mirada-greeter 0.0.1
+ binutils libcap linux-headers make ncurses pcre2
+
+ rust 1.97.0
Rust
lista
- mesa wayland wayland-protocols libdrm expat zlib zstd libffi pkgconf linux-pam
-
- libadwaita 1.7.6
- GUI
- espera 1
- meson samurai python3 pkgconf sassc appstream libyaml curl openssl libxmlb libxml2 zstd gtk4 pango gdk-pixbuf cairo graphene glib harfbuzz fribidi fontconfig freetype pixman libpng expat libjpeg-turbo libtiff libepoxy wayland wayland-protocols libxkbcommon libdrm pcre2 libffi zlib mesa
-
- gtksourceview 5.16.0
- GUI
- espera 1
- meson samurai python3 pkgconf gettext-tiny gtk4 pango gdk-pixbuf cairo graphene glib harfbuzz fribidi fontconfig freetype pixman libpng expat libxml2 libjpeg-turbo libtiff libepoxy wayland wayland-protocols libxkbcommon libdrm pcre2 libffi zlib mesa
-
- foot 1.27.0
- GUI
- espera 1
- fcft tllist utf8proc fontconfig freetype harfbuzz libxkbcommon ncurses pixman wayland wayland-protocols libffi libpng zlib expat meson samurai python3 pkgconf linux-headers
-
- gtk4-hello 4.18.6
- GUI
- espera 1
- pkgconf gtk4 pango gdk-pixbuf cairo graphene glib harfbuzz fribidi fontconfig freetype pixman libpng expat libjpeg-turbo libtiff libepoxy wayland libxkbcommon libdrm pcre2 libffi zlib mesa
-
- mirada-compositor 0.0.1
- GUI
- espera 1
- mesa wayland wayland-protocols libdrm seatd linux-pam libinput libudev-zero libevdev mtdev libxkbcommon pixman expat zlib zstd libffi pkgconf
-
- adwaita-hello 1.7.6
- GUI
- espera 2
- pkgconf libadwaita appstream libyaml curl openssl libxmlb libxml2 zstd gtk4 pango gdk-pixbuf cairo graphene glib harfbuzz fribidi fontconfig freetype pixman libpng expat libjpeg-turbo libtiff libepoxy wayland libxkbcommon libdrm pcre2 libffi zlib mesa
-
- hammer-edit 1.0.0
+ cmake curl llvm21 openssl-threads pkgconf python3 samurai
+
+ firmware-tigerlake 20260910
C
- espera 3
- pkgconf gtksourceview libadwaita appstream libyaml curl openssl libxmlb libxml2 zstd gtk4 pango gdk-pixbuf cairo graphene glib harfbuzz fribidi fontconfig freetype pixman libpng expat libjpeg-turbo libtiff libepoxy wayland libxkbcommon libdrm pcre2 libffi zlib mesa
-
- sourceview-hello 5.16.0
- GUI
- espera 3
- pkgconf gtksourceview libadwaita appstream libyaml curl openssl libxmlb libxml2 zstd gtk4 pango gdk-pixbuf cairo graphene glib harfbuzz fribidi fontconfig freetype pixman libpng expat libjpeg-turbo libtiff libepoxy wayland libxkbcommon libdrm pcre2 libffi zlib mesa
+ espera 1
+ busybox linux-firmware sof-firmware
diff --git a/docs/state/build-state.json b/docs/state/build-state.json
index 0db46d16..b2318d22 100644
--- a/docs/state/build-state.json
+++ b/docs/state/build-state.json
@@ -3,10 +3,10 @@
"totals": {
"recipes": 937,
"nodes": 940,
- "sealed": 933,
- "never": 3,
- "ajeno": 3,
- "debt": 1
+ "sealed": 930,
+ "never": 5,
+ "debt": 2,
+ "ajeno": 3
},
"by_class": {
"ajeno": 3,
@@ -17,16 +17,16 @@
"rust": 236
},
"debt_by_class": {
- "c": 2,
- "kernel": 1,
+ "c": 4,
+ "kernel": 2,
"rust": 1
},
"by_queue": {
"corpus": {
- "sealed": 933,
- "never": 3,
- "ajeno": 3,
- "debt": 1
+ "sealed": 930,
+ "never": 5,
+ "debt": 2,
+ "ajeno": 3
}
},
"by_profile": {
@@ -49,8 +49,8 @@
"metal-tigerlake": {
"raices": 2,
"clausura": 6,
- "sealed": 4,
- "never": 2
+ "sealed": 2,
+ "never": 4
},
"servidor": {
"raices": 120,
@@ -1147,7 +1147,7 @@
"hash": "b3:8cd3ec35022757fcd099e1a72d9fb30a3d05a54197f81b0fef6af87a6e7a0686",
"state": "sealed",
"blocked_by": [],
- "unblocks": 0,
+ "unblocks": 1,
"perfiles": [
"base",
"cli",
@@ -1444,7 +1444,7 @@
"hash": "b3:2a2b1280c57affe906ce43ba20fd3867dda18b9ed4476ef64285baf018c4a5fd",
"state": "sealed",
"blocked_by": [],
- "unblocks": 2,
+ "unblocks": 4,
"perfiles": [
"cli",
"escritorio-cosmic",
@@ -4294,7 +4294,7 @@
"hash": "b3:552bc65053e3fc2fc42a02cac4e76ae1eac706e3c225cf09a05f9733bb75103f",
"state": "sealed",
"blocked_by": [],
- "unblocks": 0,
+ "unblocks": 1,
"perfiles": [],
"dependientes_total": 5
},
@@ -4996,7 +4996,8 @@
"hash": "b3:0aa44a4736b54be472be3a9fa4f1ab00f3009944a6233dfd8f6f0f6d833e0479",
"state": "never",
"blocked_by": [
- "linux-firmware"
+ "linux-firmware",
+ "sof-firmware"
],
"unblocks": 0,
"perfiles": [
@@ -5016,7 +5017,7 @@
"hash": "b3:6b25e3518cb8036738f0b63d04e64b9da93094e4757b74f7559ccc8bd53a1fee",
"state": "sealed",
"blocked_by": [],
- "unblocks": 0,
+ "unblocks": 1,
"perfiles": [
"base",
"cli",
@@ -5725,7 +5726,7 @@
"cls": "c",
"queue": "corpus",
"foreign": false,
- "hash": "b3:51aa5e137fc764d063e898ce847f77c8f34ed5a253042de8732148d487d9d137",
+ "hash": "b3:215742cb11adb747de7655346a3982e5d5a140539cb95c69df290dfc430ea8ef",
"state": "sealed",
"blocked_by": [],
"unblocks": 0,
@@ -8239,7 +8240,7 @@
"queue": "corpus",
"foreign": false,
"hash": "b3:24cfc64333220544d577eb20ce66122d0bf0e95a7116eec2d5c71065e1c0ed0b",
- "state": "sealed",
+ "state": "never",
"blocked_by": [],
"unblocks": 0,
"perfiles": [
@@ -11019,7 +11020,7 @@
"queue": "corpus",
"foreign": false,
"hash": "b3:63fdd57ca3557bf9e6490bc00677f6cc0af2c014f026babfb41645951fcf0287",
- "state": "sealed",
+ "state": "debt",
"blocked_by": [],
"unblocks": 0,
"perfiles": [],
@@ -11447,7 +11448,7 @@
"hash": "b3:2ff37f0516b091d1c67099aa5df817cfbe2891d5da9c263eb47c5ef87fe99814",
"state": "sealed",
"blocked_by": [],
- "unblocks": 0,
+ "unblocks": 1,
"perfiles": [
"base",
"cli",
@@ -11507,7 +11508,7 @@
"hash": "b3:57d38057b82cef4e871d68a3324fd485b298df81a766a5dcf8269e6fb63efe16",
"state": "sealed",
"blocked_by": [],
- "unblocks": 1,
+ "unblocks": 2,
"perfiles": [
"base",
"cli",
@@ -13407,7 +13408,7 @@
"hash": "b3:4b1f2457160137530bee89b9fbcc250bf43deb15c428a5ec06a01ac3114b27bc",
"state": "sealed",
"blocked_by": [],
- "unblocks": 0,
+ "unblocks": 1,
"perfiles": [
"base",
"cli",
@@ -16000,7 +16001,7 @@
"queue": "corpus",
"foreign": false,
"hash": "b3:a85c2a254dcb20a6ffce76b8ef1300739b5b6adab6bc34dbb999f743c1e36a55",
- "state": "sealed",
+ "state": "never",
"blocked_by": [],
"unblocks": 1,
"perfiles": [
diff --git a/scripts/build-state-view.py b/scripts/build-state-view.py
index 2d837608..970a7f5d 100755
--- a/scripts/build-state-view.py
+++ b/scripts/build-state-view.py
@@ -22,9 +22,17 @@ OUT = ROOT / ("docs/state/build-state-kde.html" if KDE else "docs/state/build-st
doc = json.loads(DATA.read_text())
nodes = doc["nodes"]
+# Los estados que SÍ son del corpus de recetas: son los que entran a la barra y a los tiles, y su
+# suma es `totals["recipes"]`.
STATE_ORDER = ["sealed", "debt", "never", "unhashable"]
STATE_ES = {"sealed": "sellado al día", "debt": "deuda de rebuild",
"never": "nunca construida", "unhashable": "ilegible"}
+# Y los que NO lo son: `wanted` es un hueco declarado en targets.toml (no hay receta todavía) y
+# `ajeno` es una imagen de qorpa (ADR 0015), que no se construye desde fuente. `build-state.py` los
+# excluye de `totals["recipes"]` a propósito, así que meterlos en la barra la haría pasar del 100 %.
+# Antes ni siquiera se los nombraba: el visor reventaba con KeyError al toparse con uno, o sea que
+# **agregar un estado nuevo rompía el tablero entero**. Ahora se cuentan aparte y se muestran.
+STATE_FUERA = {"wanted": "querida (sin receta aún)", "ajeno": "imagen ajena (qorpa)"}
CLASS_ES = {"c": "C", "go": "Go", "rust": "Rust", "gui": "GUI", "kernel": "kernel"}
# blocked_by / unblocks los computa build-state.py sobre el grafo; acá sólo los leemos.
@@ -47,10 +55,15 @@ n_total = totals["recipes"]
# Reparto por clase (para las barras por-clase).
classes = {}
+fuera = {}
for n, r in nodes.items():
+ st = r["state"]
+ if st not in STATE_ORDER: # wanted / ajeno / cualquiera que aparezca mañana
+ fuera[st] = fuera.get(st, 0) + 1
+ continue
c = r.get("cls", "c")
classes.setdefault(c, {s: 0 for s in STATE_ORDER})
- classes[c][r["state"]] += 1
+ classes[c][st] += 1
def pct(x): return f"{100*x/n_total:.1f}%"
@@ -222,6 +235,7 @@ td{padding:10px 14px;border-bottom:1px solid var(--line);vertical-align:top}
.chip.s-debt{background:var(--debt-bg);color:var(--debt);border-color:var(--debt)}
.chip.s-never{background:var(--never-bg);color:var(--never);border-color:var(--never)}
.chip.s-unhashable{background:var(--unhashable-bg);color:var(--unhashable);border-color:var(--unhashable)}
+.chip.s-wanted,.chip.s-ajeno{background:var(--panel);color:var(--ink-2);border-color:var(--line)}
.chip.empty{color:var(--ink-2);font-style:italic}
.hint{color:var(--ink-2);font-size:.82rem;margin:0 0 14px}
.count{color:var(--ink-2);font-size:.82rem;margin-left:auto;font-family:ui-monospace,monospace}
@@ -281,6 +295,7 @@ HTML = f'''
{totals.get('sealed',0)} sellado al día
{totals.get('debt',0)} deuda de rebuild
{totals.get('never',0)} nunca construida
+ {''.join(f'{v} {E(STATE_FUERA.get(k, k))} (fuera del corpus) ' for k, v in sorted(fuera.items()))}
{''+str(totals.get('unhashable',0))+' ilegible ' if totals.get('unhashable') else ''}