Commit Graph
1752 Commits
Author SHA1 Message Date
Sergio 1de1fc31f6 atuq: lo que limpia el contador es SOBREVIVIR un rato después de pintar, no pintar
El par aísla la variable —mismo pin, mismo perfil, misma imagen, y la única diferencia es cuánto vive
el navegador después del primer cuadro—:

  S1       +97 s,  muerta en el acto (`--until-paint`)   ⇒ contador después: 1
  cierre-1 +120 s, ~360 s de vida después de pintar      ⇒ contador después: AUSENTE

Con eso queda contestada la pregunta que dos secciones atrás este documento daba por cerrada y no lo
estaba, y A deja de ser una anomalía: también siguió viva minutos después del primer cuadro.

Se dice además lo que la tabla NO prueba: si ese arranque además SELLÓ el éxito. El volcado del
«después» sólo grepeaba el contador; ahora `toolkit.startup.last_success` va en los DOS volcados y se
guarda en la medición (`last_success_antes` / `_despues`), que es lo que faltaba para no repetir la
corrida. Si el sello se mueve, es un gancho que sella y limpia a la vez; si no, son dos.

Y queda escrito que el 16 sigue sin explicación, ahora con una contradicción medida encima:
desapareció en una corrida diálogo + ATUQ-EXIT=0, y las fases k2/k3 del umbral fueron diálogo +
ATUQ-EXIT=0 y no limpiaron nada. La respuesta buena no tapa la sucia.

La corrida `cierre-1` y el mando `--watch-prefs` son de la otra sesión del frente.
2026-09-15 19:09:09 +00:00
Sergio aa4fd151be SDD 26 §7.quinquies: el cable tiene dos puntas en dos repos, y hoy no coinciden
La bóveda se commiteó esta mañana con sus cuatro enchufes en orden y no funciona igual. El motivo no
está en ninguno de los cuatro: cada función de atuq es un VERBO del host, el host vive en tawasuyu, y
`recipes/puriy-costura.toml` lo pinea por commit. Escribir la extensión y subir el pin son dos
unidades distintas y la primera se commitea sin la segunda sin que nada proteste.

Queda escrito con las dos mediciones y sus controles: el binario SELLADO y vigente tiene «vault» 0
veces contra «cas» 5 —el hermano que tenía que dar positivo, sin el cual el cero no prueba nada— y
el pin es ANCESTRO del commit que agregó los verbos. Más la tabla de las diez extensiones: 13 verbos
sobre 8, y los únicos tres sin dueño son los de la bóveda; o sea que «cuándo se tocó la receta» no
contestaba esto.

También queda la trampa del instrumento, que costó más que el vigía: el extractor buscaba `verb: "…"`
y la extensión de IA arma el mensaje con el verbo en una VARIABLE, así que encontraba cero y la
declaraba sana. De ahí el control de cobertura.

Y por qué el pin no subió en el mismo turno, que es lo que hay que leer antes de intentarlo:
el `Cargo.lock` de tawasuyu no cierra para `puriy-costura` —11 deps viejas, sin `pacha-boveda`, y
`pacha-boveda-daemon` ausente del lock—. Reproducido en árbol limpio del commit: `cargo metadata
--locked` muere con «cannot update the lock file» sin nombrar al culpable, tal como la receta
avisaba; y `cargo metadata --offline` lo cierra con 37 líneas sin mover una versión de registry.

Pero el fichero está `MM` en el clon compartido —otra sesión lo tiene stageado Y modificado, y su
árbol YA trae la reparación sin commitear—, así que no se tocó. Con un repo de juguete quedó medido
por qué el `--` no alcanza ahí, que es lo contrario de lo que uno supone: con un fichero en MM,
`git commit -- <ruta>` commitea EL ÁRBOL, no lo stageado, y el índice ajeno de esa ruta desaparece.
El pathspec aísla de lo que el otro dejó en OTRAS rutas; en la ruta que uno nombra, no.

