Commit Graph
286 Commits
Author SHA1 Message Date
Sergio eb20e1d91e estado: cosecha granja 2026-09-05T15:33:38Z — avance del árbol KDE 2026-09-05 15:33:38 +00:00
Sergio 6a5408adae estado: cosecha granja 2026-09-05T15:05:08Z — avance del árbol KDE 2026-09-05 15:05:08 +00:00
Sergio 9f79362201 estado: cosecha granja 2026-09-05T14:32:59Z — avance del árbol KDE 2026-09-05 14:32:59 +00:00
Sergio 323475a6f1 estado: cosecha granja 2026-09-05T13:02:07Z — avance del árbol KDE 2026-09-05 13:02:07 +00:00
Sergio af0e90ba8d estado: cosecha granja 2026-09-05T12:32:10Z — avance del árbol KDE 2026-09-05 12:32:10 +00:00
Sergio 0bda91a374 estado: cosecha granja 2026-09-05T12:02:20Z — avance del árbol KDE 2026-09-05 12:02:20 +00:00
Sergio 9250f07a56 estado: cosecha granja 2026-09-05T11:01:56Z — avance del árbol KDE 2026-09-05 11:01:56 +00:00
Sergio 6d8bb7d901 estado: cosecha granja 2026-09-05T10:02:14Z — avance del árbol KDE 2026-09-05 10:02:14 +00:00
Sergio 9d0ed92b60 estado: cosecha granja 2026-09-05T09:02:08Z — avance del árbol KDE 2026-09-05 09:02:09 +00:00
Sergio a4af37e01d estado: cosecha granja 2026-09-05T05:01:58Z — avance del árbol KDE 2026-09-05 05:01:58 +00:00
Sergio f32fcb15d9 estado: cosecha granja 2026-09-05T04:32:12Z — avance del árbol KDE 2026-09-05 04:32:12 +00:00
Sergio 52e4dbe8cc estado: cosecha granja 2026-09-05T04:02:19Z — avance del árbol KDE 2026-09-05 04:02:19 +00:00
Sergio b38e121a6b estado: cosecha granja 2026-09-05T03:32:02Z — avance del árbol KDE 2026-09-05 03:32:02 +00:00
Sergio 067631fa52 estado: cosecha granja 2026-09-05T01:02:18Z — avance del árbol KDE 2026-09-05 01:02:18 +00:00
Sergio 7083a0edfc estado: cosecha granja 2026-09-04T23:00:02Z — avance del árbol KDE 2026-09-04 23:00:02 +00:00
Sergio 688ea27f40 estado: cosecha granja 2026-09-04T22:31:53Z — avance del árbol KDE 2026-09-04 22:31:53 +00:00
Sergio caeee204a6 estado: cosecha granja 2026-09-04T22:02:03Z — avance del árbol KDE 2026-09-04 22:02:03 +00:00
Sergio 5776f63aed estado: cosecha granja 2026-09-04T21:31:52Z — avance del árbol KDE 2026-09-04 21:31:52 +00:00
Sergio 9f908090d5 estado: cosecha granja 2026-09-04T19:03:00Z — avance del árbol KDE 2026-09-04 19:03:00 +00:00
Sergio 8c15c2eaf4 estado: cosecha granja 2026-09-04T18:32:49Z — avance del árbol KDE 2026-09-04 18:32:49 +00:00
Sergio 188a45b1d5 estado: cosecha granja 2026-09-04T18:05:16Z — avance del árbol KDE 2026-09-04 18:05:16 +00:00
Sergio dc8aa7367e plataforma Gecko: cbindgen sube al corpus
Genera las cabeceras C++ de los componentes Rust de Gecko (Stylo, WebRender) y el
build de Firefox la exige. Mudanza gratis: [deps] vacío ⇒ no hay cierre que
cambiar, mismo ArtifactHash (b3:bd2e6ca6) en las dos rutas, radio 0.
2026-09-04 17:54:17 +00:00
Sergio 027d3a25ef plataforma Gecko: clang18 sube al corpus — bindgen necesita libclang
El build de Firefox corre bindgen sobre los headers de C++ y bindgen carga
libclang.so en RUNTIME. La receta ya existía —nació en incoming-cosmic por un
crate *-sys del portal, y su commit de origen dice «sólo libclang.so»— pero desde
el corpus no se alcanza una cola hermana. Sin esto no hay Firefox, ni Waterfox,
ni Zen.

Mudanza medida ANTES, no después: sus cinco deps (cmake, samurai, python3,
pkgconf, llvm18) viven sólo en el corpus, así que incoming-cosmic ya las resolvía
por caída al padre y el cierre no cambia. hammer hash dio el MISMO ArtifactHash
(b3:25d95279) en las dos rutas.
Verificado que xdg-desktop-portal-cosmic —su único dependiente— sigue SELLADO y
que la cola cosmic queda en 36/36 sin deuda: cero rebuilds.

Se MUEVE y no se copia: dos ficheros para un artefacto es el cuadro de las dos
glib esperando a que uno de los dos derive.
2026-09-04 17:53:03 +00:00
Sergio e684c26e52 targets: obs-studio entra al perfil escritorio-kde (274/274)
Una receta sellada que ningún perfil declara NO ESTÁ EN NINGUNA IMAGEN, y la
métrica de clausura no lo puede ver porque mide lo declarado — la lección que este
fichero ya aprendió con foot en sway y con las 22 apps KDE. OBS estaba sellado y
en ninguna imagen.

