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
|
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:
|
[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).
|
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
|
- **Stage 2** ✅ — rebuild nativo dentro del rootfs y diff de hashes ⇒ **auto-alojamiento
|
||||||
bit-reproducible.
|
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`
|
- 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
|
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 —
|
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`).
|
los de red en `HAMMER_NETWORK_TESTS`).
|
||||||
- ⏳ Único ítem de las fases diferido: `CRASHED` real (necesita supervisión de servicios →
|
- ⏳ Único ítem de las fases diferido: `CRASHED` real (necesita supervisión de servicios →
|
||||||
init propio del track posterior).
|
init propio del track posterior).
|
||||||
- ⏭️ **Siguiente: arrancar el track posterior** (distro propia). Primer paso natural sin
|
- ✅ **Track posterior arrancado y con su hito mayor cerrado:** bootstrap from-scratch
|
||||||
bloquear nada: el bootstrap from-scratch Stage 0/1 con `zig`/`musl-cross-make`.
|
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
|
## Notas de entorno
|
||||||
- Desarrollo principal: laptop del autor.
|
- 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 stage0(seed: &SeedSpec, store: &Store) -> Result<ArtifactHash>; // ✅ toolchain semilla
|
||||||
pub fn stage1(spec: &Stage1Spec, cfg: &BuildConfig, store: &Store)
|
pub fn stage1(spec: &Stage1Spec, cfg: &BuildConfig, store: &Store)
|
||||||
-> Result<RootfsHash>; // ◑ musl+busybox+hammerd; init arje ☐
|
-> 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>; // ☐
|
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
|
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
|
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
|
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
|
determinismo necesario lo dan las rutas fijas (`/src`) + `SOURCE_DATE_EPOCH` del sandbox +
|
||||||
in-rootfs es el sub-ítem que queda (corre en la VM destino).
|
`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()`
|
`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
|
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 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 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 # ☐
|
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)
|
## 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
|
La verificación de reproducibilidad de Stage 2 está operativa, probada y **ejecutada end-to-end**:
|
||||||
de bytes) + `verify_against`, y los 4 componentes reconstruyen **bit-idéntico** (ver
|
`of_tree` (content-hash de bytes) + `verify_against`, los 4 componentes reconstruyen
|
||||||
[runbook §8/§8b](runbooks/stage1-vm-boot.md)). Lo que falta es el **rebuild *dentro* del rootfs
|
**bit-idéntico**, y el **rebuild *dentro* del rootfs** ya corrió en la VM dando `✓ REPRODUCIBLE`
|
||||||
usando sólo sus herramientas** — y ahí aparece el obstáculo real:
|
(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**
|
> 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
|
> (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
|
deterministas). El sub-ítem era: **ensamblar el builder** (variante de `assemble_rootfs` que hidrata
|
||||||
el toolchain) y **correr el rebuild anidado** en la VM.
|
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):
|
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*
|
`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
|
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
|
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**:
|
`3ce721ec…` ⇒ builder `81dad3d9…`, 1.2 GB con el toolchain). **El paso operacional ya se ejecutó:**
|
||||||
bootear el builder en la VM y correr `rebuild-stage1` (ver [runbook §8c](runbooks/stage1-vm-boot.md)).
|
`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
|
## 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
|
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
|
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.
|
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