tawasuyu

sergio/takana

> Una distribución Linux construida con un laboratorio funcional y hermético en el > sótano, y una terminal mutable, clásica y anárquica en el piso de arriba — diseñada > desde el suelo para que una IA programadora entienda, modifique y co…

⎇ 458afec6db2f8af8fdbf3266315dcf999d3c0475 scripts/farm/farm-sync.sh Shell · 73 lines · 3.8 KB History raw

granja: el worker rehacía 87 de 90 recetas por ciclo — el sync del store es de UN SOLO SENTIDO 129aff9dd · sergio ·

1#!/usr/bin/env bash
2# farm-sync.sh <user@host> — orquesta el worker VPS desde el HUB (laptop). Una sola pasada:
3#   1. sube código + recipes/incoming/ al worker (rsync, el worker no toca gitea)
4#   2. baja el store/ sellado que el worker construyó
5#   3. promueve+firma lo cosechado (cache-hit instantáneo en los artefactos bajados) + commit/push
6#
7# El acceso es UNO solo: laptop->VPS por SSH (la clave de firma y gitea nunca salen del laptop).
8# Idempotente y seguro de re-correr. Pensado para correr cada vez que el laptop está online.
9#
10# Uso:    scripts/farm/farm-sync.sh root@1.2.3.4
11#         scripts/farm/farm-sync.sh root@1.2.3.4 --no-promote   # sólo sincroniza, no firma
12# Env:    SSH_KEY (def ~/.ssh/github5), REMOTE (def /opt/hammer)
13set -euo pipefail
14
15VPS="${1:?uso: farm-sync.sh user@host [--no-promote]}"
16SSH_KEY="${SSH_KEY:-$HOME/.ssh/github5}"
17REMOTE="${REMOTE:-/opt/hammer}"
18ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
19cd "$ROOT"
20SSH="ssh -i $SSH_KEY -o StrictHostKeyChecking=accept-new"
21
22# El MANIFIESTO de lo ya sellado en el hub, para que el worker no rehaga trabajo hecho. Es la otra
23# mitad del arreglo del sync unidireccional (ver la nota en `scripts/build-farm.sh`): el store no
24# viaja hub→worker porque son gigabytes, pero la lista de nombres son kilobytes y evita que el worker
25# reintente y falle cada ciclo lo que el hub ya tiene. Se regenera acá, en cada sync, para que no se
26# quede vieja sola.
27mkdir -p work
28ls ./store 2>/dev/null | grep -E '^[0-9a-f]{64}-' > work/farm-sellados.txt || true
29echo "==> 0. manifiesto de sellados del hub: $(wc -l < work/farm-sellados.txt) artefactos"
30
31echo "==> 1. subiendo código + cola al worker ($VPS:$REMOTE)"
32rsync -az --delete -e "$SSH" \
33  --include '/work/' --include '/work/farm-sellados.txt' \
34  --exclude /work --exclude /store --exclude '/store-*' --exclude /target \
35  --exclude /dist --exclude /.dev-fs --exclude /.git --exclude /.scratch \
36  --exclude '*.png' --exclude '/content*' \
37  ./ "$VPS:$REMOTE/"
38
39echo "==> 2. bajando artefactos sellados del worker"
40# ── ⚠ NO BAJAR LO QUE YA PODAMOS: era un BUCLE DE CHURN DE 24 G ────────────────────────────────
41# Medido el 2026-08-07: `store-gc.sh` borró 362 artefactos superados (24 G) por la mañana y por la
42# tarde volvió a borrar **los mismos 362** — solapamiento del 100%. No era casualidad: este rsync
43# bajaba el store del worker ENTERO, y el worker nunca se poda, así que conservaba los superados y
44# nos los devolvía en cada cosecha. Podar → cosechar → vuelven → podar. El disco pagaba 24 G por
45# vuelta y la métrica de espacio libre mentía sobre el progreso.
46#
47# El registro `work/store-gc-superados.txt` es la unión de todos los manifiestos de poda: nombres
48# `<hash>-<paquete>` de artefactos que YA decidimos que sobran. Como el store es CAS —los nombres
49# son inmutables y un artefacto superado no vuelve a ser vigente salvo que una receta retroceda—
50# excluirlos es seguro; y si una receta retrocediera, su artefacto se reconstruye, que es barato.
51LEDGER="work/store-gc-superados.txt"
52if [ -s "$LEDGER" ]; then
53  echo "    (excluyendo $(wc -l < "$LEDGER") artefactos ya podados — ver la nota del bucle de churn)"
54  rsync -az -e "$SSH" --exclude-from="$LEDGER" "$VPS:$REMOTE/store/" ./store/
55else
56  rsync -az -e "$SSH" "$VPS:$REMOTE/store/" ./store/
57fi
58
59if [ "${2:-}" = "--no-promote" ]; then
60  echo "✓ store sincronizado (sin promote)"; exit 0
61fi
62
63echo "==> 3. promote + firma (cache-hit en lo que el worker selló)"
64scripts/build-farm.sh
65
66echo "==> 4. commit + push de la cosecha"
67git add recipes/ tandas/ 2>/dev/null || true
68if ! git diff --cached --quiet; then
69  git commit -q -m "Etapa G: cosecha del worker VPS — promote + firma"
70  git push -q origin main && echo "✓ pusheado"
71else
72  echo "(nada nuevo que commitear)"
73fi