mesa-llvmpipe b3:7662f5ec25c42cd679da1679c8c6ed7c53cd49d57fa781493ab7ff433d51b9b0
En vez de lanzar 153 rebuilds a ciegas, la campaña se prueba en la única de las tres mesa que tiene
**radio 0 y cero imágenes** (`yupana radio mesa-llvmpipe`: 0 dependientes, «(ninguna declarada)»).
Cambiarla no tira un solo sellado ajeno, así que es el laboratorio exacto.
LA PREGUNTA, que hasta hoy nadie tenía contestada: con `-Dglvnd=true`, ¿mesa produce de verdad el
VENDOR que al despacho le falta? RESPUESTA MEDIDA SOBRE EL ARTEFACTO:
usr/lib/libEGL_mesa.so.0 ← el vendor (hoy no existe en ningún lado)
usr/share/glvnd/egl_vendor.d/50_mesa.json ← su registro, que es lo que glvnd busca
usr/lib/libgbm.so.1 · libglapi.so.0 · dri/{swrast,kms_swrast}_dri.so
…y **deja de instalar libEGL.so.1 y libGLESv2.so.2** (los dos `ls` fallan).
⇒ La colisión de sonames del rootfs de KDE —dos libEGL.so.1 distintos en la misma ruta— DESAPARECE
POR CONSTRUCCIÓN con la campaña: mesa ya no reclama esas rutas y el dueño pasa a ser glvnd, que es
exactamente lo que su partición quiere. La campaña deja de ser una apuesta: se sabe qué produce.
Lo que queda por decidir es CUÁNDO pagar, no SI funciona.
EL PRECIO, medido antes de empezar y sin cambiar: `yupana radio mesa` = 148 directos, 154
transitivos, **153 sellados que caen a deuda**, las CINCO imágenes, 123 de ellos en incoming-kde —
la cola que otro agente está moliendo ahora mismo. Por eso esto es una prueba, no la campaña.
⚠ Y cubre SÓLO la mitad de mesa. La otra es que `libglvnd` vuelva a instalar su libEGL.so.1 de
despacho (hoy va `-Degl=false` justamente para no colisionar). Las dos mitades van en la MISMA
campaña o el resultado es el de hoy con otro disfraz. Queda escrito en las dos recetas.
Barrido de TEXTO puro: 1427 líneas de comentario TOML. Cero ArtifactHash
movidos, y eso está MEDIDO, no deducido: hasheé las 741 antes y después y los
ficheros de hashes son idénticos byte a byte (723 con hash real + 18 que ya no
hasheaban de antes).
El guardián valió la pena: el primer barrido, filtrando por 'la línea empieza
con #', movió el hash de helix, lsof y steam-runtime-sniper. La causa es que una
fase se escribe como compile = <triple> ... <triple> y sus comentarios de SHELL
también empiezan con #, pero viven dentro del VALOR — y las fases sí entran en
hash_inputs. El barrido ahora calcula los rangos de las cadenas multilínea de
TOML y no entra ahí.
Quedan intactos a propósito: .hammer-zig-cc y .hammer-cargo-vendor (literales
dentro de fases), hammerd, hammer-recover y toda ruta que empiece por /
Siete recetas decían «lo vigila `scripts/audit-needed.sh`» y ese script ya no
existe: lo borré yo mismo en 02facebe, bien borrado, porque duplicaba a
`scripts/vigia-sonames.py` — que además ya estaba en el repo y ahora corre en el
latido. Pero las referencias quedaron, escritas por mí unas horas antes.
Es exactamente la etiqueta que se lee como el hecho, y en mi propia letra: un
comentario que afirma que existe un guardián manda a quien dude de una dep de
runtime a correr un script que no está. En el mejor caso pierde diez minutos; en
el peor concluye que no hay con qué comprobarlo.
Ahora apuntan a `vigia-sonames.py` y a `docs/state/sonames.txt`, que es el
fichero que el latido regenera y donde se ve si algo empeora entre cosechas.
Ningún ArtifactHash se mueve: los siete comentarios caen fuera de campos
hasheados. Verificado uno por uno antes y después, incluido
firefox-instrumentado, que tiene un build en vuelo y se habría invalidado.
Lo levantó hammer-99 desde el frente atuq. `recipes/atuq.toml` NO se toca: su
mención es una nota histórica ya corregida por ellos («…y NO audit-needed.sh»),
y mi primer grep casi la «arregla» por no leerla.
Y la advertencia que traían vale para cualquiera con pruebas de runtime: si el
runner monta `.dev-fs/alpine` debajo, `libstdc++.so.6` se resuelve contra el LAB
y la prueba es ciega. Comprobado que la mía NO lo estaba: el rootfs hidratado
trae el del corpus (20.850.968 bytes) y no el del lab (2.804.104), y el bwrap de
la prueba nunca montó .dev-fs.
Las seis recetas que el audit daba por colgantes declaran ahora
`runtime = ["gcc-libs"]`. `deps.runtime` NO entra en el ArtifactHash —medido:
firefox sigue en b3:8116bdec, atuq en b3:f2960991, waterfox en b3:88b5a762—
así que esto NO reconstruye nada. Lo que cambia es la CLAUSURA, que es lo que se
hidrata en la imagen.
EVIDENCIA DE QUE ARREGLA EL FALLO REAL, no de que compila: `atuq` bajo sway
headless, sin GPU, renderizando about:buildconfig con sus tablas y la barra de
contenedores de la v0.5. Antes moría con decenas de «Error relocating:
_ZNKSt5ctypeIcE13_M_widen_initEv: symbol not found».
docs/evidencia/atuq-arranca-con-gcc-libs-2026-09-06.png
Y el audit se corrige, porque SUB-REPORTABA en dos formas:
· Miraba sólo ejecutables y `head -12` por artefacto. El siguiente NEEDED que
faltaba estaba en una LIBRERÍA (libmozsandbox.so pedía libnspr4.so), así que
daba «6 recetas» cuando el artefacto de firefox declara 30 sonames. Ahora
recorre TODOS los ELF.
· No contaba lo que el propio artefacto TRAE. Firefox bundlea su nspr/nss y
las encuentra por el LD_LIBRARY_PATH que fija su lanzador; contarlas como
colgantes era un falso positivo.
Con las dos correcciones y gcc-libs en el store, el corpus baja de 25 artefactos
colgantes a TRES, y son otra cosa:
sqlite-shared libreadline.so.8
python3 libreadline.so.8
naabu libdl.so.2 libpthread.so.0 libc.so.6
Los dos primeros piden una receta que falta (readline). El tercero pide sonames
de GLIBC, que en una distro musl es un síntoma distinto y merece su propia
mirada. Quedan anotados, no arreglados.
`licencias.sh --sembrar` escribe desde una tabla curada a mano y `licencias-desambiguar.sh` resuelve
`-only` vs `-or-later` preguntándole a la búsqueda de código de GitHub. Los dos dejan fuera lo mismo:
lo que nadie curó y lo que no vive en GitHub.
Pero `work/tarballs/` indexa cada tarball por su sha256, así que el árbol EXACTO que la receta pinea
ya está en disco: la declaración del propio autor, en el commit que construimos, sin red. De las 76
sin licencia, 55 tenían su tarball cacheado y 25 salieron con evidencia citable.
`scripts/licencias-tarball.py` la busca en tres niveles: la declaración del autor (`Cargo.toml`,
`meson.build`), un único fichero en `LICENSES/` (REUSE, que usa KDE), y el texto del COPYING más la
CONCESIÓN buscada en las cabeceras de los fuentes — excluyendo COPYING/LICENSE, porque el apéndice
de la GPL trae literalmente «or (at your option) any later version» y buscarla ahí da siempre
positivo siendo plantilla. Es la regla que ya fijó `licencias-desambiguar.sh`, aplicada al árbol
pineado en vez de a GitHub.
La primera versión resolvía 40, y CUATRO estaban mal. Las dejo escritas porque son la forma del
error, no accidentes:
· `socat` salía BSD-2 por su `COPYING.OpenSSL`, que es la excepción, no la licencia. Un `COPYING`
a secas gana ahora a cualquier sufijado.
· `pigz` salía Apache-2.0 por `zopfli/COPYING`: la licencia de una pieza VENDORIZADA leída como la
del contenedor. Sólo se mira la raíz.
· `openssh` salía MIT porque su `LICENCE` es un compendio de cuatro y me quedaba con la primera
que pegara. Si el texto trae varias, no hay veredicto: lo compone un humano.
· `nano` salía GPL-3.0-**or-later** citando el «either version 2» de su `aclocal.m4` — plantilla de
autotools, no del proyecto, y encima de otra versión. Ahora la cita tiene que venir de un fichero
del autor Y hablar de la misma versión mayor que el COPYING.
Y dos bugs míos que producían el mismo daño en silencio: la marca de BSD-3 era «Neither the name of»,
que libpcap y libzip no usan («The names of the authors may not be used to endorse») ⇒ se declaraban
BSD-2; y el mayor de versión lo sacaba de `"GPL-3.0".rsplit("-",1)[0][-1]`, que da «L», así que la
comprobación de coherencia rechazaba TODA cita válida.
La validación final no es una regex: un identificador vale si tenemos su texto en `licenses/`. La
obligación legal es acompañar el binario del TEXTO, así que un SPDX que no podemos entregar no
adelanta nada y sí crea una afirmación que no se sostiene. Eso es lo que atrapa el «GPL2+» que meson
deja escribir en `gsd-schemas` y `libgdm`, que no es un SPDX sino taquigrafía.
Nada se sembró a ojo: cada línea de `docs/licencias-evidencia.tsv` lleva la cita que la decidió, y
las 50 que quedan salen listadas con lo que SÍ se encontró en vez de rellenarse.
Comprobado que no se invalida nada: los 26 ArtifactHash afectados son idénticos antes y después
(`license` no está en `hash_inputs`) — medido, no supuesto.
mesa-llvmpipe con gcc/libstdc++ (matchea el ABI de libLLVM; zig-cc usaba libc++ ⇒
undefined symbols en el JIT). qemu-desktop-image inyecta libLLVM.18+libgcc_s+libstdc++.
HITO: kwin toma DRM master de virtio-gpu, crea el GBM device (llvmpipe, ya no softpipe),
expone compositor y ACEPTA clientes. Muro restante: kwin segfaultea (139) al componer la
1ra superficie con llvmpipe — necesita backtrace (gdb) para diagnosticar.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
llvmpipe necesita libLLVM (softpipe no bindea el GBM/EGL que kwin exige). El LLVM 22 del
sandbox no compila con mesa 24.0.9 ⇒ sellamos LLVM 18.1.8 desde fuente (rango soportado),
patrón gcc-de-gueto + static-libstdc++. mesa-llvmpipe = mesa-swrast con -Dllvm=enabled.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>