Files
takana/scripts/test-atuq-suite.sh
T
Sergio 2098e86ba4 atuq: la boveda ANDA — 19 guardianes en verde, y el bloqueo de tres semanas era un fichero sin empujar
El pin de `puriy-costura` subio a `23a292863` y con eso se apagaron los dos rojos del cable. La suite
entera sobre `b3:e556024b`: **19 verdes, 0 rojos, 32,1 min**. No se toco ningun guardian — que la
suite existiera ANTES del arreglo es lo que permite afirmarlo: el cuadro de ayer y el de hoy son el
mismo instrumento.

La medicion que cierra es la que abrio el §7.quinquies, leida al reves: `strings` sobre el binario
sellado da `vault` **10** veces donde daba 0, con `cas`/`sct` de control; y `vigia-atuq-verbos` pasa
de 3 verbos sin dueno a cero, con su control positivo intacto.

Lo destrabo publicar el `Cargo.lock` de tawasuyu (`23a292863` alla), regenerado en un arbol limpio:
215 lineas, todas de contabilidad de deps por ruta, cero `checksum` y cero `source` movidos. Y el
remate, que es la leccion: **ese lock era byte a byte el que la otra sesion ya tenia en su arbol sin
commitear**. Tres semanas de bloqueo y el fichero correcto estaba escrito, sin empujar, a un
directorio de distancia. Antes de decir «bloqueado por otro repo», mirar si lo que falta no esta ya
hecho y sin publicar.

Commiteado alla con indice temporal (`GIT_INDEX_FILE` + `commit-tree`), que es la unica forma de
publicar una ruta en `MM` sin llevarse por delante lo del otro agente: su arbol quedo byte a byte
igual, comprobado con `cmp` antes y despues.

⚠ Y la cabecera del runner se desmintio SOLA dos veces: anuncio «un rojo» cuando eran dos, y «dos»
cuando ya no quedaba ninguno. Un numero escrito como prediccion envejece callado. Con todo en verde
el numero ya no distingue un producto sano de un runner que no corre nada, asi que lo que sostiene la
corrida queda escrito: la puerta del sello (verificada contra un store vacio) y el control interno de
cada guardian.
2026-09-16 15:55:30 +00:00

154 lines
9.8 KiB
Bash
Executable File

