Commit Graph
1920 Commits
Author SHA1 Message Date
Sergio 3f84cd761b estado: cosecha granja 2026-09-04T17:02:11Z — avance del árbol KDE 2026-09-04 17:02:11 +00:00
Sergio f3767f6361 corpus: pciutils-shared y mbedtls — dos deps duras de OBS
pciutils-shared: obs-ffmpeg (el plugin de codificación, sin perilla para
apagarlo) hace find_package(Libpci) para identificar la GPU por su ID. La
pciutils canónica va SHARED=no e instala SÓLO bin/sbin/share — provee.py
confirmaba que libpci.so no lo publicaba NINGUNA cola. Patrón zlib-shared: una
variante, sin mover el hash de la canónica.
Verificado que NO colisionan listando los dos artefactos: la variante sólo pone
usr/lib y usr/include; la canónica no pone nada en usr/lib. Rutas disjuntas
conviven; rutas pisadas son el cuadro de las dos glib. Por eso el install usa el
target `install-lib` y no `install`, que traería los binarios.

mbedtls: obs-outputs (streaming RTMP) hace find_package(MbedTLS REQUIRED) y NO
acepta OpenSSL — no hay opción en su CMake, está cableado.
Va por TARBALL DE RELEASE y no por commit, que es excepción consciente al ADR
0006: mbedtls 3.6 tiene framework/ como submódulo y [source] de hammer no clona
submódulos, así que el árbol llegaría incompleto. Un fichero de
/releases/download/ lo sube upstream y su sha256 es estable; lo inestable es
/archive/<tag>, que la forja genera al vuelo. La propiedad que el ADR exige —que
la fuente sea la misma mañana— se cumple igual.
PIC ON porque quien la consume es obs-outputs.so, un módulo dlopen.
2026-09-04 16:49:57 +00:00
Sergio 99eb0071f6 corpus: simde 0.8.2 — libobs la exige REQUIRED
libobs/CMakeLists.txt:10 hace find_package(SIMDe REQUIRED) y linkea SIMDe::SIMDe,
así que no es opcional para OBS. Sólo cabeceras, pero se instala por meson y no
copiando a mano porque genera simde.pc, que es por donde el FindSIMDe de OBS lo
encuentra: dejar las cabeceras sin su fichero de descubrimiento da el «está pero
no lo encuentra», peor de diagnosticar que una ausencia.
2026-09-04 16:33:22 +00:00
Sergio 684c1b0a24 estado: cosecha granja 2026-09-04T16:31:58Z — avance del árbol KDE 2026-09-04 16:31:58 +00:00
Sergio c2feb3eab6 corpus: uthash, nlohmann-json, jansson y x264 — las 4 deps que a OBS le faltaban
Las cuatro no existían en NINGUNA cola (medido cruzando el grafo, no con grep).
Van al corpus y no a una cola porque OBS es una app que quieren las cuatro
imágenes, y una receta resuelve sibling-first y después el catálogo PADRE, nunca
una cola hermana.

Verificadas por CONTENIDO del artefacto, no por exit 0 (regla 3 del repo):
 · uthash          5 cabeceras; no compila nada y la fase `compile` dice `true`
                   explícito, porque que una librería sea sólo cabeceras es un
                   hecho suyo, no un descuido de la receta.
 · nlohmann-json   pasa por CMake y no por un `cp` para que instale sus
                   nlohmann_jsonConfig/Targets.cmake: OBS hace find_package, y
                   copiar los .hpp a mano dejaría «está pero no lo encuentra».
 · jansson         libjansson.so.4.
 · x264            libx264.so.165 + x264.pc, y `asm: yes` — con SIMD, que es la
                   lección que ffmpeg acaba de costar hoy.

⚠ jansson trajo su propia trampa: la perilla es JANSSON_BUILD_SHARED_LIBS, NO la
estándar BUILD_SHARED_LIBS de CMake (CMakeLists.txt:5, default OFF). Con la
estándar el build sale exit 0 y sella un artefacto con SÓLO libjansson.a — la
receta diciendo link="dynamic" y el artefacto estático. Se vio mirando usr/lib/
del artefacto, no el código de salida.
2026-09-04 16:27:24 +00:00
Sergio 323a675ed0 estado: cosecha granja 2026-09-04T16:01:58Z — avance del árbol KDE 2026-09-04 16:01:58 +00:00
Sergio 666a681812 libglvnd 1.7.0: el GL de escritorio que a la distro le faltaba
Hasta hoy NINGUNA cola publicaba libGL.so, libGL.so.1 ni gl.pc (medido con
provee.py): mesa va -Dglx=disabled -Dglvnd=false, así que sólo había libEGL y
libGLESv2. Toda app de GL fijo compilaba —mesa SÍ instala GL/gl.h— y moría al
LIGAR. Lo destapó OBS: deps/glad linkea PUBLIC OpenGL::GL, que ES libGL.so, y eso
es un link, no un gate de configure que se pueda apagar.

