la caja ya es un HUB: el lab viajó pineado, hashea igual, y el latido late desde allá

El §6.42 dijo qué faltaba y el usuario eligió darle el lab a la caja. Hecho.

EL LAB NO SE COPIA, SE PINEA Y SE TRAE. `lab-image.sh` lo empaqueta determinista (--sort=name
--mtime=@1 --owner=0, excluyendo var/log/apk.log), lo publica al Storage Box con el sha en el nombre,
y `--traer` VERIFICA EL SHA ANTES DE EXTRAER. El empaquetado de hoy devolvió exactamente el sha que
el repo ya pineaba (d1e341d5…): o sea que el lab de gioser nunca derivó Y que el empaquetado es
reproducible de verdad, no una promesa del comentario.

LA PRUEBA QUE DECIDE no es que arranque: la caja calcula los MISMOS ArtifactHash que gioser en las
cuatro recetas de control (zlib, busybox, caddy, shuma-daemon). Con otro lab serían otros números y
el store no lo notaría.

⚠ Y UNA TRAMPA QUE ME TENDÍ SOLO: al copiar los 24 artefactos que le faltaban al store de la caja,
`rsync -a --files-from=<lista de DIRECTORIOS>` mandó 2.281 bytes y «total size is 0» — pero creó los
24 DIRECTORIOS VACÍOS. `--files-from` no recursa sin `-r`, y un directorio vacío en el store ES UN
CACHE-HIT (§3 de CLAUDE.md): `build` lo habría dado por sellado sin construir. Detectado contando,
borrados los 24, repetido con `-r`: 3,18 GB y 0 vacíos de 1655.

Stores convergidos (copiados también obs-studio y spectacle, justo los dos que el worker no logra
construir). La caja no empata, gana por uno: corpus 930 selladas / 1 deuda contra 929 / 2; KDE
1106 / 1 contra 1105 / 2.

Latido mudado: cron apagado en gioser, encendido en la caja, y un ciclo corrido a mano mirando lo que
publica — `repo al día (ff)` → `estado commiteado+pusheado` con los números buenos.

⚠ Lo que queda apretado es el disco: /store de la caja al 91%, 8,2 G libres. Un hub sella y cosecha:
ése es el próximo muro, y `store-gc.sh` no se corrió nunca allá.

⇒ PUERTA 4 EN VERDE. De las ocho quedan dos a medias (5 y 7) y ninguna en rojo.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Sergio
2026-09-17 15:14:26 +00:00
co-authored by Claude Opus 5
parent 5b5b1aad1e
commit ba3ed16169
+73
View File
@@ -2543,6 +2543,79 @@ tiene el lab— y vuelve a publicar los números buenos.
No rompe nada, pero un `EPIPE` sin manejar en una herramienta de operación aparece justo cuando
alguien la encadena.
### 6.43 🧪 La caja ya es un HUB: el lab viajó, y con él la puerta 4 *(2026-09-17)*
El §6.42 dejó dicho qué faltaba y el usuario eligió: **darle el lab a la caja**. Hecho, y el latido
ya late desde allá.
#### El lab no se copia: se PINEA y se trae
`scripts/lab-image.sh` empaqueta `.dev-fs/alpine` de forma **determinista** (`--sort=name
--mtime=@1 --owner=0 --group=0 --numeric-owner`, excluyendo `var/log/apk.log`, que es lo único que
difiere entre dos labs por lo demás iguales), lo publica al Storage Box con el sha en el nombre, y
del otro lado `--traer` **verifica el sha antes de extraer**. Eso es lo que hace que las dos máquinas
hasheen igual, y es un contrato, no una copia.
**Y el empaquetado de hoy devolvió el sha que el repo ya pineaba:**
```
empaquetado hoy en gioser : d1e341d5dd434a11e2290b0340069ce4a83563eac8e4481f379b4951b1162045
pineado en bootstrap-devfs.sh: d1e341d5dd434a11e2290b0340069ce4a83563eac8e4481f379b4951b1162045
```
O sea dos cosas de una: **el lab de gioser nunca derivó** desde que se publicó esa imagen, y **el
empaquetado es reproducible de verdad** — no era una promesa del comentario.
#### La prueba que decide, y no es que arranque
Con el lab instalado, la caja calcula los MISMOS `ArtifactHash` que gioser:
```
zlib b3:dc363f26… busybox b3:2a2b1280…
caddy b3:c915987d… shuma-daemon b3:f9b92acc…
```
Cuatro de cuatro. Si el lab fuera otro, estos números serían otros y el store no lo notaría — es el
agujero que `hash_inputs` cerró (§lab en el hash) y la razón por la que esto se verifica con hashes
y no con un «arrancó bien».
#### Los stores, convergidos — y una trampa que me tendí solo
El grafo seguía discrepando porque el store de la caja no tenía 24 artefactos vigentes de gioser
(3,0 G). Al copiarlos con `rsync -a --files-from=<lista de DIRECTORIOS>` pasó lo peor posible:
```
sent 2,281 bytes … total size is 0 ← no copió NADA
artefactos en la caja: 1631 → 1655 ← pero creó los 24 DIRECTORIOS
```
**`--files-from` no recursa sin `-r`**: creó 24 directorios vacíos en el store. Y un directorio vacío
en el store **es un cache-hit** (§3 de CLAUDE.md, [[artefacto-vacio-envenena-cache]]): `build` lo
habría dado por sellado y habría salido OK sin construir. Se detectó al contar, se borraron los 24 y
se repitió con `-r`: 3,18 GB transferidos, **0 vacíos de 1655**.
Después faltaban dos más (`obs-studio` y `spectacle`, justo los que el worker no logra construir),
copiados también. Resultado:
| | gioser | caja |
|---|---|---|
| corpus | sealed 929 · debt 2 | **sealed 930 · debt 1** |
| KDE | sealed 1105 · debt 2 | **sealed 1106 · debt 1** |
La caja no empata: **gana por uno** en los dos grafos.
#### El latido, mudado
Cron apagado en gioser, encendido en la caja, y un ciclo completo corrido a mano para mirar lo que
publica: `==> repo al día (ff)` → `==> estado commiteado+pusheado`, con los números buenos. El
`build-state` que hay en `main` ahora lo escribió la caja.
⚠ **Lo que queda apretado es el disco**: `/store` de la caja está al **91 %, 8,2 G libres**. Un hub
sella y cosecha, así que ése es el próximo muro — `scripts/store-gc.sh` es la herramienta y todavía
no se corrió allá.
⇒ **puerta 4 en verde.** Con eso, de las ocho quedan sólo las dos a medias (5 y 7) y ninguna en rojo.
## 7. Reusar los scripts que ya existen, y no escribir de nuevo
Pedido explícito del usuario. El inventario de lo que ya hace el trabajo: