86645c379c6fcb6381cf4e19a8feb866370ec912
286
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
86645c379c |
🖥 cosmic/metal: la imagen forzaba render por SOFTWARE — el viaje no podía ganar
Diagnóstico del 1er viaje al OptiPlex 3060 (Coffee Lake, UHD 630). El dmesg del propio USB muestra que la GPU estaba PERFECTA: [drm] Found coffeelake (device ID 3e92) ... Initialized i915 1.6.0 on minor 0 fbcon: i915drmfb (fb0) is primary device Lo que fallaba era el script de arranque. `cosmic-start-qemu.sh` exportaba LIBGL_ALWAYS_SOFTWARE=1 y MESA_LOADER_DRIVER_OVERRIDE=kms_swrast INCONDICIONAL — correcto sobre virtio-gpu, letal sobre Intel real: la mesa del corpus va con -Dgallium-drivers=iris -Dllvm=disabled y NO EXISTE ningún kms_swrast_dri.so ⇒ EGL falla. Y en el mejor caso habría sido peor: si arrancaba, componía por software y ScreenCast fallaba igual que en QEMU ⇒ el viaje NO PODÍA contestar su pregunta. El origen es un comentario que yo escribí en metal-desktop-image.sh afirmando que el script no tenía supuestos del emulador. Los tenía, y el nombre del fichero lo decía. Ahora: - `cosmic-start-qemu.sh` → `cosmic-start.sh` (se llama por lo que hace). - El modo de GL se DETECTA con dos patas: driver DRM del kernel Y .so de mesa presente. Si no hay ninguna, lo DICE en vez de morir dentro de EGL. - La imagen VERIFICA que el script instalado no fuerce kms_swrast (falla el build si vuelve a pasar). Y correr cosmic-start sobre la imagen de metal POR PRIMERA VEZ (antes sólo se validaba que llegara al prompt) destapó que le faltaba entera la preparación de sesión que sólo tenía qemu-desktop-image.sh: sin grupo `video` no arranca seatd, sin usuario `messagebus` no arranca el bus de SISTEMA — y sin bus de sistema NO HAY PORTAL, o sea que portal-probe screencast no habría tenido con quién hablar aunque el GL fuese perfecto. Copiada: arje-logind-compat + política, video, messagebus, setuid del launch-helper, /var/run→/run, COSMIC_MODE, libc.musl-x86_64.so.1. Además, para que el próximo fallo en metal no cueste otro viaje a ciegas: - Los logs van a /var/log/cosmic (ext4) y no a /tmp (RAM, se evapora al apagar). `dump()` también, que iba SÓLO al serial — donde se perdió la explicación de los tres fallos de arriba. - authorized_keys horneada: sshd escuchaba en :22 pero era INALCANZABLE (PasswordAuthentication no, sin clave) ⇒ ahora se depura por red. - netup-wait: el r8169 levanta el enlace a los 20,2s y el ente sshd pedía DHCP a los 13,7s, sin reintento. En QEMU no se ve: virtio-net tiene carrier desde el instante cero. - firmware i915 de otras generaciones (la base sólo traía tgl_*; el Coffee Lake pedía kbl_dmc_ver1_04.bin). Validado arrancando como usb-storage: seatd OK, bus de sistema OK, login1 OK, pipewire+wireplumber OK, compositor OK. La línea de GL dice la verdad en QEMU. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
08440220b6 | estado: cosecha granja 2026-08-05T19:00:17Z — avance del árbol KDE | ||
|
|
705a70c33a |
🩺 EFI: el initramfs perdía la carrera contra la enumeración USB — y en silencio
Síntoma en metal ajeno: la pantalla se congela justo tras `sdc: sdc1 sdc2 sdc3 sdc4` / `Attached SCSI removable disk`. No estaba colgado. Prueba de que el root nunca se montó: con `ignore_loglevel` un montaje ext4 imprime `EXT4-fs (...): mounted filesystem` en pantalla sí o sí, y no aparecía. Dos causas encadenadas: 1. CARRERA. El rdinit arranca en cuanto se desempaqueta el initramfs, pero el bus USB enumera asíncrono y tarda segundos (reset de hub, settling de 1s por dispositivo, scan SCSI). Los 5 reintentos de 1s no alcanzaban. En QEMU el disco es virtio y está desde el instante cero ⇒ la carrera NUNCA se veía en validación. Es el `rootwait` que no podemos usar porque no hay root= en el cmdline. Ahora espera 60s. 2. CEGUERA. El cmdline horneado es `console=tty0 console=ttyS0,115200` y /dev/console = la ÚLTIMA `console=` ⇒ el serial. El `exec sh` de rescate nacía invisible. Es el MISMO bug que costó el 1er viaje físico de KDE, una capa más temprano: allá se arregló para después del switch_root (getty en tty1) y el initramfs quedó ciego. Ahora el log del pivote va a /dev/tty0, el marcador INIT-OK también, y el rescate abre shell en tty1 listando los bloques visibles. + `timeout 15` a `hammer boot menu`: corre ANTES del exec de arje-zero ⇒ colgarse ahí deja un arranque sin PID1 ni pantalla, indistinguible de un kernel muerto. El `|| true` protegía del fallo, no del bloqueo. Validado arrancando la imagen COMO USB (qemu-xhci + usb-storage, -serial null, con pantalla): marcadores del pivote visibles, motd y prompt `/ #`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
11e6a3c78c |
🔩 cosmic/metal: imagen EFI con iris HW — el viaje que cierra ScreenCast
Hermano de kde/metal-desktop-image-dual.sh, pero con la decisión INVERTIDA y ése es el motivo de existir. La de KDE va por mesa-llvmpipe a propósito (tenía que aguantar también una NVIDIA Pascal, cuya mesa HW sólo existe como binario Alpine ⇒ rompería soberanía). Acá el objetivo es cerrar ScreenCast, y el diagnóstico de hoy midió que lo que falla es el COMPOSITOR en una llamada EGL —8 ms antes del `Paused`— porque en QEMU mesa es kms_swrast: software, SIN exportación dmabuf. El `mesa` del corpus se construye con -Dgallium-drivers=iris y YA está en el rootfs de COSMIC; en QEMU nunca se usaba, en un TigerLake es el driver correcto y trae dmabuf de verdad. O sea que este viaje no es "lo mismo pero en metal": es la única forma de saber si ScreenCast está bien. ⚠ Por eso NO se inyecta llvmpipe: mezclarlos no es aditivo — llvmpipe trae su propio libgbm/libEGL/libgallium y sobrescribirlos DESACTIVA iris. Si la máquina no tuviera Intel, la imagen correcta sería la de KDE, no ésta con un parche. Y lo que NO hace falta inyectar, medido: la de KDE mete libLLVM.so.18 + libgcc_s + libstdc++ porque el JIT de llvmpipe los NEEDea. Acá NO — iris_dri.so pide sólo libglapi/libdrm/libz/libzstd/libc (mesa va con -Dllvm=disabled) y cosmic-comp ocho NEEDED sin C++. CERO binarios ajenos de Alpine. Verificado con clausura ELF completa del rootfs: 472 objetos escaneados, 42 raíces de runtime, 0 con NEEDED sin proveedor (los 3 huecos son llvm-*/perl, herramientas de build que el escritorio no arranca). Se instala EL MISMO cosmic-start validado en QEMU, no una variante: nada de lo que hace es específico del emulador, y que corra el mismo fichero es lo que hace que "validado en QEMU" signifique algo para el metal. VALIDADO EN OVMF CON PANTALLA, que es la regla de oro que costó un USB en el 1er viaje de KDE (-serial null para simular metal sin puerto serie): arje-zero PID 1, las 4 particiones montadas, el motd VISIBLE y el prompt `/ #` en la pantalla — o sea que el getty de tty1 hace su trabajo. El shell responde: iris_dri.so presente, /dev/dri/card0, y cosmic-start/portal-probe/wireplumber en PATH. Falta quemar el USB, que es destructivo y necesita que el usuario confirme el device. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
8d10bccf34 |
🔇 wireplumber: construido, corriendo… y NO era el bloqueo
b3:b8f3baf0, selló a la primera. Arranca desde cosmic-start ("wireplumber OK (pid
192) — hay gestor de sesión"), se conecta al grafo (dos clientes en wpctl status) y
wpctl pasa a mostrar una sección Video que antes no existía.
Y el Start de ScreenCast SIGUE sin Response a los 60s. Mismo resultado exacto.
LA HIPÓTESIS QUEDA MATADA POR MEDICIÓN. "Falta el gestor de sesión que mueva el nodo
de Paused a Streaming" era mía y era razonable; no era cierta. Queda escrita junto a
su refutación porque una hipótesis descartada CON EVIDENCIA vale más que una lista de
sospechosos: acota el próximo paso a lo que queda, que es el backend mismo.
El dato nuevo, que es por dónde seguir: con wireplumber corriendo, `wpctl status`
lista `Video → Streams` VACÍO durante el handshake. O sea que el nodo
`cosmic-screencast` que SÍ existe en `pw-cli ls Node` no llega a wireplumber como
stream gestionado. Próximo movimiento: RUST_LOG=trace sobre screencast_thread, no
otra dep.
── por qué receta propia y no la de GNOME ──────────────────────────────────────
La de incoming-gnome funciona pero NEEDea libglib/libgobject/libpipewire de la ISLA
DINÁMICA de GNOME: traerla metería una segunda glib y una segunda pipewire en la
imagen. De 19 deps, 14 dan hash idéntico; las que divergen divergen a propósito —
sobre todo `pipewire`, que acá apunta a la de COSMIC (338d1d8c), la que el escritorio
realmente ARRANCA. Un gestor de sesión contra otra pipewire que la que corre no
gestiona nada.
El cambio de fondo es glib → glib-shared. COSMIC usa la glib ESTÁTICA del corpus, que
le alcanza al portal porque es un ejecutable. Acá no: wireplumber produce un .so y 17
módulos, y libglib-2.0.a tiene 44.275 reubicaciones R_X86_64_32/32S ⇒ no es PIC. La
regla del frente GNOME (readelf -r ANTES de gastar el build) ahorró uno.
Y la salida no fue una campaña nueva sino una MEDICIÓN: incoming-kde/glib-shared
copiada a esta cola resuelve al MISMO hash (0584ce1f) y ya estaba sellada ⇒ cero
rebuild. Idem pcre2-shared, lua y libelogind. Las dos glib coexisten sin pisarse (.a
y .so son ficheros distintos) y el portal conserva sus 3 NEEDED.
escritorio-cosmic: 84 → 89 recetas, 0 faltantes.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
ee037912a9 |
🎥 ScreenCast: el stream SE CREA — nodo cosmic-screencast vivo en pipewire
La receta de la sonda (b3:af49d32d) y lo que midió. Es la única receta de la campaña
cuyo producto no es una pieza del escritorio sino un instrumento para medirlo: entra
a la imagen porque un handshake de portal sólo se puede ejercer DESDE la sesión, con
bus y compositor vivos, y sale ESTÁTICA (0 NEEDED) porque un instrumento no debe
depender de aquello que mide.
[1/4] CreateSession → Response 0, session_handle ✓
[2/4] SelectSources → Response 0 ✓
[3/4] Start → el backend ABRE "Share your screen", con
miniatura EN VIVO del framebuffer y el output
Virtual-1; se elige, se pulsa Share…
y NO llega Response en 60s ✗
El log del backend da la línea exacta:
screencast_thread: state-changed 'Connecting' -> 'Paused'
Y `pw-cli ls Node` durante la espera da el veredicto INDEPENDIENTE:
node.name = "cosmic-screencast" media.class = "Video/Source"
EL NODO DE VIDEO EXISTE EN EL GRAFO DE PIPEWIRE. La cadena entera —cliente →
frontend → backend → compositor → demonio— funciona hasta crear y negociar el stream.
Lo único que no ocurre es el Response de vuelta tras quedar en `Paused`. Eso es un
lugar muy distinto del de esta mañana ("no hay demonio con quien negociar").
Sospecha para el próximo paso, y es HIPÓTESIS no medición: falta `wireplumber`. Sin
gestor de sesión nadie mueve el nodo de Paused a Streaming y el backend parece
esperarlo. Construirlo la confirma o la mata.
Gotchas que costaron corridas y quedan escritos:
· matar el backend se lleva puesto al frontend (ambos pierden dueño del bus);
· el lanzador busca por NOMBRE VISIBLE: `cosmic-term` no matchea, `Terminal` sí —
escribir el nombre del binario abre otra app;
· `| head -N` bufferiza y deja la terminal en blanco: parece colgada y está esperando;
· pkg-config OMITE los -L de dirs "estándar" y zig cc cross NO los busca ⇒
`-ldbus-1` pelado da "unable to find static system library", que suena a librería
faltante cuando lo que falta es la ruta.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
28dc473aca |
🧹 store-gc: el recolector que hammer gc no tiene — 702 artefactos, 34G
El disco llegó a 100% y el gordo no estaba en `work/`: el store guarda un artefacto
por cada SELLADO, no uno por receta. Cuando una dep cambia, el ArtifactHash de todo
lo que cuelga cambia y el sellado nuevo SE SUMA al viejo. Medido: 1996 artefactos
para 1130 recetas — 12 copias de libqalculate, 9 de qt6-qtdeclarative, 8 de gtk4.
51G de 74G eran versiones anteriores.
El conjunto VIVO es `hammer hash` sobre todas las recetas de todas las colas: la
respuesta a "¿cuál es el hash vigente HOY?", que el store solo no puede dar. Lo que
no está ahí es rancio — pero rancio son DOS cosas muy distintas, y confundirlas es
la diferencia entre podar y perder:
SUPERADO — su nombre TIENE un artefacto vigente presente. Versión anterior de algo
ya sellado al día. Se reconstruye desde la receta, que está en git.
HUÉRFANO — ningún artefacto con ese nombre es el vigente. El hash de hoy NO está
sellado y éste es el ÚNICO ejemplar. Borrarlo sí pierde.
Por eso el default borra sólo los superados; `--huerfanos` hay que quererlo aparte.
Aplicado: 702 superados = 34G, de 5,4G libres a 43G. La verificación de que el
criterio era correcto no fue el `df`: fue que `hydrate-cosmic.sh` siguió dando 83/83
recetas y 0 faltantes.
Los 255 huérfanos (17G) quedan INTACTOS y son un hallazgo aparte: casi todos KDE
(kio×8, kparts×8, kcmutils×8), o sea que las recetas KDE se movieron después del
último sellado y el escritorio hidratado vive de artefactos que ya no son vigentes.
Dos avisos que el script lleva escritos porque cuestan al descubrirlos solos: el
espacio NO siempre se libera (los rootfs de work/ son hardlinks al store — borrar el
dir no rompe nada pero tampoco libera hasta que el rootfs se vaya), y `--store` por
defecto apunta a /store, no a ./store.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
e43ce95786 |
🎥 cosmic: pipewire ARRANCA, y el portal ya figura como cliente suyo
El bloqueo decisivo de ScreenCast no era una receta que faltara: `/usr/bin/pipewire`
estaba en la imagen desde que entró como dep de `cosmic-settings-daemon`, pero NADIE
lo lanzaba. En una distro con systemd de usuario eso lo hace `pipewire.socket`; acá
no hay tal cosa, así que es tarea de `cosmic-start` — el mismo patrón que el bus de
sistema y que login1.
Va justo después de asegurar XDG_RUNTIME_DIR y NO junto al bus de sesión, a
propósito: pipewire no necesita D-Bus para arrancar, sólo el runtime dir donde abre
su socket. Ahí sirve para los dos modos (bare y session) sin duplicar el bloque. Y se
espera EL SOCKET, no el pid: un demonio que muere al instante deja el pid existiendo
un rato, y esperar por él da un OK falso.
Medido dentro de la VM, cada paso una pregunta distinta:
pipewire OK (socket pipewire-0, pid 189) ¿abre socket?
pw-cli info 0 → Core/4, 1.2.7, core.daemon ¿SIRVE a un cliente?
pw-cli ls Factory → "client-node" ¿tiene lo que ScreenCast usa?
pw-cli ls Client → "xdg-desktop-portal" ¡el portal YA está conectado!
La última línea es el veredicto: el frontend del portal aparece como cliente del
demonio, una conexión que antes no podía existir y que es justo la que `Start`
necesita para negociar el nodo. `client-node` es la factory con que el backend lo crea.
Sin regresión, con la cadena entera: `cosmic-screenshot` levanta la UI INTERACTIVA
del portal (región/ventana/pantalla + Capture + Save to Pictures) y el click deja un
PNG de 53.590 bytes. Esa UI no estaba documentada — el registro anterior sólo probaba
la ruta no-interactiva. Escritorio completo: 2414 colores (el panel mutilado da 130).
Lo que sigue faltando son DOS cosas distintas, y ninguna es un one-liner:
· el handshake de punta a punta pide un cliente `ashpd` PERSISTENTE — el portal
asocia la sesión al *sender*, así que CreateSession con un dbus-send y
SelectSources con otro se rechazan por venir de nombres únicos distintos;
· wireplumber, que separa "hay stream de video" de "hay audio". Ni construido está.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
2e26a45060 |
🎥 cosmic: ScreenCast — dos bloqueos, y el que importa es que NADIE ARRANCA PIPEWIRE
BLOQUEO 1: dbus-send no puede manejarlo, al revés que FileChooser. El
selector se abre con UNA llamada; ScreenCast necesita un handshake de tres
pasos con estado (CreateSession → SelectSources → Start) y la sesión queda
atada a la CONEXIÓN que la creó — cada dbus-send es una conexión distinta
que muere al terminar, así que el paso 2 nunca encuentra la sesión del paso
1. Es límite de la herramienta, no del portal.
Lo que sí se midió: CreateSession FUNCIONA. El frontend devuelve
/org/freedesktop/portal/desktop/request/1_106/sc1 con nuestro handle_token.
BLOQUEO 2, y éste no lo arregla ningún cliente: NO HAY DEMONIO DE PIPEWIRE.
ls /usr/bin/ | grep -i pipewire → pipewire, pipewire-aes67,
pipewire-avb, pipewire-pulse
ps ax | grep -c pipewire → 1 (el propio grep)
Los binarios están —el backend del portal enlaza libpipewire-0.3.so— pero el
demonio no corre: cosmic-start no lo lanza y no hay systemd de usuario. O
sea que aunque se escribiera el cliente ashpd, Start no tendría con quién
negociar el stream. Arreglo: lanzarlo desde cosmic-start. Para AUDIO además
falta wireplumber, que ni está construido.
Y se corrigió un comentario DESACTUALIZADO de cosmic-start que decía que
cosmic-settings-daemon «todavía no se puede construir acá (arrastra
pipewire)»: es falso hace tiempo, ese daemon está sellado y corre. Un
comentario viejo manda a buscar un bloqueo que ya no existe, y eso cuesta
igual que un bug.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
1e786aaf42 |
🚪 cosmic: el BACKEND del portal sella (b3:7ad0f124) — cadena completa en la imagen
69 min. NEEDED: libgbm, libpipewire, libxkbcommon, libc. Instala el binario en /usr/libexec, el .service de D-Bus con @libexecdir@ sustituido, el cosmic.portal que declara las cinco interfaces (Access/FileChooser/Screenshot/Settings/ScreenCast) y sus iconos. clang18 se construyó en la granja y se cosechó al laptop (b3:62c6bfb5), pero el backend NO se pudo construir allá: el worker no tiene la cola COSMIC horneada —el snapshot golden es del 2026-07-15 y toda esta cola es posterior— así que intentó reconstruir pipewire y murió buscando glib. Es la regla de «rootfs laptop ≠ worker» pero con el STORE: lo que en el laptop es cache-hit, en el worker es un build entero con sus propias deps. Y destapó que la receta de pipewire NO lleva --wrap-mode=nodownload: ante una dep faltante intenta bajarse un subproyecto de internet y, sin red, el error que sale no es «te falta glib» sino «Unhandled python exception / This is a Meson bug». Queda anotado como deuda. --offline SIN --locked, y no es descuido: el sed del parche corre en la fase compile, o sea DESPUÉS del cargo vendor, así que cargo ve el Cargo.toml cambiado y con --locked se niega. Quitar una feature sólo puede ENCOGER el conjunto de crates, así que lo que haga falta ya está vendorizado; la hermeticidad la da --offline + el árbol vendorizado, no el --locked. Dos raíces en el perfil y en la hidratación, porque son DOS procesos que se encuentran por D-Bus en runtime y ningún [deps] los relaciona. Imagen en 83 recetas (eran 74). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
520271ea2f |
📷 cosmic: cosmic-screenshot sellada y ROTA A PROPÓSITO — y la glib compartida YA existe
b3:8b57ec9b, 9 minutos, NEEDED = libc.so y nada más. Un solo NEEDED, y el único `[deps] build = []` de la campaña: 130 líneas de Rust que no dibujan ni hablan wayland. Se incluye en la imagen sabiendo que falla, para que el hueco sea MEDIBLE en vez de supuesto. Error exacto capturado corriéndola desde cosmic-term dentro de la VM: panicked at src/main.rs:76:10: failed to send screenshot request: Portal(ZBus(MethodError(ServiceUnknown, "The name org.freedesktop.portal.Desktop was not provided by any .service files"))) Misma forma que la deuda de org.freedesktop.locale1: un nombre de D-Bus que nadie sirve. LA CADENA DEL PORTAL SON TRES ESLABONES, NO DOS. Medido en el fuente: xdg-desktop-portal-cosmic declara DBUS_NAME = "org.freedesktop.impl.portal.desktop.cosmic" (src/main.rs:27) — es BACKEND, no toma el nombre que los clientes buscan. Falta también el frontend xdg-desktop-portal, y ninguno de los dos está en ninguna cola. ⚠ CORRECCIÓN AL PROPIO RUNBOOK: decía que `gvfs` exigía «una campaña propia». Es falso desde que KDE selló las piezas. Verificado con `hammer hash` desde las dos colas —el método correcto para saber si una receta se comparte—: glib-shared 2.88.1 (b3:0584ce1f) y pcre2-shared (b3:f254abaa) resuelven IDÉNTICO desde incoming-cosmic ⇒ cero rebuild, los artefactos sirven tal cual. zlib-shared ya estaba en la cola. libffi entra estático dentro de la .so (su Requires.private lo ignora pkg-config fuera del modo estático). Lo que queda de `gvfs` NO es técnico sino una decisión: mete una segunda glib en la imagen —lo que GNOME midió y evitó— y re-hashea cosmic-files, que arrastra a cosmic-term y cosmic-edit porque lo usan como crate. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
04146ec77b |
🛍 cosmic: la tienda LISTA — el catálogo AppStream hubo que fabricarlo, y el <provides> la vaciaba
Validado con pantalla: «Popular apps» poblada (App Library, Files,
Launcher, Settings), «Recently updated», y la búsqueda `text` devolviendo
COSMIC Text Editor. 2564 colores sobre un escritorio completo.
DOS TRAMPAS ENCADENADAS, y la primera invalida lo que dije al escribir la
receta:
1. El backend `pkgar` NO lee /usr/share/metainfo/*.metainfo.xml —los
ficheros que instala cada receta—. Lee el CATÁLOGO, o sea
{/usr/share,/var/lib,/var/cache}/{swcatalog,app-info}/{xml,yaml}/, que en
una distro normal genera `appstreamcli compose`. Sin ese fichero la
tienda abre perfecta y no lista NADA. Lo genera ahora
qemu-desktop-image.sh agregando los metainfo en un <components>: doce
líneas de python, cero AppStream y cero glib.
2. Con el catálogo puesto listaba 2 de 7. Los metainfo que genera `xdgen`
escriben <provides> con los envoltorios <mimetypes>/<binaries>, y el
crate `appstream` espera los hijos PLANOS del esquema de catálogo: muere
con «The tag provide doesn't have a value» y DESCARTA EL COMPONENTE
ENTERO, callado. Los dos que se veían eran justo los que no tienen
<provides>. Se elimina el bloque al agregar.
Cómo se diagnosticó, que es lo reutilizable: desde el lanzador la salida del
proceso no llega al log de la sesión. Hay que abrir cosmic-term DENTRO de la
VM y correr `rm -rf ~/.cache/cosmic-store; RUST_LOG=info cosmic-store`. El
rm no es opcional: la tienda cachea el parseo en bitcode y sin borrarlo
repite el resultado viejo.
Y el deadline del panel es una CARRERA, no un umbral: un arranque de esta
tanda salió mutilado (130 colores) con el anfitrión ocioso y -smp 8. Si sale
mutilado con carga baja, rearrancar antes de culpar al propio cambio.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
b51f90ffea |
🛍 cosmic: cosmic-store — sella (b3:a06437f7), y BoringSSL cruza a musl sin cmake
La quinta aplicación, y la primera de la suite que choca con que hammer es
OTRA distro: una tienda es la cara de un gestor de paquetes y el de abajo no
es el suyo. De los cuatro backends de `src/backend/`:
flatpak pide libflatpak (GObject) ⇒ la cadena glib COMPARTIDA más
ostree/libsoup/gpgme: la torre de C que esta campaña no tiene
packagekit Rust puro (packagekit-zbus) pero necesita el DEMONIO en el bus
rpm-ostree irrelevante
pkgar el único que arranca: ni demonio ni enlace, lee el AppStream
del sistema — o sea los .metainfo.xml que instalan las recetas
ALCANCE HONESTO: con pkgar NAVEGA, no INSTALA. Ninguna operación está
cableada al .swm de hammer (Etapa F). El camino para arreglarlo quedó
identificado y no cuesta un solo .so de C: servir
`org.freedesktop.PackageKit` sobre .swm, mismo patrón que
arje-logind-compat.
HALLAZGO REUTILIZABLE: `aws-lc-sys` (BoringSSL, C + ensamblador) compiló
bajo zig-cc/musl SIN cmake y SIN perl — ninguno de los dos está en los 182
binarios de work/builder-rootfs/usr/bin. Tomó el camino de bindings
pregenerados (`cargo:rustc-cfg=universal`) y compiló los 21 MB de
libaws_lc_crypto.a con el crate `cc`. El `Compiling cmake v0.1.58` del log
es el crate ayudante, que se compila aunque el binario no se invoque. Esto
destraba cualquier receta futura que entre con rustls por defecto, que hoy
es casi todo lo que use reqwest.
NEEDED: libxkbcommon.so.0 y libc.so, igual que cosmic-edit.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
539e2acd5b |
✎ cosmic: cosmic-edit VALIDADO en QEMU — y el deadline del panel sí mira la carga del anfitrión
El editor abre desde el lanzador (Super → «text» → primer resultado) y se
ESCRIBE: la evidencia tiene `hammer edita` tecleado sobre la línea 1 y el
punto de modificado en la pestaña. 2105 colores, icono en el dock con el
punto de «en ejecución». Hidratación 72 recetas (era 71).
CORRECCIÓN al runbook, medida acá: decía «no es carga del anfitrión (falla
con el anfitrión ocioso)», cierto para 4 vCPU pero se leía como que con
`-smp 8` el anfitrión daba igual. Dos arranques de la MISMA imagen con la
MISMA línea de QEMU:
load ≈ 6 (otro agente compilando) → 130 colores, mutilado, `deadline has
elapsed` en el log
anfitrión ocioso (load ≈ 1,8) → 1671 colores, completo
Este anfitrión tiene 8 núcleos, así que `-smp 8` le da la máquina entera a
la VM y cualquier compilación compite por los mismos hilos. Receta: mirar
/proc/loadavg antes de creerle a un arranque mutilado.
También: con las cuatro aplicaciones en el dock el escritorio completo da
~1670 colores, no 894. El umbral útil es «cientos vs miles».
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
232f23c5a8 |
⚙ cosmic: cosmic-settings — el panel de control, y NO arrastra medio sistema
Sellada b3:716dac53. Cola 33/33, escritorio-cosmic 71/71. Abre desde el lanzador con la barra lateral entera (Red, Bluetooth, Accesibilidad, Escritorio, Pantallas, Sonido, Energía, Entrada, Aplicaciones, Fecha y hora, Sistema y cuentas). Tarda ~20s con render por software; no está colgado. La sorpresa buena: nada de NetworkManager, libpulse, udisks ni accountsservice — habla con los daemons por zbus, que es Rust puro. Se verificó ANTES de escribir la receta listando los crates -sys del Cargo.lock, que es donde vive la verdad sobre qué C hace falta: sólo drm-sys, input-sys, libudev-sys, dav1d-sys, wayland-sys (dlopen) y gettext-sys. Regla barata: grep '^name = ".*-sys"' Cargo.lock antes de adivinar deps por lo que el programa hace. Volvió a morder la doble barra de cosmic-protocols// (404 de GitHub, muere en el fetch con tres reintentos). Segunda víctima ⇒ es patrón de la suite, no rareza de un repo. Instala 32 .desktop, uno por página. Y default_schema va con find, no cp plano: es el árbol <Componente>/v1/<clave> de cosmic-config, donde cada clave es un fichero con su nombre. Deuda que deja su propio log: org.freedesktop.locale1 no lo sirve nadie ⇒ la página de idioma no podrá cambiar nada. Mismo tipo que login1, mismo arreglo. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
23c0e82527 |
📁 cosmic: cosmic-files — la 2ª aplicación, y «ya está compilado» era falso por una línea
Sellada b3:48d2b072. Cola 32/32, escritorio-cosmic 70/70. Abre desde la biblioteca y lista el sistema de ficheros real de hammer (bin 72 ítems, dev, ente, etc, lib, lost+found). Entró creyendo que era casi gratis porque cosmic-term ya la compila como crate. No lo era: cosmic-term la declara con default-features = false. Lo que un paquete cuesta depende de con qué features lo pide quien lo usa, así que «ya se compiló» puede ser falso. Dos features apagadas, las dos por medición: · gvfs trae gio/glib y el enlace final pide las glib COMPARTIDAS; el corpus sólo las tiene estáticas. Se pierden montajes remotos, no la navegación local. Por eso tampoco se construye cosmic-files-applet: su Cargo.toml fija gvfs a mano. · wgpu desbordó el filesystem dos veces (No space left on device en /src/target) con wgpu+naga+ash+glow+spirv a codegen-units=1. Sin él el árbol queda en ~2 GB, y no se pierde nada: el resto de la suite pinta con tiny-skia y la imagen no tiene GPU. Y la regla que dejó el intento con glib declarado: el error fue «Package libpcre2-8, required by glib-2.0, not found» — el que falla no es la dep sino lo que su .pc declara en Requires. Declarar una dep trae su artefacto, no su clausura de pkg-config; se lee con grep ^Requires sobre los .pc ANTES de gastar el build. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
e39610588d |
🖥 cosmic: cosmic-term — la primera APLICACIÓN, y la biblioteca deja de estar vacía
Sellada a la primera (b3:d0ea1c1e). Cola 31/31, escritorio-cosmic 69/69. Dentro de la ventana: bash-5.3#, uname -srm devuelve Linux 6.16.12 x86_64 —el kernel propio de hammer— y qalc -t '6*7' devuelve 42, o sea la calculadora que empaquetamos una hora antes. Se abre con click en su icono en la biblioteca, que hasta hoy salía vacía con razón: los 20 .desktop de la imagen eran NoDisplay=true. Éste no lo es. Lo que arrastra y no se adivina: su Cargo.toml depende de cosmic-files, o sea que el gestor de ficheros entra como LIBRERÍA (selector y drag-and-drop) y compilar la terminal compila medio gestor de ficheros. En esta suite las aplicaciones se usan unas a otras como crates, y el grafo de Cargo no se parece al mapa de componentes. De paso, empaquetar cosmic-files como aplicación queda casi gratis. wgpu viene en default, al revés que el resto de los clientes: se deja, porque wgpu y naga ya se habían compilado enteros para cosmic-workspaces y apartarse de las features por defecto es apartarse de la única combinación que upstream prueba. Cierra con dos NEEDED. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
9665cc29d4 |
cosmic: la calculadora del lanzador ANDA — el stdin de qalc era el stdout
=123*456 → 56088 en el lanzador. libqalculate re-sellado b3:edb8d14d. La causa del «no lee nada de la tubería» no era readline, ni el toolchain, ni la versión: el binario salía DINÁMICO pese a link="static", porque libtool se come el -static que inyecta el harness. Y en un musl dinámico stdin, stdout y stderr se resolvieron por copy relocation a UNA SOLA ranura de BSS compartida —las tres en la misma dirección—, así que fileno(stdin) daba 1: el stdin del programa era el stdout. Eso explica la asimetría que parecía absurda, que qalc -f /dev/stdin funcionara (abre el fd por RUTA, sin tocar el FILE* roto) y qalc leyendo stdin no. Fix: make LDFLAGS="-all-static -no-pie", el mismo par que ya usa libxml2. Con él los tres símbolos vuelven a tener direcciones distintas en .rodata. Regla para el runbook: link="static" en la receta NO garantiza un binario estático — readelf -d y nm -S | grep ' std' lo contestan en dos segundos. Segundo muro: qalc pregunta si activar autocalc antes de leer nada, el plugin le manda la expresión y cierra, la expresión se consume como respuesta y qalc nunca llega a guardar config ⇒ vuelve a preguntar siempre. Se siembra qalc.cfg desde cosmic-start, política de imagen como el color de fondo. Y hay que repetir el -L de los alias de curses en el make: el LDFLAGS del make pisa al del configure. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
03ec0e6827 |
cosmic: libqalculate + gmp + mpfr — qalc anda, y el plugin del lanzador igual no lo puede usar
Las tres selladas a la primera (gmp b3:d99a0a5d, mpfr b3:13982d20, libqalculate b3:6bb435a7). La cadena entera desde una tecla está en el catálogo: Super → cosmic-launcher → pop-launcher → plugin calc → qalc → mpfr → gmp. Cola 30/30, escritorio-cosmic 68/68. qalc FUNCIONA: -t '2+2' da 4, -f fichero anda, e interactivo sobre terminal calcula. Pero el plugin lo invoca SIN expresión, con stdin en tubería, le escribe la cuenta y cierra — y en ese modo nuestro binario no lee nada. Acotado a que, con el EOF ya pendiente en un stdin que no es terminal, readline() devuelve NULL antes de entregar la línea que sí está en el búfer. Descartado midiendo, para no repetirlo: no es el toolchain (una sonda estática musl del sandbox lee la tubería en C y en C++); no es readline vs no-readline (sin ella es peor: no lee nunca); no es la versión de readline (una 8.3 sombra no movió el síntoma, y se descartó en vez de dejar una receta duplicada inútil); y no es el descriptor 0, porque Could not open "/dev/stdin". —el mismo pipe reabierto por ruta— sí funciona. El que no sirve es el FILE* stdin, y ahí queda la pista. Dos gotchas del empaquetado: gmp va con --disable-assembly (elige rutinas mirando la CPU de quien compila, o sea hornearía la ISA del laptop en el hash), y el configure de libqalculate no encuentra readline porque prueba -lncurses/-lcurses/-ltinfo y el corpus sólo empaqueta libncursesw.a — los alias van en un directorio local, no ensuciando /usr/lib, que es la evidencia de qué se declaró. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
505eaf5e44 |
cosmic: pop-launcher — el lanzador eran DOS programas, y ahora Super abre
cosmic-launcher sólo dibuja: manda lo tecleado por stdin a un proceso hijo, pop-launcher, que es quien busca. Sin ese binario la ventana no tiene qué mostrar y no se muestra — mismo modo de falla que el panel sin applets: falta un HIJO, no una librería, y el log del padre se lee sano. Vive en otro repo (pop-os/launcher), fuera del pin epoch-N. La versión la fija el Cargo.lock de cosmic-launcher (rev a332a3a7 de la 1.2.7), no el último tag: el lock es lo que garantiza que hablen el mismo protocolo. Tarball por commit, porque no hay tag que nombre esa rev. Selló a la primera, b3:64a5cbaa, con un solo NEEDED: libc.so. Verificado de punta a punta: Super abre el lanzador, «?» lista los seis plugins con su sintaxis (o sea que la enumeración y el IPC JSON-sobre-stdio andan) y «=2+2» LANZA el plugin, que contesta «qalc command is not installed». Esa respuesta es la mejor prueba disponible: el hijo corrió, evaluó y devolvió fila. Falta libqalculate, que es un paquete, no un problema. Cola 27/27, escritorio-cosmic 63/63. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
cd1497d740 |
🏔 cosmic: EL ESCRITORIO ENTERO DIBUJADO — panel, dock y applets en QEMU
26/26 recetas selladas, escritorio-cosmic 62/62. La captura (895 colores) muestra el panel superior con Workspaces/Applications, reloj y los applets de a11y, audio, red, batería y encendido; el dock inferior con lanzador, workspaces y biblioteca; y el fondo en el color exacto que configura cosmic-start. 48 procesos cosmic estables a los 30s. Y CORRIGE UN DIAGNÓSTICO MÍO. Cuando el panel selló y no dibujó, lo atribuí a que le faltaban los applets. Hacían falta —sin ellos el panel está vacío— pero no eran la causa de la pantalla lisa: -device virtio-gpu-pci no reemplaza la VGA por defecto de QEMU, la SUMA. Dos cards, dos outputs, cosmic-bg pinta en los dos y el panel se ancla en uno; el screendump capturaba el otro. Log impecable, pantalla lisa. Con -vga none sale entero. Un síntoma puede tener dos causas suficientes: arreglar la primera no prueba nada. También: PATH como primera línea de cosmic-start. El getty da un PATH sin /usr/bin y en la imagen mkdir sólo vive ahí, así que los cuatro mkdir -p fallaban en silencio — gratis hoy porque los directorios venían horneados, fatal el día que cambie la imagen. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
e99fc836fb |
cosmic: los applets necesitan la libdbus COMPARTIDA, y el linker lo dice una hora tarde
`cosmic-applets` declaraba `dbus` a secas. Alcanza para que el build.rs de libdbus-sys pase —le basta el .pc, que el paquete del daemon trae— y el fallo salta recién en el enlace final del multiplexor: 'unable to find dynamic system library dbus-1'. El corpus sólo empaqueta libdbus-1.a; el .so vive en `dbus-shared`, que es lo que ya declaraban settings-daemon y pipewire. Era la única receta de la cola que pedía la estática. De paso, las cuatro piezas que spawnea el PANEL (no cosmic-session) entran como raíces de hydrate-cosmic.sh: se invocan por AppID, así que ningún grafo de deps las alcanza. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
d724f0e267 |
🎉 cosmic: LA SESIÓN ARRANCA ENTERA — el camino de producción, no el andamio
cosmic-session levanta la cadena completa sobre el kernel de hammer con arje-zero
como PID1: cosmic-comp → settings-daemon → notifications → panel → osd → bg. El
fondo pinta (164 colores, el azul configurado) y el cursor está.
Los cuatro que faltan (app-library, launcher, workspaces, greeter) dejan una línea
de error! y la sesión SIGUE VIVA — exactamente lo que la tabla de .expect del
runbook predecía. Verificado, no supuesto.
cosmic-notifications sellado (b3:3e2a5478) completa el mínimo viable de cuatro.
Nota de método: esta corrida fue headless porque el Xwayland del laptop perdió la
autorización a mitad de sesión ('Authorization required, but no authorization
protocol specified'). El screendump por el monitor de QEMU sirve igual y es la
forma automatizable de la regla de validar con pantalla.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
999e9bdcb5 |
cosmic: los componentes que MATAN la sesión son TRES, no uno — corrección medida
El arranque en modo session murió con 'failed to start notifications daemon'
(main.rs:306). Grepeando '\.expect(' aparecen los tres:
main.rs:255 cosmic-settings-daemon
main.rs:306 cosmic-notifications
main.rs:325 cosmic-panel
O sea que el mínimo viable de una sesión COSMIC son CUATRO binarios: compositor
más esos tres.
Cómo me equivoqué, que es la parte reusable: leí start_component(), vi que sólo
logueaba, y generalicé a 'todos menos el settings-daemon'. Pero notifications y
panel NO PASAN por esa función — tienen su propio .expect() unas líneas antes.
Buscar la función que lanza no es lo mismo que buscar los .expect del fichero, y
grepear la construcción que mata cuesta lo mismo y no generaliza de más.
De paso, el bloque que configura el fondo de color sale del branch de modo bare:
estaba adentro, así que en modo session cosmic-bg se quedaba con el wallpaper por
defecto (que vive en git-lfs y no existe) y la pantalla salía negra por una razón
distinta de la que se estaba investigando.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
516610b307 |
cosmic: cosmic-panel selló y no pintó — le faltaban los HIJOS, no una librería
cosmic-panel (b3:ac5e48c5) arranca perfecto: lee su config, crea su wl_output, dice 'Spawning applets' y 'Done spawning applets'. Y la pantalla no cambió ni un color. La respuesta estaba en esa misma línea: spawnea TRECE clientes por AppID y ninguno existía. Un panel sin applets no es un panel vacío, es un panel que no tiene nada que medir y no se dibuja. Es la misma forma del muro de los typelibs en GNOME: un componente puede arrancar sin errores y no pintar porque lo que le falta es un HIJO. El log del padre se lee sano. La receta cubre el panel entero de una: upstream compila UN binario multiplexor y cada applet es un symlink con el nombre que el panel invoca; despacha por argv[0]. Veinte symlinks, dos binarios. Fase compile custom porque hay que construir DOS targets (los default-members) y 'cargo rustc --' sólo admite uno. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
570fd3747e |
🧮 cosmic: trazarle la yupana — el frente existía en el store y el ábaco no lo veía
Faltaba la mitad del método. SÍ cruzaba incoming-cosmic (lo usé antes de tocar libdisplay-info, pipewire y glib), pero la campaña no estaba en el KHIPU: build-state.py sólo conocía --kde y --gnome, y targets.toml no declaraba perfil. Y eso no era cosmético. Antes de este commit, decía 21 dependientes transitivos y dos imágenes; ahora dice 31 y TRES — escritorio-cosmic entre ellas, con incoming-cosmic=10 en el reparto por cola. O sea que el próximo que tocara libinput, libudev-zero o mesa habría MEDIDO DE MENOS, que es exactamente el punto ciego que la metodología existe para cerrar. Tres piezas: - build-state.py --cosmic (y su build-state-cosmic.json). - perfil.escritorio-cosmic en targets.toml, con las raíces que cosmic-session levanta MÁS los datos que ningún [deps] alcanza (iconos, xkb, fuentes, bash, dbus). Primera medición: 54/61 listo, faltan 7. - el LATIDO lo regenera, por la misma razón por la que se le agregó GNOME en su momento: un frente que el cron no regenera envejece en silencio, y un grafo viejo miente con la misma cara que uno fresco. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
98608524dd |
cosmic: COSMIC_MODE viaja como fichero, no como variable
El getty ejecuta cosmic-start sin ambiente heredable, así que probar el modo session exigía editar el script. Ahora la imagen hornea /etc/cosmic-mode, mismo truco que /etc/gnome-mode. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
78899549fe |
cosmic: el wallpaper por defecto vive en git-lfs — fondo de color liso en la imagen de prueba
El default de cosmic-bg apunta a una imagen del repo cosmic-wallpapers, cuyo tarball de GitHub pesa 20 KB: son punteros LFS, no imágenes. Una receta escrita del modo normal produciría un paquete de ficheros de texto que además PARECERÍA correcto — nombre bueno, ruta buena. Mientras tanto cosmic-start escribe la config de usuario con una fuente Color, que cosmic-bg soporta de fábrica. Va en el lanzador y no en el artefacto porque es política de esta imagen de prueba, no algo que el paquete prometa. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
ef4b18bc88 |
🖥 cosmic: COMPONE EN QEMU — cosmic-comp presenta frames sobre el kernel de hammer
Pantalla completa en el gris de COSMIC (39,41,42) con el cursor dibujado, 134 colores distintos, validado CON PANTALLA (DISP=gtk + screendump). Entra el andamiaje completo: hydrate-cosmic.sh (44 recetas, 0 faltantes), qemu-desktop-image.sh y cosmic-start-qemu.sh. Tres causas medidas en tres arranques, ninguna donde uno la busca: 1. cosmic-settings-daemon NO es opcional: cosmic-session lo lanza con .expect() (main.rs:255) y panickea si falta. Corrige lo que este runbook afirmaba. De ahi el modo bare del lanzador, que separa como compone de como arranca la sesion. 2. La pantalla negra era libz.so.1: kms_swrast_dri.so lo NEEDea y el corpus solo traia zlib estatica. Sin driver de software no hay GBM y el compositor arranca igual, negro. Causa a tres capas del sintoma. 3. Los clientes no pueden ser estaticos: wayland-client entra con la feature dlopen y un musl estatico no tiene dlopen funcional — moria 'The wayland library could not be loaded' CON el .so presente. Y dos carreras con /run (dbus y XDG_RUNTIME_DIR) de la misma forma que el bug de PolicyKit1 de hoy en GNOME: comprobar al principio y usar al final. Se crea justo antes de usar. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
98a8152f49 |
cosmic: hidratador del cierre de runtime — 35 recetas, 0 faltantes
Hermano de hydrate-gnome.sh y con su misma propiedad: el cierre sale del GRAFO REAL de recetas y el artefacto se elige por 'hammer hash' (la receta de HOY), no por el más reciente del store, que con dos artefactos del mismo paquete miente. Las raíces se nombran a mano porque en COSMIC la brecha entre cierre de build y cierre de runtime es enorme: cosmic-session lanza a sus componentes por PATH y por nombre, así que ninguno es dep de build de otro y el grafo no los ve. La lista autoritativa es cosmic-session/src/main.rs. Resultado: 207 binarios, 109 .so, y los siete NEEDED de cosmic-comp resueltos dentro del propio cierre. Falta sólo el loader musl, que lo pone la base metal. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
c0055331c7 |
gnome: esperar el NOMBRE de PolicyKit1 antes de lanzar a sus clientes
accounts-daemon y upowerd morían al arrancar: el shim de polkit se lanza en background y tarda ~2s en adquirir org.freedesktop.PolicyKit1, ellos llamaban a polkit_authority_get_sync() en ese hueco, D-Bus intentaba ACTIVAR el servicio y fallaba con 'Failed to execute program ... Permission denied'. Lo peor era el informe: los tres esperar_nombre estaban al final, así que para cuando corrían el shim ya tenía el nombre y el resumen daba 'PolicyKit1 OK' sobre dos clientes ya muertos. Un chequeo posterior a la carrera no la mide. esperar_nombre pasa a definirse antes del primer daemon y el bloque de polkit espera su propio nombre antes de que arranque ningún cliente suyo. Lanzar en orden no es estar listo en orden. De paso queda cerrado el ítem 4 del runbook: validación CON PANTALLA (DISP=gtk) del Overview con el PID1 sellado nuevo — 689 colores distintos, con evidencia. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
84e088fd13 |
imágenes: PID1 sale del artefacto sellado, no del directorio base congelado
Las 4 imágenes de escritorio (GNOME + los 3 de KDE: qemu, metal, dual) fundían `work/metal-rootfs` por hardlinks y se llevaban SU arje-zero, que era del 2026-06-19: ese directorio se armó a mano en la campaña de metal y nadie lo regeneraba al re-sellar la receta. Resultado: todas arrancaban con un PID1 de hace mes y medio, en silencio. No es hipotético — se comió un fix real. El `identity mismatch` del bus del fractal estaba arreglado río arriba y la VM seguía imprimiendo el mensaje viejo porque el binario de la imagen no venía de la receta (ver el comentario de recipes/arje-zero.toml). El síntoma engaña porque el directorio base es LEGÍTIMO para todo lo demás —busybox, firmware, el kernel EFI-stub, la estructura de /etc—: sólo la pieza que TAMBIÉN es receta se queda atrás, y justo esa es PID1. La regla que queda escrita en el helper: si algo del rootfs tiene receta, la imagen lo toma del artefacto sellado, no de la copia congelada. El helper va en scripts/lib/ y no inline ×4 a propósito: el porqué es largo y vale una sola copia. Elige el artefacto por `hammer hash` (el de la receta de HOY, no el más nuevo por fecha, que miente en cuanto conviven dos) y ABORTA si falta, porque seguir con el PID1 congelado es exactamente el modo de falla que cierra. Probado: las 4 pasan `bash -n` y la imagen GNOME lo ejecuta bien sourceado (`✓ e570c1482432 (el de work/metal-rootfs era de 2026-06-19)`), con la VM ya validada booteando ese PID1. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
7190cc48a3 | estado: cosecha granja 2026-07-30T23:20:59Z — avance del árbol KDE | ||
|
|
2430528c16 |
dbus: las políticas de login1 y PolicyKit1 viajan en su ARTEFACTO, no en el script de imagen
Cierra un TODO que el propio script tenía escrito («esto pertenece al artefacto de arje-logind-compat, no a la imagen») y que estaba bien puesto: **un servicio que no puede adueñarse de su nombre no es un servicio**, así que su política D-Bus es parte de lo que el paquete promete, igual que el binario. Con la política en el script de UNA imagen, cualquier otra —metal, KDE, mirada— se llevaba el daemon y no podía usarlo. arje-logind-compat b3:b4795829 · arje-polkit-compat b3:6c82f44b. Radio de las dos: 0. **Y la comprobación que reemplaza a escribirlas atrapó un bug de verdad en el primer intento.** Mover algo a un artefacto sólo es una mejora si se NOTA cuando falta, así que el script pasó de ESCRIBIR los .conf a EXIGIRLOS. Falló al toque: `✗ falta org.freedesktop.login1.conf`. Causa — el script inyectaba **sólo el binario** del artefacto (`install -Dm755 .../usr/bin/...`), así que el .conf existía en el store y nunca llegaba a la imagen. Sin esa comprobación habría sido el fallo tardío de siempre: daemon que arranca, no adquiere el nombre, y 25s de espera por servicio sin decir por qué. Verificado de punta a punta con las políticas viniendo del artefacto: los cuatro nombres del bus arriba (login1, PolicyKit1, Accounts, UPower) y el audio intacto. El `zz-` de la de polkit no es decorativo y queda explicado en su receta: a diferencia de login1, ese nombre YA tiene política —la trae el artefacto de polkit— y permite `own` sólo al usuario polkitd; dbus lee system.d en orden alfabético y las reglas posteriores ganan, así que un fichero que ordene después AÑADE el permiso sin descartar el resto de upstream. ColorManager sigue sin aparecer: es lo de colord, ya diagnosticado hasta dónde llega y fuera del alcance de este cambio. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
beb2851d99 |
colord: el demonio ya se construye (b3:8100fa39) — arranca, abre sus DB y NO adquiere el nombre
La receta iba con `-Ddaemon=false` y el razonamiento era «mutter enlaza libcolord, no necesita el demonio». Cierto para COMPILAR mutter y falso para el escritorio andando: el artefacto INSTALA el `.service` de activación (`Exec=/usr/libexec/colord`) y ese binario no existía, así que cada arranque se comía 25s de timeout. **No era «colord apagado» sino colord roto de forma lenta** — el peor de los dos, porque no falla, tarda. Su propio comentario marcaba la condición de vuelta: «si alguna vez hace falta el demonio de verdad, vuelve con polkit encima». Polkit ya está (arje-polkit-compat). Y medido: prender el demonio **no agrega una sola dep nueva** salvo polkit-gobject-1, ya sellada — el bloque de dependency() de colord 1.4.7 es de nivel superior y pedía gusb/gudev/libudev igual con daemon=false. El coste estaba pagado desde el 2026-07-27 sin que nadie lo cobrara. **PERO EL TIMEOUT SIGUE**, y lo que aprendí es dónde NO está: - El binario existe y arranca: `/usr/libexec/colord` crea sus tres bases en /var/lib/colord (mapping.db, storage.db) y lo dice en el log. - Con `--verbose` NO hay una línea más después de abrir la tercera base. - La política D-Bus SÍ permite `own` a root, y el `.service` corre como root: no es el caso de polkit (donde `own` estaba restringido al usuario `polkitd`). - Los cuatro `cd_main_load_introspection` que van entre las DB y `g_bus_own_name` (cd-main.c:2434-2460) leen de un **GResource compilado en el binario**, no de disco, así que no pueden faltar. Los XML instalados en /usr/share/dbus-1/interfaces son para otros. ⇒ Queda entre `cd_main_load_introspection` y `g_main_loop_run`, y el siguiente dato es si el proceso sigue vivo en ese momento. **Esa comprobación me faltaba en el script** — reportaba «colord lanzado (pid N)» sin verificar nada, que es exactamente el error que yo mismo había señalado para upowerd («un pid no es un servicio») y no apliqué acá. Ya está puesta: sin ella, «no apareció el nombre» no distingue MURIÓ de SE COLGÓ, y son dos investigaciones distintas. Verificado que no hay regresión en lo que sí funciona: audio (48. HDA Intel, sink y source reales) y vídeo (0 page-flips fallidos) siguen bien con el demonio en la imagen. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
888fdc31c7 |
firmware: SOF para TigerLake — el DSP de audio, pineado como el de i915
El kernel ya traía el driver (SND_SOC_SOF_TIGERLAKE); faltaban los blobs, y sin ellos SOF carga y falla: en el laptop no hay sonido aunque ALSA esté. Mismo patrón que i915 con su DMC/GuC — driver desde fuente, firmware pineado por contenido, porque Intel no libera el código y la soberanía build-from-source no aplica a datos fijos. Tres piezas, cada una por un motivo distinto: - `sof-tgl.ri` + `sof-tgl-h.ri`: el firmware del DSP. Se copian LOS DOS porque el driver elige según el SKU y no quiero hornear la suposición. **`cp -L` es obligatorio**: en linux-firmware son SYMLINKS a `intel-signed/`, y un symlink relativo copiado a otro árbol apunta a la nada. Verificado: los tres quedan ficheros reales (525K/447K/95K). - `sof-tgl.ldc`: el diccionario de logs del DSP. No es opcional en la práctica — el driver lo pide al inicializar y sin él el firmware arranca SIN TRAZA, o sea que el día que algo falle no hay por dónde mirar. - 47 topologías (`sof-hda-generic-*`, `sof-tgl-*`): describen el grafo de audio. El driver pide UNA por nombre derivado de la máquina, y no se puede saber cuál sin el hardware delante. Copiar de más cuesta megas; copiar de menos cuesta un viaje físico al laptop para descubrir qué nombre pidió. ~3 MB en total. Si no hay SOF en el origen, AVISA y NO falla: el audio del laptop se pierde pero la imagen sigue booteando y en QEMU suena por HDA legacy — fallar bloquearía builds que no necesitan SOF. Verificado que no hay regresión: con los blobs en la imagen, el audio de la VM sigue funcionando por la ruta HDA (48. HDA Intel [alsa], sink y source reales) y cero page-flips fallidos. **El camino SOF en sí queda SIN VALIDAR hasta el próximo viaje al metal** — en QEMU no se ejerce, y eso está escrito en la receta del kernel en vez de dado por bueno. De paso, la cabecera del script deja de mentir: se llama «firmware» y no «wifi» porque copia las TRES familias de blobs que el metal necesita (iwlwifi, i915, SOF). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
8c3bd323d5 |
audio: ALSA encendido en el kernel — y el muro real es libudev-zero, no el stack de audio
ALSA =y en linux-metal (b3:613bca15): HDA legacy + codecs (lo que emula QEMU y usan las máquinas pre-SOF), SOF para TigerLake (el laptop del target NO suena por la ruta legacy: Intel movió el audio al DSP) y SND_USB_AUDIO. Todo =y porque el producto es monolítico. ⚠ Falta inyectar el FIRMWARE de SOF en la imagen (intel/sof/*.ri, sof-tplg/*.tplg), igual que metal-firmware.sh hace con los tgl_* de i915: sin blobs el driver carga y falla. FUNCIONÓ LA MITAD: en la VM `/dev/snd` ya trae controlC0 + pcmC0D0p/c y /sys/class/sound lista card0. El kernel detecta la tarjeta. Pero wpctl sigue con `Devices:` vacío. **Y LA CAUSA ES ESTRUCTURAL, no una propiedad que falte.** `get_card_nr` de SPA (alsa-udev.c:178-183) sólo acepta el device CARD —`/sys/.../sound/card0`—, que es un device de CLASE: sin major:minor, sin nodo en /dev. Y `udev_enumerate_scan_devices` de libudev-zero recorre EXCLUSIVAMENTE /sys/dev/block y /sys/dev/char (udev_enumerate.c:281), o sea sólo devices CON nodo; el udev real enumera /sys/class entero. **El device que SPA necesita nunca entra en la enumeración**: no hay guarda que sacar, falta la mitad del espacio de búsqueda. Salidas: (a) enseñarle a libudev-zero a recorrer /sys/class —radio 51 sellados— o (b) empaquetar eudev. Es decisión de arquitectura, no parche. CORRIJO ALGO QUE ESCRIBÍ ANTES: el parche `pipewire-sound-initialized.patch` se hizo creyendo que SOUND_INITIALIZED era el bloqueo, y NO lo era — con el parche aplicado el resultado no cambió. Se conserva porque la incompatibilidad que describe es real (sin udevd nadie pone esa propiedad y SPA descartaría toda tarjeta en cuanto la enumeración funcione), pero su prosa ahora empieza avisando que no es la solución. Sacarlo del camino importa: dejarlo presentado como el arreglo mandaría al próximo a buscar en el lugar equivocado. Dos arreglos de andamiaje que costaron un ciclo cada uno: - **`-nic none` por defecto.** Agregar la tarjeta de sonido CORRIÓ LAS RUTAS PCI, la entrada de disco cacheada en las VARS de OVMF dejó de coincidir, y la firmware se fue al orden por defecto: PXE v4, PXE v6, HTTP… minutos de timeouts. Con un TIMEOUT corto eso se lee como «la VM no arrancó» y el serial sólo dice `PXE-E16: No valid offer received`. - El filtro del log de wireplumber era `alsa|udev|sound|card|monitor` con `tail -40`, y se llenó de bluez/v4l2/libcamera —tres monitores que avisan que su plugin no está— dejando fuera justo las líneas de ALSA. **Un filtro ancho con cola corta es peor que ninguno.** Ahora filtra `alsa` y además copia el log entero a la raíz ext4 (tmpfs muere con la VM). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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>
|
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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>
|
||
|
|
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> |
||
|
|
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>
|
||
|
|
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>
|