un solo NetworkManager (y KDE recupera WiFi) + upower al corpus sin arrastrar polkit

── 1. Se RETIRA incoming-kde/networkmanager.toml ───────────────────────────────────────────────
  networkmanager-qt  b3:78bbdcda00d758fb3cc3a0be7da6a67395dfbe0e4d55c5d8e5cf8afaf728ff72
  plasma-nm          b3:496a9ff7794ae5d89ac2842bdfbca38c25c91df37465a049db7cf75ee0041b82

Ayer se promovió NetworkManager al corpus CON WiFi porque la variante de KDE iba con -Dwifi=false,
y quedaron dos. Esto cierra el arco: retirada la de la cola, `networkmanager-qt` resuelve al PADRE
y la distro tiene UNO solo. Consecuencia concreta: **KDE pasa a tener WiFi**, porque su applet
hablaba con un demonio construido sin soporte inalámbrico.

Medido con `yupana radio` antes de borrar: 2 rebuilds (networkmanager-qt, plasma-nm), los dos en
la cola KDE. Y comprobado sobre el ARTEFACTO del corpus que publica lo que nm-qt pide —`libnm.pc`
y `usr/include/libnm`— antes de quitarle el suelo. Los dos sellan.

── 2. upower al corpus: COSMIC dibujaba una batería sin nadie que se la contara ────────────────
  libgudev  b3:87ca5e73…  ·  udev-pc  b3:fa880b5c…   (hash IDÉNTICO desde las dos partes ⇒ cache-hit)
  upower    b3:c82e655ff7011150f21f9413433c518f12c827c52ecf6f9fc3484f75d85c155c

Ayer escribí que esta cadena eran «3 promociones, una de ellas polkit, decisión de arquitectura».
Fui a mirar y polkit SALE de la ecuación con una perilla: la variante de KDE va `-Dpolkit=enabled`
«porque polkit YA está sellada» —cierto EN ESA COLA y falso desde el corpus—, y apagarlo cuesta
poco medido en FUNCIÓN: polkit en upower sólo gobierna las acciones privilegiadas (suspender e
hibernar por org.freedesktop.UPower, además deprecadas: hoy eso lo hace logind). Reportar batería,
carga, tiempo restante y línea de corriente NO pasa por polkit, que es justo lo que COSMIC quiere.

Se corrigió además la frase del comentario heredado que decía `-Dpolkit=enabled` al lado de un flag
que ahora dice `disabled`: una nota que desmiente al código de al lado es peor que no tener nota.
Y se le añadió su [[service]] (el corpus no lo traía; el label/id son los mismos que en GNOME a
propósito: el ULID identifica al SERVICIO, no al artefacto). No mueve el hash.

Comprobadas las NEEDED de upowerd con provee.py: libupower-glib, libffi.so.8, libz.so.1,
libudev.so.1 — las cuatro las publica el corpus y ya estaban en [deps]. Sin NEEDED colgante.

── 3. targets.toml ─────────────────────────────────────────────────────────────────────────────
  escritorio-kde     servicios += NetworkManager  (llegaba por clausura de plasma-nm y NADIE lo
                                                   arrancaba: el applet sobre un demonio apagado)
  escritorio-cosmic  paquetes  += upower · servicios += upowerd

