Files
sergioandClaude Opus 5 e3403ff20e sway ARRANCA EN QEMU con pantalla — evidencia, y seis muros que el grafo no podía ver
`docs/evidencia/sway-qemu-2026-08-08.png`: 1280×800, **102 colores distintos**, sway con foot a
pantalla completa y un prompt vivo, la barra de título del compositor arriba y el fondo
#1a4b8c asomando en los bordes. Sobre el kernel de hammer con arje-zero como PID1, sin X11 y
sin systemd.

EL VEREDICTO ES CONTAR COLORES, NO LEER EL LOG — y esta campaña lo demuestra sola: hubo un
arranque con TODO verde en el log (salida activada, modo 1280x800, «Commit of 1 outputs
succeeded», workspace creado) y la captura salía **100% negra**. Un compositor puede estar
perfectamente vivo y no pintar nada.

LOS SEIS MUROS, ninguno visible en un grafo de dependencias que decía 121/121:

1. `PATH` vacío — el console-getty no lo exporta y ni `mkdir` se encontraba. «mkdir: not found»
   se lee como «falta busybox» cuando busybox está entero: mismo engaño que el exit 127 de meson.
2. `libz.so.1` AUSENTE del rootfs. El zlib del corpus es sólo estático; la compartida vive en
   `zlib-shared`, en otra cola. Se cazó comparando los NEEDED del ELF contra el rootfs, no
   leyendo logs.
3. `LIBSEAT_BACKEND=builtin` NO EXISTE en nuestro libseat: `recipes/seatd.toml` construye con
   `-Dlibseat-seatd=enabled -Dlibseat-logind=disabled`, o sea UN backend, confirmado con
   `strings`. La receta manda sobre lo que uno cree recordar del proyecto — y la misma receta
   traía la salida: `-Dserver=enabled` construye `seatd-launch`.
4. `/run` de SÓLO LECTURA. La raíz de hammer es inmutable por diseño, y sway moría con «unable
   to open lockfile … check permissions», que suena a permisos de directorio y era un
   filesystem read-only. Se resolvió montando un tmpfs, que es lo que hace cualquier init.
5. `xkeyboard-config` — «failed to add default include path /usr/share/X11/xkb». Es EXACTAMENTE
   lo que dejé anotado en la receta de swaylock: «para que el teclado tenga distribución en una
   imagen real hará falta incluirlo por el lado del perfil». Apareció donde se dijo.
6. SIN TIPOGRAFÍAS no hay terminal. `fcft: failed to match font` → `failed to load primary
   fonts`: foot arrancaba y no dibujaba. `dejavu-fonts` estaba en el catálogo pero en otra cola.
   Va en la lista de §I.5 del SDD 20 («tipografías») y acá se ve por qué no es un detalle.

Y un fallo de MÉTODO que costó dos ciclos: mandé el log de sway a /var/log/sway.log DENTRO de
la VM, así que la primera captura negra vino sin una sola línea que la explicara — el
diagnóstico estaba dentro de la caja que no arranca. Un log que no se puede leer desde fuera no
es un log. Ahora va al serial.

Los `exec` de la config de sway disparan ANTES de que exista el workspace (0,259 s vs 0,305 s)
y mueren con «Failed to create launch context. No workspace». Los clientes se lanzan desde
sway-start esperando el socket de Wayland, que es la condición real.

Andamiaje reutilizable en scripts/wlr/: qemu-sway-image.sh (hermano del de COSMIC, sin logind
ni dbus, que sway no necesita), sway-start.sh y sway-config.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-07 22:38:51 -04:00

76 lines
5.2 KiB
Bash
Executable File

