Los encontró la corrida en el worker, y los tres estaban disfrazados de resultado.
1. El `exit 77` se insertaba antes de la ÚLTIMA `'''` del fichero, que no siempre cierra una fase:
una receta puede traer bloques `'''` después (un `[[service]]`, una nota larga). En `dwarves`,
`elfutils` y `elfutils-libdw` cayó fuera de toda fase, el build corrió entero y SELLÓ — con el
hash movido por el `set -e`, o sea tres artefactos basura. Ahora se rastrea la anidación.
2. El veredicto se leía con `grep "exit 77"` sobre el log, y takana IMPRIME el script de la fase:
esa cadena aparece siempre porque la inyectamos nosotros. Daba SOBREVIVE hasta a un build que
selló. Ahora se ata a `build phase falló (exit 77)`, que es el estado de salida de verdad.
(Comprobado a posteriori que los 14 SOBREVIVE de la corrida buena sí habían salido 77.)
3. Sin `--store`, takana usa su default `/store`, que en el worker es un store de SCRATCH casi
vacío — reconstruía el mundo en vez de reusar el de la granja (`./store`, 908 artefactos). Ahora
el store va por `STORE`.
Y un guardián para lo que no debería volver a pasar: si un build SELLA, se clasifica
`SELLO-INDEBIDO` y se grita el hash, en vez de contarse como un resultado más. Los tres artefactos
basura ya se borraron del `/store` de scratch del worker; el store de la granja nunca se tocó.
La siembra de código hub→worker de `cosecha-cron` corre con `--delete` cada 30 minutos. Las copias
del experimento viven en `recipes/` por obligación (takana resuelve las deps relativas al directorio
de la receta), así que una tanda larga en el worker las vería desaparecer a mitad. Con `REC` se
apunta a una copia entera de `recipes/` fuera del árbol sembrado y el problema no existe.
Tres cosas mías que sólo se vieron al correrlo allá. El lock estaba cableado a `/work/.farm-build.lock`,
que es la ruta de la CAJA (donde `work` es symlink a /work); en el worker `work` es un directorio de
verdad y flock moría con `cannot open lock file`. `takana` no está en el PATH del worker, que lo
invoca por `./target/release/takana`. Y el techo de 420 s alcanza para las ligeras pero no para llvm,
firefox ni los kernels, así que ahora es `TLIMITE`.
Todas por entorno y con el valor de antes por defecto, así que la corrida de la caja no cambia.
El diseño es la parte que vale: NO SELLA NADA. Modificar una receta le cambia el ArtifactHash, así
que medirlo a lo bruto habría dejado una docena de duplicados basura en un store que se respalda. En
vez de eso se inyecta `set -e` en cada fase Y un `exit 77` al final de la última: el build siempre
falla, nunca sella, y el veredicto se lee en el código de salida — 77 significa que todas las fases
corrieron enteras bajo set -e. Queda en scripts/farm/exp-ec.sh.
Muestra de 12 recetas ligeras (los pesos pesados quedan fuera por tiempo, y el sesgo va declarado):
10 sobreviven sin tocar nada, 1 se rompe, 1 inconcluso por timeout.
El que se rompe es `e2fsprogs`, y mirarlo de cerca cambia lo que significa: su ./configure aborta con
`external uuid library not found` pese a que la receta pasa --disable-libuuid, y hoy eso se traga
—comprobado: la misma receta sin set -e y con exit 77 LLEGA al 77—. Pero el artefacto que sella está
bien: 149 ficheros con e2fsck, mke2fs, los cuatro fsck.ext* y los mkfs.ext*. O sea que ahí `-ec` no
atrapa un bug: rompe una receta que funciona. Ése es el coste, y es el número que no se podía
adivinar leyendo: ~8%, unas 8 recetas sobre las 96 expuestas.
También se corrige el recuento: 96, no 89. El 89 salía de restar 142−53 dando por hecho que las 53
con `set -e` propio estaban todas dentro de las 142, y no lo estaban.
jaula-preparar suma lo que hizo falta para poder correr todo esto desde adentro: rsync/python3/jq/
cargo enlazados del store, y el cargador de musl, sin el cual python3 y cargo no arrancan en una
imagen glibc.