SIN GLX Y SIN X11, que es lo que hace esto coherente con la distro: glvnd parte el
libGL.so.1 histórico en libGL.so.1 (GL+GLX ⇒ implica X11) y libOpenGL.so.0 (GL
pelado ⇒ no implica nada). Vamos por la segunda. Encender glx metería
libX11/libxcb/xorgproto —hoy sólo en incoming-kde— en el CORPUS, o sea en las
cinco imágenes, para servir a una sola app.

Entrega verificada en el artefacto: libOpenGL.so.0, libGLdispatch.so.0,
libEGL.so.1, libGLESv{1_CM,2}, y opengl.pc. Cero GLX.

El wrapper: meson emite `-Wl,--version-script <ruta>` con ESPACIO. Con gcc anda de
casualidad (reenvía al linker el argumento suelto que no entiende); zig-cc lo
rechaza con «unrecognized file extension». El wrapper une el par con `=`. No se
parchea upstream: el defecto es del contrato meson↔driver, no de glvnd.

⚠ Instala libEGL.so.1, que HOY la pone mesa. Mismo soname, otro dueño ⇒ mesa se
reconstruye con -Dglvnd=true en esta misma campaña, no después.
2026-09-04 15:35:32 +00:00
Sergio 8ddafc15e6 estado: cosecha granja 2026-09-04T15:32:15Z — avance del árbol KDE 2026-09-04 15:32:15 +00:00
Sergio 8d48f1869f vaapi: mpv cierra su último hueco — decodificación por hardware
libva sube al corpus y la copia de incoming-kde se JUBILA (git mv, no copia: dos
ficheros para un artefacto es el cuadro de las dos glib esperando a derivar). La
mudanza fue gratis y medida antes: las cinco deps de libva viven sólo en el
corpus, así que incoming-kde ya las resolvía por caída al padre y hammer hash dio
el MISMO ArtifactHash en las dos rutas (b3:405c6211).

libva pasa a -Dwith_wayland=yes, que eso SÍ cambia el hash. La razón está en
mpv/meson.build:1464: el feature `vaapi` se requiere contra
`vaapi-drm or vaapi-wayland or vaapi-x11 or vaapi-win32` ⇒ -Dvaapi=enabled a
secas no habilita NADA. De los cuatro backends, x11/win32 están fuera por
Wayland-only y vaapi-drm exige features[drm] de mpv, apagado porque vo=drm pide
libdisplay-info. Queda vaapi-wayland, que pide libva-wayland.pc.

Evidencia, no sólo sello: meson lista «vaapi vaapi-wayland» entre los features
habilitados, y el binario sellado trae NEEDED libva.so.2 + libva-wayland.so.2.

Radio medido antes de tocar: 2 dependientes (kpipewire, spectacle), los dos
reconstruidos. Las 7 imágenes siguen en 0 en deuda.

⚠ El driver es RUNTIME (intel-media-driver / gallium VA por dlopen): que esto
selle y que --hwdec=vaapi funcione en una máquina son cosas distintas.
2026-09-04 15:06:14 +00:00
Sergio 269e8410fd estado: cosecha granja 2026-09-04T15:02:12Z — avance del árbol KDE 2026-09-04 15:02:12 +00:00
Sergio 814676ad26 ffmpeg: x86asm encendida — mpv decodificaba sin SIMD por una prohibición vencida
La receta llevaba --disable-x86asm heredado de cuando ffmpeg entró SÓLO para
kpipewire (codificar un stream de escritorio, donde da igual). Para el
reproductor era decodificar sin SIMD.

Dos recetas —ffmpeg.toml y mpv.toml— prohibían tocarlo con la misma razón: un
hash distinto dejaría DOS ffmpeg peleando por las mismas rutas en una imagen KDE,
y el arreglo correcto sería «promover una sola y jubilar la de la cola». Eso ya
había pasado: incoming-kde/ffmpeg.toml no existe y hay UNA sola receta ffmpeg en
todo el disco. La prohibición sobrevivió a la condición que la justificaba.

