Commit Graph
1234 Commits
Author SHA1 Message Date
sergioandClaude Opus 5 51c6830f58 audio: wireplumber (b3:39a9a06c) + lua (b3:e6c35f98) — y el Devices vacío es del KERNEL
Cierra el gestor de sesión de PipeWire, que es lo que separa «PipeWire acepta clientes»
de «PipeWire tiene dispositivos». Su política está escrita en Lua, así que arrastró una
receta de Lua que hubo que autorar entera.

LO QUE LA RECETA DE LUA TIENE QUE INVENTAR: el Makefile de upstream sólo produce
liblua.a y los binarios — **no hay regla de .so ni fichero pkg-config**, los agrega cada
distro. Acá la compartida se enlaza a mano desde la .a con --whole-archive (una estática
sólo aporta lo referenciado y hay que llevarse todo) y el .pc se escribe con los TRES
nombres que se usan por ahí, porque wireplumber prueba lua-5.4, lua5.4 y lua54 en orden.
`-fPIC` no es opcional: libwplua es un objeto compartido.

Dos símbolos más en libelogind (tawasuyu 087230054 → re-pineado 749edfe41):
sd_uid_get_seats y sd_uid_get_state, que module-logind.c de wireplumber usa para saber si
el usuario está en un asiento antes de tomar los dispositivos. Van 28 símbolos sd-*.

**EL `Devices:` VACÍO DE wpctl NO ES UN FALLO DE wireplumber: el kernel no tiene ALSA.**
recipes/linux-metal.toml:111 lo apaga explícito (`-d SOUND -d SND`), así que no hay
/dev/snd que enumerar. Y esto NO se dio por supuesto: se agregó una ich9-intel-hda
emulada a QEMU (AUDIO=1, ahora el default de run-qemu-desktop.sh) justo porque un
«Devices: vacío» se lee IGUAL si wireplumber funciona sobre una VM sin hardware que si no
funciona. Con tarjeta y sin ALSA en el kernel, el resultado no cambia — la ambigüedad
queda resuelta. Encender el sonido en la distro es una decisión con costo (re-sellar el
kernel, rehacer la imagen metal) y queda a la vista en vez de escondida en un default.

Bug propio destapado en el camino: el bloque de wireplumber quedó DUPLICADO en
gnome-start y había DOS wireplumber peleándose el grafo. El síntoma no era un error sino
una lista de clientes que se lee normal si no se cuenta: dos «WirePlumber» con pids
distintos en wpctl status.

Y una nota de ADR 0012 que costó un rato: la cascada de libelogind cortó a mitad y dejó
el `output/` de mutter a medio hacer; el reintento moría con «error opening
'...c.o.d': No such file or directory». Un `rm -rf output` en el configure NO alcanzó
—el árbol tenía estado viejo más allá del build dir—; lo que lo arregló fue BORRAR
work/sources/mutter-* para que el fetch lo re-extraiga limpio.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-29 20:40:12 -04:00
sergio d57fb8c5c7 estado: cosecha granja 2026-07-30T00:25:06Z — avance del árbol KDE 2026-07-29 20:25:06 -04:00
sergioandClaude Opus 5 5faa259603 audio: PipeWire es el servidor de la distro (decisión del usuario) — gvc conecta
Cierra una pregunta que estaba explícitamente abierta en varias recetas, y que es la
razón por la que `pulseaudio` se había construido con `-Ddaemon=false`: sólo el cliente,
para que gvc hablara el protocolo sin cerrar la decisión de prestado.

**Los dos conviven y por eso la decisión no rompe nada**: pipewire va con
`-Dlibpulse=enabled` ⇒ `pipewire-pulse`, un servidor que habla el protocolo de
PulseAudio. gnome-shell usa libpulse sin enterarse de qué hay del otro lado. No hubo que
tocar una línea del cliente.

  == gnome-qemu :: socket pipewire-0 OK
  == gnome-qemu :: socket pulse/native OK — gvc va a poder conectar
  Gvc-DEBUG: Updating client: index=32 name='pipewire'
  Gvc-DEBUG: Updating sink: index=33 name='auto_null' description='Dummy Output'

