tawasuyu

sergio/takana

> Una distribución Linux construida con un laboratorio funcional y hermético en el > sótano, y una terminal mutable, clásica y anárquica en el piso de arriba — diseñada > desde el suelo para que una IA programadora entienda, modifique y co…

TOML 1435Shell 145Markdown 88Rust 852973 Definiciones

gnome: el compositor SUBE ENTERO en headless — el muro DRM es libinput, y aparece accountsservice

Experimento decisivo: `gnome-shell --headless --virtual-monitor 1280x800`. El
backend headless crea el seat con META_SEAT_NATIVE_FLAG_NO_LIBINPUT, o sea que
saltea init_libinput() — justo el último paso del hilo de input antes de señalar
`input_thread_initialized` (meta-seat-impl.c:3098). Resultado:

  libmutter-Message: Added virtual monitor Meta-0
  libmutter-Message: Using Wayland display name 'wayland-0'
  == compositor OK (wayland-0) — el shell ES el display server

⇒ **CONFIRMADO: el bloqueo del camino DRM está en libinput/udev, no en el resto
del arranque.** Todo lo demás de mutter funciona. Primer sospechoso libudev-zero.

Y con el compositor arriba aparece el muro siguiente, que es de otra naturaleza:

  Gjs-CRITICAL: JS ERROR: Requiring AccountsService, version 1.0:
                Typelib file for namespace 'AccountsService' not found

LA LECCIÓN DE MÉTODO: gnome-shell selló con su cierre de build COMPLETO (108/108)
y aun así la sesión muere pidiendo este typelib. **El cierre de build no es el
cierre de runtime**: todo lo que el shell carga por `imports.gi.*` desde
JavaScript es invisible al grafo de deps. Se encuentra ARRANCANDO, no compilando.

Se autoró recipes/incoming-gnome/accountsservice.toml. El configure pasa entero
—tres seds verificados contra el build real: generate-version.sh (deriva la
versión del nombre del DIRECTORIO, que en el sandbox es /src, y la rama git usa
`date`, o sea no-determinista), la aserción de wtmp (musl no define WTMPX_FILENAME
ni _PATH_WTMPX) y subdir('tests') (arrastra mocklibc, que llama fgetgrent, ausente
en musl)—. Ojo: -Dsystemdsystemunitdir tiene que ser literalmente `no`; con la
cadena vacía el meson interpreta "averiguá el directorio" y aserta pidiendo
systemd.pc.

NO SELLA todavía, y la frontera está contada símbolo por símbolo, no estimada:

  · libelogind exporta 14 símbolos (los que pedía mutter) y accountsservice usa
    OCHO que faltan: sd_get_sessions, sd_seat_can_multi_session,
    sd_session_get_display y los cinco de sd_login_monitor_*. Estos últimos son
    la parte con enjundia: no son getters sino una API de NOTIFICACIÓN (un fd
    poll-able). Sobre el diseño actual el camino natural es inotify sobre
    /run/systemd/{sessions,seats,users}.
  · fgetspent_r no existe en musl (extensión glibc de /etc/shadow, usada en
    src/daemon.c:265): necesita shim o parche a la variante no-reentrante.

Ninguno de los dos es de accountsservice: son huecos de NUESTRA capa de compat.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

f56bab72f520a5ae69c91fd99c8a1e75d362d9ec · por sergio · (hace 2 meses) · padre 34c7962b2 · ver el árbol en este commit

Delta semántico

Ninguna definición cambió: el cambio es de texto, documentación o datos.

3 archivos · +114 −2

