Commit Graph
1155 Commits
Author SHA1 Message Date
sergioandClaude Opus 5 ea210ba3cd 🔌 portal-probe: activar el portal en vez de exigirlo presente
Bug que la propia sonda destapó al usarla: los portales son servicios ACTIVABLES por
D-Bus, no demonios siempre presentes — el bus los arranca cuando alguien los pide,
leyendo su `.service`. `NameHasOwner` NO dispara esa activación, sólo pregunta.

Costó una corrida entera de diagnóstico: la sonda dijo "nadie posee
org.freedesktop.portal.Desktop — no hay frontend de portal en el bus" sobre un
sistema donde el portal andaba perfecto, sólo que dormido.

Ahora pide `StartServiceByName` y deja que el bus decida. Si de verdad falta el
`.service`, falla con ServiceUnknown y ahí el diagnóstico sí es real; y distingue
"arrancado ahora" de "ya estaba corriendo", que no es lo mismo cuando lo que se
investiga es una carrera de arranque.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-05 10:25:55 -04:00
sergio b77cc68a91 estado: cosecha granja 2026-08-05T14:11:28Z — avance del árbol KDE 2026-08-05 10:11:29 -04:00
sergioandClaude Opus 5 6ec556decc 🔌 portal-probe: la sonda del portal XDG, en C sobre libdbus
Los portales NO son RPC: son un protocolo asíncrono en dos tiempos. Cada método
devuelve al instante un object path de `Request`, y el resultado llega DESPUÉS como
señal `Response` sobre ese path. `dbus-send` ya salió para entonces — por eso la URI
del FileChooser nunca se pudo capturar desde el shell.

Y hay una razón más dura: el portal ata la sesión al SENDER. CreateSession con un
dbus-send y SelectSources con otro llegan de nombres únicos distintos y el segundo se
rechaza. Hace falta UNA conexión viva durante todo el intercambio.

El path del Request se PREDICE (/…/request/<sender>/<token>, sender = nombre único
sin ':' y con '.'→'_'). Eso existe a propósito: permite suscribirse ANTES de llamar.
Esperar al path devuelto para recién ahí hacer AddMatch es una carrera real — el
portal puede haber emitido ya la señal.

En C y no con ashpd: el árbol fuente de esta receta es el repo de la propia
herramienta de build, así que ashpd significaría sumar ~150 crates al Cargo.lock de
hammer por una sonda de diagnóstico. libdbus ya está en la imagen y en el corpus
(y con `libdbus-1.a`, así que la sonda sale ESTÁTICA, sin un solo NEEDED). Sobre
todo: acá el protocolo se VE. Una sonda cuyo valor es documentar un handshake no
debería esconderlo tras una biblioteca que lo abstrae.

Cuatro modos: `version` (qué interfaces sirve y en qué versión), `screencast` (el
handshake de 4 pasos hasta el fd de pipewire), `filechooser` (captura las uris) y
`screenshot`. El impresor de valores es recursivo y NO filtra: si el portal devuelve
un campo que este programa no conoce, sale igual por pantalla — que es exactamente lo
que uno quiere de una sonda.

Validado en el host contra el portal real: compila sin warnings y lee las versiones
(Screenshot v2, FileChooser v4, Settings v2).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-05 10:06:02 -04:00
sergioandClaude Opus 5 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>
2026-08-05 09:46:41 -04:00
sergioandClaude Opus 5 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>
2026-08-05 09:46:21 -04:00
sergioandClaude Opus 5 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>
2026-08-05 07:51:36 -04:00
sergioandClaude Opus 5 5f606111d1 📂 cosmic: FileChooser ejercido — pero NO desde cosmic-store, y el motivo importa
NO SE PUEDE DESDE LA TIENDA. cosmic-store se compila con la feature
xdg-portal, pero su ÚNICO uso del selector (src/update.rs:505,
Message::RepositoryAddDialog) arranca con
`if backend_name == BackendName::FlatpakUser`: el diálogo sólo se abre para
añadir un repositorio flatpak, y esta imagen no construye el backend
flatpak. La feature está compilada y el punto de llamada es INALCANZABLE.
Tener la feature encendida no es tener el flujo disponible.