Entra SÓLO en escritorio-kde, y no por preferencia: su frontend es Qt6 y las 13
recetas Qt viven sólo en esa cola. Verificado con `yupana perfiles obs-studio`.
El perfil pasa de 263/263 a 274/274 — arrastra 11 nodos a la clausura, todos ya
sellados, y el grafo sigue cerrando.

De paso: el aviso de los «tres huecos de mpv» estaba repetido en los CUATRO
perfiles de escritorio y hoy quedó vencido en los cuatro (ALSA/PipeWire, Lua/OSC
y vaapi están cerrados). Corregidos los cuatro; el assert de count==1 fue lo que
destapó que no era uno solo.
2026-09-04 17:42:47 +00:00
Sergio 3f84cd761b estado: cosecha granja 2026-09-04T17:02:11Z — avance del árbol KDE 2026-09-04 17:02:11 +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 323a675ed0 estado: cosecha granja 2026-09-04T16:01:58Z — avance del árbol KDE 2026-09-04 16:01:58 +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
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 3329317737 estado: cosecha granja 2026-09-04T00:02:50Z — avance del árbol KDE 2026-09-04 00:02:50 +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
SergioandClaude Opus 5 6c37df6fa4 ncurses-shared: cierra la fuga de pw-top al lab, que llevaba desde agosto
recipes/pipewire.toml:85-88 afirma que quitando la dep de ncurses «meson saltea pw-top
y el resto construye». ES FALSO, y llevaba así desde al menos el 2026-08-29. Quitar la
dep no desactivó nada: el guardián de upstream es `if ncurses_dep.found()` y meson lo
encontró igual, en el sysroot Alpine DEL LAB. pw-top se construye, se sella y sale con
NEEDED libncursesw.so.6, que ningún artefacto del cierre publica porque el ncurses del
catálogo es --without-shared. Una herramienta rota dentro de las CUATRO imágenes,
invisible para el store porque el lab no entra en hash_inputs.

LA LECCIÓN, que es más grande que pw-top: QUITAR UNA DEP DE [deps] NO APAGA LA FUNCIÓN.
Cambia de dónde sale. Para apagarla de verdad hay que decírselo a la perilla del
proyecto; si no la hay, la dep tiene que estar declarada y satisfecha desde el store.

POR QUÉ UNA RECETA NUEVA Y NO RE-SELLAR PIPEWIRE. El arreglo limpio es declarar la dep y
reconstruir; cuesta 10 dependientes directos y 7 sellados que caen a deuda, entre ellos
xdg-desktop-portal-cosmic y cosmic-settings-daemon, que son Rust —el portal murió por
OOM tres veces y el que selló tardó 48 min con pico de 5,4 GiB de swap—. No se paga eso
hoy por una herramienta de diagnóstico, y menos con otro agente compilando en la misma
máquina. Lo que cruza acá es un SONAME, y para eso el repo ya tiene regla escrita:
enlazar contra una variante y CORRER contra otra es legítimo cuando lo que cruza es un
SONAME. Cero rebuilds.

⚠ QUEDA DEUDA ANOTADA: pipewire sigue enlazando contra el lab en BUILD. El día que se
re-selle por cualquier otro motivo hay que declarar ncurses-shared en sus [deps] y
corregir el comentario mentiroso. Esto tapa el síntoma en runtime, no la causa.

DOS COSAS QUE COSTARON, y están escritas en la receta:
- `-stats` es un flag de GNU ld que lld rechaza, y viene DENTRO del token
  `-Wl,-soname,...,-stats,-lc` que arma el configure de ncurses. No se puede pasar por
  LDFLAGS ni hay perilla MK_SHARED_LIB, y el patrón .zwrap de poppler tampoco sirve tal
  cual porque filtra argumentos completos y acá hay que reescribir uno.
- Quitando `-stats`, el siguiente en caer es el `-lc` del mismo token. El driver de zig
  valida lo que va dentro de `-Wl,` y no deja pasar ninguno de los dos; libc la liga él
  solo, así que la cola `,-stats,-lc` se va entera. Se quita del Makefile GENERADO, con
  un grep previo que FALLA si el configure deja de emitirlo (para no seguir en silencio).

EVIDENCIA, con control discriminante:
  sin ncurses-shared -> Error relocating /lib/libncursesw.so.6: __vfprintf_chk: symbol
                        not found   (símbolo de _FORTIFY_SOURCE de glibc que musl no
                        tiene: la fuga al lab, reproducida)
  con ncurses-shared -> carga y corre; sólo falla en el runtime de PipeWire por no haber
                        demonio ni plugins SPA en la raíz de prueba

vigia-sonames en los cuatro perfiles: libncursesw.so.6 Y libpanelw.so.6 desaparecen.
Lo que queda son herramientas de build (go, python3, perl) más tres de RUNTIME que NO
son de este cambio y quedan anotadas: spidermonkey pide libgcc_s/libstdc++ en gnome,
libadwaita pide liblzma, y sqlite-shared pide libreadline.