Y la unidad 12 entra al plan con lo que le falta dicho: el lock de allá, el pin, el rebuild y el
guardián de metal.
2026-09-15 19:06:34 +00:00
Sergio 2566bdd3c8 estado: cosecha granja 2026-09-15T19:02:16Z — avance del árbol KDE 2026-09-15 19:02:16 +00:00
SergioandClaude Opus 5 a1ccce2b65 squid mudado — y la jaula arrancaba DEGRADADA cuando la arranca un init
El proxy de salida sirve desde la caja: `squid 7.7` en 2.29.29.217:1137 con la config, el `passwd`
de los tres usuarios y las dos ACL de gioser tal cual, dentro de una instancia qorpa y supervisado
por arje. El de gioser sigue vivo e intacto (7.6). Es un servicio con gente encima: el access.log
del origen mostraba CONNECT a api.anthropic.com y a claude.ai en el minuto anterior a mudarlo.

Control en los dos sentidos: desde una IP no autorizada, 407 igual que el original; desde localhost,
que su propia config permite, TCP_TUNNEL/200 a claude.ai y api.anthropic.com.

EL MURO QUE VALE, y es un bug de qorpa: **el rango de subuid se buscaba por `$USER`**. Una shell
interactiva lo trae; un init NO. Bajo arje la tarjeta arranca con PATH y HOME, el nombre salia
vacio, no habia rango, y la jaula caia al userns de UN SOLO ID — con lo que squid moria en
`setgid(15): (22) Invalid argument` y el supervisor lo reintentaba 80 veces. El aviso de qorpa
estaba impreso y era correcto («no hay rango para "" en /etc/subuid»), pero lo que se ve en el bucle
es el error de squid: **la degradacion silenciosa la paga el de mas abajo**. Y el MISMO comando a
mano funcionaba, porque la shell si pone `$USER`: el sintoma dependia de quien lo arrancaba.

⇒ `nombre_de_usuario()` deriva el nombre del UID REAL leyendo /etc/passwd y el entorno queda como
ultimo recurso, con la mitad pura (`nombre_en_passwd`) probada, control negativo incluido: un uid
que no esta NO inventa un nombre — devolver algo ahi haria buscar un rango ajeno.

Los otros tres muros quedan documentados en §6.27: provisionar ANTES de montar la config (pacman
aborta si el paquete no puede escribir sus defaults), `/dev/shm` que bwrap crea 0755 y squid no
puede usar al bajar a `proxy`, y el pidfile que en una jaula con `--unshare-pid` SIEMPRE parece
fresco porque cada corrida tiene su propio PID 2.

Y la pregunta que corresponde —¿no va en una receta?— con su respuesta: si, y sigue pendiente. La
jaula fue la via urgente. La diferencia con php-fpm importa: PHP no queremos que entre al corpus,
squid es C y su sitio natural es una receta como la de gitea.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-15 18:59:13 +00:00
Sergio 98c9e4daa6 atuq: la tasa con perfil sano es +97 y +98 s — y PINTAR NO ES TERMINAR el arranque
Cuatro arranques fríos en serie, el perfil partiendo del 5 que dejó la corrida del umbral:

  S1  pin 0   antes 5  después 1   el navegador   ✓ +97 s
  S2  sin pin antes 1  después 2   el navegador   ✓ +98 s
  S3  sin pin antes 2  después 3   (matada a los 60 s)
  S4  sin pin antes 3  después 4   EL DIÁLOGO     ✗ en 420 s

Tres cosas:

· la tasa, por fin con perfil sano: dos corridas independientes y pegadas, +97 y +98 s, contra los
  +123/+195/+197/+204 de antes. Con el anfitrión descargado el mismo artefacto pinta en la mitad del
  tiempo ⇒ el número es de la máquina y la carga tanto como del producto, y se publica con sus
  condiciones;
· el umbral se reprodujo solo y en otra secuencia: S4 arrancó con 3, sumó a 4 y abrió el diálogo —
  segunda medición independiente del mismo borde, esta vez identificando la ventana por `min_size`
  y no por el título (que está traducido, así que un grep por «Troubleshoot Mode» en una imagen en
  castellano no engancha y su ausencia se lee como la conclusión contraria);