El camino que sí ejerce la interfaz es llamarla directo por D-Bus, que
además prueba los tres eslabones sin depender de qué app la use:

  dbus-send --session --print-reply --dest=org.freedesktop.portal.Desktop \
    /org/freedesktop/portal/desktop \
    org.freedesktop.portal.FileChooser.OpenFile \
    string:"" string:Prueba dict:string:variant:handle_token,string:hammer1 &

Medido: el frontend devuelve el objeto Request con NUESTRO token
(/org/freedesktop/portal/desktop/request/1_113/hammer3) y el backend dibuja
el diálogo REAL — título «Prueba», el FS de verdad (run/tmp/dev/proc/sys),
panel de detalles (inode/directory, 963 items), Cancel/Open. La navegación
anda: doble clic en dev cambia la miga a «Filesystem › dev» y lista sus 129
entradas; seleccionar y pulsar Open lo cierra.

⚠ LO QUE NO QUEDÓ CAPTURADO: la URI devuelta. El Response de la spec de
portales es una señal UNICAST al llamador, y dbus-send termina apenas recibe
el method return, así que ya no está para recibirla; dbus-monitor con un
match rule normal tampoco la ve. Pide un cliente que implemente el ciclo
Request/Response, que es lo que hace ashpd dentro de las aplicaciones.
El diálogo está probado; la entrega del fichero a la aplicación, no.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-05 07:32:46 -04:00
sergioandClaude Opus 5 99e670ee4f 🚪 cosmic: las cinco interfaces del portal, sondeadas — y Access no es un hueco
Del lado CLIENTE (org.freedesktop.portal.Desktop): Screenshot 2,
FileChooser 3, ScreenCast 5, Settings 2.

`org.freedesktop.portal.Access` NO EXISTE, y está bien: Access vive sólo
como org.freedesktop.impl.portal.Access, del lado del BACKEND — es como el
frontend le pide al escritorio que muestre el diálogo de permiso. Mi primer
sondeo la pidió al frontend y el «No such interface» era un error DEL
SONDEO, no del portal.

Del lado BACKEND (impl.portal.desktop.cosmic): Screenshot 2, ScreenCast 4,
Settings 2; Access y FileChooser devuelven UnknownProperty 'version'. Ese
error PRUEBA que la interfaz está: si faltara, D-Bus contestaría «No such
interface». UnknownProperty = la encontró y esa implementación no publica
esa propiedad.

Y el ListNames muestra impl.portal.desktop.cosmic ACTIVADO junto a
impl.portal.PermissionStore: el frontend levantó al backend por D-Bus
activation, que es el eslabón que habilita el .service con @libexecdir@
sustituido.

ALCANCE HONESTO: esto prueba DISPONIBILIDAD y ENRUTADO, no los flujos
completos. La única ejercida de punta a punta —con fichero en disco— sigue
siendo Screenshot.

Próximo: ejercer FileChooser desde una app que use el portal (cosmic-store
se compiló con la feature xdg-portal; cosmic-edit NO la usa, va con el
selector propio de cosmic-files como crate) y ScreenCast, que es la que
ejercita pipewire de verdad.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-05 06:50:30 -04:00
sergioandClaude Opus 5 ada054cf07 🚪 cosmic: LA CADENA DEL PORTAL CERRADA — cosmic-screenshot captura de verdad
cosmic-screenshot corrido desde cosmic-term dentro de la VM devuelve una
ruta en vez del panic de ayer, y el fichero existe:

  /root/Pictures/Screenshots/Screenshot_2026-08-05_10-18-14.png
  -rw-r--r-- 1 root root 42256 Aug  5 10:18
  0000000 211   P   N   G  \r  \n 032  \n     ← firma PNG

El veredicto es el FICHERO, no el código de salida: que no panickee sólo
prueba que encontró el servicio; que haya 42 KB con \x89PNG prueba que el
compositor entregó píxeles por la cadena entera
(cliente → portal.Desktop → impl.portal.desktop.cosmic → cosmic-comp).

