`vigia-sonames.py` corría por defecto SÓLO sobre los cinco perfiles de escritorio
(`p.startswith("escritorio")`). O sea que `base`, `cli` y `servidor` —el objetivo de la mudanza—
**nunca se miraron**. Apuntándolo a ellos a mano:
== servidor 147 nodos · 183 sonames provistos · 1 sin proveedor
FALTA libffi.so.8 ← lo piden: python3
`python3` no arrancaba en las tres imágenes, por el mecanismo EXACTO que `musl-shared` y
`zlib-shared` arreglaron dos días antes: la receta canónica de libffi es `--disable-shared`, ningún
artefacto del cierre publica ese soname, y dentro del lab el agujero lo tapa el rootfs de Alpine —
así que el build pasa y la imagen sale rota. `libffi-shared` ya existía en el corpus y ya estaba
declarada en otros dos perfiles; sólo faltaba en `base`.
servidor 148 nodos · 186 sonames · **0 sin proveedor** (base y cli, igual)
## Y el vigía pasa a mirar TODOS los perfiles
⚠ **Es la tercera vez en dos días que un guardián de este repo mide menos de lo que su resumen
afirma**: `static-audit.sh` sólo globeaba `recipes/` y no las 5 colas (3 mentiras ocultas); el bloque
de raíces sucias sólo corría al hidratar un perfil y no veía las 649 recetas fuera de toda imagen
(qdrant con 69 M de basura); y éste dejaba fuera medio sistema. **Un «0 huecos» sobre la mitad del
sistema se imprime igual que uno sobre todo él.**
⇒ Al leer un guardián, leer su SCOPE antes que su veredicto: el glob, el bucle, de dónde saca la
lista. Los ocho perfiles dan 0 sin proveedor, así que ampliar el alcance no mete ruido — sólo deja de
esconder.
Tras devolver protobuf y abseil a `zig-cc`, qdrant cayó a deuda y se reconstruyó en el worker:
2 ficheros, sólo `usr/`, 70 M, `qdrant 1.19.1`. La limpieza del `/out/src` —el DESTDIR global que
heredaba el `make install` anidado de protobuf-src— aguanta el cambio de dep. REPRODUCE bit a bit.
El corpus queda en 907/907 sellado con deuda 0.
networkmanager b3:c36414ece23e322ef007d0acc7ce6f65b8b822ae55c38b38c9afa4b3eb340adb (52 MB)
Arreglo del segundo hueco del barrido: `networkmanager` figuraba SÓLO en escritorio-kde, y desde
GNOME, COSMIC o sway no se alcanza (cola hermana). Pero promover la receta de KDE tal cual habría
sido peor que no hacerlo, y sólo se vio mirando el ARTEFACTO:
· `-Dwifi=false` ⇒ un gestor de red que no maneja interfaces inalámbricas. Allá es correcto
(esa receta existe para dar libnm.so a plasma-nm y nada más); acá habría puesto en tres
imágenes un demonio que arranca, dibuja el applet y no lista una sola red.
· sin `nmcli` ⇒ ni una herramienta con la que manejarlo. En sway eso es la diferencia entre
tener red y no tenerla.
La variante del corpus cambia tres cosas, y la tercera hizo falta MEDIRLA:
1. `-Dwifi=true`. Habla nl80211 por libnl (ya era dep) y delega el handshake WPA2 en
`wpa_supplicant`, que desde hoy está en perfil.base ⇒ va también en [deps] runtime.
2. `readline` en [deps] build.
3. `-Dnmcli=true -Dreadline=libreadline`. Con sólo la dep, nmcli NO se construyó: `-Dnmcli` vale
true de fábrica pero `-Dreadline` es un COMBO que por defecto va en `auto`, y sin decirle
dónde mirar resolvió a «none» ⇒ meson apagó el CLI EN SILENCIO. Comprobado sobre el store.
Y `readline-shared` en runtime, cazado con provee.py sobre las NEEDED del binario: nmcli sale con
`NEEDED libreadline.so.8` y la readline canónica del corpus es sólo .a. La dep de BUILD y la de
RUNTIME son artefactos distintos — tercer caso del día tras cmus y bluez. No mueve el hash.
⚠ Se queda `-Dcrypto=null`, y es una limitación real escrita en la receta: sin cripto no valida
802.1X / WPA-Enterprise (el WiFi de una oficina). WPA2-PSK funciona porque ése lo hace el
supplicant. Encender nss o gnutls arrastra dos cadenas enormes: unidad de trabajo aparte.
── targets.toml ────────────────────────────────────────────────────────────────────────────────
escritorio-gnome, escritorio-cosmic, escritorio-sway += networkmanager (+ servicio)
escritorio-kde, escritorio-sway += wireplumber (+ servicio)
⚠ networkmanager NO se declara en escritorio-kde: allá plasma-nm ya arrastra la variante de la
cola, y dos NetworkManager distintos en la misma ruta es la enfermedad de las dos glib. Que la de
KDE vaya sin WiFi es deuda del frente KDE, y queda escrita donde toca.
Tres preguntas del usuario, contestadas midiendo, y dos de las mediciones CORRIGEN cosas que este
mismo fichero afirmaba.
1. CENSO: de ~50 apps muy usadas el catálogo tiene 9, y CINCO de las nueve son de KDE (o sea que
llegan a una de las cuatro imágenes).
2. ⚠ CORRECCIÓN al «tercer defecto del método». Este documento dice, con fecha 2026-09-03, que
ninguna cola publica libGL.so ni gl.pc. Dejó de ser cierto AL DÍA SIGUIENTE: recipes/libglvnd.toml
es del 2026-09-04 y `provee.py --desde corpus opengl` da ✓ (libOpenGL.so.0 + opengl.pc). Y la
corrección trae su propia corrección: la campaña quedó A MEDIAS. Las tres mesa siguen con
-Dglvnd=false, no hay libEGL_mesa.so.0 ni egl_vendor.d, y en el rootfs KDE hidratado conviven DOS
libEGL.so.1 distintos (mesa 1.440.624 B gana el symlink; el de glvnd, 323.144 B, queda huérfano).
OBS —la razón de escribir libglvnd— NO la usa en runtime: libobs-opengl.so sale con NEEDED
libEGL.so.1 y ni un gl[A-Z] indefinido, o sea que su glad resuelve por eglGetProcAddress.
⇒ el `opengl ✓` es verdad DE ENLACE. El muro pasó de «no enlaza» a «enlaza y no corre».
Corolario: darktable estaba MAL clasificada como caso de GL. Su UI es GTK3+cairo; su muro es la
cola de deps (lensfun, libgphoto2, openexr, imath, libraw, osm-gps-map, portmidi + cuatro que
sólo viven en colas). Blender sí es el caso de GL.
3. ELECTRON: `grep -rni electron docs/ recipes/` da CERO. Nunca estuvo planeado. Y no existe un
«Electron con base Firefox» porque Gecko no tiene API de embebido desde XULRunner (SDD 26 §1) —
pero eso es exactamente lo que es atuq, y ya está: artefacto derivado + chrome propio +
extensiones + host de native messaging en Rust. Falta un modo SSB, que es más barato que UN port.
GenOffice concretamente: Apache-2.0 (salvo ee/), acepta endpoints OpenAI-compatible locales ⇒ la
mitad de IA es una línea de config contra el llama-cpp que YA viaja en los cuatro escritorios. La
mitad de runtime es qorpa. ⚠ Y el muro real es el MODELO: Qwen2.5-1.5B no sostiene IA agéntica
sobre un .xlsx.
4. QUÉ REHACER, con criterio escrito: sólo cuando el bloqueo es estructural Y el valor vive en un
protocolo o formato abierto. Pasan tres: el shell de apps sobre atuq, una bóveda de contraseñas
(la mitad cara —la integración con el navegador— ya está construida), y un cliente Matrix si
fractal no construye. Thunderbird es el más desaprovechado de la lista de EMPAQUETAR: es Gecko.
Deja escrito lo que el barrido midió y, sobre todo, CÓMO se midió, para que el recuento se pueda
repetir en vez de re-derivar.
Lo que aporta que no estaba en ningún lado:
1. **La política «catálogo ≠ imagen».** El repo ya la aplicaba de hecho y no la había escrito, y sin
ella «620 hojas sin perfil» se lee como deuda. No lo es: 529 son volcado crudo del importador y
355 son herramientas Go de nube. Una receta sellada y no declarada es CATÁLOGO — se instala por
nombre. Se vuelve deuda sólo cuando lo que falta es una CAPACIDAD.
2. **El método en tres preguntas encadenadas**, y por qué el orden importa: ¿está en algún perfil?
→ ¿podría llegar por clausura ajena (`dependientes_total>0`)? → ¿fue curada alguna vez (la
cabecera «PUNTO DE PARTIDA» del importador)? Las hojas son el hueco; las librerías no.
3. **El triaje completo de las 91 hojas trabajadas a mano**, en seis clases que suman 91 exactas.
Incluye las que NO se declaran de oficio y por qué: `openrc` compite con arje-zero, `uutils` y
coreutils/grep/findutils compiten con los applets de busybox, `waterfox` es un segundo Gecko,
y valkey/opensmtpd/step-ca/qdrant definen QUÉ CLASE de servidor es el perfil `servidor`.
4. **Dos hallazgos que no eran el objetivo del barrido:**
- `networkmanager` existe SÓLO en incoming-kde ⇒ GNOME, COSMIC y sway no lo alcanzan. Con
wpa_supplicant la WiFi se destraba, pero se configura a mano y el indicador de red del
escritorio no tiene con qué hablar.
- `ia-modelo-embeddings` no está en ningún perfil: hay motor (llama-cpp) y hay chat
(ia-modelo-chat) en los cuatro escritorios, y NO hay búsqueda por significado. La mitad
semántica del §6.3 de atuq no viaja.
5. **Una trampa del instrumento**, que casi hace escribir mal las listas de servicios:
`scripts/targets.py <perfil>` imprime las RAÍCES, no la clausura. Cruzar los [[service]] contra
esa salida dejaba fuera a pipewire y colord en GNOME, que sí están en la imagen. La clausura la
da el campo `perfiles` de los build-state*.json.
── BARRIDO 1: las hojas selladas sin perfil ────────────────────────────────────────────────────
Método, para que se pueda repetir: cruzar el campo `perfiles` de los cinco build-state*.json con
`dependientes_total`. De 905 nodos, 631 sin perfil; de ésos, **620 son HOJAS** (nadie depende de
ellas, o sea que ninguna clausura las puede alcanzar) y 11 llegan por la clausura de otra.
Las 620 se parten en dos por una marca objetiva, la cabecera del importador:
· **529** dicen «PUNTO DE PARTIDA, no final» — volcado crudo de import-nix/import-alpine
(328 Go + 195 Rust + 6 C). Nadie las curó nunca para una imagen.
· **91** están trabajadas a mano. Ésas son las que se triaron una por una.
Lo que salió de ese triaje, y lo que se declara:
**`base` += `wpa_supplicant` — la imagen NO PODÍA ASOCIARSE A UN WiFi.** dhcpcd resuelve la IP de
un cable; el handshake WPA2 de 4 vías lo hace un supplicant en userspace y busybox no lo trae. La
receta existía desde el frente de metal —su cabecera dice «para asociar el WiFi del medio live al
AP»— y estaba en CERO perfiles. Es la figura de `foot` y esta vez el precio era quedarse sin red.
**`cli` += nano, tig, patch, socat, pigz, miller, dwarves.** El criterio va escrito en el fichero
porque meter las 620 habría sido peor que no mirar: entra lo que un usuario de esta capa ESPERA
encontrar y hoy no está. El resto queda en el catálogo, que NO es lo mismo que la imagen.
**`escritorio-sway` += wlr-randr**: no había con qué cambiar la resolución ni rotar una pantalla.
── BARRIDO 2: el «enable» ──────────────────────────────────────────────────────────────────────
De los cuatro escritorios **sólo GNOME tenía lista `servicios`**. Los otros tres salían con sus
demonios instalados y NINGUNO arrancado, y la métrica de clausura daba N/N igual — `paquetes` dice
qué se instala, `servicios` dice qué se levanta, y sin la segunda la imagen está a medias sin que
nada falle.
Escritas las tres que faltaban, computando la lista (no a ojo): se cruzaron los `[[service]]` de
las 11 recetas que los declaran contra el campo `perfiles` de los cinco grafos — la CLAUSURA, no
las raíces, porque la mitad de los demonios llegan como dep. Y GNOME sumó `cupsd`+`bluetoothd`,
que nacieron ayer.
⚠ El cruce destapó tres ausencias que NO se arreglan acá y quedan escritas en el fichero:
· KDE y sway tienen `pipewire` y **no tienen `wireplumber`**: sin gestor de sesión los nodos
existen y nadie los conecta.
· COSMIC **no tiene `upowerd`** y dibuja un indicador de batería.
· KDE y sway no tienen `logind-compat`.
Comprobado: tomllib parsea, y los ocho perfiles resuelven con scripts/targets.py.