Commit Graph
1913 Commits
Author SHA1 Message Date
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
Sergio d0c1402267 estado: cosecha granja 2026-09-03T22:01:32Z — avance del árbol KDE 2026-09-03 22:01:32 +00:00
SergioandClaude Opus 5 914c1b72af kcoreaddons: prender el módulo QML — el menú de Plasma ABRE, y detrás de él konsole
`-DKCOREADDONS_USE_QML=OFF` estaba desde que se escribió la receta, con el argumento razonable de
que un framework tier-1 no debería arrastrar QML. El precio no se vio hasta hacer CLIC en el
lanzador dentro de QEMU: `kickoff` importa `org.kde.coreaddons` y ese módulo lo instala esta receta
y ninguna otra ⇒ **el menú de aplicaciones no abría**. La librería C++ salía completa, sus 70
consumidores enlazaban bien y el perfil reportaba 100%.

Es la forma más pura del «sellado ≠ arranca»: no falta una librería, falta una porción OPCIONAL de
una librería que sí está. Ninguna métrica de clausura puede verlo — mide recetas, no features.

`qtdeclarative` ya estaba en `[deps].build`, así que prenderlo no agrega una dep: deja de tirar lo
que ya se podía construir.

VERIFICADO CON UN SOLO BUILD (56 s), a propósito, en vez de pagar la cascada para averiguarlo:
  · panel → menú abre (usuario, buscador, Favoritos/Todas, Aplicaciones/Lugares/Sesión)
  · buscar «konsole» + Enter → la terminal arranca y corre:
        uname -a         → Linux (none) 6.16.12 #1 SMP PREEMPT_DYNAMIC … x86_64
        konsole --version → konsole 25.04.3
Es la cadena completa del escritorio por primera vez: panel → menú → búsqueda → app → shell.

COSTO, medido antes de tocar y confirmado después: `yupana radio kcoreaddons` predijo 71, y el grafo
regenerado da exactamente **71 en deuda** (`escritorio-kde 192/263`). Queda como deuda DECLARADA
para una campaña de granja; la imagen de hoy corre con un kcoreaddons más nuevo que aquel contra el
que enlazaron sus consumidores, lo que es legítimo porque cruza un SONAME (misma ABI, sólo se suma
un módulo QML) — la misma regla que decidió la promoción de pipewire.

De yapa: `export SHELL=/bin/sh` en plasma-start-qemu.sh. El aviso rojo de konsole («Could not find
'', starting '/bin/sh' instead») era real y no venía de /etc/passwd —que dice /bin/sh— sino de que
konsole lee $SHELL y este getty no es un login shell.

Y el barrido que encuentra esto sin hacer clic queda escrito en el runbook: cruzar los `import` de
los `.qml` instalados contra los módulos con `qmldir`. Además de éste destapó `org.kde.kscreenlocker`
y `org.kde.newstuff.core`, sin diagnosticar.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YGXe6mShYYw6V8ea1dQ13u
2026-09-03 21:57:38 +00:00
SergioandClaude Opus 5 4a68dfe761 qorpa D9: el canal de evidencia, cableado — la única forma de auditar el montón B
De un binario ajeno no hay fuente que leer. Lo único observable es lo que el
kernel le NIEGA y anota, y hasta acá ese canal existía en el build pero ninguna
instancia lo abría. `hammer qorpa run <id> --evidence` levanta el lector
(`harkaq-audit`) en el HOST —el audit no está namespaceado— antes de que arranque
la instancia, y al terminar imprime uno de tres estados. Los tres, medidos:

  HERMÉTICO     0 denegaciones Y el canario las respalda
  IMPURO        `touch /usr/INTRUSO; mkdir /opt/INTRUSO` →
                  fs.make_reg · /usr     fs.make_dir · /opt
  SIN EVIDENCIA quitándole las capabilities al lector. NO es «limpio»

**El canario es lo que hace que «cero denegaciones» valga algo:** un fichero
donde la política no alcanza; al leerlo, el kernel emite una denegación que
revela el `domain=` de ESTE dominio Landlock, un número que desde fuera no se
adivina. Sin él, `denials=[]` sería el instrumento callado.

**Dos condiciones estructurales, y se FALLA en vez de dar un veredicto vacío:**
con `nesting` no hay Landlock (D9 conflicto 1) ⇒ o anidás o auditás; y sin
`seal_image` la política es `rw /` ⇒ no hay NADA denegable y el veredicto sería
limpio por construcción, no por mérito. No es un defecto de la implementación:
**la evidencia sólo existe donde algo puede ser negado.**

**Un bug del propio instrumento, que sólo salió usándolo:** sin CAP_AUDIT_READ
el kernel RESPONDE que no (`NLMSG_ERROR`/EPERM) y el lector ignoraba esa
respuesta esperando una que no iba a llegar — 8 s por consulta, 16 s en su
compuerta. Como `qorpa run` lo despierta al terminar, moría por señal dentro de
la compuerta **sin emitir nada**: un «no» tardío se parecía demasiado a un
cuelgue. Ahora atiende el NLMSG_ERROR y dice su motivo en 2 s. Y si aun así el
veredicto sale vacío, se reporta con el código de salida del lector, que es el
único dato que queda.