El `Failed to connect context: Connection refused` desapareció. El sink es auto_null, que
es la respuesta honesta: la VM no tiene tarjeta de sonido.

**⚠ Falta wireplumber** (gestor de sesión, Lua + su cierre). Sin él PipeWire acepta
clientes pero NO enumera ni enruta dispositivos. «El shell conecta» ≠ «hay sonido», y el
log de arriba es justo el caso donde confundirlos sería fácil. Queda escrito en la receta
y en el runbook.

GOTCHA MEDIDO: ya existía incoming-kde/pipewire.toml sellada y NO se puede reusar
hidratándola acá — los dos cierres traen glib y **no son la misma glib**:
incoming-kde/glib-shared y incoming-gnome/glib producen libglib-2.0.so.0.8800.1 con bytes
distintos (verificado con cmp) y comparten 370 rutas. Proyectar las dos deja que una gane
por orden de proyección ⇒ dos registros de GType en un proceso, el cuadro que costó el
episodio de colord. De ahí la copia en la cola GNOME (glib-shared→glib, dbus→dbus-shared,
pcre2-shared→pcre2), que sí re-construye. Lo que FUE gratis: alsa-lib, cuya única dep es
pkgconf y resuelve al catálogo PADRE ⇒ hash idéntico y cache hit (b3:93cae411).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-29 19:59:30 -04:00
sergio d250d57c2b estado: cosecha granja 2026-07-29T23:54:54Z — avance del árbol KDE 2026-07-29 19:54:54 -04:00
sergio 579107b6db estado: cosecha granja 2026-07-29T23:24:42Z — avance del árbol KDE 2026-07-29 19:24:42 -04:00
sergioandClaude Opus 5 3d01d5cb04 gnome: el bus de sistema COMPLETO — faltaba polkit, y lo dijo la lista de nombres
bus: org.freedesktop.login1      OK
  bus: org.freedesktop.PolicyKit1  OK
  bus: org.freedesktop.Accounts    OK
  bus: org.freedesktop.UPower      OK

accounts-daemon y upowerd arrancaban, seguían vivos, y NUNCA adquirían su nombre: los
dos se bloquean en `polkit_authority_get_sync()` al iniciar, y `org.freedesktop.PolicyKit1`
no lo servía nadie —nuestra receta polkit es libs-only a propósito, porque el demonio lo
pone arje—. gnome-shell esperaba después 25s por cada uno.

**El dato que lo resolvió no salió del log de los daemons sino de la LISTA DE NOMBRES DEL
BUS**: ahí estaban como conexiones anónimas `:1.0`, `:1.1`, sin nombre bien conocido. Eso
distingue tres cosas que en el log del cliente se ven igual — «no arrancó», «arrancó y no
llegó a pedir el nombre» y «lo pidió y se lo negaron». Era la segunda. `gnome-start` ahora
espera cada nombre con NameHasOwner y, si no aparece, vuelca el log del daemon y la lista.

Receta nueva `arje-polkit-compat` (b3:03e0a86f), tercer shim de este tipo tras
arje-logind-compat y arje-sdlogin-compat. Su propio autor ya había escrito el diagnóstico
en el crate: «apps que usan polkit bloquean en CheckAuthorization si no responde nadie».
⚠ AUTORIZA TODO — es la postura de sistema confiado que arje ya tenía tomada, no algo que
esta receta introduzca; queda explícito en su comentario.

Dos gotchas del empaquetado:
- **La política de polkit ya existe y NO alcanza**: permite `own` sólo al usuario polkitd
  y el shim corre como root. Se agrega un `zz-arje-polkit-compat.conf` en vez de reescribir
  la de upstream — dbus lee system.d en orden alfabético y las posteriores ganan.
