`docs/evidencia/sway-qemu-2026-08-08.png`: 1280×800, **102 colores distintos**, sway con foot a pantalla completa y un prompt vivo, la barra de título del compositor arriba y el fondo #1a4b8c asomando en los bordes. Sobre el kernel de hammer con arje-zero como PID1, sin X11 y sin systemd. EL VEREDICTO ES CONTAR COLORES, NO LEER EL LOG — y esta campaña lo demuestra sola: hubo un arranque con TODO verde en el log (salida activada, modo 1280x800, «Commit of 1 outputs succeeded», workspace creado) y la captura salía **100% negra**. Un compositor puede estar perfectamente vivo y no pintar nada. LOS SEIS MUROS, ninguno visible en un grafo de dependencias que decía 121/121: 1. `PATH` vacío — el console-getty no lo exporta y ni `mkdir` se encontraba. «mkdir: not found» se lee como «falta busybox» cuando busybox está entero: mismo engaño que el exit 127 de meson. 2. `libz.so.1` AUSENTE del rootfs. El zlib del corpus es sólo estático; la compartida vive en `zlib-shared`, en otra cola. Se cazó comparando los NEEDED del ELF contra el rootfs, no leyendo logs. 3. `LIBSEAT_BACKEND=builtin` NO EXISTE en nuestro libseat: `recipes/seatd.toml` construye con `-Dlibseat-seatd=enabled -Dlibseat-logind=disabled`, o sea UN backend, confirmado con `strings`. La receta manda sobre lo que uno cree recordar del proyecto — y la misma receta traía la salida: `-Dserver=enabled` construye `seatd-launch`. 4. `/run` de SÓLO LECTURA. La raíz de hammer es inmutable por diseño, y sway moría con «unable to open lockfile … check permissions», que suena a permisos de directorio y era un filesystem read-only. Se resolvió montando un tmpfs, que es lo que hace cualquier init. 5. `xkeyboard-config` — «failed to add default include path /usr/share/X11/xkb». Es EXACTAMENTE lo que dejé anotado en la receta de swaylock: «para que el teclado tenga distribución en una imagen real hará falta incluirlo por el lado del perfil». Apareció donde se dijo. 6. SIN TIPOGRAFÍAS no hay terminal. `fcft: failed to match font` → `failed to load primary fonts`: foot arrancaba y no dibujaba. `dejavu-fonts` estaba en el catálogo pero en otra cola. Va en la lista de §I.5 del SDD 20 («tipografías») y acá se ve por qué no es un detalle. Y un fallo de MÉTODO que costó dos ciclos: mandé el log de sway a /var/log/sway.log DENTRO de la VM, así que la primera captura negra vino sin una sola línea que la explicara — el diagnóstico estaba dentro de la caja que no arranca. Un log que no se puede leer desde fuera no es un log. Ahora va al serial. Los `exec` de la config de sway disparan ANTES de que exista el workspace (0,259 s vs 0,305 s) y mueren con «Failed to create launch context. No workspace». Los clientes se lanzan desde sway-start esperando el socket de Wayland, que es la condición real. Andamiaje reutilizable en scripts/wlr/: qemu-sway-image.sh (hermano del de COSMIC, sin logind ni dbus, que sway no necesita), sway-start.sh y sway-config. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
hammer
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 comparta el sistema.
hammer no es otro gestor de paquetes inmutable. Es una arquitectura de dos mundos:
- El laboratorio compila desde fuentes upstream (commits fijados), de forma
determinista y aislada (
bubblewrap+zig cc+ musl estático), y direcciona cada artefacto por su hash (BLAKE3) en un content-addressed store. - El userland es un Linux clásico, mutable, con FHS de verdad (
/bin,/lib,/etc). Los binarios se hidratan desde el store por hardlinks. Puedes pisar archivos en caliente, romper cosas con unrm -rf, y revertir cuando quieras.
Entre ambos mundos viven las tres piezas que hacen a hammer distinto:
- Overlay de experimentación — prueba cambios sobre el sistema real con red de
seguridad;
hammer try/commit/discard. - Diario de mutaciones — un daemon
fanotifyregistra todo lo que tú (o la IA) cambiáis a mano. Vives imperativamente; el sistema genera el delta contra la base limpia. El diario es tu configuración — sin ser declarativa. - Manifiesto
.swm— compartes la receta de la mutación (parche de fuente + flags + ediciones de config), no el binario cocinado. El receptor reproduce y verifica; no confía en tu binario.
Encima de todo corre el bus de agente (/run/agent.sock): la IA habla un protocolo
pequeño y legible, dispara compilaciones, inyecta en el overlay, escucha fallos y reacciona.
Tú tienes la última palabra.
Estado
Fase de arranque. Validamos la capa AI-nativa sobre Alpine (musl + FHS ya cocidos)
antes de bajar a distro propia. Ver docs/10-roadmap.md.
Documentación de diseño (SDD)
Toda la arquitectura está en docs/. Empieza por
docs/00-vision.md y docs/01-architecture.md.
Estructura
crates/
hammer-core tipos compartidos: Recipe, Swm, hashing CAS, store
hammer-build el laboratorio: sandbox + compilación + hidratación
hammer-cli el binario `hammer` (build, hydrate, try, commit, apply, export…)
hammerd daemon: bus de agente + diario de mutaciones
docs/ SDDs y ADRs
Stack
| Capa | Decisión |
|---|---|
| Base de validación | Alpine (musl + FHS mutable) |
| Tooling / daemons | Rust (estático-musl) |
| Compilador del lab | zig cc por defecto, pluggable por receta |
| Sandbox de build | bubblewrap (namespaces) |
| Direccionamiento | BLAKE3 content-addressed store |
| Despliegue | Hidratación por hardlinks + patchelf |
Filosofía
La automatización es mi empleada en el sótano, pero en el piso de arriba mando yo.
Eficiencia matemática en la manufactura, libertad biológica en la ejecución.