3ffca7c7fe4502bd9f9050fb6fc0c2e9e79618c2
770
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
3ffca7c7fe |
firefox: pasa a compiler=gcc — zig-cc choca con una negativa de upstream
Tercer fallo de configure, y el que decide: «Firefox does not support linking statically with libstdc++». No es un flag. flags.configure:79 compila un C++ mínimo, lo pasa por llvm-objdump --private-headers y EXIGE encontrar un `NEEDED …libc++`; zig enlaza libc++ estática para musl, así que ese NEEDED no existe nunca. Es una negativa de Mozilla, no una opción. Cambiar a gcc derriba los tres muros que zig-cc levantó, de una vez: 1. el sondeo del linker (gcc se anuncia como «GNU ld», que Firefox reconoce), 2. «Cannot find ar» (hay un ar de verdad; se quitan los wrappers de zig), 3. libstdc++ COMPARTIDA — el gcc del lab es 15.2.0 con libstdc++.so.6. Es una excepción consciente y del mismo tipo que la que el repo ya mantiene para el kernel y cmake (ADR 0011), a la que se llegó por eliminación y no por comodidad: los tres intentos con zig-cc están documentados en la cabecera. ⚠ El precio queda escrito en la receta: el lab NO entra en hash_inputs, así que un Firefox construido con el gcc del lab queda más expuesto a la deriva del rootfs que uno con zig-cc — dos labs con gcc distinto pueden sellar bytes distintos sin que el store lo note. Misma deuda que ya cargan el kernel y las otras recetas compiler=gcc, y razón para no ampliar esa lista sin agotar antes el camino zig. |
||
|
|
61143203f9 |
firefox: wrappers de ar/nm/ranlib — zig los trae como subcomandos
Segundo fallo de configure: «ERROR: Cannot find ar». moz.configure hace
check_prog("AR", …) y en el sandbox no existe un ejecutable llamado `ar`: existe
`zig ar`. Un AR="zig ar" con espacio tampoco sirve, se ejecutaría como un binario
único llamado «zig ar» — el mismo gotcha que ya documentan la receta de ffmpeg y
el de los crates cc en las recetas Rust.
Wrapper de UN SOLO TOKEN por herramienta (ar, ranlib, nm, objcopy), que es el
patrón ya establecido en el corpus, exportados en configure Y en compile porque
las dos fases los necesitan.
El linker ya pasó: este fallo es posterior, lo que confirma que quitar
--enable-linker fue correcto.
|
||
|
|
2fd738bf82 |
firefox: quitar --enable-linker=lld — el sondeo de Mozilla no reconoce a zig
Primer intento de build: configure murió con «Could not use lld as linker».
NO era que faltara lld. toolchain.configure sondea con
`$CC -fuse-ld=lld -Wl,--version` y clasifica por la SALIDA, buscando «mold»,
«GNU ld», «GNU gold» o «LLD». zig se identifica como `zig ld 0.16.0`, que no casa
con ninguno ⇒ kind = "unknown".
«unknown» por sí solo NO rompe: el código lo acepta explícitamente. Lo que rompe
es PEDIR el linker por nombre, porque eso vuelve fatal cualquier fallo del sondeo:
if linker: result = try_linker(linker)
if result is None: die("Could not use %s as linker")
Sin el flag, unas líneas más abajo Firefox prueba lld igual —c_compiler.type es
clang y la versión 21.1.0 pasa el umbral de 15.0— y si el sondeo falla sigue a
gold y al linker por defecto, que es exactamente el lld que zig trae adentro.
Mismo linker, sin el die.
Diagnóstico hecho leyendo toolchain.configure en el árbol del worker, no
suponiendo: el comando sondeado devuelve rc=0 y sí imprime la versión cuando se
corre a mano.
|
||
|
|
90364fabbf |
nodejs y firefox: strip_debug — medido, no supuesto
El nodejs que selló en el LXC sin strip pesa 984 MB, de los cuales .debug_info son 497 MB y .debug_line otros 43: MÁS DE LA MITAD del artefacto es información de depuración, para una herramienta que nadie va a depurar y que ni siquiera se publica. Se aplica también a firefox ANTES de construirlo, que es donde importa: Firefox es varias veces V8 y sin strip su artefacto entraría en varios GB. El store no es sólo disco — se sincroniza hub↔worker y se respalda. Es el hallazgo del SDD 23: el 79% del contenido binario del store era .debug_*, y quitarlo hace que artefactos que no reproducían PASEN a reproducir, porque lo que difería eran las rutas del árbol de build embebidas en esas secciones. El campo entra en hash_inputs a propósito (cambia el contenido) y usa zig objcopy, que siempre está en el sandbox ⇒ no agrega dep de build. Node se reconstruye. |
||
|
|
428be5e8d1 |
firefox 154.0 — la cabeza de la familia Gecko (receta, sin construir todavía)
154 y no 155 pese a que Zen sigue 155.0.1 y Waterfox también va por release: los
parches de musl de Alpine son para 154.0, y son ONCE. Ese es el trabajo de
portabilidad que un import de nix pierde y sin el cual Firefox no compila contra
musl. Un Firefox que compila con el set probado vale más que uno con el número
correcto que no compila; y como Firefox se mueve cada 4 semanas, la paridad exacta
con Zen es una cinta de correr. Lo que se reutiliza entre los tres es la
PLATAFORMA (gtk3/nodejs/clang18/cbindgen, ya en el corpus) y este set de parches.
Subir a 155 después es un rebase, no un port.
Se traen los 11 de musl y NO los de ppc64le, loongarch ni Android: cada parche que
no hace falta es una forma más de que un rebase falle sin motivo.
TODO BUNDLEADO salvo GTK3. Alpine usa --with-system-{icu,nspr,nss,av1,libvpx,
webp,libevent} y de ésas el corpus tiene cero; Firefox las trae en el árbol.
Menos piezas móviles para el primer build, que es cuando conviene minimizar
variables.
SIN BRANDING OFICIAL, y no es descuido: el binario lleva once parches, y poner el
nombre y el logo de Firefox sobre un build modificado entra en la política de
marcas de Mozilla — es la historia de Iceweasel en Debian. Misma cautela que
dejavu-fonts-nerd con la licencia de Bitstream Vera: una fuente modificada no
puede llamarse como la original, y un navegador parcheado tampoco.
HERMÉTICO: --disable-bootstrap (su trabajo es descargar toolchains),
MACH_BUILD_PYTHON_NATIVE_PACKAGE_SOURCE=system (si no, mach arma un virtualenv con
pip y sale a la red) y MOZBUILD_STATE_PATH al árbol (por defecto escribe en $HOME,
que en el sandbox no es suyo). Los crates vienen vendorizados en el tarball.
Wayland-only heredado de gtk3 (-Dx11_backend=false) ⇒ este Firefox NO correrá como
cliente X11 ni bajo Xwayland. Escrito en las dos recetas.
|
||
|
|
9c657efe61 |
plataforma Gecko: nodejs 24.18.1 — ./mach configure lo exige
Firefox aborta con «Could not find a Node.js executable»: lo usa para empaquetar los bundles de JS. Waterfox y Zen lo necesitan igual ⇒ al corpus con el resto de la plataforma. TODO BUNDLEADO, a diferencia de Alpine, que lo construye contra diez deps del sistema de las cuales el corpus tiene dos. La decisión de fondo: acá Node es un COMPILADOR, no software que la distro publique — entra al sandbox de Firefox y desaparece, así que el cierre chico gana al cierre puro y el precio (binario gordo, openssl bundleado que nadie expone) no lo paga ningún usuario. Si algún día se quiere PUBLICAR Node, esa es otra receta; queda avisado en la cabecera. Dos AVX-512 apagados, y los dos por la perilla que upstream mismo deja: · simdjson → SIMDJSON_AVX512_ALLOWED=0. ⚠ EN EL .h Y EN EL .cpp: la librería se distribuye AMALGAMADA y el .cpp lleva su propia copia (línea 2493), así que tocar sólo el header no sirve — y engaña, porque ninja sigue con otros objetos y el log parece avanzar. · simdutf (dentro de V8) → se antepone SIMDUTF_IMPLEMENTATION_ICELAKE 0, que es el override que habilita su #ifndef. No se pierde nada: todo el corpus va -mcpu=baseline y ambas eligen implementación en RUNTIME. CXXFLAGS NO sirve acá — GYP no lo propaga a la línea de compilación (verificado buscando el -D en el comando que ninja reportó al fallar). EL PARALELISMO SE CAPA POR RAM Y SIN ESCRIBIR UN NÚMERO. Sin cap, ninja lanza nproc+2 y muere con `job terminated due to signal 9` en el objeto 2936/4414 compilando lo que genera Torque (~2 G por job). Un `-j2` fijo ataría el ArtifactHash a la RAM de quien escribió la receta; la cuenta es un job cada 3 GiB de MemTotal, mínimo 1, tope nproc. Da 2 en momento (7,6 GiB) y 5 en el LXC (16 GiB, 6 cores) con el MISMO texto y el mismo hash. |
||
|
|
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. |
||
|
|
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. |
||
|
|
7c58f6b62e |
plataforma Gecko: atk + GTK3 Wayland-only — la base que comparten Firefox, Waterfox y Zen
GTK3 no existía en NINGUNA cola y es el único toolkit de Gecko en Linux. Como Waterfox y Zen son forks de Gecko, los tres navegadores consumen exactamente esta misma pieza: una receta sostiene a los tres. Por eso va al CORPUS y no a una cola —una receta resuelve sibling-first y después el catálogo padre, nunca una cola hermana—, que es la lección de mpv y justo lo que OBS no pudo cumplir al quedar atado a incoming-kde por Qt6. La plataforma nace bien puesta para que los tres navegadores no repitan ese error. Al medir el cierre antes de escribir, TODO estaba ya en el corpus salvo `atk`. Un ladrillo chico destrabando una pieza grande: por eso atk fue primero. WAYLAND-ONLY de verdad, no de intención: -Dx11_backend=false. A diferencia de OBS —que exigía find_package(X11) incondicional— GTK3 sí deja apagarlo, y eso saca libX11/libXext/libXi/libXrandr/… del cierre. Esa cadena vive sólo en incoming-kde y meterla en el corpus la pondría en las CINCO imágenes. Verificado en el artefacto: los .pc son gdk-wayland-3.0 y gtk+-wayland-3.0 (no hay gdk-x11-3.0), libgtk-3.so.0 no enlaza X11 ni xcb, y libgdk-3.so trae NEEDED libwayland-client/cursor/egl + libxkbcommon. ⚠ Consecuencia escrita en la receta: un Firefox contra este GTK3 no correrá como cliente X11 ni bajo Xwayland. Bajo Wayland nativo sí. Es la postura de la distro aplicada al navegador, no un accidente. Las deps van a las variantes -shared EN LUGAR DE las estáticas, nunca junto a ellas: libgtk-3.so es un objeto compartido y un .a sin PIC adentro da `relocation R_X86_64_32 against png_default_write_data`. Se sustituye y no se suma porque ambas variantes instalan los MISMOS .pc y cabeceras — declarar las dos serían dos artefactos peleando por lib/pkgconfig/glib-2.0.pc. |
||
|
|
670a5b6b49 |
OBS Studio 32.2.2 — segunda app gráfica de usuario final, con el renderer portado a EGL
13 plugins sellados, entre ellos los que importan: linux-pipewire (captura de
pantalla en Wayland), obs-ffmpeg, obs-x264, obs-outputs (RTMP RTMP),
linux-pulseaudio/alsa y text-freetype2.
EL PORT. El glad de OBS hacía dlopen("libGL.so.1") + dlsym("glXGetProcAddressARB")
y devolvía 0 si no lo hallaba, o sea que el renderer no arrancaba: OBS estaba
atado a GLX —y por tanto a X11— aun corriendo en Wayland puro. Acá nadie publica
libGL.so.1 y el libglvnd del corpus va sin GLX a propósito. El parche carga por
libEGL.so.1 + eglGetProcAddress, que es lo que OBS ya usa para las extensiones.
Verificado en el artefacto, no en el log: libobs-opengl.so.30 tiene CERO
ocurrencias de glXGetProcAddressARB, sus NEEDED son libEGL.so.1 +
libwayland-egl.so.1, y el binario no filtra a glibc.
DÓNDE VIVE. En incoming-kde y no en el corpus porque su frontend es Qt6 y las 13
recetas Qt viven sólo en esa cola. Se midió antes de descartar el corpus: qtbase
sin X11 cierra en 26 nodos que YA están en el corpus, pero el qtbase de la cola va
xcb=ON, así que un qtbase de corpus tendría otro hash con el MISMO nombre de
artefacto ⇒ dos Qt peleando por /usr/lib/libQt6Core.so. Unificar obligaría a
apagarle xcb a KDE: radio 119.
Los símbolos indefinidos salieron por CAPAS y ninguno nombraba al culpable:
freetype (.a no PIC) → fontconfig (idem) → i2d_SSL_SESSION → inflateInit_. Las dos
primeras se arreglaron usando las variantes -shared que YA existían en el corpus;
las dos últimas con -lssl -lcrypto -lz, porque OBS resuelve curl con el FindCURL
de CMake, que toma libcurl.a por fichero y no lee su Libs.private. Un símbolo
indefinido nombra a la librería que lo USA, no a la que falta.
Huecos escritos en la receta para que no se descubran en la mano del usuario:
sin webcam (ENABLE_V4L2=OFF, libv4l2 no está en ninguna cola), sin salida MPEG-TS
(SRT/RIST ausentes) y sin scripting (falta swig). Grabar, capturar pantalla y
publicar por RTMP no pasan por ninguno de los tres.
|
||
|
|
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. |
||
|
|
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. |
||
|
|
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.
|
||
|
|
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.
|
||
|
|
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. |
||
|
|
269e8410fd | estado: cosecha granja 2026-09-04T15:02:12Z — avance del árbol KDE | ||
|
|
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. |
||
|
|
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
|
||
|
|
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 |
||
|
|
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 |
||
|
|
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
|
||
|
|
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
|
||
|
|
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
|
||
|
|
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
|
||
|
|
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
|
||
|
|
058e3e9206 |
recetas: girara, xxhash y json-glib al corpus — la cadena de zathura, medida
⚠ CORRIGE UNA CREENCIA DEL REPO: zathura NO está bloqueada por GTK3. Upstream VACIÓ girara — en 2026.07.18 su árbol son siete .c (datastructures, input-history, log, template, utils) y su meson.build no menciona GTK ni una vez. Toda la UI se mudó adentro de zathura, que hoy pide GTK4 >= 4.12, y gtk4 4.18.6 está en el corpus. El plan de apps daba a zathura por «verificar si su cadena es GTK4 y no GTK3»: lo es. Las tres piezas que faltaban, medidas con scripts/provee.py --desde corpus: - girara: sella al primer intento; sus tres deps (glib/gobject/gio) salen del mismo artefacto glib. -Ddocs=disabled porque ese target es doxygen y produce HTML de API. - xxhash 0.8.3 (zathura lo usa para la caché de páginas). DISPATCH=0 no es preferencia, el build se cae sin eso: Makefile:58-62 hace `$(CC) -dumpmachine | grep x86_64` y enciende DISPATCH solo por detección de arquitectura — una perilla auto que hace depender el artefacto de dónde se construyó. Con ella, xxh_x86dispatch.c muere porque pide AVX-512 con -mavx512f a secas y el clang de zig ya exige además -mevex512 («AVX vector argument of type __m512i without evex512 enabled changes the ABI»). No se arregla subiendo flags: esa variante sólo la usa el despacho en runtime, que es justo lo que no queremos. Apaga las dos cosas de una. - json-glib PROMOVIDA al corpus, y salió GRATIS por la misma razón que pipewire: la variante de COSMIC resuelve sus deps enteras contra el catálogo padre ⇒ mismo ArtifactHash desde las dos partes (b3:62011e81, medido antes de mover nada). La de GNOME no podía: arrastra gobject-introspection, glib-introspected, gi-foreign-girs y py3-setuptools. La copia de incoming-cosmic se jubila, verificado como manda el repo: su único consumidor (xdg-desktop-portal) hashea b3:749fbffe ANTES y DESPUÉS ⇒ cero rebuilds. La de incoming-gnome SE QUEDA: variante deliberada, artefacto distinto. Falta todavía el backend de PDF, que es el hueco real: incoming-kde/poppler va con -DENABLE_GLIB=OFF ⇒ publica libpoppler.so pero NO poppler-glib, y encima sólo se alcanza desde su cola. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XB2iEmxeLZgzqNfhWChrLo |
||
|
|
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 |
||
|
|
2d68e70a07 |
recetas: luajit 2.1 (rolling) — el intérprete que swayimg 5.x exige y mpv prefiere
Tercer Lua del catálogo y hay razón para cada uno: `lua` 5.4 para wireplumber,
`lua5.2` para el OSC de mpv, y ésta porque hay consumidores que piden LuaJIT POR
NOMBRE — swayimg >=5.0 hace dependency('luajit') sin alternativa. No es la misma ABI:
LuaJIT es Lua 5.1 + FFI + JIT. Convive sin pisar: todas sus rutas ya vienen
versionadas (include/luajit-2.1, libluajit-5.1.so.2, /usr/bin/luajit-2.1.<relver>).
⚠ EL PIN DE COMMIT NO ALCANZA. Desde que 2.1 es rolling no hay tags: la versión sale
de `git show -s --format=%ct` sobre el árbol, y NO es cosmética — entra en un SÍMBOLO
EXPORTADO (luaJIT_version_2_1_ROLLING). Dos builds del mismo commit con distinto
estado de .git publican símbolos distintos y el consumidor muere con símbolo
indefinido. Se escribe .relver a mano Y se borra .git, porque la rama que consulta git
gana si el directorio existe. Verificado: nm -D da luaJIT_version_2_1_1787165859.
LIBS=-lunwind: la misma deuda que ya paga librsvg. Sin esto, nueve _Unwind_*
indefinidos desde lj_err.o — LuaJIT usa unwinding DWARF de verdad y en glibc ese
runtime vive en libgcc_s, que musl no tiene. Va por LIBS= y no LDFLAGS= porque
TARGET_ALIBS se expande DESPUÉS de los objetos, que es donde el linker resuelve.
TARGET_STRIP=true: su Makefile strippea como parte de la compilación, lo que pediría
binutils y borraría el .debug_* antes de que hammer lo parta (SDD 23).
Evidencia de que anda: NEEDED = libc.so y nada más; jit.status() da true con todas las
optimizaciones; FFI llama a C; y los cuatro caminos de unwinding responden — pcall,
error DENTRO de un trace compilado (err_unwind_jit, el que pedía _Unwind_GetIP),
metamétodo y xpcall+traceback.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XB2iEmxeLZgzqNfhWChrLo
|
||
|
|
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 |
||
|
|
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. |
||
|
|
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. |
||
|
|
3448ca4678 | estado: cosecha granja 2026-09-03T06:02:15Z — avance del árbol KDE | ||
|
|
f04364fc06 |
pipewire al corpus: falta el parche, que quedó fuera del commit ajeno y dejó la receta rota
⚠ INCIDENTE, y queda escrito porque es la regla 2 del CLAUDE.md en vivo: los cuatro `git mv` de esta promoción (pipewire, pulseaudio, libsndfile, dbus-shared) estaban STAGED y sin commitear cuando `89da9c8` («qorpa: el mapeo por rango») se los llevó puestos. El commit ajeno barrió el índice de otro agente — exactamente lo que la regla prohíbe— y encima lo hizo A MEDIAS: se llevó los cuatro `.toml` pero no el `.patch`, porque el `git mv` del parche se cortó cuando el disco se llenó al 100%. Resultado: HEAD quedó con `recipes/pipewire.toml` declarando `patches = ["pipewire-sound- initialized.patch"]` y ese fichero **inexistente en `recipes/`**. Cualquiera que clonara veía `Error: receta inválida: no pude leer patch`. Esto lo repara. El hash confirma que la promoción es gratis: `recipes/pipewire.toml` sella b3:e240653adae656318d5c3445b36ffb37aa491589b5c34c8688515bc3806944ab, EXACTAMENTE el mismo que tenía `incoming-cosmic/pipewire`. Era la variante que ya resolvía todo su cierre contra el catálogo padre. |
||
|
|
89da9c822f |
qorpa: el mapeo por rango — subuid + --userns FD, y el impuesto se paga
Resuelve §NO-resuelve 2 del ADR 0015, que era el ticket que más desbloqueaba. Tres síntomas que parecían distintos —apt sin poder bajar a `_apt`, pacman sin poder chownear a `alpm`, pressure-vessel sin poder escribir su uid_map— eran la misma causa: bwrap crea el userns con UN SOLO id. La cura resultó tener TRES partes, y ninguna sobra: 1. `setcap cap_setuid+ep newuidmap` (+ cap_setgid en newgidmap). shadow.toml los instala pero no los provisiona; sin la capability no escriben el mapa. 2. Crear el userns nosotros, mapear el rango de /etc/subuid con newuidmap y pasárselo a bwrap con `--userns FD`. bwrap crea el suyo con un solo id A PROPÓSITO y nunca llama a newuidmap: el trabajo es de quien lo invoca. El fd lo abre la shell (`exec 3<…`), porque un fd sólo cruza el exec si no es CLOEXEC y no valía la pena una dep de C para un fcntl. 3. Devolver las capabilities DENTRO del namespace. Ésta no estaba en el plan y es la que costó: bwrap las tira todas, y en Linux ser root es tener CAP_SETUID, no tener uid 0. Sin ella apt seguía sin poder seteuid(42) — un síntoma que parecía de subuid y no lo era. Son seguras por construcción: dentro de un userns sólo alcanzan lo que ese namespace posee, o sea nuestros propios subuid. CAP_SYS_ADMIN queda fuera y sigue colgando de `nesting`. MEDIDO después: uid_map de 65537 ids, setgroups: allow, apt instala SIN el APT::Sandbox::User=root, pacman sincroniza con DownloadUser=alpm INTACTO, y el userns anidado monta con root=true ⇒ el conflicto 2 de D9 se disuelve solo. Dos cosas más que salieron por medir, no por pensar: - El guardián MENTÍA. qorpa-preflight envolvía al hijo en `timeout`, que forkea, así que newuidmap apuntaba al PID equivocado y el kernel respondía "Operation not permitted" — un falso negativo idéntico a un fallo real. Decía que subuid no andaba cuando a mano andaba. Ahora sale exit 0. - Quitar el impuesto MUEVE el problema: el upper pasa a contener ficheros de los subuid (apt deja los suyos con uid 165577) que nuestro uid no puede borrar ⇒ recreate entra a un userns mapeado para limpiar. Y cuando no hay rango, se degrada diciendo la causa exacta en vez de quedar en misterio. Y un detalle que no es cosmético: `--perms 1777` antes del `--tmpfs /tmp`, o el _apt al que apt baja no puede escribir su fichero temporal. Un /tmp que no es 1777 no es /tmp. 2 tests nuevos (el rango se lee por usuario; CAP_SYS_ADMIN NO está en las caps de root, o `nesting` dejaría de ser una decisión). 45/45. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U5cQtQrYNjWJVXVE6aEpQ2 |
||
|
|
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. |
||
|
|
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.
|
||
|
|
032aa02582 |
lua5.2 5.2.4: mpv gana el OSC — la barra, las estadísticas y la consola
El OSC de mpv es `player/lua/osc.lua`: sin Lua el reproductor anda y responde al teclado pero NO DIBUJA NADA de interfaz. La `lua` del corpus no sirve — `meson.build:701` acepta 5.1, 5.2 o LuaJIT y el `lua.pc` genérico va acotado a `>=5.1.0, <5.3.0`; la nuestra es 5.4.8 y entró para wireplumber. CÓMO CONVIVEN LAS DOS SIN PISARSE, que es lo que hace legítimo tener dos Lua: esta receta instala **sólo la librería**. Sin `/usr/bin/lua`, sin `luac` y sin `lua.pc` genérico — que son exactamente los tres ficheros que colisionarían si una imagen hidratara las dos. Las `.so` no colisionan porque el SONAME lleva la versión, y los headers van a `/usr/include/lua5.2/` porque los de 5.2 y 5.4 se llaman igual y dicen cosas distintas. La diferencia con 5.4 que muerde: en 5.2.4 `luaconf.h:43-49` hace que `LUA_USE_LINUX` implique `LUA_USE_READLINE` (en 5.4 eso vive en el target `linux-readline` del Makefile). Se esquiva construyendo el target `a` —sólo `liblua.a`— en vez de `all`: `LUA_USE_READLINE` lo consume nada más que `lua.c`, el binario del REPL, que acá no se compila. Sale gratis y de paso es lo que hace que no haya `/usr/bin/lua` que colisione. `-Dlua=lua5.2` y no `auto`: auto recorre ocho nombres de `.pc` y se lleva el primero que encuentre en el sandbox ⇒ el artefacto dependería de qué otra cosa quedó montada en el lab. EVIDENCIA, del mpv re-sellado (b3:d9072a10): List of enabled features: … libass libplacebo **lua5.2** … wayland [cplayer] Set property: user-data/osc/visibility="auto" -> 1 [cplayer] Done loading scripts. o sea que el script del OSC no sólo compiló: se carga y corre. alsa-lib: se corrige el comentario, que decía que las pipewire iban con `-Dpipewire-alsa=disabled`. Ya no. Y queda escrito el gotcha que costó encontrarlo: el `alsa.conf` que instala carga `/var/lib/alsa/conf.d`, `/usr/etc/alsa/conf.d` y `/etc/alsa/conf.d`, NO `/usr/share/alsa/alsa.conf.d`, que es donde meson deja la config del plugin. |
||
|
|
16e2be84d4 |
mpv 0.41.0: la primera app gráfica de usuario final del corpus
Cuatro escritorios que cierran y ninguna forma de abrir un video. El ADR 0015 ordenó los montones
y puso a mpv primero del A —lo que no tiene muro estructural, sólo falta escribirlo—. Éste es.
Sellada b3:8e6ab4e7. Evidencia de que ANDA, no sólo de que sella:
· `mpv --version` corre con el loader musl → v0.41.0, libplacebo v7.360.1, FFmpeg 7.1
· decodifica un h264 640x480 + AAC de prueba, 75 frames, `Exiting... (End of file)`
· `--vo=help` → `gpu-next` (libplacebo) y `gpu`; `--ao=help` → `alsa`
· `--gpu-context=help` → SÓLO `wayland` (Wayland/EGL). Ni un contexto X11 en el binario.
· NEEDED: libav*, libplacebo, libasound, libEGL, libc. Cero glibc, cero X11.
En el corpus y no en una cola: un reproductor lo quieren las cuatro imágenes, y una receta resuelve
sibling-first + catálogo padre, nunca una cola hermana.
`-Dbuild-date=false` no es cosmético: su default estampa la fecha de compilación DENTRO del binario
⇒ dos builds del mismo commit darían bytes distintos y el artefacto dejaría de reproducir.
`-Dprefer_static=true` (como foot) porque sin él meson resuelve los `.pc` sin `Libs.private` y el
link muere con símbolos `XML_*` sin definir «en libfontconfig.a» — culpando a fontconfig cuando lo
que falta es propagar expat.
Las ~90 opciones van EXPLÍCITAS: casi todas nacen `auto`, o sea que miran el sandbox y se prenden
con lo que encuentren. Misma trampa que ffmpeg cierra con `--disable-autodetect`.
TRES HUECOS CONOCIDOS, escritos en la receta para que no se descubran en la mano del usuario:
1. audio ALSA, y las tres pipewire llevan `-Dpipewire-alsa=disabled` ⇒ hoy no suena en un
escritorio con PipeWire vivo. Radio de darlo vuelta: 4/3/2. Es el próximo paso.
2. sin Lua ⇒ sin OSC. mpv 0.41 sólo acepta 5.1/5.2/LuaJIT y la del corpus es 5.4.8 (wireplumber).
3. sin vaapi ⇒ sin decodificación por hardware (libva está sólo en incoming-kde), y el ffmpeg
heredado va `--disable-x86asm` ⇒ tampoco SIMD.
|
||
|
|
2a84b8252a |
libplacebo 7.360.1: la librería de render de mpv, con los submódulos resueltos como recetas
`meson.build:29` de mpv la pide sin `required:` ⇒ es la segunda dep dura, junto con libass. EL PROBLEMA REAL NO ERA COMPILARLA, era que upstream le entrega CINCO 3rdparty por submódulo git y `[source]` de hammer no clona submódulos (sólo repo+commit o tarball+sha256). Resolución uno por uno: · glad + jinja + markupsafe → recetas del corpus (commit anterior), como el `py3-glad` de Alpine · Vulkan-Headers → sube al corpus, headers-only, hash idéntico (b3:7731a012) · fast_float → upstream lo guarda con `fs.is_dir` ⇒ su ausencia es camino soportado La sorpresa fue Vulkan-Headers: hace falta AUNQUE Vulkan vaya apagado. `src/vulkan/stubs.c` se compila siempre y hace `#include <vulkan/vulkan.h>` — los stubs de «Vulkan no disponible» también necesitan saber contra qué API no están. Dinámica y no estática: `src/convert.cc` compila siempre ⇒ el artefacto lleva C++ y arrastra su runtime. La `.so` se lo lleva puesto en vez de obligar a cada consumidor a pedir `-lc++`. Además es lo coherente con mesa y ffmpeg, sus dos vecinos en el cierre de mpv. Todas las perillas explícitas aunque el default sea `auto`: `auto` escanea el sandbox y activa lo que encuentre — el mismo no-determinismo que ffmpeg cierra con `--disable-autodetect`. Sellada b3:4346feca, con `pl_has_opengl=1` / `pl_has_vulkan=0` en el .pc y 8 símbolos `pl_opengl` exportados. Vulkan queda pendiente a propósito: el loader arrastra el stack X11 entero por los WSI y esta distro es Wayland-only ⇒ subirlo es una decisión con radio propio. |
||
|
|
bb3fdc2ca0 |
libass 0.17.5 + libunibreak 6.1: el renderizador de subtítulos que mpv exige sin opción
`meson.build:32` de mpv pide libass sin `required:` ⇒ no hay build de mpv sin esto. libunibreak es "opcional" para upstream (`default=check`) y obligatorio acá: sin él libass parte los renglones por espacios, que es justo lo que no sirve en japonés, chino o tailandés. Cuesta una receta leaf de C plano. `--enable-asm`: 234 símbolos SSE2/AVX2 en la `.a` sellada. Es la razón por la que `nasm` subió al corpus en el commit anterior. La lección de las deps, para la próxima receta que resuelva `.pc`: más de la mitad de `[deps]` no aparece en el `./configure`. La harfbuzz del corpus va `-Dglib=enabled` (por GTK4) ⇒ su `.pc` pide `glib-2.0`, que arrastra pcre2 y libffi. Y el fallo NO dice que falte glib: dice «Package requirements (harfbuzz >= 1.2.3) were not met», culpando a la lib que sí estaba. Selladas: libunibreak b3:a01fb6bd, libass b3:213df6b1. |
||
|
|
ecc6166dfe |
jinja2 3.1.6 + glad 2.0.8: el generador del loader GL que libplacebo trae como submódulo
libplacebo genera su `gl.h` con `python -m glad`, y glad le llega a upstream como submódulo git (`3rdparty/glad`). El `[source]` de hammer no clona submódulos —sólo repo+commit o tarball+sha256— así que glad entra como receta propia desde PyPI, que además pinea por sha256. Es lo mismo que hace Alpine con `py3-glad` como makedepend. Python puro las dos, mismo molde que `mako`/`markupsafe`: se copia el paquete a site-packages, sin pip ni wheel. jinja2 es dep de runtime de glad; markupsafe ya estaba en el corpus. El sdist de glad trae los XML de Khronos adentro ⇒ el generador no sale a la red, que es lo que lo hace usable dentro del sandbox hermético. Selladas: jinja2 b3:74a3aa9f (27 ficheros), glad b3:c1d773f2 (75 ficheros). |
||
|
|
681bb642c2 |
corpus: subir nasm, alsa-lib y ffmpeg desde las colas — los tres con hash idéntico
Primer paso del frente de apps (ADR 0015, montón A: mpv → OBS → Firefox). `mpv` va al corpus porque lo quieren las cuatro imágenes, y una receta del corpus resuelve sibling-first en `recipes/`: desde ahí NO alcanza `incoming-kde/` ni `incoming-cosmic/`. Sus tres deps de sistema vivían sólo en colas. Lo que hace que esto no sea duplicar: `hammer hash` da el MISMO ArtifactHash a cada par (nasm b3:3624bdd8, alsa-lib b3:73fb200a, ffmpeg b3:bfef7bf3), porque las deps que las colas les resolvían ya caían al catálogo padre. Cache hit, cero rebuild, y una imagen que arrastre las dos recetas hidrata UN artefacto en vez de dos peleando por la misma ruta. Verificado también que comentar la receta es gratis: las cabeceras nuevas no mueven el hash. |
||
|
|
520f1d5279 |
polkit (variante KDE) + polkit-qt-1 0.201.1: Plasma ya puede pedir autorización
Tercer y cuarto hueco de RUNTIME del triaje. Sin polkit-qt-1, Plasma no puede
elevar privilegios: ni montar un disco, ni cambiar ajustes del sistema.
Son DOS recetas porque hacía falta una segunda polkit. Hammer resuelve las deps
hermano→padre —la cola propia, después recipes/— y nunca cruza a una cola hermana,
así que la polkit de incoming-gnome es invisible desde incoming-kde. Y aunque se
viera no serviría: aquélla va con -Dintrospection=true contra glib-introspected,
que es la ISLA DINÁMICA del shell de GNOME (gjs importa gi://Polkit y necesita el
typelib). KDE enlaza las libs desde C++ y el typelib le sobra; traerlo obligaría a
meter gobject-introspection entero en la cola.
La nueva es homónima a propósito, mismo patrón deliberado que dbus (incoming-kde vs
raíz) y gmp (incoming-kde vs incoming-cosmic), con el mismo coste conocido:
store-gc no puede decidir por NOMBRE cuál de los dos sellados es el vigente. No la
renombré a polkit-kde porque el .pc que busca polkit-qt-1 es polkit-gobject-1, no
el nombre del paquete: renombrar sólo movería el problema al lector.
Radio medido antes de escribirla (yupana radio polkit): la de incoming-gnome tiene
6 dependientes transitivos y no se toca; la nueva, 0. Cero daño colateral.
Nada de esto necesitó descubrirse: glib-shared ya existía en la cola KDE y su
propio encabezado nombraba a polkit como uno de los motivos por los que se escribió.
── El guardián que sí hizo falta ────────────────────────────────────────────────
polkit-qt-1 sondea polkit con check_function_exists, que COMPILA Y ENLAZA. Si ese
enlace falla por algo del sandbox —y no porque la función falte—, cmake NO da
error: imprime «You have an older polkit-1 version» y define
POLKIT_QT_1_COMPATIBILITY_MODE. El build sella, el artefacto pesa lo esperado y la
autorización queda recortada sin que nadie se entere. La fase configure ahora
aborta si HAVE_POLKIT_SYSTEM_BUS_NAME_GET_USER_SYNC no llegó a 1 en el header
generado: polkit 127 tiene esa función, así que un 0 significa «el sondeo no pudo
enlazar», no «polkit es viejo». Pasó: no hay modo compatibilidad.
También va -DQT_MAJOR_VERSION=6 explícito. El default del CMakeLists es "5", y sin
la flag construiría bindings con otros nombres (polkit-qt5-1) que el dependiente
no encontraría hasta mucho después.
── Lo que esto NO enciende, a propósito ─────────────────────────────────────────
Los dos consumidores siguen esquivando polkit igual que antes:
· kauth construye con el backend polkit OPCIONAL apagado (cae al backend fake);
· plasma-workspace apaga el helper de Región&Idioma con -DGLIBC_LOCALE_GEN=OFF
-DGLIBC_LOCALE_PREGENERATED=ON, que es justo lo que evita el PolkitQt6-1
REQUIRED.
Encenderlos es otra decisión con su propio radio (plasma-workspace arrastra medio
escritorio). La pieza está puesta; la palanca no se toca sin pedirlo.
⚠ Y con las librerías viaja la postura de seguridad que ya declaraba
arje-polkit-compat: el demonio responde is_authorized=true a TODO. Estas libs son
la INTERFAZ que el escritorio espera, no la política. Queda repetido en las dos
recetas nuevas porque son las que ponen la pieza en manos del escritorio.
Las dos REPRODUCEN bit a bit (verificar-repro.sh 2/2). Los NEEDED de
libpolkit-qt6-core-1 son exactamente los esperados: Qt6DBus, Qt6Core,
libpolkit-gobject-1, gio/gobject/glib y libc.
corpus 788/788 · escritorio-kde 171/171 · grafo CIERRA · gate --check OK
Queda 1 wanted en KDE: xwayland — y ése no es deuda técnica sino una decisión
(X11 al tacho, Xwayland = compat opcional por-imagen, no en el core).
|
||
|
|
de660fc10f |
qqc2-breeze-style 6.7.2: el estilo QML de Plasma sellado — KDE pasa de 3 wanted a 2
Segundo hueco de RUNTIME del triaje de la frontera. Nadie lo pide para construir —por eso el escritorio sellaba completo sin él— pero sin este módulo los controles QML de Plasma (botones, sliders, combos, los menús de los applets y de los KCM) se dibujan con el estilo genérico de Qt. No lo reemplaza qqc2-desktop-style: aquél es el estilo de escritorio integrado con KStyle; éste es la implementación QML nativa de Breeze, la que Plasma 6 usa por defecto. Dos cosas que no eran obvias: 1. Se llama casi igual que el vecino y viene de otro tarball. qqc2-DESKTOP-style sale de Frameworks 6.27.0; qqc2-BREEZE-style sale del release de Plasma 6.7.2, el mismo de breeze/kwin/plasma-workspace. Copiar la URL del vecino da 404. El sha256 va contrastado contra el .sha256 que publica KDE al lado del tarball, no sólo contra lo que bajó acá: la primera descarga volvió con 0 bytes y su sha256 era el de la cadena vacía — un vacío que se lee como éxito. 2. La lista de deps no es la del vecino copiada: sale de la clausura de find_dependency de los KF6*Config.cmake que ya están en el store. Ese recorrido enseñó algo reutilizable: casi todo lo que esos configs piden (X11, XCB, Wayland, OpenSSL, BZip2, LibLZMA) vive dentro de un `if (NOT TRUE)` — la rama de build ESTÁTICO — y por lo tanto es código muerto en nuestro corpus, que compila KF6 dinámico. Por eso acá no hay libX11 ni xorgproto, coherente con Wayland-only. El find_package(X11) del CMakeLists raíz no es REQUIRED, así que falla en silencio sin romper el feature_summary(FATAL_ON_MISSING_REQUIRED). Confirmado a posteriori: los NEEDED del plugin son exactamente los 5 KF6 que la clausura predijo (KirigamiPlatform, IconThemes, ColorScheme, GuiAddons, ConfigCore) más Qt6 Quick/Gui/DBus/Core. La fase install verifica por CONTENIDO, no por presencia: qmldir de org.kde.breeze y de org.kde.breeze.impl no vacíos, Button.qml presente y el plugin de plataforma de kirigami instalado. Un módulo QML sin su qmldir ocupa disco y arranca con el estilo genérico sin decir nada. Salieron 83 controles y 3 .so. Selló al primer intento y REPRODUCE bit a bit (verificar-repro.sh 1/1). corpus 788/788 · escritorio-kde 166/166 · grafo CIERRA · gate --check OK Quedan 2 wanted en KDE: xwayland y polkit-qt-1. Nota sobre el diff de los cinco grafos: cambian los `dependientes_total` de las deps de esta receta en TODAS las vistas, no sólo en --kde. Es correcto y está documentado en build-state.py: ese campo se calcula sobre el grafo entero (todas las colas del disco), que es la corrección del bug de libdrm. |
||
|
|
a6beb3b28d |
shared-mime-info 2.5.1: la base MIME sellada — KDE pasa de 4 wanted a 3
Primero de los cuatro huecos de RUNTIME del triaje de la frontera. Ninguna receta lo pedía para construir (por eso escritorio-kde cerraba 163/163 sin él), pero sin la base el escritorio no sabe qué es un fichero: ni asociaciones, ni iconos, ni abrir-con. Qt6 y GLib lo leen los dos de /usr/share/mime. Vive en recipes/ y no en incoming-kde: es freedesktop puro, y en la raíz lo ven los cinco grafos (GNOME y COSMIC lo quieren igual — gdk-pixbuf hoy lo ESQUIVA con -Dgio_sniffing=false). Tres cosas que no eran obvias: 1. Fuente por GIT, no tarball. Freedesktop no publica downloads de release para este proyecto: la API sólo ofrece los -/archive/ autogenerados de GitLab, que no son estables byte a byte (mismo criterio ya escrito en wlr-randr). El pin es el tag 2.5.1 PELADO — acá el tag es objeto tag, la trampa de las 4 del mirror (ADR 0013). 2. i18n.merge_file de data/meson.build es INCONDICIONAL: no lo apaga -Dbuild-translations=false, porque es el paso que PRODUCE freedesktop.org.xml, el payload entero. Eso exige un msgfmt que entienda --xml. El de gettext-tiny sirve y no degrada nada: desde 2.x el template ya es XML válido (las traducciones se marcan con reglas ITS externas, cero ocurrencias de "<_"), así que sin catálogos la salida de un msgfmt real ES el template. Verificado a mano: copia byte a byte de los 384036 del template. 3. meson install deja SÓLO el XML fuente. Los consumidores no leen ese XML: leen los índices que genera update-mime-database (mime.cache, globs2, magic, aliases, subclasses). Sin ese paso el artefacto pasa toda verificación de presencia y el escritorio sigue sin saber qué es un .png — la regla 3 del repo en su forma exacta. La fase install lo corre contra /out y verifica por CONTENIDO: mime.cache y globs2 no vacíos, image/png en types. Salieron 1038 tipos y 1448 globs. Nace con strip_debug = true y REPRODUCE bit a bit (verificar-repro.sh: 1/1, cero divergencias), caché binaria incluida. Estático, 0 NEEDED. corpus 788/788 sealed · escritorio-kde 165/165 · grafo CIERRA · gate --check OK Quedan 3 wanted en KDE: xwayland, polkit-qt-1, qqc2-breeze-style. |
||
|
|
390c6a5e5e |
llimphi-counter: pinear a v0.2.0 y arreglar el install — el corpus queda 787/787
Deja de ser una plantilla con `commit = 000…0`. Tres cosas, y las dos últimas
son el valor del commit:
1. PIN. `v0.1.0` era el tag que la versión declaraba y NO SIRVE: su `Cargo.lock`
está desincronizado con sus manifiestos en el propio repo, y `cargo vendor
--locked` se niega ("cannot update the lock file … because --locked"). No es
de hammer: el vendoreo del fetch arranca bien y muere DENTRO de cargo.
Comprobado con `cargo metadata --locked` en los tres refs — v0.1.0
incoherente, v0.2.0 y main coherentes. Se pinea v0.2.0, PELADO con ^{commit}
porque es objeto tag (93253cc2, no 0beb83b7).
=> Un tag no sirve como pin sólo por existir: hay que verificar que su
lockfile cierre.
2. El requisito de `vendor/` en la fuente que pedía el comentario quedó VIEJO:
hammer vendorea en el FETCH a partir del Cargo.lock, host-side, y por eso el
`--offline --locked` del sandbox se cumple. El repo no trae vendor/ en ningún
tag y aun así construye.
3. ⚠ FASE `install` PROPIA, obligatoria con `--example`. El default de Cargo hace
`find target/release -maxdepth 1 -type f -perm -100`, y cargo deja los
ejemplos en `target/release/examples/`. El find no encontraba nada, salía 0 y
**hammer selló un artefacto SIN BINARIO**: 22 min de compilación y un `sealed`
con sólo `.hammer/recipe.toml` dentro, 20K. `hash --check` decía SELLADO y el
grafo lo habría contado como al día.
No lo atrapa `Store::has` ni el guardián de vacíos de build-state, porque el
directorio NO está vacío — tiene el manifiesto. Es la regla 3 del CLAUDE.md en
su peor forma: un ausente falla a gritos, esto llegó al final diciendo que
todo fue bien. Por eso la fase lleva un `test -x` que hace ruidosa la
ausencia.
Verificado por contenido, no por el `sealed`: 17 M, usr/bin/llimphi-counter, ELF
pie, NEEDED = libc.so (dinámico, como la receta promete para un binario que
dlopea Vulkan/Wayland). El artefacto falso se podó y quedó en el ledger.
`version` pasa de 0.1.0 a 0.2.0 y NO mueve el hash: no está en hash_inputs (como
`license`). La identidad la da el commit.
Corpus: 787/787 SELLADAS, 0 deuda, 0 never. Gate --check OK, grafo CIERRA.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LykB7vw38b4Ck1Zij15RQ4
|
||
|
|
12c30ec9f9 |
gnome: la terna no es deuda, es alcance — a .deferred/ con el mapa corregido
gdm, gnome-session y gnome-settings-daemon salen de la cola y quedan aparcadas
en `recipes/incoming-gnome/.deferred/`, que es el mecanismo que el repo ya usa
(precedente: incoming-kde/.deferred/libXft.toml). El glob del worker es
TOP-LEVEL y el del grafo también, así que dejan de molerse cada ciclo y dejan de
contarse como deuda que nadie va a pagar. `targets.toml` ya no las lista desde
el 2026-08-07 («APARCADAS POR DISEÑO»); esto alinea el árbol con esa decisión.
Y el mapa que llevaban estaba mal en las dos direcciones:
1. «La terna GTK3» es un nombre engañoso: **GTK3 no es el muro**. GTK3 tiene
backend Wayland y se construye con -Dx11_backend=false. Autorarlo no habría
destrabado ninguna de las tres. Lo que bloquea de verdad:
- g-s-d 48.1: gtk+-x11-3.0 / x11 / xfixes INCONDICIONALES => imposible en
Wayland-only, no «pendiente».
- gnome-session 48.0: dependency('libsystemd', required: true) en meson:124
es una comprobación de pkg-config EN BUILD. arje-logind-compat no la
satisface y es a propósito — su receta explica que GNOME consulta login1
en RUNTIME por D-Bus y que no hace falta la C-ABI sd-login. Único camino:
parchear ese required a false, que es una decisión, no un arreglo.
- gdm: cuelga de gnome-session, y con mirada-greeter probablemente sobra.
2. La lista «FRONTERA» estaba VIEJA: ya existen libX11, libXfixes, xorgproto,
libXau/Xcursor/Xdmcp/Xext/Xi/Xrender/Xtst, libxcb (casi todas por KDE) y
polkit, upower, geocode-glib, libgweather. Cuatro de las ocho líneas de g-s-d
habían dejado de ser ciertas. Faltan de verdad: gtk3, libnotify y una
variante libcanberra-gtk3.
Verificado contra el TARBALL (sha256 = el del pin), no contra el comentario.
incoming-gnome queda en 79 recetas, sellado=79 deuda=0 nunca=0.
Gate --check OK, grafo CIERRA, escritorio-gnome sigue 119/119.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LykB7vw38b4Ck1Zij15RQ4
|
||
|
|
c29a4fcb9e |
gnome: retirar 8 copias de cola que sellan igual que el corpus
`fontconfig-shared`, `freetype-shared`, `libjpeg-turbo-shared`, `libpng-shared`, `libtiff-shared`, `libxml2-shared`, `libyaml-shared` y `zlib-shared` existían a la vez en `incoming-gnome/` y en `recipes/`, y las ocho daban el MISMO ArtifactHash que su gemela del corpus. Como la resolución de deps cae al padre cuando no hay hermano, quitarlas deja a las consumidoras resolviendo contra `recipes/` y con el mismo hash. Medido, no supuesto: se hashearon las 1144 recetas antes y las 1136 después, y de las 1136 supervivientes **0 cambiaron de hash**. No hay rebuild. Lo que NO se toca, y conviene que quede dicho porque se parece: - Las variantes de la ISLA DINÁMICA (glib, gtk4, gdk-pixbuf, pango, harfbuzz, graphene, libadwaita, json-glib, libusb, libxcvt, pipewire, pulseaudio, wireplumber, xdg-desktop-portal): mismo nombre, hash DISTINTO. Son sombras a propósito — la introspección de GNOME exige .so reales. - Las copias entre COLAS (alsa-lib, hwdata, xkeyboard-config, libdisplay-info, lcms2, icu4c, lua, nasm, fuse3, libsndfile, libelogind, hicolor-icon-theme, dbus-shared): también dan el mismo hash, pero NO sobran. Cada cola necesita su propio hermano para cerrar su clausura; borrar la de una rompe esa cola. No es el caso de onda-2, donde la cola entera duplicaba a otra. Y el criterio, otra vez: `pipewire` y `pulseaudio` son TEXTUALMENTE idénticas a las de COSMIC y sellan distinto, porque sus deps resuelven distinto según la cola. El fichero no dice la verdad; el hash sí. Gate --check OK, grafo CIERRA, escritorio-gnome sigue 119/119. La cola queda en 82 recetas (79 selladas + la terna GTK3) y sus 5 parches, todos en uso. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LykB7vw38b4Ck1Zij15RQ4 |
||
|
|
42db2dfb35 |
gmp: las dos recetas son variantes DELIBERADAS, no un duplicado — queda escrito
Yo mismo las reporte como "la misma clase de colision que onda1" y me pase: no
lo son. onda1 tenia una copia RANCIA del mismo build; esto son dos builds
distintos, cada uno correcto para su frente:
KDE link=dynamic --enable-shared --enable-cxx => libgmp.so + libgmpxx.so
COSMIC link=static --disable-shared => libgmp.a, sin C++
Las dos citan libqalculate y llegan a conclusiones opuestas sobre gmpxx.h, y las
dos tienen razon para su cola. Unificarlas romperia una de las dos.
Lo que compartir nombre SI cuesta es que hace ambigua la clasificacion de
store-gc: un artefacto rancio de una puede caer como SUPERADO porque la otra
tiene sellado vigente. La condicion es precisa y esta medida — solo hay riesgo si
el hash vigente de una NO esta sellado, y hoy las dos lo estan => exposicion
CERO. Antes de podar con nombres compartidos hay que comprobar ESO, no el nombre.
La salida, si algun dia molesta, es renombrar la dinamica a gmp-shared (la
convencion que el corpus ya usa: zlib-shared, cairo-shared...). No se hizo
porque cuesta: da 7 sellados de KDE que caen a deuda. es
el mismo par por la misma razon.
Los comentarios NO entran en hash_inputs (medido: mismo hash antes y despues),
asi que esto no re-hashea nada.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LykB7vw38b4Ck1Zij15RQ4
|
||
|
|
75b402d1bf |
deferred: system-libs.patch es de kalker — va con su receta
Al verificar la resolucion estricta de parches salio la unica referencia rota del arbol: `.deferred/kalker.toml` pide `system-libs.patch` y el fichero estaba en `recipes/`. Los patches se resuelven `base_dir.join(nombre)` sin fallback, asi que la receta nunca lo habria encontrado. No es una rotura nueva: `.deferred/system-libs.patch` no existio jamas (el importador dejo la receta en .deferred y el parche en recipes/). Y es inequivocamente de kalker — parchea `kalk/Cargo.toml` — ademas de que ninguna receta lo citaba desde recipes/, o sea que ahi era un huerfano. Ningun hash se mueve por esto. Referencias de parche: 95 resuelven, 0 rotas. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LykB7vw38b4Ck1Zij15RQ4 |