Guardián: `scripts/qorpa/evidence-probe.sh`, con las tres aserciones. La 2 es la
que sostiene a la 1 — sin algo que TIENE que salir sucio, «HERMÉTICO» lo cumple
igual un canal muerto. Comprueba también las capabilities del lector, que **se
pierden en cada recompilación** y son la forma más probable de que el canal
muera en silencio.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QZjGRqvjWij9dew7NVFu4Q
2026-09-03 21:57:26 +00:00
SergioandClaude Opus 5 e04fdf4599 evidencia: el panel de Plasma con iconos, y el lanzador que NO abre por un módulo QML
Verificado en QEMU tras declarar `breeze-icons`: el panel pasa de «reloj solo» a completo —
kickoff, gestor de tareas, bandeja (notificaciones, volumen, teclado, red), reloj y mostrar
escritorio. Confirma que el panel nunca estuvo roto: no tenía iconos que dibujar. Y el mensaje
`kf.iconthemes: Icon theme "breeze" not found` desapareció del log.

⚠ CORRIJO una atribución del commit anterior (d69c437): dije que la barra derecha vacía de la
captura de GNOME era el mismo hueco de iconos, y NO lo es — `scripts/gnome/hydrate-gnome.sh` SÍ
hidrata `adwaita-icon-theme`, así que ese rootfs tenía tema. El hueco de GNOME es real pero está
en el PERFIL (`targets.toml`, que es lo que define la imagen enviable), no en aquella corrida;
la barra derecha vacía tiene otra causa, sin diagnosticar.

Y la segunda captura es un hallazgo nuevo, encontrado haciendo CLIC en el lanzador desde el
monitor de QEMU:

    kickoff/main.qml:191:25: Type FullRepresentation unavailable
    Header.qml:18:1: module "org.kde.coreaddons" is not installed

`kcoreaddons.toml` pasa `-DKCOREADDONS_USE_QML=OFF` ⇒ el módulo QML no se construye ⇒ **el menú
de aplicaciones no abre**. `yupana radio kcoreaddons` = 71: prenderlo es campaña de granja.

El barrido que lo generaliza (cruzar los `import` de los `.qml` instalados contra los módulos con
`qmldir` del rootfs) encontró además `org.kde.kscreenlocker` y `org.kde.newstuff.core`.

El runbook queda con las tres piezas que hacen falta en gioser, que no tiene ni ventana ni socat:
STAGE en el volumen (o EXDEV), monitor por socket unix desde python, y cómo hacer CLIC con un
ratón RELATIVO (fijar contra una esquina y moverse desde ahí).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YGXe6mShYYw6V8ea1dQ13u
2026-09-03 21:32:46 +00:00
Sergio ee21787713 estado: cosecha granja 2026-09-03T21:31:25Z — avance del árbol KDE 2026-09-03 21:31:26 +00:00
SergioandClaude Opus 5 d69c437051 escritorios: KDE y GNOME corrían SIN tema de iconos — el panel vacío no era el panel
Medido sobre los artefactos del cierre de cada imagen, contando qué `usr/share/icons/*/`
trae un `index.theme` (que es lo que convierte un directorio en un tema):

    escritorio-kde      sólo Breeze_Light y breeze_cursors — que son CURSORES
    escritorio-gnome    CERO, ni siquiera hicolor
    escritorio-cosmic   Cosmic + hicolor            <- el único que estaba bien
    escritorio-sway     CERO

Las dos capturas de QEMU de hoy ya lo mostraban y se leyeron como «arranca»:

- `plasma6-qemu-2026-09-03-kactivitymanagerd.png`: panel con el reloj y nada más. Los `.so`
  de los applets estaban TODOS instalados; lo que faltaba era qué pintar. `kickoff`,
  `systemtray`, `showdesktop` y `trash` SON un icono, así que sin tema quedan de ancho cero
  — el reloj se ve porque dibuja TEXTO. El log lo decía en una línea:
  `kf.iconthemes: Icon theme "breeze" not found.`
- `gnome-shell-qemu-2026-09-03-libs-compartidas.png`: barra superior con la fecha y el pill
  de espacios, y la DERECHA vacía — red, volumen y batería son iconos.

`breeze` (ya declarado) es el tema de WIDGETS y CURSORES; los ~14.000 iconos viven en
`breeze-icons`, receta aparte, sellada desde siempre y declarada por NADIE. Igual
`adwaita-icon-theme` en GNOME, que además trae los XCursor (su cabecera dice por qué:
sin tema de cursor no hay puntero visible con el cursor por software de virtio-gpu).

Es la figura de las fuentes y de `foot` otra vez: data de RUNTIME, ninguna arista de BUILD
la alcanza, y la métrica de clausura no la echa de menos porque mide lo declarado.

`hicolor-icon-theme` —el fallback obligatorio de freedesktop— se promueve al corpus para que
lo alcancen las cuatro imágenes: hash IDÉNTICO desde la cola y desde el corpus
(b3:98ad44a5), y sus 4 consumidores (adwaita-icon-theme, cosmic-icons, cosmic-app-library,
cosmic-launcher) miden el mismo hash antes y después ⇒ un solo artefacto, CERO rebuilds.

Cierre tras declararlos, todo sellado y sin deuda:
  kde 263/263 (+2) · gnome 158/158 (+2) · sway 173/173 (+1) · cosmic 133/133 (igual)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YGXe6mShYYw6V8ea1dQ13u
2026-09-03 21:18:17 +00:00
Sergio 08d27f0e2f estado: cosecha granja 2026-09-03T21:01:46Z — avance del árbol KDE 2026-09-03 21:01:46 +00:00