diff --git a/recipes/incoming-gnome/accountsservice.toml b/recipes/incoming-gnome/accountsservice.toml
new file mode 100644
index 00000000..f77b794e
--- /dev/null
+++ b/recipes/incoming-gnome/accountsservice.toml
@@ -0,0 +1,97 @@
+# accountsservice 23.13.9 — el servicio D-Bus de cuentas de usuario (nombre, avatar, idioma, si es
+# administrador). Lo pide gnome-shell desde JAVASCRIPT, no desde C: por eso no aparecía en el
+# meson.build de la cima ni en su cierre de build, y sólo se destapó ARRANCANDO la sesión:
+#
+#   Gjs-CRITICAL: JS ERROR: Requiring AccountsService, version 1.0:
+#                 Typelib file for namespace 'AccountsService', version '1.0' not found
+#   Execution of main.js threw exception
+#
+# Lección del método: **el cierre de BUILD no es el cierre de RUNTIME**. gnome-shell selló con
+# 108/108 recetas y aun así le falta esto, porque `imports.gi.AccountsService` se resuelve en tiempo
+# de ejecución. Toda dep que el shell cargue por typelib desde JS es invisible al build.
+#
+# -Delogind=true es la pieza que hace que esto entre gratis: accountsservice pide `libsystemd` por
+# defecto (meson.build:219) y con esta opción pide `libelogind` (:217), que YA está sellada —
+# arje-sdlogin-compat, con Version 255 en su .pc, por encima del >= 229.4 que exige. Es la quinta vez
+# en la campaña que la C-ABI de logind aparece, y la primera que se resuelve sin esquivarla.
+#
+# Apagados:
+#   -Dvapi=false      → no hay valac en el corpus.
+#   -Ddocbook=false -Dgtk_doc=false → xmlto/gtk-doc.
+#   -Dsystemdsystemunitdir=no  → no instala units de systemd; acá PID1 es arje-zero. Ojo: el valor
+#                        tiene que ser literalmente `no`, NO la cadena vacía — con vacía el meson
+#                        interpreta "averiguá el directorio" y ASERTA pidiendo systemd.pc (:183).
+# libxcrypt es `required: false` (meson.build:161) ⇒ no hace falta receta: sin ella el servicio no
+# cambia contraseñas, que no es lo que el shell le pide (le pide el usuario y su avatar).
+#
+# `generate-version.sh` se reemplaza por un `echo` de la versión. El script del tarball deriva la
+# versión del NOMBRE DEL DIRECTORIO (`basename $PWD | sed 's/^accountsservice-\(.*\)$/\1/'`), y en el
+# sandbox de hammer el árbol de fuentes es `/src` ⇒ no matchea y aborta con "Version unknown". Fijarla
+# además la vuelve DETERMINISTA: la otra rama del script (la de checkout git) calcula la versión con
+# `date` sobre el último commit, que es exactamente lo que un store direccionable por contenido no
+# puede tolerar.
+#
+# El otro sed borra una ASERCIÓN sobre wtmp (meson.build:107). accountsservice busca el fichero de
+# histórico de logins probando `WTMPX_FILENAME` y `_PATH_WTMPX`; **musl no define ninguno de los dos**
+# —no implementa wtmp—, así que cae a la rama final, que exige que `/var/log/utx.log` EXISTA en el
+# constructor y aborta si no. Se borra sólo la línea del assert: la rama igual deja
+# `PATH_WTMP='/var/log/utx.log'`, o sea que el servicio vigila esa ruta y, como nunca aparece, no
+# reporta histórico de sesiones. Lo que el shell le pide —el usuario, su nombre y su avatar— no
+# depende de wtmp. La alternativa era `touch` ese fichero en el sandbox para que el chequeo pasara,
+# que es hacer verdadera una premisa falsa; preferible borrar el chequeo y decir por qué.
+#
+# Y un tercer sed saca `subdir('tests')` (:235), que accountsservice no expone como opción. No es por
+# ahorrar tiempo de build: los tests arrastran el subproyecto `mocklibc`, que llama `fgetgrent()` —
+# una extensión GNU que **musl no implementa**. No hay forma de compilarlo acá, y lo que se pierde es
+# la suite del upstream, no la librería.
+#
+# El sed saca `subdir('po')`. QUINTA vez que el msgfmt de gettext-tiny obliga a esto (iso-codes, gcr,
+# eds, gnome-shell y ahora ésta). Ya no es un gotcha: es la deuda de autorar el gettext de GNU.
+#
+# ISLA DINÁMICA: -Dintrospection=true + shared, porque lo que falta es justamente el TYPELIB.
+#
+# ══ ⛔ NO SELLA TODAVÍA — FRONTERA MEDIDA, NO ADIVINADA (2026-07-29) ═════════════════════════════
+# El configure pasa entero (los tres seds y las opciones de arriba están verificados contra el build
+# real); lo que corta es el COMPILE, y por dos motivos independientes:
+#
+# 1. LA C-ABI DE sd-login SE QUEDA CORTA. `libelogind` (arje-sdlogin-compat) exporta 14 símbolos —
+#    los que necesitaba mutter— y accountsservice usa OCHO que no están:
+#      sd_get_sessions · sd_seat_can_multi_session · sd_session_get_display
+#      sd_login_monitor (el tipo) · sd_login_monitor_new · sd_login_monitor_unref
+#      sd_login_monitor_get_fd · sd_login_monitor_flush
+#    Los cinco de `sd_login_monitor_*` son la parte con enjundia: no son getters sobre ficheros sino
+#    una API de NOTIFICACIÓN (un fd que se puede meter en un poll y despierta cuando cambia el
+#    estado de sesiones). Sobre el diseño actual —leer /run/systemd/{sessions,seats,users}— el
+#    camino natural es un inotify sobre esos directorios.
+#
+# 2. `fgetspent_r` NO EXISTE EN musl. Es la variante reentrante de la API de /etc/shadow, extensión
+#    de glibc. La usa src/daemon.c:265 para saber si una cuenta tiene contraseña. Necesita un shim
+#    o un parche que use la variante no-reentrante.
+#
+# NINGUNO DE LOS DOS es de accountsservice: son huecos de NUESTRA capa de compatibilidad. La receta
+# queda como mapa honesto de la cadena —el mismo criterio que gnome-session y gnome-settings-daemon
+# en esta cola—, con la frontera contada símbolo por símbolo en vez de estimada.
+#
+# CÓMO SE DESTAPÓ, y es la lección de método: gnome-shell selló con su cierre de build COMPLETO
+# (108/108) y aun así la sesión murió pidiendo este typelib. **El cierre de build no es el cierre de
+# runtime**: todo lo que el shell carga por `imports.gi.*` desde JavaScript es invisible al grafo de
+# deps. Se encuentra arrancando, no compilando.
+name    = "accountsservice"
+version = "23.13.9"
+
+[source]
+tarball = "https://www.freedesktop.org/software/accountsservice/accountsservice-23.13.9.tar.xz"
+sha256  = "adda4cdeae24fa0992e7df3ffff9effa7090be3ac233a3edfdf69d5a9c9b924f"
+
+[build]
+compiler = "zig-cc"
+target   = "x86_64-linux-musl"
+link     = "dynamic"
+
+[build.phases]
+configure = "printf '#!/bin/sh\\necho 23.13.9\\n' > generate-version.sh && sed -i \"/^subdir('po')$/d\" meson.build && sed -i '/Do not know which filename to watch for wtmp changes/d' meson.build && sed -i \"/^subdir('tests')$/d\" meson.build && PKG_CONFIG_PATH=/usr/lib/pkgconfig PYTHONPATH=/usr/lib/python3.12/site-packages meson setup output --prefix=/usr --buildtype=release --wrap-mode=nodownload -Ddefault_library=shared -Delogind=true -Dintrospection=true -Dvapi=false -Ddocbook=false -Dgtk_doc=false -Dsystemdsystemunitdir=no -Dc_args=-Wno-error=date-time"
+compile   = "PYTHONPATH=/usr/lib/python3.12/site-packages ninja -C output"
+install   = "PYTHONPATH=/usr/lib/python3.12/site-packages DESTDIR=/out meson install -C output --no-rebuild"
+
+[deps]
+build = ["meson", "samurai", "python3", "pkgconf", "gettext-tiny", "py3-setuptools", "gi-foreign-girs", "gobject-introspection", "glib", "glib-introspected", "polkit", "dbus-shared", "libelogind", "libffi", "pcre2", "zlib-shared", "expat"]
diff --git a/scripts/gnome/gnome-start-qemu.sh b/scripts/gnome/gnome-start-qemu.sh
index 5182ee60..4102caca 100755
--- a/scripts/gnome/gnome-start-qemu.sh
+++ b/scripts/gnome/gnome-start-qemu.sh
@@ -13,6 +13,8 @@
 set -u
 # getty ejecuta este script DIRECTO ⇒ PATH viene vacío. Primero eso, antes de invocar nada.
 export PATH=/usr/bin:/bin:/usr/sbin:/sbin
