Commit Graph
2932 Commits
Author SHA1 Message Date
SergioandClaude Opus 5 fd96229ce2 shuma entra al catálogo: el último vhost de gioser se DECLARA en vez de copiarse
Decisión del usuario: `/shuma/*` —lo único que todavía ata `sergio.gioser.net` a la máquina que se
borra— se construye desde el monorepo de tawasuyu, no se muda como binario.

Y no es una preferencia de estilo: el `shuma-gateway` que corre hoy en gioser es ELF **glibc**,
puesto a mano, y su **inodo está BORRADO del disco** — vive mientras el proceso no muera. El
`shuma-daemon` igual. Copiarlos sería mudar dos binarios que nadie puede reconstruir a una caja que
no tiene su cargador.

Dos recetas Cargo contra el monorepo, pinneadas a `23a292863` — **el mismo commit que ya usa
`puriy-costura`**, a propósito: el árbol de fuentes se comparte por `<dep>-<sha>`, así que dos pines
distintos son dos vendoreos de 2,4 G en vez de uno. Estáticas musl con zig-cc, que es lo que pide un
servicio que arranca el init de la caja.

Comprobado antes de encolar: los dos crates son miembros del workspace en ese commit, el
`Cargo.lock` está commiteado, `rust-version = 1.80` contra el 1.97.0 del lab, y reqwest va por
rustls (nada de openssl). `takana hash` da b3:107dfb54 (gateway) y b3:f9b92acc (daemon), ninguno
sellado todavía.

Van a `recipes/incoming/` —la cola que el worker muele, primera en QUEUES— y no a `recipes/`
canónico: se promueven cuando sellen, que es el orden documentado. Un fichero en `recipes/` a secas
NO lo muele nadie.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 15:21:33 +00:00
SergioandClaude Opus 5 e2bb4f9b89 censar: «no existe» y «no puedo mirar» se confundían — 572 M invisibles, y el censo de hoy
El censo ya tenía tres estados a propósito (`ausente` / `sin_permiso` / `ok`), pero el tercero sólo
se detectaba sobre la PROPIA ruta: cuando el que no deja pasar es un ANCESTRO, `[ -e "$p" ]`
contesta que no existe y la ruta caía en `ausente`, que el censo descarta sin decir nada.

Medido en gioser: `/root/.local` es 0700 ⇒ un censo corrido como `sergio` daba `/root/.local/bin`
por AUSENTE. Como root son 572 M de binarios puestos a mano que ningún paquete provee — justo la
clase que la mudanza no puede reconstruir.

Arreglado: si un ancestro existe y no es atravesable, el estado es `sin_permiso`. Probado en los dos
sentidos, que es lo que separa un guardián de un adorno:

  ancestro 0700 de otro dueño   →  sin_permiso   (sale en el ⚠ del resumen)
  ruta que NO existe de verdad  →  ausente       (no se reporta)   ← el control que tiene que pasar

Con el arreglo, el censo sin privilegio pasa de 2 rutas ciegas a 13, entre ellas el home entero de
`artix`, que antes no figuraba de ninguna manera.

Y el §6.34 con el estado MEDIDO de la mudanza hoy: de los 29 dominios queda UNO sirviéndose desde
gioser (`sergio.gioser.net`); los otros seis vivos ya contestan 200 contra 2.29.29.217. El rescate
del §6.20 sigue coincidiendo bit a bit con cuatro de los seis procesos que corren desde un inodo
borrado, y los otros dos tienen en disco una versión más nueva. Lo que queda abierto son los pasos 6
y 7: el montón de daemons propios (shuma, willay, pacha, tejido, tupu, matilda…) y los datos.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 15:11:16 +00:00
Sergio fff28ad53f estado: cosecha granja 2026-09-16T15:01:36Z — avance del árbol KDE 2026-09-16 15:01:36 +00:00
Sergio ffe959d567 estado: cosecha granja 2026-09-16T14:31:36Z — avance del árbol KDE 2026-09-16 14:31:36 +00:00
Sergio fde7cb8ef2 puriy-costura: el pin sube a 23a292863 — la boveda de atuq deja de hablarle a un host sordo
El pin viejo (`e19bb0e5`) era ANCESTRO del commit que agrego los verbos de la boveda, asi que `atuq`
mandaba `vault.match` y el host contestaba «verbo desconocido»; la extension lo lee como «no hay
boveda», borra la insignia y se calla. Navegador sin la funcion y ficheros en orden — el fallo mas
caro de encontrar que tiene este cable (SDD 26 §7.quinquies).