#!/bin/sh
# sway-start.sh — arranque de sway dentro de la VM. Lo ejecuta el `console-getty` de arje-zero en
# lugar de /bin/sh, así que corre como PID de sesión sin login manager.
#
# ── LA SESIÓN VA POR `seatd-launch`, NO POR EL BACKEND «builtin» ───────────────────────────────
# Primer intento: `LIBSEAT_BACKEND=builtin`, que en libseat abre el DRM directo siendo root.
# **Falló, y el log lo dijo exacto**:
# [libseat] No backend matched name 'builtin'
# [backend/session] Unable to create seat: Invalid argument → Failed to start a DRM session
# Porque NUESTRO libseat no lo trae: `recipes/seatd.toml` construye con `-Dlibseat-seatd=enabled
# -Dlibseat-logind=disabled`, o sea UN solo backend. Confirmado con `strings libseat.so`: lista
# `seatd` y nada más.
# ⇒ La receta manda sobre lo que uno cree recordar de un proyecto. Y la misma receta trae la
# solución: `-Dserver=enabled` construye el demonio Y `seatd-launch`, que lo levanta, corre el
# comando y limpia al salir.
# ── tmpfs SOBRE /run: la raíz de hammer se monta de SÓLO LECTURA ───────────────────────────────
# El diagnóstico lo dijo sin ambigüedad: «/run/user/0 NO escribible». `/run` no es un tmpfs sino un
# directorio normal sobre la raíz, y la raíz de esta distro es INMUTABLE por diseño (root ro +
# partición de estado aparte). Sin esto, sway no puede crear su lockfile y muere en bucle con
# «unable to open lockfile /run/user/0/wayland-N.lock check permissions» — un mensaje que suena a
# permisos de directorio y en realidad es un sistema de ficheros de sólo lectura.
# Montar un tmpfs es lo que hace cualquier init; acá lo hace el lanzador porque arje-zero deja /run
# para quien lo necesite.
BB=/bin/busybox
$BB mount -t tmpfs -o mode=755 tmpfs /run 2>/dev/null || true
export XDG_RUNTIME_DIR=/run/user/0
$BB mkdir -p "$XDG_RUNTIME_DIR"; $BB chmod 700 "$XDG_RUNTIME_DIR"
# ── RENDERER PIXMAN, NO GLES2: en QEMU no hay driver de GPU que mesa pueda cargar ──────────
# Con gles2 el arranque muere: «MESA-LOADER: failed to open virtio_gpu: /usr/lib/dri/virtio_gpu_dri.so
# No such file or directory» — mesa busca el driver del dispositivo REAL que ve (virtio_gpu) y
# nuestro mesa-llvmpipe sólo trae swrast/kms_swrast. Y «Not allowed to force software rendering when
# API explicitly selects a hardware device»: LIBGL_ALWAYS_SOFTWARE no lo salva porque wlroots ya
# eligió el dispositivo EGL explícitamente. Las dos variables juntas se pedían cosas contradictorias.
# wlroots trae un renderer PIXMAN por software que NO pasa por EGL ni GBM (buffers dumb del DRM) y
# se construye SIEMPRE: -Drenderers sólo elige entre gles2 y vulkan. Es la salida para una VM sin GPU.
export WLR_RENDERER=pixman
# Diagnóstico: sin esto, cuando algo falla el log dice «no outputs» y nada más.
export WLR_DRM_NO_ATOMIC=1
export WAYLAND_DEBUG=0
# ⚠ EL LOG VA AL SERIAL, NO A UN FICHERO DENTRO DE LA VM. El primer intento lo mandaba a
# /var/log/sway.log y la captura salió 99% negra SIN UNA SOLA LÍNEA que explicara por qué: el
# diagnóstico estaba dentro de la caja que no arranca. Un log que no se puede leer desde fuera no
# es un log. (La causa resultó ser `libz.so.1` ausente del rootfs, invisible en la pantalla negra.)
# ── DIAGNÓSTICO EXPLÍCITO antes de arrancar ────────────────────────────────────────────────────
# sway falló con «unable to open lockfile /run/user/0/wayland-N.lock check permissions» y yo no
# tenía forma de saber si el directorio existía, de quién era, ni si /run era escribible. Adivinar
# cuesta un ciclo de imagen+arranque (~3 min); imprimir la verdad cuesta cuatro líneas.
echo "== id: $($BB id 2>&1)"
echo "== /run: $($BB ls -ld /run 2>&1)"
echo "== /run/user/0: $($BB ls -ld /run/user/0 2>&1)"
if $BB touch /run/user/0/.probe 2>/dev/null; then echo "== /run/user/0 ESCRIBIBLE"; $BB rm -f /run/user/0/.probe
else echo "== /run/user/0 NO escribible"; fi
$BB rm -f /run/seatd.sock # el getty reinicia en bucle si sway falla; un socket huérfano impide arrancar seatd
# ── LOS CLIENTES SE LANZAN CUANDO EL SOCKET YA ESCUCHA, NO DESDE LA CONFIG ─────────────────────
# Los `exec` del fichero de config de sway dispararon a los 0,259 s y el workspace se creó a los
# 0,305 s ⇒ los tres murieron con «Failed to create launch context. No workspace». Resultado: el
# compositor arrancaba PERFECTO —salida activada, modo 1280x800, commit OK— y la captura salía 100%
# negra, porque no había un solo cliente dibujando. Es el peor tipo de fallo: todo verde en el log
# y nada en la pantalla, que es exactamente por lo que la regla dice validar CON PANTALLA.
# Acá se espera al socket de Wayland y recién entonces se lanza, que es la condición real.
(
i=0
while [ ! -S /run/user/0/wayland-1 ] && [ $i -lt 60 ]; do $BB sleep 1; i=$((i+1)); done
export WAYLAND_DISPLAY=wayland-1
/usr/bin/swaybg -c '#1a4b8c' &
/usr/bin/yambar &
/usr/bin/foot &
) &
exec /usr/bin/seatd-launch -- /usr/bin/sway -d 2>&1