Grafos: 820/820, 999/999, 883/883, 856/856, 833/833.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XB2iEmxeLZgzqNfhWChrLo
2026-09-03 17:29:24 +00:00
SergioandClaude Opus 5 1f415802f1 apps: GNOME tenía imagen sin terminal ni editor — arreglado con CERO recetas; y el montón A queda agotado
DOS COSAS, y la segunda no estaba en el plan.

1. EL MONTÓN A SE AGOTÓ DE COSAS SIN MURO. Re-triadas con scripts/provee.py las tres
   candidatas que la tabla daba como baratas o dudosas; las tres son muro, y ninguna por
   el motivo que decía la tabla:

   - imv     → no hay proveedor de OpenGL de escritorio (ya documentado; la sustituyó swayimg)
   - mupdf   → la nota decía «el X11 es del visor mupdf-x11; mupdf-gl no». Falso: platform/gl/
               va sobre GLUT + OpenGL de escritorio, el mismo muro que imv. mupdf NO TIENE
               visor Wayland: sus dos UIs son X11 o GL. El motor no tiene muros pero no hace
               falta, el PDF ya lo da poppler.
   - inkscape→ era GTK3 encubierto, como la tabla sospechaba: INKSCAPE_1_4_4 pide
               gtkmm-3.0>=3.24 y gtk+-3.0>=3.24. master SÍ migró a GTK4 (gtk4>=4.14) pero
               está sin publicar, y además el catálogo no tiene NI UN binding C++:
               provee.py da ✗ en sigc++-2.0, glibmm-2.4, cairomm-1.0, pangomm-1.4 y gtkmm.

   ⇒ todo lo que queda está detrás de UNA de cuatro decisiones (GTK3 / Qt6-en-el-corpus /
   GL de escritorio / X11), no de trabajo de recetas.

2. LO QUE SÍ ESTABA ROTO, Y NO ERA FALTA DE RECETAS. Cruzando la membresía de los cuatro
   perfiles contra emuladores de terminal, editores y gestores de ficheros:

       escritorio-cosmic  term=cosmic-term  editor=cosmic-edit  archivos=cosmic-files
       escritorio-sway    term=foot         editor=vim          archivos=—
       escritorio-gnome   term=—            editor=—            archivos=—
       escritorio-kde     term=—            editor=—            archivos=—

   Es la lección de foot otra vez y a mayor escala: sway llegó a 121/121 SIN emulador de
   terminal porque nadie lo declaraba, y la métrica de clausura no lo ve porque mide lo
   DECLARADO. Un escritorio sin terminal no es uno incompleto: es uno del que no se puede
   salir cuando algo falla.

   GNOME arreglado con CERO recetas nuevas: foot y helix viven en el CORPUS, ya estaban
   selladas y no las declaraba NINGÚN perfil. foot es Wayland puro sobre xdg-shell (no
   pide protocolos de wlroots) así que corre bajo mutter igual que bajo sway; su único
   NEEDED es libc.so. helix es TUI y corre dentro de la terminal.

   ⚠ KDE NO SE TOCA, y es un hallazgo aparte que hay que acordar con ese frente: tiene 22
   apps con .desktop selladas en su cola y sin declarar (konsole, dolphin, kate, okular,
   spectacle, ark, gwenview, systemsettings, kcalc…) y además le faltan plasma-desktop,
   plasma-nm, plasma-pa, powerdevil y kscreen — o sea red, audio, energía y pantalla. Su
   perfil son 13 raíces de ARRANQUE EN METAL, no la imagen de escritorio completa (ésa se
   hidrató aparte, por hash). No cuesta un build; cuesta acordarlo.

Nota de método: build-state.py invoca `hammer hash` ~1000 veces y el otro agente
recompiló el binario a mitad del barrido ⇒ kjobwidgets salió `unhashable` y KDE reportó
997/998. No era la receta: era la carrera. Re-corrido da 998/998.

Los cinco grafos: 819/819, 998/998, 882/882, 855/855, 832/832, cero nodos `wanted`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XB2iEmxeLZgzqNfhWChrLo
2026-09-03 16:18:44 +00:00
SergioandClaude Opus 5 cab9439644 fuentes: dejavu al corpus (arregla un wanted que dejé), KDE con fuente, y la nerd de monospace
TRES COSAS, y la primera es un bug mío de hace un rato.

1. dejavu-fonts PROMOVIDA AL CORPUS — arregla un nodo `wanted` que introduje.
   Al añadirla de raíz a escritorio-gnome quedó como `wanted`: la receta existía en
   incoming-{kde,wlr,cosmic} y NO en incoming-gnome ni en el corpus, y una receta no
   alcanza una cola hermana. O sea que la raíz no resolvía a nada y GNOME seguía sin
   fuentes. `wanted` NO es `debt`, así que drenaje.json seguía diciendo deuda=0 y el
   hueco no salía por ninguna métrica — se vio mirando el nodo en build-state-gnome.json.
   Promoción gratis: las tres copias sellaban el mismo hash (b3:5b3a5df3) y sus deps
   están vacías. Las tres se jubilan. Ahora los cuatro perfiles resuelven a corpus y los
   cinco grafos quedan con CERO nodos `wanted`.

