libva sube al corpus y la copia de incoming-kde se JUBILA (git mv, no copia: dos
ficheros para un artefacto es el cuadro de las dos glib esperando a derivar). La
mudanza fue gratis y medida antes: las cinco deps de libva viven sólo en el
corpus, así que incoming-kde ya las resolvía por caída al padre y hammer hash dio
el MISMO ArtifactHash en las dos rutas (b3:405c6211).
libva pasa a -Dwith_wayland=yes, que eso SÍ cambia el hash. La razón está en
mpv/meson.build:1464: el feature `vaapi` se requiere contra
`vaapi-drm or vaapi-wayland or vaapi-x11 or vaapi-win32` ⇒ -Dvaapi=enabled a
secas no habilita NADA. De los cuatro backends, x11/win32 están fuera por
Wayland-only y vaapi-drm exige features[drm] de mpv, apagado porque vo=drm pide
libdisplay-info. Queda vaapi-wayland, que pide libva-wayland.pc.
Evidencia, no sólo sello: meson lista «vaapi vaapi-wayland» entre los features
habilitados, y el binario sellado trae NEEDED libva.so.2 + libva-wayland.so.2.
Radio medido antes de tocar: 2 dependientes (kpipewire, spectacle), los dos
reconstruidos. Las 7 imágenes siguen en 0 en deuda.
⚠ El driver es RUNTIME (intel-media-driver / gallium VA por dlopen): que esto
selle y que --hwdec=vaapi funcione en una máquina son cosas distintas.
La receta llevaba --disable-x86asm heredado de cuando ffmpeg entró SÓLO para
kpipewire (codificar un stream de escritorio, donde da igual). Para el
reproductor era decodificar sin SIMD.
Dos recetas —ffmpeg.toml y mpv.toml— prohibían tocarlo con la misma razón: un
hash distinto dejaría DOS ffmpeg peleando por las mismas rutas en una imagen KDE,
y el arreglo correcto sería «promover una sola y jubilar la de la cola». Eso ya
había pasado: incoming-kde/ffmpeg.toml no existe y hay UNA sola receta ffmpeg en
todo el disco. La prohibición sobrevivió a la condición que la justificaba.
--x86asmexe=nasm explícito y nasm (2.16.03) a [deps].build: sin ensamblador
declarado configure apagaría x86asm en SILENCIO, sellando un artefacto con otro
hash y sin la SIMD que dice traer.
Evidencia, no sólo sello: configure imprime «x86 assembler nasm», compila los
objetos X86ASM, y libavcodec.so pasa de 12.685.744 a 14.454.288 bytes (+1,77 MB).
Radio medido antes de tocar (yupana radio ffmpeg): 4 dependientes, ninguno
transitivo de más — mpv, wf-recorder, kpipewire, spectacle. Los 4 reconstruidos y
sellados; las 7 imágenes siguen en 0 en deuda.
targets.toml declara 7 perfiles; drenaje.json listaba 5. escritorio-cosmic (cola
incoming-cosmic) y escritorio-sway (cola incoming-wlr) declaraban una cola que
ningún grafo de GRAFOS contenía, así que cargar() devolvía None y --todos hacía
`continue` pelado. Dos imágenes enteras fuera del artefacto sin dejar rastro, y
los dos números —5 medidos, 7 declarados— no se cruzaban en ningún lado.
Mismo olvido que ya costó 17 días de build-state-wlr.json congelado: la lista de
grafos crece a mano y se queda atrás cuando se abre una cola.
Tres cambios:
- GRAFOS suma los grafos de cosmic y wlr.
- Un perfil sin medir se anota en el artefacto (`sin_medir`), se grita por stdout
y drenar.py sale 1. Regla 3 del repo: un ausente falla ruidosamente.
- cosecha-cron deja de tragarse la salida; filtra las líneas ⚠ al log, que si no
llegaban como un "falló" mudo que no dice cuál imagen falta.
Medido: las 2 imágenes que nadie miraba estaban limpias, 0 en deuda. Ahora son
7/7 verificadas en vez de 5 verificadas y 2 supuestas.
dolphin filelight kate kinfocenter konsole kscreen plasma-integration
plasma-desktop. Ninguna era fallo de receta: las 8 murieron el 2026-09-03 con
«No space left on device» y el bucle las anotó ✗ igual que a una que no compila.
Reintentadas tal cual, sin tocar una sola receta, sellaron las 8 a la primera.
escritorio-kde pasa a 263/263 y drenaje.json queda en 0 en deuda en los cinco
perfiles: base, cli, escritorio-{gnome,kde,mirada}.
`vigia-imagen.py` daba ✗ en cursores en DOS de los cuatro escritorios. No es cosmético: con el
cursor por software —obligatorio en virtio-gpu y en todo render por CPU— el compositor dibuja la
imagen que le da el TEMA, y sin tema el ratón se mueve invisible. cosmic llegó a 43/43 y sway a
173/173 así, porque un tema de cursor no es dep de build de nadie: sólo entra si se DECLARA.
`adwaita-cursors` (corpus, 48.1, data-only): del mismo tarball que `adwaita-icon-theme` pero SÓLO
`Adwaita/cursors/` — 39 ficheros y 14 MB, sin un icono. Promover el tema entero habría regalado a
sway y a cosmic los iconos de GNOME, que está anotado como decisión pendiente y no como olvido.
Las dos cosas que el tarball no trae y la receta fabrica:
· los nombres X11 heredados (`left_ptr`, `xterm`, `watch`, `hand2`…) son enlaces que genera el
`meson.build` de upstream. El mapa se PARSEA de ahí, no se copia: copiado envejece en silencio.
Si el origen de un enlace no existe, la fase falla — upstream pone un `files()` como aserción.
· `/usr/share/icons/default/index.theme` con `Inherits=Adwaita`. Sin `XCURSOR_THEME` en el
entorno, libXcursor y wlroots buscan el tema llamado literalmente `default`; sin él no hay
puntero AUNQUE Adwaita esté instalado. Es el eslabón que hace que ande sin configuración.
⚠ no declarar esta receta junto a `adwaita-icon-theme`: chocan en `Adwaita/cursors/*`.
Y el vigía estaba midiendo el invariante de al lado: exigía `index.theme` en el directorio para
contar un tema, que es correcto para ICONOS —la búsqueda XDG recorre `Directories=`— y falso para
CURSORES, porque libXcursor abre `<tema>/cursors/<nombre>` directo y el índice sólo hace falta para
seguir un `Inherits=`. Con la receta instalada seguía diciendo «NINGÚN tema de cursor».
De paso queda anotado en `targets.toml` que el comentario de cosmic decía «sin ellos arranca sin
puntero» sobre `cosmic-icons`, que no trae cursores: describía una protección que no existía.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CGyBj4QyeCZiwLMkP9GJp6
D8 decía que sniper «entra al store por `file_drop`». Dos correcciones, y la
primera es de vocabulario: **`file_drop` en hammer es otra cosa** — una
operación de `hammer apply` que coloca un fichero en el sistema instalado
verificando su hash. No tenía nada que ver con sellar. Lo que sella es lo de
siempre, una receta. Queda escrito en el ADR: un término inventado que suena a
mecanismo existente manda a buscar el código donde no está.
`recipes/steam-runtime-sniper.toml` sella el árbol del runtime (11196 ficheros)
pineado por el sha256 que ya estaba verificado. Entra donde Arch y Ubuntu no
pueden por una propiedad, no por simpatía: **no muta** —nadie le instala nada
adentro— así que el mismo tarball da siempre el mismo árbol y sellarlo es una
afirmación verdadera.
**La marca: `foreign = true`.** No cambia el build en un byte y **no entra en
`hash_inputs`** (describe procedencia, no identidad — hay test). Lo que cambia
es contable: `build-state.py` la clasifica `ajeno`, la resta del denominador de
las imágenes y la deja fuera del recuento de recetas. Sin eso, sellar un
prebuilt habría subido la cifra que todo el mundo lee como «cuánto
construimos» — el riesgo que el ADR escribió antes de que existiera la primera
instancia. Verificado: sigue diciendo 821 recetas, y aparte
`de las ajenas, 1 selladas al store (prebuilt pineado, sin procedencia de fuente)`.
Y la diferencia con el otro ajeno: `xwayland` no se hashea (no hay receta, y un
hash afirmaría que lo reproducimos); el sellado **sí conserva su hash**, porque
está en el store y que un artefacto exista mientras el grafo lo niega sería otra
forma de mentir. Comparten el estado, que es lo que protege la cifra.
**`hammer qorpa import --from-store <hash>`** lo consume, y ahí está el detalle
que hace que valga: la imagen se registra bajo el **sha256 del archivo de
upstream**, no bajo el ArtifactHash. Al revés, la imagen del store y la traída
con `pull` serían dos imágenes distintas con los mismos bytes y las instancias
de dos máquinas dejarían de coincidir — justo lo que el pin existe para evitar.
El árbol se **enlaza**: una imagen nunca se escribe (lo que escribe la instancia
va a su `upper`), así que compartir inodos con un artefacto sellado y de sólo
lectura es correcto por construcción y la imagen cuesta ~0 bytes. La contracara
conocida de `.dmerge`: mientras el artefacto siga en el store, borrar la imagen
no libera disco; `--copy` lo evita.
Licencia `LicenseRef-qorpa-ajena-no-enumerable` a propósito: adentro hay cientos
de paquetes Debian y no podemos enumerarlos; vacío se leería como «todavía no la
poblamos». SDD 20 lo recoge y afila la distinción: replicarla a nuestras
máquinas es lo que ya hace ADR 0013 con las fuentes; publicarla a terceros sigue
pidiendo licencia y marca.
29 tests verdes. El sellado en sí corre aparte, esperando el lock de la granja.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QZjGRqvjWij9dew7NVFu4Q
`-DKCOREADDONS_USE_QML=OFF` estaba desde que se escribió la receta, con el argumento razonable de
que un framework tier-1 no debería arrastrar QML. El precio no se vio hasta hacer CLIC en el
lanzador dentro de QEMU: `kickoff` importa `org.kde.coreaddons` y ese módulo lo instala esta receta
y ninguna otra ⇒ **el menú de aplicaciones no abría**. La librería C++ salía completa, sus 70
consumidores enlazaban bien y el perfil reportaba 100%.
Es la forma más pura del «sellado ≠ arranca»: no falta una librería, falta una porción OPCIONAL de
una librería que sí está. Ninguna métrica de clausura puede verlo — mide recetas, no features.
`qtdeclarative` ya estaba en `[deps].build`, así que prenderlo no agrega una dep: deja de tirar lo
que ya se podía construir.
VERIFICADO CON UN SOLO BUILD (56 s), a propósito, en vez de pagar la cascada para averiguarlo:
· panel → menú abre (usuario, buscador, Favoritos/Todas, Aplicaciones/Lugares/Sesión)
· buscar «konsole» + Enter → la terminal arranca y corre:
uname -a → Linux (none) 6.16.12 #1 SMP PREEMPT_DYNAMIC … x86_64
konsole --version → konsole 25.04.3
Es la cadena completa del escritorio por primera vez: panel → menú → búsqueda → app → shell.
COSTO, medido antes de tocar y confirmado después: `yupana radio kcoreaddons` predijo 71, y el grafo
regenerado da exactamente **71 en deuda** (`escritorio-kde 192/263`). Queda como deuda DECLARADA
para una campaña de granja; la imagen de hoy corre con un kcoreaddons más nuevo que aquel contra el
que enlazaron sus consumidores, lo que es legítimo porque cruza un SONAME (misma ABI, sólo se suma
un módulo QML) — la misma regla que decidió la promoción de pipewire.
De yapa: `export SHELL=/bin/sh` en plasma-start-qemu.sh. El aviso rojo de konsole («Could not find
'', starting '/bin/sh' instead») era real y no venía de /etc/passwd —que dice /bin/sh— sino de que
konsole lee $SHELL y este getty no es un login shell.
Y el barrido que encuentra esto sin hacer clic queda escrito en el runbook: cruzar los `import` de
los `.qml` instalados contra los módulos con `qmldir`. Además de éste destapó `org.kde.kscreenlocker`
y `org.kde.newstuff.core`, sin diagnosticar.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YGXe6mShYYw6V8ea1dQ13u
De un binario ajeno no hay fuente que leer. Lo único observable es lo que el
kernel le NIEGA y anota, y hasta acá ese canal existía en el build pero ninguna
instancia lo abría. `hammer qorpa run <id> --evidence` levanta el lector
(`harkaq-audit`) en el HOST —el audit no está namespaceado— antes de que arranque
la instancia, y al terminar imprime uno de tres estados. Los tres, medidos:
HERMÉTICO 0 denegaciones Y el canario las respalda
IMPURO `touch /usr/INTRUSO; mkdir /opt/INTRUSO` →
fs.make_reg · /usr fs.make_dir · /opt
SIN EVIDENCIA quitándole las capabilities al lector. NO es «limpio»
**El canario es lo que hace que «cero denegaciones» valga algo:** un fichero
donde la política no alcanza; al leerlo, el kernel emite una denegación que
revela el `domain=` de ESTE dominio Landlock, un número que desde fuera no se
adivina. Sin él, `denials=[]` sería el instrumento callado.
**Dos condiciones estructurales, y se FALLA en vez de dar un veredicto vacío:**
con `nesting` no hay Landlock (D9 conflicto 1) ⇒ o anidás o auditás; y sin
`seal_image` la política es `rw /` ⇒ no hay NADA denegable y el veredicto sería
limpio por construcción, no por mérito. No es un defecto de la implementación:
**la evidencia sólo existe donde algo puede ser negado.**
**Un bug del propio instrumento, que sólo salió usándolo:** sin CAP_AUDIT_READ
el kernel RESPONDE que no (`NLMSG_ERROR`/EPERM) y el lector ignoraba esa
respuesta esperando una que no iba a llegar — 8 s por consulta, 16 s en su
compuerta. Como `qorpa run` lo despierta al terminar, moría por señal dentro de
la compuerta **sin emitir nada**: un «no» tardío se parecía demasiado a un
cuelgue. Ahora atiende el NLMSG_ERROR y dice su motivo en 2 s. Y si aun así el
veredicto sale vacío, se reporta con el código de salida del lector, que es el
único dato que queda.
Guardián: `scripts/qorpa/evidence-probe.sh`, con las tres aserciones. La 2 es la
que sostiene a la 1 — sin algo que TIENE que salir sucio, «HERMÉTICO» lo cumple
igual un canal muerto. Comprueba también las capabilities del lector, que **se
pierden en cada recompilación** y son la forma más probable de que el canal
muera en silencio.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QZjGRqvjWij9dew7NVFu4Q
Verificado en QEMU tras declarar `breeze-icons`: el panel pasa de «reloj solo» a completo —
kickoff, gestor de tareas, bandeja (notificaciones, volumen, teclado, red), reloj y mostrar
escritorio. Confirma que el panel nunca estuvo roto: no tenía iconos que dibujar. Y el mensaje
`kf.iconthemes: Icon theme "breeze" not found` desapareció del log.
⚠ CORRIJO una atribución del commit anterior (d69c437): dije que la barra derecha vacía de la
captura de GNOME era el mismo hueco de iconos, y NO lo es — `scripts/gnome/hydrate-gnome.sh` SÍ
hidrata `adwaita-icon-theme`, así que ese rootfs tenía tema. El hueco de GNOME es real pero está
en el PERFIL (`targets.toml`, que es lo que define la imagen enviable), no en aquella corrida;
la barra derecha vacía tiene otra causa, sin diagnosticar.
Y la segunda captura es un hallazgo nuevo, encontrado haciendo CLIC en el lanzador desde el
monitor de QEMU:
kickoff/main.qml:191:25: Type FullRepresentation unavailable
Header.qml:18:1: module "org.kde.coreaddons" is not installed
`kcoreaddons.toml` pasa `-DKCOREADDONS_USE_QML=OFF` ⇒ el módulo QML no se construye ⇒ **el menú
de aplicaciones no abre**. `yupana radio kcoreaddons` = 71: prenderlo es campaña de granja.
El barrido que lo generaliza (cruzar los `import` de los `.qml` instalados contra los módulos con
`qmldir` del rootfs) encontró además `org.kde.kscreenlocker` y `org.kde.newstuff.core`.
El runbook queda con las tres piezas que hacen falta en gioser, que no tiene ni ventana ni socat:
STAGE en el volumen (o EXDEV), monitor por socket unix desde python, y cómo hacer CLIC con un
ratón RELATIVO (fijar contra una esquina y moverse desde ahí).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YGXe6mShYYw6V8ea1dQ13u
Medido sobre los artefactos del cierre de cada imagen, contando qué `usr/share/icons/*/`
trae un `index.theme` (que es lo que convierte un directorio en un tema):
escritorio-kde sólo Breeze_Light y breeze_cursors — que son CURSORES
escritorio-gnome CERO, ni siquiera hicolor
escritorio-cosmic Cosmic + hicolor <- el único que estaba bien
escritorio-sway CERO
Las dos capturas de QEMU de hoy ya lo mostraban y se leyeron como «arranca»:
- `plasma6-qemu-2026-09-03-kactivitymanagerd.png`: panel con el reloj y nada más. Los `.so`
de los applets estaban TODOS instalados; lo que faltaba era qué pintar. `kickoff`,
`systemtray`, `showdesktop` y `trash` SON un icono, así que sin tema quedan de ancho cero
— el reloj se ve porque dibuja TEXTO. El log lo decía en una línea:
`kf.iconthemes: Icon theme "breeze" not found.`
- `gnome-shell-qemu-2026-09-03-libs-compartidas.png`: barra superior con la fecha y el pill
de espacios, y la DERECHA vacía — red, volumen y batería son iconos.
`breeze` (ya declarado) es el tema de WIDGETS y CURSORES; los ~14.000 iconos viven en
`breeze-icons`, receta aparte, sellada desde siempre y declarada por NADIE. Igual
`adwaita-icon-theme` en GNOME, que además trae los XCursor (su cabecera dice por qué:
sin tema de cursor no hay puntero visible con el cursor por software de virtio-gpu).
Es la figura de las fuentes y de `foot` otra vez: data de RUNTIME, ninguna arista de BUILD
la alcanza, y la métrica de clausura no la echa de menos porque mide lo declarado.
`hicolor-icon-theme` —el fallback obligatorio de freedesktop— se promueve al corpus para que
lo alcancen las cuatro imágenes: hash IDÉNTICO desde la cola y desde el corpus
(b3:98ad44a5), y sus 4 consumidores (adwaita-icon-theme, cosmic-icons, cosmic-app-library,
cosmic-launcher) miden el mismo hash antes y después ⇒ un solo artefacto, CERO rebuilds.
Cierre tras declararlos, todo sellado y sin deuda:
kde 263/263 (+2) · gnome 158/158 (+2) · sway 173/173 (+1) · cosmic 133/133 (igual)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YGXe6mShYYw6V8ea1dQ13u
Hasta acá el ADR afirmaba «el manifiesto es la verdad, el upper es caché»
mientras `recreate` confesaba en su propia salida que «instalarlos todavía es a
mano». Con eso el `upper` SÍ era el activo: un blob irreemplazable, que es justo
lo que hammer existe para no tener.
`hammer qorpa provision <id>` instala lo declarado, y **`recreate` lo llama
solo** (`--no-provision` para saltarlo).
Cuatro decisiones, cada una con su porqué:
- **El gestor se DETECTA** en la vista merged (apt, pacman, dnf, apk), no se
configura: cada imagen trae el suyo. Y no se multiplexa detrás de un comando
único —el `pmm` de Bedrock que el ADR rechaza—: se elige cuál correr.
- **`provision` ensancha la política y lo dice en la cara.** Instalar pide las
tres cosas que una instancia bien declarada no tiene: red, root y la imagen
sin sellar. Se ensancha SÓLO durante esa operación, el manifiesto no se toca
y el siguiente `run` vuelve a lo escrito. En silencio sería lo que D7 prohíbe.
- **El registro vive FUERA del `upper`** (`provisioned.toml`): dentro se iría
con la capa. Por eso `recreate` lo borra — un registro que afirma paquetes
sobre una capa recién vaciada es la forma más pura del error de la regla 3.
- **Los nombres se validan y se comillan**: salen de un fichero que escribe una
persona, así que `strace; rm -rf /` no llega al guión.
**Las dos manías que sólo salen provisionando de verdad:** el bootstrap de Arch
trae la mirrorlist ENTERA comentada (pacman muere con «no servers configured») y
el llavero sin inicializar (toda firma inválida). El guión pone el mirror geo
oficial avisando cuál, y hace `pacman-key --init && --populate` sólo si falta.
`apt` no necesita ni un workaround: es el dividendo del rango de subuid.
Probado de punta a punta en los dos gestores —apt sobre Ubuntu base, pacman
sobre el bootstrap de Arch—: instalan, el binario corre después con la red
apagada, y un `recreate` tira la capa y la deja igual. 27 tests verdes.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QZjGRqvjWij9dew7NVFu4Q
Fondo Breeze + panel + reloj, sobre virtio-gpu con llvmpipe y SIN KVM (TCG puro:
gioser es un vServer sin virtualización anidada). Antes de 8df2559 esta misma imagen
daba pantalla negra con kwin=1 plasmashell=1.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0164nrZWZc78Mr2srrsnoM8U
El paso 6 quedaba parcial por esta frase: «pressure-vessel con un juego real
sigue sin ejercitarse», porque el runtime sniper sólo se baja al instalar un
juego y eso pide credenciales. Era un techo falso: el depot está publicado y
ahora pineado, así que se coloca a mano y la pregunta que ordenaba D6 se
responde entera.
**La evidencia**, dentro de una instancia qorpa sobre Ubuntu base, con `nesting`
y la jaula puesta:
os-release Ubuntu 24.04.3 LTS → Steam Runtime 3 (sniper)
ns de montaje mnt:[4026532468] → mnt:[4026532526]
/usr/lib/x86_64-linux-gnu → 675 libs de sniper, libSDL2 incluida
Contenedor de Valve anidado dentro del nuestro, con el runtime real adentro.
**Y la concesión resultó de verdad:** con `nesting = false` el mismo comando
muere en `bwrap: Creating new namespace failed: Operation not permitted`. Queda
como guardián (`scripts/qorpa/pressure-vessel-probe.sh`), que exige las DOS
mitades — sin la negativa, «no salió sniper» lo cumpliría también un cuelgue.
Tres cicatrices del camino, todas en los comentarios:
1. **`ldd --version` es la comprobación equivocada** y es la primera que uno
escribe: pressure-vessel importa la libc del host cuando es más nueva que la
del runtime, así que ver la glibc de afuera adentro es lo correcto y no
prueba nada. El veredicto es `os-release`.
2. **`SALIDA=$(timeout … qorpa run …)` se cuelga para siempre** aunque timeout
mate al hijo: la sustitución no espera al PROCESO, espera a que se cierre el
PIPE, y pressure-vessel deja descendientes con el fd abierto. A fichero
termina y devuelve su código.
3. **Dos `run` seguidos sobre la misma instancia fallaban** con `Can't make
overlay mount … Device or resource busy`. El kernel niega dos overlays vivos
con el mismo `upper` porque eso corrompe la capa — o sea que el EBUSY es un
guardián correcto a destiempo: la corrida anterior ya devolvió el prompt y su
namespace no terminó de reaparse. `run` reintenta acotado y, si sigue tomado,
dice la causa en vez de soltar el mensaje crudo de bwrap.
El punto 3 salió porque el guardián exige evidencia POSITIVA de la denegación:
con «no apareció sniper» habría dado OK tapando un fallo distinto.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QZjGRqvjWij9dew7NVFu4Q
Arrancando la imagen KDE en QEMU: kwin toma el DRM, expone wayland-0, plasmashell
arranca… y la pantalla se queda EN NEGRO con los dos procesos vivos. El serial
repetía 'STATUS: kwin=1 plasmashell=1' durante minutos, que se lee como salud.
La causa estaba en el log de Qt, no en el estado de procesos:
kde.plasmashell: Aborting shell load: The activity manager daemon
(kactivitymanagerd) is not running.
No sale de la clausura de las 7 raíces porque NO es dep de build de nada: plasmashell
lo pide por D-Bus al arrancar. scripts/kde/plasma-start-qemu.sh ya lo lanzaba (l.188);
lo que faltaba era que el paquete entrara al rootfs. Ya estaba sellado — declararlo no
cuesta un build.
Misma figura que las raíces de runtime de GNOME (imports.gi.*): lo que se invoca por
bus es invisible al grafo de deps.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0164nrZWZc78Mr2srrsnoM8U