Medido recorriendo los `.service` de D-Bus de TODO el store: los únicos backends de portal sellados
eran los de COSMIC y GNOME. Ninguno de KDE, y la cola `incoming-kde` no tenía ni el frontend.
Consecuencia concreta: la imagen KDE trae `obs-studio` con su plugin linux-pipewire, que captura
pantalla POR EL PORTAL — o sea que en Plasma no tenía con quién hablar mientras en los otros dos
escritorios ese frente estaba cerrado. Sin portal tampoco hay diálogo de fichero ni compartir
pantalla para nada que los use.
Van los DOS paquetes porque la cadena es de tres:
cliente → org.freedesktop.portal.Desktop [frontend] → org.freedesktop.impl.portal.* [backend]
El frontend se copia de la cola de COSMIC y **comparte artefacto**: hash idéntico (ecbe13f68eca6)
desde las dos colas ⇒ un solo directorio en el store, cero builds.
El backend es receta NUEVA, 6.7.2 — la MISMA versión que plasma-workspace, kwin y kscreenlocker de
esta cola, porque habla interfaces privadas de kwin para el ScreenCast y desalinear ahí es pedir que
dos mitades del mismo release se entiendan por casualidad. **Cero frontera nueva**: sus 22
dependencias (Qt6, KF6, KWayland, protocolos de Wayland, xkbcommon) ya estaban todas, verificadas
una por una antes de escribir la receta.
⚠ SIN EL PORTAL DE IMPRESIÓN, y la causa es más honda que el error. El build moría en
`src/print.cpp:27` con `'QtPrintSupport/private/qcups_p.h' file not found`, y la cadena está medida
entera: no hay NINGUNA receta de cups en el catálogo ⇒ qtbase 6.11.1 se construyó sin CUPS ⇒ su
`QtPrintSupport/private/` trae qpaintengine_alpha_p.h y qprintengine_pdf_p.h pero NO qcups_p.h.
No falta una cabecera: falta el subsistema. Un portal de impresión sin con qué imprimir no es
funcionalidad que se pierde, es código muerto que no enlaza.
Upstream no expone `option()` para portales —se compilan todos—, así que el parche va en TRES
sitios y no en uno: la fuente, la instanciación (desktopportal.cpp/.h) y **la lista de interfaces
que el backend ANUNCIA**. El tercero es el que se olvidaría y el que importa: anunciar
`impl.portal.Print` sin implementarlo hace que el frontend enrute a un portal que no contesta, que
es peor que no tenerlo. Cada `sed` lleva su `grep` de verificación al lado, para que el día que
upstream mueva esas líneas el parche falle RUIDOSO en vez de volverse inerte.
VERIFICADO sobre el artefacto sellado: publica `org.freedesktop.impl.portal.desktop.kde.service`,
y su `kde.portal` anuncia 17 interfaces con **0 apariciones de Print** e incluyendo ScreenCast,
Screenshot y RemoteDesktop, que es exactamente lo que OBS necesita. Y sobre el rootfs hidratado:
están el frontend (`org.freedesktop.portal.Desktop.service`), el backend y el `kde.portal`.
⚠ Y la licencia casi la firmo mal: leí la cabecera de UN fichero y generalicé. Contadas las
etiquetas SPDX del árbol entero: 88 `LGPL-2.0-or-later`, 23 de la fórmula de KDE e.V. y 1
`GPL-2.0-or-later`. El binario las enlaza a todas ⇒ la expresión es la CONJUNCIÓN.
El perfil pasa a 98 raíces, 361/361 listo, deuda 0.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LCt3ettR4Z7b6wPCBmbvEV
Paso 1 del SDD 27. Resultó ser UNA LÍNEA POR PERFIL: el mecanismo `hereda` ya existía en
`scripts/targets.py` —transitivo, con detección de ciclos y orden preservado— y `escritorio-sway`
ya lo usaba desde el 2026-08-07. Los otros tres nunca lo declararon, y eso no era una decisión: era
composición no declarada.
LO QUE ARREGLA, medido antes: de los 27 paquetes del perfil `base`, la clausura de escritorio-kde
alcanzaba DOS. Contra el rootfs real: sin `bash`, sin `sudo`/`doas`, sin `git`, sin `useradd`, sin
`gpg` y **sin `dhcpcd`** —o sea sin con qué pedir una IP—; y lo que parecía estar (`ip`, `mount`,
`fsck`) eran applets de busybox (`/sbin/ip → ../bin/busybox`).
DESPUÉS, verificado hidratando de verdad y no leyendo el grafo: en el rootfs aparecen `bash`,
`sudo`, `doas`, `git`, `dhcpcd`, `useradd`, `gpg`, `rg`, `fd`, `bat`, y `/sbin/ip` pasa a ser el
BINARIO de iproute2 en vez del applet.
raíces kde 49→96 · gnome 39→86 · cosmic 43→88
nodos kde 301→356 · gnome 204→256 · cosmic 162→216
deuda 0 en los tres — no hubo que construir NADA, ya estaba todo sellado
colisiones nuevas al hidratar: CERO (los 28 .hammer-tmp son los de gmp/mpfr de antes)
⚠ `escritorio-mirada` NO hereda a propósito: es el rootfs *slim* del USB y sumarle 47 raíces
contradice su razón de ser. Si algún día se quiere, es la misma línea.
`kde-rootfs` en el volumen se rehidrató con la herencia (11 G) para que el nombre canónico no quede
viejo — que es el error que este mismo día costó encontrar en GNOME y COSMIC. El rootfs FUNDIDO y la
imagen siguen siendo los de antes: rehacerlos es un paso aparte.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LCt3ettR4Z7b6wPCBmbvEV
Primero de los dos huecos que dejaban a KDE POR DEBAJO de una instalación estándar. El perfil
declaraba `powerdevil` —el gestor de energía de Plasma— pero no a `upower`, que es con quien
powerdevil habla para leer la batería y aplicar perfiles. Medido: upower sólo existía en la cola de
GNOME, y las colas no se ven entre sí (HERMANO→corpus, nunca de reojo). En un portátil eso es un
escritorio sin indicador de batería, y el arranque no falla ⇒ no se ve hasta usarlo.
Cuesta TRES recetas y no siete, y la diferencia es una perilla: `-Dintrospection=disabled`.
GNOME la necesita ENCENDIDA porque su shell hace `imports.gi.UPowerGlib` desde JavaScript, o sea que
carga el typelib. powerdevil NO: habla D-Bus con `org.freedesktop.UPower`. Apagarla saca de la
frontera gobject-introspection, gi-foreign-girs, glib-introspected y py3-setuptools, que sólo viven
en la cola de GNOME.
⚠ Y NO SE PROMUEVEN AL CORPUS, aunque era lo primero que intenté. Al mover `libgudev` allá su
ArtifactHash CAMBIÓ (7404bc8d → 87ca5e73) y eso no es una mudanza: `glib` existe en las DOS colas y
son recetas distintas, así que desde `incoming-gnome/` se construye contra la glib de GNOME y desde
el corpus contra la del corpus. Promoverla habría arrastrado a GNOME a la glib del corpus — el
cuadro de las «dos glib» que este repo ya pagó caro. Revertido y verificado que vuelve al hash de
antes (7404bc8d), o sea GNOME intacto. Se COPIAN a la cola de KDE.
`udev-pc` sí comparte artefacto (sus deps son sólo pkgconf ⇒ mismo hash desde las dos colas, un
solo directorio en el store). `libgudev` es otro a propósito, por la glib.
VERIFICADO sobre el artefacto sellado, no supuesto: trae `usr/libexec/upowerd`, el
`org.freedesktop.UPower.service` de system-services y su política en `system.d` — que es exactamente
lo que powerdevil necesita para que el demonio arranque por activación D-Bus.
El perfil pasa a 49 raíces, 301/301 listo, deuda 0.
Queda el segundo hueco: KDE no tiene backend de portal (ni `xdg-desktop-portal` en su cola), o sea
que no hay compartir pantalla — y en particular la captura de obs-studio, que la imagen ya trae, no
tiene con quién hablar en Plasma. Eso es más caro: pide traer el portal a la cola y ESCRIBIR
`xdg-desktop-portal-kde`, que no existe como receta en ninguna cola.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LCt3ettR4Z7b6wPCBmbvEV
Decisión del usuario (2026-09-09): X11 se erradica, y eso incluye no construir el servidor que lo
mantiene vivo. La receta se retira; `xwayland` VUELVE a ser lo que sus propios documentos decían.
⚠ LO QUE APARECIÓ AL MIRAR: esto ya estaba decidido, por escrito y DOS VECES, el 2026-09-03
(commit f64859ba):
docs/state/targets.toml:143 «`xwayland` sigue acá como RAÍZ pero su receta NO se va a escribir:
lo provee una imagen ajena enjaulada … el hueco se disuelve sin
receta y sin tocar la postura Wayland-only»
docs/state/qorpa-ajenos.toml «X11 está fuera de alcance para toda la distro … el Xwayland vive
DENTRO de la imagen —Arch y Fedora ya lo traen— y se cuelga de
nuestro kwin por el socket. La receta no se escribe.»
El 2026-09-08 se escribió igual (3d8c6fc6, «cerrar los 3 huecos que quedaban»), y los dos
documentos siguieron diciendo lo contrario durante toda la jornada de hoy. No hubo que cambiar
ninguno de los dos: alcanzó con borrar la receta para que el repo volviera a coincidir con ellos.
MEDIDO ANTES DE SACARLA, no supuesto:
· Sólo kwin podía lanzarlo. mutter va con -Dxwayland=false y wlroots con -Dxwayland=disabled ⇒
GNOME, sway y COSMIC no podían usarlo aunque el binario existiera. Nunca sirvió a más de un
perfil de los cuatro.
· NINGUNA app del catálogo necesita servidor X: todo lo gráfico es Wayland nativo (Qt6 con
qtwayland, GTK3 Wayland-only, mpv, OBS con ENABLE_WAYLAND=ON, foot, fuzzel, swayimg). El
consumidor que lo justificaba está nombrado en qorpa-ajenos.toml y es Steam, que corre
enjaulado y TRAE EL SUYO ADENTRO.
· Y la imagen KDE ya arrancaba sin él: la propia receta contaba que KDE sellaba 1037/1037 con las
apps X11 muertas. Esto no estrena una configuración, vuelve a una ya probada.
EFECTO EN EL GRAFO, verificado regenerando: `xwayland` deja de ser una receta y pasa a clase
`ajeno` —que es como targets.toml decía que había que contarlo— y el perfil escritorio-kde baja de
304 a 299 nodos con deuda 0. Los cinco que se van son la cadena que sólo él usaba.
⚠ QUEDAN CINCO RECETAS HUÉRFANAS, y no las borro de paso: `libfontenc`, `libXfont2`, `libxkbfile`,
`libxshmfence` y `xkbcomp`. Medido: NADA más en el catálogo las declara, y ninguna es raíz de
ningún perfil ⇒ siguen selladas pero no entran en ninguna imagen. Sacarlas es su propia unidad de
trabajo y su propia decisión.
El triaje pasa de `provisto` a `opcional` con la historia entera en su `porque`, y con eso se cae
el alias `xwayland xwayland` de alias-triaje.txt, que habría afirmado que tenemos una receta con
ese nombre.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LCt3ettR4Z7b6wPCBmbvEV
purpose 6.27.0 — el marco de «compartir» de KDE. 23 plugins (código de barras, bluetooth,
portapapeles, correo, imgur…) más sharefileitemaction.so, que añade «Compartir» al menú de
Dolphin.
Era el último hueco. La receta de okular lo degradaba con el flag oficial
FORCE_NOT_REQUIRED_DEPENDENCIES y su cabecera decía «los que no tenemos sellados» — un ESTADO,
no una preferencia. Ahora sale de esa lista.
⚠ Y va ENGANCHADO, no sólo autorado: una receta que nadie alcanza no arregla nada. okular sale
de la lista de degradados; gwenview y spectacle lo declaran (ninguna lo mencionaba: construían
sin él y el CMake se lo saltaba en silencio). Coste medido antes de tocar: las tres son hojas
con 0 dependientes transitivos ⇒ 3 builds, sin cascada.
La prueba es el enlace, no la intención: las tres referencian libKF6Purpose (2 cada una).
Un tropiezo con su lección: el CMake abortó pidiendo tres MÓDULOS QML —org.kde.prison,
org.kde.kitemmodels, org.kde.kcmutils— que no salen de ningún find_package. Los pide con
ecm_find_qmlmodule, o sea que comprueba que el IMPORT exista, no que la librería esté enlazada.
Las tres recetas ya existían y publicaban su qmldir; sólo faltaba pedirlas. Un requisito que no
se ve leyendo los find_package.
KAccounts6 NO se pide: su find_package va sin REQUIRED y arrastraría toda la torre de
kaccounts/signond que esta distro no tiene.
Verificado: REPRODUCE bit a bit · tarball en el mirror · escritorio-kde 304/304 sellado, deuda 0.
FRONTERA: 0 HUECOS.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014QPJteswQvP1L7zSBrQQe2
update-desktop-database construye la caché MIME→APLICACIÓN (mimeinfo.cache). Comprobado antes
de escribir la receta: NINGÚN artefacto del store lo traía, así que esa caché no se construía
nunca. Con shared-mime-info (cerrado ayer) el escritorio sabe QUÉ TIPO es un fichero; sin ésta
seguía sin saber CON QUÉ abrirlo — el menú «abrir con» vacío y sin aplicación por defecto.
Misma familia que aquel hueco: falla en RUNTIME, no en build. gnome-shell, libadwaita y mutter
lo piden en nixpkgs y acá construyen tan contentos sin él, así que ninguna métrica de deuda
puede verlo.
Prueba del consumidor con 14 .desktop REALES de okular/dolphin/kate/konsole/spectacle:
mimeinfo.cache de 2.368 bytes · 47 asociaciones
application/pdf=okularApplication_pdf.desktop
text/plain=okularApplication_txt.desktop;org.kde.kate.desktop;org.kde.kwrite.desktop
Los 4 binarios estáticos con 0 NEEDED (--prefer-static desde el principio, no tras el error).
REPRODUCE bit a bit · tarball en el mirror.
Va como RAÍZ en los CUATRO escritorios y no en , y la razón importa: escritorio-kde y
escritorio-gnome comparten CERO raíces con base y bash NO está en su clausura. escritorio-mirada
documenta que no hereda «a propósito, es slim»; esos dos no dicen nada, y sway sí hereda cli.
Declararla en los cuatro funciona con cualquiera de las dos lecturas. La asimetría en sí queda
para decidir aparte: hoy «KDE 302/302» significa «la capa de escritorio está completa», no «la
imagen está completa».
Triaje: huecos 2 → 1 (queda ). Clausuras 303/182/160/205, todas selladas.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014QPJteswQvP1L7zSBrQQe2
bash es RAÍZ del perfil base —el shell de la distro— y cinco recetas repartidas en cuatro colas
(appstream, colord, gnome-shell, modemmanager, swayimg) instalan completados en el directorio
que este paquete define. Sin él NO los instalan y siguen adelante: nada falla, nadie se entera,
y el usuario se queda sin tabulador en las herramientas del sistema. Hueco de RUNTIME puro, de
los que ninguna métrica de deuda puede ver — por eso hizo falta la frontera para encontrarlo.
Va al CORPUS y como raíz de , no a una cola: lo alcanzan las cuatro imágenes de escritorio
y la CLI, y una receta resuelve sibling-first y después el catálogo padre, nunca una cola
hermana. Y entra como RAÍZ porque nadie lo alcanza por deps de build: los consumidores sólo
preguntan por su .pc.
Verificado como consumidor, las dos mitades:
pkgconf --variable=completionsdir bash-completion → /usr/share/bash-completion/completions
el marco carga 131 completados y complete devuelve regla · 522 ficheros instalados
REPRODUCE bit a bit · tarball en el mirror
Triaje: los huecos vuelven a CERO. base pasa de 26 a 27 raíces, clausura 58/58 sellada.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014QPJteswQvP1L7zSBrQQe2
La frontera queda en CERO huecos y cero pendientes, y el perfil escritorio-kde en 302/302
sellados. Los tres eran huecos de RUNTIME: KDE sellaba 1037/1037 con la autorización muerta,
los controles QML en estilo genérico y ninguna app X11 capaz de arrancar.
polkit-qt-1 0.201.1 — al conectarlo se vio lo que ninguna métrica decía: kauth NO traía plugin
de backend, ni siquiera el directorio. Ahora trae kf6/kauth/backend/kauth_backend_plugin.so con
el símbolo KAuth::Polkit1Backend. Cascada de 26 dependientes reconstruida, 26/26 sin fallos.
Añadirlo cambió la rama del CMake y pidió kwindowsystem y tras él las X11 — cada cosa dicha por
el configure al fallar, no supuesta.
qqc2-breeze-style 6.7.2 (la del stack Plasma, NO la 6.7.4 de nixpkgs: mezclar versiones de un
mismo release es pedir desajuste de ABI en los plugins QML, que se ve en runtime y no al
construir). Enganchado a plasma-workspace como deps.runtime, no build: es un plugin que Qt carga
por la ruta de imports. Verificado que runtime no re-hashea ⇒ cero rebuilds.
xwayland 24.1.13 — resultó ser una CADENA de seis: libfontenc, libXfont2, libxkbfile,
libxshmfence, xkbcomp y el servidor. Ninguna existía. Tres tropiezos con su lección:
· libxkbfile 1.2.0 ya no trae ./configure: es sólo meson. El resto de las libs X11 de la cola
son autotools, así que copiar su plantilla era lo natural y estaba mal.
· «checking for freetype2... no» culpaba a freetype, que estaba perfecta: freetype2.pc declara
Requires: zlib, libpng y pkg-config resuelve transitivamente. El mensaje señala al paquete
equivocado.
· libXfont2 construye una .so y moría en «recompile with -fPIC» contra la libfreetype.a
estática. Van las variantes -shared.
Y xkbcomp es el eslabón que NINGÚN build habría delatado: xwayland lo lanza como subproceso en
runtime (xkb/ddxLoad.c) y su meson lo pide con required:false, así que la receta compila igual
y el servidor arranca sin teclado. Se encontró leyendo la fuente.
⚠ Sin GLX, y no por preferencia: glx/meson.build:43 pide dependency('gl') y ninguna cola publica
gl.pc — las tres recetas de mesa van con glx y glvnd apagados por decisión anterior. Las apps
X11 corren en 2D. ⚠ Y el meson.build RAÍZ engaña: ahí build_glx sólo enciende una tabla hash y
parece gratis; yo mismo di la preocupación por infundada mirando el fichero equivocado.
Verificado: Xwayland arranca y se identifica («The X.Org Foundation Xwayland Version 24.1.13»),
las 6 REPRODUCEN bit a bit, los 5 grafos con deuda 0, y los 6 tarballs en el mirror.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014QPJteswQvP1L7zSBrQQe2