· ⚠ y una corrida que PINTA no limpia el contador: S2 pintó y dejó 2. Más todavía,
  `toolkit.startup.last_success` vale lo mismo en las CUATRO (1789494795, las 17:53) ⇒ el gancho de
  cierre no corrió ni una vez, ni en las que pintaron. Pintar no es terminar de arrancar.

Entonces «quién limpia el contador» SIGUE SIN MEDIR, y el propio documento decía que esta serie lo
cerraría: no lo cierra, y queda escrito así. Hace falta una corrida que deje al navegador terminar
de arrancar y salir limpio.

Lo más caro es para el instrumento: con `--until-paint` cada corrida suma uno, pinte o no, así que
una serie se rompe sola a la cuarta — que es lo que pasó ayer sin que nadie lo viera. El arnés ahora
AVISA cuando el contador está en 3 («esta corrida va a abrir el diálogo, no el navegador») y la
receta para una serie queda escrita: pinnear `--crashes 0` en cada corrida, que resetea la base
(S1 lo muestra partiendo de 5).

También cae una candidata mía, con un cero que viene con control (medido por la otra sesión): el pref
no tiene default en este build, así que fijarlo en 0 SÍ se persiste y el «ausente» no era el pin.
2026-09-15 18:52:48 +00:00
Sergio 721845fb37 estado: cosecha granja 2026-09-15T18:31:47Z — avance del árbol KDE 2026-09-15 18:31:47 +00:00
Sergio 7997464337 atuq: el umbral son 4 — y mostrar el diálogo NO limpia el contador, como este documento decía
Medido en los dos lados, partiendo del perfil en 2 y con tres fases más en un arranque: el que
encuentra 2 guardado PINTA (y queda en 3); el que encuentra 3 lo sube a 4, compara 4 > 3 y abre el
diálogo (y queda en 4); el siguiente queda en 5 y vuelve a abrir el diálogo. O sea que la
comparación va DESPUÉS del incremento del propio arranque: contando desde la última corrida que
terminó bien, son cuatro arranques interrumpidos seguidos y el quinto lanzamiento ya no abre el
navegador.

`toolkit.startup.last_success` vale lo mismo en las tres fases (1789494795, el arranque de la última
corrida sana): el contador sube mientras esa marca no se mueve. Con las dos cifras juntas, un
contador que no cambió deja de ser ambiguo entre «no subió» y «subió y se limpió».

⚠ Y eso refuta una atribución que yo había escrito ayer y que estaba en tres sitios: mostrar el
diálogo NO limpia el contador (k2 lo dejó en 4, k3 en 5). Queda retirada del SDD y del comentario
del arnés. La desaparición del 16 entre las 17:12 y las 17:20 pasa a ser un hecho SIN explicación
medida, con dos candidatas escritas y ninguna dada por buena — y una de ellas es mía y fea: todas
las corridas que pintaron llevaban `--crashes 0` pinneado, que es el valor por DEFECTO, y un pref
igual al default no se persiste. El «ausente» puede ser eso y no una limpieza. Queda dicho cómo se
cierra: dejar el contador en 2 SIN pinnearlo, correr hasta que pinte y leerlo después.

Un discriminador que salió gratis: `ATUQ-EXIT=137` es «la matamos» (128+9) y `ATUQ-EXIT=0` es «se
fue sola» por el diálogo. El código de salida contesta lo que una captura no podía.

Medido por la otra sesión del frente (work/umbral-1.txt), con la predicción escrita antes de mirar.
2026-09-15 18:20:23 +00:00
Sergio cd678efd06 atuq: el contador de caídas es un TALLY — 0 · 1 · 2, y lo suma el arranque siguiente
Lo que el §6.10.terdecies dejaba escrito como «todavía NO medido» quedó medido: tres fases de 60 s en
un mismo arranque, cada una matada con kill -9 antes de pintar, dan contador 0 · 1 · 2. Uno por
arranque interrumpido y sin techo.

Dos cosas que la serie sola no distinguía, y que valen más que el número:

