gioser

sergio/takana

> 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 co…

TOML 1389Shell 137Markdown 80Rust 802602 Definiciones

bootstrap: hammerd como receta Cargo en Stage 1 (Lote 7)

Cierra el userland mínimo salvo el init definitivo. hammerd entra como tercer
componente de stage1, construido por el lab vía BuildSys::Cargo + vendoring:

- recipes/hammerd.toml: source git del repo hammer a commit fijado (ADR 0006),
  flags=["-p","hammerd"] para construir sólo ese binario del workspace, estático
  con zig cc; las deps se vendorean en el fetch (Lote 6) ⇒ build --offline
- STAGE1_COMPONENTS += hammerd; el inittab provisional lo arranca como servicio
  respawn (/usr/bin/hammerd) tras montar los pseudo-FS
- el test de recetas del repo ahora valida también hammerd.toml (parse + hash)

Falta sólo sustituir el init provisional de busybox por arje (ADR 0007) para el
CRASHED real. El cross-compile se valida en la VM.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

02827f62c99c3c53d7802bf2f4564f1bf856b30d · por Sergio · (hace 4 meses) · padre e9b055121 · ver el árbol en este commit

Delta semántico · 2

crates/hammer-bootstrap/src/lib.rs

4 archivos · +47 −20

diff --git a/crates/hammer-bootstrap/src/lib.rs b/crates/hammer-bootstrap/src/lib.rs
index 422c67ba..1bf338a7 100644
--- a/crates/hammer-bootstrap/src/lib.rs
+++ b/crates/hammer-bootstrap/src/lib.rs
@@ -165,20 +165,22 @@ pub fn seed_build_config(
 /// mismos artefactos producen el mismo hash aunque difieran en inodes o timestamps.
 pub type RootfsHash = ArtifactHash;
 
-/// Los componentes del userland mínimo, en orden de ensamblado. `musl` primero (libc), luego
-/// `busybox` (coreutils + sh + init). `hammerd` (Rust, vía receta Cargo) y el init `arje` entran
-/// en un lote posterior (ADR 0008): hasta entonces el PID 1 provisional es el `init` de busybox.
-const STAGE1_COMPONENTS: &[&str] = &["musl", "busybox"];
-
-/// `inittab` del init provisional (busybox). Monta los pseudo-FS y abre una shell. Cuando
-/// `hammerd` entre como servicio supervisado se añadirá `::respawn:/sbin/hammerd`; cuando entre
-/// `arje` como PID 1 (ADR 0007) este archivo se reemplaza por su supervisión real.
+/// Los componentes del userland mínimo, en orden de ensamblado. `musl` primero (libc), `busybox`
+/// (coreutils + sh + init), `hammerd` (daemon, receta Cargo). El init `arje` (ADR 0007) reemplaza
+/// al de busybox en un lote posterior; hasta entonces el PID 1 provisional es el `init` de busybox
+/// que arranca a `hammerd` por `/etc/inittab`.
+const STAGE1_COMPONENTS: &[&str] = &["musl", "busybox", "hammerd"];
+
+/// `inittab` del init provisional (busybox). Monta los pseudo-FS, arranca `hammerd` como servicio
+/// respawn y abre una shell. Cuando entre `arje` como PID 1 (ADR 0007) este archivo se reemplaza
+/// por su supervisión real (que entrega el `CRASHED` que la Fase 5 dejó diferido).
 const PROVISIONAL_INITTAB: &str = "\
 # Stage 1 — init provisional (busybox). Reemplazado por arje (ADR 0007) más adelante.
 ::sysinit:/bin/mount -t proc proc /proc
 ::sysinit:/bin/mount -t sysfs sysfs /sys
 ::sysinit:/bin/mount -t devtmpfs dev /dev
 ::sysinit:/bin/mount -o remount,rw /
+::respawn:/usr/bin/hammerd
 ::respawn:/bin/sh
 ::ctrlaltdel:/bin/umount -a -r
 ::shutdown:/bin/umount -a -r
diff --git a/docs/10-roadmap.md b/docs/10-roadmap.md
index b4af9f37..19cb134c 100644
--- a/docs/10-roadmap.md
+++ b/docs/10-roadmap.md
@@ -184,11 +184,12 @@ Diseño completo en [SDD 11 — Bootstrap from-scratch](11-bootstrap.md). Resume
     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), `hammer bootstrap stage1` que las construye con la
-    semilla, ensambla el rootfs FHS (hardlink) y lo sella con un `RootfsHash` de contenido +
-    init provisional (busybox/inittab). Falta: `hammerd` (receta Cargo, sourcing del plan M2) y
-    sustituir el init por `arje`. El cross-compile real se valida en la VM (los e2e se saltan
-    sin `.dev-fs`); el manifiesto anota la línea de Stage 1.
+    `busybox` 1.36.1 (estáticas, zig cc) + `hammerd` (receta Cargo: repo pinned + deps
+    vendoreadas en el fetch para build `--offline`); `hammer bootstrap stage1` las construye con
+    la semilla, ensambla el rootfs FHS (hardlink) y lo sella con un `RootfsHash` de contenido +
+    init provisional (busybox/inittab que arranca `hammerd`). Falta sólo sustituir el init por
+    `arje`. El cross-compile real se valida en la VM (los e2e se saltan sin `.dev-fs`); el
+    manifiesto anota la línea de Stage 1.
   - **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/11-bootstrap.md b/docs/11-bootstrap.md
