worker-loop: recompilar hammer POR CICLO, no sólo al arrancar
El bloque de rebuild que ya existía corre una sola vez, al arrancar el loop, y este loop vive días — hoy el worker llevaba 8 de uptime. El source SÍ sigue llegando fresco cada 30 min (la siembra rsync-ea el repo), así que el worker acaba con FUENTE NUEVO y BINARIO VIEJO. Eso es peor que el fósil de la golden que motivó el bloque original, porque nada lo delata: la versión de hammer NO entra en el ArtifactHash, así que el build se comporta distinto y build-state.json sigue en verde. Misma familia que el lab fuera de hash_inputs, sin siquiera el aviso del lock. Caso real que lo motiva, de hoy: el worker corría un hammer de las 04:54 y el arreglo que materializa los submódulos git había entrado a las 15:11 (114aeba). `waterfox` moría en CUATRO SEGUNDOS por waterfox/browser/locales/moz.build inexistente, y el diagnóstico apuntaba a la receta, a los once parches de musl y al --filter=blob:none: a todo menos al binario. Lo resolvió `strings` sobre los dos binarios en un minuto — hub 2 cadenas de .gitmodules/gitlink, worker 0. Recompilado el worker (23 s) y borrado el árbol de fuentes viejo, waterfox pasa el punto donde moría y el submódulo se materializa. Se comprueba por mtime y no se recompila a ciegas: cargo cacheado son ~24 s, pero correrlo cada IDLE_SLEEP sin motivo es ruido en el log y CPU que le estamos quitando a un build. Si nada cambió cuesta un `find`. Probado en los dos sentidos (fuente más nuevo -> detecta; binario más nuevo -> no hace nada).
Delta semántico
Ninguna definición cambió: el cambio es de texto, documentación o datos.
1 archivos · +28 −0
diff --git a/scripts/farm/farm-worker-loop.sh b/scripts/farm/farm-worker-loop.sh
index 903dfb85..60d5d200 100755
--- a/scripts/farm/farm-worker-loop.sh
+++ b/scripts/farm/farm-worker-loop.sh
@@ -154,8 +154,36 @@ if command -v cargo >/dev/null 2>&1; then
cargo build --release --bin hammer -j"$JOBS" 2>&1 | tail -2 || echo " ⚠ rebuild falló — uso el binario existente"
fi
+# EL MISMO REBUILD, PERO POR CICLO Y NO SÓLO AL ARRANCAR (2026-09-06). El bloque de arriba corre
+# UNA vez, y este loop vive días: `uptime` de 8 días con el binario congelado en el arranque. El
+# source SÍ sigue llegando fresco cada 30 min (la siembra rsync-ea el repo), así que el worker
+# termina con FUENTE NUEVO y BINARIO VIEJO — que es peor que el fósil de la golden, porque nada lo
+# delata: el ArtifactHash NO se mueve por la versión de hammer, así que el build se comporta
+# distinto y `build-state.json` sigue en verde.
+#
+# Caso real que lo motiva: el 2026-09-06 el worker corría un hammer de las 04:54 y el arreglo que
+# materializa los submódulos git había entrado a las 15:11 (`114aeba`). `waterfox` moría en 4 s por
+# `waterfox/browser/locales/moz.build` inexistente y el diagnóstico apuntaba a la receta, a los
+# parches y al `--filter=blob:none` — a todo menos al binario. `strings` sobre los dos binarios lo
+# resolvió en un minuto: hub 2 cadenas de `.gitmodules`, worker 0.
+#
+# Se comprueba por MTIME y no se recompila a ciegas: `cargo` cacheado son ~24 s, pero correrlo cada
+# IDLE_SLEEP sin motivo es ruido en el log y CPU que le estamos quitando a un build. Si nada cambió,
+# esto cuesta un `find`.
+rebuild_si_hace_falta() {
+ command -v cargo >/dev/null 2>&1 || return 0
+ bin=target/release/hammer
+ [ -x "$bin" ] || { echo "$(date -u +%FT%TZ) no hay binario: compilando"; cargo build --release --bin hammer -j"$JOBS" 2>&1 | tail -2; return 0; }
+ # ¿Algún fuente más nuevo que el binario? (Cargo.lock incluido: un bump de dep también cuenta.)
+ if [ -n "$(find crates Cargo.toml Cargo.lock -newer "$bin" -type f -print -quit 2>/dev/null)" ]; then
+ echo "$(date -u +%FT%TZ) el source es más nuevo que el binario ⇒ recompilo hammer"
+ cargo build --release --bin hammer -j"$JOBS" 2>&1 | tail -2 || echo " ⚠ rebuild falló — sigo con el binario existente"
+ fi
+}
+
echo "$(date -u +%FT%TZ) worker-loop arrancado: JOBS=$JOBS IDLE_SLEEP=$IDLE_SLEEP QUEUES='$QUEUES'"
while :; do
+ rebuild_si_hace_falta
total=0
for Q in $QUEUES; do
n=$(ls "$Q"/*.toml 2>/dev/null | wc -l)