2. dejavu-fonts en escritorio-kde, como se pidió. Tenía UNA fuente y de rebote, dentro
   de qtbase — apoyarse en un detalle de empaquetado de Qt deja sin nada a todo lo que
   no es Qt.

3. dejavu-fonts-nerd 3.5.1 en los CUATRO perfiles: DejaVu Sans Mono parcheada con Nerd
   Fonts. Lo que se midió antes de escribirla, porque cambia la forma de hacerla:

   - SE AÑADE, NO REEMPLAZA, y no es prudencia: la licencia de Bitstream Vera exige que
     una fuente modificada se RENOMBRE. Por eso upstream la llama «DejaVuSansM Nerd Font
     Mono» — leído del name de la TTF, no supuesto. Una fuente nerdeada NO puede
     responder al nombre de la original; sustituirla rompería a todo lo que pide «DejaVu
     Sans Mono», empezando por foot, que ya murió una vez así.
   - SÓLO LA MONOESPACIADA: upstream no publica DejaVu Sans ni Serif parcheadas, y en una
     fuente de interfaz proporcional esos glifos no los pide nadie. «Todas nerdeadas» no
     se puede cumplir al pie de la letra.
   - SÓLO UNA DE LAS TRES VARIANTES: NerdFont / NerdFontMono / NerdFontPropo son los
     mismos glifos con distinto avance. Las doce pesan 32 MB; las cuatro de Mono, 11 MB.
     Se quedan las Mono, que son las correctas para una rejilla de terminal. Referencia:
     la familia DejaVu ENTERA son 9,8 MB.

   ⚠ EL NÚMERO DEL .conf ESTÁ MEDIDO, NO ELEGIDO. fontconfig carga conf.d en orden
   alfabético y el <prefer> que llega antes gana. Con 60-nerd-monospace.conf —que ordena
   después de 60-latin.conf, que ya prefiere Noto/DejaVu/Inconsolata— `fc-match
   monospace` seguía dando DejaVu Sans Mono: la conf estaba INSTALADA Y ERA INERTE, el
   mismo modo de fallar que el plugin ALSA de PipeWire. A 59- gana. 45-latin.conf también
   menciona monospace pero usa <default>, no <prefer>, así que no compite.

   ⚠ Y strip_components = 0, que tampoco es cosmético: el tarball de nerd-fonts es PLANO
   y con el default de 1 el árbol de fuentes queda VACÍO — el build no se detiene ahí,
   sigue y falla más tarde en el cp, con un mensaje que no menciona la extracción.

   ⚠ LA LICENCIA NECESITA UNA PASADA HUMANA antes de `hammer pack`: el LICENSE.txt del
   tarball cubre sólo DejaVu/Bitstream Vera y no menciona los ~10 conjuntos de iconos
   importados, que tienen licencias propias (Font Awesome CC-BY-4.0, Octicons MIT,
   Material OFL, Powerline MIT…). El campo dice lo DOCUMENTADO, no el conjunto real; no
   se inventa una cadena SPDX. Anotado en la receta.

EVIDENCIA, contra el conf.d REAL del artefacto de fontconfig:
  monospace          -> DejaVuSansM Nerd Font Mono   (los iconos llegan)
  "DejaVu Sans Mono" -> DejaVu Sans Mono             (intacta)
  sans-serif         -> DejaVu Sans                  (sin tocar)
  serif              -> DejaVu Serif                 (sin tocar)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XB2iEmxeLZgzqNfhWChrLo
2026-09-03 16:09:24 +00:00
SergioandClaude Opus 5 da0186d250 apps: zathura + backend de PDF, en gnome/cosmic/sway — y tres defectos de imagen que salieron
La cadena: 5 recetas nuevas (girara, xxhash, poppler-glib, zathura,
zathura-pdf-poppler) y 5 promociones GRATIS al corpus (json-glib, lcms2, glib-shared,
pcre2-shared, bzip2-shared — todas con hash idéntico desde la cola y desde el corpus,
medido con hammer hash antes de mover nada).

NO va en escritorio-kde, y está escrito en tres sitios para que no se liste por
descuido: su backend necesita una poppler con ENABLE_GLIB=ON, y esa imagen ya trae la
de Qt6 vía okular. Las dos instalan /usr/lib/libpoppler.so.146 y son artefactos
DISTINTOS ⇒ hidratar las dos pone dos ficheros en la misma ruta. La salida no sería
listarla igual, sería jubilar una de las dos popplers.

LAS TRES COSAS QUE SE ROMPIERON, que valen más que las recetas:

1. -DENABLE_GLIB=ON SE APAGA SOLO Y EL BUILD SALE OK. CMakeLists:260 hace
   `if(NOT CAIRO_FOUND) set(ENABLE_GLIB OFF)`: no falla, obedece distinto. El primer
   artefacto selló sin nada de glib, exit 0, sin aviso. La causa era una línea que este
   repo ya tiene como patrón: `.pc Requires` → `[deps].build`. cairo.pc pide pixman-1 y
   pixman no estaba declarado ⇒ `pkg-config --exists cairo` falso ⇒ CAIRO_FOUND falso.
   Un .pc que falta a tres saltos apaga una FUNCIÓN, no una librería. La receta ahora
   comprueba en install que poppler-glib.pc y libpoppler-glib.so existan.

