wlr: el escritorio DIBUJA — arranque headless en 2 min y 5 piezas que el cierre no traía

`scripts/wlr/sway-headless.sh` corre el perfil escritorio-sway dentro de un bwrap, sin QEMU, sin
kernel y sin imagen de disco, y captura con grim. Evidencia: PNG 1280x720 con 383 colores —#242424
fondo de foot, #285577/#4c7899 bordes de sway, #d0d0d0 el texto. sway 1.10 / wlroots 0.18.2 /
foot 1.27.0, todo del corpus.

Sirve porque el ciclo de diagnóstico pasa de ~40 min (product-rootfs + imagen EFI + arranque) a ~2
min. No sustituye al arranque en QEMU: no prueba kernel, initramfs, DRM ni PID1. Prueba lo que el
arranque en VM tapa detrás de una pantalla negra.

LO QUE SE MIDIÓ, y es lo que importa: el perfil da 121/121 y aun así NO arranca solo. Faltan cinco
cosas, ninguna en la clausura:
  · libz.so.1 / libexpat.so.1 / libffi.so.8 — sway salió DINÁMICO y el corpus sólo produce `.a`.
    Sin ellas ni arranca. libz existe como artefacto `zlib-shared`; las otras dos hoy sólo están en
    `.dev-fs/alpine`, o sea que el escritorio depende del rootfs del lab.
  · xkeyboard-config y dejavu-fonts — HAY receta de las dos, en incoming-{kde,gnome,cosmic}. En la
    cola de wlr no, así que el perfil no las alcanza. Un escritorio sin una sola fuente.
  · /etc/passwd y /etc/fonts/fonts.conf.

Y bash NO CORRE: enlazado dinámico contra ncurses, del que sólo hay `libncurses.a` ⇒ «Error
relocating /bin/bash: tgetent: symbol not found».