Estaba bloqueado por algo que no era de takana: el `Cargo.lock` de tawasuyu no cerraba para este
crate. Publicado alla como `23a292863`, regenerado en un arbol LIMPIO del commit: 215 lineas, todas
de contabilidad de deps por ruta, **cero `checksum` y cero `source` movidos** — ninguna version de
registry se toco. Y el lock publicado resulto ser BYTE A BYTE el que la otra sesion ya tenia en su
arbol sin commitear, asi que no compite con su trabajo: es el suyo.

Commiteado alla con un indice TEMPORAL (`GIT_INDEX_FILE` + `commit-tree`) porque ese fichero estaba
en vuelo en el clon compartido y `git commit -- Cargo.lock` se habria llevado el arbol pisando lo
que el otro agente tuviera stageado (regla 2 de CLAUDE.md, el segundo aviso).

⚠ El artefacto todavia NO esta: el vendoreo son 2,4 G y el disco del hub esta al 99% (lo llena
`tawasuyu/target`, que no es mio para podar), asi que se construye en el worker. Hasta que vuelva,
los guardianes que usan el host quedan en rojo por ausencia del artefacto, no por rotura.
2026-09-16 14:24:25 +00:00
Sergio fb7dba530d atuq: el que estaba «nombrado como hueco» entra a la suite — 17 verdes y 2 rojos en 32 min
La primera version dejaba afuera al guardian de notificaciones (`dunst-headless.sh --via-atuq`) con
la excusa de que vive en el arnes de sway, y lo escribia en la cabecera «para que su ausencia no se
lea como cobertura». Eso dura tres dias: al cuarto la lista ES la cobertura y el parrafo no lo lee
nadie. Corrido aparte: verde en 180 s. Entra.

Es ademas el que mide lo que ningun auditor de ELF puede ver: una pagina llama `new
Notification(...)`, `libxul` hace `dlopen("libnotify.so.4")` —que no es NEEDED de nada—, el bus
activa dunst y dunst DIBUJA. Cinco piezas y la unica forma de saber que estan las cinco es verlo.

Para que entrara, la lista pasa a llevar el COMANDO de cada guardian en vez de su nombre de fichero:
lo que lo tenia afuera era el despacho por extension, no una decision.

Corrida entera de los diecinueve sobre `b3:e556024b`: **17 verdes, 2 rojos, 32,2 min**, que es
exactamente lo que la cabecera predice — y la cabecera es el control, no un adorno.

Los caros: sct 242 s, archivo semantico 238 s, ia 182 s, instalacion 180 s, notificaciones 180 s.
Los cuatro primeros salen en 5 s y no tocan el navegador.
2026-09-16 14:05:51 +00:00
Sergio 216b981484 estado: cosecha granja 2026-09-16T14:02:14Z — avance del árbol KDE 2026-09-16 14:02:14 +00:00
SergioandClaude Opus 5 eaa7d02725 el corte, con hora: 93 minutos — y en un servicio que ya autoriza no va límite por tasa
Del `access.log`, sin ambigüedad. La IP del usuario (`45.234.61.160`, autenticada como `sergio`,
2709 peticiones) tuvo tres silencios: **93,2 min (11:59:37 → 13:32:49 UTC)**, 50,1 min (10:44:58 →
11:35:06) y 10,0 min (11:45:06 → 11:55:05). Los tres son el `timeout` de 10 minutos del ban
disparándose una y otra vez: cada vez que volvía, su primera ráfaga lo baneaba de nuevo. El corte
grande terminó exactamente cuando vacié los sets.

🧨 Y LA EXENCIÓN QUE TENÍA NO SERVÍA: la ACL histórica de squid exime `45.234.60.0/24` y él entra
desde `45.234.61.160` — **una red de al lado**. Parecía cubierto y no lo estaba. La pertenencia se
MIDE (`ip in red`), no se deduce del parecido del prefijo.

DECISIÓN DE FONDO: en un servicio que YA AUTORIZA no va límite por tasa. El uso de esta caja es
INTENSIVO —varias sesiones de agente en paralelo, cada una abriendo túneles a la vez— y un límite
calibrado para «una persona normal navegando» no protege de nada: el atacante ajusta su ritmo, el
usuario no puede trabajar más despacio. Squid ya pide usuario y contraseña y tiene su ACL. El ban del
puerto queda apagado (60000/min, ráfaga 1000) y contra un flood queda el tope GLOBAL
`syn_nuevas_por_seg`, que no distingue usuarios ni banea a nadie por ser rápido.