2. DOS COPIAS ESTÁTICAS DE GObject EN UN PROCESO. Con la glib estática del corpus todo
   sella y zathura arranca — y al dlopen del plugin escupe «cannot register existing
   type 'gchar'» y no abre nada. No son dos ficheros en una ruta: son dos copias del
   sistema de tipos dentro del mismo proceso, una en el ejecutable y otra dentro de
   libpoppler-glib.so. Un .a NO duplica (sólo tiene símbolos sin definir, se resuelven
   al ligar); el problema aparece sólo cuando dos objetos enlazados por separado meten
   cada uno la suya. Arreglo: las TRES recetas de la cadena declaran glib-shared.

3. FUGA AL LAB, cazada por scripts/vigia-sonames.py: zathura selló con
   NEEDED libsqlite3.so.0, un SONAME que ningún artefacto del cierre publica — meson
   había resuelto dependency('sqlite3') contra el sysroot Alpine DEL LAB. Y declarar la
   dep NO alcanzó: el .pc da un -lsqlite3 pelado y el linker prefiere la .so del lab
   sobre la .a del store. Lo arregla -Dprefer_static=true. Medido: los NEEDED bajaron de
   DIEZ a CUATRO y los cuatro los publica el cierre.

DOS DEFECTOS DE IMAGEN PREEXISTENTES que salieron de paso:

- libbz2.so.1 no lo publicaba nadie y freetype-shared lo pide, en los TRES perfiles.
  Se vio de verdad al probar el visor (el plugin no hacía dlopen). bzip2-shared existía
  sólo en incoming-kde; promovida y puesta de raíz junto a expat-shared/libffi-shared.

- escritorio-gnome NO TRAÍA NI UN FICHERO DE FUENTE. Contado sobre los artefactos del
  cierre: gnome=0, sway=22, kde=1 (una de rebote dentro de qtbase). Tenía fontconfig,
  que es el MOTOR que busca fuentes, no una fuente. Un PDF con base-14 se ve VACÍO y sin
  error. Añadida dejavu-fonts, la única receta de fuentes del catálogo entero.
  ⚠ KDE queda igual y NO se toca acá: no lleva zathura y su árbol lo trabaja otro frente.

EVIDENCIA DE QUE ANDA, no de que sella:
- `zathura --version` con el plugin lista «(plugin) pdf-poppler (2026.07.18)» sin un
  solo GObject-CRITICAL.
- poppler-render-check, receta-TESTIGO en el espíritu de gtk4-hello: arma un PDF a mano,
  lo abre con poppler-glib, lo rasteriza sobre cairo y CUENTA PÍXELES — 9600 negros,
  exactamente el rectángulo de 160x60. Un lienzo blanco no pasa. Su primera versión
  medía el TEXTO y falló: el sandbox no tiene fuentes, que es cómo se descubrió el
  hueco de arriba. El assert quedó sobre el rectángulo, que no depende de tipografía, y
  el texto se informa aparte.

Los cinco grafos quedan en N/N con cero deuda.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XB2iEmxeLZgzqNfhWChrLo
2026-09-03 12:14:07 +00:00
Sergio 4e1fed04d7 estado: cosecha granja 2026-09-03T12:01:45Z — avance del árbol KDE 2026-09-03 12:01:45 +00:00
SergioandClaude Opus 5 e2bcd96feb apps: swayimg sube a 5.5, que es lo que justificaba escribir luajit
Entró como 4.7 —la última sin Lua— sólo porque no había receta de luajit. Con luajit
sellada, sube a la actual. Lo que se gana: el motor de configuración pasó a ser Lua
(src/luaengine.cpp), y con él los perfiles de teclas y el .lua de ejemplo. Formatos:
suma qoi, ttf y xbm a los de 4.7.

Dos cambios de forma que sacan dos deps: `compositor` ya no pide json-c (la
integración con sway se rehizo sin JSON) y la man page viene PRE-GENERADA en
extra/swayimg.1 en vez de armarse con scdoc. -Ddoc=false porque ese target regenera
markdown con dos scripts de Python y lo que instala son .md, no páginas de manual.

Corregido de paso el comentario de las opciones apagadas: son DOS por cola, no una.
`svg` pide librsvg-2.0 (sólo en incoming-gnome) y `exif` pide exiv2 (sólo en
incoming-kde). Las dos existen en el disco y ninguna es alcanzable desde el corpus.
Por eso este visor no muestra metadatos EXIF, y queda escrito dónde está el hueco.

Evidencia de que la cadena cierra, no sólo de que sella: `swayimg -e` ejecuta Lua
dentro del visor y reporta «Lua 5.1 · jit=true · LuaJIT 2.1.1787165859» — que es
exactamente el relver de nuestra receta de luajit, o sea que el intérprete que corre
es el que construimos. Un script con error de sintaxis se reporta como error de Lua.
NEEDED sigue siendo sólo libc.so.