#!/usr/bin/env bash
# test-atuq-suite.sh — corre TODOS los guardianes de `atuq`, en orden de coste, y da un cuadro.
#
# ══ POR QUÉ EXISTE ════════════════════════════════════════════════════════════════════════════
# Los guardianes de atuq son diecinueve y ninguno corre solo. Ya pasó lo que tenía que pasar: el de
# descargas estuvo ROJO dos días y nadie lo corrió (commit `29831e62`), y el 2026-09-15 el artefacto
# vigente estuvo SIN SELLAR desde el commit de la bóveda hasta que alguien miró — durante esas horas
# ningún guardián podía medir nada y el repo se veía igual de sano. Un guardián que nadie corre es
# documentación, no una medición.
#
# ══ LO PRIMERO QUE MIRA ES EL SELLO, Y NO ES UN DETALLE ═══════════════════════════════════════
# Todo `recipes/atuq/` es `source.dir` ⇒ tocar una extensión, `atuq.cfg`, la política o el README
# cambia el ArtifactHash, y los guardianes se NIEGAN a medir un artefacto que no sea el vigente. El
# ciclo es **editar todo → resellar UNA vez → medir**; al revés se pagan 340 M de store por edición.
# Si falta el sello, esto NO corre nada: dice cómo construirlo y sale.
#
# ══ EL CONTROL DE ESTA CORRIDA ════════════════════════════════════════════════════════════════
# Hoy (2026-09-16) el resultado CORRECTO es **19 en verde**. Lo fue «17 y dos rojos» hasta esta
# tarde: los dos eran los verbos de la bóveda, y se apagaron al subir el pin de `puriy-costura`
# (SDD 26 §7.quinquies.bis). Si mañana hay un rojo, cambió algo que hay que ir a ver.
#
# ⚠ **Un cuadro entero en verde puede ser un producto sano o un runner que no corre nada, y se ven
# igual.** Mientras hubo un rojo conocido, el número lo distinguía solo. Ahora no, así que lo que
# sostiene la corrida son otras dos cosas, las dos comprobadas:
#
# · **la puerta del sello** — contra un store sin el artefacto, esto NO corre nada y devuelve 1
# (verificado a propósito con un store vacío);
# · **el control de cada guardián** — todos traen el suyo (una rotura que TIENE que matarlos, o un
# positivo que TIENE que aparecer). El runner no los reemplaza: los junta.
#
# ⚠ Y la advertencia que este fichero se aplicó a sí mismo dos veces: la cabecera anunció «un rojo»
# y eran dos, y después «dos» cuando ya no quedaba ninguno. **Un número escrito como predicción
# envejece callado.** Si el cuadro no coincide con esto, el sospechoso es esta cabecera.
#
# ══ LO QUE CUESTA ═════════════════════════════════════════════════════════════════════════════
# **~32 min** en gioser, en serie (32,1 min medidos el 2026-09-16, sobre 19 guardianes). Los cuatro primeros salen en 10 s y no tocan
# el navegador: para «¿rompí algo del cruce política↔XPI?» alcanza con `--only` y no hace falta la
# media hora. Los caros son `sct` (241 s, seis cargas), `archivo-semantico` (227 s, embeddings),
# `instalacion` (180 s, tres sesiones) y `ia` (180 s, levanta `llama-server`).
#
# ══ QUÉ NO ESTÁ ACÁ ═══════════════════════════════════════════════════════════════════════════
# Nada, hoy. El de notificaciones (`scripts/wlr/dunst-headless.sh --via-atuq`) vive en el arnés de
# sway y por eso se había quedado afuera; entra igual, porque una lista con un hueco nombrado en la
# cabecera se lee como cobertura al tercer día. Si mañana alguien saca uno, que lo nombre acá.
#
# NO CONSTRUYE NADA y NO TOMA EL LOCK de la granja: sólo lee artefactos ya sellados, así que se puede
# correr con la granja a pleno. Va en SERIE a propósito — cada guardián levanta un navegador y esta
# máquina tiene cuatro núcleos sin swap; dos a la vez es un OOM. Y cada uno escribe en SU fichero:
# dos corridas sobre el mismo log se MEZCLAN y el resultado parece un pase.
#
# scripts/test-atuq-suite.sh # los diecinueve, en orden de coste
# scripts/test-atuq-suite.sh --list # qué afirma cada uno, sin correr nada
# scripts/test-atuq-suite.sh --only sct # sólo los que contengan «sct» en el nombre
# scripts/test-atuq-suite.sh --store DIR --logs DIR
set -u
STORE="./store"
LOGS="work/atuq-suite"
SOLO=""
LISTAR=0
while [ $# -gt 0 ]; do
case "$1" in
--store) STORE="$2"; shift 2 ;;
--logs) LOGS="$2"; shift 2 ;;
--only) SOLO="$2"; shift 2 ;;
--list) LISTAR=1; shift ;;
-h|--help) sed -n '2,40p' "$0"; exit 0 ;;
*) printf 'no entiendo «%s» — ver --help\n' "$1" >&2; exit 2 ;;
esac
done
# etiqueta|comando|qué AFIRMA. El orden es de barato a caro: lo que se rompe gratis
# se descubre en el primer minuto y no después de media hora de navegadores.
GUARDIANES=(
"vigia-atuq-verbos|python3 scripts/vigia-atuq-verbos.py|el host PINEADO atiende los verbos que mandan las diez extensiones (§7)"
"test-atuq-boveda-coherente|python3 scripts/test-atuq-boveda-coherente.py|la bóveda está enchufada en los CINCO lugares (SDD-BOVEDA §8)"
"test-atuq-politica|python3 scripts/test-atuq-politica.py|el cruce XPI empaquetado ↔ política, con cinco roturas a propósito"
"test-atuq-rootfs|python3 scripts/test-atuq-rootfs.py|el rootfs resuelve todos los NEEDED y nada se cae al LAB"
"test-atuq-inicio|python3 scripts/test-atuq-inicio.py|la página de inicio y la pestaña nueva son las NUESTRAS (§4.e)"
"test-atuq-chrome|python3 scripts/test-atuq-chrome.py|el JS de atuq.cfg llega al gBrowser, y la vista dividida (§4.g)"
"test-atuq-nativo|python3 scripts/test-atuq-nativo.py|una extensión habla con un proceso NATIVO y le vuelve la respuesta (§7)"
"test-atuq-foco|python3 scripts/test-atuq-foco.py|el navegador MUESTRA el foco del sistema y no lo apaga (§6.5)"
"test-atuq-instalacion|python3 scripts/test-atuq-instalacion.py|quién instala de verdad las extensiones: el ESCANEO, no la política"
"test-atuq-ruteo|python3 scripts/test-atuq-ruteo.py|el contenedor sale por SU proxy — saludo SOCKS5 (§6.8)"
"test-atuq-archivo|python3 scripts/test-atuq-archivo.py|congelar lo leído al CAS y buscarlo; nunca lo privado (§6.3)"
"test-atuq-descargas|python3 scripts/test-atuq-descargas.py|la descarga entra al CAS con su BLAKE3 y el fichero no se toca (§6.2)"
"test-atuq-medios|python3 scripts/test-atuq-medios.py|el medio lo abre mpv, no una pestaña (§6.6)"
"test-atuq-torrent|python3 scripts/test-atuq-torrent.py|magnet → daemon propio que sobrevive al navegador (§6.9)"
"test-atuq-sct|python3 scripts/test-atuq-sct.py|la cadena de sct entera: seis cargas y un servidor HTTP real (§6.1)"
"test-atuq-codecs|bash scripts/test-atuq-codecs.sh|H.264+AAC · VP9+Opus · AV1 · MP3 · FLAC REPRODUCEN (§4.f)"
"test-atuq-ia|python3 scripts/test-atuq-ia.py|la barra lateral le pregunta a un modelo de ESTA máquina (§6.7)"
"test-atuq-archivo-semantico|python3 scripts/test-atuq-archivo-semantico.py|el archivo contesta por PARECIDO, no por palabra exacta (§6.3)"
"dunst-via-atuq|sh scripts/wlr/dunst-headless.sh --via-atuq|una PÁGINA WEB notifica y la notificación se DIBUJA (§6.10)"
)
if [ "$LISTAR" = 1 ]; then
printf '── los guardianes de atuq, de barato a caro ──\n'
for g in "${GUARDIANES[@]}"; do
IFS='|' read -r etq cmd afirma <<<"$g"
printf ' %-30s %s\n %s\n' "$etq" "$afirma" "$cmd"
done
exit 0
fi
# ── el sello, antes que nada ──────────────────────────────────────────────────────────────────
H=$(./target/release/takana --store "$STORE" hash recipes/atuq.toml --check 2>/dev/null | tail -1)
case "$H" in
*SELLADO*) : ;;
*) printf 'no pude preguntar el hash de atuq (¿sin `target/release/takana`?)\n'; exit 2 ;;
esac
if [ "${H#* }" != "SELLADO" ]; then
printf '✗ el `atuq` VIGENTE no está sellado: %s\n' "${H%% *}"
printf ' Ningún guardián puede medir — se niegan, y con razón. Construilo UNA vez y volvé:\n\n'
printf ' flock -o work/.farm-build.lock ./target/release/takana --store %s build recipes/atuq.toml\n\n' "$STORE"
exit 1
fi
printf '── los guardianes de atuq sobre %s ──\n' "${H%% *}"
mkdir -p "$LOGS"
verdes=0; rojos=0; saltados=0
RESUMEN=()
for g in "${GUARDIANES[@]}"; do
IFS='|' read -r nombre cmd afirma <<<"$g"
case "$nombre" in *"$SOLO"*) : ;; *) continue ;; esac
log="$LOGS/$nombre.txt"
printf ' %-30s ' "$nombre"
t0=$(date +%s)
# Cada guardián a SU fichero: dos corridas sobre el mismo log se MEZCLAN y el resultado parece un
# pase — ya pasó (se leyó «✓ SALIDA=0» de la corrida vieja con las cargas de la nueva).
$cmd >"$log" 2>&1
rc=$?
t=$(( $(date +%s) - t0 ))
# 77 es «no están las condiciones» (falta un rootfs, falta un modelo), no un fallo del producto.
case "$rc" in
0) veredicto="✓ verde "; verdes=$((verdes+1)) ;;
77) veredicto="— saltado"; saltados=$((saltados+1)) ;;
*) veredicto="✗ ROJO "; rojos=$((rojos+1)) ;;
esac
printf '%s %4ds %s\n' "$veredicto" "$t" "$afirma"
RESUMEN+=("$veredicto|$nombre|$t|$log")
done
printf '\n'
if [ "$rojos" -gt 0 ]; then
printf 'los ROJOS, con su salida entera:\n'
for r in "${RESUMEN[@]}"; do
case "$r" in "✗"*) printf ' %s → %s\n' "$(echo "$r" | cut -d'|' -f2)" "$(echo "$r" | cut -d'|' -f4)" ;; esac
done
printf '\n'
fi
printf '%d verde(s) · %d rojo(s) · %d saltado(s) — salidas en %s/\n' "$verdes" "$rojos" "$saltados" "$LOGS"
[ "$rojos" -eq 0 ]