· el incremento lo escribe el arranque SIGUIENTE, no el kill — el «después» de la primera fase sigue
  ausente (el navegador estaba vivo) y el 1 aparece recién en la segunda. Quien cuenta es el que
  arranca y encuentra el anterior sin terminar;
· un arranque que sigue a una corrida SANA no suma. Eso separa «cualquier arranque incrementa» de
  «sólo después de uno interrumpido», que es la diferencia entre culpar al kill y culpar al arranque
  que no llegó a terminar.

Queda dicho qué sigue sin medir: si la comparación con `max_resumed_crashes` va antes o después del
incremento del propio arranque. Las dos lecturas dan «cuatro interrumpidos seguidos» en la práctica;
la diferencia es poder decir el número sin inventarlo, y se está midiendo cruzando el umbral en vivo.

Medido por la otra sesión del frente (work/contador-1.txt), con la predicción escrita antes de mirar.
2026-09-15 18:09:09 +00:00
Sergio 596b27dcad estado: cosecha granja 2026-09-15T18:02:30Z — avance del árbol KDE 2026-09-15 18:02:30 +00:00
Sergio 8880ce7a7b atuq: el navegador SÍ respeta el xulstore — y el debugfs miente si la VM se acaba de matar
Dos cierres del mismo día, los dos medidos por la otra sesión del frente sobre la imagen:

· la #3 queda contestada: con perfil sano el navegador pinta a +195 s y pide
  `set_window_geometry(1332, 852)` —el tamaño que el `xulstore` recuerda— y acata el
  `configure(1280, 692)` del maximizado. Ninguna cifra es 1152×720, o sea que `browser-init.js` no
  calculó nada: es lo correcto en un perfil que ya recuerda. Y de paso sale el discriminador barato
  entre las dos ventanas: el navegador pide `min_size` 638×120 y el diálogo 117×37;
· y una corrección de MÉTODO a lo que este mismo documento recomendaba ayer: leer el perfil con
  `debugfs` sobre el raw es válido con la imagen apagada, NO para leer lo que dejó un kill. Con el
  journal sucio `debugfs` se planta, con `-c` lee el estado pre-journal y ahí `prefs.js` figura de
  0 bytes — indistinguible de «el navegador borró el perfil», que es más grave y falso.

También queda escrito que la corrida que pinta LIMPIA el contador de caídas (el mecanismo visto
desde el otro lado: explica el «se arregla sola» sin hipótesis) y que una corrida sana no ensucia
el `xulstore`.
2026-09-15 18:00:45 +00:00
SergioandClaude Opus 5 d52824efeb mudados tawasuyu.net y gioser.net — y los padres que inventa bwrap eran 0700
Los dos sitios que quedaban con trafico real sirven desde la caja `takana`, con TLS publico y
verificados desde fuera. Los servicios viejos SIGUEN corriendo en gioser a proposito (decision del
usuario: mover el DNS y dejar el origen vivo, para poder volver en un minuto).

· `tawasuyu.net` + `www`: la raiz en gioser era EL MONOREPO ENTERO (145 G) servido por HTTP. El log
  de accesos dice que las unicas rutas con trafico son `/`, `/descargas` y `/web`, asi que se
  replicaron solo los dos subarboles que el sitio usa (1,2 M + 3,8 G) con la MISMA estructura, para
  que cada `rewrite` siga siendo el mismo.
· `gioser.net` + `www`: 428 M de estaticos + `/reencuentro`, que necesita PHP. `/hooks/*` NO se
  muda: lo atiende `webhook-deploy.py`, que redespliega aura/sigma/summa/brahman — los cuatro
  FOSILES del §6.19 — y tiene cero peticiones. Muere con la caja vieja.
· `sergio` dejo de ser `CNAME -> www` y tiene su A propio (apuntando a gioser, sin cambio visible).
  Sin eso, mover `www` se lo llevaba puesto: en esa zona casi todo cuelga de `www`.