- **Los ficheros del rootfs fundido son hardlinks de SÓLO LECTURA del store** (0444). Un
  `cat >` encima falla con Permission denied y rompió un build. Regla: nunca sobrescribir
  un fichero que venga de un artefacto; agregar al lado.

Queda escrito en el runbook lo que sigue faltando (colord, y que el shell no tiene servidor
de sonido porque pulseaudio se construyó sólo-cliente: el demonio de audio de la distro
sigue sin decidirse) y las dos lecciones de método que costaron una iteración cada una.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-29 19:19:23 -04:00
sergioandClaude Opus 5 32926dc6df gnome: runbook — iconos/cursor cerrados, y el setuid del launch-helper era una causa con dos síntomas
Captura actualizada: ahora se ve el puntero (Adwaita) y el icono de la notificación.
Colores distintos 582 → 629.

El setuid del dbus-daemon-launch-helper explicaba DOS cosas, no una: el «permission of
the setuid helper is not correct» de colord y, por la misma vía, que ninguna activación
por bus de sistema funcionara. Con el arreglo, colord pasó de «permiso incorrecto» a
«timed out» — la activación ya se intenta y lo que queda es del demonio.

Queda UPower: upowerd arranca y sigue vivo, pero no adquiere su nombre en el bus (su
política D-Bus está verificada y permite own a root), así que el shell espera sus 25s.
Es el indicador de batería en una VM sin batería.

Y queda escrita la lección que costó una iteración: **un pid no es un servicio**.
Reportar «lanzado» sin comprobar que el daemon adquirió su nombre es reportar una
intención, no un hecho.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-29 19:02:45 -04:00
sergioandClaude Opus 5 3999b421da gnome: cursor visible, iconos y el setuid del launch-helper de D-Bus
adwaita-icon-theme b3:429aef43 + hicolor-icon-theme. No es cosmética: con el cursor por
SOFTWARE —obligatorio en virtio-gpu— mutter dibuja la imagen que le da el tema, y sin
tema el puntero se movía INVISIBLE. Ahora se ve en la captura, y la notificación del
shell tiene su icono. Colores distintos 582 → 618.

hicolor arrastrada por `Inherits=hicolor` del index.theme de Adwaita: la cadena de
fallback tiene que terminar en algo que sea un TEMA (con su index.theme), no sólo un
directorio. No trae un solo icono propio — es el contrato, no el contenido.

Dos gotchas medidos:
- **hicolor 0.18 pasó de autotools a meson**: su tarball ya no trae `configure` (127).
- adwaita declara `gtk-update-icon-cache` como `required: true` para un
  `add_install_script` que **su propio autor marcó `skip_if_destdir: true`** — exige un
  binario que en un build empaquetado no puede ejecutar. Se borran los dos bloques.
  `required: false` NO alcanza: meson no propaga el disabler dentro de
  add_install_script y revienta con «Unhandled python exception». Se descartó declarar
  gtk4 como dep: acoplaría el hash de un paquete de DATOS al del toolkit.

**El setuid del launch-helper es la causa raíz de dos síntomas, no de uno.** El
`dbus-daemon-launch-helper` comprueba sus propios permisos antes de activar nada y se
niega si no es setuid root — de ahí el «The permission of the setuid helper is not
correct» de colord. Sin eso NINGUNA activación por bus de sistema funciona, que es
también por qué UPower timeouteaba a los 25s. La imagen ahora lo deja root:messagebus 4750.

