Commit Graph
349 Commits
Author SHA1 Message Date
Sergio 9bbd2e42c9 estado: cosecha granja 2026-09-11T03:02:03Z — avance del árbol KDE 2026-09-11 03:02:03 +00:00
Sergio 953706909d estado: cosecha granja 2026-09-11T02:32:11Z — avance del árbol KDE 2026-09-11 02:32:11 +00:00
Sergio 7bdb781352 estado: cosecha granja 2026-09-11T02:01:57Z — avance del árbol KDE 2026-09-11 02:01:57 +00:00
Sergio 38338913eb estado: cosecha granja 2026-09-10T23:31:52Z — avance del árbol KDE 2026-09-10 23:31:52 +00:00
Sergio 6704ebe033 estado: cosecha granja 2026-09-10T22:32:06Z — avance del árbol KDE 2026-09-10 22:32:06 +00:00
Sergio e063fc16e9 estado: cosecha granja 2026-09-10T22:01:45Z — avance del árbol KDE 2026-09-10 22:01:45 +00:00
Sergio 5beb3aa461 estado: cosecha granja 2026-09-10T21:31:53Z — avance del árbol KDE 2026-09-10 21:31:53 +00:00
Sergio 3ff7585aa2 estado: cosecha granja 2026-09-10T21:02:45Z — avance del árbol KDE 2026-09-10 21:02:45 +00:00
Sergio ca7d228512 estado: cosecha granja 2026-09-10T20:35:24Z — avance del árbol KDE 2026-09-10 20:35:25 +00:00
Sergio 8db076bf3e estado: cosecha granja 2026-09-10T20:03:03Z — avance del árbol KDE 2026-09-10 20:03:03 +00:00
Sergio 9a1573e0cb estado: cosecha granja 2026-09-10T16:02:11Z — avance del árbol KDE 2026-09-10 16:02:11 +00:00
Sergio f9dae780fa estado: cosecha granja 2026-09-10T15:32:35Z — avance del árbol KDE 2026-09-10 15:32:35 +00:00
Sergio 9fbbb775a9 estado: cosecha granja 2026-09-10T15:01:48Z — avance del árbol KDE 2026-09-10 15:01:48 +00:00
Sergio f3236ef74a estado: cosecha granja 2026-09-10T14:32:10Z — avance del árbol KDE 2026-09-10 14:32:11 +00:00
Sergio 655a682aa6 estado: cosecha granja 2026-09-10T14:01:58Z — avance del árbol KDE 2026-09-10 14:01:58 +00:00
Sergio 3441a6129f estado: cosecha granja 2026-09-10T02:02:17Z — avance del árbol KDE 2026-09-10 02:02:17 +00:00
Sergio e3d984475a estado: cosecha granja 2026-09-10T01:32:00Z — avance del árbol KDE 2026-09-10 01:32:00 +00:00
Sergio 1d2d636bba estado: cosecha granja 2026-09-10T00:32:07Z — avance del árbol KDE 2026-09-10 00:32:08 +00:00
Sergio fb748370e1 estado: cosecha granja 2026-09-10T00:02:52Z — avance del árbol KDE 2026-09-10 00:02:53 +00:00
Sergio cf574c5bc4 estado: cosecha granja 2026-09-09T23:32:00Z — avance del árbol KDE 2026-09-09 23:32:00 +00:00
Sergio 894bfaf0f5 estado: cosecha granja 2026-09-09T23:02:09Z — avance del árbol KDE 2026-09-09 23:02:09 +00:00
SergioandClaude Opus 5 c20372597a targets: kde/gnome/cosmic heredan cli — las imágenes ya no salen sin shell ni red
Paso 1 del SDD 27. Resultó ser UNA LÍNEA POR PERFIL: el mecanismo `hereda` ya existía en
`scripts/targets.py` —transitivo, con detección de ciclos y orden preservado— y `escritorio-sway`
ya lo usaba desde el 2026-08-07. Los otros tres nunca lo declararon, y eso no era una decisión: era
composición no declarada.

LO QUE ARREGLA, medido antes: de los 27 paquetes del perfil `base`, la clausura de escritorio-kde
alcanzaba DOS. Contra el rootfs real: sin `bash`, sin `sudo`/`doas`, sin `git`, sin `useradd`, sin
`gpg` y **sin `dhcpcd`** —o sea sin con qué pedir una IP—; y lo que parecía estar (`ip`, `mount`,
`fsck`) eran applets de busybox (`/sbin/ip → ../bin/busybox`).

DESPUÉS, verificado hidratando de verdad y no leyendo el grafo: en el rootfs aparecen `bash`,
`sudo`, `doas`, `git`, `dhcpcd`, `useradd`, `gpg`, `rg`, `fd`, `bat`, y `/sbin/ip` pasa a ser el
BINARIO de iproute2 en vez del applet.

  raíces  kde 49→96 · gnome 39→86 · cosmic 43→88
  nodos   kde 301→356 · gnome 204→256 · cosmic 162→216
  deuda   0 en los tres — no hubo que construir NADA, ya estaba todo sellado
  colisiones nuevas al hidratar: CERO (los 28 .hammer-tmp son los de gmp/mpfr de antes)