PHP no entra al corpus y no hace falta: `php-fpm 8.5.10` corre en la instancia `gioser-php` (ADR
0015), supervisado por arje. Control contra el original en los dos sentidos: POST con la trampa
anti-robots da `{"ok":true}` 200 y GET da 405, igual que en gioser.

EL MURO, que es general y no de PHP: para montar en `/work/www/gioser-web`, bwrap crea `/work` y
`/work/www` —que la imagen no trae— y los crea **0700 root**. Adentro somos root y a mano todo
funciona; pero un servicio que BAJA de privilegio (php-fpm a `http`, o cualquier instancia con
`run_as`) no puede ni atravesarlos, y el sintoma es un «File not found» sobre un fichero que ESTA.
Medido con el control que lo separa de un problema de permisos del anfitrion: como `http`, leer un
fichero de la IMAGEN funciona y leer el directorio CONCEDIDO da Permission denied.

`grants_to_args` crea ahora los ancestros que faltan con `--perms 0755 --dir`, y SOLO los que la
imagen no trae: hacerlo sobre `/etc` o `/home` le cambiaria los modos a la imagen. Con test, y
probado rompiendolo a proposito (sale `["/etc","/etc/php"]` en vez de `["/etc/php"]`).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-15 17:58:17 +00:00
Sergio b3ec21375e atuq: el 117x70 era un DIÁLOGO — el navegador nunca abría, y el perfil venía envenenado
Cuatro secciones discutiendo por qué la ventana de atuq salía de 117x70, y no era la ventana de atuq.
Lo dice el mismo volcado de protocolo que ya se había leído, dos líneas más abajo de donde paró la
lectura:

    558  -> xdg_toplevel#58.set_title("Open atuq in Troubleshoot Mode?")

Es safeMode.xhtml, el diálogo de Modo de resolución de problemas. La cadena, cada eslabón con su
fuente y ninguno deducido:

1. el perfil del usuario traía `toolkit.startup.recent_crashes = 16` (prefs.js del 15-Sep 00:36,
   ANTES de las corridas del día; leído con debugfs sobre la partición, sin montar y sin root);
2. el umbral de NUESTRO build es 3 (browser/omni.ja -> defaults/preferences/firefox.js:831);
3. BrowserGlue.sys.mjs:389 abre el diálogo MODAL en `_beforeUIStartup()`, que por su propio
   comentario corre «before the first window is opened»: no hay navegador detrás esperando;
4. el `set_max_size(348, 16332)` sale del Fluent del diálogo (`max-width: 400px`);
5. y el proceso se va solo con `ATUQ-EXIT=0` porque el único camino de ese diálogo que termina el
   programa es `onCancel()` -> `quit(eForceQuit)`. Quién lo cancela no está medido.

El control, en los dos sentidos, mismo artefacto y mismo perfil: con el contador limpio pinta a
+123 s (704.458 px); fijado en 16, nada en 300 s y vuelve el diálogo. Y una honestidad que cambia la
fuerza del argumento: en la corrida limpia el `--crashes 0` fue un NO-OP —Gecko ya lo había
borrado—, así que la que prueba la causa es la que lo pone de vuelta y rompe de vuelta.

Cae también la sospecha del §6.10.duodecies: con `WidgetScreen:5`, Gecko ve la pantalla completa
(1280x800 de workarea) CINCO SEGUNDOS antes de crear la ventana. No había carrera con wl_output.

Y lo más caro: la serie de primera-pintura.json está contaminada por el propio andamiaje. El arnés
mata la VM con el navegador vivo, cada arranque sin terminar es una caída para Gecko y pasados 3 el
sujeto medido deja de ser el navegador. «3 de 13» y «2 de 10» midieron un perfil que se degradaba
corrida a corrida. Lo que cada corrida sume exactamente NO está medido y así queda escrito.

