Fase 0+1 cerradas: GNU grep 3.12 real construido e hidratado

Cierra el primer entregable del roadmap. Cambios:

- `Source`: ahora admite dos modos mutuamente excluyentes — `git` (repo+commit) o
  `tarball` (url+sha256). El hash de entrada del artefacto usa el commit en modo
  git y el sha256 en modo tarball; ambos son identificadores inmutables del
  contenido fuente. Validación en `Source::kind()` con error claro.
- `fetch`: dispatch por modo. Tarball cacheado en `work/tarballs/<sha>.tar`,
  descarga vía `curl -fL`, verificación sha256 con `sha2`, extracción con
  `--strip-components` (default 1, GNU-style).
- `recipes/grep.toml`: GNU grep 3.12 desde el tarball release de gnu.org
  (sha256 fijado, sin patches, `--disable-perl-regexp --disable-nls`).
- Bootstrap: añade `binutils` al rootfs Alpine — configure de autotools mira
  ld/ar/ranlib incluso cuando el compilador real es zig cc.
- `.gitignore`: `/work/` (artefactos transitorios del build).
- `docs/10-roadmap.md`: Fase 0 y Fase 1 marcadas ; entregable cerrado.

Nota sobre v3.11 vs v3.12: probé primero v3.11 y el binario producido daba
"memory exhausted" en cualquier regex (bug conocido de grep+musl static al
inicializar DFA). v3.12 corrige y funciona limpio dentro del rootfs Alpine.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Sergio
2026-06-09 14:11:46 +00:00
co-authored by Claude Opus 4.7
parent e53877a532
commit 1fc8c97617
10 changed files with 386 additions and 38 deletions
+17 -13
View File
@@ -17,21 +17,25 @@ Ver [ADR 0002](adr/0002-alpine-first.md).
## Fases (sobre Alpine)
### Fase 0 — Laboratorio de build ▶ *empezamos aquí*
- [ ] `hammer-core`: tipos `Recipe`, `ArtifactHash`, `Store` (BLAKE3, layout `/store`).
- [ ] `hammer-build`: sandbox con `bubblewrap` + `zig cc` → binario musl estático.
- [ ] CAS: hashing de entrada, caché por hash, sellado en el store.
- [ ] `hammer build <recipe.toml>` → imprime el hash del artefacto.
- **Hecho cuando:** una receta compila reproduciblemente y queda en el store.
### Fase 0 — Laboratorio de build
- [x] `hammer-core`: tipos `Recipe`, `ArtifactHash`, `Store` (BLAKE3, layout `/store`).
- [x] `hammer-build`: sandbox con `bubblewrap` + `zig cc` → binario musl estático.
- [x] CAS: hashing de entrada, caché por hash, sellado en el store.
- [x] `hammer build <recipe.toml>` → imprime el hash del artefacto.
- [x] Fuente git **y** tarball (sha256 fijado), patches opcionales.
- [x] Heurística de build system: autotools / cmake / meson / make plano.
- [x] Caché persistente de zig entre builds (~30s/build ahorrados).
### Fase 1 — Hidratación
- [ ] `hydrate(hash, target, mode)`: hardlink a FHS, `patchelf` para el caso dinámico.
- [ ] `hammer hydrate <hash> --into /`.
- **Hecho cuando:** un artefacto del store aparece como `/bin/<x>` real y ejecutable.
### Fase 1 — Hidratación
- [x] `hydrate(hash, target, mode)`: hardlink a FHS, `patchelf` para el caso dinámico.
- [x] `hammer hydrate <hash> --into /`.
### 🎯 Primer entregable (Fase 0 + 1)
**Compilar `grep` estático desde su repo con un patch, hidratarlo a `/bin/grep`, y que corra**,
todo dentro de una VM/LXC Alpine. Esto prueba el corazón "fábrica funcional → FHS mutable".
### 🎯 Primer entregable (Fase 0 + 1)
**GNU grep 3.12 compilado estático desde el tarball upstream, sellado en el store
(`b3:b81e893e…`), hidratado por hardlink a `/usr/bin/grep` y ejecutado dentro del rootfs
Alpine vía `bwrap`** — confirma el corazón "fábrica funcional → FHS mutable" sobre el
substrato Alpine. La VM/LXC dedicada queda como ejercicio de empaque, no como
pre-requisito de validación.
### Fase 2 — Overlay de experimentación
- [ ] `try` / `commit` / `discard` / `status` sobre `overlayfs`.