⚠ `escritorio-mirada` NO hereda a propósito: es el rootfs *slim* del USB y sumarle 47 raíces
contradice su razón de ser. Si algún día se quiere, es la misma línea.

`kde-rootfs` en el volumen se rehidrató con la herencia (11 G) para que el nombre canónico no quede
viejo — que es el error que este mismo día costó encontrar en GNOME y COSMIC. El rootfs FUNDIDO y la
imagen siguen siendo los de antes: rehacerlos es un paso aparte.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LCt3ettR4Z7b6wPCBmbvEV
2026-09-09 22:31:12 +00:00
SergioandClaude Opus 5 542d9875fb kde: upower — la imagen declaraba powerdevil y no tenía batería
Primero de los dos huecos que dejaban a KDE POR DEBAJO de una instalación estándar. El perfil
declaraba `powerdevil` —el gestor de energía de Plasma— pero no a `upower`, que es con quien
powerdevil habla para leer la batería y aplicar perfiles. Medido: upower sólo existía en la cola de
GNOME, y las colas no se ven entre sí (HERMANO→corpus, nunca de reojo). En un portátil eso es un
escritorio sin indicador de batería, y el arranque no falla ⇒ no se ve hasta usarlo.

Cuesta TRES recetas y no siete, y la diferencia es una perilla: `-Dintrospection=disabled`.
GNOME la necesita ENCENDIDA porque su shell hace `imports.gi.UPowerGlib` desde JavaScript, o sea que
carga el typelib. powerdevil NO: habla D-Bus con `org.freedesktop.UPower`. Apagarla saca de la
frontera gobject-introspection, gi-foreign-girs, glib-introspected y py3-setuptools, que sólo viven
en la cola de GNOME.

⚠ Y NO SE PROMUEVEN AL CORPUS, aunque era lo primero que intenté. Al mover `libgudev` allá su
ArtifactHash CAMBIÓ (7404bc8d → 87ca5e73) y eso no es una mudanza: `glib` existe en las DOS colas y
son recetas distintas, así que desde `incoming-gnome/` se construye contra la glib de GNOME y desde
el corpus contra la del corpus. Promoverla habría arrastrado a GNOME a la glib del corpus — el
cuadro de las «dos glib» que este repo ya pagó caro. Revertido y verificado que vuelve al hash de
antes (7404bc8d), o sea GNOME intacto. Se COPIAN a la cola de KDE.
`udev-pc` sí comparte artefacto (sus deps son sólo pkgconf ⇒ mismo hash desde las dos colas, un
solo directorio en el store). `libgudev` es otro a propósito, por la glib.

VERIFICADO sobre el artefacto sellado, no supuesto: trae `usr/libexec/upowerd`, el
`org.freedesktop.UPower.service` de system-services y su política en `system.d` — que es exactamente
lo que powerdevil necesita para que el demonio arranque por activación D-Bus.

El perfil pasa a 49 raíces, 301/301 listo, deuda 0.

Queda el segundo hueco: KDE no tiene backend de portal (ni `xdg-desktop-portal` en su cola), o sea
que no hay compartir pantalla — y en particular la captura de obs-studio, que la imagen ya trae, no
tiene con quién hablar en Plasma. Eso es más caro: pide traer el portal a la cola y ESCRIBIR
`xdg-desktop-portal-kde`, que no existe como receta en ninguna cola.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LCt3ettR4Z7b6wPCBmbvEV
2026-09-09 22:02:49 +00:00
SergioandClaude Opus 5 eb8f217245 gnome: el perfil y el hidratador decían cosas distintas — 21 paquetes no llegaban a la imagen
Verificando que las extensiones de la tanda anterior llegaran al rootfs apareció algo bastante peor
que lo que fui a buscar: **`scripts/gnome/hydrate-gnome.sh` no lee `targets.toml`**. Arma el rootfs
desde una lista de 14 raíces escrita a mano dentro del propio script, y de las 28 raíces que el
perfil declaraba sólo DOS coincidían.

MEDIDO recorriendo la clausura de esa lista (123 recetas) contra la membresía del perfil: **21
paquetes declarados en `escritorio-gnome` no llegaban al rootfs hidratado**. No son accesorios —
son las hojas, que es justo lo que un perfil declara porque no es dep de build de nadie:

  atuq (el navegador) · foot (la terminal) · helix (el editor) · mpv · swayimg (el visor)
  zathura + zathura-pdf-poppler (el lector de PDF) · dejavu-fonts y dejavu-fonts-nerd (las FUENTES)
  xdg-desktop-portal-gnome · libnotify · desktop-file-utils
  bzip2-shared, expat-shared, libffi-shared, ncurses-shared, xz-shared (las .so que se cazaron el
  2026-09-03 recorriendo NEEDED, justamente para que el rootfs no resolviera contra el lab)
  y las cuatro de ayer: las tres extensiones y gnome-tweaks

O sea que el trabajo de descubrir que la imagen no tenía terminal, ni editor, ni una sola fuente
—con su análisis largo escrito en este mismo fichero— estaba DECLARADO y no llegaba.