--x86asmexe=nasm explícito y nasm (2.16.03) a [deps].build: sin ensamblador
declarado configure apagaría x86asm en SILENCIO, sellando un artefacto con otro
hash y sin la SIMD que dice traer.

Evidencia, no sólo sello: configure imprime «x86 assembler nasm», compila los
objetos X86ASM, y libavcodec.so pasa de 12.685.744 a 14.454.288 bytes (+1,77 MB).

Radio medido antes de tocar (yupana radio ffmpeg): 4 dependientes, ninguno
transitivo de más — mpv, wf-recorder, kpipewire, spectacle. Los 4 reconstruidos y
sellados; las 7 imágenes siguen en 0 en deuda.
2026-09-04 14:37:52 +00:00
Sergio 99a3ad5a30 estado: cosecha granja 2026-09-04T14:33:11Z — avance del árbol KDE 2026-09-04 14:33:11 +00:00
Sergio 9834f57052 yupana: --help imprimía literalmente None
Todo el encabezado del fichero era comentario `#`, así que __doc__ era None y
`main()` hace `print(__doc__)` en dos caminos: `--help` y verbo desconocido. La
puerta única de la metodología no sabía explicarse, y el error de verbo tampoco
decía cuáles son los verbos válidos.

La ayuda operativa pasa a docstring; el diseño y el porqué se quedan arriba como
comentario. Cotejada contra el despacho real: los 11 verbos de la ayuda existen y
los 11 que existen están en la ayuda (faltaba `sembrar`).
2026-09-04 14:27:34 +00:00
Sergio 28d98dc5f9 drenaje: medía 5 de 7 imágenes y las otras 2 desaparecían en silencio
targets.toml declara 7 perfiles; drenaje.json listaba 5. escritorio-cosmic (cola
incoming-cosmic) y escritorio-sway (cola incoming-wlr) declaraban una cola que
ningún grafo de GRAFOS contenía, así que cargar() devolvía None y --todos hacía
`continue` pelado. Dos imágenes enteras fuera del artefacto sin dejar rastro, y
los dos números —5 medidos, 7 declarados— no se cruzaban en ningún lado.

Mismo olvido que ya costó 17 días de build-state-wlr.json congelado: la lista de
grafos crece a mano y se queda atrás cuando se abre una cola.

Tres cambios:
- GRAFOS suma los grafos de cosmic y wlr.
- Un perfil sin medir se anota en el artefacto (`sin_medir`), se grita por stdout
  y drenar.py sale 1. Regla 3 del repo: un ausente falla ruidosamente.
- cosecha-cron deja de tragarse la salida; filtra las líneas ⚠ al log, que si no
  llegaban como un "falló" mudo que no dice cuál imagen falta.

Medido: las 2 imágenes que nadie miraba estaban limpias, 0 en deuda. Ahora son
7/7 verificadas en vez de 5 verificadas y 2 supuestas.
2026-09-04 14:26:04 +00:00
Sergio e8ca740119 estado: cosecha granja 2026-09-04T14:02:09Z — avance del árbol KDE 2026-09-04 14:02:09 +00:00
Sergio 2db76cfb32 estado: cosecha granja 2026-09-04T13:32:00Z — avance del árbol KDE 2026-09-04 13:32:00 +00:00
Sergio c52b2737bd estado: KDE cierra 1001/1001 — saldadas las 8 que mató el disco lleno
dolphin filelight kate kinfocenter konsole kscreen plasma-integration
plasma-desktop. Ninguna era fallo de receta: las 8 murieron el 2026-09-03 con
«No space left on device» y el bucle las anotó ✗ igual que a una que no compila.
Reintentadas tal cual, sin tocar una sola receta, sellaron las 8 a la primera.

escritorio-kde pasa a 263/263 y drenaje.json queda en 0 en deuda en los cinco
perfiles: base, cli, escritorio-{gnome,kde,mirada}.
2026-09-04 13:21:12 +00:00
Sergio 97023c3306 granja: PODA_FUENTES nace encendida y respeta el árbol de la receta que falló
Causa raíz de la deuda KDE de hoy: la cascada del 2026-09-03 corrió campana-deuda
SIN PODA_FUENTES=1 (cero menciones en su log). Los 71 árboles de fuentes se
acumularon en /dev/sdc a ~300 MB cada uno y lo llenaron en la receta 52; las 8
últimas murieron por disco, no por receta. Un default que hay que acordarse de
encender no es una defensa.

