Sellada b3:25caa359 al primer intento. `--help` corre y los NEEDED traen `libpipewire-0.3.so.0`:
graba CON audio, que era exactamente lo que anoche no se podía.
Es la app que estaba bloqueada por el defecto del triaje —preguntaba «¿existe la receta?» en vez de
«¿la alcanza quien la usa?»—: sus dos backends de captura de sonido vivían sólo en colas y una
receta del corpus no alcanza una cola hermana. Con pipewire en el corpus, cae sola.
`-Ddefault_audio_backend=pipewire` explícito y no `auto`: su meson resuelve `auto` mirando qué
encontró en el sandbox (meson.build:95-101), o sea que el artefacto dependería de lo que quedó
montado en el lab. Misma disciplina que en mpv y ffmpeg.
⚠ SE LISTA SÓLO EN `escritorio-sway`, y la razón es de PROTOCOLO: captura por `wlr-screencopy`, que
implementan los compositores wlroots. KWin y mutter NO lo implementan —usan el portal/ScreenCast—,
así que meterlo en esas dos imágenes sería enviar una herramienta que no puede funcionar ahí: deuda
fantasma con forma de app. En COSMIC hay que verificar si cosmic-comp expone el protocolo antes de
listarlo; no se listó a ciegas.
Cubre el caso de uso principal por el que uno instala OBS, con UNA receta en vez de las 20 + Qt6 +
X11 que OBS pedía. escritorio-sway 146/146.
Paso 5 del ADR 0015, sus dos mitades.
SHIMS. `hammer qorpa export <id>` genera lanzadores finos y `.desktop` en el
espacio del host, desde lo DECLARADO en `[export]` — nunca todo: exportar todo
haría que el `ls` de la imagen compita con el nuestro, que es la falla de
Bedrock (arbitra en tiempo de exec, por heurística). Gana en tres cosas contra
un FUSE: cero costo en runtime, `cat` al shim y ves qué hace, y se revoca
borrándolos.
Se GENERAN, no se copian. El `.desktop` se arma con lista BLANCA de claves, así
que `Exec`, `TryExec`, `Path` y `DBusActivatable` quedan fuera por definición y
no por enumeración — una lista negra dejaría entrar la próxima clave ejecutable
que invente el estándar. El Exec original se cita en un comentario del fichero
generado, para que se vea qué decía y qué no se copió. El icono se busca en la
vista merged (upper primero, imagen después: si no, se perdería lo que instaló
el gestor de paquetes) y se copia al host, porque un icono que el host no
resuelve se ve como un cuadrito gris. Y `exported.json` registra cada fichero
escrito, para que `--remove` borre EXACTAMENTE eso y no por patrón sobre el
~/.local/bin de alguien.
Probado de punta a punta con un .desktop ajeno real de la imagen de Arch: el
shim corre `pacman -Q` del huésped desde el host, el X-KDE-Wayland-Interfaces
quedó fuera, el icono viajó, y --remove dejó 0 ficheros con la instancia intacta.
CLASE `ajeno`. build-state.py inyecta los nodos declarados en el nuevo
docs/state/qorpa-ajenos.toml ANTES que los `wanted`, y ese orden es la mitad del
punto: un nodo que provee una imagen ajena no es una receta por escribir. Con
eso el `xwayland` de escritorio-kde deja de ser deuda y pasa a contarse aparte:
escritorio-kde 187/188 listo falta 1 (raíces 14, + 1 ajenas)
Dos decisiones que sostienen esa cifra: los ajenos se RESTAN del denominador (si
entraran, el número que se lee como "cuánto construimos" crecería solo cada vez
que alguien enjaula una app), y la declaración vive en el REPO y no se lee de
/var/lib/hammer — build-state.json se commitea y lo regenera el cron en dos
máquinas; si la clase saliera de las instancias instaladas, cada una diría algo
distinto y se pisarían en cada cosecha. Es el error que ya se cometió con
sealed_remoto. Qué provee una imagen ajena es diseño; qué tenés instalado, no.
Un ajeno tampoco se hashea, y no por comodidad: no tiene procedencia de fuente,
así que un hash afirmaría que lo reproducimos.
2 tests nuevos (que del .desktop ajeno no sobreviva nada ejecutable; que el shim
no se rompa con rutas raras). 47/47.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U5cQtQrYNjWJVXVE6aEpQ2
Continúa lo que ya se hizo el 2026-09-02 con las 8 copias de gnome. Medido receta por receta con
`hammer hash`: de los 30 nombres que viven en el corpus Y en alguna cola, 13 dan el MISMO
ArtifactHash que su gemela del corpus y 22 son variantes deliberadas (glib/gtk4/pango de gnome,
dbus/openssl/libxml2 de kde…) que NO se tocan.
Se van las 13 redundantes: alsa-lib ×3, nasm ×2, zlib-shared ×2, y de incoming-kde ffmpeg,
fontconfig-shared, freetype-shared, libjpeg-turbo-shared, libpng-shared y vulkan-headers. Cada
consumidor las resuelve ahora en el catálogo PADRE, con el mismo hash.
VERIFICADO ANTES Y DESPUÉS, no argumentado: se snapshotearon los 47 consumidores directos, se
borraron las 13, y se re-hashearon. **0 consumidores vivos con hash distinto** (las 4 diferencias
son las propias recetas borradas, que se consumían entre sí). Cero rebuild.
EL EFECTO QUE NO SE BUSCABA Y ES EL MÁS VALIOSO: `build-state.json` guarda sus nodos POR NOMBRE, y
cuando un nombre vive en dos colas la membresía se consulta por el par `(cola, nombre)` de UNA sola
de ellas. Resultado: `ffmpeg`, `alsa-lib`, `vulkan-headers` y `zlib-shared` reportaban
`perfiles: []` —o sea "no está en ninguna imagen"— **mientras estaban en las cuatro**. Ahora dicen
la verdad, y `escritorio-kde` pasa de 183 a 185 porque aparecen dos nodos que el grafo no contaba.
La lección para el próximo análisis, que ya quedó en `scripts/vigia-sonames.py`: sobre el grafo se
pregunta con `yupana.membresia()`, que llavea por `(cola,nombre)`; el campo `perfiles` del JSON es
fiable sólo mientras el nombre viva en una sola cola.
Sin cambios en la deuda: cosmic sigue 105/106 por el OOM de xdg-desktop-portal-cosmic.
Las tres recetas pasan a `-Dpipewire-alsa=enabled`. Sirve a TODA app ALSA del corpus, no sólo a mpv:
un cliente que abre "default" desemboca en PipeWire por `libasound_module_pcm_pipewire.so` en vez de
pelearle la tarjeta al servidor. Es protocolo en vez de ABI compartida — la misma figura con la que
el ADR 0015 cruza el borde de la jaula.
EL FLAG SOLO NO HACE NADA, y ésta es la parte que no se ve venir: meson deja los plugins en
`/usr/lib/alsa-lib` (bien, ahí los busca alsa-lib) pero la CONFIGURACIÓN en
`/usr/share/alsa/alsa.conf.d`, **un directorio que alsa-lib no lee**. Sus `@hooks` cargan
`/var/lib/alsa/conf.d`, `/usr/etc/alsa/conf.d` y `/etc/alsa/conf.d` — leído del `alsa.conf` del
artefacto sellado, no supuesto. Sin el enlace que agrega la fase install, el plugin queda instalado
y no lo usa nadie: sellado e inerte, que es la familia de fallo del artefacto vacío. Se enlazan los
DOS ficheros: `50-pipewire.conf` hace que el destino EXISTA, `99-pipewire-default.conf` hace que sea
el destino POR DEFECTO — sin el segundo, mpv abriendo "default" no llega igual.
EVIDENCIA (test discriminante, porque "no falla" no prueba nada acá):
mpv --audio-device=alsa/pipewire → abre el device, falla al conectar (no hay demonio) ⇒ el PCM
ESTÁ DEFINIDO
mpv --audio-device=alsa/noexiste → "ALSA lib: Unknown PCM noexiste" ⇒ el control
El camino de verdad —que suene— sólo se puede ejercer con un PipeWire vivo, o sea en la sesión; eso
no se probó y no se afirma.
⚠ PRECIO, escrito para que no se diagnostique mal: con `99-pipewire-default.conf` puesto,
`pcm.!default` ES PipeWire. En una máquina donde PipeWire no esté corriendo, un cliente ALSA ya no
cae a la tarjeta: no suena. Es el trato que hace toda distro con pipewire-alsa.
Radio medido antes de tocar (`yupana radio pipewire`): 4 cosmic / 3 gnome / 2 kde. Reconstruidos 10
de 11 dependientes.
⚠ DEUDA DECLARADA, 1: `incoming-cosmic/xdg-desktop-portal-cosmic` murió DOS VECES por OOM (7 G de
RAM, sin cgroups, y otro agente compilando Rust a la vez — `dmesg` confirma «Out of memory: Killed
process (cargo)»). No es un fallo de la receta ni del cambio: es la máquina. Queda visible en el
grafo (escritorio-cosmic 105/106) en vez de escondido, y lo levanta el worker o un reintento con la
máquina libre.
Los otros tres perfiles cierran: KDE 183/183, GNOME 132/132, sway 140/140.
Sin esto mpv quedaba sellado y en NINGUNA imagen. Es exactamente la lección que este fichero ya
tiene escrita en el perfil de sway: `foot` estaba sellado en el corpus, ningún perfil lo listaba,
y el escritorio daba 121/121 SIN EMULADOR DE TERMINAL. La métrica de clausura mide las raíces
declaradas y no puede ver lo que falta en la declaración.
Se lista en los cuatro porque mpv vive en el corpus: una receta resuelve sibling-first y después
el catálogo padre, así que desde cualquiera de las cuatro colas se alcanza.
Los cuatro perfiles siguen en 0 deuda y cierran con la clausura nueva ya sellada:
escritorio-kde 171 → 180/180
escritorio-gnome 119 → 129/129
escritorio-cosmic 90 → 103/103
escritorio-sway 129 → 139/139
Corpus 788 → 798 recetas, 798 selladas. grafo: CIERRA | topo-sort: OK en los cinco.
Tercer y cuarto hueco de RUNTIME del triaje. Sin polkit-qt-1, Plasma no puede
elevar privilegios: ni montar un disco, ni cambiar ajustes del sistema.
Son DOS recetas porque hacía falta una segunda polkit. Hammer resuelve las deps
hermano→padre —la cola propia, después recipes/— y nunca cruza a una cola hermana,
así que la polkit de incoming-gnome es invisible desde incoming-kde. Y aunque se
viera no serviría: aquélla va con -Dintrospection=true contra glib-introspected,
que es la ISLA DINÁMICA del shell de GNOME (gjs importa gi://Polkit y necesita el
typelib). KDE enlaza las libs desde C++ y el typelib le sobra; traerlo obligaría a
meter gobject-introspection entero en la cola.
La nueva es homónima a propósito, mismo patrón deliberado que dbus (incoming-kde vs
raíz) y gmp (incoming-kde vs incoming-cosmic), con el mismo coste conocido:
store-gc no puede decidir por NOMBRE cuál de los dos sellados es el vigente. No la
renombré a polkit-kde porque el .pc que busca polkit-qt-1 es polkit-gobject-1, no
el nombre del paquete: renombrar sólo movería el problema al lector.
Radio medido antes de escribirla (yupana radio polkit): la de incoming-gnome tiene
6 dependientes transitivos y no se toca; la nueva, 0. Cero daño colateral.
Nada de esto necesitó descubrirse: glib-shared ya existía en la cola KDE y su
propio encabezado nombraba a polkit como uno de los motivos por los que se escribió.
── El guardián que sí hizo falta ────────────────────────────────────────────────
polkit-qt-1 sondea polkit con check_function_exists, que COMPILA Y ENLAZA. Si ese
enlace falla por algo del sandbox —y no porque la función falte—, cmake NO da
error: imprime «You have an older polkit-1 version» y define
POLKIT_QT_1_COMPATIBILITY_MODE. El build sella, el artefacto pesa lo esperado y la
autorización queda recortada sin que nadie se entere. La fase configure ahora
aborta si HAVE_POLKIT_SYSTEM_BUS_NAME_GET_USER_SYNC no llegó a 1 en el header
generado: polkit 127 tiene esa función, así que un 0 significa «el sondeo no pudo
enlazar», no «polkit es viejo». Pasó: no hay modo compatibilidad.
También va -DQT_MAJOR_VERSION=6 explícito. El default del CMakeLists es "5", y sin
la flag construiría bindings con otros nombres (polkit-qt5-1) que el dependiente
no encontraría hasta mucho después.
── Lo que esto NO enciende, a propósito ─────────────────────────────────────────
Los dos consumidores siguen esquivando polkit igual que antes:
· kauth construye con el backend polkit OPCIONAL apagado (cae al backend fake);
· plasma-workspace apaga el helper de Región&Idioma con -DGLIBC_LOCALE_GEN=OFF
-DGLIBC_LOCALE_PREGENERATED=ON, que es justo lo que evita el PolkitQt6-1
REQUIRED.
Encenderlos es otra decisión con su propio radio (plasma-workspace arrastra medio
escritorio). La pieza está puesta; la palanca no se toca sin pedirlo.
⚠ Y con las librerías viaja la postura de seguridad que ya declaraba
arje-polkit-compat: el demonio responde is_authorized=true a TODO. Estas libs son
la INTERFAZ que el escritorio espera, no la política. Queda repetido en las dos
recetas nuevas porque son las que ponen la pieza en manos del escritorio.
Las dos REPRODUCEN bit a bit (verificar-repro.sh 2/2). Los NEEDED de
libpolkit-qt6-core-1 son exactamente los esperados: Qt6DBus, Qt6Core,
libpolkit-gobject-1, gio/gobject/glib y libc.
corpus 788/788 · escritorio-kde 171/171 · grafo CIERRA · gate --check OK
Queda 1 wanted en KDE: xwayland — y ése no es deuda técnica sino una decisión
(X11 al tacho, Xwayland = compat opcional por-imagen, no en el core).
Segundo hueco de RUNTIME del triaje de la frontera. Nadie lo pide para construir
—por eso el escritorio sellaba completo sin él— pero sin este módulo los controles
QML de Plasma (botones, sliders, combos, los menús de los applets y de los KCM) se
dibujan con el estilo genérico de Qt. No lo reemplaza qqc2-desktop-style: aquél es
el estilo de escritorio integrado con KStyle; éste es la implementación QML nativa
de Breeze, la que Plasma 6 usa por defecto.
Dos cosas que no eran obvias:
1. Se llama casi igual que el vecino y viene de otro tarball. qqc2-DESKTOP-style
sale de Frameworks 6.27.0; qqc2-BREEZE-style sale del release de Plasma 6.7.2,
el mismo de breeze/kwin/plasma-workspace. Copiar la URL del vecino da 404.
El sha256 va contrastado contra el .sha256 que publica KDE al lado del tarball,
no sólo contra lo que bajó acá: la primera descarga volvió con 0 bytes y su
sha256 era el de la cadena vacía — un vacío que se lee como éxito.
2. La lista de deps no es la del vecino copiada: sale de la clausura de
find_dependency de los KF6*Config.cmake que ya están en el store. Ese recorrido
enseñó algo reutilizable: casi todo lo que esos configs piden (X11, XCB,
Wayland, OpenSSL, BZip2, LibLZMA) vive dentro de un `if (NOT TRUE)` — la rama
de build ESTÁTICO — y por lo tanto es código muerto en nuestro corpus, que
compila KF6 dinámico. Por eso acá no hay libX11 ni xorgproto, coherente con
Wayland-only. El find_package(X11) del CMakeLists raíz no es REQUIRED, así que
falla en silencio sin romper el feature_summary(FATAL_ON_MISSING_REQUIRED).
Confirmado a posteriori: los NEEDED del plugin son exactamente los 5 KF6 que la
clausura predijo (KirigamiPlatform, IconThemes, ColorScheme, GuiAddons,
ConfigCore) más Qt6 Quick/Gui/DBus/Core.
La fase install verifica por CONTENIDO, no por presencia: qmldir de org.kde.breeze
y de org.kde.breeze.impl no vacíos, Button.qml presente y el plugin de plataforma
de kirigami instalado. Un módulo QML sin su qmldir ocupa disco y arranca con el
estilo genérico sin decir nada. Salieron 83 controles y 3 .so.
Selló al primer intento y REPRODUCE bit a bit (verificar-repro.sh 1/1).
corpus 788/788 · escritorio-kde 166/166 · grafo CIERRA · gate --check OK
Quedan 2 wanted en KDE: xwayland y polkit-qt-1.
Nota sobre el diff de los cinco grafos: cambian los `dependientes_total` de las
deps de esta receta en TODAS las vistas, no sólo en --kde. Es correcto y está
documentado en build-state.py: ese campo se calcula sobre el grafo entero (todas
las colas del disco), que es la corrección del bug de libdrm.
Primero de los cuatro huecos de RUNTIME del triaje de la frontera. Ninguna receta
lo pedía para construir (por eso escritorio-kde cerraba 163/163 sin él), pero sin
la base el escritorio no sabe qué es un fichero: ni asociaciones, ni iconos, ni
abrir-con. Qt6 y GLib lo leen los dos de /usr/share/mime.
Vive en recipes/ y no en incoming-kde: es freedesktop puro, y en la raíz lo ven
los cinco grafos (GNOME y COSMIC lo quieren igual — gdk-pixbuf hoy lo ESQUIVA con
-Dgio_sniffing=false).
Tres cosas que no eran obvias:
1. Fuente por GIT, no tarball. Freedesktop no publica downloads de release para
este proyecto: la API sólo ofrece los -/archive/ autogenerados de GitLab, que
no son estables byte a byte (mismo criterio ya escrito en wlr-randr). El pin
es el tag 2.5.1 PELADO — acá el tag es objeto tag, la trampa de las 4 del
mirror (ADR 0013).
2. i18n.merge_file de data/meson.build es INCONDICIONAL: no lo apaga
-Dbuild-translations=false, porque es el paso que PRODUCE freedesktop.org.xml,
el payload entero. Eso exige un msgfmt que entienda --xml. El de gettext-tiny
sirve y no degrada nada: desde 2.x el template ya es XML válido (las
traducciones se marcan con reglas ITS externas, cero ocurrencias de "<_"), así
que sin catálogos la salida de un msgfmt real ES el template. Verificado a mano:
copia byte a byte de los 384036 del template.
3. meson install deja SÓLO el XML fuente. Los consumidores no leen ese XML: leen
los índices que genera update-mime-database (mime.cache, globs2, magic,
aliases, subclasses). Sin ese paso el artefacto pasa toda verificación de
presencia y el escritorio sigue sin saber qué es un .png — la regla 3 del repo
en su forma exacta. La fase install lo corre contra /out y verifica por
CONTENIDO: mime.cache y globs2 no vacíos, image/png en types. Salieron 1038
tipos y 1448 globs.
Nace con strip_debug = true y REPRODUCE bit a bit (verificar-repro.sh: 1/1, cero
divergencias), caché binaria incluida. Estático, 0 NEEDED.
corpus 788/788 sealed · escritorio-kde 165/165 · grafo CIERRA · gate --check OK
Quedan 3 wanted en KDE: xwayland, polkit-qt-1, qqc2-breeze-style.
Deja de ser una plantilla con `commit = 000…0`. Tres cosas, y las dos últimas
son el valor del commit:
1. PIN. `v0.1.0` era el tag que la versión declaraba y NO SIRVE: su `Cargo.lock`
está desincronizado con sus manifiestos en el propio repo, y `cargo vendor
--locked` se niega ("cannot update the lock file … because --locked"). No es
de hammer: el vendoreo del fetch arranca bien y muere DENTRO de cargo.
Comprobado con `cargo metadata --locked` en los tres refs — v0.1.0
incoherente, v0.2.0 y main coherentes. Se pinea v0.2.0, PELADO con ^{commit}
porque es objeto tag (93253cc2, no 0beb83b7).
=> Un tag no sirve como pin sólo por existir: hay que verificar que su
lockfile cierre.
2. El requisito de `vendor/` en la fuente que pedía el comentario quedó VIEJO:
hammer vendorea en el FETCH a partir del Cargo.lock, host-side, y por eso el
`--offline --locked` del sandbox se cumple. El repo no trae vendor/ en ningún
tag y aun así construye.
3. ⚠ FASE `install` PROPIA, obligatoria con `--example`. El default de Cargo hace
`find target/release -maxdepth 1 -type f -perm -100`, y cargo deja los
ejemplos en `target/release/examples/`. El find no encontraba nada, salía 0 y
**hammer selló un artefacto SIN BINARIO**: 22 min de compilación y un `sealed`
con sólo `.hammer/recipe.toml` dentro, 20K. `hash --check` decía SELLADO y el
grafo lo habría contado como al día.
No lo atrapa `Store::has` ni el guardián de vacíos de build-state, porque el
directorio NO está vacío — tiene el manifiesto. Es la regla 3 del CLAUDE.md en
su peor forma: un ausente falla a gritos, esto llegó al final diciendo que
todo fue bien. Por eso la fase lleva un `test -x` que hace ruidosa la
ausencia.
Verificado por contenido, no por el `sealed`: 17 M, usr/bin/llimphi-counter, ELF
pie, NEEDED = libc.so (dinámico, como la receta promete para un binario que
dlopea Vulkan/Wayland). El artefacto falso se podó y quedó en el ledger.
`version` pasa de 0.1.0 a 0.2.0 y NO mueve el hash: no está en hash_inputs (como
`license`). La identidad la da el commit.
Corpus: 787/787 SELLADAS, 0 deuda, 0 never. Gate --check OK, grafo CIERRA.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LykB7vw38b4Ck1Zij15RQ4
gdm, gnome-session y gnome-settings-daemon salen de la cola y quedan aparcadas
en `recipes/incoming-gnome/.deferred/`, que es el mecanismo que el repo ya usa
(precedente: incoming-kde/.deferred/libXft.toml). El glob del worker es
TOP-LEVEL y el del grafo también, así que dejan de molerse cada ciclo y dejan de
contarse como deuda que nadie va a pagar. `targets.toml` ya no las lista desde
el 2026-08-07 («APARCADAS POR DISEÑO»); esto alinea el árbol con esa decisión.
Y el mapa que llevaban estaba mal en las dos direcciones:
1. «La terna GTK3» es un nombre engañoso: **GTK3 no es el muro**. GTK3 tiene
backend Wayland y se construye con -Dx11_backend=false. Autorarlo no habría
destrabado ninguna de las tres. Lo que bloquea de verdad:
- g-s-d 48.1: gtk+-x11-3.0 / x11 / xfixes INCONDICIONALES => imposible en
Wayland-only, no «pendiente».
- gnome-session 48.0: dependency('libsystemd', required: true) en meson:124
es una comprobación de pkg-config EN BUILD. arje-logind-compat no la
satisface y es a propósito — su receta explica que GNOME consulta login1
en RUNTIME por D-Bus y que no hace falta la C-ABI sd-login. Único camino:
parchear ese required a false, que es una decisión, no un arreglo.
- gdm: cuelga de gnome-session, y con mirada-greeter probablemente sobra.
2. La lista «FRONTERA» estaba VIEJA: ya existen libX11, libXfixes, xorgproto,
libXau/Xcursor/Xdmcp/Xext/Xi/Xrender/Xtst, libxcb (casi todas por KDE) y
polkit, upower, geocode-glib, libgweather. Cuatro de las ocho líneas de g-s-d
habían dejado de ser ciertas. Faltan de verdad: gtk3, libnotify y una
variante libcanberra-gtk3.
Verificado contra el TARBALL (sha256 = el del pin), no contra el comentario.
incoming-gnome queda en 79 recetas, sellado=79 deuda=0 nunca=0.
Gate --check OK, grafo CIERRA, escritorio-gnome sigue 119/119.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LykB7vw38b4Ck1Zij15RQ4
`fontconfig-shared`, `freetype-shared`, `libjpeg-turbo-shared`, `libpng-shared`,
`libtiff-shared`, `libxml2-shared`, `libyaml-shared` y `zlib-shared` existían a
la vez en `incoming-gnome/` y en `recipes/`, y las ocho daban el MISMO
ArtifactHash que su gemela del corpus. Como la resolución de deps cae al padre
cuando no hay hermano, quitarlas deja a las consumidoras resolviendo contra
`recipes/` y con el mismo hash.
Medido, no supuesto: se hashearon las 1144 recetas antes y las 1136 después, y
de las 1136 supervivientes **0 cambiaron de hash**. No hay rebuild.
Lo que NO se toca, y conviene que quede dicho porque se parece:
- Las variantes de la ISLA DINÁMICA (glib, gtk4, gdk-pixbuf, pango, harfbuzz,
graphene, libadwaita, json-glib, libusb, libxcvt, pipewire, pulseaudio,
wireplumber, xdg-desktop-portal): mismo nombre, hash DISTINTO. Son sombras a
propósito — la introspección de GNOME exige .so reales.
- Las copias entre COLAS (alsa-lib, hwdata, xkeyboard-config, libdisplay-info,
lcms2, icu4c, lua, nasm, fuse3, libsndfile, libelogind, hicolor-icon-theme,
dbus-shared): también dan el mismo hash, pero NO sobran. Cada cola necesita su
propio hermano para cerrar su clausura; borrar la de una rompe esa cola. No es
el caso de onda-2, donde la cola entera duplicaba a otra.
Y el criterio, otra vez: `pipewire` y `pulseaudio` son TEXTUALMENTE idénticas a
las de COSMIC y sellan distinto, porque sus deps resuelven distinto según la
cola. El fichero no dice la verdad; el hash sí.
Gate --check OK, grafo CIERRA, escritorio-gnome sigue 119/119. La cola queda en
82 recetas (79 selladas + la terna GTK3) y sus 5 parches, todos en uso.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LykB7vw38b4Ck1Zij15RQ4
El caso LIMPIO del mismo fenomeno que onda-1, sin ninguna de sus asperezas: las
22 recetas son byte a byte identicas a las de incoming-gnome Y las 22 dan el
MISMO ArtifactHash, o sea la misma direccion del store. Sin divergencias, sin
colision de nombre y sin un solo artefacto que podar al retirarla.
La comprobacion que decide NO es `diff` sino `hammer hash`: la resolucion de
deps es hermano->padre, asi que dos ficheros identicos en colas distintas pueden
sellar distinto. Aca coinciden los 22.
Se va tambien `cairo-ctime-r.patch`, verificado identico al de incoming-gnome, y
comprobado que ninguna receta de ninguna cola queda apuntando a un parche
inexistente.
El andamio ya no sostenia nada: el trabajo de la isla dinamica vive en
incoming-gnome, que es la cola que el perfil usa. Sale de QUEUES en el mismo
commit, por la simetrica de la regla que ese fichero documenta.
Gate --check OK, grafo CIERRA, escritorio-gnome sigue 119/119, corpus 786/787.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LykB7vw38b4Ck1Zij15RQ4
Cierra la jubilacion empezada con gnome-desktop. Las 5 recetas que quedaban:
- glib, glib-introspected, gobject-introspection, py3-setuptools: byte a byte
identicas a las de incoming-gnome Y con el MISMO ArtifactHash, o sea que
sellaban en la misma direccion y entraban por cache-hit. Coste de build cero;
coste real: un segundo sitio donde editar, que se separa en silencio.
- gsettings-desktop-schemas: la unica distinta, y es la version ANTERIOR al
2026-07-28 (introspection=false + link=static). La vigente lo activo porque el
gir de Meta de mutter incluye GDesktopEnums-3.0.gir, que sale de ahi, y sin el
el g-ir-scanner corta en el ultimo target de mutter (721/722).
Lo caro no era el tiempo sino el NOMBRE: el gsettings viejo competia con el
bueno, dos artefactos homonimos con hash distinto en el store. Podado el
huerfano (0fb1703d, 155 KiB exclusivos) y anotado en el ledger anti-churn; los
otros cuatro artefactos siguen vigentes porque los produce incoming-gnome.
Y al jubilar gnome-desktop las dos hojas de la cola se habian quedado sin
consumidor: la cola se alimentaba a si misma y terminaba en el aire.
Sale tambien de QUEUES en farm-worker-loop.sh, por la simetrica de la regla que
ese fichero ya documenta dos veces: una cola ausente de la lista no da error,
da silencio — y una cola retirada que sigue en la lista, tambien.
Gate --check OK, grafo CIERRA, escritorio-gnome sigue 119/119, corpus 786/787.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LykB7vw38b4Ck1Zij15RQ4
Ningun nodo cambia de estado y el gate `--check` sigue OK: lo unico que se
mueve es `dependientes_total` de sus deps, un dependiente menos cada una. Es
la yupana cruzando TODAS las colas, onda-1 incluida, aunque ningun grafo la
cargue como cola propia.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LykB7vw38b4Ck1Zij15RQ4
`targets.toml` declaraba gnome-session, gnome-settings-daemon y gdm como raíces del
perfil, mientras el encabezado de las tres recetas dice "APARCADA por diseño" desde el
2026-08-07, verificado contra el meson.build de cada tag: las tres mueren en GTK3, que es
una de las tres deudas que el frente GNOME aparcó a propósito (GTK3 / X11 / PAM).
Dos documentos del repo decían cosas opuestas, y el que se mira primero es el grafo. El
resultado era deuda FANTASMA: escritorio-gnome reportaba 124/127 con 3 en `never` para
siempre, se leía como trabajo pendiente, y el worker las reintentaba en cada ciclo. En
esta misma sesión me hizo afirmar dos veces que GNOME estaba "a 3 recetas de cerrar".
No bloquean el escritorio: gnome-shell no depende de gnome-session ni de g-s-d, ni en
build ni para arrancar. El camino vivo es mutter → gnome-shell, lanzado por arje; el
único que pedía gnome-session era gdm.
Las recetas SIGUEN en el repo con su análisis intacto. Si algún día se autora GTK3, se
vuelven a añadir a `paquetes` y el objetivo reaparece solo.
escritorio-gnome: 119/119, CIERRA.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LykB7vw38b4Ck1Zij15RQ4