Y la divergencia iba en los dos sentidos: 11 raíces de RUNTIME vivían sólo dentro del script y el
perfil no las conocía (accountsservice, geoclue, libgdm, libgweather, upower, librsvg, ibus, los dos
gi-*-typelibs, gsd-schemas y wireplumber). Sin ellas el shell no arranca: las carga por
`imports.gi.*`, que es invisible para la clausura de deps.

ARREGLO: las 11 se mueven a `targets.toml` con la justificación que el script ya traía bien escrita,
y el script queda marcado como SUPERADO por `scripts/hydrate-profile.py`, que hidrata desde el
perfil — la única declaración que existe. Su propia cabecera ya advertía de este modo de fallo
(«DOS fuentes de verdad para lo mismo, y divergen sin que nada lo diga»); esto es esa advertencia
cumpliéndose. El perfil pasa de 28 a 39 raíces y de 190 a 204 nodos, deuda 0.

VERIFICADO HIDRATANDO DE VERDAD, no leyendo: `hydrate-profile.py escritorio-gnome` proyecta
210/210 nodos (27993 ficheros, 3,5 G) y ahí están las tres extensiones, `gnome-tweaks` con su
módulo `gtweak`, y los tres gschemas en el directorio GLOBAL. Después se corrió el bloque nuevo del
lanzador contra ESE árbol: enumeró las tres, escribió el override y `glib-compile-schemas` salió 0
con stderr vacío.

⚠ DOS COSAS QUE APRENDÍ MIDIENDO Y CONVIENE QUE ESTÉN DICHAS:

1. **El hub NO puede hidratar GNOME hoy.** `gjs`, `gnome-shell` y `spidermonkey` salen «no sellado»
   localmente. No es deriva ni un grafo mintiendo: sus hashes vigentes SÍ están en
   `work/farm-sellados.txt` — o sea sellados EN EL WORKER — y la cosecha baja el manifiesto y no el
   store, a propósito (bajarlo deshacía la poda). `build-state` los cuenta bien porque mira también
   el manifiesto; `hydrate-profile.py` mira sólo el disco local. Los dos tienen razón.
2. **EXDEV entre bind-mounts, otra vez.** Hidratar a `work/` o a `work/out` falla con «Invalid
   cross-device link» AUNQUE `work/out` esté en el mismo /dev/sdb que el store: son bind-mounts
   distintos y `linkat()` no cruza montajes. Hay que hidratar accediendo al store por su montaje
   raíz (`--store /mnt/cosecha/store --into /mnt/cosecha/escritorios/…`). El mensaje de error del
   script lo dice y aun así me costó dos intentos.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LCt3ettR4Z7b6wPCBmbvEV
2026-09-09 19:56:19 +00:00
SergioandClaude Opus 5 4e4a2c8d2a gnome: dash-to-panel, appindicator y gnome-tweaks — y la lista de activas sale de las recetas
GNOME deja de ser la cáscara: tres extensiones y la app que el proyecto no instala y todo el mundo
termina instalando. El perfil queda 190/190 con 28 raíces, deuda 0.

  dash-to-panel v73   junta dash, ventanas y bandeja en una sola barra (lo que más cambia el uso)
  appindicator v64    devuelve los ICONOS DE BANDEJA que GNOME quitó; sin ella las apps que usan
                      StatusNotifierItem corren y no tienen dónde mostrarse
  blur-my-shell v72   (ya estaba; se le saca el override, ver abajo)
  gnome-tweaks 46.1   tema, iconos, cursor, tipografías, los botones de minimizar/maximizar que
                      GNOME esconde, y el interruptor de las extensiones

⚠ LA LISTA DE ACTIVAS SE MUEVE A UN SOLO SITIO, y esto era una bomba de relojería. `enabled-extensions`
es un ARRAY: un override de GSettings lo escribe ENTERO. Con la primera extensión el override vivía
en su receta y funcionaba; con la segunda NO se habrían sumado — ganaría la que compile última
(orden alfabético) y las otras quedarían instaladas y MUERTAS, sin un solo error. Ahora la arma
`scripts/gnome/gnome-start-qemu.sh`, que ya compilaba los esquemas al arrancar, enumerando los uuid
presentes en /usr/share/gnome-shell/extensions. La política es «lo que la imagen instala, se
activa»; el dconf del usuario gana sobre el default.
Una receta NO puede ser ese sitio: hammer exige `[source]` en toda receta («missing field `source`»),
así que no hay forma de escribir una receta de pura política. Se probó el bloque contra un árbol de
juguete: lista las dos extensiones, salta un directorio sin metadata.json, el override compila con
stderr vacío y `gsettings get` devuelve las dos. Y si la lista cambia borra `gschemas.compiled` para
forzar recompilación — sin eso, una imagen ya arrancada ignoraría la extensión nueva en silencio.

⚠ EL HALLAZGO CARO: `msgfmt` de gettext-tiny REVIENTA con las formas plurales del árabe. SIGILL,
exit 132, «index 6 out of bounds for type 'size_t[6]'», y deja un .mo de 0 bytes. Reproducido FUERA
de la receta con el binario sellado. No es el idioma sino el mensaje: blur-my-shell compila su
ar.po sin problema porque no tiene NINGÚN plural (msgstr[5] = 0); el de tweaks tiene exactamente
uno. Acá se saca `ar` del LINGUAS y se pierde la traducción de UNA app, con el diagnóstico escrito
en la receta. ARREGLARLO ES OTRA UNIDAD DE TRABAJO: gettext-tiny la usan 108 recetas.