Control tras aplicar: su túnel pasando —`45.234.61.160 … CONNECT api.anthropic.com:443 sergio`— y
`45.234.61.160 ∈ 45.234.60.0/23` comprobado con aritmética de redes, no a ojo.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 13:38:54 +00:00
SergioandClaude Opus 5 618dcfd851 🧨 el cortafuegos baneaba a los usuarios del proxy — y squid nunca se cayó
Preguntaron si el proxy estaba caído. NO lo estaba: el ente llevaba horas corriendo con ↻ 0 y
contestando 407. Lo caído era el ACCESO — el cortafuegos de ayer baneaba a los autorizados.

La prueba en una línea: **154.197.1.2, una IP que está en la ACL de squid (gente con contraseña),
apareció en `@ban4`**, con el contador del ban en 38.246 paquetes tirados.

LA CAUSA NO ES LA TASA, ES LA RÁFAGA: `limit rate over 300/minute burst 5 packets` tolera cinco
conexiones por encima del promedio, y un navegador o un agente detrás de un proxy abre DECENAS de
CONNECT en el mismo instante aunque su promedio sea bajísimo. Y como @ban4 es UN SOLO set consultado
antes que todo, caer por el puerto del proxy te tira también el web y el git.

⚠ El tipo ya traía el campo `rafaga` (default 5) con un comentario que dice «para un servicio web va
alto (100-200)». Otra vez leí el .ron de EJEMPLO y no el TIPO.

Hecho, en orden de urgencia: flush de los sets (servicio restaurado en el acto) · los 21 IPs y 5
redes de la ACL de squid a `confiables` · `rafaga` por servicio según su clientela (ssh 5, git 20,
web 100, proxy 200) · proxy a 1200/min con ban de 60 s, que es red de contención contra un flood y
no control de uso. Control después: CERO autorizados en el set, 24 baneados (escáneres) y tráfico
real pasando —`154.194.14.37 … CONNECT api.deepseek.com:443 sigma`, 298 K tunelados—.

⚠⚠ Y un fallo de método que casi lo tapa: **`nft -f` SUMA a la tabla existente**. Cargué el reglaset
corregido encima del viejo y quedaron 30 reglas con las VIEJAS ADELANTE, así que los `confiables`
nuevos no se evaluaban nunca. Por eso `cortafuegos apply-input` borra la tabla antes de cargar.

La lección: un cortafuegos correcto y uno usable no son lo mismo, y la diferencia NO se ve al
aplicarlo. El control que lo habría cazado es el que no corrí: una ráfaga de conexiones desde una IP
que no esté en `confiables`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 13:33:50 +00:00
Sergio 9923aa2779 estado: cosecha granja 2026-09-16T13:32:44Z — avance del árbol KDE 2026-09-16 13:32:45 +00:00
SergioandClaude Opus 5 65dab8d262 rust: rpath = false, la pareja obligatoria de poner lld como enlazador directo
El build con `ld.lld` en el spec murió compilando `std`:

    ld.lld: error: unknown argument '-Wl,-z,origin'
    ld.lld: error: unknown argument '-Wl,-rpath,$ORIGIN/../lib'

Con el enlazador invocado DIRECTO (sin driver de C), los `-Wl,…` que el bootstrap añade para el
rpath de sus propios binarios llegan tal cual a lld, que no los entiende — esa sintaxis existe para
que un `cc` los traduzca.

El rpath sobra igual: con `prefix = "/usr"` las librerías quedan en `/usr/lib`, que ya está en el
camino del cargador. Es lo que hacen las distros que empaquetan rust.

Costó 6 minutos de build descubrirlo, que es lo que vale tener la cadena en la granja: cada intento
falla temprano y con el mensaje exacto.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 13:21:12 +00:00
SergioandClaude Opus 5 e903f486d9 el enlazador va DENTRO del compilador — /etc/cargo/config.toml es una ruta que cargo no lee
La prueba de la caja recién instalada —`cargo build` en un proyecto nuevo, sin flags ni rutas a
mano— falló con `linker `cc` not found`, y destapó que la pieza que había empaquetado era falsa:
**cargo NO LEE `/etc/cargo/config.toml`**. Sólo lee `$CARGO_HOME/config.toml`, los
`.cargo/config.toml` del proyecto y sus padres, y lo que se le pase con `--config` — que es lo que yo
venía pasando a mano en cada prueba, y por eso «funcionaba».

Y el arreglo no era mover el fichero: **el que enlaza es `rustc`, y rustc no lee la config de
cargo**. Las flags van DENTRO del compilador, en el spec del triple:

· `linker = "ld.lld"` + `linker_flavor = Gnu(Cc::No, Lld::Yes)` — sin esto rustc busca `cc`, que una
  caja takana no tiene.
· `crt_static_default = true` — sin esto enlaza dinámico y pide `-lgcc`, que no existe (la distro se
  construye con zig, que trae compiler-rt).
