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.
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.
El destino de la distro vivía en 2 strings de product-userland-from-repo.sh, 1
de mirada-usb.sh y 55 tandas planas. Ahora en docs/state/targets.toml: un perfil
= una imagen enviable, listando sólo las RAÍCES (lo que se pide por nombre); la
clausura la calcula el grafo, no un humano.
4 perfiles: base (26), cli (46, hereda base), escritorio-mirada (14),
escritorio-kde (7 raíces, cola incoming-kde). scripts/targets.py expande hereda
(transitivo, con detección de ciclo) preservando el orden — mirada lo necesita.
Lift-and-shift verificado: las 3 listas expandidas son byte-idénticas a los
strings que reemplazan. Ninguna imagen cambia de contenido.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
product-userland-from-repo.sh ahora hidrata el userland foundational C (bash/git/sudo/util-linux/
shadow/red/disco/TLS/gpg/…) además de la capa CLI Rust, todo desde el repo firmado con
--require-signed (verifica firma → reproduce del .swm → hidrata FHS). BASE_SYSTEM_PKGS + CLI_RUST_PKGS.
Cierra el lazo Etapa F+G: el userland del producto se arma vía `hammer install
--repo --prefix --require-signed` desde el repo firmado, no del bootstrap
hardcodeado. scripts/product-userland-from-repo.sh hidrata un set curado (13+
tools validados estáticos del repo).
Dos bugs reales del path install/pack encontrados+arreglados:
1. pack derivaba target_bin=/usr/bin/{name}; para paquetes con binario≠nombre
(ripgrep→rg, repgrep→rgr) quedaba mal y el sanity-check de install fallaba.
Ahora pack lo deriva del flag `--bin <X>` de la receta Cargo.
2. La reproducción del source_patch derivaba el NOMBRE de la receta del
target_bin ⇒ "rg" ≠ "ripgrep" del corpus ⇒ no cache-hit ⇒ rebuild + dup en
el store (find_by_hash ambiguo). build_source_patch/run_apply ahora reciben
el nombre del paquete (install/bootstrap lo pasan; apply=None) ⇒ cache-hit
del artefacto del corpus, sin duplicar.
(El "EACCES" inicial era sólo --store ausente: DEFAULT_STORE=/store root-only.)
hammer-build 49/49 tests ok; ripgrep install validado e2e (rg hidratado).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>