Cada receta usa el mecanismo de SU upstream, que no es el mismo en las tres:
  blur-my-shell   `make build` llama a `gnome-extensions pack` —el CLI que nuestro shell apaga— así
                  que se copia el árbol a mano, con el layout LEÍDO del zip de EGO y comparado
                  contra él (idéntico, sin sobras ni faltantes)
  dash-to-panel   su Makefile tiene un `install` que honra DESTDIR y hace lo de un paquete de
                  distro: gschema y locale a los directorios GLOBALES. ⚠ `VERSION=73` se pasa a
                  mano porque sin ella el Makefile hace `git describe` y el árbol viene por
                  `git archive`, sin `.git` ⇒ metadata quedaría con el marcador "version": 9999
  appindicator    meson. ⚠ `-Dlocal_install=disabled` explícito: en `auto` decide mirando si el uid
                  es 0, o sea que hoy acierta POR ACCIDENTE — y si el lab dejara de correr como
                  root instalaría en $HOME/.local y el artefacto sellaría vacío. Y `jq` va en deps
                  aunque sea JavaScript puro: su meson saca el uuid del metadata.json con jq

⚠ gnome-tweaks NO costó ninguna receta nueva, y eso hubo que medirlo: su meson declara siete deps
mínimas de runtime y las siete ya estaban selladas. La que parecía traer una cadena de Python
entera —`pygobject-3.0`— la provee `py3-gobject`, que YA ESTABA en el corpus con otro nombre y
publica `pygobject-3.0.pc`. El nombre no es el hecho, otra vez.
Sí costó dos deps que el configure reclamó y que son el patrón `.pc Requires` → `[deps].build`:
`appstream` (la pide `libadwaita-1.pc` y el error culpa a libadwaita, que está bien instalada) y
`desktop-file-utils` (meson la busca como PROGRAMA para `update-desktop-database`).
Sus deps de RUNTIME —python3 y py3-gobject— van declaradas: es una app de Python, si no están en la
imagen se instala y no arranca, y ningún build lo delata.

Las cuatro licencias, verificadas en la fuente pineada y NINGUNA leída del COPYING —cuyo apéndice
«How to Apply» trae siempre la frase «or any later version»—: blur-my-shell del README del commit,
dash-to-panel y appindicator de la cabecera de sus fuentes, gnome-tweaks de su etiqueta SPDX.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LCt3ettR4Z7b6wPCBmbvEV
2026-09-09 19:41:52 +00:00
SergioandClaude Opus 5 8c2cb10414 gnome: la primera extensión del catálogo — blur-my-shell v72, instalada Y activa
La imagen de GNOME traía la CÁSCARA: el shell sabe cargar extensiones —`ui/extensionSystem.js` va
en el gresource sin opción que lo apague y su gschema sellado trae `enabled-extensions`— pero no
había ninguna que cargar. Esta es la primera, y fija el patrón para las otras ~1400.

⚠ NO HIZO FALTA TLS, que era la conclusión fácil del análisis de ayer. glib-networking sólo lo pide
BAJARLAS desde extensions.gnome.org con el descargador del shell. Empaquetada, una extensión se
instala como cualquier receta y no toca la red.

LA FUENTE ES EL REPO DEL AUTOR, NO EL ZIP DE EGO, por dos razones y las dos medidas:
  1. hammer no sabe abrir un zip: el fetch extrae con `tar -x` y GNU tar contesta «This does not
     look like a tar archive». Ninguna receta del corpus usa .zip.
  2. Y aunque lo abriera, el zip de EGO es un ARTEFACTO que construye EGO desde este mismo repo.
     Pinear el zip es pinear el binario de un tercero; pinear el commit es pinear el código.
El tag v72 es el que EGO sirve para shell 48 —preguntado a su API, no supuesto— y el metadata.json
declara ['46','47','48','49','50']. ⚠ Eso hay que preguntarlo por extensión: nixpkgs va por GNOME
50 y hay extensiones que ya sólo declaran el major nuevo.

SIN `gnome-extensions pack`, que es lo que usa el Makefile de upstream y es el CLI que nuestra
receta del shell apaga (-Dextensions_tool=false; encenderlo costaría gnome-autoar y re-hashear
gnome-shell entero). No hace falta: `pack` sólo arma un zip que después alguien descomprime, y lo
que el shell lee es un DIRECTORIO. El layout no se inventó — se leyó del zip de EGO v72, que es la
salida de ese mismo `pack`, y el artefacto sellado se comparó contra él: **entradas idénticas, ni
sobras ni faltantes**, 45 .mo compilados.