· `crt_static_allows_dylibs = true` — su pareja obligatoria: sin ella `crt-static` apaga los dylibs
  y con ellos los PROC-MACROS (serde_derive, clap_derive, las 44 recetas `cargo-*` con `derive`).
  El compilador en sí sigue dinámico: el `bootstrap.toml` fija `crt-static = false` para el build, y
  eso gana sobre el default del spec.

⇒ `cargo-config` (receta, árbol y copia en scripts/) se van enteros: un paquete que instala un
fichero que nadie abre es peor que no tenerlo.

Y de paso, `lld21` instala los cuatro alias como SYMLINKS y no como copias: cmake los duplicaba, 5 ×
96 M = 478 M de artefacto para 97 M de enlazador. Ahora 108 M, y `ld.lld` sigue despachando por
`argv[0]`, que es como upstream lo diseñó.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 13:07:56 +00:00
Sergio c57fcb214f estado: cosecha granja 2026-09-16T13:02:56Z — avance del árbol KDE 2026-09-16 13:02:56 +00:00
SergioandClaude Opus 5 0a894cfac1 perfil.servidor: fuera el prebuilt ajeno, entra el toolchain propio
Sale `rust-toolchain-bin` —799 M de bytes AJENOS sellados tal cual (`foreign`)—, que era el escalón 1
del SDD 31 y cumplió su función: con él se construyó el escalón 2, y el escalón 2 ya compila,
enlaza y corre.

Entran TRES, que son el mismo hecho («esta caja compila Rust») partido en piezas:
· `rust` (353 M) — el compilador y cargo, de la granja, desde fuente.
· `lld21` — el enlazador. NO es opcional: una caja takana no tiene `cc`, y sin enlazador `rustc`
  compila objetos y no produce un ejecutable.
· `cargo-config` — receta nueva que publica `/etc/cargo/config.toml` con las tres flags que unen a
  los dos. Sin ellas `cargo build` muere con «linker `cc` not found»: el toolchain estaría completo
  y MUDO, que es [[subcomando-sin-driver]] otra vez. Es config de SISTEMA y no de usuario a
  propósito — un `~/.cargo/config.toml` funcionaría para quien lo escribió y no para el siguiente.

⚠ Y `rust` se re-hashea otra vez (702094a8 → fe277b32) por una línea que descubrió el control de
PATH: **x.py instala en `/usr/local` por defecto, y el PATH de una caja takana es
`/bin:/usr/bin:/sbin:/usr/sbin`** — medido en la caja. O sea que el perfil habría proyectado un
`rustc` perfecto que nadie puede invocar: «existe ≠ se encuentra». Ahora `[install] prefix = "/usr"`,
como el resto del corpus.

Control previo que sí pasó: `rustc` y `cargo` corren SIN `LD_LIBRARY_PATH` — su `RUNPATH` es
`$ORIGIN/../lib`, así que la proyección del artefacto basta.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 12:38:15 +00:00
Sergio 240069801e estado: cosecha granja 2026-09-16T12:32:03Z — avance del árbol KDE 2026-09-16 12:32:03 +00:00
Sergio d22bc8443a estado: cosecha granja 2026-09-16T12:02:13Z — avance del árbol KDE 2026-09-16 12:02:13 +00:00
Sergio f8a900a923 estado: cosecha granja 2026-09-16T11:32:14Z — avance del árbol KDE 2026-09-16 11:32:15 +00:00
SergioandClaude Opus 5 72ba86c290 la cadena rehecha: llvm21 arreglado, lld enlaza, rust reconstruido — los seis controles pasan
Un cambio de dos líneas en `llvm21` re-selló tres artefactos y los molió la granja sola, en orden,
por dependencia: llvm21 95956a16→bd4a4094, lld21 27be53c1→95a4794b, rust 015a07fb→702094a8.

    llc --version        Stack dump: + segfault   →   LLVM 21.1.2, Optimized build
    opt --version        ídem                     →   LLVM 21.1.2
    ld.lld               «not built with zlib»    →   ENLAZA
    rustc --version                               →   1.97.0 (built from a source tarball)
    --print target-list                           →   x86_64-alpine-linux-musl
    cargo build + correr                          →   0,16 s y el binario habla

La config del sitio pasa a usar `lld` (más rápido); el `ld` de binutils queda documentado como
alternativa que también funciona.

LA REGLA QUE SE GANÓ SU LUGAR: **`link = "static"` en el encabezado decide cosas que la receta no
dice**. Van tres, todas medidas: apagó los threads de openssl, le mintió a libtool, y acá rompió los
registros estáticos de LLVM (`cl::opt`, `TargetRegistry`) porque el `static-pie` descarta sus
constructores globales. Con C++ grande la postura por defecto pasa a ser `dynamic` y medirlo — y el
control no es que selle: es CORRER UNA HERRAMIENTA del artefacto.

