From 54b2cd69cec65903d8a481c7d772242963af7235 Mon Sep 17 00:00:00 2001 From: sergio Date: Fri, 17 Jul 2026 11:18:54 -0400 Subject: [PATCH] =?UTF-8?q?granja:=20saldar-deuda-static.sh=20=E2=80=94=20?= =?UTF-8?q?reconstruye=20la=20deuda=20que=20destap=C3=B3=20hammer=20hash?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit El nuevo 'sin artefacto' del static-audit (deuda de rebuild ya no enmascarada) son 92 recetas link=static cuyo hash VIGENTE no está sellado: el trabajo reciente (matar-gcc, static, harkaq) cambió recetas base sin re-sellar, y cada cambio re-hashea en cascada todo lo que las declara. Este script las salda. Calcula la deuda EN VIVO con 'hammer hash --check' (nunca una lista que envejece), y construye cada receta NO-SELLADA. NO necesita orden topológico: 'hammer build' arrastra sus deps recursivamente (construir curl construye openssl+perl primero); las cache-hit son instant. Pensado para el WORKER (store completo, toolchain que no rompe el stack GUI): SKIP_GUI=1 por default salta cairo/pango/gtk… que fallan en el laptop por zig-skew. Reparto medido: 76 C-base + 16 GUI. Verificado end-to-end SIN quemar el laptop: modo DRY lista la deuda; y construí UNA receta diminuta (which: NO-SELLADO → build 58s → SELLADO, hash vigente idéntico, estática de verdad en el audit). El ciclo build+re-check del script es correcto. which quedó saldada de paso (deuda 76→75). Confirma la decisión de usar la granja: 58s × 76 con openssl/gnupg/perl pesadas = 2-4h de laptop. Cuando levantes la granja: farm-up, correr esto en el worker (SKIP_GUI=0 para incluir el GUI), farm-down. Co-Authored-By: Claude Opus 4.8 --- scripts/farm/saldar-deuda-static.sh | 73 +++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100755 scripts/farm/saldar-deuda-static.sh diff --git a/scripts/farm/saldar-deuda-static.sh b/scripts/farm/saldar-deuda-static.sh new file mode 100755 index 00000000..bf37581c --- /dev/null +++ b/scripts/farm/saldar-deuda-static.sh @@ -0,0 +1,73 @@ +#!/bin/sh +# saldar-deuda-static.sh — reconstruye las recetas `link = "static"` cuyo hash VIGENTE no está +# sellado en el store (la "deuda de rebuild" que destapó `hammer hash`, 2026-07-17). +# +# POR QUÉ EXISTE. El trabajo reciente (matar-gcc migró 27 recetas C a zig, el frente static, harkaq +# declarando deps) cambió muchas recetas base sin re-sellarlas. Cada cambio re-hashea la receta Y +# todo lo que la declara como dep ⇒ una cascada de recetas cuyo artefacto sellado ya no corresponde +# a la receta de hoy. `scripts/static-audit.sh` las cuenta como "sin artefacto" (deuda real, ya no +# enmascarada). Este script las salda. +# +# NO HACE FALTA ORDEN TOPOLÓGICO: `hammer build` arrastra sus deps de build recursivamente +# (resolve_build_dep_hashes), así que construir `curl` construye `openssl` y `perl` primero. Se +# puede correr en cualquier orden; las cache-hit son instantáneas. +# +# DÓNDE CORRERLO. Pensado para el WORKER de la granja (store completo, toolchain que no rompe el +# stack GUI — ver etapa-g-gui-chain-boundary): `farm-up`, copiar este script y el repo, correrlo, +# `farm-down`. Corre igual en el laptop, pero el stack GUI (cairo/pango/gtk…) fallará por zig-skew: +# usá `SKIP_GUI=1` para saltarlo (default en laptop). +# +# LA DEUDA SE CALCULA EN VIVO, no de una lista que envejece: `hammer hash --check` por receta. Eso +# es exactamente lo que el audit usa para no auditar sellados rancios. +# +# Uso: scripts/farm/saldar-deuda-static.sh # construye toda la deuda +# DRY=1 scripts/farm/saldar-deuda-static.sh # sólo LISTA la deuda, no construye +# SKIP_GUI=1 scripts/farm/saldar-deuda-static.sh # salta el stack GUI (default si no hay DISPLAY-cap) +# Env: HAMMER (def target/release/hammer), STORE (def ./store), JOBS no aplica (serie, por deps). +set -u + +ROOT="$(cd "$(dirname "$0")/../.." && pwd)"; cd "$ROOT" +HAMMER="${HAMMER:-$ROOT/target/release/hammer}" +STORE="${STORE:-$ROOT/store}" +DRY="${DRY:-0}" +# El stack GUI no construye en el laptop (zig-skew rompe cairo). Default: saltarlo salvo que se pida. +SKIP_GUI="${SKIP_GUI:-1}" +GUI_RE='^(cairo|pango|gtk|harfbuzz|glib|gdk-pixbuf|libadwaita|gtksourceview|fribidi|graphene|fontconfig|adwaita|fcft|.*-hello|mirada|appstream|gnome)' + +[ -x "$HAMMER" ] || { echo "no encuentro hammer en $HAMMER (cargo build --release -p hammer-cli)"; exit 1; } + +deuda=""; skipped_gui="" +for f in $(grep -lE '^[[:space:]]*link[[:space:]]*=[[:space:]]*"static"' recipes/*.toml); do + n=$(basename "$f" .toml) + # ¿el sellado VIGENTE (el que corresponde a la receta de HOY) está en el store? cache-hit ⇒ al día. + if "$HAMMER" --store "$STORE" hash --check "$f" >/dev/null 2>&1; then continue; fi + if [ "$SKIP_GUI" = "1" ] && echo "$n" | grep -qE "$GUI_RE"; then + skipped_gui="$skipped_gui $n"; continue + fi + deuda="$deuda $n" +done + +n_deuda=$(echo "$deuda" | wc -w); n_gui=$(echo "$skipped_gui" | wc -w) +echo "== deuda static: $n_deuda recetas a reconstruir; $n_gui de stack GUI saltadas (SKIP_GUI=$SKIP_GUI)" +[ -n "$skipped_gui" ] && echo " GUI (correr en el worker):$skipped_gui" +[ "$DRY" = "1" ] && { echo "== DRY: no construyo. Deuda:$deuda"; exit 0; } +[ -z "$deuda" ] && { echo "== nada que saldar (o todo es GUI y se saltó)"; exit 0; } + +ok=""; fail="" +for n in $deuda; do + printf ' → %-20s ' "$n" + if "$HAMMER" --store "$STORE" build "recipes/$n.toml" >/dev/null 2>&1; then + # verificar que el sellado vigente quedó (build pudo salir 0 y no sellar el hash esperado) + if "$HAMMER" --store "$STORE" hash --check "recipes/$n.toml" >/dev/null 2>&1; then + echo "✓ sellado"; ok="$ok $n" + else + echo "✗ construyó pero el hash vigente no quedó sellado"; fail="$fail $n(hash)" + fi + else + echo "✗ build falló"; fail="$fail $n(build)" + fi +done + +echo "== saldados:$ok" +echo "== fallaron:$fail" +[ -z "$fail" ]