⚠ INSTALADA ≠ ACTIVA, y esto es lo que hace que la receta sirva. El shell sólo carga lo que esté en
`org.gnome.shell enabled-extensions`: sin eso el artefacto sella, el fichero está en la imagen y NO
PASA NADA al arrancar — el mismo cuadro de «sellado ≠ instalado» que este repo ya se comió con
foot, mpv y libnotify, un escalón más abajo. Se resuelve con un override de GSettings, que cambia
el DEFAULT y deja ganar al dconf del usuario que no la quiera.
PROBADO DE VERDAD, no deducido: se compiló el directorio de esquemas del shell con el override
puesto (`glib-compile-schemas`, exit 0 y stderr vacío — que hay que mirar, porque sale 0 aunque
RECHACE un esquema) y después `gsettings get org.gnome.shell enabled-extensions` devolvió
['blur-my-shell@aunetx'].

⚠ TRAMPA ANOTADA PARA LA SEGUNDA: `enabled-extensions` es un ARRAY y el override lo escribe ENTERO.
Dos recetas con su propio override no se suman — gana la que compile última y la otra queda
instalada y muerta, sin error. Cuando llegue la segunda, la lista pasa a un solo sitio.

Y una corrección sobre la licencia, que casi firmo mal: el LICENSE es el texto del GPLv3, y su
apéndice «How to Apply» CONTIENE la frase «either version 3 … or any later version» siempre, así
que grepearla ahí no distingue -only de -or-later (la trampa que la memoria del repo ya tenía
escrita). La evidencia buena es el README del commit pineado: «This program is distributed under
the terms of the GNU General Public License, version 3 or later». El árbol JS no lleva cabecera de
licencia en ningún fichero.

Va de RAÍZ en escritorio-gnome por la lección de `foot` que targets.toml ya aprendió tres veces.
El perfil queda 183/183 listo con 25 raíces, deuda 0.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LCt3ettR4Z7b6wPCBmbvEV
2026-09-09 19:14:08 +00:00
Sergio 49e65d147c estado: cosecha granja 2026-09-09T19:01:53Z — avance del árbol KDE 2026-09-09 19:01:53 +00:00
Sergio ee8162fcf3 estado: cosecha granja 2026-09-09T14:03:18Z — avance del árbol KDE 2026-09-09 14:03:18 +00:00
SergioandClaude Opus 5 248fa8e991 desktop-file-utils: cerrar el «abrir con»
update-desktop-database construye la caché MIME→APLICACIÓN (mimeinfo.cache). Comprobado antes
de escribir la receta: NINGÚN artefacto del store lo traía, así que esa caché no se construía
nunca. Con shared-mime-info (cerrado ayer) el escritorio sabe QUÉ TIPO es un fichero; sin ésta
seguía sin saber CON QUÉ abrirlo — el menú «abrir con» vacío y sin aplicación por defecto.

Misma familia que aquel hueco: falla en RUNTIME, no en build. gnome-shell, libadwaita y mutter
lo piden en nixpkgs y acá construyen tan contentos sin él, así que ninguna métrica de deuda
puede verlo.

Prueba del consumidor con 14 .desktop REALES de okular/dolphin/kate/konsole/spectacle:
  mimeinfo.cache de 2.368 bytes · 47 asociaciones
  application/pdf=okularApplication_pdf.desktop
  text/plain=okularApplication_txt.desktop;org.kde.kate.desktop;org.kde.kwrite.desktop
Los 4 binarios estáticos con 0 NEEDED (--prefer-static desde el principio, no tras el error).
REPRODUCE bit a bit · tarball en el mirror.

Va como RAÍZ en los CUATRO escritorios y no en , y la razón importa: escritorio-kde y
escritorio-gnome comparten CERO raíces con base y bash NO está en su clausura. escritorio-mirada
documenta que no hereda «a propósito, es slim»; esos dos no dicen nada, y sway sí hereda cli.
Declararla en los cuatro funciona con cualquiera de las dos lecturas. La asimetría en sí queda
para decidir aparte: hoy «KDE 302/302» significa «la capa de escritorio está completa», no «la
imagen está completa».

Triaje: huecos 2 → 1 (queda ). Clausuras 303/182/160/205, todas selladas.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014QPJteswQvP1L7zSBrQQe2
2026-09-09 13:40:46 +00:00
SergioandClaude Opus 5 1da6851775 bash-completion: cerrar el hueco del tabulador
bash es RAÍZ del perfil base —el shell de la distro— y cinco recetas repartidas en cuatro colas
(appstream, colord, gnome-shell, modemmanager, swayimg) instalan completados en el directorio
que este paquete define. Sin él NO los instalan y siguen adelante: nada falla, nadie se entera,
y el usuario se queda sin tabulador en las herramientas del sistema. Hueco de RUNTIME puro, de
los que ninguna métrica de deuda puede ver — por eso hizo falta la frontera para encontrarlo.

Va al CORPUS y como raíz de , no a una cola: lo alcanzan las cuatro imágenes de escritorio
y la CLI, y una receta resuelve sibling-first y después el catálogo padre, nunca una cola
hermana. Y entra como RAÍZ porque nadie lo alcanza por deps de build: los consumidores sólo
preguntan por su .pc.

Verificado como consumidor, las dos mitades:
  pkgconf --variable=completionsdir bash-completion → /usr/share/bash-completion/completions
  el marco carga 131 completados y complete  devuelve regla · 522 ficheros instalados
  REPRODUCE bit a bit · tarball en el mirror