Queda una decisión de producto que no se mete de paso porque re-sella el artefacto: si atuq debe
traer `toolkit.startup.max_resumed_crashes = -1`.
2026-09-15 17:46:49 +00:00
Sergio 70107b1685 estado: cosecha granja 2026-09-15T17:32:10Z — avance del árbol KDE 2026-09-15 17:32:10 +00:00
SergioandClaude Opus 5 486bf7bb22 SDD 28 §6.25: api.sergio.gioser.net sirve desde la caja, dentro de una jaula qorpa
El primer servicio AJENO que corre sobre takana. 200 con TLS publico desde 2.29.29.217 y
`/api/chat/` contestando con Gemini de verdad, con el backend en una instancia `qorpa` sobre el
rootfs de Arch pineado por sha256, supervisado por arje-zero como el ente `sergioh-api`.

Es el que §6.21 llamo «lo que decide la fecha de borrado de gioser»: su venv trae extensiones
`cpython-314-...-linux-gnu.so`, o sea glibc, y no tiene camino a musl. La coincidencia que lo hizo
barato: el Arch pineado trae python 3.14.7 y el venv de gioser es 3.14.6 — misma serie, asi que el
venv se REHACE adentro con pip en vez de copiarse.

La seccion trae ademas el muro (la jaula no viajaba en ninguna imagen — commit anterior), los tres
tropiezos del camino (el uid 1001 del rsync que cae fuera del userns; una instancia admite UN solo
`run`; `ps` que no ve procesos y `dig` que no existe, dos ausencias que se leen como diagnostico) y
lo que quedo declarado: `instance.toml` con un unico dir concedido, las 84 deps pineadas en
`requirements.lock`, y la tarjeta en cards.d Y en el genesis.

Y una correccion de rumbo en §9: la lista «lo que falta para el cutover» era del 11-09 y sus pasos
1-5 ya estan hechos. Lo que sigue vivo en gioser son TRES vhosts, no quince.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-15 17:31:00 +00:00
SergioandClaude Opus 5 dbfb7d492b la jaula no viajaba en NINGUNA imagen: bwrap y harkaq-exec entran a perfil.base
Mudando `api.sergio.gioser.net` a la caja de produccion, `takana qorpa provision` aborto:

    Error: no encuentro harkaq-exec en /root/.cache/harkaq/harkaq-exec
      construilo:  gcc -O1 -Wall -static -o ... scripts/harkaq/harkaq-exec.c

El mensaje es bueno y la receta que propone es IMPOSIBLE de seguir: en una caja instalada no hay
gcc, ni `scripts/`, ni arbol de desarrollo. El binario solo existia como un `gcc` a mano en la
cache de `$HOME` del hub, o sea que la jaula del ADR 0015 funcionaba unicamente en la maquina
donde alguien la habia compilado.

Y su companero estaba igual, medido en `build-state.json`: `bwrap` sellado desde hace meses con
`"perfiles": []` — CERO perfiles. Lo invocan por PATH tanto `qorpa` como el sandbox de
`takana build` (`takana-build/src/sandbox.rs`), asi que **ninguna imagen de takana podia enjaular
nada, ni construir**. Es [[subcomando-sin-driver]] un piso mas abajo: el CLI que los llama viaja
en todas las imagenes y sus herramientas en ninguna.

Tres piezas:

· `recipes/harkaq-exec.toml` — nueva. Estatico musl, `b3:cd34954f...`, 269 K. El pin va al commit
  que toco la FUENTE (`1d9ddcee`, 2026-09-03) y no a HEAD: el `.c` no se mueve desde entonces y el
  repo commitea cada media hora por el cron de la cosecha — pinear HEAD re-hashearia la receta cada
  media hora sin que su fuente cambiara. La fuente sigue en `scripts/harkaq/` y no en un arbol
  propio porque tres scripts la compilan desde ahi y dos copias divergen en silencio.
· `qorpa.rs` — busca el binario tambien en `/usr/bin`, que es de donde sale en cualquier maquina
  que no sea el hub. El orden es HARKAQ_BIN (lo que el operador declara) → arbol de desarrollo →
  paquete, para que un cambio en la jaula se pruebe sin instalar nada. Y el error ya nombra las
  dos salidas, no solo la del hub.
· `targets.toml` — los dos en `perfil.base`.