No poda tras un ✗: el árbol de la receta fallida es el post-mortem, y es justo el
caso en que alguien va a mirarlo. Mismo criterio que el suelo de 24 h de
poda-fuentes.sh, aplicado por resultado en vez de por edad.

Probado: sobrevive tras ✗, poda tras ✓, y PODA_FUENTES=0 sigue apagándola.
2026-09-04 13:11:47 +00:00
Sergio 3f26d37d17 granja: guardián de disco en campana-deuda — corta en vez de anotar ✗ falsos
La cascada KDE del 2026-09-03 llenó el disco en la receta 52 de 71 y siguió
moliendo: las 8 últimas murieron en 1-20 s con «No space left on device» y el
bucle las anotó ✗, el mismo símbolo que una receta que no compila. El grafo del
día siguiente decía «8 en deuda, clase c» y mandó a buscar un bug inexistente.

Mide el MÍNIMO de dos filesystems, no uno: en gioser store/ (/dev/sdb, 109 G) y
work/ (/dev/sdc, 53 G) son discos distintos y el que se llenó fue el de work/,
donde vive el árbol de fuentes. Mirando sólo el store el vigía habría leído
109 G y dejado moler igual.

Al cruzar el suelo corta con exit 3 y lista las recetas SIN INTENTAR, que no es
lo mismo que fallidas.
2026-09-04 13:09:17 +00:00
Sergio 6f145abe58 estado: cosecha granja 2026-09-04T13:01:50Z — avance del árbol KDE 2026-09-04 13:01:50 +00:00
Sergio cb7462249c estado: cosecha granja 2026-09-04T12:32:07Z — avance del árbol KDE 2026-09-04 12:32:07 +00:00
Sergio 728cbec07d estado: cosecha granja 2026-09-04T12:01:54Z — avance del árbol KDE 2026-09-04 12:01:54 +00:00
Sergio 3be39111c6 estado: cosecha granja 2026-09-04T11:31:54Z — avance del árbol KDE 2026-09-04 11:31:54 +00:00
Sergio bbbaf7141a estado: cosecha granja 2026-09-04T11:01:57Z — avance del árbol KDE 2026-09-04 11:01:57 +00:00
Sergio f41569beb1 estado: cosecha granja 2026-09-04T10:31:53Z — avance del árbol KDE 2026-09-04 10:31:53 +00:00
Sergio dbaf8d9a43 estado: cosecha granja 2026-09-04T10:01:53Z — avance del árbol KDE 2026-09-04 10:01:53 +00:00
Sergio a36124f38d estado: cosecha granja 2026-09-04T07:31:54Z — avance del árbol KDE 2026-09-04 07:31:54 +00:00
Sergio b2b261dd98 estado: cosecha granja 2026-09-04T07:01:52Z — avance del árbol KDE 2026-09-04 07:01:52 +00:00
Sergio 7db1522c14 estado: cosecha granja 2026-09-04T06:01:53Z — avance del árbol KDE 2026-09-04 06:01:53 +00:00
Sergio d67a7fa038 estado: cosecha granja 2026-09-04T05:01:49Z — avance del árbol KDE 2026-09-04 05:01:49 +00:00
Sergio 99f7f46c47 estado: cosecha granja 2026-09-04T04:31:42Z — avance del árbol KDE 2026-09-04 04:31:42 +00:00
Sergio 7e58b42987 estado: cosecha granja 2026-09-04T04:02:22Z — avance del árbol KDE 2026-09-04 04:02:23 +00:00
Sergio 9f513ade73 estado: cosecha granja 2026-09-04T03:31:59Z — avance del árbol KDE 2026-09-04 03:31:59 +00:00
Sergio 9c1910ffbd estado: cosecha granja 2026-09-04T03:02:26Z — avance del árbol KDE 2026-09-04 03:02:26 +00:00
SergioandClaude Opus 5 1645e251bc cosmic anidado: el panel dibuja en una ventana — y el cierre del perfil NO puede hacer GL
Hermano de `sway-nested.sh` para el cuarto escritorio. Levanta cosmic-comp nesteado y sus clientes;
sale con el panel entero: app-library, app-list, siete applets, pop-launcher, cosmic-toplevel y los
dos procesos del portal.

**El hallazgo, que es de la IMAGEN y no del arnés**: `/usr/lib/dri` del rootfs hidratado trae
`iris_dri.so` y NADA MÁS — el driver de Intel real. Sin `swrast_dri.so`, EGL no inicializa y
cosmic-comp muere con `Egl(InitFailed(NotInitialized))` detrás de dos `MESA-LOADER: failed to open
{zink,swrast}`. O sea que el cierre 133/133 de `escritorio-cosmic` **no puede componer en ninguna
máquina que no sea Intel** — ni en una VM, ni nesteado.

