scripts/product-image-from-repo.sh cierra el lazo Etapa F+G entero:
base product-rootfs (arje-zero PID1 + musl/busybox) → hidrata userland rico vía
`hammer install --require-signed` del repo firmado → imagen GRUB auto-booteable →
boot en QEMU + handshake SSH que CORRE los tools del repo.
VALIDADO e2e: booteó, arje-zero PID1, hammerd+netup+sshd, y por SSH corrieron
bat 0.26.1 / fd 10.4.2 / jq 1.8.1 / eza — userland farmeado, servido desde el
repo firmado, no del bootstrap hardcodeado. 240 bins en /usr/bin (base+repo).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Cierra el lazo Etapa F+G: el userland del producto se arma vía `hammer install
--repo --prefix --require-signed` desde el repo firmado, no del bootstrap
hardcodeado. scripts/product-userland-from-repo.sh hidrata un set curado (13+
tools validados estáticos del repo).
Dos bugs reales del path install/pack encontrados+arreglados:
1. pack derivaba target_bin=/usr/bin/{name}; para paquetes con binario≠nombre
(ripgrep→rg, repgrep→rgr) quedaba mal y el sanity-check de install fallaba.
Ahora pack lo deriva del flag `--bin <X>` de la receta Cargo.
2. La reproducción del source_patch derivaba el NOMBRE de la receta del
target_bin ⇒ "rg" ≠ "ripgrep" del corpus ⇒ no cache-hit ⇒ rebuild + dup en
el store (find_by_hash ambiguo). build_source_patch/run_apply ahora reciben
el nombre del paquete (install/bootstrap lo pasan; apply=None) ⇒ cache-hit
del artefacto del corpus, sin duplicar.
(El "EACCES" inicial era sólo --store ausente: DEFAULT_STORE=/store root-only.)
hammer-build 49/49 tests ok; ripgrep install validado e2e (rg hidratado).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Cierra el último tramo de validación de B.2 (adoptar arje como init): el
adaptador arje_link ya estaba escrito y cableado en main, pero su único test
era un round-trip del espejo contra sí mismo — no probaba la ruta de transporte
real ni el contrato con arje-bus.
arje_link_e2e levanta un socket falso de arje-bus (mismo wire: frames
u32-BE-len + postcard), valida que el adaptador emite el frame Subscribe exacto
([00 01 00 0D]), le inyecta un EnteCrashed(Killed 11), y verifica que sale como
Event::Crashed{code:139} por el EventBus — ejercitando run() entero
(connect→subscribe→leer→traducir→publicar) sin necesitar un init vivo. run()
pasa a pub(crate) para que el test lo maneje. El contrato de bytes con arje-bus
queda fijado del lado arje por arje-bus::contrato_wire.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
libevent 2.1.12 (async/red), libgpg-error+libgcrypt (cripto), libuv 1.52
(async; necesitó ./autogen.sh, el dist tarball no trae configure), json-c 0.18
(CMAKE — el rootfs tiene cmake), freetype 2.14 (fuentes, vs zlib+libpng con el
fix CPPFLAGS/LDFLAGS). Set de libs base ya cubre 20+ deps de cola C/-sys.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
El pkill del rsync dejó el store/<hash>-pixi parcial (sin binario); build-farm
hizo cache-hit por presencia del dir y lo promovió. Vuelve a incoming para
re-cosecharlo completo. rustcat/sshs/tere quedan (estáticos, íntegros).
Cosechado tras recuperar conexion (terremoto corto el ISP local). El VPS siguio
moliendo autonomo durante el corte. pixi (entornos), rustcat (nc), sshs, tere.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
zstd 1.5.7 (libzstd.a — zstd-sys en montones de crates), xz 5.8.3 (liblzma.a),
bzip2 1.0.8 (libbz2.a), libsodium 1.0.22 (libsodium.a). Compresión/cripto =
deps de muchísima cola C + crates -sys. compiler=gcc, estáticas.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
libffi 3.5.2 (libffi.a), sqlite 3.53.2 (libsqlite3.a, FTS3/4/5+rtree+threadsafe),
readline 8.3 (libreadline.a+libhistory.a, vs ncurses/libtinfo del corpus).
Alto unlock: sqlite destraba atuin y la cola DB; libffi el mundo python/-sys.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
hurl 8.0.1 estaba diferido por necesitar libcurl+libxml2+openssl. Con las 3
libs base ahora en el corpus, curl-sys/libxml las materializan y hurl construye
estático. Prueba de que el track de libs base abre los tools bloqueados.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
angle-grinder, cargo-auditable, cargo-fuzz, cargo-supply-chain, cargo-temp,
evcxr (REPL Rust), fblog. Construidos en el VPS, estáticos. Total cosechado
del VPS esta sesión: 24 tools.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Track de libs fundacionales (pivote tras gmp). Ambas static-musl, gcc:
- pcre2 10.47 → libpcre2-8.a + libpcre2-posix.a (regex; dep de pcre2-sys, grep-variants)
- libxml2 2.13.9 → libxml2.a (XML/HTML; dep de mucha cola C + crates -sys)
FIX CLAVE de comportamiento del lab (causa de los fallos previos, gmp incluido):
el lab tiene fases configure Y compile SEPARADAS; si configure se deja vacío, la
heurística inyecta su propio ./configure minimal (defaults → python/probe) que
corre ANTES y aborta. Solución: definir [build.phases].configure explícito.
libxml2 con --without-python/lzma/zlib; configure-phase split lo desbloqueó.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Primera lib C del track base. El probe de configure de gmp no linkea su conftest
(undefined reference to main) bajo gcc 15.2/C23 + el sandbox; el patch Alpine no
alcanza. Track de libs base confirma ser el trabajo no-trivial (no cores).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
cargo-careful, cargo-cyclonedx, cargo-feature, cargo-flamegraph, cargo-insta:
construidos ÍNTEGRAMENTE en el VPS Hetzner, cosechados al hub (rsync store↓ +
build-farm cache-hit → promote + firma). El laptop NO compiló nada de esto.
Todos ELF static-musl. Pipeline distribuido trustless validado end-to-end.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
import-batch fuel-1 (95 candidatos): yield 65/95, dedup vs corpus/deferred →
~57 nuevas pineadas a incoming/. Empujadas al worker Hetzner (rsync aditivo);
69 recetas en su cola = ~1 día de molienda a 2 cores sin idle.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Tres frentes que aparecieron al provisionar un CCX13 (Ubuntu 24.04) de verdad:
- bootstrap-devfs §3b: el loader musl-256-keys ahora DETECTA la versión del
rootfs (apk db) en vez de hardcodear 1.2.5. Alpine edge avanzó a musl 1.2.6 ⇒
un loader 1.2.5 vs coreutils 1.2.6 da `renameat2: symbol not found` → chmod
roto en el sandbox → el wrapper zig-cc no queda +x → EACCES. case con sha de
1.2.5 y 1.2.6, die si aparece una nueva.
- vps-setup §2b: compila bubblewrap 0.11.2 si el de la distro no soporta
--overlay-src (Ubuntu 24.04 trae 0.9.0 sin overlayfs; el sandbox lo necesita).
- farm-sync: excluye /.scratch (44G de fuentes mrustc/rustc) + *.png/content*
del rsync al worker (casi copia 44G de más).
Smoke test en el VPS: builds compilan código real (pasan cc/chmod), rustc 2
cores al 93%, RAM holgada. Worker funcional.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Paraleliza el build a un/varios VPS sin exponer gitea ni la clave de firma.
Modelo: el laptop es el HUB (firma + gitea); el worker sólo construye la cola
incoming/ y sella al store local (PROMOTE=0). Reproducibilidad bit-a-bit +
content-addressing ⇒ el store del worker es byte-idéntico, se rsync-ea de vuelta
y el hash valida solo (no hay que confiar en el VPS).
- vps-setup.sh: provisiona Debian/Ubuntu (deps, userns p/bwrap, swap 16G,
rustup, build hammer, bootstrap-devfs rootfs Alpine edge, systemd unit).
- farm-worker-loop.sh: loop autónomo 24/7, PROMOTE=0, watchdog de disco
integrado; muele lo que haya sin esperar al hub.
- hammer-farm.service: systemd, JOBS=2 (CCX13 = 2 vCPU dedicado), Nice/idle-io.
- farm-sync.sh (hub): rsync código+cola arriba, store sellado abajo,
promote+firma+commit+push. Acceso único laptop->VPS por SSH.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Granja nocturna JOBS=4 + watchdog de disco (drena work/sources no-activas
cada 3 min ⇒ disco acotado, no se llenó). import 38/45 → 36 a cola →
build-yield 20/36. Todos ELF static-musl que corren:
bingrep 0.12, cargo-deb 3.7, cargo-llvm-lines 0.4, cargo-modules 0.26,
cargo-wipe, cargo-zigbuild 0.22, cpc 3.0, csview 1.3, dufs 0.46,
fastmod 0.4, git-graph 0.7, jql 8.0, kibi 0.3, ox 0.7, ruplacer 0.10,
rustic 0.11, simple-http-server 0.8, ttyper 1.6, xan 0.59, zenith 0.15.
16 fallos quedan staged en incoming/ para triage (frontera de libs C /
imports rotos). Verificado `file ... statically linked` en los 20.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Drenada la cola de 14 staged. 5 sellados+publicados al repo firmado, todos
ESTÁTICOS y ejecutan (versión correcta):
- topgrade 17.6.1, git-absorb 0.9.0, cargo-audit 0.22.1, yazi 26.5.6, cargo-edit 0.13.11
Patrón común de de-Alpinización (estilo zellij): el lab NO trae `cargo auditable`
⇒ reescritas LIMPIAS sin él ni manpage/completions. Claves de la tanda:
- SIN fase compile custom ⇒ path default del lab (aplica crt-static tras `cargo
rustc --`, sólo el bin top, NO en RUSTFLAGS donde rompería los proc-macros) +
linker zig-cc ⇒ binario estático. Las fases custom con `cargo build` salían
DINÁMICAS (musl pie) y no corrían en el host — corregido.
- compiler="gcc" donde hay deps-C de build-script (git2/openssl/ring/mlua-lua/
jemalloc/onig): el CC=zig global rechaza el triple x86_64-alpine-linux-musl; el
gueto gcc-musl los compila, linker sigue zig-cc. +deps zlib en git-absorb/cargo-audit.
- cargo-edit: 4 bins (cargo-add/rm/upgrade/set-version, no hay bin `cargo-edit`);
el path default (`cargo rustc -- flags`) exige un único target ⇒ fase custom que
itera los 4 bins con crt-static por-bin.
- yazi: dropeado el patch system-lua + dep lua5.5 ⇒ mlua vendorea su Lua.
Diferidos a incoming/.deferred (frontera dura, motivo documentado):
- jless → libxcb (clipboard X11, dep real sin receta)
- b3sum → proyecto anidado con Cargo.lock propio (el vendor del lab no lo alcanza)
- dprint/mprocs → libclang.a/bindgen (clang-sys estático)
- hck → libz-sys (-lz no hallado), kalker → gmp, dura → Cargo.lock stale,
xcp → libfs i32/u64 musl, mdcat → #![deny(warnings)] en lib (path default no
deja inyectar --cap-lints)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
nushell 0.104.1: uno de los paquetes más duros del ecosistema (openssl-sys + libgit2-sys +
libssh2-sys + libsqlite3-sys + mimalloc, todos sus C vendoreados). Fix clave: convertir la
receta del estilo abuild (fase compile custom, que NO monta el wrapper .hammer-zig-cc) al
build POR DEFECTO (flags=['--bin','nu']) ⇒ el wrapper traduce el target alpine→musl que zig
no conoce, y los -sys compilan. Dropea system-deps.patch (vendor todo). mise diferido
(.deferred: su build.rs busca git/archivo en build-time).
HALLAZGO GENERAL: recetas import-Alpine con fase abuild + C-deps fallan porque la fase custom
no monta el wrapper zig-cc. Fix = usar el build por defecto (sin fase compile).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Granja dedicada de giants (JOBS=3, RAM 31G): zola ✓ (no necesitaba fix, solo tiempo).
mise ✗ (su build.rs busca git/archivo faltante) y nu ✗ (openssl-sys: la fase abuild no
monta el wrapper zig-cc → zig recibe target alpine que no conoce) quedan para fix.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Granja sobre incoming (giants apartados): monolith + tuc + cargo-generate + cargo-outdated
sellados y promovidos + repo re-firmado. Valida los fixes de hammer-build de esta sesión:
- monolith: openssl-sys vía OPENSSL_DIR.
- cargo-generate/cargo-outdated: cargo-tools COMPLETOS (git2+openssl) — libgit2-sys vendorea
su libgit2 con cmake; openssl-sys usa la openssl del corpus. Frontera C-FFI destrabada.
- tuc: cargo build (sin auditable).
14 staged (aws-lc/lint/C-libs/mecánicos) + 3 giants en .deferred para tanda dedicada.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Aplica el mismo patrón openssl a los cargo-* (dep 'openssl' ⇒ OPENSSL_DIR) y deja que
libgit2-sys vendoree su propio libgit2 con cmake (sin dep espuria). cargo-audit: además
'cargo auditable'→'cargo build', fix path '../target'→'target', dep 'openssl-dev>3'→'openssl'.
Quedan staged para la próxima granja (validar el vendoring de libgit2 con zig-cc/cmake).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Dos fixes en hammer-build que juntos destraban las recetas con C-FFI:
- Inyecta OPENSSL_DIR=/usr + OPENSSL_STATIC + OPENSSL_NO_VENDOR cuando la receta declara
'openssl' como dep ⇒ openssl-sys usa la openssl hammer-built (estática/musl) en vez de
buscar en el host y abortar.
- resolve_dep_path(): fallback al catálogo PADRE — una receta en recipes/incoming/ ahora ve
las deps del corpus recipes/ sin duplicarlas (la granja construye desde incoming/).
Recetas: +dep openssl a monolith/mdcat/mise; tuc saca 'cargo auditable'→'cargo build'.
VALIDADO: monolith v2.10.1 sella (openssl-sys linkea contra la openssl del corpus).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Diagnóstico cerrado: el reboot-probe probó que el kernel está VIVO en el metal del
usuario (se reinicia solo); la pantalla negra es porque el panel TigerLake se apaga al
pasar el kernel y solo i915 (driver Intel real) lo reenciende — efifb/simpledrm/earlyprintk
escriben a un fb muerto (validado: nomodeset tampoco). Era un recorte de más (i915 venía
-d del kernel QEMU). Fix = lo que toda distro normal trae:
- linux-metal.toml: -e DRM_I915 -e DRM_FBDEV_EMULATION (saca -d DRM_I915).
- metal-firmware.sh: inyecta i915/tgl_* (DMC/GuC/HuC, 1.3M) en /lib/firmware/i915.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Diagnóstico metal: con systemd-boot, earlyprintk=efi NO imprime NADA del kernel
(solo 'Loaded initrd MEDIA_GUID' + 'Measured initrd PCR 9' y cuelga) ⇒ el kernel
no llega ni a su consola temprana: hang en ExitBootServices o el decompresor.
- metal-usb-sdboot.sh: piso de 48MiB a la ESP (FAT32 -F exige ~33MiB; con initramfs
chico caía debajo y la firmware no leía el BOOTX64.EFI → 'Not Found').
- USB de bisección (work/hammer-tiny-usb.img, initramfs busybox 1.3MB): ✓ OVMF llega a
/init. Si en el metal del usuario ARRANCA a shell ⇒ el cuelgue era el initrd 100MB;
si TAMBIÉN cuelga ⇒ es el kernel/EBS (probar nokaslr/no5lvl).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
tandas/cli-rust-7.txt (24 nombres, yield 6/24: yazi/topgrade/kalker/git-absorb/jless/tuc;
el path nix dio 0 por el gotcha de sandbox, solo Alpine). Cola incoming=21 para drenar.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
El boot por EFI-stub DIRECTO se cuelga en el firmware del usuario tras 'Measured initrd
PCR 9' (quirk EFI_LOAD_OPTION del firmware + initrd 100MB por la firmware). Pivote:
- scripts/metal-usb-sdboot.sh: arma work/hammer-metal-usb.img (disco GPT+ESP FAT32) con
systemd-boot (binario del host, crutch de bringup) como BOOTX64.EFI + loader entry.
systemd-boot provee el initrd por LoadFile2 (esquiva el parseo de cmdline del firmware)
y permite EDITAR la cmdline en vivo (tecla 'e') ⇒ iterar sin recompilar 45min.
✓ VALIDADO OVMF: menú → 'Loaded initrd from LINUX_EFI_INITRD_MEDIA_GUID' → arje-zero PID1.
- linux-metal.toml: kernel diagnóstico — cmdline +earlyprintk=efi,keep +ignore_loglevel
+efi=novamap (ve el boot en pantalla post-ExitBootServices) y -DEBUG_WX (saca el trace).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
work/hammer-metal.iso (257M) bootea en OVMF por las dos vías como DISCO:
- virtio-disk y USB-storage(xhci): EFI-stub carga kernel+initrd de la ESP (GPT
isohybrid), cmdline horneado aplica, usbhid/cfg80211 init, arje-zero PID1, SIN panic.
- El '-cdrom' falla (El Torito EFI se trunca >32MB) pero es IRRELEVANTE: un USB es disco
⇒ la firmware lee la ESP por GPT. Confirmado el escenario real del pendrive.
Falta solo el hardware: quemar y bootear (Secure Boot OFF).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
scripts/hammer-banner.txt: icono ASCII cabeza-de-martillo rellena de '#' (el hash
content-addressed) + handle, wordmark 'hammer' (toilet pagga, estilo pixel-block que
rima con la cabeza de hashes) + acrónimo HAMMER + uso WiFi. metal-iso.sh lo copia a
/etc/motd ⇒ es lo primero que ves al loguear en consola. Reutilizable como base de
logo/wallpaper.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
La rama GRUB-EFI cuelga (bug GRUB 2.14 del host rolling, afecta a cualquier kernel).
Solución: bootear el kernel por su EFI-STUB directo, sin GRUB-EFI.
- linux-metal.toml: CONFIG_CMDLINE_BOOL=y + CMDLINE horneado
('console=tty0 ... initrd=/initramfs.cpio.gz rdinit=/init'). Sin FORCE ⇒ en BIOS
GRUB sigue mandando su cmdline. Confirmado en fuente (libstub/file.c:50): el
EFI-stub convierte '/'→'\' y efi_load_initrd cae a la carga por cmdline sin loader.
- iso-image.sh: modo EFI_STUB=1 ⇒ la ESP lleva el bzImage como \EFI\BOOT\BOOTX64.EFI
+ initramfs.cpio.gz en su raíz (FAT32). La firmware lanza el kernel directo.
- metal-iso.sh: pasa EFI=1 EFI_STUB=1 (híbrido: BIOS GRUB + UEFI EFI-stub).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- scripts/metal-iso.sh: arma work/hammer-metal.iso (kernel metal + firmware AX201
+ wpa_supplicant + wifi-connect), consola en pantalla (console=tty0).
- VALIDADO BIOS (QEMU): el kernel metal bootea, inicializan usbhid/i8042 (teclado),
e1000/e1000e/igb, cfg80211+regulatory (stack WiFi), simpledrm/VGA console, y
arje-zero arranca PID1. iwlwifi/nvme presentes (no bindean en QEMU sin hw real).
- HALLAZGO: la rama UEFI (OVMF) NO bootea el kernel — regresión pre-existente de
GRUB 2.14 (host rolling): GRUB-EFI dice 'Booting' y el kernel queda mudo, con
CUALQUIER kernel (el QEMU tmb falla; efi-boot-test FALLA UEFI / PASA BIOS).
Fix propuesto: boot por EFI-stub directo (sin GRUB-EFI) — requiere kernel con
CONFIG_CMDLINE embebido + ESP con bzImage como BOOTX64.EFI.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- recipes/libnl.toml: netlink lib (libnl-3 + libnl-genl-3), estática, deps
flex/bison/m4 (regenera parsers). Base nl80211 del kernel metal.
- recipes/wpa_supplicant.toml: supplicant WPA2 2.11, driver nl80211 sobre libnl,
CONFIG_TLS=internal (sin dep openssl; suficiente WPA2-PSK). Compila a la 1ra con
zig-cc/musl ⇒ wpa_supplicant/wpa_cli/wpa_passphrase ESTÁTICOS x86-64. udhcpc de
busybox da el DHCP. (iw omitido: wpa_cli scanea.)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Pieza 1+2 de 'hammer en el metal' (laptop TigerLake, WiFi AX201):
- recipes/linux-metal.toml: variante del kernel con hardware real built-in
(efifb/simpledrm, USB+HID, AHCI/NVMe, cfg80211+mac80211+iwlwifi/iwlmvm,
e1000e/r8169, USB-CDC). Conserva los bits hammer (overlay/userns/fanotify/
virtio) ⇒ sigue booteando en QEMU. MODULES=off (monolítico, sin modprobe).
Deja linux.toml INTOCADO (su of_tree es load-bearing del selfhost).
- scripts/metal-firmware.sh: inyecta iwlwifi-QuZ-a0-hr-b0/cc-a0 + regulatory.db
en /lib/firmware de un rootfs (descomprime .zst → .ucode plano). Blobs fijos
(TODO pin a linux-firmware).
- ESTADO.md: resumen humano del proyecto.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Granja cortada a tiempo (devuelvo la CPU); promoví manualmente los 8 sellados antes del corte:
cargo-binstall/cargo-bloat/cargo-deny/cargo-expand/cargo-machete/cobalt/fnm/ripsecrets. zola
quedó a medio compilar (no sellado) + el resto de cargo-* fallan por dep-C (openssl/git2) —
quedan staged para la próxima. build-yield parcial 8/22.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sin construir (no peleamos CPU ahora). import-batch 15/15 (nix=14, alpine=1) + pin 14 tag→SHA.
Herramientas cargo + dev CLIs: cargo-edit/deny/audit/expand/machete/bloat/outdated/generate/
binstall + mdcat/zola/cobalt/mise/fnm/ripsecrets. La próxima sesión arranca con build-farm.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>