Triaje: los huecos vuelven a CERO. base pasa de 26 a 27 raíces, clausura 58/58 sellada.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014QPJteswQvP1L7zSBrQQe2
2026-09-09 02:48:20 +00:00
SergioandClaude Opus 5 3d8c6fc6c7 KDE: cerrar los 3 huecos que quedaban — polkit-qt-1, qqc2-breeze-style y xwayland
La frontera queda en CERO huecos y cero pendientes, y el perfil escritorio-kde en 302/302
sellados. Los tres eran huecos de RUNTIME: KDE sellaba 1037/1037 con la autorización muerta,
los controles QML en estilo genérico y ninguna app X11 capaz de arrancar.

polkit-qt-1 0.201.1 — al conectarlo se vio lo que ninguna métrica decía: kauth NO traía plugin
de backend, ni siquiera el directorio. Ahora trae kf6/kauth/backend/kauth_backend_plugin.so con
el símbolo KAuth::Polkit1Backend. Cascada de 26 dependientes reconstruida, 26/26 sin fallos.
Añadirlo cambió la rama del CMake y pidió kwindowsystem y tras él las X11 — cada cosa dicha por
el configure al fallar, no supuesta.

qqc2-breeze-style 6.7.2 (la del stack Plasma, NO la 6.7.4 de nixpkgs: mezclar versiones de un
mismo release es pedir desajuste de ABI en los plugins QML, que se ve en runtime y no al
construir). Enganchado a plasma-workspace como deps.runtime, no build: es un plugin que Qt carga
por la ruta de imports. Verificado que runtime no re-hashea ⇒ cero rebuilds.

xwayland 24.1.13 — resultó ser una CADENA de seis: libfontenc, libXfont2, libxkbfile,
libxshmfence, xkbcomp y el servidor. Ninguna existía. Tres tropiezos con su lección:

  · libxkbfile 1.2.0 ya no trae ./configure: es sólo meson. El resto de las libs X11 de la cola
    son autotools, así que copiar su plantilla era lo natural y estaba mal.
  · «checking for freetype2... no» culpaba a freetype, que estaba perfecta: freetype2.pc declara
    Requires: zlib, libpng y pkg-config resuelve transitivamente. El mensaje señala al paquete
    equivocado.
  · libXfont2 construye una .so y moría en «recompile with -fPIC» contra la libfreetype.a
    estática. Van las variantes -shared.

  Y xkbcomp es el eslabón que NINGÚN build habría delatado: xwayland lo lanza como subproceso en
  runtime (xkb/ddxLoad.c) y su meson lo pide con required:false, así que la receta compila igual
  y el servidor arranca sin teclado. Se encontró leyendo la fuente.

⚠ Sin GLX, y no por preferencia: glx/meson.build:43 pide dependency('gl') y ninguna cola publica
gl.pc — las tres recetas de mesa van con glx y glvnd apagados por decisión anterior. Las apps
X11 corren en 2D. ⚠ Y el meson.build RAÍZ engaña: ahí build_glx sólo enciende una tabla hash y
parece gratis; yo mismo di la preocupación por infundada mirando el fichero equivocado.

Verificado: Xwayland arranca y se identifica («The X.Org Foundation Xwayland Version 24.1.13»),
las 6 REPRODUCEN bit a bit, los 5 grafos con deuda 0, y los 6 tarballs en el mirror.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014QPJteswQvP1L7zSBrQQe2
2026-09-08 22:26:17 +00:00
Sergio a939ff0a3a estado: cosecha granja 2026-09-08T22:03:10Z — avance del árbol KDE 2026-09-08 22:03:10 +00:00
Sergio 13ee11826f estado: cosecha granja 2026-09-08T21:03:09Z — avance del árbol KDE 2026-09-08 21:03:09 +00:00
SergioandClaude Opus 5 71bdb5ec5b shared-mime-info: cerrar el primer hueco de la frontera
Salió de 'yupana frontera' en cuanto nix volvió a correr: kcoreaddons la pide y no había receta.
Es un hueco de RUNTIME, no de build — KDE sella 1037/1037 sin ella, y por eso NINGUNA métrica de
deuda la veía. Sin la base MIME el escritorio no resuelve asociaciones, iconos por tipo ni
'abrir con', y GIO cae a adivinar por extensión.

Va al CORPUS, no a incoming-kde: la necesitan las cuatro imágenes de escritorio, y una receta
resuelve sibling-first y después el catálogo padre, nunca una cola hermana.

Dos cosas que se comprobaron ANTES de construir, no después de que fallaran:

  · El tarball de GitLab no trae el submódulo 'xdgmime' — .gitmodules lo declara y el directorio
    llega vacío. Leyendo meson.build:26-47 se ve que sólo lo usa la suite de tests y con
    required:false, así que con build-tests=false lo único que pasa es un warning.
  · 'i18n.merge_file' corre SIEMPRE, no lo gobierna build-translations: no traduce UI, arma el
    fichero de datos desde el .in. De ahí el msgfmt, que gettext-tiny sí provee.