Cinco recetas: fuse3, json-glib (sin introspección), xdg-desktop-portal
1.18.4, clang18 y xdg-desktop-portal-cosmic. Dos raíces del perfil, porque
son dos PROCESOS que se encuentran por D-Bus y ningún [deps] los relaciona.

El runbook queda con las decisiones y sus precios (pin 1.18.4 por gstreamer,
el choque de gvdb y los dos caminos descartados por medición, de dónde sale
libclang) y con cuatro gotchas de andamiaje que costaron tiempo real:

  · --offline SIN --locked cuando la receta parchea el manifiesto
  · el worker NO puede construir la cola COSMIC (golden de 2026-07-15,
    cola posterior ⇒ nada es cache-hit allá): «rootfs laptop ≠ worker»
    pero con el STORE
  · farm-down cosecha /opt/hammer/store y farm-up ancla el store en
    /mnt/cosecha/store — directorios DISTINTOS, no symlink
  · pipewire sin --wrap-mode=nodownload: ante una dep faltante intenta
    bajarse un subproyecto y el error miente («This is a Meson bug»)

Próximo: las otras cuatro interfaces (FileChooser, ScreenCast, Settings,
Access). El andamiaje QMP ya está.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-05 06:20:39 -04:00
sergio d55a83e428 estado: cosecha granja 2026-08-05T10:14:35Z — avance del árbol KDE 2026-08-05 06:14:35 -04:00
sergioandClaude Opus 5 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>
2026-08-05 06:04:13 -04:00
sergio 3f3ae98a63 estado: cosecha granja 2026-08-05T09:14:09Z — avance del árbol KDE 2026-08-05 05:14:09 -04:00
sergio d08d61f698 estado: cosecha granja 2026-08-05T08:43:52Z — avance del árbol KDE 2026-08-05 04:43:52 -04:00
sergio 987d14b7af estado: cosecha granja 2026-08-05T08:12:53Z — avance del árbol KDE 2026-08-05 04:12:54 -04:00
sergioandClaude Opus 5 e914dd63e9 🚪 cosmic: el BACKEND del portal + clang18 — recetas listas para la granja
clang18                    b3:62c6bfb5   (sólo libclang.so)
  xdg-desktop-portal-cosmic  b3:97dfddd8

EL PARCHE DE UNA LÍNEA resultó ser el que se esperaba: xdp-cosmic declara
cosmic-files con features = ["gvfs", "wayland"] FIJADAS a mano —mismo patrón
que deja fuera a cosmic-files-applet— así que apagarla desde afuera no
alcanza. El sed la saca y queda la misma combinación que ya compilaron
cosmic-term y cosmic-edit. Se pierden los montajes remotos DENTRO del
selector del portal, no el selector.

PERO APARECIÓ UN ESLABÓN QUE NO ESTABA EN EL PLAN: libclang.

  xdp-cosmic declara pipewire y libspa-sys como deps DURAS (screencast)
    → libspa-sys/build.rs corre bindgen::builder() INCONDICIONAL
      → bindgen carga libclang.so en tiempo de build

Verificado que no hay atajo: ese build.rs no tiene rama alternativa, a
diferencia de aws-lc-sys —que sí cae a bindings pregenerados
(cargo:rustc-cfg=universal) y por eso cruzó a musl sin cmake ni perl—. Y
libclang no está ni en el corpus ni en los 182 binarios del rootfs del
constructor: llvm18 se selló con -DLLVM_ENABLE_PROJECTS="".

Lo barato es que NO se recompila LLVM: el artefacto llvm18 ya publica
usr/include/llvm, usr/include/llvm-c y usr/lib/cmake/llvm, así que clang18
es un build de clang CONTRA un LLVM sellado. Se instala sólo libclang.so y
clang-c/: el binario `clang` no es el objetivo — el compilador de esta
distro sigue siendo zig-cc, y sumar otro sería lo contrario de la deuda que
la campaña «matar gcc» viene pagando.

Patrón gcc-de-gueto (igual que llvm18 y cmake): g++ con -static-libstdc++
-static-libgcc para que la .so quede con NEEDED sólo libc.musl y no contagie
el runtime C++ de Alpine a cada build que la declare.

Vale decir de dónde sale este costo: no de COSMIC, sino de que pipewire-rs
genera sus bindings en cada build.

