docs: Stage 1 bootea end-to-end en QEMU ✅ (bitácora + roadmap)
La corrida real cierra el lazo: con el build nativo crt-static (cargo rustc), arje-zero y hammerd salen statically-linked (ET_EXEC, sin DT_NEEDED), el rootfs se sella, y el boot en QEMU (-cpu Broadwell) levanta el sistema: arje-zero (PID 1) → carga+valida /ente/seed.card.json → bucle primordial → encarna hammerd (Pid 59) + console-getty (Pid 60) → shell en consola; hammerd levanta su watcher fanotify y el agent.sock. Runbook §8: bitácora completa (todos los fixes: gcc/HOSTCC, GNU-ld, rust en el lab, triple nativo, wrapper saneador, vendoring condicional, AVX→Broadwell, dinámico→crt-static vía cargo rustc). Roadmap: Stage 1 ◑→✅. Pendiente: demo del CRASHED real (kill hammerd → restart con backoff; la supervisión Restart ya corre), bus único (B.2), atestación (A1/A2). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Semántico sayk'uy
Mana ima sutichaypas t'ikrakurqanchu: qillqalla, yachachiylla utaq willaylla t'ikrakurqan.
2 qillqakuna · +43 −9
- docs/10-roadmap.md +9 −9
- docs/runbooks/stage1-vm-boot.md +34 −0
diff --git a/docs/10-roadmap.md b/docs/10-roadmap.md
index 5245dead..f0951376 100644
--- a/docs/10-roadmap.md
+++ b/docs/10-roadmap.md
@@ -183,15 +183,15 @@ Diseño completo en [SDD 11 — Bootstrap from-scratch](11-bootstrap.md). Resume
- **Stage 0** ✅ — crate `hammer-bootstrap` + `hammer bootstrap stage0`: ingiere el toolchain
semilla pinned (`SeedSpec`, hash por identidad), verifica sha256 antes de sellar,
idempotente. Cubierto por 4 unit + 1 e2e de CLI (offline, `file://`).
- - **Stage 1** ◑ — userland mínimo cross-compilado. Hecho: recetas pinned `musl` 1.2.5 +
- `busybox` 1.36.1 (estáticas, zig cc) + `hammerd` (receta Cargo: repo pinned + deps
- vendoreadas en el fetch para build `--offline`) + `arje-zero` (init PID 1, receta Cargo a
- tawasuyu); `hammer bootstrap stage1` los construye con la semilla, ensambla el rootfs FHS
- (hardlink) y lo sella con un `RootfsHash` de contenido. El init es **arje-zero como PID 1**
- (`/sbin/init`→arje-zero) con su seed card `/ente/seed.card.json` (hammerd + getty supervisados
- ⇒ el `CRASHED` real) — diseño en [SDD 12](12-init-real.md), seed verificada contra
- `card_core::Card`. Falta: bus único (B.2) y atestación (A1/A2). El cross-compile y el boot
- reales se validan en la VM; el manifiesto anota la línea de Stage 1.
+ - **Stage 1** ✅ — userland mínimo, **booteado end-to-end en QEMU**. Recetas pinned `musl` 1.2.5 +
+ `busybox` 1.36.1 (estáticas, zig cc) + `hammerd` + `arje-zero` (recetas Cargo: repo pinned +
+ deps vendoreadas en el fetch, build nativo crt-static vía `cargo rustc`); `hammer bootstrap
+ stage1` los construye con la semilla, ensambla el rootfs FHS y lo sella. El init es **arje-zero
+ como PID 1** (`/sbin/init`→arje-zero) con su seed card `/ente/seed.card.json`; al bootear,
+ arje-zero carga+valida la seed y **supervisa hammerd + getty** (el `agent.sock` y el watcher
+ fanotify de hammerd levantan). Diseño en [SDD 12](12-init-real.md); corrida y fixes en el
+ [runbook](runbooks/stage1-vm-boot.md). Pendiente: demo del `CRASHED` real (matar hammerd → restart),
+ bus único (B.2) y atestación (A1/A2).
- **Stage 2** ☐ — rebuild nativo dentro del rootfs y diff de hashes ⇒ auto-alojamiento
bit-reproducible.
- Reemplazar el init de Alpine por **tu init** (bus por pipes nativo) — habilita el `CRASHED`
diff --git a/docs/runbooks/stage1-vm-boot.md b/docs/runbooks/stage1-vm-boot.md
index f1af59e3..11e220c3 100644
--- a/docs/runbooks/stage1-vm-boot.md
+++ b/docs/runbooks/stage1-vm-boot.md
@@ -185,6 +185,40 @@ otra razón: **tawasuyu no commitea `Cargo.lock`** (`git ls-files Cargo.lock` va
`git archive` no lo trae y `cargo vendor --locked` no puede crearlo. Decisión pendiente: commitear
el lock en tawasuyu (reproducible, plan C.2 #5) vs relajar `--locked` en el vendoring de hammer.
+**Cierres posteriores.** (1) Vendoring `--locked` **condicional** al lock committeado → arje-zero
+vendorea sin `--locked` (genera el lock) y **se sella**: los 4 componentes buildan. (2) Boot:
+AVX → `-cpu Broadwell`; y el linking **dinámico** de musl (Alpine rust es dinámico por defecto →
+`DT_NEEDED libc.musl-x86_64.so.1`; nuestro `libc.so` no exporta `memcpy/…`) → fix **crt-static**.
+(3) Iteración del crt-static (cada paso destapó el siguiente; hammerd valida barato):
+`+crt-static [-C relocation-model=static]` en **RUSTFLAGS** rompe los proc-macros (dylibs PIC) en
+build nativo → **solución:** `cargo rustc --release … -- <flags>`, que aplica los flags sólo a la
+crate top-level. musl vuelve a `--disable-shared` (no se necesita loader).
+
+### ✅ BOOT LOGRADO (2026-06-11)
+
+Con `cargo rustc -- +crt-static -C relocation-model=static`, `arje-zero` y `hammerd` salen
+**`statically linked` (ET_EXEC, sin `DT_NEEDED`, sin interpreter)**, el rootfs se sella, y el boot en
+QEMU (`-cpu Broadwell`) **levanta el sistema**:
+
+```
+arje_zero: ente-zero despierta como PID 1
+arje_zero::seed: Tarjeta Semilla cargada y validada path=/ente/seed.card.json
+arje_zero: Ente #0 entra al bucle primordial label=hammer-stage1
+arje_zero::graph::lifecycle: instanciando genesis count=2
+ Ente encarnado label=hammerd pid=Some(Pid(59))
+ Ente encarnado label=console-getty pid=Some(Pid(60))
+~ # (shell en consola)
+hammerd: arranque agent_sock=/run/agent.sock …
+hammerd: watcher fanotify activo
+hammerd::bus: escuchando sock=/run/agent.sock
+```
+
+**arje-zero es PID 1**, carga+valida la seed y **supervisa hammerd + getty**; hammerd corre con su
+watcher fanotify y su `agent.sock`. **Stage 1 bootea end-to-end.** Pendiente (demo, no diseño): matar
+hammerd y observar el restart con backoff = el `CRASHED` real (la supervisión `Restart` ya está
+activa). Comando reproducible: `qemu-system-x86_64 -m 512 -no-reboot -nographic -cpu Broadwell
+-kernel <vmlinuz> -initrd stage1.cpio.gz -append "console=ttyS0 rdinit=/sbin/init"`.
+
## 9. Cross-check opcional — `arje-packager`
arje trae su propio empaquetador (`03_ukupacha/arje/init/arje-packager`):