From b6d000eca3e837b48a1d796a58a0aa795eaed73c Mon Sep 17 00:00:00 2001 From: Sergio Date: Mon, 7 Sep 2026 15:37:46 +0000 Subject: [PATCH] =?UTF-8?q?atuq-nested:=20el=20runner=20med=C3=ADa=20un=20?= =?UTF-8?q?rootfs=20M=C3=81S=20POBRE=20que=20la=20imagen,=20y=20su=20cach?= =?UTF-8?q?=C3=A9=20no=20cacheaba?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tres cosas en el mismo fichero, las tres medidas hoy: 1. `ffmpeg` y `libva` entran a las raíces. NO son recetas nuevas: las dos están selladas en el corpus y ya viven en la clausura de los cuatro escritorios, arrastradas por `mpv` (verificado con `yupana.membresia`, no leyendo el TOML). Faltaban acá, o sea que el runner abría un rootfs sin libavcodec y desde ahí se concluía que la imagen no tiene códecs. El instrumento otra vez, no el artefacto. 2. El bucle de hidratación salía 1 SIEMPRE: `$VIGENTES` termina en `\n`, `echo` agrega otro, la última vuelta lee la línea vacía, `[ -n "$d" ]` da 1 y con `set -e` el script moría sin imprimir una sola línea, justo después de hidratar bien las 41 raíces. Ahora `continue` en la vacía y un `hydrate` que falla grita. 3. La comparación del sello NUNCA daba igual: el lado izquierdo lleva su `\n` final y `$(cat …)` lo recorta ⇒ «DESACTUALIZADO» en cada corrida y 3013 ficheros rehidratados de más. Los dos lados pasan ahora por la misma sustitución de comandos. Y `ROOTFS_ONLY=1`, que corta después de hidratar: lo necesita el guardián de códecs, que corre headless y tiene que usar ESTA lista de raíces y no una copia. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01NNFzrqFBEt6W7maGJKf2Xs --- scripts/atuq-nested.sh | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/scripts/atuq-nested.sh b/scripts/atuq-nested.sh index c16b6dbd..d6371c98 100755 --- a/scripts/atuq-nested.sh +++ b/scripts/atuq-nested.sh @@ -41,6 +41,7 @@ RAICES="atuq gcc-libs gtk3 atk gdk-pixbuf-shared pango-shared cairo-shared libep libxml2-shared dejavu-fonts bzip2-shared expat-shared ncurses-shared libsndfile libudev-zero zstd dbus-shared libnotify + ffmpeg libva xkeyboard-config grim" # ⚠ `gcc-libs` FALTABA, y su ausencia hacía MENTIR a esta prueba entera (2026-09-07). `atuq` declara # `NEEDED libstdc++.so.6` y `libgcc_s.so.1` —lo hereda de firefox, que va con clang++ y la libstdc++ @@ -59,6 +60,15 @@ RAICES="atuq gcc-libs gtk3 atk gdk-pixbuf-shared pango-shared cairo-shared libep # `libdbus-1.so.3` lo pide pipewire y NO lo trae `dbus` sino `dbus-shared`, el mismo cuadro de las # variantes `-shared` de gtk3. Mantener esta lista a mano es lo que falla: por eso ahora hay un # guardián que la audita en vez de confiar en que alguien se acuerde. +# `ffmpeg` y `libva` entran el 2026-09-07 y NO son recetas nuevas: las dos estaban selladas en el +# corpus y ya viven en la CLAUSURA de los cuatro escritorios, arrastradas por `mpv`. Lo que faltaba +# era esta lista, o sea otra vez el instrumento. Firefox abre `libavcodec.so.<53..63>` por `dlopen` +# literal —está en las cadenas de `libxul.so`— y nuestro ffmpeg 7.1 publica `libavcodec.so.61`, o +# sea H.264/AAC por software. Sin estas dos raíces el runner mide un rootfs MÁS POBRE que la imagen +# y reporta un hueco que la imagen no tiene. Ver SDD 26 §6.10. +# ⚠ `libva` va por simetría con la imagen, no porque encienda VA-API: las tres mesa construyen con +# `-Dgallium-va=disabled -Dvideo-codecs=`, así que el cargador está y no hay UN SOLO driver +# (`*_drv_video.so`) que cargar. Es media función, como libnotify sin daemon. # `grim` no lo necesita atuq: lo necesita QUIEN LO MIRA. Con `CAPTURA=` este script # saca la pantalla real desde dentro de la jaula, contra el mismo socket wayland. Es lo que separó # «el proceso vive» de «la ventana muestra lo que queremos»: durante horas dije «mirá tu pantalla» @@ -89,21 +99,42 @@ done [ -z "$faltan" ] || { echo "✗ faltan artefactos:$faltan" >&2; exit 1; } SELLO="$RFS/.raices" -if [ "${REHIDRATAR:-0}" = "1" ] || [ ! -f "$SELLO" ] || [ "$VIGENTES" != "$(cat "$SELLO")" ]; then +# ⚠ LOS DOS LADOS DE LA COMPARACIÓN TIENEN QUE PASAR POR LA MISMA TRITURADORA. `$VIGENTES` termina +# en `\n` y `$(cat …)` RECORTA los `\n` finales ⇒ comparados en crudo NUNCA son iguales y el rootfs +# se rehidrataba entero en CADA corrida (3013 ficheros), diciendo «DESACTUALIZADO» aunque estuviera +# perfecto. La caché existía y no cacheaba nada; medido 2026-09-07. Metiendo el de la izquierda en +# otra sustitución de comandos, los dos pierden el mismo `\n` y la comparación vuelve a significar +# lo que dice. +if [ "${REHIDRATAR:-0}" = "1" ] || [ ! -f "$SELLO" ] || [ "$(printf '%s' "$VIGENTES")" != "$(cat "$SELLO")" ]; then # Nada de `diff <(...)`: esto es /bin/sh, y la sustitución de proceso es de bash. Un script que # sólo funciona cuando /bin/sh resulta ser bash es una trampa que salta en otra máquina. [ -f "$SELLO" ] && echo "==> el rootfs está DESACTUALIZADO — se rehidrata" echo "==> hidratando $(echo $RAICES | wc -w) raíces en $RFS" rm -rf "$RFS"; mkdir -p "$RFS" + # ⚠ ESTE BUCLE SALÍA 1 SIEMPRE, Y CON `set -e` MATABA EL SCRIPT SIN IMPRIMIR NADA (2026-09-07). + # `$VIGENTES` termina en `\n` y `echo` agrega otro ⇒ la última vuelta lee la línea VACÍA, el + # `[ -n "$d" ]` da 1, ése es el estado de la última vuelta, ése es el estado del `while`, ése es + # el del pipeline, y `set -e` sale. Justo DESPUÉS de hidratar bien las 41 raíces: la única señal + # era `exit=1` tras «==> hidratando». No se veía porque esta rama sólo corre cuando cambian los + # hashes —con el sello al día el script ni entra—, así que el bug vivía escondido detrás de la + # caché. Lo destapó agregar `ffmpeg` a las raíces. Ahora: `continue` en la vacía, y un `hydrate` + # que falla GRITA en vez de dejar un rootfs a medias con el sello sin escribir. echo "$VIGENTES" | while read -r d; do - [ -n "$d" ] && "$H" --store "$STORE" hydrate "${d%%-*}" --into "$RFS" >/dev/null - done + [ -n "$d" ] || continue + "$H" --store "$STORE" hydrate "${d%%-*}" --into "$RFS" >/dev/null || { + echo "✗ hydrate falló en $d" >&2; exit 1; } + done || exit 1 printf '%s' "$VIGENTES" > "$SELLO" echo "==> hidratado: $(find "$RFS" -type f | wc -l) ficheros" else echo "==> rootfs al día ($(echo "$VIGENTES" | grep -c . ) raíces, hashes vigentes)" fi +# `ROOTFS_ONLY=1` corta acá: deja el rootfs hidratado y al día, y no abre ventana ni pide pantalla. +# Lo usa `scripts/test-atuq-codecs.sh`, que corre headless y necesita el MISMO árbol que esta +# ventana — duplicar la lista de raíces en dos scripts es exactamente cómo se desincronizan. +[ "${ROOTFS_ONLY:-0}" = "1" ] && exit 0 + [ -n "${WAYLAND_DISPLAY:-}" ] || { echo "✗ no hay WAYLAND_DISPLAY — esto necesita una pantalla" >&2; exit 1; } SOCK="${XDG_RUNTIME_DIR:-/run/user/$(id -u)}/$WAYLAND_DISPLAY" [ -S "$SOCK" ] || { echo "✗ no existe el socket $SOCK" >&2; exit 1; }