Los cinco grafos quedan en N/N con cero deuda.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XB2iEmxeLZgzqNfhWChrLo
2026-09-03 11:37:02 +00:00
SergioandClaude Opus 5 d8dd779812 apps: swayimg 4.7 sellada, visor de imágenes en las cuatro imágenes
El plan proponía `imv` como paso 4. Al medirla apareció un muro que el método de
triaje no podía ver: imv dibuja con OpenGL de función fija (glBegin/glOrtho) y esta
distro NO tiene proveedor de GL de escritorio — las tres variantes de mesa van
-Dglx=disabled -Dglvnd=false y no publican libGL.so ni gl.pc ni opengl.pc, y no hay
receta libglvnd. La trampa fina: mesa SÍ instala GL/gl.h, así que compila entero y
muere al ligar. Darlo vuelta = autorar libglvnd + rehacer mesa (radio 139).

swayimg cubre el mismo caso de uso sin tocar GL (rasteriza a wl_shm) y con CERO
recetas nuevas: sus deps requeridas ya estaban en el corpus. De yapa trae backend DRM
(imágenes en TTY pelada, sin compositor).

Pineada 4.7 y no 5.5 a propósito: desde la 5.0 luajit es obligatoria y no hay receta
(la lua5.2 del OSC de mpv es otra ABI). Escribir luajit es el próximo paso barato.

-Dversion=4.7 no es cosmético: su default 0.0.0 dispara un `git describe` sobre el
árbol ⇒ la versión estampada en el binario dependería del checkout. Misma familia que
el -Dbuild-date de mpv.

Evidencia de que anda, no sólo de que sella: NEEDED = libc.so y nada más (cero glibc,
cero X11, cero GL), `--version` dice 4.7 con jpeg/png/gif/webp/tiff, prueba las dos
UIs (Wayland → DRM) y el bucle de decodificación rechaza lo que no es imagen.

Añadida a las raíces de los cuatro perfiles (sellado ≠ instalado). Los cinco grafos
quedan en N/N con cero deuda.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XB2iEmxeLZgzqNfhWChrLo
2026-09-03 11:28:19 +00:00
Sergio d3fa729698 estado: COSMIC vuelve a 106/106 — el portal selló al 4º intento, con el zram en 12 G
`xdg-desktop-portal-cosmic` b3:9e6d432b, 9 ficheros / 38 M. Los cuatro perfiles cierran otra vez:
KDE 188/188, GNOME 132/132, COSMIC 106/106, sway 146/146. CERO deuda.

No era la receta, era la máquina, y ahora hay el número que lo prueba. Los tres intentos anteriores
murieron por OOM entre los 24 y los 25 minutos con el zram de 4 GiB lleno al 90%. Éste tardó **48
minutos** y su pico de swap fue **5,4 GiB** — o sea que necesitaba 1,4 GiB MÁS de los que el swap
entero podía darle. Con 4 GiB no había paciencia que alcanzara.

CÓMO SE PASÓ DE 4 A 12 GiB, y por qué no fue con `swap-zram 12`. Su freno se negaba con razón:
había 3.694 M adentro contra 3.283 M de RAM disponible, y ese guardián existe porque un `swapoff`
sin destino es como se volteó la máquina el 2026-08-17. Esperar tampoco servía: el zram no se drena
solo, sus páginas son de procesos vivos. Se hizo AÑADIENDO ANTES DE QUITAR, que es la forma estándar
de redimensionar swap sin el pico:

  1. zramctl --find --size 12G --algorithm zstd            → /dev/zram1
  2. verificar `backing_dev: none`  ← el único agujero de zram contra T9 de qullqa; con un
     backing_dev las páginas salen EN CLARO a disco. Se comprobó a mano por no pasar por el script.
  3. swapon --priority 110 /dev/zram1                       ← destino disponible antes de quitar
  4. swapoff /dev/zram0                                     ← migra, no choca contra la pared
  5. zramctl --reset /dev/zram0

El 12 no es a ojo: sale de la compresión MEDIDA acá (`mm_stat` daba orig=3,7G compr=1,3G ⇒ 3,0x con
zstd), así que 12 GiB de páginas viven en ~4 GiB de RAM. 12 sobre 7,6 de RAM es 1,6x.

⚠ NO se puso un swapfile en disco, ni en claro ni cifrado, y no es prudencia: T9 del SDD de qullqa
dice que «un `swapon` sin cifrar anula todo el documento», y la variante cifrada (dm-crypt sobre
loop) congeló la máquina 70 minutos el 2026-08-17. Queda escrito en `/etc/conf.d/zram-swap`, que
además hace persistente el tamaño (`ZRAM_TAM_GIB=12`) por el override que el propio init prevé.
2026-09-03 07:51:46 +00:00
Sergio 39f5007cff wf-recorder 0.6.0: la primera app que cobra la promoción de pipewire
Sellada b3:25caa359 al primer intento. `--help` corre y los NEEDED traen `libpipewire-0.3.so.0`:
graba CON audio, que era exactamente lo que anoche no se podía.

Es la app que estaba bloqueada por el defecto del triaje —preguntaba «¿existe la receta?» en vez de
«¿la alcanza quien la usa?»—: sus dos backends de captura de sonido vivían sólo en colas y una
receta del corpus no alcanza una cola hermana. Con pipewire en el corpus, cae sola.

`-Ddefault_audio_backend=pipewire` explícito y no `auto`: su meson resuelve `auto` mirando qué
encontró en el sandbox (meson.build:95-101), o sea que el artefacto dependería de lo que quedó
montado en el lab. Misma disciplina que en mpv y ffmpeg.

