b3:f9de6d2a. deps = cadena canónica sellada (libgpg-error/libgcrypt/libassuan/libksba/npth/zlib).
Fase configure explícita --disable-{tofu,scdaemon,dirmngr,doc,bzip2} + --with-*-prefix=/usr. gpg+gpgv
estáticos; round-trip cifrado simétrico -c/-d + --print-md SHA512 verificados. Nota: NO apareció el
ubsan de libz.a (el zlib limpio de este mismo commit-set ya se materializa). base-system-3 completo.
b3:a141de41. Patrón meson -Dprefer_static=true (sin él meson enlaza libudev.so → link estático falla).
deps: libusb (nueva) + libudev-zero (stub del catálogo, satisface la dep dura de libudev>=196 en
meson.build; hwdb name-lookup queda stub pero lsusb corre). Cierra el chain libusb→usbutils.
b3:14ab12e0. Lib 3/3 de la cadena gnupg. Fase configure explícita --with-libgpg-error-prefix=/usr
--enable-static. deps: libgpg-error+linux-headers+pkgconf. La cadena crypto de gnupg está completa.
b3:f6a4fa5f. Fase configure explícita --disable-udev (backend netlink/sysfs) --enable-static.
Deja libusb-1.0.a + .pc + header para que usbutils la halle.
b3:2623a403 (antes tenía 77 refs __ubsan_handle_*). Sin -O explícito, zig cc emite el runtime UBSan
que el .a estático arrastra → rompía el link estático de todo lo que enlaza -lz (git/curl/mandoc/
pciutils…). Fix de raíz: -O2 (apropiado para lib de compresión) + opt-out explícito. No está en el
camino de reproducibilidad selfhost/rust (verificado); los ~45 dependientes sellados siguen cacheados,
los rebuilds futuros toman el libz.a limpio y ya no necesitan workarounds ad-hoc.
b3:d4aa8f26. deps→linux-headers; fase configure explícita --enable-mpers=no --without-{libunwind,
libdw,libselinux}; make -C src (tests/ rompe con zig cc -E - por -mcpu= vacío). Deuda menor: zig
FUERZA sus headers UAPI por delante de -I (io_uring zcrx tiene 2 campos más nuevos que zig) → quité
esas 2 líneas de decode; strace traza todo lo demás igual.
b3:a07b7b14. Suite completa estática. Fase configure explícita --without-{libbsd,libpam,fcaps}
(libbsd ausente→usa readpassphrase de fábrica; fcaps→setcap falla en sandbox); make LDFLAGS=-all-static
(libtool ignora -static, gotcha util-linux); limpié install de pam.d de aports. Habilita usuarios
reales (antes sólo root).
b3:a7b8a634. Quité shared-libmandoc.patch (forzaba .so); fase configure explícita que escribe
configure.local (PREFIX=/usr, LDFLAGS=-static, CC='zig cc'). 3er caso del libz.a-UBSan: acá se
resuelve fijando CC=zig cc (su compiler-rt trae __ubsan_handle_*). TODO durable: rebuildear zlib
sin instrumentación UBSan (afecta a todo lo que linkee libz.a estático).
b3:b87f0307. deps→linux-headers (perl/bash eran el fallo de carga). El tarball trae el Configure
viejo (sh, no autotools) → ./Configure -n linux + make CC='cc -static' (Configure genera su propia
línea de link que ignora los LDFLAGS del lab).
b3:e6f71fc4 (procps-ng 4.0.6). compiler=gcc gueto + ncursesw + -no-pie (patrón vim), fase configure
explícita --without-systemd --enable-static. Gotcha: patch a un .am dispara regeneración automake
(ausente) → reordené timestamps de fuentes en configure para saltarla. Herramientas de proceso base.
b3:e9b90fe2 (kbd 2.8.0). deps→flex+linux-headers; fase configure explícita --disable-vlock/tests.
Gotcha del incoming-clib compartido: patches con nombres genéricos (busybox.patch/tests.patch) eran
de STRACE, no de kbd, y rompían el build → patches reducido a [lex.patch]. Cierra el lazo del keymap
que el instalador interactivo ya recogía pero no podía aplicar.
b3:b6ac56cf. make ZLIB=no SHARED=no (sin autotools). Nota recurrente: el libz.a canónico está
instrumentado con UBSan → link estático falla con __ubsan_handle_* (mismo issue que mordió a git);
acá zlib es opcional (pci.ids sin comprimir) → ZLIB=no. TODO durable: rebuildear zlib sin ubsan.
b3:d73a5286. util-linux ya compila y provee libuuid.a + uuid.pc; parted la halla vía
PKG_CHECK_MODULES/pkgconf (dep de build util-linux). Elimina la libuuid v4 mínima que se
horneaba en la fase configure cuando util-linux estaba roto. Verificado: parted --version OK.
Los 17 que construyen de la tanda base-system-1 pasan de recipes/incoming-clib a recipes/
canónicas y al índice firmado (dist/repo, artefacto local): bash git sudo doas util-linux
rsync sed tzdata dbus dhcpcd iproute2 iputils dosfstools e2fsprogs parted vim ca-certificates.
Sólo foot queda staged (stack Wayland, diferido). Cierra el grueso del hueco 'userland
foundational' hacia la distro completa: shell real + VCS + privilegios + red + disco + TLS.
b3:d0d0ebaa (util-linux 2.42.2). De-Alpinizado (deps→linux-headers), fase configure explícita
--without-{python,systemd,udev,ncurses,...}. Bug real del lab parcheado: zig cc -mcpu=baseline
traduce a -mcpu= VACÍO en modo preprocesador (-dM -E -) que zig rechaza; sed filtra ese flag sólo
en tools/all_{errnos,syscalls}. Estáticos vía --enable-static-programs=blkid,fdisk,mount,umount;
lsblk/lscpu quedan musl-dinámicos (libtool ignora -static). Utilería base del sistema.
b3:64b797d2. Reescribí las fases garabateadas (compile hacía _perl_config; install compilaba la
suite de tests) a make all/install limpios con NO_GETTEXT/TCLTK/PYTHON. deps zlib/openssl/curl/
pcre2. Gotchas: FUZZ_PROGRAMS= (oss-fuzz usa --allow-multiple-definition que ld.lld rechaza);
-fsanitize=undefined en compile+install IDÉNTICO (libz.a trae refs __ubsan_* + git relinkea si
GIT-CFLAGS difiere entre fases). El hueco más grande del userland, cerrado.
b3:3d7bb8a7. --disable-device-mapper (sin lvm2) --enable-static; make LDFLAGS=-all-static
(libtool ignora el -static del lab → binario musl-dinámico que segfaultea fuera del sandbox).
parted EXIGE libuuid (uuid_generate p/ GUIDs GPT) y util-linux está roto → horneé una libuuid
mínima (UUID v4 desde /dev/urandom) en la fase configure. Probado: mklabel gpt + mkpart reales.
TODO: reapuntar a la libuuid real de util-linux cuando ésta compile.
b3:d0b9752d. URL/sha256 arreglados (var abuild sin expandir); fase configure explícita;
--without-pam/sssd/skey + --with-secure-path. Clave del link: --disable-shared
--enable-static-sudoers --disable-log-{server,client} (sin eso ld.lld falla por símbolos
versionados sudo_*_v1 de libsudo_util). Install con INSTALL_OWNER= (setuid lo re-aplica la
hidratación). Con doas cubre el escalado de privilegios.
b3:c5a52051. Un solo cambio: [deps] build=[openssl]. La premisa era falsa: c_rehash es un binario
C (no el script perl) que sólo faltaba -lcrypto; perl SÍ está en la dev-fs (mk-ca-bundle.pl corre).
ca-certificates.crt con 119 certs + update-ca-certificates. Sin esto curl/wget HTTPS no validan.
b3:1fdc6fdd. Console-only (--disable-gui --without-x, sin intérpretes). Gotchas: zig-cc
miscompila vim → compiler=gcc (como nano/htop); ncurses del corpus es widec-only (--with-tlib=
ncursesw); termcap usa reubicaciones R_X86_64_32 sobre _nc_globals que no entran en static-PIE →
-fno-pie/-no-pie; vim_cv_* cacheadas para no colgar en musl estático; fase configure explícita.
b3:e2d2244d. configure --without-pam ya andaba (bison=yacc para parse.y); el fallo era el install
(chown root:root falla en el sandbox + doas.conf de aports ausente) → copia manual del binario.
b3:6b4f0397. Raíz del fallo: el tarball IANA tzcode NO trae los datos de zona (y el combinado
es .tar.lz sin lzip acá). Cambié [source] a git github.com/eggert/tz @ tag 2026b (código+datos
juntos, commit fijo ADR 0006), quité los patches de posixtz (no lo construimos), fases = zic →
DESTDIR posix_only. Habilita la zona horaria real del instalador interactivo.
iputils 20250605 estático (b3:669520e9). Migré de la shell abuild al patrón meson estándar
(samurai=ninja + meson canónicos), docs off (BUILD_MANS=false) para no arrastrar docbook-xsl,
LTO off. libcap:yes.
dhcpcd 10.3.2 (b3:aaeda08e), INET/IPv6/DHCPv6/PRIVSEP. Sólo sobraba bsd-compat-headers
(dhcpcd trae su propio compat/) + una línea install de dhcpcd.initd de aports. Con iproute2
completa el bring-up de red del sistema.
e2fsprogs 1.47.4 (b3:3cf73aea): mke2fs, e2fsck, mkfs.ext2/3/4. Quité fuse3, --disable-elf-shlibs
+ --enable-static + --disable-fuse2fs. Junto a dosfstools completa el herramental de disco real
que hoy el instalador cubre con busybox mke2fs.
rsync 3.4.4 estático (b3:40dbac6f). Gotcha: sin fase [build.phases] configure propia,
hammer autogenera su ./configure e ignora los --disable-* de la receta ⇒ hay que declararla.
Flags: --disable-{acl,xattr,xxhash,zstd,lz4,openssl} --with-included-{popt,zlib}. Quité las
build-deps ausentes y las líneas install de ficheros de servicio Alpine (rsyncd.initd/conf).
b3:a03c1ad5. Arreglé el tarball (URL con vars abuild sin expandir → bash-5.3.tar.gz
limpio + sha256), readline embebido (--without-installed-readline), quité --with-curses
(link estático) y las líneas install de bashrc/profile inexistentes. deps: ncurses+readline
+linux-headers. Primer shell POSIX completo del userland (hasta ahora sólo busybox sh).
iproute2-7.1.0 (b3:f05e947f). Quité build-deps ausentes (iptables/libmnl/elfutils/
libcap/bash) y desactivé sus features (HAVE_MNL=n HAVE_ELF=n HAVE_CAP=n HAVE_SELINUX=n)
para el 'ip'/'ss' base de la red del sistema.
mkfs.vfat/fsck.fat 4.2 estático (b3:6fdabec4) para la ESP del instalador. La receta
ya usaba ./configure directo; sólo sobraban las build-deps de regeneración autotools.
Primer esencial del userland foundational que compila real: GNU sed 4.10 estático
musl (b3:f237dd4b), quitando el build-dep espurio 'perl' (sólo tests/docs de Alpine)
y el -flto=auto que zig-cc rechaza. Valida el patrón de de-Alpinización de la tanda
base-system-1 (imports Alpine punto-de-partida → recetas limpias).
hammer-install crece una cara humana sin tocar la mecánica EFI/BIOS validada:
- sin device + TTY ⇒ interactive_setup: detecta discos (/sys/block, marca el
montado como posible medio live), el usuario elige + confirma escribiendo el
nombre del disco, y recoge hostname / credencial de root (contraseña vía
cryptpw o authorized_keys) / zona horaria (best-effort si hay tzdata) /
teclado / tamaños de / y /store.
- apply_post_install_config escribe hostname+hosts, reemplaza el hash de root en
/etc/shadow, instala authorized_keys, symlinkea localtime y deja install.conf;
se llama tras la copia en AMBAS ramas (EFI y BIOS).
- con device ⇒ autoinstalador de siempre (iso/efi-install-test intactos); la
config sale de env (HAMMER_HOSTNAME/ROOT_PW/ROOT_AUTHKEYS/TZ/KEYMAP).
- iso-image.sh: ISO instalador sin AUTO_INSTALL ahora recibe con la TUI en la
consola (INSTALLER_INTERACTIVE, default on) y ofrece reiniciar/caer al live.
Verificado: scripts/install-tui-test.sh (4/4, dry-run con sysfs+rootfs falsos)
+ iso-install-test.sh VERDE end-to-end en QEMU (autoinstalador con la config
nueva bajo busybox real → disco bootea solo y sirve SSH).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Los huecos reales para una distro completa (el sistema ya está: bootstrap/
self-host/kernel/init/EFI/paquetería). Cola aislada en incoming-clib:
git rsync bash ca-certificates sudo doas util-linux sed tzdata e2fsprogs
dosfstools parted iproute2 iputils dhcpcd vim dbus foot. Import 18/18
(17 alpine + 1 nix), deps ya-canónicas podadas. Patches musl viajan.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
hammer boot menu ata las tres piezas del contrato: emite el grafo → lanza el
compositor (mirada, --compositor configurable) → activa el nodo que el usuario
dejó en boot-select. Graceful: sin compositor (servidor headless) emite el grafo
y sigue el arranque. Refactor: activate_and_report compartido con boot activate;
--out/--select configurables (testeable sin /run/hammer root-only).
Wiring: iso-image INSTALLER=1 + install-image-efi bundlean el CLI hammer (static
musl) al sistema instalado (el producto trae arje-zero/hammerd pero no el CLI);
el wrapper /sbin/init lo invoca tras hammer-recover, salida al serial (no pinta
tty0 ⇒ respeta cero-parpadeo). Cierra la pieza #3 del handoff mirada (quién
lanza el menú en el boot): lo ownea hammer, desde el hook de init.
Tests: boot_menu.rs (3 caminos del glue: graceful/sin-selección/selección→activate)
+ efi-disk-boot-test asevera que el menú corre. Validado en OVMF: pivote →
INIT-OK → menú (emite boot-graph.json + saltea sin mirada) → arje-zero.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Validado por captura de framebuffer OVMF-GOP: el kernel metal con deferred-
takeover + quiet no toca el framebuffer (Δ=0). Falta sólo el seamless i915 y el
metal real.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
efi-flicker-test valida por CONTRIBUCIÓN del kernel al framebuffer (2 capturas:
handoff-firmware vs post-boot; Δ≈0 ⇒ el kernel no tocó el FB). Con el kernel
metal cero-parpadeo: Δ=0.000 VERDE — el splash de la firmware sobrevive intacto,
sin texto de boot ni cursor (el kernel viejo saltaba de ~3 a ~11). No mide negro
absoluto: el splash de OVMF (TianoCore) daría falso-positivo y no existe en metal.
Fix: busybox switch_root NO mueve /dev ⇒ los wrappers /sbin/init montan devtmpfs
antes de tee'ar HAMMER-EFI-INIT-OK a /dev/ttyS0 (si no, el nodo no existe y el
marcador se perdía). efi-disk-boot-test VERDE con el kernel quiet.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
El 1er número de identify -verbose varía por quantum (10.99 en PPM vs 0.129 en
PNG para la misma imagen); el normalizado 0..1 es fiable. Validado: negro→0,
texto→11, umbral 1.5 los separa.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER=y (fbcon no toca el framebuffer
hasta el primer output ⇒ pantalla negra desde la firmware hasta que mirada abre
el DRM). Cmdline horneada: quiet loglevel=3 vt.global_cursor_default=0, sin el
earlyprintk=efi,keep ignore_loglevel de bringup (forzaban salida y rompían el
deferred-takeover). Orden de consola: ttyS0 ÚLTIMO ⇒ /dev/console=serie ⇒ la
shell de arje-zero sale por serial, no pinta tty0 (pantalla). CONFIG_LOGO ya off.
Fix diagnosticado por captura de framebuffer en OVMF-GOP. Rebuild en curso.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Con el kernel metal cero-parpadeo (quiet), los marcadores serie kernel-side
(EFI-stub/Linux-version/EXT4) desaparecen. Los /init de pivote + /sbin/init
real ahora tee'an marcadores a /dev/ttyS0 (escritura al puerto directo, sortea
el printk ⇒ sobreviven quiet): HAMMER-EFI-DISK-PIVOT-OK + HAMMER-EFI-INIT-OK.
efi-disk-boot-test y efi-install-test pasan a apoyarse en ésos (kernel-side =
informativos). Compatible con el kernel viejo (verbose) también.
efi-flicker-test.sh: valida cero-parpadeo por captura de framebuffer OVMF-GOP
(media de brillo < umbral ⇒ pantalla negra, sin texto de boot). El seamless
i915 queda para metal Intel real.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Evidencia por captura de framebuffer en OVMF-GOP: el kernel metal pinta todo
el log de boot sobre el FB gráfico (simpledrm 160x50). Quitar console=tty0 no
alcanza (VT_CONSOLE=y auto-registra); quiet/loglevel por LoadOptions no frena
(fbcon redibuja el ring buffer + ignore_loglevel horneado fuerza salida).
Fix identificado (requiere rebuild del kernel metal, cambia hash firmado):
CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER=y + cmdline horneada quiet
loglevel=3 vt.global_cursor_default=0 sin earlyprintk/ignore_loglevel
(CONFIG_LOGO ya off). Seamless i915 sólo validable en metal Intel real.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
efi-install-test.sh cierra el lazo completo bajo UEFI (hermano de
iso-install-test.sh que es BIOS): (1) ISO live EFI=1 INSTALLER=1 AUTO_INSTALL
en OVMF con disco en blanco → hammer-install detecta /sys/firmware/efi y toma
la rama EFI (MBR+ESP-0xEF) desatendido → HAMMER-INSTALL-OK; (2) el disco
instalado bootea SOLO en OVMF → firmware → BOOTX64.EFI → pivote → arje-zero
PID1, sin GRUB. VERDE end-to-end.
Prueba el instalador live REAL corriendo dentro del live, no sólo sus
artefactos. ADR 0010: paso 5 cerrado salvo metal.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
hammer-live-install.sh detecta /sys/firmware/efi y ramifica a EFI-stub soberano:
MBR con ESP tipo 0xEF (UEFI arranca una ESP MBR igual que GPT ⇒ sólo busybox
fdisk/mkfs.vfat/mount, sin GPT-tool ni mtools en el live). Arma el mismo
initramfs de pivote (findfs LABEL=hammer-root → switch_root) que el builder
host-side; /sbin/init = wrapper hammer-recover→arje-zero (el pivote ya montó
store/estado por LABEL). La rama BIOS+GRUB queda intacta tras la detección.
iso-image.sh INSTALLER=1 bundlea el kernel metal EFI-stub (bzImage-efi) en el
payload; el genérico no sirve (no hornea initrd=/rdinit= en la cmdline).
MBR+ESP-EF spot-checked en OVMF (firmware → BOOTX64.EFI → pivote → arje-zero).
ADR 0010 actualizado: pasos 2 y 5 ✅.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
install-image-efi.sh arma una imagen GPT+ESP donde el bzImage metal ES el
binario EFI (\EFI\BOOT\BOOTX64.EFI, ruta fallback removible) — sin GRUB ni
systemd-boot. La cmdline horneada del kernel (initrd=/initramfs.cpio.gz
rdinit=/init) se activa al no haber LoadOptions; un initramfs mínimo de pivote
resuelve hammer-root por LABEL (findfs) y hace switch_root a la ext4 real.
Layout: ESP + hammer-root/store/state ext4 (mke2fs -d bajo unshare -r, ESP con
mtools de hammer). Cierra el paso 2 (initrd chico destraba EFI-stub) y el 5.
efi-disk-boot-test.sh valida en OVMF (sin -kernel): VERDE — firmware →
BOOTX64.EFI → pivote → arje-zero PID1. Marcadores serie deterministas (los dos
primeros bytes del handoff firmware→kernel son informativos; el veredicto se
apoya en el montaje/re-mount aguas abajo, prueba concluyente de la cadena).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Hornea firmware nvidia/gp106 (ctxsw/acr/sec2) descomprimido a .bin (nouveau da GL 3D).
- init: modo HARDWARE por defecto (WGPU_BACKEND=gl sobre gallium-nouveau, que da float16
vía unpackHalf2x16; tapa lavapipe). Pascal no tiene NVK ⇒ greeter va por GL, no Vulkan.
- cmdline default = hardware; 'mirada.sw nouveau.modeset=0' = fallback software.
- CHIP/FW_SRC parametrizables para otras GPUs.
Regresión: el fallback software sigue levantando el compositor en la imagen final.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- recipes/mesa-swrast.toml: mesa softpipe hammer-nativo (sin LLVM) para render software.
- scripts/mirada-usb.sh: ensambla rootfs (dev-fs musl + hydrate mirada/seatd/libinput/
mesa + overlay Alpine llvmpipe/lavapipe/nouveau + XKB + PAM + init seatd+compositor) y
empaqueta la USB con linux-generic vía systemd-boot.
- docs/mirada-usb-nvidia.md: uso + estado.
Validado en QEMU virtio-gpu: el COMPOSITOR arranca entero (libseat→card0→GBM+EGL+
GlesRenderer→[8/8]→escritorio, acepta clientes, dibuja la ventana del greeter). El
GREETER (Vello) exige shaders float16 que llvmpipe/lavapipe NO dan ⇒ su login sólo
pinta con GPU real (nouveau+firmware, v2).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
El fix cargo_vendor_dir (b580c5b) destrabó mise: selló (ELF estático funcional,
mise 2026.7.0) y se promovió. Sale del diferido; queda en recipes/mise.toml con
[source] cargo_vendor_dir=.hammer-cargo-vendor. README del diferido actualizado.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
`cargo vendor vendor` borra lo que no reconoce del dir destino; proyectos que
commitean su PROPIO vendor/ (mise → vendor/aqua-registry, 3.1MB que build.rs lee)
lo perdían → build.rs falla 'No such file'. Nuevo campo opcional [source]
cargo_vendor_dir (default 'vendor', sin cambios para las ~200 recetas selladas)
manda el vendoreo cargo a otro dir; el .cargo/config.toml que emite cargo vendor
ya apunta ahí. mise.toml usa '.hammer-cargo-vendor'. Validado en vivo: aqua-registry
sobrevive + compila 591 crates pasando los muros previos (openssl vía rustls + AR).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>