Ambas van a la granja (decisión del usuario): mismo peso que llvm18, que ya
se selló en el worker gordo.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-05 03:57:07 -04:00
sergio 71aeb36622 estado: cosecha granja 2026-08-05T04:05:55Z — avance del árbol KDE 2026-08-05 00:05:55 -04:00
sergioandClaude Opus 5 d664267eff 🚪 cosmic: EL FRONTEND DEL PORTAL sella — org.freedesktop.portal.Desktop existe
Tres recetas nuevas y el eslabón que faltaba de verdad:

  fuse3 3.18.2          b3:3a84af86
  json-glib 1.10.8      b3:dc8c8e78   (variante SIN introspección)
  xdg-desktop-portal    b3:f4adb8c9   1.18.4

El artefacto trae /usr/share/dbus-1/services/org.freedesktop.portal.Desktop.service
—el nombre exacto que cosmic-screenshot no encontraba— más
xdg-document-portal y xdg-permission-store. NEEDED del frontend: libz,
libpipewire y libc.

CUATRO COSAS MEDIDAS QUE VALEN MÁS QUE LAS RECETAS:

1. PIN A 1.18.4 POR GSTREAMER. Desde 1.20 meson pide
   dependency('gstreamer-pbutils-1.0') sin required: —para validar sonidos
   de notificación— y eso arrastra gstreamer + gst-plugins-base. La 1.18.4
   no lo pide: sus deps duras son glib/gio/gio-unix, json-glib, fuse3,
   gdk-pixbuf y pipewire, y de ésas la única que faltaba era fuse3. Es un
   pin deliberado: el día que se quiera 1.22 el precio es gstreamer.

2. fuse3: NO poner -Ddisable-libc-symbol-version=true aunque suene a lo
   correcto para musl. Lo probé razonando eso y falla el enlace: la opción
   sólo hace que compat.c no emita los alias versionados, pero
   lib/meson.build:54 pasa --version-script INCONDICIONALMENTE, o sea que
   el script queda pidiendo símbolos que ya nadie define. Es una combinación
   incoherente de upstream, no una limitación de musl. La auto-detección de
   upstream tampoco conoce musl: sólo apaga versionado para __UCLIBC__ y
   __APPLE__. Se deja el defecto, que es con lo que Alpine construye.

3. json-glib NO se puede reusar de incoming-gnome: aquella está en la ISLA
   DINÁMICA (introspection=enabled, default_library=both) porque su .gir es
   entrada del .gir de evolution-data-server. Traerla metería toda la
   maquinaria de introspección de GNOME en la clausura de COSMIC para no
   usar un solo .typelib.

4. EL CHOQUE DE gvdb, y por qué se resolvió renombrando símbolos. El portal
   vendoriza gvdb y glib TAMBIÉN lo lleva adentro (GSettings): con glib
   estática el .a expone los símbolos y el enlazador ve dos definiciones.
   Los otros dos caminos se descartaron POR MEDICIÓN:
     · --allow-multiple-definition / -z muldefs: zig-cc NO lo acepta
       («unsupported linker arg»), y meson lo reporta como «Compiler
       hammer-zig-cc cannot compile programs», que manda a buscar el
       problema donde no está.
     · glib-shared: no es cambiar una dep sino abrir una cadena (json-glib y
       gdk-pixbuf también enlazan glib) y meter la segunda glib en la imagen.
   El renombrado con -D es total —afecta definición y usos, todos pasan por
   gvdb-reader.h— así que el binario queda con lector+constructor de la
   misma copia. Importa: glib empaqueta sólo el LECTOR, el CONSTRUCTOR
   existe únicamente en el portal.