Y el corolario de por qué nadie lo vio en meses: el único consumidor de llvm21 era rust, que usa
`llvm-config` y las `.a`, nunca una herramienta. **Un artefacto puede estar roto en todo lo que nadie
usa** — como los 44 `cargo-*` sin cargo y los 23 binarios sin cargador.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 11:19:18 +00:00
Sergio 3a68db44b8 estado: cosecha granja 2026-09-16T11:02:38Z — avance del árbol KDE 2026-09-16 11:02:38 +00:00
SergioandClaude Opus 5 bad2b1c63a llvm21: dynamic y con zlib — las 79 herramientas dejan de crashear, y rust se rehace detrás
Dos cambios, los dos medidos, y los dos re-sellan la cadena entera (`link` y las deps son entrada de
hash): `llvm21` 95956a16… → bd4a4094…, `rust` 015a07fb… → 702094a8…, `lld21` → 95a4794b…

1. `link = "dynamic"`. Con `static`, las 79 herramientas que publica el artefacto CRASHEAN —`llc
   --version` incluido, y también en el worker, o sea que es el build y no el entorno—: salen
   `static-pie` y el enlace estático descarta los constructores globales de los que dependen los
   registros de LLVM (`cl::opt`, `TargetRegistry`). Funciona lo que no los necesita (`llvm-ar`,
   `llvm-config`) y revienta lo que sí. **No se notó en meses porque el único consumidor, `rust`, usa
   `llvm-config` y las `.a` — nunca una herramienta.** Lo destapó `lld21`, que enlaza contra estas
   mismas librerías: estático crasheaba con cualquier entrada, dinámico da errores limpios.
2. `-DLLVM_ENABLE_ZLIB=ON` + dep `zlib`. Sin eso, cualquier `lld` construido contra este LLVM hereda
   `LLVM_ENABLE_ZLIB 0` de `LLVMConfig.cmake` y no puede leer las secciones de depuración COMPRIMIDAS
   que trae la libc del lab. Encenderlo acá es la única vía: el build standalone de lld no puede
   contradecir a su LLVM.

Las `.a` que consume `rust` no cambian de contenido —el flag sólo quita el `-static` del enlace de
los EJECUTABLES— pero el hash sí, y eso es correcto: es lo que hace que la granja rehaga rust con un
LLVM cuyas herramientas funcionan.

Los tres hashes coinciden hub↔worker antes de sembrar.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 10:36:20 +00:00
Sergio 2ff2a31150 estado: cosecha granja 2026-09-16T10:31:47Z — avance del árbol KDE 2026-09-16 10:31:47 +00:00
Sergio 5d30ef4b58 estado: cosecha granja 2026-09-16T10:01:44Z — avance del árbol KDE 2026-09-16 10:01:44 +00:00
Sergio 10878bf4a7 estado: cosecha granja 2026-09-16T09:31:22Z — avance del árbol KDE 2026-09-16 09:31:22 +00:00
Sergio c936d55675 estado: cosecha granja 2026-09-16T09:02:07Z — avance del árbol KDE 2026-09-16 09:02:07 +00:00
Sergio 83f5ec6e66 estado: cosecha granja 2026-09-16T08:31:20Z — avance del árbol KDE 2026-09-16 08:31:20 +00:00
Sergio 3a58cc6cbe estado: cosecha granja 2026-09-16T08:01:51Z — avance del árbol KDE 2026-09-16 08:01:51 +00:00
Sergio c0fbf75353 estado: cosecha granja 2026-09-16T07:31:21Z — avance del árbol KDE 2026-09-16 07:31:21 +00:00
Sergio ba6680c7b2 estado: cosecha granja 2026-09-16T07:01:54Z — avance del árbol KDE 2026-09-16 07:01:55 +00:00
Sergio 611d420f99 estado: cosecha granja 2026-09-16T06:31:20Z — avance del árbol KDE 2026-09-16 06:31:20 +00:00
Sergio 60e6197970 estado: cosecha granja 2026-09-16T06:01:45Z — avance del árbol KDE 2026-09-16 06:01:45 +00:00
Sergio afae751e65 estado: cosecha granja 2026-09-16T05:31:21Z — avance del árbol KDE 2026-09-16 05:31:21 +00:00
Sergio 4a6696bb52 estado: cosecha granja 2026-09-16T05:01:35Z — avance del árbol KDE 2026-09-16 05:01:35 +00:00
SergioandClaude Opus 5 ef1f9252a1 EL TOOLCHAIN COMPILA, ENLAZA Y CORRE — en una caja sin compilador de C
$ cargo build --offline
       Compiling prueba v0.1.0 … Finished in 0.44s
    $ ./target/debug/prueba
    cargo, rustc y ld: los tres nuestros

