diff --git a/docs/state/targets.toml b/docs/state/targets.toml index af33cc81..ae1ad81f 100644 --- a/docs/state/targets.toml +++ b/docs/state/targets.toml @@ -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] diff --git a/recipes/incoming-kde/networkmanager.toml b/recipes/incoming-kde/networkmanager.toml deleted file mode 100644 index 5ee13593..00000000 --- a/recipes/incoming-kde/networkmanager.toml +++ /dev/null @@ -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"] diff --git a/recipes/libgudev.toml b/recipes/libgudev.toml new file mode 100644 index 00000000..e59e8af2 --- /dev/null +++ b/recipes/libgudev.toml @@ -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"] diff --git a/recipes/udev-pc.toml b/recipes/udev-pc.toml new file mode 100644 index 00000000..65fbcfa6 --- /dev/null +++ b/recipes/udev-pc.toml @@ -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"] diff --git a/recipes/upower.toml b/recipes/upower.toml new file mode 100644 index 00000000..c0ec9fad --- /dev/null +++ b/recipes/upower.toml @@ -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 }