Bonus de meson: las opciones de tipo lista se parten por COMAS, así que
-Dc_args/-Dc_link_args no sirven para banderas con comas; van por CFLAGS y
LDFLAGS. Y quitar un subdir() no es gratis: subdir comparte ámbito de
variables, y sacar subdir('tests') rompía el summary() que lee
enable_pytest.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-04 23:56:04 -04:00
sergioandClaude Opus 5 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>
2026-08-04 23:40:00 -04:00
sergio bf07e20deb estado: cosecha granja 2026-08-05T03:34:29Z — avance del árbol KDE 2026-08-04 23:34:29 -04:00
sergioandClaude Opus 5 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>
2026-08-04 23:14:01 -04:00
sergio f808693060 estado: cosecha granja 2026-08-05T03:04:12Z — avance del árbol KDE 2026-08-04 23:04:12 -04:00
sergioandClaude Opus 5 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>
2026-08-04 22:42:53 -04:00
sergio eb792b73b9 estado: cosecha granja 2026-08-05T01:00:58Z — avance del árbol KDE 2026-08-04 21:00:58 -04:00
sergioandClaude Opus 5 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>
2026-08-04 20:40:35 -04:00
sergio 326f8579eb estado: cosecha granja 2026-08-05T00:29:50Z — avance del árbol KDE 2026-08-04 20:29:51 -04:00
sergioandClaude Opus 5 d5f798a6b1 ✎ cosmic: cosmic-edit — la 4ª aplicación, y el Cargo.lock miente por exceso
El editor de texto sella en b3:2323a325, igual que el dry-run. Es la más
barata de las cuatro: depende de `cosmic-files` como CRATE con
`default-features = false`, así que su árbol ya estaba compilado (68 min de
enlace, no de compilación desde cero).

Lo que aprendió esta receta, y que corrige un borde de la regla anterior:
**el `Cargo.lock` lista lo POSIBLE, no lo ENCENDIDO**. Aparecen `gio-sys`,
`glib-sys` y `gobject-sys` —que en cualquier otro paquete mandarían a
declarar glib y de ahí a la cadena compartida— y sin embargo entran sólo por
la feature `gvfs`, que se apaga. El lock dice el universo; las features
dicen el recorte.

Features: `--no-default-features --features dbus-config,wayland`. Fuera
`gvfs` (pide las glib compartidas, el corpus las tiene estáticas) y `wgpu`
(el que desbordó el filesystem dos veces en cosmic-files).

La doble barra `pop-os//` que mordió en applets y settings acá está
comentada en el Cargo.toml; verificado con grep ANTES del build.

Evidencia: el binario enlaza sólo `libxkbcommon.so.0` y `libc.so` — dos
NEEDED, el mínimo de la suite.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-04 20:21:56 -04:00
sergio 6fefca620c estado: cosecha granja 2026-08-04T23:29:11Z — avance del árbol KDE 2026-08-04 19:29:11 -04:00
sergioandClaude Opus 5 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>
2026-08-04 17:21:53 -04:00
sergio bc6f686988 estado: cosecha granja 2026-08-04T21:20:21Z — avance del árbol KDE 2026-08-04 17:20:21 -04:00
sergio 7f91237282 estado: cosecha granja 2026-08-04T19:47:49Z — avance del árbol KDE 2026-08-04 15:47:49 -04:00
sergioandClaude Opus 5 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>
2026-08-04 13:28:42 -04:00
sergio db986e7f00 estado: cosecha granja 2026-08-04T16:46:26Z — avance del árbol KDE 2026-08-04 12:46:26 -04:00
sergio 641e19824a estado: cosecha granja 2026-08-04T16:16:07Z — avance del árbol KDE 2026-08-04 12:16:07 -04:00
sergio 2e9610617e estado: cosecha granja 2026-08-04T11:31:08Z — avance del árbol KDE 2026-08-04 07:31:08 -04:00
sergio a7d1675093 estado: cosecha granja 2026-08-04T11:00:52Z — avance del árbol KDE 2026-08-04 07:00:52 -04:00
sergioandClaude Opus 5 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>
2026-08-04 06:32:27 -04:00
sergio 554fd8756d estado: cosecha granja 2026-08-04T10:30:18Z — avance del árbol KDE 2026-08-04 06:30:18 -04:00
sergio 087ee22e3d estado: cosecha granja 2026-08-04T09:29:54Z — avance del árbol KDE 2026-08-04 05:29:54 -04:00
sergioandClaude Opus 5 73e0bc7a3e cosmic: barrido de la cola tras el hallazgo del stdin — ningún otro paquete miente
De las recetas de incoming-cosmic que declaran link="static", ninguna tiene NEEDED
indebido ni los símbolos de stdio compartiendo dirección. Era un caso, no un patrón.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-04 05:15:02 -04:00
sergioandClaude Opus 5 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>
2026-08-04 05:13:14 -04:00
sergio 4d9f17dafb estado: cosecha granja 2026-08-04T08:58:50Z — avance del árbol KDE 2026-08-04 04:58:50 -04:00
sergioandClaude Opus 5 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>
2026-08-04 04:47:55 -04:00
sergio 3a7347634d estado: cosecha granja 2026-08-04T08:28:32Z — avance del árbol KDE 2026-08-04 04:28:32 -04:00
sergioandClaude Opus 5 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>
2026-08-04 04:00:12 -04:00
sergio 78cdc18a8c estado: cosecha granja 2026-08-04T07:57:13Z — avance del árbol KDE 2026-08-04 03:57:13 -04:00
sergioandClaude Opus 5 a232bcc0af cosmic: los atajos andan (Super+A, Super+W) y el panel tiene un deadline de arranque
Faltaba sanear un SEGUNDO fichero: system_actions de cosmic-settings-daemon, que liga
acción→comando, con la misma entrada ScreenReader que el enum del parser no conoce. Con
defaults roto no hay ligaduras; con system_actions roto hay ligadura y ningún comando.
Ahora Super+A abre la biblioteca y Super+W la vista de espacios de trabajo — con
miniatura VIVA del escritorio dentro, o sea que el camino DMA-BUF→GBM de cosmic-workspaces
anda de verdad. Super a secas no abre nada porque pop-launcher (el motor del lanzador)
no está en el catálogo; los atajos no tienen la culpa.