No es nuevo, es un hueco de DECLARACIÓN: `scripts/gnome/qemu-desktop-image.sh` ya lo dice en su
cabecera y copia `mesa-llvmpipe` encima con `--remove-destination`. Cada script de imagen inyecta a
mano algo que `targets.toml` no declara — justo la divergencia que `hydrate-profile.py` hace
visible. Y no se arregla declarándolo: `mesa` y `mesa-llvmpipe` instalan los MISMOS `.so`
(libEGL/libgbm/libGLESv2), así que las dos en un perfil colisionan fichero a fichero — la figura de
las dos poppler. Los scripts lo resuelven PISANDO, que es decisión de imagen y no arista de grafo.
Acá se hace lo mismo y se dice: `mesa-llvmpipe` entra como TERCER overlay, el último, o sea el de
mayor prioridad. El artefacto se elige por `hammer hash`, no por el más reciente del store.

Y `cosmic-session` no sirve para nestear: no le pasa `WAYLAND_DISPLAY` a cosmic-comp —para ella el
compositor ES el display server— y su stderr lo captura `launch_pad`, que sólo repite «cosmic-comp
exited with error code 1» y lo reinicia en bucle, así que la causa no aparece en ningún log. Por eso
el modo por defecto es `bare`: compositor a mano y clientes apuntados a SU socket.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CGyBj4QyeCZiwLMkP9GJp6
2026-09-04 02:35:24 +00:00
Sergio 094b056cad estado: cosecha granja 2026-09-04T02:32:07Z — avance del árbol KDE 2026-09-04 02:32:07 +00:00
SergioandClaude Opus 5 02e93a02ea raíz sucia: 945 ficheros de perl en /, con guardián que nombra al culpable y el número que difiere el arreglo
Hidratando el rootfs de sway aparecieron 945 ficheros sueltos en la raíz — `AnyDBM_File.0`,
`App::Cpan.0`, … Son las páginas nroff de perl: su `Configure -des` no encuentra nroff, elige
`man1ext='0'` y `man1dir=' '` (la convención de perl para «no instales man»), pero `installman` las
GENERA igual y con el directorio vacío `make install DESTDIR=/out` las deja en `/out/`.

Ninguna métrica sobre recetas puede ver esto: hay que hidratar un rootfs de verdad y mirarlo.

El guardián va en `hydrate-profile.py` y mira **por artefacto**, no sobre el árbol fundido: en el
árbol fundido el nombre del culpable ya se perdió y 945 ficheros en `/` no se parecen en nada a
«una fase install con el destino vacío», que es lo que son. Barrido el store entero: **perl es el
único** — `.times`/`.dmerge` son internos del store y `product-rootfs`/`seed-zig` son especiales.

El arreglo es UNA línea (`-Dman1dir=… -Dman3dir=… -Dman1ext=1 -Dman3ext=3`) y NO se aplica hoy:

    yupana radio perl → transitivos 347 · sellados que CAEN a deuda 305 · TODAS las imágenes

305 rebuilds para mover páginas de man de sitio no se paga solo. Queda escrito en la receta para ir
con el próximo bump de perl, cuando el re-hash ya esté pagado. Comprobado que el comentario NO entra
en `hash_inputs`: el ArtifactHash es idéntico antes y después (b3:1af26f6b).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CGyBj4QyeCZiwLMkP9GJp6
2026-09-04 02:27:22 +00:00
Sergio 937169da28 estado: cosecha granja 2026-09-04T02:02:16Z — avance del árbol KDE 2026-09-04 02:02:16 +00:00
SergioandClaude Opus 5 b08212a7f1 waypipe: el escritorio en una ventana — ciclo de segundos, y el hueco de la libc queda medido
Dos piezas para mirar la distro sin QEMU, que es lo que hacía falta para cazar el puntero
invisible: ese defecto no lo ve ninguna métrica de clausura Y TAMPOCO una captura headless — el
cursor no está en el framebuffer que devuelve screencopy. Hay que mirar la ventana.

