23bb79f2ea6db97e3e0ae6e309982450ca5df16f
689
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
23bb79f2ea |
gobetween: replace a illarion/udpfacade — la dep transitiva desapareció de internet
`github.com/eric-lindau/udpfacade` (que importa src/server/udp) ya no existe: GitHub da «Repository not found» y proxy.golang.org 404 para esa versión, así que `go mod vendor` moría y la receta era INCONSTRUIBLE. No se arregla subiendo de versión: master de gobetween pinea el mismo módulo. Se redirige con `replace` al único superviviente, illarion/udpfacade. ⚠ Apunta a MASTER (031998cc71fa), no al commit pineado. El original (d8c1c27add169599654f71a6c62d13cde1c51e50) SÍ existe como objeto en illarion —los forks comparten almacén y la API de GitHub lo muestra— pero NO es alcanzable desde ninguna ref, y `go` sólo resuelve pseudo-versiones alcanzables desde una ref. Comprobado: `unknown revision d8c1c27add16`. (`git fetch <sha>` sí lo trae; `go` no usa esa vía.) ⚠ SEGURO y comprobado, no supuesto: entre master y el commit pineado hay TRES commits y el diff entero es `udp.go` +2 y `udp_test.go` +2 —sólo la línea `// +build !windows`— más `udp_windows.go` nuevo con `// +build windows`. Para GOOS=linux el código compilado es IDÉNTICO, y esto construye x86_64-linux-musl. Va como PATCH y no como fase porque `vendor_go_deps` corre en el fetch (lib.rs:277), antes de las fases; los patches se aplican antes (lib.rs:224). Verificado: el patch aplica limpio sobre un checkout pristino, hammer sella, y el binario arranca e imprime su versión. |
||
|
|
c1466de9d6 |
rsync: subir 3.4.4 → 3.5.0 — upstream podó el tarball viejo
samba.org borró `rsync-3.4.4.tar.gz` (404) y en ese directorio ya sólo queda
3.5.0. Tampoco estaba en nuestro mirror, así que la receta era INCONSTRUIBLE:
la única fuente MUERTA del corpus según docs/state/fuentes-vigia.json (1164
vivas / 3 muertas; las otras dos son un 502 transitorio de savannah).
⚠ NO es «cambiar el sha256 para tapar un 404» (lo prohibido por ADR 0013): el
tarball es OTRO, con su versión y su hash propios. Provenance verificada de
verdad, no asumida:
gpg --verify rsync-3.5.0.tar.gz.asc rsync-3.5.0.tar.gz
→ Good signature from "Andrew Tridgell <andrew@tridgell.net>"
RSA key 9FEF112DCE19A0DC7E882CB81BB24997A8535F6F
Clave traída de keys.openpgp.org; su fingerprint coincide con el `issuer` del
.asc. El aviso «User ID not certified» es esperable (no hay web-of-trust acá);
la firma en sí es válida.
Comprobado ANTES de subir: las diez opciones de configure siguen existiendo en
3.5.0, `rrsync.1` sigue en la raíz, y dont-use-nobody.patch aplica limpio
(`patch -p1 --dry-run` sin rechazos).
Verificado: sella, artefacto de 3,3 M con rsync/rrsync/rsync-ssl, y el binario
responde `rsync version 3.5.0 protocol version 32`.
|
||
|
|
0a2f8916e6 |
python3: TRAE ssl — la causa era link=static, no openssl
CPython abortaba `_ssl` con «OPENSSL_THREADS is not defined, Python requires
thread-safe OpenSSL», y la receta lo daba por imposible sin rehacer openssl.
CAUSA RAÍZ, probada: no es openssl, es `link = "static"`.
`hammer-build/src/lib.rs:285` inyecta `LDFLAGS=-static`, y el Configure de
openssl (línea 1514) hace:
if (grep { $_ =~ /(?:^|\s)-static(?:\s|$)/ } @{$config{LDFLAGS}}) {
disable('static', 'pic', 'threads');
}
⇒ el propio `-static` apaga los threads en silencio. Añadir `threads` explícito
NO sirve (el disable() va después y gana): el configuration.h salía byte a byte
idéntico. Dentro del sandbox `configdata.pm` decía `thread_scheme => pthreads`
pero `THREADS_DEFINE=0`; fuera del sandbox, los mismos flags —y hasta con el
perl del corpus— SÍ definían el macro. La diferencia era el entorno.
`openssl-threads`: misma receta con `link = "dynamic"` (mantiene `no-shared`,
sigue emitiendo .a). Verificado: OPENSSL_THREADS definido y 36 símbolos
pthread_ reales en libcrypto.a.
VARIANTE y no tocar `recipes/openssl.toml`: de la canónica cuelgan los CUATRO
kernels (linux, linux-generic, linux-metal, linux-metal-dual) y la reproducción
bit a bit del 6.16.12 es un resultado cerrado; moverle el hash lo invalidaría,
más 125 sellados.
Además `ssl` entra en la asserción del install. Sin ese guardián se volvería a
sellar un intérprete mudo — que es justo como esto estuvo escondido meses.
Verificado: `checking for stdlib extension module _ssl... yes`,
_ssl.cpython-312-x86_64-linux-musl.so instalada, y el propio install imprime
`modulos opcionales: OK` importando ssl.
⚠ Mueve el hash de python3: 251 dependientes directos, ~369 sellados en los
cinco grafos (161 en KDE). Es el coste aceptado de la decisión.
|
||
|
|
5f6c062cd9 |
adwaita-hello, sourceview-hello, hammer-edit: añadir xz a [deps]
Con gtk4 ya sin objetivos compartidos, estas tres dejaron de fallar por PIC (0 errores) y pasaron a morir en el link con `unable to find static system library 'lzma'`. Misma causa que appstream: declaran `appstream` y `libxmlb` pero no `xz`, y `libxmlb.pc` trae `Requires: gio-2.0, liblzma, libzstd`. Al enlazar appstream estática necesitan la liblzma igual. Patrón `.pc Requires`→[deps]; `xz` va junto a `zstd`, que viene del mismo .pc. Con esto cierra la clausura ENTERA de gtk4 en el grafo del corpus, las 6 que colgaban de él: gtk4-hello, libadwaita, gtksourceview, adwaita-hello, sourceview-hello y hammer-edit — todas SELLADAS y con binario real. |
||
|
|
0d6796e319 |
gtk4: no construir NINGÚN objetivo compartido — la .so era el muro PIC
`gtk/meson.build` declara dos hermanos con llamadas explícitas —`static_library('gtk')`
y `shared_library('gtk-4')`— y por ser explícita, `-Ddefault_library=static`
NO la suprime: no hay flag. Esa .so era el único objetivo compartido que se
enlazaba, arrastraba CINCO archives sin PIC (libtiff, libfreetype,
libfontconfig, libjpeg, libpng16) y moría con 13930 `relocation … recompile
with -fPIC`. Un ejecutable puede enlazar una .a no-PIC; una .so no.
Se apagan con `build_by_default: false` + `install: false` vía dos seds
acotados por rango (tocan 1 de 10 y 1 de 3 `install: true` respectivamente).
⚠ `build_by_default: false` NO BASTA SOLO: ninja construye igual lo que algo
NECESITA. El primer intento falló exactamente así — `shared_module('printbackend-file')`
depende de `libgtk_dep` y el fuente avisa «The 'file' print backend cannot be
disabled» (está fuera de los `if` de cpdb/cups), así que devolvía la .so al
grafo y re-aparecían los 13930 errores. Por eso se apagan LOS DOS.
En todo el árbol hay 5 objetivos compartidos: libgtk-4.so, printbackend-{cpdb,
cups,file} y media-gstreamer; las flags ya quitaban tres, estos seds los otros dos.
No se borra la declaración de libgtk: `pkg_config.generate(libgtk)` la necesita
para emitir el .pc con `-lgtk-4`, que es el nombre del archive GORDO que fabrica
la fase install. Nada la enlaza: los usuarios de `libgtk_dep` son demos, tests,
testsuite, examples y los backends de impresión/media, todos desactivados.
Verificado: sella, 0 errores PIC, 0 .so enlazadas, targets 997→993. Artefacto
con gtk4.pc `Libs: -lgtk-4`, libgtk-4.a de 808 objetos y `gtk_window_new` como
símbolo T definido. Las colas wlr/gnome tienen sus PROPIAS recetas de gtk4.
|
||
|
|
b6bcdee006 |
dufs: añadir xz a [deps] — sys-crate de compresión exige liblzma
Quinta de la familia (appstream, cargo-deb, cargo-make, dprint). Sin `[deps]` el link muere con `unable to find static system library 'lzma'`. Pendiente de verificar en la próxima parada; el patrón está verificado tres veces. |
||
|
|
f14322bd6b |
dprint: añadir xz y bzip2 a [deps] — sys-crates de compresión
Falla con las DOS a la vez: `unable to find static system library 'lzma'` y `… 'bz2'`. La receta no tenía `[deps]`. Cuarta de la misma familia esta noche (appstream, cargo-deb, cargo-make): el lab trae el toolchain de Rust pero NO las libs C que los crates `*-sys` esperan del sistema. El arreglo va en [deps], NUNCA engordando el rootfs (regla de rootfs-laptop-worker-divergen). NO se añade en bloque a las 220 recetas Cargo sin [deps]: la mayoría construye bien y re-hashearlas invalidaría las ya selladas. Se arregla la que falla. ⚠ Pendiente de verificar como cargo-make en su momento; el patrón está verificado tres veces (appstream, cargo-deb, cargo-make selladas tras el mismo arreglo). Se verifica en la próxima parada. |
||
|
|
6a0f3a1afe |
cargo-make: añadir bzip2 a [deps] — un sys-crate exige libbz2 del sistema
`unable to find static system library 'bz2' using strategy 'no_fallback'`. La receta no tenía `[deps]`: el lab trae el toolchain de Rust pero no las libs C que los crates `*-sys` esperan del sistema. bzip2 está sellado y aporta /usr/lib/libbz2.a. Tercera de la misma familia esta noche: appstream (lzma vía el .pc Requires de libxmlb), cargo-deb (lzma vía lzma-sys) y ésta (bz2). El síntoma del linker es idéntico en las tres y el arreglo también. ⚠ PENDIENTE DE VERIFICAR: las otras dos se construyeron y sellaron antes de commitear; ésta no, para no parar el driver una vez por receta. Se verifica en la próxima tanda de reanudación. Si fallara, el patrón —no la receta— es lo que habría que revisar. |
||
|
|
7934a82e36 |
cargo-deb: añadir xz a [deps] — lzma-sys exige la liblzma del sistema
La receta NO tenía `[deps]` en absoluto. El lab trae el toolchain de Rust pero no las libs C que los crates `*-sys` esperan del sistema, así que el link moría con `unable to find static system library 'lzma' using strategy 'no_fallback'`. El log lo confirma: vendoriza y compila `lzma-sys v0.1.20`. Mismo fallo y mismo arreglo que `appstream.toml` de hace un rato, por vías distintas: allá liblzma entraba por el `.pc Requires` de libxmlb, acá por un sys-crate. El síntoma del linker es idéntico. Verificado: sella en 3m02s, artefacto de 4,6 M con un ELF real en /usr/bin/cargo-deb. Blast radius nulo: en deuda en los cinco grafos con 0 dependientes sellados. |
||
|
|
93e8fd9848 |
appstream: falta xz en [deps] — liblzma entra por el .pc Requires de libxmlb
libxmlb.pc → Requires: gio-2.0 >= 2.45.8, liblzma, libzstd
appstream declaraba libxmlb y zstd pero NO xz, así que el link moría con
`unable to find static system library 'lzma'`. Patrón `.pc Requires`→[deps].
Se veía primero en los binarios de tests/ (as-test_xml, as-test_validate…) y
appstream 1.0.5 NO tiene opción `tests` en meson_options.txt. Sedear
`subdir('tests')` —como ya hace la receta con docs/— habría tapado el síntoma
y dejado el fallo para los 4 dependientes, que enlazan appstream estática y
necesitan la liblzma igual.
Verificado: sella en 23 s, 0 errores de lzma, artefacto de 18 M / 97 ficheros.
Blast radius nulo: en deuda en los cinco grafos con 0 dependientes sellados.
El dependiente adwaita-hello pasa de fallar en 23 s a 3m33s y ahora muere en
gtk4 (libgtk-4.so contra libtiff/libfreetype/libfontconfig/libjpeg/libpng16
no-PIC), que es una decisión de arquitectura aparte y sigue abierta.
|
||
|
|
5044c9f1ca |
gdk-pixbuf: -Dgif=disabled — el único .so de la receta no podía enlazar libpng no-PIC
En 2.44 `gif` es opción propia con default `auto` y ya no cae bajo `others`. Sin declararla, el loader de GIF se construía como MÓDULO COMPARTIDO (`libpixbufloader-gif.so`, el único .so de los 14 targets; el resto son ejecutables), y una .so no puede enlazar una .a sin PIC: 1978 errores `relocation R_X86_64_32 ... recompile with -fPIC`, todos de /usr/lib/libpng16.a (que es --disable-shared). Coherente con la intención declarada de la receta —«solo PNG (leaf mínimo)»: jpeg y tiff ya se desactivaban; gif se coló por DERIVA DE VERSIÓN. Por eso el arreglo es la flag y NO `[deps]`: cambiar libpng→libpng-pic es la decisión de arquitectura que se descartó para el canónico el 2026-08-21, y que las colas wlr/gnome resuelven con SOMBRAS propias. Regresión CONGELADA, no fallo nuevo: se servía por cache-hit y sólo aparece al reconstruir. Tumbaba en cascada xdg-desktop-portal, gnome-desktop, gjs, gdm, gnome-session, gnome-settings-daemon y gnome-shell — todas fallando en 2-45 s por su dep, no por sí mismas. Verificado: sella en 12 s, 0 errores PIC, artefacto de 58 M con libgdk_pixbuf-2.0.a y ningún .so. Blast radius nulo: el canónico estaba en deuda con 0 dependientes sellados en los cinco grafos. |
||
|
|
f8f679d038 |
corpus: expat-shared y libffi-shared cierran la fuga al Alpine del lab
sway es `link = "dynamic"` A PROPÓSITO —un compositor dlopea los drivers DRI de mesa en runtime— y sale con doce NEEDED. Nueve los cubría la clausura (pixman, drm, evdev, input, udev, wayland-server, wlroots, xkbcommon, libc), porque esas recetas ya son dinámicas. Los otros tres —libz.so.1, libexpat.so.1, libffi.so.8— venían de recetas `--disable-shared`, así que NINGÚN artefacto sellado producía ese `.so` y el rootfs los resolvía contra el sysroot Alpine DEL LAB. POR QUÉ ERA PEOR QUE UNA DEP FALTANTE. Una dep ausente falla ruidosamente. Ésta no: el lab NO entra en `hash_inputs`, así que el store daba el artefacto por bueno mientras el binario sólo arrancaba en una máquina que tuviera Alpine debajo. La fuga era invisible para todo el sistema de medición. `zlib-shared` ya existía en el corpus y sólo faltaba declararla. `expat-shared` y `libffi-shared` son nuevas, calcadas del patrón: autotools con --enable-shared, sin el truco de --whole-archive que zlib-shared necesita porque SU configure aborta bajo zig cc. SONAMEs verificados contra lo que pide el ELF: libexpat.so.1, libffi.so.8, libz.so.1. Exactos. NO se tocó `link` en las canónicas: entra en `hash_inputs` y habría re-hasheado expat, libffi y todo lo que los lista en deps —fontconfig, dbus, mesa, glib, python3, los crates `-sys`— cientos de recetas selladas por libs que ya están bien. El nombre `*-shared` es distinto del canónico, así que conviven. Verificado antes de construir: recalculadas las 794 recetas, **0 hashes cambiados**, sólo las 2 nuevas. Van al CORPUS y no a incoming-wlr/ porque la resolución de deps es hermano→padre: una receta del corpus no ve una cola. Es donde ya viven zlib-shared, fontconfig-shared, freetype-shared… VERIFICADO CON PÍXELES, no con el log. Rootfs rehidratado desde cero (126/126), CERO ficheros de `.dev-fs/alpine`. Cero «Error relocating». La captura tiene el MISMO sha256 que la de las libs de Alpine: 177fea396caa9dca, 1280x720, 383 colores. Tercera vez que la evidencia sale bit a bit igual al cambiar la procedencia — la soberanía no costó ni un píxel. Perfil: escritorio-sway 126/128. Faltan strace (linux-headers del lab) y rsync (404 de upstream). QUEDA UN RESTO: el loader `/lib/ld-musl-x86_64.so.1` todavía se toma del host. `recipes/musl.toml` existe en el corpus pero está EN DEUDA y fuera de todo perfil — mismo agujero de declaración, un nivel más abajo. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016v9ozVm44p6DB7EMXeZK4o |
||
|
|
428ad80b24 |
wlr: fuentes y XKB DECLARADAS en el perfil — la captura sale bit a bit idéntica
`dejavu-fonts` y `xkeyboard-config` entran en `recipes/incoming-wlr/` y en las raíces de `escritorio-sway`. La clausura pasa de 123 a 125 y ambas ya estaban selladas: cero builds. POR QUÉ TENÍAN QUE SER RAÍCES Y NO PODÍAN LLEGAR POR CLAUSURA. Son DATOS, no binarios: ninguna receta depende de una fuente ni de un mapa de teclado para COMPILAR. El grafo puede seguir todas las aristas que quiera y no va a alcanzarlas nunca. Si no se declaran, no están — y el perfil sigue dando 100%, porque mide la clausura de las raíces declaradas. Copias BYTE-IDÉNTICAS a las de incoming-kde, a propósito. Ya había tres copias iguales de xkeyboard-config (kde, gnome, cosmic) y dos de dejavu-fonts (kde, cosmic); ésta es la cuarta. No se consolidan al corpus ahora porque eso toca las colas de otros tres frentes que otros agentes trabajan. Mantenerlas idénticas deja esa consolidación como un `git mv` trivial en vez de un merge: cuatro ficheros iguales se unifican de un tirón, cuatro casi-iguales exigen revisión. VERIFICADO de punta a punta, no por el log: rootfs rehidratado DESDE CERO con sólo lo que la clausura declara (123/123), y `sway-headless.sh` sin una línea de inyección manual de fuentes ni XKB. Cero errores de xkbcommon, cero de fcft. La captura resultante tiene el MISMO sha256 que la de ayer con todo inyectado a mano — 1280x720, 383 colores. La declaración es exactamente equivalente a la inyección, y el pipeline reproduce. Queda como deuda real (no de declaración): libz.so.1 / libexpat.so.1 / libffi.so.8, que sway pide por estar enlazado dinámico y el corpus sólo produce como `.a`. Y `fonts.conf` NO era deuda: lo trae el propio artefacto de fontconfig. Perfil: escritorio-sway 123/125. Los 2 que faltan son strace (choca con los linux-headers del lab) y rsync (404 de upstream), ninguno del escritorio. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016v9ozVm44p6DB7EMXeZK4o |
||
|
|
2b4999f682 |
libpng-pic: la variante que faltaba entre la estatica y la .so
gdk-pixbuf no sellaba, y las dos libpng del corpus fallaban por extremos
OPUESTOS — probadas las dos hoy, una detras de otra:
libpng .a sin PIC → «relocation R_X86_64_64 cannot be used against
local symbol; recompile with -fPIC», porque ese
link acaba siendo dinamico (aparece libc.so)
pese al `link = "static"` de la receta.
libpng-shared solo la .so → «unable to find static system library 'png16'»,
porque la receta pide --prefer-static.
Es la misma tenaza que el `bz2` de freetype: los -dev traen .so pero no .a. La
salida no es elegir un extremo sino una .a que TAMBIEN sea PIC. `libpng-pic` es
copia literal del canonico con `--with-pic` en el configure; nada mas.
EVIDENCIA de que es PIC, y hay que medirla bien: 0 relocs R_X86_64_32/32S
contra 706 del canonico — EXCLUYENDO las secciones .debug_*. Sin ese filtro
ambas dan >13000 y parecen identicas; es la correccion de la regla del .a
no-PIC que ya nos mordio en GNOME.
El canonico NO se toca (decision del usuario): 12 dependientes en cuatro colas
y es estatico por diseño. Se añade una SOMBRA en incoming-wlr que cambia una
sola linea de deps. libpng-pic si va al corpus, porque la resolucion es
HERMANO→PADRE y una receta del corpus no veria una variante en incoming-*.
⚠ ALCANCE: la sombra la ve su cola. gtk4, libadwaita, gtksourceview y otras 4
son del CORPUS y siguen resolviendo el gdk-pixbuf canonico roto.
⚠ NO ERA UN FALLO NUEVO: gdk-pixbuf tenia artefacto sellado y se servia por
cache-hit. La reconstruccion no lo rompio, lo DESTAPO.
Verificado: sombra SELLADA, 71 MB, con .a, .pc y los loaders .so reales — no un
directorio vacio haciendose pasar por artefacto.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xd5DComN9Nu47TBpYMBHBn
|
||
|
|
dba9ec47c5 |
licencias: el detector borraba la evidencia que decia registrar
Consulta solo las recetas que HOY no tienen licencia, asi que su cosecha MENGUA a cada pasada: lo sembrado ayer ya no sale en --faltan. Y reescribia el fichero entero con la cosecha del dia. Hoy una pasada con CERO detecciones dejo docs/licencias-detectadas.tsv en 0 filas y se llevo las 610 que documentaban de donde salia cada licencia ya sembrada. Salio con exit 0 diciendo «escrito» y «sembrar con». Un vacio que llega hasta el final afirmando que todo fue bien — la regla 3 de CLAUDE.md, esta vez sobre el registro de procedencia en vez de sobre un artefacto. Ahora FUSIONA con lo registrado (la fila nueva gana) y se niega a sobrescribir si el resultado pierde filas: un registro de evidencia que encoge es un fallo, no un resultado. Con CON=0 lo dice y no invita a sembrar nada. Y las cuatro de HashiCorp quedan declaradas: BUSL-1.1. No es adivinado ni sale de la API —que devuelve NOASSERTION en las cuatro, y por eso llevaban meses sin licencia—: es el texto del LICENSE del TAG QUE LA RECETA PINEA, no el de la rama por defecto. consul v1.22.7, vault v1.21.4, nomad v1.11.3 y packer v1.15.4 abren con «Business Source License 1.1». ⚠ BUSL-1.1 NO es una licencia libre: prohibe el uso en produccion que compita con el producto de pago, y solo pasa a MPL-2.0 cuatro años despues de cada version. Cuatro paquetes del catalogo publicable no son redistribuibles como si fueran libres. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Xd5DComN9Nu47TBpYMBHBn |
||
|
|
683dd9cbee |
freetype: --with-bzip2=no explicito — su autodeteccion tumbo el escritorio entero
Cadena probada de punta a punta (2026-08-12): 1. Se añadio `bzip2-dev` al lab para que CPython tuviera sus modulos. 2. freetype AUTODETECTA bzip2 —la receta desactivaba harfbuzz y brotli de forma explicita, pero no este— y lo grabo en su freetype2.pc: `Requires: zlib, bzip2, libpng`. 3. Toda receta que enlaza freetype con `-all-static` resuelve ese Requires via pkg-config y pide `-lbz2`. 4. Los `-dev` de Alpine traen `.so` pero NO `.a` ⇒ «unable to find static system library 'bz2'». 5. Cayo fontconfig y con el 27 recetas: KDE, GNOME y COSMIC dependen de el. Verificado: el freetype nuevo vuelve a `Requires: zlib, libpng` y fontconfig SELLA (8290b402...). Se arregla en la receta y NO quitando bzip2-dev del lab: esto mueve el hash de freetype y sus dependientes; lo otro re-hashearia el corpus ENTERO por tercera vez en un dia. freetype solo usa bz2 para fuentes PCF comprimidas. ⚠ Metodo, porque me costo tres hipotesis fallidas: hay CINCO artefactos de freetype en el store y mirar uno al azar dio el `.pc` equivocado. Y al apartar bzip2.pc el error cambio a «freetype2 not met» — eso era evidencia A FAVOR (pkg-config no podia resolver el Requires) y lo lei como si fuera en contra. Comprobar el hash VIGENTE, no el primero que lista `ls`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
1940a94a11 |
lab: los -dev al rootfs — es el unico sitio donde _curses se puede resolver
Decision del usuario. CPython construye sus modulos opcionales como .so
COMPARTIDOS y las .a del corpus NO son PIC («relocation R_X86_64_PC32 against
symbol 'stdscr'»), asi que declararlas en [deps] NO funciona: se probo una
por una. Las libs del rootfs son compartidas y si sirven.
Añadidos: libffi-dev ncurses-dev readline-dev sqlite-dev bzip2-dev xz-dev
expat-dev. Resultado VERIFICADO: el guardian de python3 importa los OCHO
modulos (_ctypes _curses readline sqlite3 bz2 lzma zlib pyexpat) y pasa. De
paso `libffi` sale de [deps]: ya lo aporta el lab.
openssl-dev NO va, deliberado: se de-Alpinizo porque el host-tool del kernel
enlaza el openssl del corpus desde el overlay; devolverlo podria cambiar el
artefacto del kernel. python3 sigue sin `ssl`.
Y SE CIERRA EL AGUJERO QUE ESTO ABRIA. Esas libs del rootfs ahora entran en
el CONTENIDO de un artefacto, asi que su version es parte de su identidad ⇒
van a TOOLCHAIN_PREFIXES. Sin eso habriamos reabierto en pequeño el mismo
fallo que
|
||
|
|
6ab29b1e78 |
python3: libffi arregla _ctypes; el resto choca con dos fronteras reales
Estado VERIFICADO: con libffi el build sella y el guardian de la fase install
imprime «modulos opcionales: OK» ⇒ _ctypes y zlib importan de verdad.
El guardian es la pieza que mas vale de este commit: `configure` de CPython
OMITE en silencio cada modulo opcional cuyos headers no encuentra, `make`
termina 0 y el artefacto se sella mutilado. El error aparece dias despues en
OTRA receta (gjs, gdm) como ModuleNotFoundError y no se parece a su causa.
Importarlos en install lo convierte en un fallo en la receta correcta.
Lo que NO se pudo añadir, probado uno por uno y documentado en la receta:
openssl → el del corpus es libcrypto ESTATICA sin threads; CPython aborta
con «OPENSSL_THREADS is not defined». Sin modulo `ssl`.
ncurses → `.a` no-PIC: _curses_panel.so no enlaza
(«relocation R_X86_64_PC32 ... against symbol 'stdscr'»).
sqlite/bzip2/xz/readline/expat → mismo muro no-PIC (_lzma lo destapo).
CPython construye sus modulos opcionales como .so COMPARTIDOS, y las .a del
corpus no son PIC. El python3 viejo tenia _ctypes Y _curses porque se
construyo contra las libs COMPARTIDAS del rootfs de entonces; el lab anclado
trae los runtime pero no los headers.
⇒ _curses sigue roto y con el la familia GNOME. Arreglarlo pide DECIDIR:
meter los -dev en la imagen del lab (re-hashea el corpus otra vez, barato
AHORA que van 48 de 1186) o hacer recetas PIC de esas libs (frente nuevo).
Queda para el usuario.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
2f0ff5d0d3 |
python3: declarar libffi — sin el, CPython se construye SIN _ctypes en silencio
Destapado reconstruyendo el corpus: gjs y el build de mozjs morian con `ModuleNotFoundError: No module named '_ctypes'`. La causa no estaba ahi: el artefacto de python3 se sella SIN ese modulo y arranca perfectamente; el fallo aparece mucho despues, en otra receta. 310 recetas dependen de python3. El rootfs del lab trae libffi (runtime) pero NO sus headers — no hay libffi-dev en el lock. El configure de CPython no encuentra ffi y omite _ctypes sin fallar. recipes/libffi.toml si instala headers y .pc, y pkgconf —ya declarado— los ve en la capa overlay. Por que aparece AHORA y no antes: el artefacto viejo de python3 tenia _ctypes porque el rootfs de entonces traia los headers, y el cache-hit lo mantuvo congelado hasta que el corpus se re-hasheo. Mismo patron que make/--disable-load: reconstruir destapa lo que la cache sostenia. Se arregla ahora y no mas tarde a proposito: mover el hash de python3 mueve el de sus 310 dependientes, y con solo ~48 recetas selladas eso es barato. Dentro de dos dias no lo habria sido. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
98a958ec48 |
make: --disable-load — sin esto el binario sale DINAMICO Y ROTO y tumba el corpus
Sintoma: al reconstruir el corpus, bash/binutils/bison/busybox/zlib morian con exit 139. dmesg lo nombraba: `traps: make general protection fault in ld-musl-x86_64.so.1`. Causa exacta, leida de la linea de link real: hammer-zig-cc -g -O2 -Wl,--export-dynamic -static -o make src/*.o GNU make 4.4.1 soporta cargar objetos en runtime (directiva `load`), asi que su configure anade -Wl,--export-dynamic. El wrapper hammer-zig-cc tiene la regla —correcta— de que `-static` CEDE ante cualquier link que exija dinamico, y --export-dynamic es uno de esos marcadores ⇒ le quitaba el -static y se sellaba un make dinamico que segfaultea. Como toda receta autotools invoca make, se propagaba a casi todo el corpus. El arreglo va en la receta y NO en el wrapper: el conflicto es de origen —pedimos estatico de un proyecto que pide symtab dinamica para una funcion que no usamos—. Ensenarle al wrapper a ignorar --export-dynamic lo romperia para gobject-introspection, que si lo necesita. POR QUE NO SE VIO ANTES, que es la leccion: el artefacto viejo de make era estatico y estaba congelado por cache-hit, probablemente desde antes de que existiera esa regla del wrapper. Nadie lo reconstruyo hasta que el corpus se re-hasheo entero. Un cambio que "no re-hashea nada sellado" igual cambia lo que producen los builds FUTUROS, y eso queda invisible hasta que algo fuerza la reconstruccion. Verificado: make ESTATICO, corre (GNU Make 4.4.1), y zlib —que fallaba con 139— sella. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
2602218332 |
kernel: THUNDERBOLT->USB4 y fuera REISERFS_FS en las cuatro recetas
Los dos simbolos ya no existen en 6.16.12, asi que `-d THUNDERBOLT` y `-d REISERFS_FS` eran no-ops silenciosos: scripts/config los escribia y el olddefconfig siguiente los tiraba por desconocidos. No son el mismo caso y por eso no reciben el mismo trato: - THUNDERBOLT se FUNDIO, no se fue. drivers/thunderbolt/Kconfig declara `menuconfig USB4` = "Unified support for USB4 and Thunderbolt". El simbolo cambio de nombre, la intencion de apagarlo sigue viva ⇒ se renombra a `-d USB4`, que ademas pasa a ser un guardian de verdad: si un dia la base o un `select` lo encienden, ahora si lo apaga. - REISERFS_FS se RETIRO del kernel. No hay nada que apagar ⇒ se quita. El .config resultante NO cambia hoy: USB4 no aparece en x86_64_defconfig y su Kconfig no trae `default`, asi que ya estaba en n. Lo que cambia es el ArtifactHash de los cuatro, porque el texto de la fase configure entra en hash_inputs. Los cuatro artefactos viejos siguen en el respaldo como superados; no se pierde nada. Verificado contra el arbol real (work/kconfig-6.16.12/), no de memoria. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
0ac421b516 |
libsndfile: su configure sólo busca python2.x — tumbaba CUATRO recetas y parecía fallo de cada una
COSMIC cerró 25 de 30 raíces. De los 5 fallos, CUATRO daban el mismo mensaje — «error: no suitable Python interpreter found»— en wireplumber, xdg-desktop-portal, xdg-desktop-portal-cosmic y cosmic-settings-daemon. NO ERA DE ELLAS, Y NI SIQUIERA ERA DE MESON. El error viene de un `configure` de AUTOTOOLS que prueba `python2.2`, `python2.1`, `python2.0` —literalmente— y aborta al no hallarlos. Se identificó por las flags del comando en el log (`--disable-mpeg --disable-full-suite`), que son inconfundibles de **libsndfile**: una dep común a las cuatro. Y declarar `python3` en `[deps]` NO ayuda —dos de las cuatro ya lo tenían—: el problema no es que falte el intérprete, es que el script no reconoce ese NOMBRE. Autoconf respeta la variable de entorno `PYTHON`, así que se le pasa `PYTHON=python3` y sella. LA LECCIÓN, que hoy ya se repitió con `dbus-shared`: cuando varias recetas fallan con el MISMO mensaje raro, el fallo está en una dep común — y **la forma de identificarla es mirar QUÉ configure/meson.build lo emite**, no la receta que se estaba construyendo. Las flags del comando y el número de línea del meson.build son la firma del paquete que realmente muere. Aplicado a las tres copias (incoming-gnome, -cosmic, -kde), que dan el mismo hash. Y de paso `cosmic-settings-daemon` sí necesitaba `python3` en deps, que no lo declaraba: dos causas distintas bajo un mensaje idéntico. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
0f1f2e9ef6 |
dbus-shared: la misma flag ausente tumbaba GNOME y COSMIC enteros
`mutter`, `gnome-shell` y `xdg-desktop-portal-gnome` fallaban las tres con «ERROR: Unhandled
python exception». Las tres YA tenían `--wrap-mode=nodownload` en su propia receta, así que no
era eso — hasta que el log mostró la línea culpable:
meson.build:372:11: ERROR: Unhandled python exception
<urlopen error unknown url type: https>
WARNING: failed to download with error: name 'ssl' is not defined
La misma línea 372 que el fallo de `dbus` de hace unas horas. No fallaban ellas: fallaba una
DEP que arrastran, `dbus-shared`, cuya sombra en incoming-gnome e incoming-cosmic no tenía la
flag. La canónica del corpus y la sombra de KDE sí la tenían; estas dos no.
⇒ UNA flag ausente en una sombra tumbaba TRES raíces de perfil en GNOME y bloqueaba COSMIC de
paso. Y el mensaje nunca nombra la red: «Unhandled python exception» se lee como un bug de
meson y es que el sandbox es hermético a propósito.
Lección de método: cuando tres recetas fallan con el MISMO error y las tres ya tienen el
arreglo obvio, el fallo está en una dep común, no en ellas. La línea de meson.build en el
mensaje es lo que lo identifica — es la firma del paquete que realmente muere.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
c56fd373a1 |
etapa 4: tanda de 30 HOJAS — cero daño colateral, que era el punto
Primera tanda con el orden nuevo (por impacto en el grafo, no alfabético). 30 recetas C de clase HOJA: bash, coreutils, git, gnupg, grep, gzip, jq, e2fsprogs, libarchive, htop… LA MEDIDA QUE JUSTIFICA EL CAMBIO DE ORDEN: activar estas 30 dejó 41 recetas sin artefacto vigente = las 12 que ya estaban en deuda + las 30 tocadas (una ya estaba entre las 12). **Cero colateral.** Contra la tanda anterior, donde tocar TRES bibliotecas base (expat, zstd, ncurses) dejó 54 sin artefacto y tumbó la cadena wlroots/sway entera. Mismo esfuerzo de build, diez veces menos destrozo. El orden no era un detalle de comodidad. Selección: clase `c` + `dependientes_total == 0` + estado sellado, excluyendo las de tawasuyu (git privado ⇒ no construyen en el worker, que es sin secretos por diseño) y las Go/Rust, que necesitan sus módulos y fallan ahí. Quedan 73 hojas C elegibles; van 30. La tanda corre DESASIDA con nohup en el worker — la lección de ayer, cuando un drenaje murió a las 14 de 54 al caerse la sesión ssh. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
15e34cb257 |
dbus: una flag ausente bloqueaba TRES perfiles — --wrap-mode=nodownload
`base`, `cli` y `escritorio-sway` bajaron a 50/51, 73/74 y 120/121 después de la cascada del
split, y los tres fallaban por LA MISMA receta: dbus.
EL ERROR NO MENCIONABA LA RED POR NINGÚN LADO:
meson.build:372:11: ERROR: Unhandled python exception
Y arriba, enterrado entre reintentos:
<urlopen error unknown url type: https>
WARNING: failed to download with error: name 'ssl' is not defined
dbus declara subproyectos con `.wrap` y meson intenta DESCARGARLOS. En el sandbox no hay red y
python no trae ssl ⇒ «Unhandled python exception», que se lee como un bug de meson y es
simplemente que no hay salida a internet. Y no debe haberla: el build es hermético a propósito.
`--wrap-mode=nodownload` obliga a usar las deps del sistema (nuestros artefactos, vía
pkg-config) y deja los wraps inertes. Mismo caso que `wl-clipboard` anoche.
⇒ base 51/51 · cli 74/74 · escritorio-sway 121/121. Los tres cierran otra vez.
ESTADO DE LA REPARACIÓN DE LA CASCADA: de las 54 que quedaron sin artefacto, 42 reconstruidas.
Las 12 restantes son EXACTAMENTE las que ya estaban en deuda antes de la campaña:
· 6 el muro del PIC (gtk4 y su cadena estática — duplicado superado de la dinámica de GNOME);
· 3 HUB-ONLY (mirada-*, llimphi-counter: git privado / commit en ceros);
· dwarves (libdw/musl), y adwaita-hello (error 39 = la carrera del ADR 0012).
O sea que la campaña no dejó deuda nueva.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
b344c5803b |
etapa 4: primera tanda desplegada y verificada (3/3) + el desplegador por tandas
zstd 12M→2M (−83%) · ncurses 6M→2M (−67%) · expat 2M→1M (−50%). Cero ficheros vacíos y **las tres REPRODUCEN**. La maquinaria de la etapa 4 queda validada de punta a punta: activar → construir en la granja → verificar con why-differs. LA DEP DE binutils VA EXPLÍCITA, y es la decisión de diseño de esta etapa. El paso de strip usa `strip --strip-debug -D` de binutils. Se podría hacer que el lab lo materialice solo, sin tocar las recetas — pero entonces la VERSIÓN de binutils sería un input INVISIBLE: dos corridas con binutils distintos darían artefactos distintos con el mismo hash. Los `deps` sí entran en `hash_inputs`, así que declararlo es lo único que mantiene el invariante. Cuesta una edición mecánica por receta; el invariante no se negocia por comodidad. EXCLUSIONES, y son exactamente dos: `binutils` y `make`. binutils provee el strip y depende de make ⇒ activarles el split los haría necesitarse a sí mismos para construirse. No es preferencia, es la circularidad. (Las recetas CERRADAS POR DECISIÓN tampoco se tocan.) POR TANDAS Y NO DE GOLPE: activar re-hashea la receta a propósito y en cascada todo lo que dependa de ella. Hacerlo sobre las 775 candidatas a la vez dejaría el corpus entero sin sellar al mismo tiempo — días de granja antes de poder verificar NADA, y el disco aguantando artefactos viejos y nuevos a la vez. Por tandas se mide, se verifica y se poda entre medias, que es lo que hace la campaña reversible. La primera tanda NO se tomó del orden alfabético que propone el script: ésas son CLIs Go/Rust que ya vimos que no reconstruyen en el worker (necesitan red para sus módulos), y validar la maquinaria con recetas que fallan por otro motivo no habría probado nada. Se eligieron tres paquetes C con artefacto presente. Para las tandas grandes hay que resolver antes el acceso a red de los módulos Go/Rust, o restringirse a lo que reconstruye. Estado: 775 candidatas, 5 desplegadas (bison y appstream del piloto + estas 3). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
fbd586f9b2 |
etapa 2: el split de debug FUNCIONA — y el piloto destruyó los artefactos antes de lograrlo
RESULTADO, con los tres criterios medidos a la vez sobre las dos recetas que divergían: bison 6M → 3M · 0 ficheros vacíos · 0 secciones .debug_ · «bison (GNU Bison) 3.8.2» appstream 56M → 18M · 0 ficheros vacíos · 0 secciones .debug_ · «AppStream version: 1.0.5» y las DOS pasan de DIVERGIR a REPRODUCIR. O sea que un solo cambio recupera espacio Y cierra la fuga de reproducibilidad, como predijo el §1.bis. Pero se llegó ahí después de tres errores que conviene dejar escritos. 🧨 1. `zig objcopy --strip-debug X X` (mismo fichero de entrada y salida) TRUNCA EL FICHERO A 0 BYTES. Destruyó los artefactos del piloto — y lo grave es que LOS TRES INDICADORES DECÍAN QUE IBA BIEN: el tamaño cayó 84% (porque los ficheros quedaron vacíos), `why-differs` dijo REPRODUCE (porque dos árboles vacíos son idénticos) y no quedaban secciones .debug_ (porque no quedaba ninguna sección). Se cazó al EJECUTAR el binario: 0 bytes. ⇒ La verificación de un artefacto tiene que incluir que SIGA FUNCIONANDO, no sólo que pese menos y reproduzca. Un artefacto vacío cumple las dos y no sirve para nada. Es la lección de esta campaña aplicada a la campaña misma: una métrica que parece éxito. 2. Al arreglarlo con fichero temporal, el strip pasó a ser un NO-OP SILENCIOSO: los binarios quedaban intactos y el tamaño no bajaba, porque no se pudo confirmar que `zig objcopy` acepte `--strip-debug`. Cambiado al `strip` de binutils, que sí funciona, a costa de declarar la dep. ⇒ Preferible una dep explícita que funciona a una comodidad que no se sabe si hace algo. 3. Con el strip real, apareció una fuga NUEVA: los artefactos seguían divergiendo, ahora por la CABECERA `ar` de los `.a` — `strip` los reescribe con los timestamps de cada corrida. Lo nombró `why-differs` exacto («archivar en modo determinista»). Arreglado con `strip -D` (= --enable-deterministic-archives). ⇒ Arreglar media causa deja el invariante igual de roto: el debug ya no divergía y el archivo sí. DISEÑO: `strip_debug` es un campo de la receta que ENTRA en `hash_inputs` y sólo si está fijado (mismo patrón que `zig_version`). Las dos mitades importan y están clavadas en un test: si no entrara, el lab cambiaría el contenido del artefacto sin mover el hash y el store MENTIRÍA; y al entrar sólo si está fijado, se despliega receta a receta sin re-hashear las 1161 de golpe — verificado: con el campo añadido al código, los 1161 hashes existentes NO se movieron. Va como paso del lab y no en la fase install de cada receta porque 383 de las 1161 no tienen install explícita: meterlo receta a receta obligaría a escribir a mano ese install por defecto en las 383, con riesgo de no clavarlo exacto. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
6e27721098 |
sombras -shared: 8 promovidas al corpus, 0 hashes movidos — y cairo se para en un muro real
Decisión del usuario: promover una por una, verificando. Hecho así, y valió la pena. EL RIESGO QUE SE TEMÍA NO APLICABA. La nota de `granja-promote-colisiones` advierte que promover a ciegas hace que variantes homónimas pisen recetas canónicas. Acá no: los nombres `*-shared` son DISTINTOS de los canónicos —`zlib-shared` no pisa a `zlib`— y se comprobó que ninguna de las 19 sombras del catálogo choca con un nombre del corpus. Decirlo importa: repetir una advertencia donde no aplica es tan malo como ignorarla donde sí. VERIFICADO EMPÍRICAMENTE, no razonado: se calcularon los hashes de LAS 1153 recetas antes y después de promover. **Ninguna cambió**, y las 8 nuevas tienen hash idéntico a su original ⇒ sus artefactos ya están sellados y no hay que reconstruir nada. Promovidas: zlib, libpng, freetype, fontconfig, libjpeg-turbo, libtiff, libxml2 y libyaml (todas en su variante -shared). ⛔ `cairo-shared` NO SE PROMOVIÓ, y el porqué es el hallazgo: su hash SÍ cambia al moverla, porque una de sus deps —`glib`— resuelve distinto desde el corpus. En `incoming-gnome-onda2` hay una SOMBRA DE GLIB CON EL MISMO NOMBRE que la canónica (`link=dynamic`, `-Ddefault_library=both` en vez de static), y `cairo-shared` está construida contra ella. ⇒ O sea que el riesgo de homónimos SÍ existe, pero un nivel más abajo del que se miraba: no en las `-shared`, sino en el `glib` sombra. Promoverlo pisaría la receta canónica de glib y re-hashearía en silencio todo lo que cuelga de ella, que es medio catálogo. El camino limpio es renombrarla a `glib-shared` —nombre que YA existe en incoming-cosmic— y reapuntar cairo-shared; eso cambia hashes de la cadena GNOME y merece su propia decisión, no colarla acá de madrugada. Con esto la cadena estática del corpus (gtk4 y las 6 que cuelgan) sigue bloqueada, pero ahora se sabe exactamente por qué y cuál es el siguiente paso concreto. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
d70098ade5 |
GTK3: decisión del usuario — NO entra; gnome-session, gsd y gdm quedan CERRADAS por escrito
Decidido el 2026-08-08. Las tres recetas dependen de GTK3 (gnome-settings-daemon además de gtk+-x11-3.0) y quedan cerradas, **no «en deuda»**. La diferencia no es semántica: una deuda invita a reintentarla en cada informe y en cada ciclo de granja; una decisión se respeta. POR QUÉ ES RAZONABLE Y NO UNA RENDICIÓN: · GNOME funciona sin esto — el camino vivo es mutter → gnome-shell arrancado por arje, y ninguno de los dos depende de gnome-session (su cierre es mutter+gjs+gobject-introspection+ gnome-desktop). · Traer GTK3 sería una torre de C muerta —y para waybar además gtkmm, sus bindings de C++— por un gestor de sesión y un login manager que este escritorio no necesita. · La función está cubierta: la sesión la levanta arje y la barra de estado es `yambar`, C puro, sellado anoche en el frente wlr. Se reabre si alguien trae GTK3 por otro motivo con peso propio (una app gráfica que lo exija). EL MARCADOR VIVE EN LA RECETA, NO EN UNA LISTA APARTE. `build-farm.sh` salta las recetas cuya cabecera dice «CERRADA POR DECISIÓN». Podría haber hecho un fichero de exclusiones, pero una lista y una cabecera se desincronizan solas: así, quien lee el porqué y quien decide saltarla miran EL MISMO TEXTO. Y el drenador lo dice en su salida, para que la decisión sea visible en vez de silenciosa. Con esto la granja deja de quemar CPU en tres recetas que nadie va a arreglar. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
427ca1dd01 |
wl-clipboard 2.2.1 SELLADA — cierra el entorno mínimo del frente wlr
`wl-copy` y `wl-paste`. En Wayland no hay forma de copiar o pegar desde un script sin esto, y
varios flujos que ya sellamos lo necesitan para ser útiles: capturar con grim, seleccionar
región con slurp, y poder pegar el resultado en algún lado.
UNA DIFERENCIA CON LAS ANTERIORES QUE CONVIENE NOTAR. Va por commit (ADR 0006, GitHub genera
sus archive/refs/tags al vuelo igual que codeberg), pero este tag es **LIGERO**: `git ls-remote`
devuelve UN solo sha y ése ES el commit. En fuzzel, yambar y foot los tags son ANOTADOS y
aparecen dos, donde el bueno es el `^{}`. Comprobar el tipo de tag antes de copiar evita pinear
el objeto del tag en vez del commit — un error silencioso, porque la receta valida y sólo falla
después, al no encontrar el árbol.
TRAE `subprojects/` CON WRAPS QUE BAJAN DE LA RED (expat, libffi, wayland, wayland-protocols).
`--wrap-mode=nodownload` es lo que lo impide y lo obliga a usar las del sistema, o sea nuestros
artefactos vía pkg-config. Sin esa flag el build intentaría salir a internet DENTRO del sandbox
hermético y moriría; con ella los wraps quedan inertes. Por eso las cuatro van en deps.
Estado del frente wlr: 10 recetas, 12 binarios — wlroots, sway (+swaybar/swaymsg/swaynag),
swaybg, swayidle, swaylock, grim, slurp, fuzzel, yambar, wl-copy/wl-paste. Con `foot` (ya en el
corpus) como terminal, el perfil «escritorio-sway» es armable: compositor, barra, lanzador,
fondo, bloqueo, inactividad, captura y portapapeles. Todo sin X11 y sin systemd.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
3545ea77fa |
fuzzel + yambar SELLADAS — y waybar queda fuera POR MEDICIÓN, no por gusto
Lanzador y barra de estado: las dos piezas que faltaban para que un WM ligero se use de
verdad y no sólo arranque. El frente wlr suma 9 recetas y 11 binarios.
WAYBAR NO ENTRA, Y CONVIENE QUE CONSTE POR QUÉ. Medidas sus dependencias reales (0.12.0):
pide `gtkmm-3.0` — o sea GTK**3** *y además* sus bindings de C++ — más gtk-layer-shell,
jsoncpp, fmt, spdlog, sigc++, date y libnl. Es el mismo muro de GTK3 que el frente GNOME
aparcó a propósito, con ocho recetas nuevas encima. `yambar` es C puro, del mismo autor que
foot/fcft/fuzzel, y **sus dependencias ya estaban selladas**: es el bar estándar de esa
familia, no un sustituto pobre. Si algún día entra GTK3, waybar vuelve a estar sobre la mesa.
FUENTE GIT POR COMMIT, no el archive de codeberg (ADR 0006). Es el criterio que ya usan foot y
fcft, con la razón medida allí: el `/archive/<tag>.tar.gz` lo genera la forge AL VUELO, así que
sus bytes dependen de la versión de git/gzip del servidor y el sha256 pineado se muere solo
cuando codeberg actualiza su tooling. ⚠ Y los tags son ANOTADOS: el sha de `refs/tags/1.12.0`
NO es el commit; hay que pinear el `^{}` desreferenciado. Lo verifiqué con `git ls-remote`
antes de escribir, porque los dos shas aparecen juntos y es fácil copiar el equivocado.
DOS DEPS DE BUILD-TIME QUE NO SE VEN EN EL BINARIO Y MATAN EL BUILD:
· `scdoc` (las dos) — generan sus man pages con él y, a diferencia de sway/swaybg/grim, NO
ofrecen `-Dman-pages` para saltárselo. Estaba en el corpus: la vía correcta es declararlo,
no buscar cómo evitarlo.
· `flex` + `bison` (yambar) — generan el parser de su lenguaje de partículas. Invisibles en el
resultado, y del tipo que se olvida hasta que el build muere con «Program 'flex' not found».
`-Dbackend-x11=disabled` en yambar evita SIETE dependencias de X11 (xcb-aux, xcb-cursor,
xcb-errors, xcb-event, xcb-ewmh, xcb-randr, xcb-render) para un backend que en una distro
Wayland pura no se usa nunca. Y en fuzzel, `-Dsvg-backend=nanosvg` (el default, vendorizado)
evita librsvg, que arrastraría la cadena de GNOME/Rust por unos iconos.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
50b080d258 |
accesorios wlroots: swaybg, swayidle, swaylock, grim y slurp — 5 selladas
Con esto el frente de WMs ligeros pasa de «hay un compositor» a «se puede usar»: fondo de escritorio, apagado por inactividad, bloqueo de pantalla y captura por región. Sumado a sway y wlroots, el frente tiene hoy 7 recetas y 9 binarios (sway swaybar swaymsg swaynag swaybg swayidle swaylock grim slurp), todos sin X11 y sin systemd. CADA FALLO FUE DE UNA CLASE DISTINTA, y ninguno del paquete que estaba escribiendo: · swayidle — pasé `-Dsd-bus-provider=none` porque es la opción que tiene SWAY. En swayidle 1.9.0 no existe: la suya se llama `logind`. **Las perillas no se heredan entre proyectos hermanos aunque resuelvan lo mismo**; hay que leer el meson_options.txt de CADA uno. Tercera vez hoy que una opción inventada mata un build (gnome-session, y ahora ésta). · grim — `undefined symbol: crc32`, o sea zlib. No lo usa grim: lo usa `libpng`, cuyo `.pc` declara zlib en `Requires.private`, la línea que pkg-config sólo expande en resolución estática. Es la MISMA causa que el `-lexpat` de sway (allí vía fontconfig), sobre otra biblioteca. Ya van dos casos ⇒ es un patrón del corpus, no un accidente: enlazar contra una lib estática cuyo .pc tiene Requires.private exige añadir esas libs a mano. · slurp — le faltaba `libxkbcommon` en deps, sin más. DOS COSAS QUE VALE GUARDAR: 1. EL TARBALL DE slurp CASI ENVENENA LA RECETA. La URL de releases de GitLab devolvió **HTTP 200 con una página HTML** en vez del archivo, así que `curl -f` no falló y el sha256sum que saqué era el de un documento HTML. Pinearlo habría dado una receta que descarga «algo» con hash correcto y no construye jamás, con un error incomprensible. Se cazó verificando el FORMATO (`tar tzf`), no el código de salida — misma lección que el `rm` que devuelve 0 sin borrar y el proceso vivo que no avanza. El sha256 correcto es el del tarball de GitHub. 2. PAM NO ESTABA BLOQUEADO. «PAM» figura entre las tres deudas aparcadas del frente GNOME, así que lo natural era dar swaylock por imposible. Pero en swaylock PAM es una OPCIÓN (cae a `crypt` si falta) y sobre todo **`linux-pam` SÍ está en el corpus**: lo aparcado era la integración de PAM del stack GNOME, no la biblioteca. ⇒ Una deuda «aparcada» nombra un frente concreto, no una palabra; conviene verificar antes de heredar el veto. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
f7aafc9d26 |
sway 1.10 SELLADA — primer compositor Wayland ligero del catálogo
b3:ae10753a5467f3642464aaad0b1b41135b8c51972091042baf0d09134af46c7e · sway, swaybar,
swaymsg y swaynag. Construido en el worker sobre el wlroots 0.18.2 sellado hace un rato
(sway 1.10 pide `wlroots-0.18` explícitamente: no es una versión cualquiera, es LA que casa).
XWAYLAND SE HEREDA, NO SE PASA. sway no tiene perilla propia: lee las variables del .pc de
wlroots (`xcb = wlroots_features['xwayland'] ? dependency('xcb') : null_dep`). Como nuestro
wlroots se selló con have_xwayland=false, sway se salta xcb y xcb-icccm solo. Para eso servía
haber inspeccionado esas variables al verificar el artefacto anterior. Si algún día se quiere
Xwayland, se cambia en wlroots, no acá.
TRES COSAS QUE SALIERON AL CONSTRUIR, y ninguna estaba en sway:
1. `json-c` NO DECLARABA NADA y sellaba igual — porque el rootfs del laptop trae cmake y make
y el sandbox los tomaba «de prestado». En el worker muere con `cmake: not found` (exit 127,
el mismo código que engaña con meson). Una receta que sólo construye en la máquina del autor
es una bomba de relojería. Declarados cmake+make+pkgconf; el arreglo es declarar, NUNCA
engordar el rootfs del worker. Re-hashea json-c y su único dependiente, que es sway: gratis.
Salió a la luz construyendo sway, o sea que el fallo estaba a tres niveles de donde miraba.
2. 45 SÍMBOLOS INDEFINIDOS AL ENLAZAR, todos `XML_*` — expat, y sólo expat (clasificada la
lista completa, no adivinado por el primero). sway no usa expat: lo usa `fontconfig`, que en
el corpus es estático, y su `.a` trae las llamadas sin resolver. `fontconfig.pc` lo declara
en `Requires.private`, que es la línea que pkg-config sólo expande en resolución ESTÁTICA, y
meson llama a dependency('cairo') en modo normal. No es un fallo de fontconfig ni de cairo:
es donde el modelo de pkg-config y el enlace estático no encajan. Resuelto con
`-Dc_link_args=-lexpat`; como los indefinidos eran de UN solo prefijo, se sabe que no falta
nada más.
3. `-Dtray=disabled` esquiva la única dep que nos falta de verdad. La bandeja habla sd-bus y
sway ofrece tres proveedores (libsystemd | libelogind | basu): no hay systemd por decisión,
`basu` no está en el catálogo, y el `libelogind` que sí tenemos NO sirve — es la
reimplementación propia de la C-ABI sd-login de arje-compat, no un sd-bus. Misma trampa del
nombre que ya mordió con `knighttime`. Traer basu es un ticket aparte y pequeño.
Con esto el frente de WMs ligeros deja de ser un hueco: había 0 compositores y ahora hay uno
que arranca desde wlroots propio, sin X11 y sin systemd.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
c13d25f02b |
wlroots 0.18.2 SELLADA — el desbloqueo del frente de WMs Wayland ligeros
Primera receta del frente nuevo. wlroots es la biblioteca de la que cuelgan casi todos los
compositores ligeros (sway, labwc, river, hyprland): sin ella no hay ninguno, y con ella los
compositores salen baratos porque no traen torre de C debajo. Hasta hoy el catálogo tenía de
toda esa familia sólo `foot` y `mako`.
b3:9b56bac0d00977524072cf393ecc9f0b847fcc1a0bfba9d9c4d57fd9a4a74b44 · 13 MB · construida en
el worker (cadena GUI: no se rebuildea en el laptop por el zig-skew).
COLA AISLADA `incoming-wlr/`, porque otro agente comparte el repo. Como la resolución de deps
es hermano→padre, una receta de acá ve el corpus pero NO ve `incoming-gnome/`, donde viven
`libdisplay-info` y `hwdata` ⇒ se copian como hermanas. No duplica trabajo: los ficheros son
idénticos, el ArtifactHash es el mismo y el build hace cache-hit. Verificado antes de
construir: ambas dan el mismo b3: que su original.
LAS OPCIONES, VERIFICADAS CONTRA EL meson_options.txt DEL TARBALL, no de memoria — porque una
opción `-D` inventada NO se ignora: meson aborta en la primera desconocida. Es exactamente lo
que tenía muerta a gnome-session con su `-Dsystemd=false`. El `.pc` resultante confirma que
salió lo pedido: have_drm_backend=true, have_libinput_backend=true, have_gles2_renderer=true,
have_gbm_allocator=true, have_session=true, y have_x11_backend / have_xwayland en FALSE —
la distro es Wayland pura y X11 es deuda aparcada por diseño; no entra por la puerta de atrás.
DOS COSAS QUE COSTARON UNA ITERACIÓN CADA UNA:
· `-Dwerror=false` no es pereza, es DIFERENCIA DE TOOLCHAIN. wlroots compila con -Werror y
upstream lo valida con gcc; nuestro `zig cc` es clang y avisa de lo que gcc calla. Murió en
`types/wlr_shm.c:503` por `-Wunused-but-set-variable` sobre has_argb8888/has_xrgb8888 —
código correcto que sólo clang señala. Tratar los avisos de OTRO compilador como errores del
proyecto es un fallo de método, no un hallazgo de calidad.
· `libffi`, `expat` y `zlib` en deps aunque wlroots no los use: los exigen los `.pc` de wayland
y mesa en su `Requires`, y pkgconf resuelve el grafo de .pc completo antes de dar un cflag.
Misma lección que wlr-randr esta mañana.
El artefacto trae `libwlroots-0.18.{a,so}`, su .pc y 111 cabeceras bajo
`usr/include/wlroots-0.18/wlr/`. Listo para que sway enlace contra él.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
129aff9dd9 |
granja: el worker rehacía 87 de 90 recetas por ciclo — el sync del store es de UN SOLO SENTIDO
Fui a mirar los fallos de la granja y el número no cuadraba: de 20 «fallos» de incoming-gnome, 17 correspondían a recetas CON ARTEFACTO VIGENTE en el hub. Primero pensé que eran marcadores `.fail` rancios, y me equivoqué: `build-farm.sh` hace `rm -rf "$FARM"` al empezar cada ciclo, así que el status es siempre del ciclo actual. Después pensé que el worker corría recetas viejas, y también me equivoqué: comparados los md5, hub y worker tienen copias IDÉNTICAS. LA CAUSA REAL está en `farm-sync.sh`: sube el código EXCLUYENDO /store y baja el store del worker. El store viaja worker→hub y nunca hub→worker. O sea que **el worker no se entera de nada de lo que se sella en el hub**, y cada ciclo reintenta —y vuelve a fallar— trabajo ya hecho. Medido: de las 90 recetas de incoming-gnome, **87 ya están selladas en el hub**. El worker estaba quemando el 97% de esa cola en repetir lo hecho. EL ARREGLO no es mandarle los artefactos (gigabytes por un enlace de 8 Mbps) sino la LISTA: `work/farm-sellados.txt` son los nombres `<hash>-<paquete>` del store del hub, unos kilobytes. `farm-sync.sh` la regenera en cada sync (para que no envejezca sola) y `build-farm.sh` salta la receta cuyo hash vigente ya esté ahí. Ojo al detalle de rsync: la subida excluye /work, así que el manifiesto necesita un `--include` ANTES del `--exclude` — rsync aplica la primera regla que casa, y sin ese orden el fichero no viajaba y el arreglo no habría hecho nada en silencio. Y LAS TRES DEUDAS REALES DE LA GRANJA SON UNA. gnome-session, gnome-settings-daemon y gdm mueren todas en GTK3, que el frente GNOME aparcó a propósito. Verificado contra el meson.build de cada tag: gnome-session 48.0 lo pide incondicional; gnome-settings-daemon 48.1 pide gtk+-3.0 Y gtk+-x11-3.0 (dos de las tres deudas aparcadas, no una); gdm 48.0 lo tiene condicionado a `if have_xdmcp` pero da igual, porque muere construyendo gnome-session. De paso, gnome-session pasaba `-Dsystemd=false -Dsystemd_journal=false`, dos opciones que NO EXISTEN en 48.0 (sus opciones reales son seis: deprecation_flags, session_selector, systemduserunitdir, docbook, man, x11). Meson aborta en la primera opción desconocida, así que la receta ni llegaba a configurar y el fallo real quedaba tapado. Corregido, más -Dx11=false. El diagnóstico de fondo YA ESTABA en la receta desde el 2026-07-27 y era más completo que el mío (dice GTK3 **y** libsystemd); quité la nota duplicada que había añadido. Y en el respaldo: la comprobación inicial de SSH era de un solo intento y tiró la corrida al relanzarlo llegando a casa, con el wifi aún sin levantar. Es el peor momento para rendirse — quien relanza un respaldo interrumpido acaba de cambiar de red. Ahora reintenta. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
2c2ee951d6 |
licencias: resolver -only vs -or-later CON LA CITA — y tres «pruebas» que no probaban nada
Los identificadores obsoletos (`GPL-2.0`, `LGPL-2.1`, `AGPL-3.0`) no dicen si el proyecto
concede «sólo esta versión» o «ésta o cualquier posterior», y eso decide con qué se puede
combinar el paquete y bajo qué términos puede redistribuirlo quien lo reciba.
NO SE PUEDE MIRAR EL COPYING, que es la trampa evidente: el texto de la GPL es IDÉNTICO en
los dos casos —es la licencia, no la concesión— y encima su apéndice «cómo aplicar la
licencia» contiene literalmente «or (at your option) any later version», así que buscarla
ahí da SIEMPRE positivo y parece evidencia siendo plantilla. Misma trampa que la regla del
`.a` no-PIC, donde grep contaba reubicaciones de `.debug_*`. La concesión vive en las
cabeceras de los fuentes y en el README; ahí se busca, excluyendo los ficheros de licencia.
SE GUARDA LA CITA, no sólo el veredicto: fichero + frase exacta que decidió. Una licencia es
una afirmación legal y quien la revise tiene que poder ver POR QUÉ dice lo que dice sin
repetir el trabajo.
Y eso pagó de inmediato: de las 12 primeras resoluciones, TRES eran evidencia inválida y
sólo se vieron porque estaba la cita. Cada una de una clase distinta:
· caligula — la frase salía de `checks/headless/expected.iso`, un FIXTURE DE TEST;
· libnl — de `include/linux-private/linux/seg6.h`, una cabecera del KERNEL vendorizada.
La licencia del kernel no es la de libnl;
· lm-sensors — declarado GPL-2.0 y la cita decía «version 2.1 of the License», que es la
LGPL. La frase era real pero no sostenía lo que se le atribuía.
Las tres clases quedan filtradas en el script: ficheros de licencia, rutas de test/fixture, y
código vendorizado; más una comprobación nueva de que **la cita hable de la misma versión que
la licencia declarada**.
Sembradas las 9 auditadas (13 ficheros; algunas viven en varias colas). Ambiguas: 55 → 41.
Las 40 sin evidencia quedan listadas y siguen contadas — la mayoría son Go y la familia
cosmic, donde la frase no aparece fuera del COPYING.
Hashes verificados: 0 movidos.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
be4e91086c |
licencias: el texto dentro de la imagen, con veto — y el SDD 19/20 se equivocaba de sitio
═══ LA CORRECCIÓN DE FONDO: no es `pack`, son las IMÁGENES ═══
El SDD 19 y el 20 decían «inyectar el texto de la licencia en `hammer pack`, que es aguas
abajo del ArtifactHash y sale gratis». La conclusión sobre el coste era correcta pero el
SITIO estaba mal, y por una razón que sólo se ve leyendo el código: `pack` produce un
`.swm`, que es una RECETA DE TRANSFORMACIÓN sobre fuente pública y por diseño explícito
«NUNCA transporta binarios cocidos»; e `install` REPRODUCE construyendo, con cache-hit del
corpus, en vez de bajar binarios. O sea que **el canal de paquetes de hammer no distribuye
binarios** y la obligación de acompañar-el-binario ahí casi no aplica.
Donde sí aplica, con toda su fuerza, es en la IMAGEN INSTALABLE: su rootfs se puebla con
`hammer install` sobre un prefix y de ahí sale un USB/ISO lleno de binarios que se le da a
alguien. Ése es el punto de entrega. (La obligación del espejo de FUENTES es otra y sigue
entera: las recetas apuntan a URLs de terceros que se caen.)
═══ LO QUE ENTRA ═══
· `scripts/licencias-textos.sh` + `licenses/`: los 44 textos CANÓNICOS de SPDX
(spdx/license-list-data), uno por identificador realmente en uso — la lista se saca de las
recetas, no de un fichero escrito a mano que se desincroniza. 764K.
· `scripts/licencias-rootfs.sh`: escribe /usr/share/licenses/<pkg>/ con el texto de CADA
licencia de la expresión (`Unlicense OR MIT` ⇒ los DOS textos: en un OR el destinatario
elige, y entregar uno solo le quita una opción que el autor le concedió), más un
MANIFEST.tsv. Medido: 1,0 MB para el perfil `cli` de 44 paquetes.
═══ Y SOBRE TODO: ES UN VETO ═══
Sale ≠0 si algún paquete del rootfs no declara licencia. Un informe que no puede bloquear no
cambia lo que ocurre; esto corta el paso. Y se ganó el sueldo al primer intento: reveló que
los perfiles `base` y `cli` —los dos más simples, los que primero se publicarían— llevaban
10 y 12 paquetes con binarios y licencia desconocida. Curados los 10 que se podían afirmar
(doas, iputils, less, mandoc, procps-ng, rsync, strace, sudo, tree, usbutils); ambos perfiles
bajan a 2.
Esos 2 NO se rellenan a propósito, y quedan vetando:
· lsof — licencia propia del proyecto, sin identificador SPDX. Toca `LicenseRef-lsof` con
su texto, que ya viaja en el tarball (la receta instala su COPYING).
· tzdata — dominio público por declaración de sus autores, y SPDX no tiene identificador
para eso (es una AUSENCIA de licencia, no una licencia). Toca
`LicenseRef-PublicDomain` documentado, no forzar uno de la lista.
De paso: normalizado `GPL-3.0+` (sufijo antiguo) a `GPL-3.0-or-later`, misma equivalencia
documentada que la barra de Cargo. Y el caso especial que puse para `Linux-syscall-note`
(«las excepciones viven en exceptions/») era una suposición razonable y FALSA: SPDX las
publica en el mismo `text/`; ese directorio no existe.
1063 de 1141 (93%). Hashes verificados: 0 movidos.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
487e155f74 |
licencias: leer el LICENSE de verdad cuando GitHub dice «no sé» — 1053 de 1141 (92%)
Último recurso mecánico, `scripts/licencias-texto.sh`: para las 60 recetas donde la API de GitHub devuelve NOASSERTION (el repo TIENE un LICENSE pero licensee no lo reconoce: texto retocado, encabezado propio, dos licencias en un fichero), baja el texto y lo clasifica acá. 34 identificadas — 16 MIT, 10 Apache-2.0, 7 BSD-2-Clause, 1 BSD-3-Clause. SÓLO PERMISIVAS, Y NO ES PEREZA. MIT, Apache-2.0, BSD, ISC, MPL-2.0 y Unlicense se reconocen por frases inconfundibles y NO tienen variantes -only/-or-later ⇒ reconocer el texto da el SPDX completo. La familia GPL se deja al humano A PROPÓSITO, y la razón es sutil: el COPYING de la GPL es IDÉNTICO tanto si el proyecto es «sólo v3» como «v3 o posterior» — lo que las distingue vive en las cabeceras de los fuentes. Y encima el propio COPYING incluye, en su apéndice «cómo aplicar la licencia», la frase «or (at your option) any later version», así que buscarla da SIEMPRE positivo y parecería evidencia siendo texto de plantilla. Es exactamente la trampa de la regla del `.a` no-PIC, donde grep contaba reubicaciones de .debug_* y mentía. Comprobado a mano un caso que daba mala espina: el LICENSE de `conftest` empieza «Conftest — Write tests against your config files / Copyright (C) 2019 …», que es el formato típico de una cabecera GPL. Leído entero, dice «Licensed under the Apache License, Version 2.0». La clasificación era correcta; la sospecha, barata. Hashes verificados sobre las 36 tocadas: idénticos. Quedan 88, ya sin vía mecánica: los repos donde ni la API ni el texto deciden, la familia GPL sin desambiguar, y tarballs de sitios propios (gmplib, xiph, sr.ht, codeberg…). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
0225aa4e08 |
licencias: el código propio (tawasuyu) queda en MIT — 1017 de 1141 (89%)
Decisión del usuario: «tawasuyu está en MIT». Es la misma licencia que hammer (LICENSE en la raíz + Cargo.toml), así que todo lo nuestro queda coherente bajo un solo término. Las 20 recetas con fuente en git.tawasuyu.net: arje-* (el init y sus compat), mirada-* (el compositor, el greeter y mirada-ctl), netup, agora-cli, cosmos-cli, dominium-cli, tinkuy-sim, llimphi-counter y libelogind. ⚠ ANOTADO EN LA TABLA porque es una trampa que casi pisé: `libelogind` NO es el elogind de upstream (que sería LGPL-2.1+). Por el nombre lo parece; su cabecera dice que es una reimplementación PROPIA de la C-ABI sd-login dentro de arje-compat. Declararla LGPL «porque se llama así» habría sido exactamente el error que este fichero prohíbe — el tercero del mismo tipo hoy, después de `knighttime` (parecía Go y es KDE) y de la familia `kube*` (parecen KDE y son Go). El nombre nunca es evidencia; la fuente sí. Hashes verificados sobre las 20: idénticos. Quedan 124 sin declarar, ya todas de terceros. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
c8d1357f06 |
licencias: la declaración del autor manda — y arreglo 5 recetas que ROMPÍ y commiteé
Dos cosas: una mejora de calidad y un fallo mío que hay que contar entero.
═══ EL FALLO: escribí un error JSON dentro de 5 recetas y las commiteé rotas ═══
En `a6a9d59`, cinco recetas quedaron con
license = "{"message":"Not Found","documentation_url":"...","status":"404"}"
Causa: cuando el repo da 404 (renombrado, borrado, privado), `gh api` escribe el CUERPO DEL
ERROR en stdout y el filtro `--jq` falla, así que la variable queda valiendo el JSON. Mi
`case` sólo descartaba ""/null/NOASSERTION/other ⇒ el JSON pasó como si fuera una licencia.
Las comillas ROMPEN el TOML, y esas 5 recetas dejaron de parsear y de tener ArtifactHash.
No lo vio nadie leyendo: lo cazó la comparación de hashes, al detectar que `cargo-sort`
había cambiado. Afectadas: cargo-sort, cargo-audit, cargo-binstall, waybackurls, usbutils.
La lección no es «se me pasó un caso», es que **validé los «no sé» conocidos en vez de la
FORMA del dato**. Ahora se acepta sólo lo que tiene forma de expresión SPDX, y la barrera
está en los DOS sitios que escriben (detectar y sembrar), más un GUARDIÁN en el informe que
sale ≠0 si alguna licencia tiene forma imposible. Un fallo aguas arriba disfrazado de dato
hay que verlo sin buscarlo.
Y de paso normalizadas 11 licencias con la barra antigua de Cargo (`MIT/Apache-2.0`), que
no es SPDX válido. Traducir la barra a OR no es inferir: Cargo documentó esa equivalencia.
═══ LA MEJORA: `scripts/licencias-cargo.sh` ═══
Lee la licencia que el AUTOR declara en su Cargo.toml, pidiéndola AL TAG QUE LA RECETA
PINEA (`?ref=v<version>`, con HEAD como último recurso y anotando cuál se usó). 176
obtenidas, 167 al tag exacto. Es la fuente más autoritativa de las que usamos y corrige los
dos defectos de la detección por API de una vez:
· las licencias DOBLES dejan de colapsar: `fd` pasa de `Apache-2.0` a `MIT OR Apache-2.0`,
`ripgrep` a `Unlicense OR MIT`, `bat` a `MIT OR Apache-2.0`;
· los SPDX AMBIGUOS caen de 71 a 55, porque el autor sí escribe -only/-or-later.
66 corregidas, 7 nuevas. Y aparecieron cosas que la detección había perdido: `eza` es
EUPL-1.2, una copyleft europea que se habría empaquetado creyendo otra cosa.
Jerarquía de evidencia, escrita en la cabecera del script: nombre (prohibido) < familia/URL
de fuente < API de licencias de GitHub < Cargo.toml del autor.
997 de 1141 (87%). Verificación COMPLETA sobre las 77 recetas tocadas —no una muestra—:
0 hashes cambiados, y 5 que ahora parsean y en HEAD no.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
fe474dab63 |
licencias: 994 de 1141 (87%) — cerradas las familias Qt, freedesktop, kernel.org y PyPI
Tercera tanda curada, agrupada por la URL DE FUENTE de cada receta (que es la evidencia que el nombre no da): los once módulos Qt sin prefijo, freedesktop (dbus, libinput, libevdev, libdisplay-info, poppler, pulseaudio, upower, NetworkManager, ModemManager, polkit), kernel.org (los tres kernels, linux-headers, git, iproute2, libuuid) y PyPI. Los kernels llevan `GPL-2.0-only WITH Linux-syscall-note` explícita. No es adorno: sin esa excepción, todo binario de espacio de usuario que hace un syscall sería obra derivada del kernel. Es exactamente el tipo de dato que un campo de licencia existe para no perder. Quedan 147 sin declarar: 69 de GitHub donde la propia API dice NOASSERTION (hay que abrir el fuente), 20 de tawasuyu —que son nuestras o del otro agente, así que la licencia la decide el usuario, no yo— y el resto repartido en GNOME, gitlab.freedesktop y sueltos. Más 71 con SPDX ambiguo pendientes de desambiguar (`licencias.sh --revisar`). Hashes verificados otra vez sobre 20 recetas tocadas: 20 idénticos, 0 cambiados. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
a6a9d59e4f |
licencias: 936 de 1141 (82%) — detección por evidencia, con sus dos imprecisiones declaradas
Esta mañana eran 0. Tras la tabla curada (228) y este paso, 936. Ninguna receta se
re-hasheó: verificado en 30 de las 708 tocadas, 30 hashes idénticos, 0 cambiados.
DE DÓNDE SALE EL DATO, Y POR QUÉ NO ES ADIVINAR. `scripts/licencias-detectar.sh` consulta
la API /repos/{o}/{r}/license de GitHub para las 673 recetas cuya fuente vive allí. Eso
devuelve el resultado de DETECTAR el fichero LICENSE que el repo tiene de verdad
(licensee), no una etiqueta escrita a mano en una web: es la misma evidencia que veríamos
abriendo el tarball, obtenida sin bajar 673 tarballs por un enlace de 8 Mbps. 610 con SPDX
definido; las 63 que GitHub marca NOASSERTION/other se DESCARTAN — un «no sé» de la fuente
se propaga como hueco, no se redondea a una licencia plausible.
Las familias no-GitHub van curadas por la URL DE FUENTE, que es la evidencia que el nombre
no da. Y ahí cometí el error simétrico al que este mismo fichero advertía: había puesto
`knighttime` entre las «herramientas Go» POR SU NOMBRE, y su tarball sale de
download.kde.org — es un Framework de KDE, LGPL. Descartar por nombre falla igual que
aceptar por nombre. Corregido en la cabecera.
LAS DOS IMPRECISIONES, contables con `licencias.sh --revisar` en vez de escondidas:
1. SPDX OBSOLETOS Y AMBIGUOS (71 recetas). GitHub devuelve `GPL-3.0`, `LGPL-2.1`,
`AGPL-3.0`… identificadores que SPDX declaró obsoletos PRECISAMENTE porque no
distinguen `-only` de `-or-later`, y esa diferencia decide con qué se puede combinar el
paquete. NO se normalizan a ciegas: mapear GPL-3.0 → GPL-3.0-or-later sería inventar el
dato que falta. Quedan marcadas para resolver mirando el fuente.
2. LICENCIAS DOBLES COLAPSADAS. La API devuelve UNA sola licencia y muchos proyectos Rust
son «MIT OR Apache-2.0» (p.ej. `fd` quedó como Apache-2.0). No es falso —cumplir una de
las opciones concedidas basta— pero es incompleto. Lo resuelve el cierre estructural:
leer el campo `license` del Cargo.toml en la fase de fetch.
Y un fallo que habría escrito basura en silencio: `licencias-detectadas.tsv` tiene TRES
columnas (añade el owner/repo consultado, para poder auditar) y el sembrador leía dos, así
que la licencia se habría llevado pegado el slug — `license = "MIT<TAB>owner/repo"`, sin
que nada lo validara. Arreglado antes de sembrar.
Quedan 205 sin licencia y 71 por desambiguar.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
7b2489a03c |
deuda del corpus: las 12 no eran un problema, eran cuatro — medido en el worker
Fui a destrabar «las 12 recetas en deuda» con el diagnóstico heredado (fallan por el rootfs
del worker: python OSError en meson, find_package en cmake). Lo probé construyéndolas de
verdad y **el diagnóstico es falso**: cmake y meson corren perfectamente ahí. Son cuatro
situaciones distintas y ninguna es el rootfs.
(a) SEIS ESTÁN SUPERADAS, NO EN DEUDA. `gtk4` del corpus es link=static y enlaza
libfontconfig.a, que tiene 1122 reubicaciones no-PIC ⇒ 13.032 errores
`R_X86_64_64 cannot be used against local symbol`. No es una receta rota: es imposible.
Y mientras tanto recipes/incoming-gnome/gtk4.toml (link=dynamic, deps -shared) YA ESTÁ
SELLADA, con libadwaita y fontconfig-shared. O sea que la cadena estática del corpus
—gtk4, libadwaita, gtksourceview y los tres hello/edit que cuelgan— es un DUPLICADO
superado de la cadena dinámica de GNOME.
Cerrarla no es construirla: es decidir si se promueven las sombras -shared al corpus,
porque la resolución de deps es hermano→padre. Es una decisión de arquitectura, y hay
aviso registrado de que promover a ciegas hace que variantes homónimas pisen recetas
canónicas. NO la tomo yo.
(b) wlr-randr: cerrada en el commit anterior.
(c) dwarves: frente propio con muro identificado, no deuda. Nuestro elfutils entrega SÓLO
libelf a propósito (libdw arrastra argp/obstack/fts, lo difícil en musl). No se arregla
ampliando elfutils: de él cuelga el kernel que ya reproduce bit a bit. El camino es una
receta aparte `elfutils-libdw`, con el patrón de las sombras -shared. Sin urgencia:
ningún perfil pide dwarves y el kernel desactiva DEBUG_INFO_BTF justamente por su
ausencia. Queda escrito en la cabecera de la receta, que es donde se va a leer.
(d) mirada-compositor, mirada-greeter, llimphi-counter: source por SSH a
git.tawasuyu.net y el worker es SIN SECRETOS por diseño ⇒ HUB-ONLY estructural, no
fallo. llimphi-counter ni siquiera llega a construir: su commit son ceros con el
comentario «fijar al commit real». Receta sin terminar, y es de tawasuyu.
EL HALLAZGO DE FONDO: el bucle del worker sólo recorre las colas incoming-*; el corpus
(recipes/) NO está en QUEUES. Las 12 nunca se habían intentado allí. Buena parte de «la
deuda» era de ENCOLADO, no técnica — y por eso el diagnóstico heredado nunca se verificó.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
f24b52df18 |
wlr-randr: SELLADA — eran dos deps ausentes, no el rootfs del worker
Primera de las 12 recetas del corpus en deuda, cerrada. Y de paso desmiente el diagnóstico
heredado («las 12 fallan por el rootfs del worker: python OSError en meson, find_package en
cmake»). Medido hoy contra el worker, las causas son CUATRO distintas y ninguna es el
rootfs:
· gtk4 construye ahí SIN TOCAR NADA. Nunca había fallado: el bucle del worker sólo recorre
las colas `incoming-*` y NO incluye el corpus, así que las 12 jamás se intentaron. La
deuda no era técnica, era de encolado.
· wlr-randr (ésta): dos deps que faltaban en la receta.
· dwarves: FindDWARF no halla las libs ELF/DWARF pese a declarar elfutils. Pendiente.
· mirada-compositor, mirada-greeter, llimphi-counter: `repo = gitea@git.tawasuyu.net:...`
por SSH. El worker es SIN SECRETOS por diseño ⇒ son HUB-ONLY estructuralmente, no un
fallo. Y llimphi-counter ni siquiera es un fallo de build: su commit es literalmente
ceros, con un comentario «fijar al commit real» — es una receta sin terminar, y es de
tawasuyu.
LAS DOS DEPS DE ESTA RECETA, que son dos lecciones distintas:
1. `python3` — porque **meson es un script de Python, no un binario**. Faltando el
intérprete la fase muere con exit 127, que se lee como «meson no está» cuando meson SÍ
está y se hidrata bien. gtk4/libadwaita/gtksourceview construyen en el worker
precisamente porque sí lo declaran. Auditadas las 1141 recetas: wlr-randr era **la
única** con meson y sin python3. Regla: meson en deps ⇒ python3 al lado.
2. `libffi` — que wlr-randr no usa. Lo exige `wayland-client.pc` en su línea `Requires`, y
pkgconf resuelve el grafo de .pc completo antes de emitir un cflag. Patrón ya
documentado `.pc Requires` → `[deps].build`; el síntoma («Package 'libffi', required by
'wayland-client', not found») culpa a wayland, que es inocente.
En ambos casos el arreglo es hidratar la dep, NO instalar nada en el rootfs del worker:
engordarlo haría que el build dependa de qué hay en una máquina concreta, que es justo lo
que rompe la reproducibilidad.
Re-hashear sale gratis: la receta estaba en deuda, nunca se había sellado.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
346cd59706 |
licencias: campo license en la receta — de 0 a 228 de 1141, sin re-hashear nada
La deuda legal bloqueante del SDD 19 §2.1. Medido hoy: **0 de 1141 recetas** declaraban licencia, no «5 de 771» como decía el informe anterior. Los dos números estaban mal: los «5» eran falsos positivos de `grep license` (el paquete `addlicense`, el paquete `cargo-bundle-licenses`, una línea `install .../share/licenses/` y un comentario), y las recetas son 1141. Contar con `grep -l <palabra>` sobre TOML cuenta comentarios y nombres, no campos; `scripts/licencias.sh` cuenta el campo de verdad (clave en la raíz, antes del primer `[table]`). LO QUE HACE LA DEUDA PAGABLE: `Recipe::hash_inputs` es una LISTA BLANCA — sólo entran source, compiler, target, link, patches, flags, phases y deps. `license` no entra, igual que `evidence` y `slots`. Por eso se puede poblar en las recetas YA SELLADAS sin mover un solo ArtifactHash. Verificado, no supuesto: en 40 recetas modificadas se comparó el hash con y sin la línea — 40 idénticos, 0 cambiados. Si el campo entrara al hash, declarar la licencia costaría reconstruir el corpus entero y no se haría nunca. Clavado con el test `licencia_round_trip_y_no_afecta_el_hash`. TRAMPA DE TOML: una clave suelta después de un `[table]` pertenece a esa tabla. Puesta al final del fichero, `license` acaba dentro de `[deps]` y se pierde EN SILENCIO, porque serde ignora los campos que no conoce — no hay error, simplemente no está. Va arriba, junto a `name` y `version`; el sembrador la inserta tras `version`. NO SE ADIVINA. Declarar mal una licencia es peor que dejarla vacía: convierte un hueco visible en una afirmación falsa. Sólo se puebla desde una tabla curada entrada por entrada (`docs/licencias-conocidas.tsv`); lo que no tiene evidencia queda vacío y se CUENTA. Concretamente se descartó el atajo «k* = KDE ⇒ LGPL»: en este catálogo `kail`, `kind`, `ko`, `kopia`, `krew`, `kustomize`, `kyverno`, `katana`, `kibi`, `kmon` y toda la familia `kube*` son herramientas Go sin relación con KDE. El nombre no es evidencia. Quedan 913, casi todas CLIs Go/Rust importados en masa — y ésas sí son automatizables con evidencia real: Cargo.toml trae el campo `license` y los módulos Go traen su LICENSE en el árbol. El cierre estructural es capturarlo en la fase de fetch, que ya descarga y extrae cada tarball, y inyectar el texto en `hammer pack` (aguas abajo del ArtifactHash) en vez de en la fase install (que sí re-hashearía). De paso, respaldo-storagebox.sh reordenado por valor irreemplazable y con zstd: medido en la oficina, el uplink da 8 Mbps iguales por cable y por wifi ⇒ 128 G no caben en una sentada, así que sube primero el cerebro (estado + repo) y `--partial-dir` hace que cortar a mitad de un artefacto no tire lo ya subido. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
85c25619ad |
recipes: wlr-randr 0.5.0 — el testigo ajeno del protocolo de salidas
La paridad cosmic no se demuestra con un cliente nuestro (eso probaria que nos entendemos con nosotros mismos), se demuestra con la herramienta que usa el resto del mundo. wlr-randr habla wlr-output-management-unstable-v1, que mirada sirve. Entra a base-system-1 con ese rol acotado. C sobre meson, 28 KB, trae el XML del protocolo adentro: solo wayland-client. Tarball de release y no el -/archive/ autogenerado de GitLab, que no es estable byte a byte y rompe el sha256 pinneado con el tiempo. Queda anotado en la receta lo que hoy NO puede hacer, para no acusar al paquete: en mirada apply/test de zwlr_output_configuration_v1 contestan failed, asi que wlr-randr lista bien y no cambia nada. Cuando mirada implemente el apply, esta misma receta pasa a probar tambien el apply. Por lo mismo no entran kanshi ni way-displays: no son herramientas sino una funcion —perfiles de salida por hotplug— y su lugar es adentro de mirada, que ya tiene el estado. Instalarlos hoy seria ademas inutil. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
aeac4a2ebb |
gnome: xdg-desktop-portal-gnome SELLA — isla de libadwaita + frontend a 1.19.4
Cae el último muro real de la cola GNOME. Cuatro piezas, ninguna en la receta que fallaba: 1. SOMBRA de libadwaita en incoming-gnome/. El «relocation ... libfontconfig.a» no lo ponía xdp-gnome sino el cierre de la libadwaita del CORPUS, receta de la era estática. La del corpus no se toca (3 dependientes ahí). 2. libyaml-shared: la única no-PIC del cierre de libadwaita sin variante. 3. xdg-desktop-portal 1.19.4 en esta cola (COSMIC sigue en 1.18.4). xdp-gnome 48 exige >=1.19.1, y el corte de la dep dura de gstreamer es 1.19.1 EXACTO —1.19.0 no la pide—, así que no hay versión que cumpla ambas. Se saca con dos sed: gstreamer alimenta un solo binario auxiliar (validate-sound) que el daemon invoca por exec, no linkea. Precio: notificaciones con sonido propio quedan rechazadas. Barato vs traer gstreamer+gst-plugins-base al corpus. 4. gettext-tiny + los cierres .pc de libadwaita-1 y gnome-desktop-4. Y se corrige una regla que estaba MAL escrita en la receta: medir PIC con `readelf -r x.a | grep R_X86_64_32` cuenta las reubicaciones de .rela.debug_*, inocuas y presentes en todo objeto. Así medido libepoxy da 39.630 «no-PIC» y sin embargo está embebida dentro de la libgtk-4.so de la isla, con 3.446 símbolos epoxy_ definidos. Excluyendo debug el control sale limpio (libepoxy=0, fontconfig=1122), y el barrido dio 7 no-PIC en vez de 13: ahorró cinco builds, dos de ellos openssl y curl. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
8aee137e36 |
gnome: xdp-gnome a la isla dinámica + diagnóstico del muro que queda
Deps canónicas -> variantes -shared, y link=static -> dynamic: la receta era de la era estática y el link moría con «relocation R_X86_64_64 ... recompile with -fPIC» sobre libfontconfig.a. No sella todavía, y el muro queda MEDIDO en la receta para que nadie itere en falso: el cierre tiene un único camino a la fontconfig estática, xdp-gnome -> libadwaita -> fontconfig, y esa libadwaita es la del CORPUS, una receta entera de la era estática (gtk4/glib/cairo/pango canónicas). No le falta una variante: no pertenece a la isla dinámica. El paso siguiente es una sombra de libadwaita en incoming-gnome, como se hizo con glib. `yupana radio libadwaita` = 4 dependientes, 0 sellados cayendo. El frontend generico xdg-desktop-portal SI sello (b3:db5e5cf8). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
29d6b32312 |
gnome: cerrar la frontera de xdg-desktop-portal en la cola GNOME
xdg-desktop-portal-gnome documentaba en prosa que le faltaba el frontend genérico («la dep dura que falta»). La campaña COSMIC ya lo autoró y selló, así que se copia a incoming-gnome/ junto con su dep fuse3 y se declara. NO es cache-hit, y conviene dejarlo escrito: desde incoming-gnome el cierre resuelve contra la glib de la isla dinámica en vez de la de COSMIC, así que el ArtifactHash se mueve (f4adb8c9 -> db5e5cf8) y hay que construirlo. Es lo correcto —backend y frontend tienen que compartir glib— y es el mismo patrón ya medido con pipewire. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
adbda20e30 |
🏁 ScreenCast CERRADO en metal — la cadena entera devuelve un stream real
Sube el pin de portal-probe a
|