El modo de fallo vale más que la lista. Nada de esto se vio como un error: `foot` abría, sway
registraba «New xdg_shell toplevel» —la ventana EXISTÍA en el árbol— y la captura salía con UN SOLO
COLOR. El shell moría al instante y la ventana se cerraba antes del frame. Log entero en verde,
pantalla vacía. Por eso la evidencia es contar colores del PNG y nunca leer el log: 1 color = sólo
swaybg, ningún cliente dibujó.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016v9ozVm44p6DB7EMXeZK4o
This commit is contained in:
Sergio
2026-08-26 17:09:04 +00:00
co-authored by Claude Opus 5
parent b6c469d28f
commit f7ce610eb9
+86
View File
@@ -0,0 +1,86 @@
#!/bin/sh
# sway-headless.sh — arranca el perfil escritorio-sway SIN QEMU, SIN kernel y SIN imagen de disco, y
# captura la pantalla con grim. Hermano de sway-start.sh (que arranca dentro de la VM); éste corre el
# cierre hidratado dentro de un `bwrap` sobre la máquina de desarrollo.
#
# PARA QUÉ. Validar «el escritorio dibuja» costaba armar un product-rootfs + imagen EFI + arranque en
# QEMU: ~40 min por vuelta y hace falta un `hammer bootstrap product` que hoy no está en el store.
# Headless da la misma evidencia —píxeles reales, dibujados por NUESTROS binarios— en ~2 min, así que
# el ciclo de diagnóstico deja de ser el cuello de botella. NO sustituye al arranque en QEMU: no prueba
# kernel, ni initramfs, ni DRM, ni el PID1. Prueba el compositor y sus clientes, que es justo lo que
# el arranque en VM tapa detrás de una pantalla negra.
#
# INVOCACIÓN (desde la raíz del repo, con work/sway-rootfs ya hidratado):
# mkdir -p /tmp/sway-out
# bwrap --bind work/sway-rootfs / --bind /usr/lib/musl /usr/lib/musl \
# --bind /tmp/sway-out /salida --dev /dev --proc /proc --tmpfs /run --tmpfs /tmp \
# --unshare-user --uid 0 --gid 0 --setenv PATH /usr/bin:/bin:/usr/sbin:/sbin \
# /bin/sh /sway-headless.sh
#
# ── LO QUE EL CIERRE 121/121 NO TRAE Y HAY QUE INYECTAR ────────────────────────────────────────
# Medido el 2026-08-26 sobre el perfil COMPLETO. Nada de esto lo aporta la clausura:
# · libz.so.1 / libexpat.so.1 / libffi.so.8 — sway salió DINÁMICO contra ellas y el corpus sólo
# produce los `.a`. `libz.so.1` está como artefacto aparte (`zlib-shared`); las otras dos hoy
# sólo existen en `.dev-fs/alpine`. Sin ellas sway ni arranca: «Error relocating /usr/bin/sway:
# XML_ParserFree: symbol not found».
# · xkeyboard-config — «xkbcommon: ERROR: failed to add default include path /usr/share/X11/xkb».
# Sway sigue vivo pero no completa el seat. HAY receta, en incoming-{kde,gnome,cosmic}; en la
# cola de wlr no, así que el perfil no la alcanza.
# · dejavu-fonts — el rootfs no tiene UNA fuente. `foot` muere con «monospace::size=8: failed to
# match font». Misma historia: la receta existe en incoming-{kde,cosmic} y no en la de wlr.
# · /etc/passwd y /etc/fonts/fonts.conf — sin el primero yambar hace getpwuid y falla; sin el
# segundo fontconfig no mira /usr/share/fonts aunque las fuentes estén.
#
# ── BASH NO CORRE EN ESTE ROOTFS, Y ASÍ ES COMO SE VE ──────────────────────────────────────────
# `/bin/bash` está enlazado dinámico contra ncurses y el corpus sólo produce `libncurses.a`:
# Error relocating /bin/bash: tgetent: symbol not found
# El síntoma NO fue un error de bash. Fue que `foot` abría, sway registraba «New xdg_shell toplevel»
# —o sea la ventana EXISTÍA en el árbol— y la captura salía con UN SOLO COLOR, el de swaybg: foot
# lanzaba el shell, el shell moría al instante y la ventana se cerraba antes del frame. Por eso acá
# el shell es busybox, que sí es autosuficiente.
#
# ── LA EVIDENCIA ES CONTAR COLORES, NO LEER EL LOG ─────────────────────────────────────────────
# El log entero puede estar en verde con la pantalla vacía. La medida que no se puede falsear:
# 1 color = sólo el fondo de swaybg ⇒ NINGÚN cliente dibujó (aunque el árbol los liste)
# ~380 = terminal con texto ⇒ #242424 fondo de foot, #285577/#4c7899 bordes de sway,
# #d0d0d0 el texto. ESO es un escritorio dibujando.
export XDG_RUNTIME_DIR=/run/user/0
mkdir -p "$XDG_RUNTIME_DIR"; chmod 700 "$XDG_RUNTIME_DIR"
export WLR_BACKENDS=headless
export WLR_HEADLESS_OUTPUTS=1
export WLR_RENDERER=pixman
export XDG_CONFIG_HOME=/root/.config
export SHELL=/bin/bash
export LANG=C
export HOME=/root
(
i=0
while [ ! -S /run/user/0/wayland-1 ] && [ $i -lt 40 ]; do sleep 1; i=$((i+1)); done
[ -S /run/user/0/wayland-1 ] || { echo "!! el socket wayland nunca apareció"; exit 1; }
export WAYLAND_DISPLAY=wayland-1
echo "== socket listo, lanzando clientes"
/usr/bin/swaybg -c '#1a4b8c' & sleep 2
# bash NO corre en este rootfs: está enlazado dinámico contra ncurses y el corpus sólo produce
# libncurses.a ⇒ «Error relocating /bin/bash: tgetent: symbol not found». foot lanzaba el shell,
# el shell moría al instante y foot cerraba la ventana: el toplevel APARECÍA en el árbol de sway
# y la captura salía 100% del color de swaybg. Se usa busybox, que sí es autosuficiente.
/usr/bin/foot -- /bin/busybox sh -c '
echo " hammer — distro reproducible desde fuente"
echo
echo " compositor : sway 1.10 / wlroots 0.18.2"
echo " terminal : foot 1.27.0"
echo " libc : musl toolchain: zig cc"
echo
/bin/busybox uname -a
echo
echo " binarios en /usr/bin: $(/bin/busybox ls /usr/bin | /bin/busybox wc -l)"
/bin/busybox sleep 60' >/salida/foot.log 2>&1 & sleep 12
echo "== capturando"
/usr/bin/grim /salida/captura.png 2>&1 && echo "== grim OK: $(ls -l /tmp/captura.png)"
sleep 1
/usr/bin/swaymsg exit 2>/dev/null
) &
exec /usr/bin/sway -d 2>&1