index 7f0bec0d..92f50343 100644
--- a/docs/11-bootstrap.md
+++ b/docs/11-bootstrap.md
@@ -120,16 +120,17 @@ No introduce mecanismo nuevo de build: encadena recetas y persiste el manifiesto
 // hammer-bootstrap
 pub fn stage0(seed: &SeedSpec, store: &Store) -> Result<ArtifactHash>;            // ✅ toolchain semilla
 pub fn stage1(spec: &Stage1Spec, cfg: &BuildConfig, store: &Store)
-    -> Result<RootfsHash>;                                                       // ◑ musl+busybox+init; hammerd ☐
+    -> Result<RootfsHash>;                                                       // ◑ musl+busybox+hammerd; init arje ☐
 pub fn stage2(stage1: &RootfsHash, store: &Store) -> Result<VerifyReport>;        // ☐ rebuild + diff
 pub fn all(seed: &SeedSpec, store: &Store) -> Result<BootstrapManifest>;          // ☐
 ```
 
-`stage1` cross-compila `musl` + `busybox` con la semilla (no el zig del host), ensambla un rootfs
-FHS por hardlink y lo sella; el `RootfsHash` se deriva del **contenido** (hashes de componentes +
-init), no del árbol en disco, así que es reproducible. El PID 1 es el `init` de busybox vía
-`/etc/inittab` provisional. Falta `hammerd` (receta Cargo: ya construible por el lab, pendiente su
-sourcing pinned + vendor del plan M2) y la sustitución del init por `arje` (ADR 0007).
+`stage1` cross-compila `musl` + `busybox` + `hammerd` con la semilla (no el zig del host),
+ensambla un rootfs FHS por hardlink y lo sella; el `RootfsHash` se deriva del **contenido** (hashes
+de componentes + init), no del árbol en disco, así que es reproducible. El PID 1 provisional es el
+`init` de busybox vía `/etc/inittab`, que arranca `hammerd` como servicio respawn. `hammerd` es una
+receta Cargo (repo pinned + deps vendoreadas en el fetch para build `--offline`). Falta sólo
+sustituir el init provisional por `arje` (ADR 0007), que entrega el `CRASHED` real.
 
 `SeedSpec { kind, version, url, sha256 }` es la identidad pinned de la semilla; `seed_hash()`
 deriva el `ArtifactHash` de `(kind, version, sha256)` — no del `url` ni del host, así que
@@ -139,7 +140,7 @@ CLI (implementado lo de Stage 0; el resto pendiente):
 
 ```
 hammer bootstrap stage0 --url URL --sha256 HEX --version V [--seed zig|musl-cross-make]   # ✅
-hammer bootstrap stage1 --seed-hash HASH [--seed zig] [--recipes DIR]                      # ◑ musl+busybox
+hammer bootstrap stage1 --seed-hash HASH [--seed zig] [--recipes DIR]                      # ◑ musl+busybox+hammerd
 hammer bootstrap stage2 --verify                                                           # ☐
 hammer bootstrap --all                # las tres + reporte de reproducibilidad             # ☐
 ```
diff --git a/recipes/hammerd.toml b/recipes/hammerd.toml
new file mode 100644
index 00000000..cecdfa74
--- /dev/null
+++ b/recipes/hammerd.toml
@@ -0,0 +1,23 @@
+# hammerd — daemon de hammer (bus de agente en /run/agent.sock + diario de mutaciones), como
+# servicio del userland mínimo del Stage 1 (SDD 11 §3).
+#
+# Receta Cargo (ADR 0008 / BuildSys::Cargo): el lab construye el crate `hammerd` del workspace
+# hammer a un commit fijado (ADR 0006), con las deps vendoreadas en el fetch para un build
+# hermético `--offline`. Enlaza con `zig cc` cross al target. El init provisional (busybox) lo
+# arranca por /etc/inittab; cuando entre `arje` (ADR 0007) pasará a ser un servicio supervisado.
+
+name    = "hammerd"
+version = "0.0.1"
+
+[source]
+# El repo del propio hammer: el `commit` es el identificador inmutable (la URL es sólo locator y
+# no entra al hash de la receta). Subir el commit cuando hammerd avance.
+repo   = "ssh://gitea@git.gioser.net:2345/sergio/hammer.git"
+commit = "e9b055121322d3ef8aef8e75738052d5aff0693a"
+
+[build]
+compiler = "zig-cc"
+target   = "x86_64-linux-musl"
+link     = "static"
+# Sólo el binario `hammerd` del workspace (no el resto de crates).
+flags    = ["-p", "hammerd"]