cierres §1: consenso de reconstrucción — funcionando (2/2 builders, mismo hash)
El top-1 de SDD 17 (mayor ventaja competitiva por esfuerzo). N builders
INDEPENDIENTES reproducen el mismo hash ⇒ el binario es confiable SIN FIRMA.
Convierte la repro de QA en primitiva de distribución: cualquiera puede ser
mirror, nadie puede envenenar el repo.
scripts/consenso.sh recipes/bzip2.toml 2
builder 1: hub local (Artix) → b3:86a33b76…
builder 2: worker efímero (Ubuntu) → b3:86a33b76…
✅ CONSENSO (2/2, bit a bit)
Dos máquinas físicas, dos distros, mismo hash byte a byte. Nix/Debian no pueden
ofrecerlo (repro incompleta). Cae SOLO del invariante que hammer ya paga — que es
la tesis del SDD 17: buscar qué cae del invariante, no qué frontera agregar.
Lo originó una observación accidental: al hacer el rollout de cmake noté que el
laptop y el worker daban el MISMO hash sin que nadie lo buscara. Eso ya era
consenso ocurriendo; esto sólo lo formaliza.
Divergencia ⇒ exit 1 y apunta a why-differs (§2): una divergencia YA es
información (un canal impuro encontrado). NO firma ni publica: sólo el veredicto.
El log de transparencia (fork-proof: hash-encadenado + detección de equivocation)
ya está escrito en tawasuyu — no hay que construir un rekor.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Semantic delta
No definition changed: this change is text, documentation or data.
1 files · +85 −0
- scripts/consenso.sh +85 −0
diff --git a/scripts/consenso.sh b/scripts/consenso.sh
new file mode 100755
index 00000000..556e83b6
--- /dev/null
+++ b/scripts/consenso.sh
@@ -0,0 +1,85 @@
+#!/bin/sh
+# consenso.sh <receta> [N] — CONSENSO DE RECONSTRUCCIÓN (SDD 17 §1).
+#
+# N builders INDEPENDIENTES reproducen el mismo hash ⇒ el binario es confiable **sin que nadie
+# firme nada**. Convierte la reproducibilidad de QA en primitiva de distribución: cualquiera
+# puede ser mirror, nadie puede envenenar el repo.
+#
+# scripts/consenso.sh recipes/bzip2.toml 2
+#
+# Builders: este hub (laptop) + N-1 workers efímeros de la granja, cada uno una máquina física
+# distinta con su propio OS. Si coinciden ⇒ CONSENSO. Si divergen ⇒ candidato a `why-differs`
+# (SDD 17 §2) — y eso también es información: una divergencia es un canal impuro encontrado.
+#
+# Por qué esto no lo puede ofrecer nix/debian: su repro es incompleta. hammer ya paga el
+# invariante (bit-repro verificada: selfhost, kernel), así que esto cae casi solo del invariante
+# — que es la tesis del SDD 17: buscar "qué cae del invariante", no "qué frontera agregar".
+#
+# NO firma ni publica: sólo produce el veredicto de consenso. El log de transparencia
+# (`fork-proof`, hash-encadenado + detección de equivocation) es el paso siguiente y YA está
+# escrito en tawasuyu — no hay que construir un rekor.
+set -eu
+
+RECETA="${1:?uso: consenso.sh <receta.toml> [N-builders]}"
+N="${2:-2}"
+HUB="$(cd "$(dirname "$0")/.." && pwd)"
+cd "$HUB"
+IMAGE="${IMAGE:-408909310}"
+TYPE="${TYPE:-ccx23}"
+LOCATION="${LOCATION:-hel1}"
+SSHKEY="${SSHKEY:-desarrollo@jlsoltech.com}"
+SSH_KEY="${SSH_KEY:-$HOME/.ssh/github5}"
+SSH="ssh -i $SSH_KEY -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o BatchMode=yes"
+n=$(basename "$RECETA" .toml)
+OUT="work/consenso"; mkdir -p "$OUT"
+
+echo "══ CONSENSO DE RECONSTRUCCIÓN — $n, $N builders independientes"
+
+# Builder 1: el hub. Es un builder legítimo (otra máquina, otro OS que los workers).
+echo "── builder 1: hub local ($(uname -s), $(grep -m1 '^NAME=' /etc/os-release 2>/dev/null | cut -d'"' -f2 || echo '?'))"
+h1=$(timeout "${POR:-900}" ./target/debug/hammer build "$RECETA" --store "$PWD/store" 2>/dev/null \
+ | grep -oE '^b3:[a-f0-9]{64}' | head -1)
+echo " → ${h1:-FALLÓ}"
+[ -z "$h1" ] && { echo " el hub no puede construir $n ⇒ sin consenso posible desde acá"; exit 3; }
+echo "$h1 hub" > "$OUT/$n.hashes"
+
+# Builders 2..N: workers efímeros, cada uno una máquina física distinta.
+i=2
+while [ "$i" -le "$N" ]; do
+ name="hkc-$i"
+ echo "── builder $i: worker efímero $name"
+ hcloud server create --name "$name" --image "$IMAGE" --type "$TYPE" --location "$LOCATION" \
+ --ssh-key "$SSHKEY" >/dev/null 2>&1
+ ip=$(hcloud server ip "$name")
+ for _ in $(seq 1 30); do $SSH "root@$ip" true 2>/dev/null && break; sleep 6; done
+ rsync -az -e "$SSH" --exclude /work --exclude /store --exclude '/store-*' --exclude /target \
+ --exclude /dist --exclude /tandas --exclude /.dev-fs --exclude /.git --exclude /.scratch \
+ --exclude '*.png' --exclude '/content*' ./ "root@$ip:/opt/hammer/" >/dev/null 2>&1
+ hN=$($SSH "root@$ip" "export PATH=\$HOME/.cargo/bin:\$PATH; cd /opt/hammer && \
+ cargo build --release -q -p hammer-cli 2>/dev/null; \
+ timeout ${POR:-900} ./target/release/hammer build $RECETA --store \$PWD/store 2>/dev/null \
+ | grep -oE '^b3:[a-f0-9]{64}' | head -1" 2>/dev/null | tr -d '\r')
+ echo " → ${hN:-FALLÓ}"
+ [ -n "$hN" ] && echo "$hN $name" >> "$OUT/$n.hashes"
+ hcloud server delete "$name" >/dev/null 2>&1
+ i=$((i + 1))
+done
+
+echo
+echo "══ VEREDICTO"
+cat "$OUT/$n.hashes" | sed 's/^/ /'
+distintos=$(awk '{print $1}' "$OUT/$n.hashes" | sort -u | wc -l)
+cuantos=$(wc -l < "$OUT/$n.hashes")
+if [ "$cuantos" -lt 2 ]; then
+ echo " SIN CONSENSO: sólo $cuantos builder(s) produjeron hash. No se afirma nada."
+ exit 3
+elif [ "$distintos" = 1 ]; then
+ echo " ✅ CONSENSO ($cuantos/$cuantos builders, mismo hash bit a bit)"
+ echo " ⇒ el artefacto es confiable SIN FIRMA: N máquinas independientes lo reprodujeron."
+ exit 0
+else
+ echo " ⚠️ DIVERGENCIA: $distintos hashes distintos entre $cuantos builders."
+ echo " ⇒ hay un canal impuro. Es trabajo para \`why-differs\` (SDD 17 §2) — y la"
+ echo " divergencia YA es información: el invariante bit-repro se rompió acá."
+ exit 1
+fi