'--prefer-static' desde el principio, que es la lección de json-glib de hace un rato: el binario
sale ESTÁTICO con 0 NEEDED y corre en el host.

Y el artefacto trae la mime.cache ya compilada (update-mimedb=true, que upstream trae en false):
sin ella el paquete son datos crudos y alguien tendría que acordarse de correr
update-mime-database al armar cada imagen.

Verificado:
  prueba del consumidor  update-mime-database genera 157.560 bytes de cache y 26 media-types
  binario                estático, 0 NEEDED, corre fuera del sandbox
  repro                  REPRODUCE bit a bit (la caché se genera en el build: era candidata)
  mirror                 el tarball subido al Storage Box (ADR 0013)
  frontera               huecos 4 → 3

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014QPJteswQvP1L7zSBrQQe2
2026-09-08 20:15:06 +00:00
SergioandClaude Opus 5 ca2c164512 sombras: CERO — promover las 6 compartidas al corpus y barrer sus 16 copias
Las 6 que quedaban (fuse3, hwdata, icu4c, libdisplay-info, libelogind, lua) no tenían copia en
el corpus, así que borrar una habría roto su cola: la resolución es sibling-first y después el
catálogo PADRE, nunca una cola hermana. Se promueve una y se barren las 16.

Las 16 eran byte a byte IDÉNTICAS entre sí, con el mismo ArtifactHash — medido con 'hammer hash',
no deducido del nombre. Cada una la comparten entre 2 y 4 imágenes, que es exactamente el
criterio que dejó escrito xkeyboard-config al promoverse: lo que comparten varias imágenes tiene
que vivir en el corpus o no lo alcanzan.

A diferencia de aquella, acá las copias SÍ se barren en el mismo movimiento: sin copia en el
corpus no había dónde caer, y dejarlas sería mantener hasta 4 ficheros que son el mismo hash.

Verificado con la huella de las 1167 recetas antes y después:
  ficheros de receta   1167 → 1157   (16 borradas, 6 promovidas)
  hashes supervivientes  ninguno se movió ⇒ CERO rebuilds
  los cinco grafos       deuda 0, huérfanas [], sellados == recetas
  static-audit           MIENTEN 0 de 690
  duplicados             SOMBRAS REDUNDANTES: 0   ← de 14

⚠ Y una lectura que casi publico mal: mi primera comparación de hashes dijo 'CAMBIÓ ✗' en las
seis. Era el grep de la comparación, que no casaba y dejaba el valor 'antes' vacío — los hashes
nuevos eran idénticos a los medidos minutos antes. Un instrumento roto que grita es tan malo
como uno mudo.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014QPJteswQvP1L7zSBrQQe2
2026-09-08 19:47:55 +00:00
SergioandClaude Opus 5 a4a462b751 sombras: barrer 14 recetas redundantes que ya tenían copia en el corpus
Las 14 sombras marcadas 'redundante' dan el MISMO ArtifactHash en todas sus colas — no son
variantes, son el mismo artefacto declarado dos, tres, cuatro y hasta cinco veces. Medido con
'hammer hash' receta por receta, no deducido del nombre.

Se barren sólo las que YA tenían copia en el corpus, porque la resolución es sibling-first: una
dep desde incoming-kde busca incoming-kde/x y, si no está, CAE al corpus/x. Son 8 nombres, 14
ficheros: bzip2-shared, glib-shared, lcms2, mpc, pcre2-shared, sqlite-shared, xkeyboard-config
y xz-shared.

13 de los 14 eran byte a byte idénticos al del corpus. El decimocuarto, xkeyboard-config,
difiere en 14 líneas de COMENTARIO (mismo hash), y ese comentario es el permiso explícito para
esto: quien la promovió el 2026-09-05 escribió que dejaba las copias a propósito y que
'barrerlas es otra unidad de trabajo, no un efecto colateral de ésta'. Ésta es esa unidad.

Verificado con la huella de las 1181 recetas antes y después: NINGÚN hash superviviente se
movió ⇒ cero rebuilds. Y tras regenerar los cinco grafos: deuda 0, huérfanas [], y todas las
clausuras de perfil siguen completas.

⚠ Nota sobre una lectura que casi me confunde: los conteos de 'recipes' NO bajan (kde sigue en
1034) y eso es lo correcto — cuentan nodos alcanzables, no ficheros. Antes incoming-kde/x tapaba
a corpus/x; ahora el del corpus ocupa su lugar. Un nodo por otro.

Quedan 6 nombres (fuse3, hwdata, icu4c, libdisplay-info, libelogind, lua) sin copia en el
corpus: ésos exigen promover una primero, y van aparte.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014QPJteswQvP1L7zSBrQQe2
2026-09-08 19:44:28 +00:00
SergioandClaude Opus 5 7892d50842 json-glib: --prefer-static — declaraba static y sus binarios no corrían fuera del sandbox
'-Ddefault_library=static' gobierna cómo se construye la librería PROPIA, y eso funcionaba: el
artefacto trae libjson-glib-1.0.a. Pero no dice nada de con qué se enlazan los EJECUTABLES, así
que json-glib-format y json-glib-validate salían dinámicos contra libffi.so.8, libz.so.1 y
libc.so — y ese libc.so es la musl de zig, 255 bytes de linker script en el host. O sea binarios
que NO CORREN fuera del sandbox, en una receta que declara link=static. Mismo remedio que
appstream, que ya llevaba --prefer-static.