⚠ Y se CORRIGE la nota de ayer que decía «NO declarar networkmanager en escritorio-kde porque
plasma-nm ya arrastra la variante de la cola». Ya no hay variante de cola.
This commit is contained in:
Sergio
2026-09-13 21:15:14 +00:00
parent ddfcdc7ab2
commit 0e35652fb1
5 changed files with 175 additions and 57 deletions
+18 -2
View File
@@ -440,6 +440,10 @@ servicios = [
"pipewire", "pipewire-pulse",
# 2026-09-13: con `wireplumber` declarado arriba, el audio pasa de «acepta clientes» a «encamina».
"wireplumber",
# `NetworkManager` llega por la clausura de `plasma-nm` y hasta hoy NADIE lo arrancaba: el applet
# de red de Plasma se dibujaba sobre un demonio apagado. Con la cola retirada es el del corpus,
# o sea el que sí maneja WiFi.
"NetworkManager",
]
[perfil.escritorio-gnome]
@@ -735,8 +739,13 @@ paquetes = [
# porque allá se escribió para dar `libnm.so` a plasma-nm y nada más. La variante del CORPUS va
# con `-Dwifi=true` y con `nmcli` (el artefacto de KDE no lo trae, comprobado sobre el store), y
# delega el handshake WPA2 en el `wpa_supplicant` que `base` declara desde hoy.
# ⚠ NO declarar esto en `escritorio-kde`: allá `plasma-nm` ya arrastra la variante de la cola, y
# dos NetworkManager distintos en la misma ruta es la enfermedad de las dos glib.
# ⚠ CORREGIDO EL MISMO DÍA: esta nota decía «NO declarar esto en escritorio-kde, allá plasma-nm ya
# arrastra la variante de la cola». **Ya no hay variante de cola**: `incoming-kde/networkmanager`
# se retiró y `networkmanager-qt` resuelve al padre, así que la distro tiene UN solo
# NetworkManager y KDE pasó a tener WiFi (la suya iba con `-Dwifi=false`). Costó 2 rebuilds
# —networkmanager-qt y plasma-nm—, medidos con `yupana radio` antes de tocar nada.
# KDE sigue sin listarlo entre sus `paquetes` porque no hace falta: `plasma-nm` lo arrastra por
# clausura. Lo que sí hacía falta era arrancarlo, y está en su lista de `servicios`.
"networkmanager",
]
@@ -975,6 +984,12 @@ paquetes = [
# ⚠ NO declarar esto en `escritorio-kde`: allá `plasma-nm` ya arrastra la variante de la cola, y
# dos NetworkManager distintos en la misma ruta es la enfermedad de las dos glib.
"networkmanager",
# `upower` (2026-09-13): **COSMIC dibujaba un indicador de batería sin nadie que se la contara.**
# El demonio no estaba en la clausura: la receta vivía en `incoming-kde` y en `incoming-gnome`,
# las dos inalcanzables desde acá. La variante del corpus va con `-Dpolkit=disabled` —polkit en
# upower sólo gobierna suspender/hibernar, que además está deprecado; reportar carga y tiempo
# restante no pasa por ahí— y con eso la cadena cierra sin meter un polkit de verdad al corpus.
"upower",
]
# ── QUÉ ARRANCA (el «enable»; SDD 30 §3) ────────────────────────────────────────────────────────
@@ -998,6 +1013,7 @@ servicios = [
"dbus-system", "logind-compat", "cupsd", "bluetoothd",
"pipewire", "pipewire-pulse", "wireplumber",
"NetworkManager", # 2026-09-13
"upowerd", # 2026-09-13: el indicador de batería deja de mirar al vacío
]
[perfil.escritorio-sway]
-55
View File
@@ -1,55 +0,0 @@
# NetworkManager 1.52.0 — libnm (libnm.so + libnm.pc + headers NetworkManager.h/nm-*.h). Campaña KDE
# (ADR 0011): destraba networkmanager-qt (KF6NetworkManagerQt) → plasma-nm, el applet de red. Era el
# "rabbit-hole libnm→glib" que plasma-workspace esquivó parcheando NetworkManagerQt a opcional.
#
# El tarball NO está en download.gnome.org (sólo llega a 1.9.x; NM migró) ⇒ git-archive de
# gitlab.freedesktop.org.
#
# **-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 cripto no valida certificados 802.1X, pero
# libnm compila y la API D-Bus que usa networkmanager-qt es completa.
#
# Deps DURAS de NM (dependency() sin required:false): libudev (→ libudev-zero YA sellado, da libudev.so.1
# + libudev.pc), libndp (receta nueva), gio-unix-2.0 (→ glib-shared, la deuda Capa 0 recién saldada).
# jansson/libpsl son required:false. Todo lo demás se apaga: sin daemon-extras (ovs/ppp/modem/wifi/nmtui/
# teamdctl/ofono/cloud-setup), sin systemd (session_tracking=no, journal off), sin polkit/selinux/audit,
# sin introspection/docs/tests/ebpf/firewalld.
name = "networkmanager"
version = "1.52.0"
license = "GPL-2.0-or-later"
[source]
tarball = "https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/archive/1.52.0/NetworkManager-1.52.0.tar.gz"
sha256 = "2ebe60a1497a9650d58336b73413d838189b04543365b3dbc22e1eb8023d205f"
[build]
compiler = "zig-cc"
target = "x86_64-linux-musl"
link = "dynamic"
flags = []
[build.phases]
configure = '''
# meson.build:92 hace `find_program('xsltproc')` INCONDICIONAL (required por defecto), pero xsltproc sólo
# se usa en man/meson.build (páginas de manual), que no se construye con -Ddocs=false. Se degrada a
# required:false y así se evita la receta libxslt entera. (sed DIRECTO: el sandbox usa busybox grep, que
# no soporta --include.)
sed -i "s/xsltproc = find_program('xsltproc')/xsltproc = find_program('xsltproc', required: false)/" meson.build
PYTHONPATH=/usr/lib/python3.12/site-packages meson setup output --prefix=/usr --buildtype=release \
-Ddefault_library=shared \
-Dld_gc=false -Dconcheck=false -Dnmcli=false -Dreadline=none \
-Dcrypto=null \
-Dsystemdsystemunitdir=no \
-Dsession_tracking=no -Dsession_tracking_consolekit=false -Dsuspend_resume=consolekit \
-Dpolkit=false -Dselinux=false -Dsystemd_journal=false -Dlibaudit=no \
-Dwifi=false -Dppp=false -Dmodem_manager=false -Dovs=false -Dnmtui=false -Dnm_cloud_setup=false \
-Dteamdctl=false -Dofono=false -Debpf=false -Dfirewalld_zone=false -Dlibpsl=false \
-Dintrospection=false -Ddocs=false -Dtests=no -Dvapi=false \
-Dconfig_dhcp_default=internal -Dqt=false
'''
compile = "PYTHONPATH=/usr/lib/python3.12/site-packages ninja -C output"
install = "PYTHONPATH=/usr/lib/python3.12/site-packages DESTDIR=/out meson install -C output --no-rebuild"
[deps]
build = ["meson", "samurai", "python3", "pkgconf", "glib-shared", "pcre2-shared", "libffi",
"libudev-zero", "libndp", "libnl", "zlib-shared", "gettext-tiny", "libxml2", "util-linux", "perl", "dbus", "expat"]
+39
View File
@@ -0,0 +1,39 @@
# ⚠ COPIA EN LA COLA KDE (2026-09-09), y NO es lo mismo que la de GNOME aunque el texto sea igual.
# Las colas no se ven entre sí (HERMANO→corpus), así que `upower` en KDE necesita una acá.
# ⚠ Y el ARTEFACTO ES DISTINTO a propósito: `glib` existe en las DOS colas y son recetas distintas.
# Desde `incoming-gnome/` esto se construye contra la glib de GNOME; desde acá, contra la del
# corpus (KDE no tiene glib hermana). Medido: promoverla al corpus le cambiaba el hash y habría
# arrastrado a GNOME a la glib del corpus — el cuadro de las «dos glib» que este repo ya pagó.
# Por eso se COPIA y no se promueve.
# libgudev 238 — envoltorio GObject sobre libudev (GUdevClient/GUdevDevice: enumerar dispositivos y
# escuchar uevents con el bucle de GLib en vez de a mano).
#
# La piden DOS de la onda 3, y por eso va antes que colord: mutter por su opción `udev`, que es la
# que necesita el backend NATIVO (KMS/DRM) —o sea, la que hace que mutter sea un compositor de
# verdad y no sólo un cliente anidado— y colord, que la exige incondicionalmente (gudev-1.0).
#
# libudev lo provee libudev-zero, ya en el corpus y sellado (libudev.pc + libudev.a). Ojo con el
# gotcha ya conocido de este frente: eudev y libudev-zero PISAN el mismo .pc y el mismo .so — acá se
# declara libudev-zero explícitamente para que no haya duda de cuál entra en el cierre.
#
# Feature-minimal: introspection/vapi/tests disabled (tests piden umockdev), gtk_doc off.
name = "libgudev"
version = "238"
license = "LGPL-2.1-or-later"
[source]
tarball = "https://download.gnome.org/sources/libgudev/238/libgudev-238.tar.xz"
sha256 = "61266ab1afc9d73dbc60a8b2af73e99d2fdff47d99544d085760e4fa667b5dd1"
[build]
compiler = "zig-cc"
target = "x86_64-linux-musl"
link = "static"
[build.phases]
configure = "PKG_CONFIG_PATH=/usr/lib/pkgconfig PYTHONPATH=/usr/lib/python3.12/site-packages meson setup output --prefix=/usr --buildtype=release --wrap-mode=nodownload --prefer-static -Ddefault_library=static -Dintrospection=disabled -Dvapi=disabled -Dtests=disabled -Dgtk_doc=false -Dc_args=-Wno-error=date-time"
compile = "PYTHONPATH=/usr/lib/python3.12/site-packages ninja -C output"
install = "PYTHONPATH=/usr/lib/python3.12/site-packages DESTDIR=/out meson install -C output --no-rebuild"
[deps]
build = ["meson", "samurai", "python3", "pkgconf", "glib", "libudev-zero", "libffi", "pcre2", "zlib"]
+53
View File
@@ -0,0 +1,53 @@
# ⚠ COPIA EN LA COLA KDE (2026-09-09). El original vive en `incoming-gnome/`, y las colas NO se ven
# entre sí: una receta resuelve HERMANO→corpus y nunca de reojo a otra cola. `upower` la necesita
# para que KDE tenga batería y perfiles de energía (powerdevil habla con upower por D-Bus).
# Sus deps son sólo `pkgconf`, que está en el corpus ⇒ **el ArtifactHash es el MISMO que el de la
# copia de GNOME** (verificado): un solo artefacto en el store, cero builds nuevos.
# udev-pc — el `udev.pc` que falta, y nada más.
#
# QUÉ ES: mutter pide DOS pkg-config distintos para su backend nativo (meson.build:262-264):
# `libudev` (la librería, que da libudev-zero) y `udev` (metadata: la variable `udevdir`, dónde van
# las reglas). libudev-zero provee el primero y no el segundo — no tiene por qué: es una libudev sin
# udevd. En distros con systemd el `udev.pc` lo pone systemd; en las que no, lo pone eudev.
#
# POR QUÉ UNA RECETA APARTE Y NO AGREGARLO A libudev-zero: `yupana radio libudev-zero` da **51
# sellados cayendo a deuda**, en las cinco imágenes (base, cli y los tres escritorios). Un fichero de
# 4 líneas no justifica reconstruir medio catálogo. Esta receta instala SÓLO el .pc, así que no pisa
# nada de libudev-zero y las dos conviven en el mismo cierre.
#
# LA FUENTE es el tarball de libudev-zero a propósito, aunque no se compile nada de él: `[source]` es
# obligatorio en el esquema de receta, y atarla a su upstream natural deja claro de quién es
# compañera. El .pc se escribe acá porque libudev-zero no lo trae.
#
# udevdir=/usr/lib/udev es la ruta real de esta distro: la Semilla de arje arranca /usr/bin/udevd y
# ahí busca sus reglas. mutter sólo usa el valor para saber dónde instalar las suyas.
name = "udev-pc"
version = "1.0.4"
license = "ISC"
[source]
tarball = "https://github.com/illiliti/libudev-zero/archive/refs/tags/1.0.4.tar.gz"
sha256 = "10148cfd6047d387bf71eca72cd19c177084224d96434a118d8def6e0a3d6316"
[build]
compiler = "zig-cc"
target = "x86_64-linux-musl"
link = "dynamic"
[build.phases]
compile = 'true'
install = '''
set -e
mkdir -p /out/usr/share/pkgconfig
cat > /out/usr/share/pkgconfig/udev.pc <<'PC'
prefix=/usr
udevdir=${prefix}/lib/udev
Name: udev
Description: udev device manager (metadata; la libreria la provee libudev-zero)
Version: 252
PC
'''
[deps]
build = ["pkgconf"]
+65
View File
@@ -0,0 +1,65 @@
# upower 1.90.10 — **la variante del CORPUS**: el demonio que reporta batería, carga y estado de
# energía por D-Bus. Es lo que alimenta el indicador de batería de un escritorio.
#
# ══ POR QUÉ EXISTE ESTA COPIA (2026-09-13) ═════════════════════════════════════════════════════
# El barrido de servicios midió que **`escritorio-cosmic` dibuja un indicador de batería y NO tiene
# `upowerd`** en su clausura: el applet existe y no tiene de dónde leer. La receta vivía en
# `incoming-kde` y en `incoming-gnome` —las dos inalcanzables desde COSMIC, que es una cola
# hermana— así que la copia va al corpus, el único sitio desde el que las cuatro imágenes la ven.
#
# ══ EL CAMBIO QUE HACE QUE LA CADENA CIERRE: `-Dpolkit=disabled` ═══════════════════════════════
# La variante de KDE va con `-Dpolkit=enabled` «porque polkit YA está sellada» — cierto **en esa
# cola**. Desde el corpus, `polkit` NO se alcanza, y promoverlo sería meter un polkit de verdad al
# lado de `arje-polkit-compat`: una decisión de arquitectura, no un paso de este barrido.
#
# Apagarlo cuesta poco y conviene saber QUÉ cuesta: polkit en upower sólo gobierna las acciones
# PRIVILEGIADAS (suspender/hibernar por `org.freedesktop.UPower`), que además están deprecadas —
# hoy eso lo hace logind. **Reportar batería, carga, tiempo restante y estado de la línea de
# corriente no pasa por polkit**, y es exactamente para lo que COSMIC lo quiere. Con esto la cadena
# es `libgudev` + `udev-pc` + `upower`, y las dos primeras sellan con hash IDÉNTICO desde las dos
# partes ⇒ entran por cache-hit.
#
# ⚠ Hay tres variantes vivas (corpus, kde, gnome) y no colisionan: ninguna imagen hidrata dos.
# La de GNOME va con introspección (gjs dlopea `libupower-glib.so.3`); ésta no la necesita.
#
# Lo que sigue es la documentación de la variante de KDE, de la que ésta es copia.
name = "upower"
version = "1.90.10"
license = "GPL-2.0-or-later"
[source]
tarball = "https://gitlab.freedesktop.org/upower/upower/-/archive/v1.90.10/upower-v1.90.10.tar.gz"
sha256 = "7fcd51bece2526dbee5170feb3ffd1adab5b0cd023575f1fd119d969b73f4b90"
[build]
compiler = "zig-cc"
target = "x86_64-linux-musl"
link = "dynamic"
[build.phases]
configure = '''
set -e
PKG_CONFIG_PATH=/usr/lib/pkgconfig:/usr/share/pkgconfig PYTHONPATH=/usr/lib/python3.12/site-packages meson setup output \
--prefix=/usr --buildtype=release --wrap-mode=nodownload \
-Ddefault_library=both -Dos_backend=linux -Dintrospection=disabled \
-Didevice=disabled -Dpolkit=disabled -Dman=false -Dgtk-doc=false \
-Dudevrulesdir=/usr/lib/udev/rules.d -Dudevhwdbdir=/usr/lib/udev/hwdb.d \
-Dsystemdsystemunitdir=no -Dc_args=-Wno-error=date-time
'''
compile = "PYTHONPATH=/usr/lib/python3.12/site-packages ninja -C output"
install = "PYTHONPATH=/usr/lib/python3.12/site-packages DESTDIR=/out meson install -C output --no-rebuild"
[deps]
# Sin las cuatro de introspección: las saca `-Dintrospection=disabled` (ver cabecera).
build = ["meson", "samurai", "python3", "pkgconf", "gettext-tiny", "glib", "libgudev", "udev-pc", "libudev-zero", "libffi", "pcre2", "zlib-shared", "expat", "dbus-shared"]
# El demonio. Mismo `label` e `id` que la variante de GNOME a propósito: es EL MISMO servicio
# lógico, y el id (ULID) del SDD 30 identifica al servicio, no al artefacto que lo trae. Ninguna
# imagen hidrata dos upower, así que no hay ambigüedad.
# ⚠ Declararlo NO lo enciende: falta que el perfil lo habilite. Ver `escritorio-cosmic`.
[[service]]
label = "upowerd"
id = "01HQAR53D4M2NBV8KZTYXFQA24"
exec = "/usr/libexec/upowerd"
scope = "system"
restart = { initial_ms = 500, max_ms = 20000 }