`cargo` y `rustc` son los que construyó la granja; el enlazador es el `ld` de nuestro `binutils`.

EL MURO 8 SE CERRÓ SIN `lld`. La cadena, que es lo que vale: `-C linker-flavor=ld.lld` → «linker
`lld` not found» (el build con LLVM externo no genera rust-lld); `rust.lld = true` → el bootstrap lo
RECHAZA; `lld21` propio → crasheaba con cualquier entrada; `lld21` con zlib → **no se puede encender
desde ahí**, porque `LLVMConfig.cmake` dice `LLVM_ENABLE_ZLIB 0` y el build standalone lo hereda.

Lo que faltaba NO era un enlazador: era decirle a rustc que enlace en ESTÁTICO. Con `+crt-static`,
rustc usa su propio libunwind/compiler_builtins y deja de pedir `-lgcc` — que es lo que rompía el
intento con `ld`, porque la distro se construye con zig (compiler-rt) y libgcc no existe. Y estático
es el modo natural de musl.

⇒ `scripts/servidor/cargo-config.toml` (instalado en `/etc/cargo/config.toml`) cierra el pendiente
«config del sitio» del §5, con las tres flags y el porqué de cada una.

🧨 Y `lld21` destapó algo que nadie había visto: **las 79 herramientas de `llvm21` están ROTAS**.
`llc --version` crashea igual —también en el worker— porque salen `static-pie` y el enlace estático
descarta los constructores globales de los que dependen `cl::opt` y `TargetRegistry`. Funciona lo
que no los necesita (`llvm-ar`, `llvm-config`) y revienta lo que sí; nadie lo notó porque `rust` usa
`llvm-config` y las `.a`, nunca una herramienta. Queda como deuda DECLARADA: arreglarlo (o encender
zlib) re-hashea `llvm21` y con él `rust`. Hoy no bloquea nada.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 04:48:25 +00:00
SergioandClaude Opus 5 201973b8f6 lld21: dinámico y con zlib — dos fallos que sólo se ven USÁNDOLO
El primer `lld21` selló, arrancó y se moría en cuanto hacía algo: `--version` y `--help` contestaban
bien, y CUALQUIER enlace —incluso uno que sólo debía dar un error, como un fichero de entrada
inexistente— terminaba en SIGSEGV con el banner de LLVM y un «Stack dump:» vacío.

🧨 Y no era culpa de esta receta: **las 79 herramientas que publica `llvm21` tienen el mismo defecto**
—`llc --version` también crashea, y también en el worker— porque salen `static-pie` y el enlace
estático descarta los constructores globales de los que dependen los registros de LLVM
(`cl::opt`, `TargetRegistry`). Lo que funciona es lo que no los necesita (`llvm-ar`, `llvm-config`),
y por eso nadie lo había visto: `rust` usa `llvm-config` y las `.a`, nunca una herramienta.
⇒ `link = "dynamic"` en esta receta (como `openssl-threads`, y por lo mismo: el flag global decide
cosas que la receta no dice). Control en los dos sentidos: con `static`, SIGSEGV; con `dynamic`,
`ld.lld: error: cannot open /no/existe.o: No such file or directory` — un error limpio.

Y el segundo, ya enlazando de verdad con nuestro rustc:

    lld: error: …/self-contained/crtn.o:(.debug_line) is compressed with ELFCOMPRESS_ZLIB,
         but lld is not built with zlib support

Los objetos `crt*` del sysroot de rust llevan las secciones de depuración COMPRIMIDAS. Para `llvm21`
apagar zlib era gratis; para el ENLAZADOR no lo es. ⇒ `-DLLVM_ENABLE_ZLIB` encendido y `zlib` a las
deps — copiar los flags del hermano sin preguntarse qué hace cada uno es lo que lo causó.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 04:36:38 +00:00
Sergio 8f3bc54f55 estado: cosecha granja 2026-09-16T04:31:36Z — avance del árbol KDE 2026-09-16 04:31:36 +00:00
Sergio cea668376c estado: cosecha granja 2026-09-16T04:02:11Z — avance del árbol KDE 2026-09-16 04:02:11 +00:00
SergioandClaude Opus 5 9f325a3c05 🐛 la granja molía UNA receta por cola y por ciclo — el xargs -I{} recibía la cola entera junta
Medido hoy al encolar `lld21` junto a `rust`: el ciclo decía «2 recetas en recipes/incoming» y
construía UNA. La causa está en el filtro de «ya sellado en el hub»: acumula en `filtrada` uniendo
con ESPACIOS, y más abajo la cola se le pasa a `xargs -I{}`, que trata **una línea = un elemento**.
Unidas por espacios, N recetas llegan como UN SOLO argumento:

    printf '%s\n' " a.toml b.toml c.toml" | xargs -I{} sh -c 'echo [$1]' _ {}
      recibe: [a.toml b.toml c.toml]          ← uno solo