Medido antes y después:
  json-glib-format    dinámico, 3 NEEDED  →  ESTÁTICO, 0 NEEDED
  json-glib-validate  dinámico, 3 NEEDED  →  ESTÁTICO, 0 NEEDED
  libjson-glib-1.0.a  igual (los consumidores no cambian de forma)

Y la prueba del consumidor, que es la que vale: json-glib-format sobre un JSON real corre EN EL
HOST y devuelve {"a":1}. (El ruido de libgvfsdbus.so en stderr es glib intentando dlopen
módulos GIO desde un binario estático: inocuo, la salida sale bien.)

Cascada reconstruida en orden de onda, con el cierre transitivo sacado de yupana y no de un grep
—que no veía a zathura ni a zathura-pdf-poppler por tener el array de deps multilínea, y la regla
del repo es justamente ésa—: zathura, incoming-cosmic/xdg-desktop-portal, zathura-pdf-poppler.

Verificado después, no antes:
  static-audit   MIENTEN 0 de 690    toda receta que declara link=static lo cumple
  los 5 grafos   deuda 0
  repro          REPRODUCEN 3 · DERIVA 0 · NO-DETERMINISMO 0

⚠ incoming-gnome/json-glib NO se toca: declara link="dynamic" a propósito porque el shell de
GNOME dlopea .so reales para introspección. No miente — es honesta, y su radio de 10 no se paga.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014QPJteswQvP1L7zSBrQQe2
2026-09-08 19:26:12 +00:00
Sergio 2e496d62e0 estado: tras aparcar el jarlog — corpus al día 2026-09-08 14:11:55 +00:00
Sergio 17508043aa estado: waterfox renombrado, corpus al día 2026-09-08 14:05:18 +00:00
Sergio 64c9e7196e estado: cosecha granja 2026-09-08T13:32:16Z — avance del árbol KDE 2026-09-08 13:32:16 +00:00
Sergio 21bec8d02e estado: cosecha granja 2026-09-08T03:32:12Z — avance del árbol KDE 2026-09-08 03:32:12 +00:00
Sergio 91a229a7c4 estado: cosecha granja 2026-09-08T02:32:04Z — avance del árbol KDE 2026-09-08 02:32:04 +00:00
Sergio 1dbaf8d85a estado: atuq sobre el firefox con PGO v2 — 860/862 y cero huecos
atuq b3:fab2fbfb, 340 M, libxul de 227.043.776 bytes: el mismo del motor con el
perfil de 46 páginas. Verificado que ARRANCA desde una hidratación limpia de
escritorio-sway, 0 errores de relocación.

El corpus queda en 860/862 sellados —los dos que faltan son `ajeno`, que es
frontera y no deuda— y el vigía de sonames en CERO huecos en los cinco perfiles.
2026-09-07 22:08:38 +00:00
Sergio 54a27b966b estado: cosecha granja 2026-09-07T22:02:23Z — avance del árbol KDE 2026-09-07 22:02:23 +00:00
Sergio 94d7e8626f estado: cosecha granja 2026-09-07T21:02:16Z — avance del árbol KDE 2026-09-07 21:02:16 +00:00
Sergio 7d9fc96acb estado: cosecha granja 2026-09-07T18:02:07Z — avance del árbol KDE 2026-09-07 18:02:07 +00:00
Sergio 7e65d35e57 estado: cosecha granja 2026-09-07T15:32:05Z — avance del árbol KDE 2026-09-07 15:32:05 +00:00
Sergio a9cfaef681 estado: 860/862 sellados, cero deuda y cero huecos de soname
El corpus queda entero tras la jornada: los dos únicos no sellados son `ajeno`
(steam-runtime-sniper, xwayland), que son frontera y no deuda.

atuq reconstruido sobre el firefox con PGO (b3:0acf6f58): 340 M, libxul de
227.802.816 bytes — el mismo del motor. La tesis del derivado sostenida: el
navegador propio se rehace en segundos sobre un motor nuevo.

Verificado que arranca desde una hidratación limpia de escritorio-sway, 0
errores de relocación. Y verificado que el PGO viaja EN EL ARTEFACTO y no sólo
en el configure: buildconfig.html dentro del omni.ja de atuq contiene
`profile-use`, junto a `wasi-sysroot` y `lto=cross`.

Nota de método: la CAPTURA no servía para esto. Salió byte a byte idéntica a la
de ayer porque la sección «Configure options» cae bajo el viewport — o sea que
una imagen igual no probaba que nada hubiera cambiado. El artefacto sí.
2026-09-07 15:12:22 +00:00
Sergio d55bc6514e estado: cosecha granja 2026-09-07T10:31:56Z — avance del árbol KDE 2026-09-07 10:31:56 +00:00
Sergio cbcc6c2c40 estado: cosecha granja 2026-09-07T01:31:55Z — avance del árbol KDE 2026-09-07 01:31:55 +00:00