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>
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.