docs: Stage 2 ✅ — auto-alojamiento bit-a-bit confirmado in-VM (✓ REPRODUCIBLE)
Cierra la deriva entre los docs y lo ya probado/commiteado (818c157):
el rebuild in-rootfs corrió end-to-end (host↔VM) y of_tree(stage1')=
0039b2b9… igualó la referencia ⇒ ✓ REPRODUCIBLE.
- roadmap §track posterior: Stage 2 ☐→✅; "Siguiente" reapunta al
auto-alojamiento puro (variante b) + ítems Stage 1 (bus único, atestación).
- SDD 11 §5/CLI: marcadores stage2 ◑→✅; §7 (intro/7.4/8) el rebuild in-VM
deja de ser "lo que falta" y queda la variante (b) como corte pleno.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+16
-4
@@ -194,8 +194,14 @@ Diseño completo en [SDD 11 — Bootstrap from-scratch](11-bootstrap.md). Resume
|
||||
init propio que la Fase 5 difirió ([ADR 0007](adr/0007-arje-como-init-propio.md)). Diseño en
|
||||
[SDD 12](12-init-real.md); corrida y fixes en el [runbook](runbooks/stage1-vm-boot.md). Pendiente:
|
||||
bus único (B.2: exponer el `CRASHED` a la capa de IA) y atestación (A1/A2).
|
||||
- **Stage 2** ☐ — rebuild nativo dentro del rootfs y diff de hashes ⇒ auto-alojamiento
|
||||
bit-reproducible.
|
||||
- **Stage 2** ✅ — rebuild nativo dentro del rootfs y diff de hashes ⇒ **auto-alojamiento
|
||||
bit-reproducible CONFIRMADO end-to-end (host↔VM)**. `KVM=1 MEM=24576
|
||||
./scripts/selfhost-verify.sh` reconstruye los 4/4 dentro del rootfs Stage 1 con sólo su
|
||||
propio toolchain (arje-zero cu=1 compila en ~27 min in-VM), sella el rootfs y su
|
||||
`of_tree(stage1') = b3:0039b2b9…` **iguala** la referencia ⇒ `✓ REPRODUCIBLE: stage1' ==
|
||||
stage1`. El último no-determinismo (#3, `arje-zero`/`codegen-units`) se cazó y eliminó
|
||||
imponiendo `CARGO_PROFILE_RELEASE_CODEGEN_UNITS=1` en el sandbox (commit `4c9bcc0`).
|
||||
Corrida y veredicto en el [runbook](runbooks/stage1-vm-boot.md) §8.
|
||||
- Reemplazar el init de Alpine por **tu init** (bus por pipes nativo) — habilita el `CRASHED`
|
||||
real que la Fase 5 dejó diferido. **Decisión: adoptar `arje`** (init from-scratch ya existente
|
||||
en el monorepo `tawasuyu`, con PID 1 + supervisión real) en lugar de escribir uno nuevo —
|
||||
@@ -219,8 +225,14 @@ Diseño completo en [SDD 11 — Bootstrap from-scratch](11-bootstrap.md). Resume
|
||||
los de red en `HAMMER_NETWORK_TESTS`).
|
||||
- ⏳ Único ítem de las fases diferido: `CRASHED` real (necesita supervisión de servicios →
|
||||
init propio del track posterior).
|
||||
- ⏭️ **Siguiente: arrancar el track posterior** (distro propia). Primer paso natural sin
|
||||
bloquear nada: el bootstrap from-scratch Stage 0/1 con `zig`/`musl-cross-make`.
|
||||
- ✅ **Track posterior arrancado y con su hito mayor cerrado:** bootstrap from-scratch
|
||||
Stage 0 → Stage 1 (booteado en QEMU, arje-zero como PID 1, `CRASHED` real) → **Stage 2
|
||||
auto-alojamiento bit-a-bit confirmado** (`✓ REPRODUCIBLE`, host↔VM). Baseline reproducible
|
||||
4/4: `of_tree(stage1)=b3:0039b2b9…` (cu=1).
|
||||
- ⏭️ **Siguiente:** (1) auto-alojamiento *puro* — que hammer construya el toolchain semilla
|
||||
desde fuente (no el zip de zig + Alpine como sustrato del builder), camino (b) de
|
||||
[SDD 11 §7](11-bootstrap.md); (2) ítems Stage 1 pendientes: bus único (B.2: exponer el
|
||||
`CRASHED` a la capa de IA) y atestación arje (A1/A2).
|
||||
|
||||
## Notas de entorno
|
||||
- Desarrollo principal: laptop del autor.
|
||||
|
||||
+26
-11
@@ -121,7 +121,7 @@ No introduce mecanismo nuevo de build: encadena recetas y persiste el manifiesto
|
||||
pub fn stage0(seed: &SeedSpec, store: &Store) -> Result<ArtifactHash>; // ✅ toolchain semilla
|
||||
pub fn stage1(spec: &Stage1Spec, cfg: &BuildConfig, store: &Store)
|
||||
-> Result<RootfsHash>; // ◑ musl+busybox+hammerd; init arje ☐
|
||||
pub fn stage2(stage1: &RootfsHash, store: &Store) -> Result<VerifyReport>; // ◑ ancla+verifica; rebuild in-rootfs en VM
|
||||
pub fn stage2(stage1: &RootfsHash, store: &Store) -> Result<VerifyReport>; // ✅ ancla+verifica; rebuild in-rootfs en VM ✓ REPRODUCIBLE
|
||||
pub fn all(seed: &SeedSpec, store: &Store) -> Result<BootstrapManifest>; // ☐
|
||||
```
|
||||
|
||||
@@ -141,8 +141,12 @@ entrega el `CRASHED` real— está diseñado en el [SDD 12](12-init-real.md) y *
|
||||
reales, no el hash input-addressed del store) como la referencia a reproducir, y la anota en el
|
||||
manifiesto. `verify_against` la compara con un rebuild `stage1'` producido **dentro** del rootfs (en
|
||||
la VM, recompilando con sólo las herramientas de Stage 1): iguales ⇒ auto-alojado bit a bit. El
|
||||
determinismo necesario lo dan las rutas fijas (`/src`) + `SOURCE_DATE_EPOCH` del sandbox. El rebuild
|
||||
in-rootfs es el sub-ítem que queda (corre en la VM destino).
|
||||
determinismo necesario lo dan las rutas fijas (`/src`) + `SOURCE_DATE_EPOCH` del sandbox +
|
||||
`CARGO_PROFILE_RELEASE_CODEGEN_UNITS=1` (impuesto por el sandbox tras cazar el no-determinismo del
|
||||
codegen paralelo de rustc en `arje-zero`). **El rebuild in-rootfs ya se ejecutó end-to-end**: `KVM=1
|
||||
MEM=24576 ./scripts/selfhost-verify.sh` reconstruyó los 4/4 dentro del rootfs y su
|
||||
`of_tree(stage1') = b3:0039b2b9…` igualó la referencia ⇒ `✓ REPRODUCIBLE: stage1' == stage1`
|
||||
(ver [runbook](runbooks/stage1-vm-boot.md) §8).
|
||||
|
||||
`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
|
||||
@@ -153,7 +157,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] # ✅ booteado en QEMU
|
||||
hammer bootstrap stage2 --rootfs HASH [--verify CONTENT_HASH] # ◑ ancla+verifica; rebuild en VM
|
||||
hammer bootstrap stage2 --rootfs HASH [--verify CONTENT_HASH] # ✅ ancla+verifica; rebuild en VM ✓ REPRODUCIBLE
|
||||
hammer bootstrap --all # las tres + reporte de reproducibilidad # ☐
|
||||
```
|
||||
|
||||
@@ -174,10 +178,11 @@ hammer bootstrap --all # las tres + reporte de reproducibilidad
|
||||
|
||||
## 7. Auto-alojamiento: el builder rootfs (camino a Stage 2 pleno)
|
||||
|
||||
La verificación de reproducibilidad de Stage 2 ya está operativa y probada: `of_tree` (content-hash
|
||||
de bytes) + `verify_against`, y los 4 componentes reconstruyen **bit-idéntico** (ver
|
||||
[runbook §8/§8b](runbooks/stage1-vm-boot.md)). Lo que falta es el **rebuild *dentro* del rootfs
|
||||
usando sólo sus herramientas** — y ahí aparece el obstáculo real:
|
||||
La verificación de reproducibilidad de Stage 2 está operativa, probada y **ejecutada end-to-end**:
|
||||
`of_tree` (content-hash de bytes) + `verify_against`, los 4 componentes reconstruyen
|
||||
**bit-idéntico**, y el **rebuild *dentro* del rootfs** ya corrió en la VM dando `✓ REPRODUCIBLE`
|
||||
(variante (a) abajo; ver [runbook §8](runbooks/stage1-vm-boot.md)). El obstáculo que hubo que
|
||||
resolver para llegar ahí:
|
||||
|
||||
> El Stage 1 que booteamos es un **runtime** (musl+busybox+hammerd+arje-zero): **no trae compilador**
|
||||
> (ni `zig`, ni `make`/autotools, ni `cargo`/rust, ni `linux-headers`, ni `bwrap`). No puede
|
||||
@@ -206,7 +211,7 @@ veredicto. El determinismo necesario está cubierto (paths fijos `/src`, `SOURCE
|
||||
deterministas). El sub-ítem era: **ensamblar el builder** (variante de `assemble_rootfs` que hidrata
|
||||
el toolchain) y **correr el rebuild anidado** en la VM.
|
||||
|
||||
### 7.4 Estado: el ensamblado del builder, hecho ✅
|
||||
### 7.4 Estado: builder ensamblado + rebuild in-VM ejecutado ✅ ✓ REPRODUCIBLE
|
||||
|
||||
El **ensamblado** del builder está implementado (`hammer_bootstrap::builder_rootfs`, variante a):
|
||||
|
||||
@@ -227,8 +232,12 @@ El builder **no se sella** (su `/toolchain` Alpine no es content-addressed); se
|
||||
`out_dir` para empaquetar como initramfs. Su identidad sí es reproducible: un `ArtifactHash` *lógico*
|
||||
de sus insumos (stage1 + semilla + recetas + binario + tag del toolchain + el driver), anotado en el
|
||||
manifiesto (línea stage 2). Validado contra el store real (Stage 1 `73d7a9be…` + semilla
|
||||
`3ce721ec…` ⇒ builder `81dad3d9…`, 1.2 GB con el toolchain). El paso que queda es **operacional**:
|
||||
bootear el builder en la VM y correr `rebuild-stage1` (ver [runbook §8c](runbooks/stage1-vm-boot.md)).
|
||||
`3ce721ec…` ⇒ builder `81dad3d9…`, 1.2 GB con el toolchain). **El paso operacional ya se ejecutó:**
|
||||
`scripts/selfhost-verify.sh` empaqueta el builder, lo bootea con KVM y corre `rebuild-stage1`
|
||||
no-interactivo; in-VM reconstruyó los 4/4 (arje-zero cu=1 en ~27 min) y `of_tree(stage1') =
|
||||
b3:0039b2b9…` igualó la referencia ⇒ `✓ REPRODUCIBLE: stage1' == stage1`. Lo que queda es la
|
||||
variante (b), el auto-alojamiento *puro* (toolchain construido por hammer desde fuente, §7.2).
|
||||
Ver [runbook §8](runbooks/stage1-vm-boot.md).
|
||||
|
||||
## 8. Hecho cuando
|
||||
|
||||
@@ -236,3 +245,9 @@ bootear el builder en la VM y correr `rebuild-stage1` (ver [runbook §8c](runboo
|
||||
propio toolchain y userland con hashes idénticos a los publicados**, sin que ninguna
|
||||
herramienta del host entre al resultado. Ese día Alpine deja de ser una dependencia y pasa a
|
||||
ser, a lo sumo, una conveniencia de desarrollo.
|
||||
|
||||
**Estado (2026-06-12):** el **mecanismo** está demostrado end-to-end con la variante (a) — el
|
||||
rootfs reconstruye su userland in-VM con `of_tree` idéntico (`✓ REPRODUCIBLE`, §7.4). Falta sólo
|
||||
la variante (b): que el **toolchain** dentro del builder lo construya hammer desde fuente (no
|
||||
provenga de Alpine), reemplazando una a una las piezas con Stage 2 verificando cada paso. Ese es
|
||||
el corte pleno del cordón.
|
||||
|
||||
Reference in New Issue
Block a user