⚠ SE LISTA SÓLO EN `escritorio-sway`, y la razón es de PROTOCOLO: captura por `wlr-screencopy`, que
implementan los compositores wlroots. KWin y mutter NO lo implementan —usan el portal/ScreenCast—,
así que meterlo en esas dos imágenes sería enviar una herramienta que no puede funcionar ahí: deuda
fantasma con forma de app. En COSMIC hay que verificar si cosmic-comp expone el protocolo antes de
listarlo; no se listó a ciegas.

Cubre el caso de uso principal por el que uno instala OBS, con UNA receta en vez de las 20 + Qt6 +
X11 que OBS pedía. escritorio-sway 146/146.
2026-09-03 06:17:57 +00:00
Sergio e08add24be pipewire al corpus: mpv habla PipeWire nativo, y pulseaudio NO se promueve (medido)
Cierra la decisión que quedó abierta anoche en `docs/plan-apps-usuario-final.md`: el corpus no
tenía ningún cliente de audio salvo ALSA, y eso bloqueaba a toda app multimedia.

GANA LA VARIANTE DE COSMIC y la promoción es GRATIS: era la única cuyo cierre ya resolvía entero
contra el catálogo padre, así que `recipes/pipewire.toml` sella b3:e240653a — el mismo hash que
tenía en la cola. Con ella suben `libsndfile` (las tres copias sellaban idéntico) y `dbus-shared`
(gnome y cosmic, idénticas). Se jubilan 9 copias de cola.

POR QUÉ ESTO NO REPITE EL EPISODIO DE LAS DOS GLIB — leído de los artefactos sellados, no razonado:
**ningún pipewire de los tres enlaza glib.** Los NEEDED de las tres variantes son exactamente
`libdbus-1.so.3`, `libpulse.so.0` y `libsndfile.so.1`; glib entraba sólo como Requires transitivo
de pkg-config, en tiempo de build. ⇒ `libpipewire-0.3.so` es glib-free y se comparte entre las
cuatro imágenes sin riesgo.

⚠ Y POR ESO `pulseaudio` NO SE PROMUEVE, aunque sea la dep de al lado. Ahí la objeción SÍ aplica y
el número lo dice solo: `libpulse-mainloop-glib.so.0.0.6` mide **45.712 bytes** en la variante de
GNOME (NEEDED `libglib-2.0.so.0`) y **2.455.600** en la del corpus, que se traga la glib ESTÁTICA
del catálogo. Meter ésa en el proceso de gnome-shell —que ya carga la glib sombra dinámica— es
literalmente el cuadro de colord. `incoming-kde/pulseaudio` e `incoming-gnome/pulseaudio` se quedan
donde están: son variantes deliberadas, no duplicados. La copia del corpus existe sólo para que
pipewire tenga contra qué enlazar `libpulse.so.0`, y ese enlace es por SONAME — en runtime lo sirve
la libpulse de cada imagen, ABI-compatible (misma 0.24.3).

Enlazar contra una variante y correr contra otra es legítimo cuando lo que cruza es un SONAME; lo
que NO se puede es hidratar dos artefactos distintos en la misma ruta. Esa distinción es la que
decide qué se promueve y qué no.

mpv (b3:392e9690) pasa a `-Dpipewire=enabled`, con ALSA encendida detrás: prueba pipewire primero y
cae a alsa si no hay demonio —KDE todavía no lista PipeWire entre sus raíces—. Evidencia:
  NEEDED … libasound.so.2 **libpipewire-0.3.so.0** libEGL.so.1 libc.so
  --ao=help → pipewire (PipeWire audio output), alsa, null

Impacto medido antes de tocar, hasheando las 336 recetas de cola y comparando: 9 retiradas, **5
rebuilds** (wireplumber, xdg-desktop-portal ×2, kpipewire, spectacle) — los 5 sellados. Sin la
salvedad de pulseaudio habrían sido 8, incluido gnome-shell.

Perfiles: KDE 188/188, GNOME 132/132, sway 145/145.
⚠ COSMIC 105/106: `xdg-desktop-portal-cosmic` murió por OOM por TERCERA vez (7 G de RAM sin cgroups,
con otro agente compilando Rust). Sigue siendo la máquina, no la receta.
2026-09-03 06:16:05 +00:00
Sergio 3448ca4678 estado: cosecha granja 2026-09-03T06:02:15Z — avance del árbol KDE 2026-09-03 06:02:15 +00:00
Sergio b1713dd221 estado: cosecha granja 2026-09-03T05:31:09Z — avance del árbol KDE 2026-09-03 05:31:09 +00:00
Sergio f19b8b3e4a jubilar 13 copias de cola que sellan IDÉNTICO al corpus — y de paso el grafo deja de mentir
Continúa lo que ya se hizo el 2026-09-02 con las 8 copias de gnome. Medido receta por receta con
`hammer hash`: de los 30 nombres que viven en el corpus Y en alguna cola, 13 dan el MISMO
ArtifactHash que su gemela del corpus y 22 son variantes deliberadas (glib/gtk4/pango de gnome,
dbus/openssl/libxml2 de kde…) que NO se tocan.