+# El modo lo hornea la imagen (GNOME_MODE=... en scripts/gnome/qemu-desktop-image.sh).
+[ -r /etc/gnome-mode ] && . /etc/gnome-mode
 say() { echo "== gnome-qemu :: $*" | tee -a /dev/console /dev/ttyS0 2>/dev/null; }
 dump() { echo "---- $1 ----" > /dev/ttyS0 2>/dev/null; cat "$1" > /dev/ttyS0 2>/dev/null; }
 
@@ -177,8 +179,17 @@ if [ "${DIAG:-1}" = 1 ]; then
 fi
 
 say "typelibs visibles: $(ls /usr/lib/girepository-1.0/*.typelib 2>/dev/null | wc -l) sistema + $(ls /usr/lib/gnome-shell/*.typelib 2>/dev/null | wc -l) del shell"
-say "lanzando gnome-shell --wayland (DRM virtio, software GL)..."
-/usr/bin/gnome-shell --wayland >/tmp/gnome-shell.log 2>&1 &
+# GNOME_MODE=headless — EXPERIMENTO DECISIVO, no un modo de producción. El backend headless de
+# mutter crea el seat con META_SEAT_NATIVE_FLAG_NO_LIBINPUT, o sea que SALTEA `init_libinput()`,
+# que es justo el último paso del hilo de input antes de señalar `input_thread_initialized`
+# (meta-seat-impl.c:3098). Si en headless aparece wayland-0, el bloqueo está en libinput/udev y no
+# en el resto del arranque; si tampoco aparece, el problema es anterior (keymap, input settings).
+case "${GNOME_MODE:-drm}" in
+  headless) SHELL_ARGS="--headless --virtual-monitor 1280x800" ;;
+  *)        SHELL_ARGS="--wayland" ;;
+esac
+say "lanzando gnome-shell $SHELL_ARGS (modo=${GNOME_MODE:-drm})..."
+/usr/bin/gnome-shell $SHELL_ARGS >/tmp/gnome-shell.log 2>&1 &
 SHELL_PID=$!
 # stream EN VIVO al serial (busybox sed no soporta -u ⇒ tail -f directo, sin pipes).
 ( echo "==== gnome-shell.log (stream vivo) ===="; tail -f /tmp/gnome-shell.log ) > /dev/ttyS0 2>/dev/null &
diff --git a/scripts/gnome/qemu-desktop-image.sh b/scripts/gnome/qemu-desktop-image.sh
index 268008f4..ce440c4d 100755
--- a/scripts/gnome/qemu-desktop-image.sh
+++ b/scripts/gnome/qemu-desktop-image.sh
@@ -138,6 +138,10 @@ for f in passwd:messagebus:x:81:81:messagebus:/dev/null:/sbin/nologin group:mess
   fi
 done
 
+# GNOME_MODE se hornea como fichero: el getty ejecuta gnome-start sin ambiente heredable.
+printf 'GNOME_MODE=%s\n' "${GNOME_MODE:-drm}" > "$MERGED/etc/gnome-mode"
+echo "==> modo de arranque: ${GNOME_MODE:-drm}"
+
 echo "==> instalando /usr/bin/gnome-start"
 install -Dm755 scripts/gnome/gnome-start-qemu.sh "$MERGED/usr/bin/gnome-start"