tawasuyu

sergio/takana

> Una distribución Linux construida con un laboratorio funcional y hermético en el > sótano, y una terminal mutable, clásica y anárquica en el piso de arriba — diseñada > desde el suelo para que una IA programadora entienda, modifique y co…

TOML 1378Shell 137Rust 79Markdown 762511 Definiciones

SDD 28 §6.5: el muro derribado — de 23 binarios inertes a 1, y sin mover un ArtifactHash

Elegidas las salidas 1 y 2 del §6.4; hecha la 1, que resultó más barata de lo que parecía y desbloquea
la 2 en vez de competir con ella.

`musl-shared` publica `/usr/lib/libc.so` + `/lib/ld-musl-x86_64.so.1`. Como variante y no tocando la
canónica: `musl` es Stage 1 y su `of_tree` es el baseline del selfhost. Control: `takana hash
recipes/musl.toml` sigue en `b3:ce952f72…`. Y `musl` no es dep de nadie ⇒ cero re-hasheo del corpus.

En la caja: `sh: python3: not found` → `Python 3.12.10`. De 23 inertes quedó **1**, `sqlite3`, que
pedía `libz.so.1`; `zlib-shared` ya estaba sellado y sólo faltaba declararla en `base`.

La salida 2 (python/perl estáticos) sigue viva pero deja de ser urgente: con el cargador publicado el
sistema ya no cuelga del rootfs del lab.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RomoxEGZUhaT4pob1QSX5x

7e41ffd0e66026921c5caf71a78de36d41143a4c · por Sergio · (hace 1 mes) · padre 7e8645973 · ver el árbol en este commit

Delta semántico

Ninguna definición cambió: el cambio es de texto, documentación o datos.

2 archivos · +51 −0

diff --git a/docs/28-servidor-de-produccion.md b/docs/28-servidor-de-produccion.md
index 3c211bbd..b79c0817 100644
--- a/docs/28-servidor-de-produccion.md
+++ b/docs/28-servidor-de-produccion.md
@@ -582,6 +582,51 @@ Es decisión de ADR, y de las que conviene tomar mirando también el [SDD 27 §4
 las dos preguntas —«¿el cliente reproduce o hidrata?» y «¿el cliente puede correr lo que le
 mandamos?»— son la misma pregunta sobre qué es un sistema takana **sin laboratorio**.
 
+### 6.5 ✅ El muro, derribado: el corpus publica su propio cargador *(2026-09-11)*
+
+De las tres salidas del §6.4 el usuario eligió la 1 y la 2. Hecha la **1**, que resultó ser más barata
+de lo que parecía y desbloquea la 2 en vez de competir con ella.
+
+**`recipes/musl-shared.toml`** — variante dinámica de musl que publica `/usr/lib/libc.so` (4,2 M) y
+`/lib/ld-musl-x86_64.so.1`. En musl el cargador Y la libc son el mismo objeto.
+
+**Por qué una variante y no `--enable-shared` en la canónica**, con su control: `musl` es componente
+de **Stage 1** y su `of_tree` es el baseline de `selfhost-verify`. Tocarla obliga a rehacer ese
+baseline a propósito. Con el patrón `*-shared` —que el corpus ya usa 23 veces— la canónica no se
+mueve: `takana hash recipes/musl.toml` sigue dando `b3:ce952f72…`, el mismo sellado de Stage 1. Y
+además **`musl` no es dep de nadie** (medido: sólo de sí misma; el enlace estático lo resuelve el
+musl que trae zig), así que esto **suma sin mover un solo ArtifactHash del corpus**.
+
+#### ⚠ Y hubo que cambiar de compilador, medido
+
+Con `zig-cc` el `libc.so` sale con **1586 símbolos dinámicos** contra los **1654** del musl de Alpine,
+y los **68 que faltan son exactamente** los que musl implementa en ensamblador x86_64 — `memset`,
+`memcpy`, `memmove`, `memcmp`, `strlen` y toda la familia matemática (`ceil floor sqrt fmod exp log
+sin cos tan fma round trunc`) — más los `__stack_chk_*`.
+
+No es que no se compilen: en el `libc.a` del musl canónico **están**. Lo que pasa es que **zig los
+resuelve con su propio musl y los deja `FUNC LOCAL HIDDEN` de tamaño 0**, fuera de la tabla dinámica.
+El síntoma es un cargador que arranca, reloca y muere con `memset: symbol not found` — que se lee
+como «el binario está roto», no como «a la libc le faltan símbolos».
+
+Con `compiler = "gcc"`: **1651 símbolos**, `memset` y `ceil` presentes.
+
+#### El resultado, en la caja
+
+| antes | después |
+|---|---|
+| `sh: python3: not found` (con `command -v` contestando `/usr/bin/python3`) | `Python 3.12.10` |
+| 23 binarios inertes de 726 | **1** |
+
+`perl 5.040002`, `readelf`/`objdump`/`nm` (GNU Binutils 2.45.1) y el resto corren. El único que
+quedaba era **`sqlite3`**, con `Error loading shared library libz.so.1`: la zlib canónica también es
+`--disable-shared` y nadie publicaba ese soname. `zlib-shared` ya existía sellado en el corpus —
+sólo faltaba declararla en `base`.
+
+**La salida 2 (python/perl estáticos) sigue viva y ahora es opcional, no urgente**: con el cargador
+publicado el sistema ya no depende del rootfs del lab. Estático seguiría siendo mejor (un binario
+menos que puede quedar colgado de un soname), pero es un frente propio y ya no bloquea la mudanza.
+
 ### 6.2 Lo que la mudanza tiene que producir, además de la mudanza
 
 El usuario lo pidió explícito: **que este experimento saque recetas y las pruebe**. La caja vieja es
diff --git a/docs/state/targets.toml b/docs/state/targets.toml
index 237b4391..bc7da54e 100644
--- a/docs/state/targets.toml
+++ b/docs/state/targets.toml
@@ -40,6 +40,12 @@ paquetes = [
   # instrumental del proyecto. El síntoma era `sh: python3: not found` con `command -v python3`
   # contestando `/usr/bin/python3`: no falta, no arranca. Ver SDD 28 §6.4.
   "musl-shared",
+  # `zlib-shared` (2026-09-11): el único hueco que quedó tras publicar el cargador. Con
+  # `musl-shared`, 22 de los 23 binarios inertes de la imagen del servidor pasaron a correr; el 23º
+  # era `sqlite3`, que muere con `Error loading shared library libz.so.1`. La zlib canónica es
+  # `--disable-shared` y ningún artefacto publicaba ese soname — otra vez el rootfs del lab tapando
+  # el agujero. La variante ya existía en el corpus; sólo faltaba declararla.
+  "zlib-shared",
 ]
 
 [perfil.cli]