Y `gnome-start` lanza upowerd, pero **verificando**: la primera versión decía «lanzado»
y el shell seguía esperando 25s. Un pid no es un servicio. Ahora comprueba que siga vivo
y, si murió, vuelca su log. Además crea los directorios de estado que upower deriva de
--prefix y sin los cuales se muere en silencio.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-29 18:59:46 -04:00
sergio df43352786 estado: cosecha granja 2026-07-29T22:54:32Z — avance del árbol KDE 2026-07-29 18:54:32 -04:00
sergio 330850182b estado: cosecha granja 2026-07-29T22:24:15Z — avance del árbol KDE 2026-07-29 18:24:15 -04:00
sergioandClaude Opus 5 723f3ead33 gnome: 🏔🏔 EL ESCRITORIO PINTA — Overview de GNOME desde fuente, con captura
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>
2026-07-29 18:05:20 -04:00
sergio 517c1bb4ff estado: cosecha granja 2026-07-29T19:32:09Z — avance del árbol KDE 2026-07-29 15:32:09 -04:00
sergioandClaude Opus 5 a3b49c24dc gnome: runbook al día — la capa JS cerrada, el muro nuevo es que no PINTA
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>
2026-07-29 15:19:22 -04:00
sergioandClaude Opus 5 417ba2a502 gnome: 🏔 LA SESIÓN ARRANCA Y SE QUEDA VIVA — cae el último muro de la capa JS
== 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>
2026-07-29 15:16:03 -04:00
sergio f70c4a2339 estado: cosecha granja 2026-07-29T19:02:00Z — avance del árbol KDE 2026-07-29 15:02:00 -04:00
sergioandClaude Opus 5 8d1efca26e gnome: GIRepository-2.0 — el typelib que no pide el shell sino gjs
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>
2026-07-29 14:54:34 -04:00
sergio 7642b4fbbc estado: cosecha granja 2026-07-29T18:31:51Z — avance del árbol KDE 2026-07-29 14:31:51 -04:00
sergioandClaude Opus 5 bc4d0c8aea gnome: los 7 typelibs CERRADOS — librsvg y ibus, y dos deudas viejas pagadas de paso
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>
2026-07-29 14:28:50 -04:00
sergio 0a76ead129 estado: cosecha granja 2026-07-29T18:01:41Z — avance del árbol KDE 2026-07-29 14:01:41 -04:00
sergioandClaude Opus 5 4d48edac0d gnome: 5 de los 7 typelibs de runtime — gnome-desktop a la isla dinámica + 5 recetas nuevas
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>
2026-07-29 13:43:06 -04:00
sergioandClaude Opus 5 cde77a8c91 gnome: la frontera de runtime MEDIDA — 7 typelibs, 6 proveedores, y la regla que la destapó
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>
2026-07-29 13:02:51 -04:00
sergio e73d205f4a estado: cosecha granja 2026-07-29T17:00:53Z — avance del árbol KDE 2026-07-29 13:00:53 -04:00
sergioandClaude Opus 5 fd9f9dff6d gnome: libgdm (b3:46fac484) + cairo-1.0.typelib — la capa JS avanza dos muros más
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>
2026-07-29 12:50:14 -04:00
sergio 94400009a9 estado: cosecha granja 2026-07-29T16:30:43Z — avance del árbol KDE 2026-07-29 12:30:43 -04:00
sergioandClaude Opus 5 a98267468c gnome: gi-foreign-typelibs (b3:a159373c) — un .gir NO es un typelib
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>
2026-07-29 12:10:05 -04:00
sergio ac04990af1 estado: cosecha granja 2026-07-29T16:00:29Z — avance del árbol KDE 2026-07-29 12:00:29 -04:00
sergioandClaude Opus 5 08fc1d4b92 gnome: accountsservice SELLA (b3:0328b0d0) — cae la frontera de la C-ABI de logind
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>
2026-07-29 11:54:52 -04:00
sergio b29bdbb346 estado: cosecha granja 2026-07-29T15:30:17Z — avance del árbol KDE 2026-07-29 11:30:17 -04:00
sergioandClaude Opus 5 b01fad94e5 gnome: 🏔 EL COMPOSITOR SUBE ENTERO SOBRE DRM REAL — cae el muro de input
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>
2026-07-29 11:23:06 -04:00
sergioandClaude Opus 5 03bdd41b4a gnome: el muro de input NO era libudev-zero — el fd de TakeDevice era bloqueante
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>
2026-07-29 11:09:54 -04:00
sergio 609fabdb76 estado: cosecha granja 2026-07-29T15:00:05Z — avance del árbol KDE 2026-07-29 11:00:05 -04:00
sergio 61bd5a5844 estado: cosecha granja 2026-07-29T11:00:10Z — avance del árbol KDE 2026-07-29 07:00:10 -04:00
sergioandClaude Opus 5 8cf9a87dd2 arje-logind-compat: repineado al fix (b3:5e4b8e04) — la cadena vuelve a ser reproducible
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>
2026-07-29 06:52:15 -04:00
sergio fc627eb8a7 estado: cosecha granja 2026-07-29T10:30:35Z — avance del árbol KDE 2026-07-29 06:30:36 -04:00
sergioandClaude Opus 5 f56bab72f5 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>
2026-07-29 06:07:42 -04:00
sergioandClaude Opus 5 34c7962b29 gnome: cae el SIGSEGV — el shell toma DRM master e input; muro nuevo en la hebra de input
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>
2026-07-28 22:49:46 -04:00
sergioandClaude Opus 5 fbd1e5fca1 gnome onda 3: json-glib con default_library=both (b3:52a20f22), no shared
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>
2026-07-28 21:47:58 -04:00
sergioandClaude Opus 5 5295aa35c6 gnome: la cima ARRANCA en QEMU — muere en meta_launcher_new, causa localizada
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>
2026-07-28 21:47:11 -04:00
sergioandClaude Opus 5 f6734d6ce6 gnome: hydrate-gnome.sh — el cierre de runtime de la cima CIERRA 108/108
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>
2026-07-28 21:06:55 -04:00
sergio fed6130199 estado: cosecha granja 2026-07-29T01:00:04Z — avance del árbol KDE 2026-07-28 21:00:04 -04:00
sergioandClaude Opus 5 50a934966b estado: regenerar grafo tras la cima de GNOME (13 recetas nuevas)
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>
2026-07-28 20:47:30 -04:00
sergioandClaude Opus 5 794d9b595e gnome onda 3: 🏔 GNOME-SHELL SELLADO (b3:b6aec8a2) — LA CIMA
/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>
2026-07-28 20:46:05 -04:00
sergio 94f311177b estado: cosecha granja 2026-07-29T00:38:41Z — avance del árbol KDE 2026-07-28 20:38:41 -04:00
sergioandClaude Opus 5 0f7817a25f gnome onda 3: CAE LA ÚLTIMA FRONTERA — evolution-data-server SELLADO (b3:ad335cfb) + nss
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>
2026-07-28 20:22:26 -04:00
sergio 5779cceae7 estado: cosecha granja 2026-07-29T00:08:28Z — avance del árbol KDE 2026-07-28 20:08:28 -04:00
sergioandClaude Opus 5 fd73295c94 gnome onda 3: las tres piezas de soporte de eds — libsecret, libxml2-shared, libuuid-shared
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>
2026-07-28 20:04:14 -04:00
sergioandClaude Opus 5 98932ec477 gnome onda 3: libical SELLADO (b3:ada6e05f) — tercera pieza de la cadena eds
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>
2026-07-28 19:54:15 -04:00
sergioandClaude Opus 5 1283215173 gnome onda 3: libsoup SELLADO (b3:79d6bf81) + sqlite-shared
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>
2026-07-28 19:51:14 -04:00
sergioandClaude Opus 5 a9f40e15bc gnome onda 3: hojas de la cadena eds — nghttp2 (b3:5f35b06e) y libpsl (b3:824b4bb9)
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>
2026-07-28 19:43:34 -04:00
sergio f07163aba0 estado: cosecha granja 2026-07-28T12:00:04Z — avance del árbol KDE 2026-07-28 08:00:04 -04:00