`hydrate-profile.py <perfil>`: proyecta el cierre ENTERO de un perfil de `targets.toml`. Los
`hydrate-*.sh` por escritorio traen la lista de raíces escrita a mano dentro del script, o sea DOS
fuentes de verdad: hoy mismo se añadió `adwaita-cursors` a cosmic y sway y esos scripts —que no la
conocen— habrían seguido armando un rootfs sin cursores mientras el perfil decía que los lleva.
Acá el cierre sale de `yupana.membresia()`, la misma función que usan build-state y vigia-imagen.

Y trae la sonda que costó dos intentos: `hydrate` ENLAZA, y `linkat()` no cruza un punto de
MONTAJE aunque sea el mismo disco. El store y `work/out` son dos binds del mismo /dev/sdb ⇒
`st_dev` COINCIDE y el hardlink falla igual. La primera versión comparaba `st_dev` y no disparó:
salieron 174 «artefactos que no proyectaron» y un rootfs de 272 ficheros con pinta de problema de
recetas. Ahora la sonda es FUNCIONAL —se intenta un enlace de verdad— y el error nombra el montaje
del store.

`sway-nested.sh`: arranca `escritorio-sway` como ventana del compositor que ya tenés delante.
Evidencia de esta corrida, con el rootfs hidratado del perfil:

    [wlr] [xcursor] Loaded cursor theme 'default' at size 24 (62 available cursors)

o sea el tema llamado literalmente `default` —el alias que fabrica `adwaita-cursors`— resolviendo
a los 62 cursores de Adwaita. Antes de hoy esa línea no existía.

Tres cosas que sólo salen corriéndolo:
· **Ningún perfil incluye `musl`.** Ni `base`. El cierre de escritorio-sway no trae UN `ld-musl` y
  sway es `link=dynamic` con intérprete `/lib/ld-musl-x86_64.so.1`: la libc sale del bootstrap, no
  de una receta del perfil. Por eso el arnés monta DOS overlays. No es un bug, pero no estaba
  escrito en ningún lado y un rootfs de perfil solo no arranca.
· **`yambar` no va en `bar { status_command … }`**: es una barra completa de layer-shell, no un
  productor de estado para swaybar. Puesta ahí, sway rechaza la config ENTERA y arranca pelado —
  se lee como «el escritorio está roto» cuando lo único mal es una línea.
· **`grim` hay que apuntarlo al socket de NUESTRO sway.** Adentro `WAYLAND_DISPLAY` es el del HOST
  (es lo que sway necesita para nestear), así que un `grim` a secas devuelve una captura perfecta…
  del escritorio de al lado. La primera captura fue exactamente eso.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CGyBj4QyeCZiwLMkP9GJp6
2026-09-04 01:56:45 +00:00
SergioandClaude Opus 5 8c4e1a6b24 cursores: cosmic y sway corrían con el puntero INVISIBLE — receta propia, y el vigía medía mal
`vigia-imagen.py` daba ✗ en cursores en DOS de los cuatro escritorios. No es cosmético: con el
cursor por software —obligatorio en virtio-gpu y en todo render por CPU— el compositor dibuja la
imagen que le da el TEMA, y sin tema el ratón se mueve invisible. cosmic llegó a 43/43 y sway a
173/173 así, porque un tema de cursor no es dep de build de nadie: sólo entra si se DECLARA.

`adwaita-cursors` (corpus, 48.1, data-only): del mismo tarball que `adwaita-icon-theme` pero SÓLO
`Adwaita/cursors/` — 39 ficheros y 14 MB, sin un icono. Promover el tema entero habría regalado a
sway y a cosmic los iconos de GNOME, que está anotado como decisión pendiente y no como olvido.

Las dos cosas que el tarball no trae y la receta fabrica:
· los nombres X11 heredados (`left_ptr`, `xterm`, `watch`, `hand2`…) son enlaces que genera el
  `meson.build` de upstream. El mapa se PARSEA de ahí, no se copia: copiado envejece en silencio.
  Si el origen de un enlace no existe, la fase falla — upstream pone un `files()` como aserción.
· `/usr/share/icons/default/index.theme` con `Inherits=Adwaita`. Sin `XCURSOR_THEME` en el
  entorno, libXcursor y wlroots buscan el tema llamado literalmente `default`; sin él no hay
  puntero AUNQUE Adwaita esté instalado. Es el eslabón que hace que ande sin configuración.

⚠ no declarar esta receta junto a `adwaita-icon-theme`: chocan en `Adwaita/cursors/*`.

Y el vigía estaba midiendo el invariante de al lado: exigía `index.theme` en el directorio para
contar un tema, que es correcto para ICONOS —la búsqueda XDG recorre `Directories=`— y falso para
CURSORES, porque libXcursor abre `<tema>/cursors/<nombre>` directo y el índice sólo hace falta para
seguir un `Inherits=`. Con la receta instalada seguía diciendo «NINGÚN tema de cursor».

