Con la cadena GTK3 arreglada, atuq arrancó de verdad: parent vivo, CERO procesos de contenido
muertos, y pintando una página local. Quedaban dos cosas.
1. SE ANUNCIABA COMO `firefox-default`. El application.ini decía RemotingName=atuq y aun así el
proceso se presentaba así — porque esa cadena es un MOZ_APP_REMOTINGNAME horneado en el ELF, y es
la que Gecko pasa a g_set_prgname(), o sea el **app_id de Wayland**. Consecuencia visible: el
escritorio no casaba la ventana con nuestro .desktop (StartupWMClass=atuq) ⇒ icono genérico y sin
agrupar.
Se parchea EN SITIO, no recompilando: cambiarlo en recipes/firefox.toml brandearía la BASE como
atuq, y firefox tiene que seguir siendo firefox para los otros forks. Es seguro porque es una
cadena C terminada en NUL en el pool de .rodata —`firefox-default\0` son 16 bytes exactos y se
escriben 16—, y se EXIGE una única ocurrencia: si upstream la duplica o la renombra, falla en vez
de parchear el sitio equivocado. Verificado después: 0 ocurrencias de la vieja, y el log dice
`(atuq:26423)`.
2. UN BUG QUE SÓLO SE VE FUERA DE ROOT. `cp -a` preserva los modos y los ficheros del store están
sellados sin permiso de escritura; todo lo que viene después los modifica. En el worker pasaba
inadvertido porque corre como root, que ignora los bits. El primer build local murió con
`PermissionError: /out/usr/lib/atuq/application.ini`. Se arregla con `chmod -R u+w` en la receta y
no en el entorno: un artefacto no debe depender de con qué uid lo construiste.
Y el runner pasa a hidratar las variantes `-shared`: en runtime una `.a` no sirve de nada, y son las
que gtk3 declara NEEDED desde el arreglo del cuadro de las dos Pango.
Este atuq se construyó EN LOCAL en segundos, que era la promesa entera del diseño derivado del
SDD 26: iterar el envoltorio sin volver a pagar un build de Gecko.
Con `atk` arreglado, atuq llegó más lejos y murió igual, ahora con Pango:
GLib-GObject-CRITICAL: cannot register existing type 'PangoFontMap'
… decenas de líneas … tipo '<invalid>'
MISMO CUADRO, CULPABLE DISTINTO Y MÁS GRANDE. `gtk3` produce DOS objetos compartidos —libgtk-3.so y
libgdk-3.so— y libxul declara NEEDED las dos, así que se cargan siempre juntas. Con las variantes
ESTÁTICAS de sus deps, cada una se llevaba adentro su propia copia. Medido con el mismo instrumento
que cazó a atk, `nm -D --defined-only`, preguntando quién DEFINE cada símbolo:
pango_font_map_get_type → libgdk-3.so, libgtk-3.so, libgailutil-3.so
cairo_create → libgdk-3.so, libgtk-3.so
gdk_pixbuf_get_type → libgdk-3.so, libgtk-3.so
hb_buffer_create → libgdk-3.so, libgtk-3.so, libgailutil-3.so
Y se comprobó el otro lado: libxul NO embebe ninguna —enlaza libgtk-3/libgdk-3 como debe—, así que
la duplicación es toda interna del par GTK3.
Cuatro variantes nuevas: harfbuzz-shared, cairo-shared, gdk-pixbuf-shared, pango-shared. Sólo cambia
el modo de librería; se conservan todos los switches del canónico para no arrastrar deps nuevas.
DOS DEUDAS ANOTADAS, NO OLVIDADAS: `fribidi` y `pixman` siguen estáticos —no existe variante— pero
quedan embebidos en UNA sola .so cada uno, así que no hay copia que colisione; y `libepoxy` sí queda
en las dos, y se deja porque no registra tipos de GObject ni mantiene estado global. Si algún día
otra .so del mismo proceso los embebe, vuelve el cuadro.
`firefox` swapea las mismas cuatro: declarar las ESTÁTICAS junto a un gtk3 que trae las compartidas
son dos artefactos peleando por el mismo `pango.pc`, que es la otra forma conocida de este fallo.
Y `xkeyboard-config` SUBE AL CORPUS. Existía idéntica en las cuatro colas de escritorio (un solo md5
entre las cuatro, verificado antes de mover) y atuq, que vive en el corpus, no podía alcanzar
ninguna: sibling-first y después el catálogo padre, nunca una cola hermana. Sin sus datos el
navegador ni pinta («xkbcommon: failed to add default include path /usr/share/X11/xkb»). Mismo hash
en el corpus que en las colas ⇒ cero rebuilds, y las copias de las colas se quedan donde están.
El script daba por bueno el rootfs si el directorio estaba: «¿ya está hidratado?». Es la pregunta
equivocada. Tras el re-hash de la cadena atk→gtk3→firefox→atuq el directorio seguía ahí con los
artefactos VIEJOS, así que habría abierto contento la versión que acabábamos de arreglar y el
diagnóstico habría sido buscar en el sitio equivocado. Misma forma del cache-hit que congela
regresiones.
Ahora resuelve los hashes vigentes, los anota en `.raices` y rehidrata cuando difieren.
De paso: nada de `diff <(...)`, que es de bash. El shebang dice /bin/sh y un script que sólo anda
cuando /bin/sh resulta ser bash es una trampa que salta en otra máquina.
Dos cosas que salieron de intentar ABRIRLO, que es lo único que distingue «sellado» de «usable».
1. EL LANZADOR. Con `/usr/bin/atuq` como symlink, el navegador moría antes de pintar:
XPCOMGlueLoad error for file /usr/lib/atuq/libmozsandbox.so:
Error loading shared library libnspr4.so: No such file or directory
El motor carga sus propias librerías desde `/usr/lib/atuq` y ni el binario ni esas `.so` traen
RPATH/RUNPATH — comprobado con `readelf -d`, no supuesto. Pasa a ser un script que exporta
`LD_LIBRARY_PATH` (lo mismo que hacen Debian y Fedora) y hace `exec`, para que el proceso que
queda sea el motor y `/proc/self/exe` siga resolviendo el appdir. El `LD_LIBRARY_PATH` además
tiene que HEREDARSE: Firefox lanza un proceso por pestaña y todos cargan las mismas librerías.
La alternativa limpia es grabar RPATH=$ORIGIN con `patchelf` —es lo que hace Alpine— pero
`patchelf` todavía no existe como receta del corpus; cuando exista, esto vuelve a ser un symlink.
2. `scripts/atuq-nested.sh` — hidrata el cierre de runtime y abre atuq como ventana anidada en el
compositor que ya está delante (waypipe, mirada, sway). Trae dos cosas aprendidas a golpes:
· EL ROOTFS VA EN EL MISMO MOUNT QUE EL STORE. `hydrate` proyecta con hardlinks y `linkat()`
rechaza cruzar un punto de montaje aunque sea el mismo filesystem. Acá el store es /dev/sdb
bind-monteado y `work/` vive en /dev/sdc: hidratar a `work/…` muere con «Invalid cross-device
link (os error 18)». El volumen entero está en /mnt/cosecha, así que el rootfs va ahí. Se
comprueba con `findmnt -T`, nunca con `stat -c %d`.
· `dejavu-fonts` va en las raíces por necesidad, no por completismo: un navegador sin una sola
fuente arranca, pinta y muestra cuadraditos. Ya nos costó una tarde en GNOME.
Y no saltea en silencio: si falta un artefacto de la lista, sale con error en vez de armar un
rootfs al que le faltan tres paquetes y falla tres capas más abajo.