⇒ la fase paralela fallaba SIEMPRE con «No such file», y la fase 1b —el reintento serial— salvaba
exactamente UNA receta: la última, porque `basename` de esa ristra da el último nombre. El log
parecía normal, con su ✗ seguido de un ✓ (reintento serial), y ese patrón está en TODAS las colas
(yambar, spidermonkey, rust…). O sea que el reintento serial, que existe para conciliar colisiones
de concurrencia, venía tapando el bug desde que se escribió el filtro.

El arreglo son dos líneas: acumular con salto de línea y descartar la línea vacía con la que arranca
el acumulador (una línea vacía también es un elemento para `xargs -I{}`). Probado en chiquito, en
los dos sentidos: antes 1 elemento, después 3.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 04:00:08 +00:00
Sergio 3f3bb2ed16 estado: cosecha granja 2026-09-16T03:31:40Z — avance del árbol KDE 2026-09-16 03:31:40 +00:00
Sergio ffe26377fb estado: cosecha granja 2026-09-16T03:01:33Z — avance del árbol KDE 2026-09-16 03:01:34 +00:00
Sergio 4f78a80c47 estado: cosecha granja 2026-09-16T02:31:35Z — avance del árbol KDE 2026-09-16 02:31:35 +00:00
Sergio 0ffcf4ed65 estado: cosecha granja 2026-09-16T02:01:47Z — avance del árbol KDE 2026-09-16 02:01:47 +00:00
Sergio 6b72d8d57b estado: cosecha granja 2026-09-16T01:31:45Z — avance del árbol KDE 2026-09-16 01:31:45 +00:00
SergioandClaude Opus 5 a9911785e1 lld21: el enlazador de la distro — porque el bootstrap de rust se NIEGA a construirlo
La vía (a) está CERRADA, y lo dice el propio bootstrap en una línea:

    Cannot enable LLD with `rust.lld = true` when using external llvm-config.

Había leído el paso `Lld` —que compila desde el `src/llvm-project/lld` del tarball y reusa el
`llvm-config` externo— y me faltó mirar la VALIDACIÓN de config, que rechaza la combinación antes de
llegar a ese paso. La guarda tiene sentido: LLD y LLVM comparten ABI de C++, y con un llvm-config
externo el bootstrap no puede garantizar que casen. O sea: mientras usemos el `llvm21` del corpus
—que es lo que queremos— el toolchain NO se va a construir su propio `rust-lld`.

⇒ `recipes/lld21.toml` construye el MISMO `lld`, del mismo `llvm-project` (mismo tarball y mismo
sha256 que `llvm21`, byte por byte), pero SÓLO el subproyecto: `cmake -S lld` contra el LLVM ya
instalado por la dep. Minutos en vez de horas, y sin re-hashear `llvm21` —que encender
`LLVM_ENABLE_PROJECTS=lld` ahí dentro habría arrastrado a `rust` con él.

⚠ Y al revertir el flag aprendí algo que vale para todas las recetas con heredoc: el texto del
`bootstrap.toml` que la fase escribe **es parte de la fase, o sea ENTRADA DE HASH**. Mi comentario
explicando el fallo, puesto ahí adentro, cambiaba el hash del compilador entero: hora y media de
granja por un párrafo. Va fuera, como comentario de la receta, y el hash vuelve a `015a07fb…` — el
artefacto que ya está sellado.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 01:02:49 +00:00
Sergio 8a6c928803 estado: cosecha granja 2026-09-16T01:01:51Z — avance del árbol KDE 2026-09-16 01:01:51 +00:00
SergioandClaude Opus 5 b7f70f37a8 rust: lld = true — el compilador que no podía enlazar ahora trae su enlazador
Muro 8, cerrado por la vía (a): el toolchain se construye su propio `rust-lld` en vez de depender de
un `cc` que en una caja takana no existe.

Lo que lo destraba es una línea del log que parece informativa: `skipping llvm-tools (…): external
LLVM`. Al usar un LLVM externo —que es lo que queremos, porque `llvm21` es del corpus— x.py se salta
las herramientas de LLVM, y `rust-lld` es una de ellas. El prebuilt oficial sí la trae, y por eso el
escalón 1 enlazaba y el 2 no.