Medido en la caja de produccion tras aplicarlos: `bwrap 0.11.0` + harkaq-exec responden, y
`takana qorpa provision sergioh-api` instala python 3.14.7 con pacman DENTRO de la jaula
(`[harkaq] jaula puesta: ABI 9`). El 3.14 no es casualidad: el venv de gioser trae extensiones
`cpython-314-...-gnu.so`, asi que la imagen de Arch pineada da la misma serie.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-15 17:17:42 +00:00
Sergio 9bb1308a5b estado: cosecha granja 2026-09-15T17:01:48Z — avance del árbol KDE 2026-09-15 17:01:48 +00:00
Sergio b8c4c50268 estado: cosecha granja 2026-09-15T16:31:46Z — avance del árbol KDE 2026-09-15 16:31:46 +00:00
Sergio 16493462b6 estado: cosecha granja 2026-09-15T16:01:41Z — avance del árbol KDE 2026-09-15 16:01:41 +00:00
Sergio 69f70db0c7 estado: cosecha granja 2026-09-15T15:31:21Z — avance del árbol KDE 2026-09-15 15:31:21 +00:00
Sergio fbb612d004 estado: cosecha granja 2026-09-15T15:02:29Z — avance del árbol KDE 2026-09-15 15:02:29 +00:00
Sergio 86f851455f estado: cosecha granja 2026-09-15T14:32:01Z — avance del árbol KDE 2026-09-15 14:32:01 +00:00
Sergio 046553670b estado: cosecha granja 2026-09-15T14:02:02Z — avance del árbol KDE 2026-09-15 14:02:02 +00:00
Sergio d13d11c3ed estado: cosecha granja 2026-09-15T13:31:21Z — avance del árbol KDE 2026-09-15 13:31:21 +00:00
Sergio db77af65e5 estado: cosecha granja 2026-09-15T13:01:40Z — avance del árbol KDE 2026-09-15 13:01:40 +00:00
Sergio 10e1e9ffb0 estado: cosecha granja 2026-09-15T12:31:33Z — avance del árbol KDE 2026-09-15 12:31:33 +00:00
Sergio d0a2da67db estado: cosecha granja 2026-09-15T12:01:21Z — avance del árbol KDE 2026-09-15 12:01:21 +00:00
Sergio 575679a4bd estado: cosecha granja 2026-09-15T11:31:16Z — avance del árbol KDE 2026-09-15 11:31:16 +00:00
Sergio 8541febca5 estado: cosecha granja 2026-09-15T11:01:39Z — avance del árbol KDE 2026-09-15 11:01:39 +00:00
Sergio fe1278c81d estado: cosecha granja 2026-09-15T10:32:01Z — avance del árbol KDE 2026-09-15 10:32:01 +00:00
Sergio 94e60c0340 estado: cosecha granja 2026-09-15T10:01:16Z — avance del árbol KDE 2026-09-15 10:01:16 +00:00
Sergio e479ccd269 estado: cosecha granja 2026-09-15T09:31:17Z — avance del árbol KDE 2026-09-15 09:31:17 +00:00
Sergio e2b03b9b90 estado: cosecha granja 2026-09-15T09:01:19Z — avance del árbol KDE 2026-09-15 09:01:19 +00:00
Sergio 92215bf937 estado: cosecha granja 2026-09-15T08:31:39Z — avance del árbol KDE 2026-09-15 08:31:39 +00:00
Sergio d13d14ef10 estado: cosecha granja 2026-09-15T08:01:40Z — avance del árbol KDE 2026-09-15 08:01:40 +00:00
Sergio 13494bee5d estado: cosecha granja 2026-09-15T07:31:19Z — avance del árbol KDE 2026-09-15 07:31:19 +00:00
Sergio 6faa9927a5 estado: cosecha granja 2026-09-15T07:01:17Z — avance del árbol KDE 2026-09-15 07:01:17 +00:00
Sergio cdd1eb6d2c estado: cosecha granja 2026-09-15T06:31:23Z — avance del árbol KDE 2026-09-15 06:31:23 +00:00
Sergio d8d5dff113 estado: cosecha granja 2026-09-15T06:01:19Z — avance del árbol KDE 2026-09-15 06:01:19 +00:00
Sergio 798e45c539 estado: cosecha granja 2026-09-15T05:31:14Z — avance del árbol KDE 2026-09-15 05:31:14 +00:00
Sergio 362250c877 estado: cosecha granja 2026-09-15T05:01:18Z — avance del árbol KDE 2026-09-15 05:01:18 +00:00
Sergio c34a3f2508 estado: cosecha granja 2026-09-15T04:31:17Z — avance del árbol KDE 2026-09-15 04:31:17 +00:00
Sergio 6f1520f60d estado: cosecha granja 2026-09-15T04:01:16Z — avance del árbol KDE 2026-09-15 04:01:16 +00:00
Sergio 12943b3d1f estado: cosecha granja 2026-09-15T03:31:14Z — avance del árbol KDE 2026-09-15 03:31:14 +00:00
Sergio aa3dacea4a estado: cosecha granja 2026-09-15T03:01:14Z — avance del árbol KDE 2026-09-15 03:01:14 +00:00
Sergio 15cfcd769d estado: cosecha granja 2026-09-15T02:31:14Z — avance del árbol KDE 2026-09-15 02:31:14 +00:00
Sergio 7cedd90c09 estado: cosecha granja 2026-09-15T02:01:16Z — avance del árbol KDE 2026-09-15 02:01:16 +00:00
Sergio 17317a2d5a estado: cosecha granja 2026-09-15T01:31:14Z — avance del árbol KDE 2026-09-15 01:31:14 +00:00
Sergio 889623afe3 estado: cosecha granja 2026-09-15T01:01:21Z — avance del árbol KDE 2026-09-15 01:01:21 +00:00
Sergio e428f6b092 estado: cosecha granja 2026-09-15T00:31:34Z — avance del árbol KDE 2026-09-15 00:31:34 +00:00
SergioandClaude Opus 5 3df94f3936 SDD 31: el compilador de Rust — el escalón 2 construyendo, y los cinco muros del camino
rustc desde fuente está compilando el stage1 en el worker. El documento recoge el frente entero: el
hueco medido (12 crates y 42 555 líneas de Rust, 44 recetas `cargo-*`, CERO de rustc, y el `rustc`
que construye todo eso saliendo del LAB — que ENTRA en el ArtifactHash), los tres escalones, y lo
que costó cada uno.