De paso queda anotado en `targets.toml` que el comentario de cosmic decía «sin ellos arranca sin
puntero» sobre `cosmic-icons`, que no trae cursores: describía una protección que no existía.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CGyBj4QyeCZiwLMkP9GJp6
2026-09-04 01:38:30 +00:00
Sergio a62ec9061d estado: cosecha granja 2026-09-04T01:33:16Z — avance del árbol KDE 2026-09-04 01:33:16 +00:00
Sergio 19a7bfb9e4 estado: cosecha granja 2026-09-04T01:02:07Z — avance del árbol KDE 2026-09-04 01:02:07 +00:00
Sergio 5fb557b274 estado: cosecha granja 2026-09-04T00:33:39Z — avance del árbol KDE 2026-09-04 00:33:39 +00:00
SergioandClaude Opus 5 fdce080d96 qorpa D8: sniper sellado al store, con la marca que evita que la cifra mienta
D8 decía que sniper «entra al store por `file_drop`». Dos correcciones, y la
primera es de vocabulario: **`file_drop` en hammer es otra cosa** — una
operación de `hammer apply` que coloca un fichero en el sistema instalado
verificando su hash. No tenía nada que ver con sellar. Lo que sella es lo de
siempre, una receta. Queda escrito en el ADR: un término inventado que suena a
mecanismo existente manda a buscar el código donde no está.

`recipes/steam-runtime-sniper.toml` sella el árbol del runtime (11196 ficheros)
pineado por el sha256 que ya estaba verificado. Entra donde Arch y Ubuntu no
pueden por una propiedad, no por simpatía: **no muta** —nadie le instala nada
adentro— así que el mismo tarball da siempre el mismo árbol y sellarlo es una
afirmación verdadera.

**La marca: `foreign = true`.** No cambia el build en un byte y **no entra en
`hash_inputs`** (describe procedencia, no identidad — hay test). Lo que cambia
es contable: `build-state.py` la clasifica `ajeno`, la resta del denominador de
las imágenes y la deja fuera del recuento de recetas. Sin eso, sellar un
prebuilt habría subido la cifra que todo el mundo lee como «cuánto
construimos» — el riesgo que el ADR escribió antes de que existiera la primera
instancia. Verificado: sigue diciendo 821 recetas, y aparte
`de las ajenas, 1 selladas al store (prebuilt pineado, sin procedencia de fuente)`.

Y la diferencia con el otro ajeno: `xwayland` no se hashea (no hay receta, y un
hash afirmaría que lo reproducimos); el sellado **sí conserva su hash**, porque
está en el store y que un artefacto exista mientras el grafo lo niega sería otra
forma de mentir. Comparten el estado, que es lo que protege la cifra.

**`hammer qorpa import --from-store <hash>`** lo consume, y ahí está el detalle
que hace que valga: la imagen se registra bajo el **sha256 del archivo de
upstream**, no bajo el ArtifactHash. Al revés, la imagen del store y la traída
con `pull` serían dos imágenes distintas con los mismos bytes y las instancias
de dos máquinas dejarían de coincidir — justo lo que el pin existe para evitar.
El árbol se **enlaza**: una imagen nunca se escribe (lo que escribe la instancia
va a su `upper`), así que compartir inodos con un artefacto sellado y de sólo
lectura es correcto por construcción y la imagen cuesta ~0 bytes. La contracara
conocida de `.dmerge`: mientras el artefacto siga en el store, borrar la imagen
no libera disco; `--copy` lo evita.

Licencia `LicenseRef-qorpa-ajena-no-enumerable` a propósito: adentro hay cientos
de paquetes Debian y no podemos enumerarlos; vacío se leería como «todavía no la
poblamos». SDD 20 lo recoge y afila la distinción: replicarla a nuestras
máquinas es lo que ya hace ADR 0013 con las fuentes; publicarla a terceros sigue
pidiendo licencia y marca.