Comprobado ANTES de encolar dos horas de build, leyendo el bootstrap y midiendo los artefactos:
· el paso `Lld` compila desde `src/llvm-project/lld`, que YA VIENE en el tarball (1,1 G de fuente);
· usa el `llvm-config`/cmake del LLVM EXTERNO y NO dispara un build de LLVM entero;
· `llvm21` publica `lib/cmake/llvm/LLVMConfig.cmake`, que es justo lo que ese paso necesita;
· `dist.rs` copia `rust-lld` al sysroot SÓLO `if builder.config.lld_enabled`;
· y `llvm21` no servía de repuesto: sobre sus 1,6 G no publica NINGÚN `lld`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 00:58:29 +00:00
Sergio 1eff89d870 estado: cosecha granja 2026-09-16T00:31:55Z — avance del árbol KDE 2026-09-16 00:31:56 +00:00
SergioandClaude Opus 5 be95b71449 SDD 31: EL ESCALÓN 2 SELLÓ — rust 1.97.0 desde fuente, b3:015a07fb…
353 M, construido por la granja desde `llvm21` del corpus y el stage0 del lab. Los controles, en la
caja (que sí tiene cargador musl; el worker no):

    rustc --version            → 1.97.0 … (built from a source tarball)   ← NUESTRO
    rustc --print target-list  → x86_64-alpine-linux-musl                 ← EL PARCHE, DENTRO
    cargo --version            → 1.97.0 … (built from a source tarball)

Y compila: `--emit=obj` da un objeto de 3,5 K y `--crate-type=rlib` una biblioteca, sin enlazador.

🧱 MURO 8, YA MEDIDO: el compilador no trae con qué ENLAZAR. En una caja sin `cc` —cualquier takana
que no sea un hub— `-C linker-flavor=ld.lld` da «linker `lld` not found» y el `ld` de binutils muere
con «cannot find -lgcc». La causa estaba en una línea del log que parece informativa:

    skipping llvm-tools (x86_64-alpine-linux-musl): external LLVM

Al usar LLVM externo —que es lo que queremos— x.py se salta las herramientas de LLVM, y `rust-lld`
es una de ellas. El prebuilt oficial sí la trae, y por eso el escalón 1 enlazaba. Y `llvm21` no
sirve de repuesto: NO publica ningún `lld` (medido sobre sus 1,6 G).

Dos salidas: (a) `[rust] lld = true`, que construye rust-lld desde el llvm-project vendoreado y deja
el toolchain autosuficiente; (b) publicar `lld` desde llvm21 y fijar el linker en un
`/etc/cargo/config.toml` del sitio.

Y la lección de método: el artefacto SELLÓ, reproduce y NO ENLAZA. Es [[subcomando-sin-driver]] en
el corazón del toolchain. Un `build ok` no es la prueba: la prueba es el objeto en el disco.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 00:23:46 +00:00
Sergio 953eadc046 estado: cosecha granja 2026-09-16T00:02:19Z — avance del árbol KDE 2026-09-16 00:02:19 +00:00
SergioandClaude Opus 5 ac856501b2 rust: el séptimo muro es el openssl de cargo — y va la variante CON THREADS
El parche del triple FUNCIONÓ: el build pasó el stage 2 —donde moría— y llegó hasta las herramientas.
Ahí cortó otra cosa:

    error: failed to run custom build command for `openssl-sys v0.9.114`
    The system library `openssl` required by crate `openssl-sys` was not found.

`tools = ["cargo"]` arrastra `openssl-sys`, y eso pasa DESPUÉS de compilar las ~400 crates del
compilador, o sea a la hora y media de build.

La dep que entra es `openssl-threads` y NO la canónica, aunque las dos publiquen sólo `.a`: el
`Configure` de openssl APAGA LOS THREADS en cuanto ve `-static` en LDFLAGS, y la canónica se
construye así. Un cargo —masivamente multihilo— enlazado contra un openssl sin soporte de hilos es
la clase de fallo que no se ve al construir ni al arrancar. La variante ya existía por exactamente
lo mismo para `python3`, y el worker la tiene sellada con el mismo hash.

Van también `OPENSSL_STATIC=1` y `OPENSSL_DIR=/usr`: el lab publica `.a` y ningún `.so`, y sin
decírselo `openssl-sys` busca la dinámica y falla con un mensaje que habla de pkg-config.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-15 23:59:22 +00:00
Sergio c8aa1ddd08 estado: cosecha granja 2026-09-15T23:31:40Z — avance del árbol KDE 2026-09-15 23:31:40 +00:00