docs/evidencia/gnome-shell-qemu-2026-07-29.png: el conmutador de espacios de trabajo,
el reloj en el panel, la miniatura del escritorio, el dash, y la notificación estándar
de GNOME por sesión de root. Todo construido desde fuente sobre el kernel de hammer,
arje-zero como PID1 y musl.
**EL MURO NO ERA DE KMS.** El diagnóstico anterior culpaba al plano primario de
virtio-gpu («no advertised formats», sólo `Queue mode set`, ningún page flip). Era
correlación. Se probó quitando MUTTER_DEBUG_FORCE_KMS_MODE=simple —el log pasó a decir
`using atomic mode setting`, o sea que el cambio SÍ tomó efecto— y la pantalla siguió
con exactamente 2 colores. Refutada. Mutter no tenía un frame que presentar; no es que
no supiera presentarlo.
La causa estaba en el stack trace, en el log, desde el principio: la excepción por el
gschema `org.gnome.settings-daemon.peripherals.touchscreen` ocurre DENTRO de
`Main.start()`, construyendo los quick settings ⇒ el panel nunca se arma. Proceso vivo,
compositor con DRM master, nada que pintar.
Receta `gsd-schemas`: los gschemas de gnome-settings-daemon SIN g-s-d, que sigue
aparcada por GTK3/X11. **Tercera vez que aparece la misma lección** (tras la política
D-Bus de login1 y el `org.gnome.login-screen` de libgdm): un gschema no es un fichero de
datos del demonio, es una interfaz publicada que consume otro programa.
Dos trampas de diagnóstico, las dos ahora blindadas:
- **`glib-compile-schemas` sale con 0 aunque RECHACE un esquema.** Instalé los once XML,
el log dijo `esquemas OK` y el shell seguía diciendo `not found`: faltaba
`org.gnome.settings-daemon.enums.xml`, que meson genera con glib-mkenums y no es uno
de los `.in`. Sin los `<enum>`, glib descarta el esquema entero, avisa por stderr y
sigue. `gnome-start` ahora vuelca ese stderr SIEMPRE, no sólo al fallar.
- El log serial persiste entre arranques y me hizo leer dos veces un `STATUS +30s` de una
VM ya muerta. Truncarlo antes de arrancar; `Failed to get "write" lock` avisa de que
hay otro QEMU con el disco tomado.
Y queda escrito cómo validar CON PANTALLA sin humano delante: screendump por el monitor
de QEMU, con una métrica barata previa a mirar — contar colores distintos. Negro = 2;
pintando = 582, con el azul GNOME (2,60,136) al frente.
Lo que falta son detalles, ninguno impide el escritorio: lanzar upowerd desde gnome-start,
un tema de cursor, el setuid de colord y gnome-control-center.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Estado: gnome-shell corre 5 minutos sobre DRM real sin una sola JS ERROR, y la
captura del framebuffer muestra la consola del kernel en negro. Mutter nunca
presentó un frame.
La pista del log de KMS es concreta: el plano primario 33 de virtio-gpu 'has no
advertised formats' y sólo hay 'Queue mode set' — ningún page flip. Tres hipótesis
de una variable cada una, la primera es quitar MUTTER_DEBUG_FORCE_KMS_MODE=simple,
que se heredó de la campaña KDE (donde el que fallaba con atomic era kwin).
Queda además escrito CÓMO validar con pantalla sin humano delante: screendump por
el monitor de QEMU + PPM→PNG. Aplicar esa regla es lo que destapó este muro — el
serial decía 'sesión viva'.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
== gnome-qemu :: compositor OK (wayland-0) — el shell ES el display server
== gnome-qemu :: STATUS +15s … +315s: gnome-shell=2
Sin una sola `JS ERROR`. gnome-shell corre 5 minutos seguidos sobre DRM real.
Dos cierres, los dos por auditar en vez de adivinar:
1. GL-1.0 y libxml2-2.0 sumados a gi-foreign-typelibs. La primera auditoría de
`<include>` la hice sólo sobre los girs de /usr/share/gir-1.0 y me faltaron los que
entran por los girs PRIVADOS de mutter (Clutter-16, Cogl-16 → GL-1.0, o sea que sin
él no carga `Meta`: el compositor entero) y por los de eds (Camel, EBook,
EDataServer → libxml2-2.0). Un ciclo de imagen+arranque perdido por auditar de menos.
La forma correcta —y ahora escrita en la receta— es cruzar los `<include>` de TODOS
los .gir del rootfs hidratado contra los typelibs presentes. Queda un solo huérfano,
`xlib-2.0`, que sólo incluye `xft-2.0`, a quien no incluye nadie: no es una falta.
2. libgdm vuelve a construir su `data/`. La había borrado entera por parecer «cosas del
greeter», y ahí vive el gschema **org.gnome.login-screen**, que gnome-shell lee al
arrancar: sin él muere con `Gio.IOErrorEnum: GSettings schema ... not found`. Un
esquema de GSettings no es un fichero de datos del demonio — es una interfaz publicada
que consume otro programa. Se borra sólo `subdir('dconf')`, la única pieza que necesita
el binario `dconf`.
Lo que queda son avisos, no muros: falta un tema de cursor, colord no arranca por el
setuid del helper, y `org.gnome.settings-daemon.peripherals.touchscreen` no existe
porque g-s-d está aparcada (rompe quick-settings, no la sesión).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Con los siete de `dependencies.js` cerrados, el arranque avanzó y murió en uno que NO
está en esa lista:
JS ERROR: Requiring GIRepository, version 2.0: Typelib file ... not found
El que lo pide es **gjs**, desde su propio JavaScript embebido: su GResource trae
literalmente `imports.gi.versions.GIRepository = '2.0';` (verificado con strings sobre
libgjs.so.0). Dep de runtime del INTÉRPRETE — invisible al grafo de build Y a la lista
del shell. O sea que `dependencies.js` es necesario pero no suficiente: hay una capa
más abajo.
HAY DOS GIRepository Y NO SON LO MISMO, y los números confunden a propósito:
· GIRepository-3.0 = la API NUEVA, la que GLib absorbió (libgirepository-2.0). La
produce glib-introspected y ya estaba.
· GIRepository-2.0 = la API VIEJA, la de libgirepository-1.0.so.1, contra la que gjs
está enlazado. La produce gobject-introspection, pero sólo con
-Dbuild_introspection_data=true, y el nuestro va con false.
La 2.0 es la vieja porque nombra la librería 1.0; la 3.0 es la nueva porque nombra la 2.0.
Receta aparte en vez de prenderle la opción a g-i: su radio alcanza toda la cadena GNOME
(catorce recetas la declaran para escanear) y además traería de vuelta los typelibs de
X11/cairo que motivaron apagarla. Acá el radio es cero.
Replica el custom_target('gir-girepository') de upstream (gir/meson.build:494) pero
escaneando contra la libgirepository-1.0 ya instalada. **La lista de fuentes va enumerada
a mano y no como glob**, y no es prolijidad: `girepository/*.h` barre también
`gitypelib-internal.h`, que declara G_TYPELIB_ERROR; el scanner emite entonces el stanza
del error-quark y su binario temporal no linkea, porque `g_typelib_error_quark` es LOCAL
en la .so instalada. Upstream nunca lo escanea — el glob era el error.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Rsvg-2.0 librsvg b3:351f4658
IBus-1.0 ibus b3:d4d3750a
**1. PERILLA NUEVA DEL LAB: `[source] cargo_vendor`.** `detect_build_system` asume UN
sistema de build por árbol, y librsvg genuinamente tiene dos: `configure.ac` gana por
precedencia pero su Makefile llama a `cargo build`, que dentro del sandbox hermético
no tiene red. La perilla fuerza el vendoreo (que ocurre en el fetch, donde sí hay red)
sin tocar la detección. **No entra al ArtifactHash** —decide de dónde salen las deps,
no cuáles: eso lo fija el Cargo.lock, ya bajo el sha256 de la fuente— así que se puede
prender en una receta ya sellada sin re-hashear nada. Con test, y verificado en vivo:
libelogind no movió su hash tras el cambio.
**2. LA DEUDA DEL UNWINDER, PAGADA.** librsvg moría en
`undefined reference: _Unwind_DeleteException`. No es de librsvg: es de la `std` de
rustc, que trae landing pads y espera el runtime que en glibc vive en libgcc_s. Es la
deuda que el corpus arrastra desde matar-gcc —«las 12 recetas Rust son UN problema, no
12»— y el remedio estaba a mano: **zig empaqueta la libunwind de LLVM** y exporta los
`_Unwind_*` (verificado con nm). Alcanza `LIBS=-lunwind`. Va por LIBS y no por LDFLAGS
porque autotools pone LIBS al FINAL de la línea de enlace, que es donde tiene que ir
una librería que resuelve símbolos indefinidos.
librsvg va en 2.58.5 y no 2.59+: en 2.59 cambió a meson + cargo-c, y cargo-cbuild
enlaza el crate `cargo` entero (libgit2, libssh2, libcurl, openssl) — una campaña
propia por un binario que sólo corre en el constructor. 2.58.5 produce el mismo
Rsvg-2.0. Mismo criterio que gnome-desktop 44.5.
**3. `x11-compose-data`, y es una tensión que vale la pena tener escrita.** ibus COMPILA
la tabla de teclas muertas de X11 dentro de libibus (Makefile.am:310, incondicional, sin
`--disable-`). Sin datos no construye. Los datos viven en el tarball de libX11 por
historia, no por necesidad técnica: son 5192 líneas de reglas. La receta extrae SÓLO los
ficheros de locale reproduciendo la regla de upstream (`cpprules.in`: cpp crudo +
CPP_SED_MAGIC literal) y no compila una línea de X11. Un escritorio Wayland-only sigue
necesitando la tabla de composición del mundo Unix.
Gotchas de ibus, los tres medidos: su ayuda MIENTE (`--enable-gtk4`/`--enable-wayland`
sugieren default apagado; el default es `yes`); `--disable-emoji-dict` NO apaga
`--disable-unicode-dict`; y con `--disable-wayland` el build muere igual porque
`tools/main.c` llama wl_display_* sin `#ifdef` mientras WAYLAND_LIBS sólo se agrega si
la opción está prendida — bug de upstream en su propia configuración sin Wayland.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
De los siete que faltaban quedan dos (Rsvg, IBus). Cerrados acá:
GnomeDesktop-4.0 + GnomeBG-4.0 gnome-desktop b3:b3aed0d6
UPowerGlib-1.0 upower b3:95d1081a
Geoclue-2.0 geoclue b3:50e9de94
GWeather-4.0 libgweather b3:d289ac66
gnome-desktop NO se duplicó en una variante `-introspected`, y la razón es la regla de
los dos registros de GType: mutter y gnome-shell ENLAZAN libgnome-desktop y gjs además
dlopearía la .so del typelib ⇒ convivirían la .a enlazada y la .so cargada, cada una
con su tabla. Es el cuadro que costó el episodio de colord. `yupana radio` = 2 sellados
a deuda (mutter, gnome-shell), el mismo par de siempre. Con introspección encendida los
dos seds que borraban `libgnome_rr_gir`/`libgnome_bg_gir` dejan de hacer falta.
Su cierre tuvo que pasar a las variantes `-shared`, y no por prolijidad: con `libpng`
estática no hay libpng16.so, `libgdk_pixbuf-2.0.so.0` no relocaliza y el `ldd` con que
g-ir-scanner resuelve las shlibs sale con 127. **Si una receta introspecta, su cierre
entero tiene que ser CARGABLE** — el scanner compila y ejecuta un binario de verdad.
Dos recetas entraron por transitividad, no por la lista del shell:
- geocode-glib (b3:f24e4147), que pide libgweather. Su `-Dsoup2=false` es LA opción:
con el default se construye `geocode-glib-1.0` contra libsoup2 —que esta distro no
tiene— y libgweather no la encuentra aunque esté instalada.
- py3-gobject/pygobject (b3:492930f2), y ésta ni siquiera va a la imagen: va al
CONSTRUCTOR. `gen_locations_variant.py` de libgweather importa gi.repository.GLib
para serializar la base de ciudades a un GVariant binario. El formato lo define GLib.
Decisiones de alcance escritas en cada receta: geoclue va SIN demonio
(-Denable-backend=false evita ModemManager, Avahi y libsoup; la librería cliente habla
por D-Bus), upower sin libimobiledevice, y libgweather sin `po-locations` ⇒ las ciudades
salen en inglés, la base de datos se genera igual.
De upower, tres perillas que hay que fijar porque su `auto` significa "preguntale a un
pkg-config de systemd": udevrulesdir/udevhwdbdir (nuestro udev-pc declara `udevdir`, no
`udev_dir`) y systemdsystemunitdir=no.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Venía cerrando typelibs de a uno: AccountsService → DBus-1.0 → cairo-1.0 → Gdm-1.0,
un rebuild de imagen y un arranque completo por cada uno. Cuatro rondas para
descubrir que la lista estaba escrita todo el tiempo.
`js/misc/dependencies.js` de gnome-shell ENUMERA lo que el shell exige al arrancar.
Cruzada contra el rootfs hidratado, la frontera completa es exacta:
GnomeDesktop-4.0 + GnomeBG-4.0 → gnome-desktop (YA sellada, pero -Dintrospection=false
y estática ⇒ falta la variante de isla dinámica)
Geoclue-2.0 → geoclue (sin receta)
GWeather-4.0 → libgweather (sin receta)
IBus-1.0 → ibus (sin receta)
Rsvg-2.0 → librsvg (sin receta; es Rust)
UPowerGlib-1.0 → upower (sin receta)
Los otros veinte de la lista ya están. GnomeBluetooth, NM/NMA4 y Malcontent son
condicionales y no bloquean.
REGLA, y es el precio de no haberla aplicado antes: cuando el muro es `Requiring X`,
no cierres X y vuelvas a arrancar — leé el fichero donde el programa DECLARA sus deps
de runtime y cerralas todas de una.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Dos rondas del mismo patrón, las dos destapadas ARRANCANDO:
1. `Requiring Gdk 4.0: Typelib 'cairo' 1.0 not found` ⇒ cairo-1.0 sumado a
gi-foreign-typelibs. Necesita el mismo sed que gi-foreign-girs (viene como .gir.in
con dos placeholders), para compilar EXACTAMENTE el XML que está instalado: si
divergieran, el typelib describiría otra librería. NO segfaultea g-ir-compiler — el
crash que motivó -Dbuild_introspection_data=false era del g-i de antes de la isla
dinámica. La lista de cinco no se adivinó: sale de leer los <include> de TODOS los
.gir del cierre y cruzarlos contra los typelibs existentes.
2. `Requiring Gdm 1.0` ⇒ receta `libgdm`, SÓLO la librería cliente. gnome-shell la
importa sin condicional (js/misc/dependencies.js:12), o sea que **la librería
cliente de GDM es dep de runtime del SHELL, no del greeter** — y eso no se ve en
ningún meson.build. `gdm.toml` (el demonio entero) sigue aparcada por linux-pam,
pero PAM es del DEMONIO: libgdm/ no lo toca. La receta corta por ahí; cuando exista
linux-pam las dos conviven.
Para que libgdm compilara hicieron falta tres símbolos más en libelogind
(tawasuyu 9bf977a52, re-pineado a 98db584fd, re-sellado b3:c1fc4bd8):
sd_seat_get_sessions, sd_session_get_service y **sd_booted**, éste en una cabecera
nueva systemd/sd-daemon.h. sd_booted NO es un stub que devuelve 0: comprueba lo mismo
que systemd —que exista /run/systemd/system/— y bajo arje no está, así que responde 0
porque ES 0.
gnome-shell re-sellado b3:b2d5919b por la cascada.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Con accountsservice adentro, la capa JS avanzó y murió un paso después:
JS ERROR: Requiring Atspi, version 2.0: Typelib file for namespace 'DBus', version '1.0' not found
`Atspi-2.0.gir` declara `<include name="DBus" version="1.0"/>`. El `DBus-1.0.gir` YA estaba en
/usr/share/gir-1.0 (lo pone gi-foreign-girs), pero gjs resuelve en runtime contra el TYPELIB
compilado, no contra el XML — el XML le alcanza al scanner, no al cargador.
Receta aparte y no un compile agregado a gi-foreign-girs porque `yupana radio` da **17 sellados
cayendo a deuda** ahí (catorce recetas la declaran para escanear, mutter y gnome-shell entre ellas).
Compilar cuatro typelibs no justifica reconstruir la cima. No se pisan: una instala sólo en gir-1.0
y la otra sólo en girepository-1.0. Mismo criterio que separó udev-pc de libudev-zero.
Se compilan CUATRO nombrados explícitamente —DBus-1.0, DBusGLib-1.0, fontconfig-2.0, freetype2-2.0—
y no un glob: los .gir de X11 y cairo arrastran includes que no tenemos y son justamente los que
hacían SIGSEGV a g-ir-compiler (la razón de nuestro -Dbuild_introspection_data=false).
Además: gnome-start lanza accounts-daemon explícito. Su .service de activación está instalado, pero
la activación por bus de sistema pasa por dbus-daemon-launch-helper, que acá no es setuid root;
correr como root probablemente alcanzaría, pero depender de eso es depender de un accidente.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Los dos huecos que bloqueaban esta receta estaban medidos desde ayer símbolo por
símbolo, y ninguno era de accountsservice. Los dos cerrados:
1. libelogind pasa de 14 a 22 símbolos (tawasuyu 8d892151b, re-pineado a b56aeff46,
re-sellado b3:9650ee06). Los ocho nuevos son los que usa accountsservice, con
`sd_login_monitor_*` implementado sobre inotify en /run/systemd/{sessions,seats,users}.
2. `fgetspent_r` no existe en musl ⇒ accountsservice-fgetspent_r-musl.patch. NO es
sustituir por `fgetspent()` a secas: daemon.c guarda los buffers en un GHashTable
y `fgetspent()` devuelve un struct estático que se reescribe en cada llamada —
todas las entradas de la tabla apuntarían al último usuario leído. El parche copia
el registro al buffer del llamador, y sigue el patrón que el propio accountsservice
ya usa para /etc/passwd (`src/fgetpwent.c` bajo `#ifndef HAVE_FGETPWENT`).
Produce `AccountsService-1.0.typelib`, que es exactamente lo que la capa JS pedía.
De paso, dos cosas que este frente enseñó y quedan horneadas:
- libelogind necesitaba `cargo_vendor_dir` (el `vendor/` de smithay entró a la rama
selfhost con el merge de main; el mismo choque que ya tenía arje-logind-compat).
- `hydrate-gnome.sh` ahora hidrata DOS raíces por defecto. accountsservice no es dep
de build de nadie: es dep de RUNTIME, resuelta por gjs al arrancar. **El cierre de
build no es el cierre de runtime**, y lo que el shell carga por `imports.gi.*` hay
que nombrarlo a mano o no entra al rootfs.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Con el `O_NONBLOCK` de TakeDevice (tawasuyu 3dd88f582, receta re-sellada
b3:7ffa9256), gnome-shell arranca en QEMU sobre el backend nativo KMS, no headless:
BACKEND: Opening and taking control of device file '/dev/input/event0' (y event2, event1)
BACKEND: Realizing stage 'MetaStageNative'
KMS: Plane 33 … primary for CRTC 37 · Plane 34 … cursor
Using Wayland display name 'wayland-0'
== gnome-qemu :: compositor OK (wayland-0) — el shell ES el display server
El muro gráfico que este runbook anunciaba como «el que viene después» NUNCA
APARECIÓ: los fixes que pagó la campaña KDE y quedaron precargados en
gnome-start-qemu.sh alcanzaron tal cual. mutter crea el renderer gbm y elige card0
como primaria sin quejarse.
Queda un solo muro, y no es un cuelgue: el shell sale con código 1 en
`Requiring AccountsService` — una dep de RUNTIME que la receta ya tiene medida
símbolo por símbolo.
El runbook además CORRIGE su propio diagnóstico anterior (culpaba a libudev-zero) y
deja escrito cómo se refutó, que es lo reusable: una sonda que hace lo mismo que el
código sospechado pero por otro camino, y /proc por hilo ANTES de abortar —porque
gdb no desenrolla a través de musl y el core sólo da `?? ()`.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Tres cambios de diagnóstico en `gnome-start` que, juntos, dieron el veredicto:
1. SONDA DE INPUT antes de lanzar el shell. `libinput list-devices` hace lo mismo
que `init_libinput()` de mutter (udev_new + create_context + assign_seat) pero
abriendo el devnode por su cuenta. Volvió con rc=0 y los tres dispositivos
listados ⇒ **la hipótesis libudev-zero del runbook queda REFUTADA**: la
enumeración por /sys funciona.
2. El volcado POR HILO corría DESPUÉS del `kill -ABRT`, o sea sobre un
/proc/<pid>/task que ya no existía: salía vacío. Movido antes. Ahí apareció el
dato: `tid 201 [Mutter Input Th] wchan=evdev_read syscall=0`. El hilo de input
dormido en un `read()` de evdev dentro del kernel. (El core no servía: gdb no
desenrolla a través de musl y devuelve `?? ()` para los 11 hilos no principales.)
3. `MUTTER_DEBUG` es una LISTA DE TÓPICOS (g_parse_debug_string sobre
meta_debug_keys), no un booleano: con `1` no encendía nada. Ahora
`backend,input,kms`, y el tópico `backend` imprime la última línea antes del
cuelgue: «Opening and taking control of device file '/dev/input/event0'».
Más: ping D-Bus a login1 en el diagnóstico (el daemon respondía: no estaba
tildado) y copia de los logs de /tmp —que es tmpfs— a la raíz ext4 para poder
sacarlos con debugfs junto al core.
La causa está arreglada en tawasuyu (3dd88f582): `TakeDevice` abría sin
`O_NONBLOCK`. Receta re-pineada a 2445fa31c y re-sellada b3:7ffa9256.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Los dos arreglos de arje-logind-compat (sesión eager + object path de Session
escapado como systemd) están commiteados y pusheados en tawasuyu, así que la
imagen ya NO corre un binario compilado a mano: corre el artefacto sellado, y se
verificó que da EXACTAMENTE el mismo resultado (mismo `Added virtual monitor
Meta-0` → `Using Wayland display name 'wayland-0'` → mismo muro en el typelib de
AccountsService).
El pin va a la rama selfhost, no a main: esa rama existe para que hammer pueda
construir con --locked de forma hermética (el monorepo gitignora el Cargo.lock).
Estaba MUY atrás — el artefacto viejo ni siquiera tenía el objeto Session que
mutter necesita —, así que se le mergeó main y se regeneró el Cargo.lock, que con
main al día había quedado viejo y habría hecho fallar el --locked.
Y ahí apareció una colisión ya conocida pero no aplicada acá: el monorepo COMMITEA
su propio `vendor/` (`[patch.crates-io] smithay = { path = "vendor/smithay" }`, la
copia parcheada que mirada usa para el tearing) y `cargo vendor` de hammer escribe
en `vendor/` por defecto, pisándolo. El build moría con
`failed to read /src/vendor/smithay/.cargo-checksum.json`. Se resuelve con el
campo que ya existía para esto: cargo_vendor_dir = ".hammer-cargo-vendor".
De paso, el script de imagen elige el artefacto por `hammer hash` sobre la receta
—el que corresponde a la receta de HOY— en vez de por el más reciente del store:
con dos artefactos del mismo paquete conviviendo, la fecha no dice cuál es el
vigente. Mismo criterio que hydrate-gnome.sh.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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>
Dos bugs REALES de arje-logind-compat, encontrados arrancando la imagen y
arreglados (con test) en el árbol de tawasuyu — todavía LOCALES, sin pushear:
1. La sesión se creaba PEREZOSAMENTE. `ensure_user` sólo corría dentro de un
método del Manager, y `write_login_state` vive adentro. Pero mutter no
empieza por D-Bus: lo primero que hace es sd_pid_get_session(), que
arje-sdlogin-compat resuelve LEYENDO /run/systemd/sessions. Huevo y gallina:
el estado en disco sólo se escribía después de un pedido que sólo ocurre si
el estado ya existe. Ahora se crea al arrancar (eager_session).
2. El object path de la Session estaba MAL ESCAPADO: era `/session/_1`. La
convención de systemd (bus_label_escape) codifica `_<hex>` todo lo que no sea
[A-Za-z0-9] **y también el primer carácter si es dígito** ⇒ el id "1" da
`_31`. Importa porque el cliente calcula el path por su cuenta y NO pregunta:
mutter reimplementa la misma regla en meta-dbus-utils.c. Con `_1` no había
nadie sirviendo ahí, la propiedad `Seat` volvía NULL y mutter —que no
chequea— moría de SIGSEGV en get_seat_proxy. Los objetos User NO usan este
escapado (systemd hardcodea `_<uid>`), así que user_path() queda igual.
Y ARJE_LOGIN_STATE=1 YA EXISTÍA: el comentario del daemon dice literalmente "en
arje (sin systemd) el launcher de sesión lo prende. Default off" — y el launcher
es gnome-start. El puente que escribía /run/systemd/ a mano era reinventar esa
perilla; queda de fallback inerte.
Resultado: el shell ya no crashea. Corre con 12 hilos, /dev/dri/card0 abierto
tres veces y /dev/input/event0 abierto — el TakeDevice de logind funciona y el
compositor tiene DRM master e input. Queda bloqueado en
meta_seat_impl_initable_init (meta-seat-impl.c:3154): espera en un condvar a que
la "Mutter Input Thread" avise que inicializó, y nunca avisa. Hipótesis principal
libudev-zero, que ya dio un episodio idéntico en el frente de la USB nvidia.
El gnome-start ahora le fuerza un core con SIGABRT al proceso colgado: sin gdb en
la imagen es la única forma de ver dónde está parado.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Corrige el commit anterior, donde quedó `shared`. Con shared-only sus otros dos
consumidores —libgusb y colord, que siguen siendo estáticos— cortaron pidiendo
`libjson-glib-1.0.a`. `both` deja la .so que necesita el g-ir-scanner y la .a que
necesitan ellos, sin obligar a de-estatizar media cola. Es el mismo fix que
destrabó glib en su momento.
Cascada re-sellada contra este hash: mutter (b3:a90e6bae), libgusb, colord y
evolution-data-server (b3:28368c7a).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
gnome-shell bootea, compila sus esquemas, toma el DRM de virtio-gpu y se declara
Wayland display server. Después SIGSEGV. El backtrace del core no deja dudas:
#4 g_variant_get (value=0x0, "(s&o)") ← GVariant NULO
#5 get_seat_proxy src/backends/meta-launcher.c:407
#6 meta_launcher_new (META_LAUNCHER_FLAG_TAKE_CONTROL)
Mutter pide la propiedad `Seat` del objeto **Session** de logind — `(s&o)` es su
firma estándar (nombre_del_seat, object_path). arje-logind-compat adquiere
org.freedesktop.login1 y sirve el Manager, pero NO expone un objeto Session con
esa propiedad ⇒ la lectura devuelve NULL y mutter desreferencia sin chequear. Que
mutter no valide es fragilidad suya; el hueco es nuestro.
Cinco eslabones hubo que armar antes de llegar a ese muro, ninguno anotado:
1. gschemas.compiled NO se genera con DESTDIR seteado (meson lo dice en el log
del build) ⇒ GSettings abortaba en el primer g_settings_new().
2. GI_TYPELIB_PATH tiene que incluir /usr/lib/gnome-shell: St/Shell/Gvc/Shew se
instalan aparte por ser privados del shell. Es el env sin análogo en KDE.
3. /var/run no existía en la base metal; arje-logind-compat busca el bus en la
ruta legacy y sin el symlink se iba a "modo idle".
4. La política D-Bus de login1 faltaba (system.conf trae <deny own="*"/> y
normalmente la instala systemd). PERTENECE al artefacto de arje: está en el
script de imagen sólo para dejar visible qué falta empaquetar.
5. /run/systemd/{sessions,seats,users} vacíos — libelogind resuelve la C-ABI
sd-login LEYÉNDOLOS y nadie los escribe (el Announce de arje-logind-compat al
bus del fractal falla con "identity mismatch"). gnome-start los escribe A
MANO y está MARCADO COMO ANDAMIO. Con ese puente desaparece el "Failed to
find any matching session".
Gotcha que costó una iteración: `kill -0` TIENE ÉXITO sobre un zombi (el padre no
lo cosechó todavía), así que el script reportaba "sin wayland-0 tras 45s" cuando
el shell había muerto en el primer segundo. Mirando State: de /proc/<pid>/status
sale el código real, 139.
Todo el ciclo (hidratar → imagen → bootear → sacar el core con debugfs → gdb) y
la lista de lo que falta quedan en docs/runbooks/gnome-qemu-desktop.md.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Proyecta al FHS el cierre de una receta GNOME desde artefactos SELLADOS, sin
rebuild. Resultado sobre gnome-shell: **108 recetas, 0 faltantes** — 614
binarios, 455 .so, 49 typelibs.
Diferencia con scripts/kde/hydrate-from-store.sh, y por qué importa: aquél
resuelve el cierre desde un index.json de repo y elige el artefacto por MTIME con
un CUTOFF. Eso es una heurística — si dos artefactos del mismo paquete conviven
en el store, la fecha no dice cuál corresponde a la receta VIGENTE. Acá el cierre
sale del GRAFO REAL de recetas (deps.build, resolución hermano→padre, la misma
que usa hammer) y el artefacto se elige por `hammer hash`. Cero ambigüedad, y si
falta algo el reporte dice qué receta y con qué hash lo buscaba.
Auditado además el cierre DINÁMICO del rootfs (452 ELF, 104 librerías NEEDED).
Sin resolver quedan cuatro, y sólo dos son hallazgos:
libc.so 359 consumidores — es el propio musl (en musl el loader
ES libc); lo aporta la base metal, no es hueco.
libc.musl-x86_64.so.1 17 artefactos (nss + spidermonkey) piden ESTE soname en
vez de libc.so. Es la MISMA libc: los construidos con el
gcc/clang de Alpine emiten un soname distinto al de
zig-cc. No rompe si el rootfs trae los dos nombres, pero
es una fisura de consistencia a documentar.
libstdc++.so.6 + SÓLO libmozjs-128.so y js128 ⇒ **la sesión GNOME arrastra
libgcc_s.so.1 el runtime C++ de Alpine por la cadena
gnome-shell → libgjs → libmozjs**. Es exactamente la
"última milla" de matar-gcc que se cerró para cmake con
-static-libstdc++ y que spidermonkey no cubrió. Radio
medido: 2 sellados (gjs, gnome-shell). Pendiente, y
conviene en el worker: el compile de mozjs come ~8GB+.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
El grafo cierra y el topo-sort da OK con las 13 recetas de la cadena
eds/nss/pulseaudio incorporadas.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
/usr/bin/gnome-shell construido desde fuente, con sus cuatro typelibs (St-16,
Shell-16, Gvc-1.0, Shew-0) y el NEEDED cerrando en artefactos sellados + libc.so:
cero fuga al sysroot de Alpine.
El draft estimaba "~10 recetas nuevas, dominadas por eds+icu". Fueron 13, pero
casi ninguna donde el mapa las esperaba. Lo que la última tanda destapó:
dbus-shared la cima enlaza atk-bridge-2.0, cuyo .pc Requires atspi-2 y ése
dbus-1 — el dbus canónico es estático no-PIC y el configure ni
llegaba a compilar. Cuarta variante -shared de la cadena, todas
por la misma raíz: el corpus se construyó para un userland
ESTÁTICO y el escritorio es dinámico por obligación.
pulseaudio la frontera llegó por el camino más indirecto de la campaña:
+ libsndfile gnome-shell incluye el subproyecto gvc (el control de volumen)
SIN condicional (meson.build:256) y gvc pide libpulse duro.
Se construye SÓLO EL CLIENTE (-Ddaemon=false): gvc necesita
HABLAR el protocolo, no implementarlo, y el demonio de sonido de
esta distro es una decisión aparte todavía abierta (PulseAudio vs
PipeWire) que construir el daemon habría cerrado de prestado.
libsndfile con --disable-external-libs = una receta, no cinco.
Dos parches al árbol, ambos verificados antes de aplicarse:
· subdir('po') fuera (:324). CUARTA vez que el msgfmt de gettext-tiny aborta
con SIGABRT, acá en po/ar.po; ya pasó en iso-codes, gcr y eds. La deuda está
clara: hace falta el gettext de GNU de verdad.
· los #include <X11/Xlib.h> y <X11/Xatom.h> de src/shell-app-usage.c son
VESTIGIALES — el fichero no usa un solo símbolo de X11. El código X11 real
(el tray XEmbed) SÍ está cerrado por have_x11_client, que sale de mutter y
acá es false. shell-app-usage.c quedó fuera del guard por olvido del upstream.
Y --undefined-version en pulseaudio: usa UN version-script para las tres libs
cliente, así que al enlazar libpulse.so el script nombra símbolos de
libpulse-simple y libpulse-mainloop-glib. GNU ld avisa; lld corta. Mismo flag que
libtiff-shared.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
La cima de GNOME ya no tiene fronteras: gnome-shell exige libecal-2.0 y
libedataserver-1.2 (meson.build:72-73) y el artefacto trae los dos .pc más los
8 typelibs (ECal-2.0, EDataServer-1.2, Camel-1.2, EBook…).
NSS: el atajo que no era. Primero se intentó esquivarla con -DENABLE_SMIME=OFF.
eds declara esa opción y su cabecera promete honrarla, pero en 3.56.2 el guard NO
EXISTE: include(FindSMIME) es incondicional (:303) y el fichero nunca vuelve a
mirar la variable. Se cableó el guard que faltaba y el configure pasó… y el build
cortó igual en el 11%: src/camel/camel.c incluye <nspr.h>/"nss.h"/<ssl.h> SIN
guardar por el #ifdef y hace init/shutdown reales de NSS. ENABLE_SMIME=OFF sólo
compila fuera camel-smime-context.c, no camel. El modo está roto de verdad.
Así que se pagó: nss 3.126 (b3:d0659c9c), y selló A LA PRIMERA pese a coreconf.
La receta absorbe lo que ese build system no da — no hay ./configure, no hay make
install, el OBJDIR lleva la versión del kernel del constructor (se resuelve por
GLOB, no se hornea, o el artefacto dependería del uname del anfitrión), y el
nss.pc se rellena del template. nss_build_all no sirve: reconstruiría NSPR, y el
nuestro ya está sellado desde spidermonkey. Tampoco era deuda huérfana: NSS es la
base criptográfica del frente del navegador.
json-glib dada vuelta a la isla dinámica (b3:9bc69a4b): su .gir es entrada del
.gir de eds. El comentario viejo de la receta había previsto exactamente este
caso. Radio medido con yupana ANTES de tocar: 3 sellados caen a deuda.
El otro hallazgo: eds usa msgfmt DOS veces. Sacar add_subdirectory(po) no alcanza
porque i18n_merge_file (I18n.cmake:19) fusiona traducciones dentro de los .desktop
desde data/. Se reemplaza por `cmake -E copy`, y NO es aproximación: los templates
traen las claves PLANAS y msgfmt --desktop sólo AGREGA variantes Name[xx]=.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Leído el CMakeLists real de evolution-data-server 3.56.2, la frontera de la cima
son cuatro cosas, no una. Estas son tres; la cuarta (NSS) va aparte.
libsecret 0.21.7 b3:b75607c6 CMakeLists:932 la mete en el pkg_check_modules
(DATA_SERVER REQUIRED …) sin perilla, y libedataserver-1.2 es lo que
gnome-shell enlaza. En gcr se la había esquivado con -Dssh_agent=false;
acá no hay cómo: eds guarda ahí las credenciales de correo y calendario.
-Dcrypto=libgcrypt de las tres del combo — gnutls no existe en el corpus
y 'disabled' apagaría el cifrado justo en la pieza que guarda contraseñas.
libxml2-shared b3:87389636 en libical la libxml2 sólo la enlazaba un binario
de build y bastó la .a canónica; en eds entra en cuatro .so reales
(CMakeLists:932,936,937,938) y la .a no es PIC. Mismos patches de CVE que
la canónica: la superficie de seguridad no diverge.
libuuid-shared b3:d42cf850 `uuid` es REQUERIDA (:424). No es un
"util-linux-shared": --disable-all-programs apaga los ~100 binarios y deja
una sola librería. Duplicar la lista de --without-* del canónico para
conseguir un .so de 30 KB sería mantener esa superficie en dos lugares.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
libecal-2.0 (lo que gnome-shell exige en meson.build:72) está construida sobre
libical-glib. Salió a la primera; leer el CMakeLists real ahorró otra receta:
LibXML → la pide ICAL_GLIB, pero SÓLO la enlaza ical-glib-src-generator, un
ejecutable de BUILD que parsea el XML de la API. No entra en ningún
.so ⇒ la libxml2.a canónica (no-PIC) sirve y NO hace falta
libxml2-shared. Segunda receta que se ahorra por leer el build real.
Perl → DURA (:193, sin perilla), y salió gratis: ya estaba promovida desde
que el barrido de harkaq en la granja la destapó como único irreducible.
ICU → opcional (RSCALE), encendida porque icu4c ya estaba paga.
-DUSE_BUILTIN_TZDATA=ON no es cosmético: por defecto libical lee la tzdata del
SISTEMA, o sea que el artefacto quedaría atado al /usr/share/zoneinfo del
constructor y se movería con cada actualización del host. Con la del tarball el
artefacto es autocontenido y entra entero al ArtifactHash. El CMakeLists avisa
"(Careful)" porque esa tabla envejece; es el precio correcto — un store
direccionable por contenido no puede depender del reloj del anfitrión.
Verificado: ICal-3.0.typelib + ICalGLib-3.0.typelib, cierre en sellados + libc.so.
Queda UNA receta para la cima: evolution-data-server.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Segunda pieza de la cadena eds. Leer el meson.build real (y no el mapa de
memoria) corrigió dos cosas del presupuesto:
libxml2 → libsoup 3.x NO la usa (era de la era 2.x, SoupXMLRPC). Se ahorra
una variante -shared que estaba presupuestada.
sqlite3 → DURA, no opcional: meson.build:123-136 termina en dependency()
sin `required:false`. Y el libsqlite3.a canónico NO es PIC, así que
no entra en un .so — mismo muro R_X86_64_32 que frenó a mutter
contra freetype. De ahí sqlite-shared (b3:7aba78e7), hermana de
zlib-shared/cairo-shared, sin tocar la canónica.
El apagado que más compra es -Dtls_check=false: el meson ASSERTEA que exista
glib-networking para TLS, y eso arrastraba gnutls o openssl+p11-kit. Apagar el
CHECK no apaga el TLS — GIO resuelve el backend por módulo en runtime, así que
el día que haya receta de glib-networking basta hidratarla, sin recompilar.
Verificado: Soup-3.0.typelib producido (la isla dinámica lo exige) y el NEEDED
cierra en artefactos sellados + libc.so, sin fuga al sysroot Alpine.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Arranca la última frontera de gnome-shell: evolution-data-server. El comentario
de gnome-shell.toml estimaba ~10 recetas dominadas por icu, pero icu4c YA quedó
sellada por la campaña KDE (b3:dbda6797) y sólo depende de pkgconf+python3, o
sea del corpus padre ⇒ copiarla a incoming-gnome da hash IDÉNTICO y cero
rebuild (la resolución de deps es hermano→padre, nunca de reojo a otra cola).
Con icu ya pago, las dos hojas de libsoup salen a la primera:
nghttp2 1.64.0 b3:5f35b06e --enable-lib-only deja la frontera en CERO deps
nuevas; las apps arrastraban libev, libcares,
openssl, jansson y libevent.
libpsl 0.21.5 b3:824b4bb9 --enable-{runtime,builtin}=libicu, verificado por
NEEDED libicuuc.so.77 (no degradó a libpsl ciego).
Frontera restante de la cima: libsoup, libical, evolution-data-server.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
El compositor construye: /usr/bin/mutter + gdctl, libmutter-*.so, los typelibs Clutter-16 y
Cogl-16, y libmutter-16.pc — que es exactamente lo que gnome-shell enlaza e importa.
LO QUE DESTRABÓ TODO: libelogind (b3:a6058906), receta nueva sobre `arje-sdlogin-compat`, un
crate que escribí en tawasuyu para esto. arje-logind-compat ya publicaba el estado de sesión
en /run/systemd/{sessions,users,seats}; faltaba la librería C que lo LEYERA, porque la API
sd-login no es cliente D-Bus: lee esos ficheros. mutter probó libsystemd (no), después
libelogind (sí) y siguió de largo. No es un stub: lee estado real que el daemon publica.
Después del muro aparecieron cinco cosas más, todas resueltas y ninguna de fondo:
udev-pc (b3:69e2d418) mutter pide DOS pkg-config: `libudev` (lo da libudev-zero) y `udev`
(metadata: udevdir). Receta aparte y no agregado a libudev-zero
porque `yupana radio` daba 51 SELLADOS cayendo a deuda en las cinco
imágenes. Un .pc de 4 líneas no justifica medio catálogo.
libxcvt (b3:ab8ede67) mutter corre `cvt` en build-time para generar meta-default-modes.h.
El app/cvt clásico vive en xorg.freedesktop.org, que desde acá no
responde (probé x.org, kernel.org y Lysator). libxcvt es la
extracción moderna del mismo código, está en el pool de Debian y no
arrastra nada de X11.
-Dbash_completion=false y el sed de subdir('doc/man') (pedía rst2man).
py3-setuptools el distutils del g-ir-scanner, mismo precedente que polkit y gjs.
cierre C dinámico freetype/fontconfig/cairo/libpng/zlib/libjpeg/libtiff pasan a sus
variantes -shared: mutter ya es .so y las estáticas canónicas no
entran («relocation R_X86_64_32 … recompile with -fPIC»). Mismas
variantes que usa gtk4.
Y gsettings-desktop-schemas pasa a introspection=true + isla dinámica: su gir GDesktopEnums
entra en el de Meta, y sin él el scanner cortaba en el ÚLTIMO target (721/722). Es exactamente
el caso que el comentario de esa receta dejaba previsto («si mutter/gjs lo pidieran vía
typelib, se re-activa»). Costo medido: 1 sellado (gnome-desktop), reconstruido acá mismo.
PENDIENTE: la receta apunta al commit de gitea que todavía NO está pusheado (ver el informe).
El artefacto ya es el correcto — la URL no entra al ArtifactHash, sólo el commit, así que
construir desde el clon local dio el MISMO hash que dará desde gitea.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Tercera de la cima. gnome-shell la exige por gcr-4 (meson.build:74) y su JS importa gi://Gcr
(js/ui/components/keyring.js) ⇒ tenía que ser .so con typelib, no había opción estática.
Cadena nueva: p11-kit (b3:8dbec390) → gcr. p11-kit va con -Dtrust_module=disabled, que es lo
único que arrastraba libtasn1: una receta menos.
EL NUDO REAL fue el PIC, otra vez. libgcrypt y libgpg-error del corpus son estáticas SIN PIC
(y libgcrypt además está afinada para binarios -all-static -no-pie, con la advertencia escrita
de que el flag va en compile e install pero nunca en configure). Meterlas en un .so da
«relocation R_X86_64_32 ... recompile with -fPIC».
NO se tocaron las canónicas: `yupana radio` dio 5 sellados cayendo a deuda en base/cli, y
mostró además que existe OTRA libgpg-error en incoming-kde con 39 dependientes — justo el
tipo de colisión que el radio existe para ver. Se hicieron variantes -shared en la cola, que
es el idioma que este frente ya tiene (zlib-shared, cairo-shared, freetype-shared…).
libgcrypt-shared compiló con ZIG-CC, no gcc como la canónica: evidencia de que esa receta puede
migrar cuando le toque el turno de matar-gcc. Necesitó -fno-sanitize=undefined (el runtime UBSan
que inyecta zig deja __ubsan_handle_* sin definir en el .so), remedio ya documentado en zlib-shared.
Otros dos apagados de gcr, cada uno ahorrando una receta: -Dssh_agent=false (libsecret sólo la
pide el agente ssh) y -Dgpg_path fijo (gcr sólo quiere la RUTA de gpg para hornearla, no ejecuta
nada). Y el sed de subdir('po'): el msgfmt de gettext-tiny ABORTA con SIGABRT en po/ar.po. Es la
segunda vez que ese msgfmt marca el límite; si hay una tercera, conviene autorar el gettext de GNU.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Segunda de la cima. Da atk.pc, atk-bridge-2.0.pc y atspi-2.pc + los typelibs Atk-1.0 y
Atspi-2.0. gnome-shell la exige por atk-bridge-2.0 (meson.build:71).
El choque que atk.toml anticipaba se confirmó: el tarball de at-spi2-core trae `atk/` adentro
e instala su propio atk-1.0. Dos recetas con el mismo .pc se pisan en el sandbox, y NO era
hipotético: el cierre de gnome-shell contiene a las dos, porque mutter es dep suya. Se retira
atk.toml y at-spi2-core queda como único proveedor — que es lo que hace upstream desde 2.51.90.
Medido antes de tocar, con `yupana radio atk`: 1 dependiente directo (mutter), 0 sellados que
caigan a deuda. mutter repuntado a at-spi2-core llega EXACTAMENTE al mismo muro de logind, sin
ninguno nuevo.
DBus-1.0.gir lo pedía el scanner y ya lo provee gi-foreign-girs (no hizo falta receta nueva).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Primera de la cima. Da polkit-agent-1.pc (lo que gnome-shell enlaza en C) y los typelibs
Polkit-1.0 + PolkitAgent-1.0 (lo que su JS importa: gi://Polkit aparece en polkitAgent.js,
endSessionDialog.js, status/thunderbolt.js y environment.js — verificado, no supuesto).
-Dlibs-only=true y acá la opción SÍ recorta, al revés que en colord: el bloque `if not
libs_only` (:145-159) es justo el que pide expat, duktape y threads. Y no es un recorte a
desgana — la Semilla de arje ya trae compat-polkit implementando el servicio D-Bus; construir
polkitd sería competirle, no completarlo.
-Dsession_tracking=ConsoleKit no es preferencia por ConsoleKit: es la ÚNICA de las tres que no
exige una C-ABI de logind (logind→libsystemd, elogind→libelogind), y son LAS MISMAS funciones
sd-login que traban a mutter (sd_uid_get_display, sd_pidfd_get_session). Con libs-only ese
camino queda inerte. Cuando exista el shim, vuelve a `logind`.
-Dauthfw=shadow (no hay linux-pam). Isla dinámica, como manda la regla del registro único de
GType. Las 3 deps de tooling que faltaban salieron de precedentes ya escritos del frente:
gettext-tiny (msgfmt), py3-setuptools (distutils de g-ir-scanner) y glib-introspected
(Gio-2.0.gir para el scanner).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
La lista de FRONTERA de la receta se había escrito de memoria y tenía dos errores. Sobraban
ibus y startup-notification: no aparecen en el meson.build de 48.8. Y faltaba la más cara:
libecal-2.0 + libedataserver-1.2, o sea evolution-data-server entero (el calendario del panel),
que arrastra libical, libsoup, nss e icu — ninguna en el corpus.
No hay atajo por versión: verificado que gnome-shell 50.3, la serie más nueva publicada, sigue
pidiendo eds incondicional en las mismas líneas.
Las reales, todas incondicionales y de nivel superior (:71-89): atk-bridge-2.0 (at-spi2-core),
libecal/libedataserver (eds), gcr-4, libxml-2.0 (ya sellada), polkit-agent-1. Costo de la cima:
~10 recetas nuevas dominadas por eds+icu. Es una campaña, no una tanda.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
El comentario decía por lectura del meson.build lo que ahora dice un build corrido: el configure
muere antes, en geocode-glib-1.0 (:100), y las de GTK3/X11 vienen enseguida y siguen incondicionales
(gtk+-3.0 :106, gtk+-x11-3.0 :107, x11 :116, xfixes :117). Cerrar geocode-glib sólo movería el muro
cuatro líneas. Aparcada junto con gnome-session.
Lo que faltaba decir: gnome-shell no depende de g-s-d ni en build ni para arrancar. Sin él la sesión
sube igual y se pierden teclas de medios, energía y perfil de color. Degradación, no ausencia.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>