250 líneas de comentario en 151 scripts. Control verificado: el diff no toca
NI UNA línea que no empiece por #, y la sintaxis de los 151 pasa.
El barrido saltea heredocs y cadenas triples, y el guardián DISPARÓ 3 veces:
las tres eran el MOTD que el script escribe DENTRO de la imagen construida —
texto del producto, no comentario del script. Se cambiaron aparte y a
propósito, que es rebranding, no limpieza.
Y el hallazgo caro: casaba contra ,
que es el TARGET de tracing — o sea el module_path!, o sea el nombre del crate.
La etapa 4 lo movió a y el script quedó casando NADA. No fallaba:
imprimía cero atribuciones, indistinguible de un log sin problemas. Comprobado
con el binario (RUST_LOG=info sobre zlib), no deducido. Ahora acepta las dos, y
tiene que seguir aceptándolas porque los logs viejos en disco dicen la vieja.
Además 14 rutas de módulo en docs, que el barrido anterior no tocó
porque no es frontera de palabra.
hammer-{core,build,bootstrap,overlay,journal,mirror,upgrade,agent,recover,cli}
→ takana-*, con sus deps de workspace, sus identificadores en el fuente y las
referencias -p de los scripts.
VERIFICADO que no mueve nada del corpus: `takana hash recipes/zlib.toml`
devuelve b3:dc363f26… , idéntico a antes del renombre. Los nombres de crate no
entran en hash_inputs, pero eso se comprueba, no se supone. 600 tests en verde.
DOS BINARIOS SE CONGELAN, y no por prolijidad:
- `hammerd` — paquete Y binario. Es componente de Stage 1 de la distro (musl,
busybox, hammerd, arje-zero), lo supervisa arje-zero en el sistema arrancado,
`PRESEED=hammerd` lo nombra en selfhost-verify y sus bytes anclan el baseline
of_tree. El nombre del crate va en los símbolos ⇒ renombrarlo mueve los bytes.
- `hammer-recover` — el PAQUETE se renombra a takana-recover, el BINARIO no.
hammer-live-install.sh lo copia a /usr/sbin/hammer-recover en sistemas ya
instalados y hornea un hook de arranque que lo invoca por ese nombre:
renombrarlo rompe máquinas instaladas, no el repo.
Consecuencia que hay que anotar igual: al renombrar hammer-core, los bytes de
hammerd cambian de todos modos porque linkea contra un crate con otro nombre.
El baseline of_tree del selfhost hay que rehacerlo — es efecto de la etapa 4,
no de un cambio de hammerd.
Las referencias en comentarios de recetas y docs (rutas hammer-core/src/…)
quedan para la etapa 5: son texto, no mueven hash.
Los llamadores EJECUTABLES: scripts/ (incluida toda la granja), los runbooks y
CLAUDE.md. Seguro porque la 3a ya garantiza que el worker emite los dos
binarios, y porque en farm-lab-sync.sh el cargo build remoto precede a la
invocación remota en el mismo script.
Verificado: sintaxis de los 49 (bash -n / py_compile — ojo que
why-differs-barrido.sh es Python con extensión .sh) y `takana hash` devuelve
hash real sobre el store.
NO se toca en esta etapa, a propósito:
- La variable de entorno HAMMER=. Es interfaz de los scripts entre sí y hay
llamadores que la fijan; renombrarla va con la etapa 4.
- docs/evidencia/ y los HANDOFF: son REGISTRO de lo que se corrió ese día.
Reescribir un comando dentro de una evidencia la falsifica.
- docs/state/: es generado, se regenera solo.
- Los ADR y los docs de diseño: texto, y `hammer` sigue funcionando. Van con
la etapa 5, que es la de churn de texto.
Va solo y ANTES de cambiar ninguna invocación, a propósito. El worker compila
desde fuente (farm-worker-loop.sh) y la siembra excluye /target: si primero
cambiara las llamadas a `takana` y después el build, habría una ventana en la
que el worker sincroniza scripts nuevos y sigue teniendo sólo el binario viejo
— y eso no falla ruidosamente, deja de cosechar en silencio.
Con los dos emitidos, cualquier orden de sincronización queda sano.
Sincronizar el codigo nuevo al worker y llamar a cargo NO basta: rsync -a
preserva el mtime del hub, asi que el fuente recien llegado puede quedar mas
VIEJO que el binario que el worker compilo hace un rato. cargo dice
«Finished in 0.09s», el worker se queda con el hammer anterior, calcula la
huella vieja y el paso 4 falla sin que se vea por que.
Paso el 2026-08-12 al empujar el lab con los -dev: el worker tenia el lab.rs
correcto Y el rootfs correcto, y aun asi divergia. Se arregla con un `touch`
a los fuentes antes de compilar.
El guardian del paso 4 hizo su trabajo: detecto la divergencia y NO dejo
construir. Sin el, el worker habria molido horas sellando en direcciones que
el hub nunca iria a buscar.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
farm-sync excluye /.dev-fs a proposito (el lab es del entorno, no del repo).
Eso valia cuando el toolchain no entraba en el hash. Desde 58d3161 si entra,
asi que un worker con el lab horneado de la golden (rustc 1.96) sella en
direcciones DISTINTAS a las del hub (1.97): no es que compile distinto, es
que lo guarda donde el hub nunca lo va a buscar.
Tampoco basta bootstrap-devfs.sh en el worker: su paso 0 solo trae la imagen
si NO hay rootfs, y la golden trae uno. Se reemplaza a la fuerza.
La imagen se EMPUJA por scp desde el hub en vez de bajarla del Storage Box,
para no poner la llave del box en el worker: el modelo hub-and-spoke dice que
el worker es compute puro sin secretos.
El paso 4 no es 'extraje la imagen', es comparar el hammer hash de una receta
testigo entre worker y hub. Si divergen FALLA: un worker que sella en otra
direccion quema dinero produciendo artefactos que nadie encuentra.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>