29 tests verdes. El sellado en sí corre aparte, esperando el lock de la granja.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QZjGRqvjWij9dew7NVFu4Q
2026-09-04 00:09:20 +00:00
Sergio 3329317737 estado: cosecha granja 2026-09-04T00:02:50Z — avance del árbol KDE 2026-09-04 00:02:50 +00:00
Sergio 8ca4fb035f estado: cosecha granja 2026-09-03T23:32:30Z — avance del árbol KDE 2026-09-03 23:32:30 +00:00
Sergio fc07286dbb estado: cosecha granja 2026-09-03T23:02:29Z — avance del árbol KDE 2026-09-03 23:02:29 +00:00
Sergio 6bfc201a50 estado: cosecha granja 2026-09-03T22:32:41Z — avance del árbol KDE 2026-09-03 22:32:41 +00:00
SergioandClaude Opus 5 7448e106b8 campana-deuda: PODA_FUENTES=1 — la campaña se poda sola, dentro del bucle
Las 71 recetas KDE de la cascada de kcoreaddons se muelen en ESTA máquina (sin worker de pago) y
`work/sources` vive en `/mnt/vvv`, que arrancó la campaña con 16 G libres. A ~300 MB de árbol por
receta, sin podar la campaña se come el disco antes de la onda 4 — y con el disco lleno git falla a
mitad y deja el índice a medias, que ya pasó.

La poda va DENTRO del bucle y no en un cron paralelo, que es el punto: ahí tenemos el lock Y
acabamos de terminar un build, así que no hay ningún bwrap usando un árbol. Correr
`poda-fuentes.sh` en paralelo sería el ADR 0012 en su forma más directa — su propio encabezado
avisa de que el mtime NO distingue «viejo» de «lento».

No cuesta nada: `fetch.rs` borra y re-extrae el árbol en CADA build, nunca lo reutiliza.
Default apagado (0), para no cambiarle el comportamiento al worker.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YGXe6mShYYw6V8ea1dQ13u
2026-09-03 22:22:20 +00:00
SergioandClaude Opus 5 5b24d8b030 vigia-imagen: el guardián de los dos huecos de hoy — data de runtime y features apagadas
La regla del repo es que cada punto ciego se vuelve un guardián. Hoy aparecieron dos, los dos
arrancando KDE en QEMU y ninguno visible para las métricas que ya había:

  1. DATA de runtime que ninguna arista de BUILD alcanza — el tema de iconos. `build-state` mide
     lo DECLARADO y nadie declara lo que no es dep de build de nadie.
  2. Una porción OPCIONAL de una librería que sí está — el módulo QML de kcoreaddons. No falta una
     receta ni una librería: falta una FEATURE, y ninguna métrica sobre recetas puede verlo.

`vigia-imagen.py` recorre los ARTEFACTOS del cierre de cada perfil (no las recetas: el artefacto es
lo que se instala) y comprueba cinco invariantes de imagen USABLE: iconos, hicolor, cursores,
fuentes, terminal y que todo `import` de los `.qml` instalados tenga un módulo con `qmldir`.
Hermano de `vigia-sonames.py`, que cubre la otra mitad del runtime (los SONAME sin proveedor).

Tres decisiones de diseño que salieron de usarlo contra el corpus real:

- **MEDICIÓN PARCIAL, gritada.** El primer informe dijo «KDE no tiene terminal» teniendo konsole:
  los 71 artefactos que la cascada de kcoreaddons dejó en deuda no existen en el store, y sin
  artefacto no se puede afirmar NI que falta NI que está. Ahora cuenta los nodos sin artefacto, lo
  dice arriba de todo y no cuenta esos ✗ como fallos. `--fail` distingue **exit 1 = medí y falta**
  de **exit 2 = no pude medir**. Es la regla del ausente ruidoso, aplicada al propio vigía.
- **EXCEPCIONES con motivo escrito.** `escritorio-mirada` es slim a propósito y `escritorio-sway`
  no lleva tema de iconos por una decisión medida. Un ✗ permanente por algo ya decidido es deuda
  fantasma — la figura de la terna GNOME que hubo que sacar de targets.toml.
- **Ruido eliminado midiendo, no suponiendo.** `QtSystemInfo` salía como hueco y estaba DENTRO de
  un bloque \qml de la documentación de `Video.qml`; `HelperWidgets` viene de los `*Specifics.qml`
  de `designer/`, que sólo carga Qt Design Studio. Se despojan comentarios y se saltea `designer/`.

Estado hoy: gnome ✓ en los seis; cosmic y sway ✓ salvo **cursores**, que queda por triar — el
puntero SÍ se ve en las capturas de las dos, así que puede ser fallback embebido del compositor
(smithay trae uno) y no un hueco. KDE sale parcial por la deuda de kcoreaddons.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YGXe6mShYYw6V8ea1dQ13u
2026-09-03 22:02:44 +00:00