Se van las 13 redundantes: alsa-lib ×3, nasm ×2, zlib-shared ×2, y de incoming-kde ffmpeg,
fontconfig-shared, freetype-shared, libjpeg-turbo-shared, libpng-shared y vulkan-headers. Cada
consumidor las resuelve ahora en el catálogo PADRE, con el mismo hash.

VERIFICADO ANTES Y DESPUÉS, no argumentado: se snapshotearon los 47 consumidores directos, se
borraron las 13, y se re-hashearon. **0 consumidores vivos con hash distinto** (las 4 diferencias
son las propias recetas borradas, que se consumían entre sí). Cero rebuild.

EL EFECTO QUE NO SE BUSCABA Y ES EL MÁS VALIOSO: `build-state.json` guarda sus nodos POR NOMBRE, y
cuando un nombre vive en dos colas la membresía se consulta por el par `(cola, nombre)` de UNA sola
de ellas. Resultado: `ffmpeg`, `alsa-lib`, `vulkan-headers` y `zlib-shared` reportaban
`perfiles: []` —o sea "no está en ninguna imagen"— **mientras estaban en las cuatro**. Ahora dicen
la verdad, y `escritorio-kde` pasa de 183 a 185 porque aparecen dos nodos que el grafo no contaba.

La lección para el próximo análisis, que ya quedó en `scripts/vigia-sonames.py`: sobre el grafo se
pregunta con `yupana.membresia()`, que llavea por `(cola,nombre)`; el campo `perfiles` del JSON es
fiable sólo mientras el nombre viva en una sola cola.

Sin cambios en la deuda: cosmic sigue 105/106 por el OOM de xdg-desktop-portal-cosmic.
2026-09-03 05:13:21 +00:00
Sergio 5e6b3631e2 pipewire ×3: ALSA pasa a ser la ABI de audio de la distro — el flag no alcanzaba
Las tres recetas pasan a `-Dpipewire-alsa=enabled`. Sirve a TODA app ALSA del corpus, no sólo a mpv:
un cliente que abre "default" desemboca en PipeWire por `libasound_module_pcm_pipewire.so` en vez de
pelearle la tarjeta al servidor. Es protocolo en vez de ABI compartida — la misma figura con la que
el ADR 0015 cruza el borde de la jaula.

EL FLAG SOLO NO HACE NADA, y ésta es la parte que no se ve venir: meson deja los plugins en
`/usr/lib/alsa-lib` (bien, ahí los busca alsa-lib) pero la CONFIGURACIÓN en
`/usr/share/alsa/alsa.conf.d`, **un directorio que alsa-lib no lee**. Sus `@hooks` cargan
`/var/lib/alsa/conf.d`, `/usr/etc/alsa/conf.d` y `/etc/alsa/conf.d` — leído del `alsa.conf` del
artefacto sellado, no supuesto. Sin el enlace que agrega la fase install, el plugin queda instalado
y no lo usa nadie: sellado e inerte, que es la familia de fallo del artefacto vacío. Se enlazan los
DOS ficheros: `50-pipewire.conf` hace que el destino EXISTA, `99-pipewire-default.conf` hace que sea
el destino POR DEFECTO — sin el segundo, mpv abriendo "default" no llega igual.

EVIDENCIA (test discriminante, porque "no falla" no prueba nada acá):
  mpv --audio-device=alsa/pipewire  → abre el device, falla al conectar (no hay demonio) ⇒ el PCM
                                      ESTÁ DEFINIDO
  mpv --audio-device=alsa/noexiste  → "ALSA lib: Unknown PCM noexiste"  ⇒ el control
El camino de verdad —que suene— sólo se puede ejercer con un PipeWire vivo, o sea en la sesión; eso
no se probó y no se afirma.

⚠ PRECIO, escrito para que no se diagnostique mal: con `99-pipewire-default.conf` puesto,
`pcm.!default` ES PipeWire. En una máquina donde PipeWire no esté corriendo, un cliente ALSA ya no
cae a la tarjeta: no suena. Es el trato que hace toda distro con pipewire-alsa.

Radio medido antes de tocar (`yupana radio pipewire`): 4 cosmic / 3 gnome / 2 kde. Reconstruidos 10
de 11 dependientes.

⚠ DEUDA DECLARADA, 1: `incoming-cosmic/xdg-desktop-portal-cosmic` murió DOS VECES por OOM (7 G de
RAM, sin cgroups, y otro agente compilando Rust a la vez — `dmesg` confirma «Out of memory: Killed
process (cargo)»). No es un fallo de la receta ni del cambio: es la máquina. Queda visible en el
grafo (escritorio-cosmic 105/106) en vez de escondido, y lo levanta el worker o un reintento con la
máquina libre.

Los otros tres perfiles cierran: KDE 183/183, GNOME 132/132, sway 140/140.
2026-09-03 05:11:47 +00:00
Sergio 9a2739f856 estado: cosecha granja 2026-09-03T04:02:45Z — avance del árbol KDE 2026-09-03 04:02:45 +00:00
Sergio 9a7e7bc17f estado: cosecha granja 2026-09-03T03:32:28Z — avance del árbol KDE 2026-09-03 03:32:28 +00:00