Me equivoqué de fichero teniendo el dato: el error traía línea y columna y busqué el
token en vez del fichero que lo tiene en esa posición. Costó 40 minutos de rebuild.

Y el panel tiene un DEADLINE para registrar su servidor D-Bus: con -smp 4 arranca sin
ala izquierda, sin reloj y sin dock (894 colores vs 130); con -smp 8 -m 8192 son 4 de 4
completos. Perseguí eso como una regresión mía, revirtiendo tres cambios inocentes, porque
usé el conteo de procesos como veredicto: un escritorio sano muestra 32, no 48. El
framebuffer es el veredicto; los procesos no distinguen «arrancó» de «dibujó».

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-04 03:18:41 -04:00
sergio 3f502afe9f estado: cosecha granja 2026-08-04T06:56:49Z — avance del árbol KDE 2026-08-04 02:56:49 -04:00
sergio c2bc71aa25 estado: cosecha granja 2026-08-04T06:26:32Z — avance del árbol KDE 2026-08-04 02:26:32 -04:00
sergio 2443743b18 estado: cosecha granja 2026-08-04T05:26:00Z — avance del árbol KDE 2026-08-04 01:26:00 -04:00
sergioandClaude Opus 5 39b91b5146 cosmic: la entrada anda — click y teclado por QMP; y 29 atajos caídos por UNA línea
El click sobre «Applications» abre la biblioteca (el color dominante pasa de fondo 91%
a 27,27,27 84%) y tecleando aparece «cosmic» en el buscador. Se maneja entero por QMP
con input-send-event, sin humano y sin ver la pantalla.

USB HID, no virtio-input: el kernel de hammer no trae VIRTIO_INPUT, así que
-device virtio-keyboard no crea ni un /dev/input/event*. Con qemu-xhci + usb-kbd +
usb-tablet anda, y además es lo que se va a usar en metal.

Y el hallazgo de fondo: Super no abría el lanzador TENIENDO la ligadura en el fichero.
keybindings.ron de epoch-1.5.0 liga Super+Alt+S a System(ScreenReader), acción que el
crate que lo parsea (cosmic-settings-config, rev 8c54bbbc) no tiene en su enum. RON no
ignora lo desconocido: falla el mapa entero y se caen las 29 ligaduras. El único rastro
era un WARN de cosmic-idle a 200 líneas del arranque hablando de un enum — el síntoma no
nombra ni la tecla ni el fichero. El pin lockstep fallando desde adentro de upstream.

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