COSMIC cerró 25 de 30 raíces. De los 5 fallos, CUATRO daban el mismo mensaje —
«error: no suitable Python interpreter found»— en wireplumber, xdg-desktop-portal,
xdg-desktop-portal-cosmic y cosmic-settings-daemon.
NO ERA DE ELLAS, Y NI SIQUIERA ERA DE MESON. El error viene de un `configure` de AUTOTOOLS que
prueba `python2.2`, `python2.1`, `python2.0` —literalmente— y aborta al no hallarlos. Se
identificó por las flags del comando en el log (`--disable-mpeg --disable-full-suite`), que son
inconfundibles de **libsndfile**: una dep común a las cuatro.
Y declarar `python3` en `[deps]` NO ayuda —dos de las cuatro ya lo tenían—: el problema no es
que falte el intérprete, es que el script no reconoce ese NOMBRE. Autoconf respeta la variable
de entorno `PYTHON`, así que se le pasa `PYTHON=python3` y sella.
LA LECCIÓN, que hoy ya se repitió con `dbus-shared`: cuando varias recetas fallan con el MISMO
mensaje raro, el fallo está en una dep común — y **la forma de identificarla es mirar QUÉ
configure/meson.build lo emite**, no la receta que se estaba construyendo. Las flags del comando
y el número de línea del meson.build son la firma del paquete que realmente muere.
Aplicado a las tres copias (incoming-gnome, -cosmic, -kde), que dan el mismo hash. Y de paso
`cosmic-settings-daemon` sí necesitaba `python3` en deps, que no lo declaraba: dos causas
distintas bajo un mensaje idéntico.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Los identificadores obsoletos (`GPL-2.0`, `LGPL-2.1`, `AGPL-3.0`) no dicen si el proyecto
concede «sólo esta versión» o «ésta o cualquier posterior», y eso decide con qué se puede
combinar el paquete y bajo qué términos puede redistribuirlo quien lo reciba.
NO SE PUEDE MIRAR EL COPYING, que es la trampa evidente: el texto de la GPL es IDÉNTICO en
los dos casos —es la licencia, no la concesión— y encima su apéndice «cómo aplicar la
licencia» contiene literalmente «or (at your option) any later version», así que buscarla
ahí da SIEMPRE positivo y parece evidencia siendo plantilla. Misma trampa que la regla del
`.a` no-PIC, donde grep contaba reubicaciones de `.debug_*`. La concesión vive en las
cabeceras de los fuentes y en el README; ahí se busca, excluyendo los ficheros de licencia.
SE GUARDA LA CITA, no sólo el veredicto: fichero + frase exacta que decidió. Una licencia es
una afirmación legal y quien la revise tiene que poder ver POR QUÉ dice lo que dice sin
repetir el trabajo.
Y eso pagó de inmediato: de las 12 primeras resoluciones, TRES eran evidencia inválida y
sólo se vieron porque estaba la cita. Cada una de una clase distinta:
· caligula — la frase salía de `checks/headless/expected.iso`, un FIXTURE DE TEST;
· libnl — de `include/linux-private/linux/seg6.h`, una cabecera del KERNEL vendorizada.
La licencia del kernel no es la de libnl;
· lm-sensors — declarado GPL-2.0 y la cita decía «version 2.1 of the License», que es la
LGPL. La frase era real pero no sostenía lo que se le atribuía.
Las tres clases quedan filtradas en el script: ficheros de licencia, rutas de test/fixture, y
código vendorizado; más una comprobación nueva de que **la cita hable de la misma versión que
la licencia declarada**.
Sembradas las 9 auditadas (13 ficheros; algunas viven en varias colas). Ambiguas: 55 → 41.
Las 40 sin evidencia quedan listadas y siguen contadas — la mayoría son Go y la familia
cosmic, donde la frase no aparece fuera del COPYING.
Hashes verificados: 0 movidos.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Último recurso mecánico, `scripts/licencias-texto.sh`: para las 60 recetas donde la API de
GitHub devuelve NOASSERTION (el repo TIENE un LICENSE pero licensee no lo reconoce: texto
retocado, encabezado propio, dos licencias en un fichero), baja el texto y lo clasifica acá.
34 identificadas — 16 MIT, 10 Apache-2.0, 7 BSD-2-Clause, 1 BSD-3-Clause.
SÓLO PERMISIVAS, Y NO ES PEREZA. MIT, Apache-2.0, BSD, ISC, MPL-2.0 y Unlicense se
reconocen por frases inconfundibles y NO tienen variantes -only/-or-later ⇒ reconocer el
texto da el SPDX completo.
La familia GPL se deja al humano A PROPÓSITO, y la razón es sutil: el COPYING de la GPL es
IDÉNTICO tanto si el proyecto es «sólo v3» como «v3 o posterior» — lo que las distingue vive
en las cabeceras de los fuentes. Y encima el propio COPYING incluye, en su apéndice «cómo
aplicar la licencia», la frase «or (at your option) any later version», así que buscarla da
SIEMPRE positivo y parecería evidencia siendo texto de plantilla. Es exactamente la trampa
de la regla del `.a` no-PIC, donde grep contaba reubicaciones de .debug_* y mentía.
Comprobado a mano un caso que daba mala espina: el LICENSE de `conftest` empieza
«Conftest — Write tests against your config files / Copyright (C) 2019 …», que es el formato
típico de una cabecera GPL. Leído entero, dice «Licensed under the Apache License, Version
2.0». La clasificación era correcta; la sospecha, barata.
Hashes verificados sobre las 36 tocadas: idénticos.
Quedan 88, ya sin vía mecánica: los repos donde ni la API ni el texto deciden, la familia
GPL sin desambiguar, y tarballs de sitios propios (gmplib, xiph, sr.ht, codeberg…).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Tercera tanda curada, agrupada por la URL DE FUENTE de cada receta (que es la evidencia que
el nombre no da): los once módulos Qt sin prefijo, freedesktop (dbus, libinput, libevdev,
libdisplay-info, poppler, pulseaudio, upower, NetworkManager, ModemManager, polkit),
kernel.org (los tres kernels, linux-headers, git, iproute2, libuuid) y PyPI.
Los kernels llevan `GPL-2.0-only WITH Linux-syscall-note` explícita. No es adorno: sin esa
excepción, todo binario de espacio de usuario que hace un syscall sería obra derivada del
kernel. Es exactamente el tipo de dato que un campo de licencia existe para no perder.
Quedan 147 sin declarar: 69 de GitHub donde la propia API dice NOASSERTION (hay que abrir
el fuente), 20 de tawasuyu —que son nuestras o del otro agente, así que la licencia la
decide el usuario, no yo— y el resto repartido en GNOME, gitlab.freedesktop y sueltos.
Más 71 con SPDX ambiguo pendientes de desambiguar (`licencias.sh --revisar`).
Hashes verificados otra vez sobre 20 recetas tocadas: 20 idénticos, 0 cambiados.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Esta mañana eran 0. Tras la tabla curada (228) y este paso, 936. Ninguna receta se
re-hasheó: verificado en 30 de las 708 tocadas, 30 hashes idénticos, 0 cambiados.
DE DÓNDE SALE EL DATO, Y POR QUÉ NO ES ADIVINAR. `scripts/licencias-detectar.sh` consulta
la API /repos/{o}/{r}/license de GitHub para las 673 recetas cuya fuente vive allí. Eso
devuelve el resultado de DETECTAR el fichero LICENSE que el repo tiene de verdad
(licensee), no una etiqueta escrita a mano en una web: es la misma evidencia que veríamos
abriendo el tarball, obtenida sin bajar 673 tarballs por un enlace de 8 Mbps. 610 con SPDX
definido; las 63 que GitHub marca NOASSERTION/other se DESCARTAN — un «no sé» de la fuente
se propaga como hueco, no se redondea a una licencia plausible.
Las familias no-GitHub van curadas por la URL DE FUENTE, que es la evidencia que el nombre
no da. Y ahí cometí el error simétrico al que este mismo fichero advertía: había puesto
`knighttime` entre las «herramientas Go» POR SU NOMBRE, y su tarball sale de
download.kde.org — es un Framework de KDE, LGPL. Descartar por nombre falla igual que
aceptar por nombre. Corregido en la cabecera.
LAS DOS IMPRECISIONES, contables con `licencias.sh --revisar` en vez de escondidas:
1. SPDX OBSOLETOS Y AMBIGUOS (71 recetas). GitHub devuelve `GPL-3.0`, `LGPL-2.1`,
`AGPL-3.0`… identificadores que SPDX declaró obsoletos PRECISAMENTE porque no
distinguen `-only` de `-or-later`, y esa diferencia decide con qué se puede combinar el
paquete. NO se normalizan a ciegas: mapear GPL-3.0 → GPL-3.0-or-later sería inventar el
dato que falta. Quedan marcadas para resolver mirando el fuente.
2. LICENCIAS DOBLES COLAPSADAS. La API devuelve UNA sola licencia y muchos proyectos Rust
son «MIT OR Apache-2.0» (p.ej. `fd` quedó como Apache-2.0). No es falso —cumplir una de
las opciones concedidas basta— pero es incompleto. Lo resuelve el cierre estructural:
leer el campo `license` del Cargo.toml en la fase de fetch.
Y un fallo que habría escrito basura en silencio: `licencias-detectadas.tsv` tiene TRES
columnas (añade el owner/repo consultado, para poder auditar) y el sembrador leía dos, así
que la licencia se habría llevado pegado el slug — `license = "MIT<TAB>owner/repo"`, sin
que nada lo validara. Arreglado antes de sembrar.
Quedan 205 sin licencia y 71 por desambiguar.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
La deuda legal bloqueante del SDD 19 §2.1. Medido hoy: **0 de 1141 recetas** declaraban
licencia, no «5 de 771» como decía el informe anterior. Los dos números estaban mal: los
«5» eran falsos positivos de `grep license` (el paquete `addlicense`, el paquete
`cargo-bundle-licenses`, una línea `install .../share/licenses/` y un comentario), y las
recetas son 1141. Contar con `grep -l <palabra>` sobre TOML cuenta comentarios y nombres,
no campos; `scripts/licencias.sh` cuenta el campo de verdad (clave en la raíz, antes del
primer `[table]`).
LO QUE HACE LA DEUDA PAGABLE: `Recipe::hash_inputs` es una LISTA BLANCA — sólo entran
source, compiler, target, link, patches, flags, phases y deps. `license` no entra, igual
que `evidence` y `slots`. Por eso se puede poblar en las recetas YA SELLADAS sin mover un
solo ArtifactHash. Verificado, no supuesto: en 40 recetas modificadas se comparó el hash
con y sin la línea — 40 idénticos, 0 cambiados. Si el campo entrara al hash, declarar la
licencia costaría reconstruir el corpus entero y no se haría nunca. Clavado con el test
`licencia_round_trip_y_no_afecta_el_hash`.
TRAMPA DE TOML: una clave suelta después de un `[table]` pertenece a esa tabla. Puesta al
final del fichero, `license` acaba dentro de `[deps]` y se pierde EN SILENCIO, porque serde
ignora los campos que no conoce — no hay error, simplemente no está. Va arriba, junto a
`name` y `version`; el sembrador la inserta tras `version`.
NO SE ADIVINA. Declarar mal una licencia es peor que dejarla vacía: convierte un hueco
visible en una afirmación falsa. Sólo se puebla desde una tabla curada entrada por entrada
(`docs/licencias-conocidas.tsv`); lo que no tiene evidencia queda vacío y se CUENTA.
Concretamente se descartó el atajo «k* = KDE ⇒ LGPL»: en este catálogo `kail`, `kind`,
`ko`, `kopia`, `krew`, `kustomize`, `kyverno`, `katana`, `kibi`, `kmon` y toda la familia
`kube*` son herramientas Go sin relación con KDE. El nombre no es evidencia.
Quedan 913, casi todas CLIs Go/Rust importados en masa — y ésas sí son automatizables con
evidencia real: Cargo.toml trae el campo `license` y los módulos Go traen su LICENSE en el
árbol. El cierre estructural es capturarlo en la fase de fetch, que ya descarga y extrae
cada tarball, y inyectar el texto en `hammer pack` (aguas abajo del ArtifactHash) en vez de
en la fase install (que sí re-hashearía).
De paso, respaldo-storagebox.sh reordenado por valor irreemplazable y con zstd: medido en
la oficina, el uplink da 8 Mbps iguales por cable y por wifi ⇒ 128 G no caben en una
sentada, así que sube primero el cerebro (estado + repo) y `--partial-dir` hace que cortar
a mitad de un artefacto no tire lo ya subido.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
La cadena de deps .pc SÍ quedó resuelta (libpng+expat añadidos); el muro restante es PIC
(freetype.a/libpng.a/expat.a no-PIC dentro de libXft.so), no resolución. Nadie lo consume:
plasma-workspace (su único declarante) selló sin él — KDE es Wayland, Xft es X11 legacy.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Elimina el injerto del artefacto viejo que destrababa la sesión Plasma anidada.
Desktop.qml de plasma-workspace importa ese módulo; sin él plasmashell falla
"module not installed". qtdeclarative ya estaba en deps. Rebuild va a la granja.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
libXft es el único de los 11 que no sella. Falla por PIC (freetype/libpng/expat
estáticas no-PIC dentro de un .so), riesgo que su propio header ya predecía. NADIE
lo consume: plasma-workspace (su único declarante) selló SIN él porque KDE es Wayland.
Forzarlo sellaría un artefacto muerto. A .deferred/ para que el loop no lo reintente;
la cadena de deps .pc quedó resuelta (libpng+expat), sólo resta el muro PIC (Capa 0).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
La única deuda irreducible del barrido (§4.10) era /usr/bin/perl en
ca-certificates y curl. Dos hallazgos al abrirla:
1. EL COMENTARIO DE ca-certificates.toml YA LO DECÍA, escrito por quien la portó:
"El resto del build (mk-ca-bundle.pl → cert.pem → split-ca-bundle.sh) usa el
perl + coreutils del rootfs". La deuda estaba escrita EN PROSA y era invisible
para el sistema; harkaq la convirtió en un veredicto. Es la tesis del §0 en una
línea: no hace falta que nadie DESCUBRA nada, hace falta que la máquina pueda
VER lo que ya se sabía.
2. LA RECETA TAMBIÉN EXISTÍA: recipes/incoming-kde/perl.toml, importada el 13/07
para la campaña KDE (syntax-highlighting e intltool exigen perl). CUARTA
convergencia independiente: dos campañas necesitaban el mismo binario y
llegaron por caminos que no se hablan.
Construye tal cual (b3:c7a899bd…) y con el artefacto en el store:
/usr/bin/perl → declarar dep: perl exit=0 ⇒ CERO deuda irreducible
EL BARRIDO DE 24 RECETAS QUEDA EN 0 IRREDUCIBLES. La métrica del §7 (<5%) se
cumple midiendo lo que la métrica quería medir: cosas que no sabemos construir.
Resultado: ninguna.
Receta promovida a recipes/perl.toml (no había canónica ⇒ sin colisión). Lo que
queda es mecánico y no es diseño: declarar `make` en las ~10 recetas que lo usan
y `perl` en ca-certificates/curl. OJO: eso re-hashea sus artefactos y son
paquetes del base-system (índice firmado 748) ⇒ decisión de rollout, no un sed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
spectacle 6.7.2 (7a6db883) → /usr/bin/spectacle. Cierre VERIFICADO, los 6 componentes de la cadena:
libKPipeWireRecord.so.6 + libopencv_core.so.410 + libopencv_imgproc.so.410 + libtesseract.so.5.5 +
libKF6PrisonScanner.so.6 + libKQuickImageEditor.so.1.
Cadena nueva completada en esta tanda:
ffmpeg 7.1 faafef5e libavcodec/avutil/avformat/avfilter/swscale — kpipewire los exige los
4 REQUIRED. ffmpeg NO usa autotools: su configure toma --cc/--ar/
--ranlib, y hay que darle wrappers de UN SOLO TOKEN (--ar="zig ar" con
espacio se ejecutaría como binario único — mismo gotcha que el AR de
los crates 'cc'). **--disable-autodetect** = determinismo: sin él
configure escanea el sandbox y activa libs a discreción.
libva 2.22.0 121cd0de libva.so + libva-drm.so, REQUIRED por kpipewire. Sólo la capa de
despacho; los drivers reales son RUNTIME (dlopen). Sólo backend DRM.
kpipewire 6.7.2 745665f3 KPipeWire + KPipeWireRecord. Deps: pipewire + ffmpeg + libva + gbm/EGL
(mesa) + libepoxy.
kquickimageeditor 0a4f8156 **BUMP 0.5.0 → 0.6.2.1**: spectacle 6.7 incluye
<KQuickImageEditor/AnnotationDocument>, que NO existe en la serie 0.5
(no tiene src/annotations). La 0.6.x suma deps propias: KF6Config
REQUIRED + OpenCV 4.7 (stack blur, WITH_OPENCV=TRUE por defecto).
Por qué era cara: TODO en spectacle es REQUIRED y casi nada degradable. En particular **KPipeWire no se
puede esquivar**: find_package va sin REQUIRED y set_package_properties lo marca TYPE REQUIRED (eso sí se
degrada con sed), pero src/CMakeLists.txt:101 linkea K::KPipeWireRecord INCONDICIONALMENTE.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
pipewire (6d15a22c) → libpipewire-0.3.so.0 + libspa-* + daemon 'pipewire' + **'pipewire-pulse'** (habla
el protocolo PulseAudio, así que los clientes libpulse ya sellados le hablan) + tools (pw-cli/pw-play/
pw-record/pw-mon/pw-dump/...). Cierra el lado SERVIDOR del audio: hasta ahora sólo teníamos el CLIENTE
(libpulse con -Ddaemon=false).
Dos frentes lo necesitaban: (1) audio real de Plasma 6; (2) spectacle → kpipewire → pipewire.
Fuente del gitlab.freedesktop.org (como networkmanager/modemmanager). Recortado al core+SPA: sin bluez5
(arrastraría los códecs aptx/ldac/aac/opus), sin jack/v4l2/libcamera/gstreamer/ffmpeg/vulkan/roc/lv2/
avahi/x11/echo-cancel-webrtc/libusb/flatpak/snap; systemd/logind/selinux/rtkit off (no hay systemd).
alsa+sndfile+libpulse+dbus+udev enabled (las 4 ya selladas).
GOTCHA static-vs-shared (variante nueva del patrón): **sin ncurses a propósito**. Su única consumidora es
la tool pw-top (monitor de terminal), guardada por 'if ncurses_dep.found()'. El ncurses del catálogo es
static-only y su .pc arrastra '-static' al link ⇒ 'error: using shared libraries requires dynamic linking'
al enlazar pw-top contra libpipewire-0.3.so. Quitando la dep, meson saltea pw-top y el resto construye.
(Alternativa futura si se quiere pw-top: variante ncurses-shared.)
Próximo: ffmpeg → kpipewire → spectacle.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Selladas:
leptonica 1.85.0 e80a5d36 procesamiento de imagen; dep dura de tesseract. Codecs recortados a
las variantes .so/PIC que ya tenemos (libjpeg-turbo-shared +
libpng-shared + zlib-shared); TIFF/WEBP/OPENJPEG/GIF off.
tesseract 5.5.0 08c05238 OCR. spectacle lo exige DURO: pkg_check_modules(TESSERACT REQUIRED)
en CMakeLists:111, sin option() para apagarlo. Sólo la lib (sin
training tools, que piden pango/cairo/icu).
kquickimageeditor 0.5.0 3d4bd904 editor de imagen QtQuick; spectacle lo marca TYPE REQUIRED.
spectacle.toml se commitea CON su blocker documentado en la cabecera (misma convención que usaba
networkmanager-qt): **KPipeWire**. find_package(KPipeWire) va sin REQUIRED y set_package_properties lo
marca TYPE REQUIRED (eso se degrada con sed), PERO src/CMakeLists.txt:101 linkea
INCONDICIONALMENTE ⇒ no hay forma de compilar sin él. Falta la cadena pipewire → (ffmpeg, para
KPipeWireRecord) → kpipewire.
El resto de su cadena YA quedó resuelto y sellado esta sesión: opencv + prison-scanner + zxing-cpp +
tesseract + leptonica + kquickimageeditor + xcb-util-cursor (sin este último: 'No suitable backend
platform was found ... XCB-CURSOR').
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
zxing-cpp 2.3.0 (c98afd82) → libZXing.so: decodificador/codificador de códigos de barras y QR.
prison-scanner 6.27.0 (cbfd6dcc) → libKF6Prison.so.6 + **libKF6PrisonScanner.so.6**.
Por qué la variante: el prison canónico de esta cola se selló con WITH_ZXING=OFF/WITH_MULTIMEDIA=OFF ⇒ no
provee KF6::PrisonScanner, y spectacle corta el build en seco:
if (NOT TARGET KF6::PrisonScanner) message(SEND_ERROR "Prison built without required PrisonScanner")
prison-scanner activa WITH_ZXING=ON + WITH_MULTIMEDIA=ON (qtmultimedia ya sellado). Nombre distinto para
NO re-hashear el prison que ya consumen plasma-workspace/plasma-nm — mismo patrón que kcoreaddons-QML /
kwindowsystem-QML / qcoro-shared.
GOTCHA zxing: hay que compilar **READERS *y* WRITERS**. Con ZXING_WRITERS=OFF el header ZXing/BitMatrix.h
ni se instala, y prison NO sólo escanea — también GENERA códigos (zxingutil.cpp/pdf417barcode.cpp lo
incluyen) ⇒ 'fatal error: ZXing/BitMatrix.h file not found'.
spectacle sigue sin construir: además exige (sin flag para apagarlos) pkg_check_modules(TESSERACT REQUIRED
tesseract) — OCR, arrastra leptonica — y kquickimageeditor TYPE REQUIRED.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
opencv (79526f4b) → libopencv_core.so.4.10 + libopencv_imgproc.so.4.10 + opencv4.pc. spectacle (la
herramienta de captura de pantalla) lo exige: find_package(OpenCV 4.7 REQUIRED core imgproc), lo usa en
src/QtCV.h.
OpenCV es enorme (~95MB de fuente, decenas de módulos): se recorta con **BUILD_LIST=core,imgproc** (CMake
ni configura el resto) + todo OFF (apps/tests/docs/python/java/protobuf/DNN/GUI/video/ffmpeg/IPP/TBB/CUDA/
OpenCL/codecs). Los codecs WITH_* van OFF porque viven en imgcodecs, que no construimos.
**GOTCHA zig-wrapper DURABLE (2da vez que aparece, ahora documentado):** el wrapper clásico de esta cola
arma la lista de args en $a SIN comillas ⇒ SPLITEA cualquier arg con espacios. OpenCV pasa
-DOPENCV_ALLOCATOR_STATS_COUNTER_TYPE="long long" ⇒ zig recibe 'long' suelto y falla con
'error: long: unrecognized file extension'. Fix acá: wrapper PASS-THROUGH con "$@" (OpenCV no es
ECM/KDE, no necesita el filtro de -Wl,--fatal-warnings). Es el mismo bug que ya había pegado en
libkscreen (moc_predefs con -I"dir1 dir2").
spectacle NO construye todavía: además de OpenCV exige KF6::PrisonScanner, y el prison sellado se hizo
con WITH_MULTIMEDIA=OFF (sin el componente Scanner, que pide ZXing + Qt Multimedia).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
kinfocenter 6.7.2 (9dee4f29): bin kinfocenter + KCMs de hardware (kcm_cpu/interrupts/kwinsupportinfo/
xserver/opencl/energyinfo/...). kmenuedit 6.7.2 (d13a64f4): editor del menú de aplicaciones. Ambos sin
recetas nuevas.
DEUDA REGISTRADA — qtbase sin Vulkan: el KCM about-distro ('Acerca de este sistema') incluye
<QVulkanInstance>/<QVulkanFunctions> tanto en sus helpers (opengl-helper/vulkan-helper) como en
GPUEntry.h. Esos headers SÓLO los genera Qt6Gui si qtbase se configuró con Vulkan, y el qtbase sellado
NO lo tiene (vulkan-headers/vulkan-loader están sellados, pero los usa kwin directo, no Qt). Se podó el
KCM entero: activar vulkan en qtbase cascadearía un rebuild de TODO el stack Qt/KF6/Plasma (horas), como
ya se vio con el fix de zlib-shared → kwin(1825 obj)+plasma-workspace(1962 obj). Pendiente para una
próxima cascada planificada de qtbase (junto con otras features que falten).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
systemsettings (4c304dd8) sella a la PRIMERA: bin /usr/bin/systemsettings, NEEDED libKF6KCMUtils.so.6 +
libKF6KCMUtilsCore.so.6 + libPlasmaActivities.so.7. Cero recetas nuevas (todas las deps ya selladas) y
sin pelear DocTools: systemsettings lo declara en OPTIONAL_COMPONENTS.
Era el hueco más grande del escritorio: los KCMs se habían apagado para poder compilar plasma-desktop, y
sin systemsettings no hay shell donde alojarlos. Ahora existe el contenedor + ya hay KCMs reales
construidos por otras piezas de esta sesión: kcm_networkmanagement (plasma-nm), kcm_pulseaudio
(plasma-pa), kcm_powerdevilprofilesconfig (powerdevil), kcm_kscreen (kscreen).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
plasma-pa 6.7.2 (51d7a25b): applet QML org.kde.plasma.volume + kcm_pulseaudio + audioshortcutsservice.
Cierra el frente de audio: hasta ahora el lab sólo tenía libcanberra con backend NULL (sin reproducción).
Cadena completa nueva:
alsa-lib/speexdsp/libsndfile → pulseaudio (cliente) → pulseaudio-qt → plasma-pa
pulseaudio 17.0 (108cac6e) → libpulse.so.0 + libpulse-mainloop-glib.so.0 + libpulse-simple.so.0 (+ .pc).
- **-Ddaemon=false -Dclient=true**: se construye SÓLO la biblioteca cliente. Es lo correcto acá — el
servidor de audio previsto es PipeWire (habla el protocolo PulseAudio) pero los clientes igual
linkean el libpulse de PulseAudio. Evita todo el árbol de módulos del daemon (alsa/bluez/jack/
avahi/orc/fftw/webrtc-aec).
- -Dglib=enabled es OBLIGATORIO (sin él no hay libpulse-mainloop-glib, que plasma-pa exige);
lo habilita glib-shared.
- **GOTCHA lld durable**: PulseAudio comparte UN map-file (version script) entre libpulse,
libpulse-simple y libpulse-mainloop-glib ⇒ al enlazar cada una, el script asigna PULSE_0 a símbolos
que viven en las OTRAS: 'version script assignment of PULSE_0 to symbol pa_glib_mainloop_new failed:
symbol not defined'. GNU ld sólo avisa; ld.lld (el de zig) lo trata como ERROR desde lld 17. Fix:
-Dc_link_args=-Wl,--undefined-version.
pulseaudio-qt 1.8.1 (c6849b9e) → libKF6PulseAudioQt.so.5, selló a la primera. OJO: NO está en el path de
plasma/ sino en download.kde.org/stable/pulseaudio-qt/, y la versión viva es 1.8.x (1.6.0 del
find_package es sólo el mínimo).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
powerdevil 6.7.2 (299af51a): daemon de energía + acciones (suspendsession/dimdisplay/dpms/
brightnesscontrol) + KCMs. kscreen 6.7.2 (ef6218e6): kcm_kscreen + kscreen KDED + kscreen-console +
hdrcalibrator.
Base de audio REAL (el lab sólo tenía libcanberra con backend NULL, sin reproducción):
alsa-lib 1.2.14 c6896caf libasound.so.2 (--disable-python)
speexdsp 1.2.1 dc235b15 libspeexdsp.so.1 (resampler de PulseAudio)
libsndfile 1.2.2 c44d0142 libsndfile.so.1 (--disable-external-libs: sin FLAC/Opus, que no están
sellados; WAV/AIFF/AU basta para sonidos del sistema). Necesita python3.
Siguiente eslabón: pulseaudio → pulseaudio-qt → plasma-pa (applet de volumen).
3 lecciones de la depuración de powerdevil (dep-set de 69):
- ** FALTABA** y el síntoma era engañoso: 'Could NOT find KF6 (missing: KIO KCMUtils
XmlGui)'. La cadena real es KF6ConfigWidgets→find_dependency(KF6WidgetsAddons) ausente ⇒ ConfigWidgets
NOT_FOUND ⇒ cascadea a XmlGui/KIO/KCMUtils. Para diagnosticar hay que seguir los 'could not be found
because dependency X' hacia ARRIBA, no fiarse de los componentes que CMake lista.
- **PlasmaWaylandProtocols/WaylandProtocols/qtwayland** son deps directas de todo lo que toca Wayland
(powerdevil, kscreen). Idem los QML modules (kscreen: org.kde.kitemmodels + org.kde.plasma.plasma5support
→ kitemmodels/plasma5support directos; ambos YA traen su qml/, no hacía falta variante QML=ON).
- **timeout del build**: mató powerdevil a mitad del rebuild de plasma-workspace (mi
cambio de zlib-shared cascadeó kwin[1825 obj]+plasma-workspace[1962 obj]). Usar timeouts largos
(9000) para recetas con dep-sets grandes. Además: 24778 AUTO-MATCHEA el propio
comando de chequeo → usar .
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
plasma-nm (6080f27f) construido: applet QML org.kde.plasma.networkmanagement + kcm_networkmanagement +
plugins VPN (openvpn/openswan/ssh/sstp/strongswan/iodine/fortisslvpn). Cierre verificado:
libKF6NetworkManagerQt.so.6 + libKF6ModemManagerQt.so.6 + libqt6keychain.so.1.
Cierra el frente que plasma-workspace esquivó parcheando NetworkManagerQt a opcional. Cadena entera:
glib-shared → networkmanager (libnm) → networkmanager-qt ─┐
glib-shared → modemmanager (libmm-glib) → modemmanager-qt ───┴→ plasma-nm
Deps nuevas de esta tanda:
modemmanager 1.22.0 9e4ce41d libmm-glib. -Dqmi/mbim/qrtr=false evita libqmi/libmbim/libqrtr;
polkit=no, udev=false (+udevdir explícito, lo exige el assert).
modemmanager-qt 6.27 37e954bb KF6ModemManagerQt (REQUIRED en el find_package(KF6) de plasma-nm
aunque no haya módem).
qtkeychain 0.16.0 6a1319b0 claves WiFi. **LIBSECRET_SUPPORT=OFF**: por defecto ON y exige
libsecret-1 (llavero de GNOME); apagado queda KEYCHAIN_DBUS =
kwallet vía Qt6DBus, que es el backend que KDE usa ⇒ cero deps nuevas.
OJO: el tag de git es '0.16.0' SIN prefijo 'v'.
libxslt 1.1.43 b41cb0fc xsltproc. A diferencia de NM (donde sólo servía a man/ y se degradó),
ModemManager lo USA de verdad: include/meson.build:25 genera
ModemManager-names.h desde header-generator.xsl.
qcoro-shared 0.12.0 b8ed5b49 el qcoro canónico sella sólo .a sin PIC (su CMake no fija
BUILD_SHARED_LIBS) ⇒ 'R_X86_64_32S QCoro::detail::TaskBase<QDBusMessage>
recompile with -fPIC' al linkear plasma-nm. Variante con
BUILD_SHARED_LIBS=ON; nombre distinto para no re-hashear el qcoro que
ya consumen plasma-workspace/powerdevil.
BUILD_OPENCONNECT=OFF es importante: con ON, plasma-nm hace find_package(Qt6WebEngineWidgets REQUIRED)
⇒ arrastraría qtwebengine (Chromium), diferido por el ADR.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Habilitado por glib-shared (deuda Capa 0 recién saldada). La receta networkmanager-qt documentaba un
'⛔ BLOCKER DURO': pkg_search_module(NetworkManager REQUIRED IMPORTED_TARGET libnm>=1.4.0) sin receta de
NetworkManager en el catálogo. Resuelto:
networkmanager 1.52.0 (f3d89133) → libnm.so.0 + libnm.pc + headers (NetworkManager.h/nm-version.h).
- Fuente: gitlab.freedesktop.org (download.gnome.org sólo llega a NM 1.9.x; el proyecto migró).
- **-Dcrypto=null es la clave**: NM ofrece crypto ∈ {nss,gnutls,null}; 'null' evita nss (→nspr/sqlite)
y gnutls (→nettle/libtasn1/p11-kit), dos cadenas enormes. Sin validación de certificados 802.1X,
pero libnm compila y la API D-Bus queda completa.
- Deps duras satisfechas: libudev (libudev-zero ya sellado), gio (glib-shared), libndp (receta nueva),
uuid (util-linux), dbus.
- NM va pidiendo sus flags de a uno; los que hicieron falta: -Dld_gc=false (lld no soporta linker
garbage collection), -Dsystemdsystemunitdir=no, -Dconcheck=false (curl), -Dnmcli=false/-Dreadline=none.
sed a meson.build:92: find_program('xsltproc') es INCONDICIONAL pero xsltproc sólo se usa en man/
(no se construye con docs=false) → required:false, evita la receta libxslt entera.
libndp 1.9 (036eb8c7): sin tarball con configure pregenerado (mirrors 404) ⇒ git-archive +
con el autoconf/automake del rootfs de build (patrón 'de gueto', como gcc/cmake).
networkmanager-qt 6.27.0 (b5850a40) SELLA. Hallazgo: libKF6NetworkManagerQt.so NO enlaza libnm — sólo
Qt6Network/DBus/Core. libnm es dep de BUILD (headers/enums); el runtime es D-Bus puro. Confirma el
comentario original de la receta. Próximo: plasma-nm (el applet).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
La deuda más arrastrada del ADR 0011: glib canónico es -Ddefault_library=static --prefer-static (sólo
.a) ⇒ no enlaza en un .so; por eso plasma-workspace tuvo que parchear NetworkManagerQt a opcional
(esquivando el rabbit-hole libnm→glib).
glib-shared 2.88.1 (dc46a620) produce el set dinámico completo: libglib-2.0.so.0 + libgobject-2.0.so.0 +
libgio-2.0.so.0 + libgmodule-2.0.so.0 + libgthread-2.0.so.0 + libgirepository-2.0.so.0. Conserva los
switches del canónico (tests/nls/libmount/selinux/introspection off) — sólo cambia el modo de librería,
sin arrastrar deps nuevas.
pcre2-shared 10.47 (f254abaa) era el prerrequisito: el pcre2 canónico es --disable-shared SIN --with-pic
⇒ su .a no entra en libglib.so. compiler=gcc como el canónico (su comentario advierte que zig-cc
MISCOMPILA libs C, patrón file/jq); el .so es ABI-compatible con los consumidores zig. libffi NO necesitó
variante: ya usa --with-pic.
Cierre verificado: libglib-2.0.so.0 → libpcre2-8.so.0; libffi PIC queda embebido estático.
Destraba: libnm (NetworkManager→plasma-nm), polkit, xdg-desktop-portal, gstreamer.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
CERO recetas nuevas: las 5 usan sólo deps ya selladas. Binarios verificados en los artefactos.
kcharselect da2ea71b selector de caracteres Unicode
kfind 9c46fee5 buscador de archivos (+qt5compat por Qt6Core5Compat REQUIRED, +kfilemetadata)
kruler f69c1bc8 regla de pantalla (+kstatusnotifieritem)
kdf fe681807 espacio en disco → bins kdf + kwikdisk (+kcmutils)
kwalletmanager 2d31f0be gestor de billetera → bin kwalletmanager5 (+kwallet/kcmutils)
4/5 sellaron a la primera con el patrón app-KDE estándar. kwalletmanager pidió además degradar DocTools:
marca TYPE REQUIRED en set_package_properties ⇒ feature_summary aborta; sed TYPE REQUIRED→OPTIONAL (el
mismo patrón que konsole/gwenview; distinto de ark/okular donde DocTools va en el COMPONENTS list).
Apps: konsole+dolphin+kate(+kwrite)+kcalc+ark+filelight+gwenview+okular+kcharselect+kfind+kruler+kdf+
kwalletmanager = 13.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
okular sella (5efc2ad9) con 8 generadores: poppler (PDF) + kimgio + txt + comicbook + fax + fb + dvi +
xps. okularGenerator_poppler.so → libpoppler-qt6.so.3 verificado.
poppler 25.02.0 (59461aff), Qt6-only: sin QT5/glib/cpp/utils/tests; NSS3/GPGME/LIBCURL/LIBTIFF off y
LIBOPENJPEG=none (sin deps selladas; los JPEG2000 embebidos no renderizan, el resto del PDF sí).
Cierre libpoppler.so VERIFICADO soberano: libfreetype.so.6 + libfontconfig.so.1 + libjpeg.so.62 +
libpng16.so.16 + liblcms2.so.2 + libz.so.1 — sin fugas al sysroot.
**DEUDA CAPA 0 'freetype/fontconfig shared-PIC' (marcada pendiente en ADR 0011) SALDADA:**
freetype-shared 2.14.3 (76fd1f4b, libfreetype.so.6, --without-harfbuzz corta el ciclo con harfbuzz) +
fontconfig-shared 2.18.1 (6ed9e303, libfontconfig.so.1). expat NO necesita variante: el canónico ya usa
--with-pic. Las variantes omiten los 3 patches Alpine de rendering (viven en recipes/, copiarlos
arriesga colisión de patches homónimos; no afectan el rasterizado que poppler necesita).
Fixes okular: FORCE_NOT_REQUIRED_DEPENDENCIES (flag OFICIAL que sugiere el propio feature_summary) para
DocTools/Purpose/TIFF/LibSpectre/KExiv2Qt6/DjVuLibre/EPub/Discount/QMobipocket6; +plasma-activities
(REQUIRED), +kpty (comicbook), +kwallet (ya sellada). GOTCHA musl durable: synctex_parser.c usa
vasprintf (extensión GNU) con -std=c99 ⇒ musl no la declara en modo estricto ⇒ CMAKE_C_FLAGS=-D_GNU_SOURCE.
Apps: konsole+dolphin+kate+kcalc+ark+filelight+gwenview+okular.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
ark sella (8ebf0e10) con sus plugins kerfuffle: kerfuffle_libarchive.so→libarchive.so.13 y
kerfuffle_libzip.so→libzip.so.5. Motor nuevo: libarchive 3.7.7 (41f9959c) + libzip 1.11.3 (f64869dc).
Deuda Capa 0 pagada (static↔dinámico): el libbz2.a/liblzma.a canónicos son SIN -fPIC → no enlazan en
un .so ('R_X86_64_PC32 recompile with -fPIC'). Nuevas variantes shared como zlib-shared: bzip2-shared
(4a015f8a, Makefile-libbz2_so → libbz2.so.1.0) y xz-shared (25765982, autotools --enable-shared →
liblzma.so.5). Cierre libarchive.so verificado soberano: liblzma.so.5 + libzstd.so.1 + libbz2.so.1.0 +
libz.so.1, sin fugas al sysroot. Apps: konsole + dolphin + kate + kcalc + ark.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
konsole (emulador de terminal) construye+sella con musl+zig-cc. Deps nuevas: kpty (pseudo-terminal,
cb0f3836) + icu4c + qtmultimedia + cierre knewstuff (attica/kpackage/kirigami). DocTools/doc a opcional.
Primera app del escritorio KDE construida — el shell ahora tiene con qué abrir algo.
kickoff (menú de apps) importaba org.kde.coreaddons (kcoreaddons con KCOREADDONS_USE_QML=ON,
variante sellada 6c0dd30e + hidratada aparte; receta revertida a OFF para no cascadear) +
org.kde.kirigamiaddons.components (kirigami-addons 1.9.0 a318888d, receta nueva). Ya no falla.
Applets rotos restantes: notifications (org.kde.quickcharts), keyboardlayout (kcm removido).
El shell Desktop.qml IMPORTA org.kde.plasma.activityswitcher (de imports/activitymanager) + org.kde.
kwindowsystem. Fix activityswitcher: switcherbackend.cpp usa XWindowTasksModel (X11, QList<WId>) bajo
#if HAVE_X11, pero HAVE_X11=1 pese a WITH_X11=OFF y el header falta en plasma-workspace wayland-puro;
WaylandTasksModel retorna QList<QUuid> (incompat) ⇒ desactivamos los bloques #if HAVE_X11 (#if 0) +
borramos el include (drag-drop X11 de ventanas entre actividades, feature menor). kwindowsystem: el
módulo QML org.kde.kwindowsystem se sella aparte (QML=ON, c9ff13c5) e hidrata al runtime; la receta
queda QML=OFF para NO cascadear el rebuild de kwin/plasma-workspace (deuda reproducibilidad ADR).
BUG CLAVE resuelto: el sandbox usa busybox grep (NO soporta --include) ⇒ mi sed de libwacom vía
grep -rl fallaba silencioso. Fix = seds directos sobre CMakeLists.txt. Cadena de blockers resuelta:
libwacom→opt, plasma-workspace añadido (LibKLookAndFeel/LibKWorkspace/LibTaskManager), KSMServer→opt
(wayland-puro sin ksmserver), xkbregistry→opt, xkeyboard-config SELLADO (ConfigureChecks xkb_base).
BLOCKER VIVO: feature_summary aborta por REQUIRED no hallados (XCB-XKB kcm-teclado, KF6Kirigami/
QQC2DesktopStyle pese a estar en deps, EGL, Qt6QuickWidgets) — interacción kcms-removido/wayland-puro,
necesita investigación fresca. Build detenido.
Cadena de blockers de configure descubierta (de-Alpinización KDE): qt5compat✓ knotifyconfig✓(sellado)
plasma5support✓ qqc2-desktop-style✓ → NetworkManagerQt/DocTools REQUIRED (patcheados a opcional) →
libwacom REQUIRED (KCM tableta) → KAccounts6 REQUIRED (online accounts). Desactivé subdir kcms (el shell
está en containments/applets, no en KCMs) pero libwacom/KAccounts6 los piden subdirs no-kcms (applets).
Tail pendiente: podar applets/subdirs que exigen accounts/wacom, o buildear shell-only. Ver handoff.
Configura OK (deps: qt5compat+knotifyconfig+plasma5support añadidos) y compila (155 obj);
en curso con cascada de rebuild de deps (fragilidad de hashing dinámico). Al sellar → hidratar
al rootfs → plasmashell cargaría la corona (H-shell). WITH_X11=OFF wayland-puro, patrón KF6.
- complete-closure.sh: escanea DT_NEEDED de todos los ELF del rootfs y proyecta del store
sellado el artefacto que provee cada soname AUSENTE, iterando a punto fijo. Resuelve las
deps runtime que el índice del repo NO lista (libmount.so.1/util-linux, libltdl, libzstd,
libQt6UiTools). Sonames base (musl libc/loader) no se hidratan.
- zlib-shared.toml: variante DINÁMICA de zlib (el canónico es --static). El stack GUI NEEDED
libz.so.1 por soname y ningún artefacto lo proveía → caía al libz.so.1 de Alpine (fuga de
soberanía Capa 0). .so fabricado del libz.a PIC vía --whole-archive (soname libz.so.1).
- Resultado: rootfs kde-store-rootfs con 1269 .so, 0 sonames faltantes; kwin_wayland resuelve
TODAS sus libs y carga su QPA (bloqueado sólo en render: worker sin GPU/llvmpipe).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>