Los cinco muros del escalón 2, todos con un mensaje que no nombra la causa:

1. `llvm18` no sirve: `bad LLVM version, need >=21`. Mínimos medidos en el propio bootstrap
   (1.87→18 · 1.90→19 · 1.93/1.95→20 · 1.97→21). Bajar de rustc no es salida porque el stage0 de N
   es N-1 o N. De ahí `llvm21` — y `llvm18` se queda, que lo usa mesa.
2. **El toolchain musl oficial no puede producir proc-macros** (crt-static=true ⇒ sin dylibs):
   muere compilando el propio bootstrap de rustc, que usa `clap` con derive. Sirve para compilar
   programas, no para arrancar el build de rustc. El stage0 es el del lab.
3. x.py DESCARGA el stage0 si no le nombras el local: en un sandbox sin red, `RuntimeError: failed
   verification` en `download_toolchain()`, que no menciona ni la red ni el stage0.
4. El triple de Alpine no es el canónico: sin fijarlo, la sección `[target.…-unknown-…]` no aplica a
   nada y x.py se pone a construir LLVM solo; forzando el canónico, el stage0 no tiene su std.
5. cmake + zig = «compiler broken» en la prueba de ABI. CC=gcc, igual que llvm21 y cmake.

Y del escalón 1, lo que no estaba en el grafo: el prebuilt no ejecuta sin `musl-shared` (cargador) y
sin `gcc-libs` (`libgcc_s.so.1`) — dos paquetes sellados y en el perfil equivocado. Más una
propiedad que vale: no hace falta un `cc`, el toolchain trae su propio lld.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016Tf9T4vGzsMoT7eS8YzMFn
2026-09-15 00:29:33 +00:00