Files
takana/scripts/test-atuq-suite.sh
T
Sergio fb7dba530d atuq: el que estaba «nombrado como hueco» entra a la suite — 17 verdes y 2 rojos en 32 min
La primera version dejaba afuera al guardian de notificaciones (`dunst-headless.sh --via-atuq`) con
la excusa de que vive en el arnes de sway, y lo escribia en la cabecera «para que su ausencia no se
lea como cobertura». Eso dura tres dias: al cuarto la lista ES la cobertura y el parrafo no lo lee
nadie. Corrido aparte: verde en 180 s. Entra.

Es ademas el que mide lo que ningun auditor de ELF puede ver: una pagina llama `new
Notification(...)`, `libxul` hace `dlopen("libnotify.so.4")` —que no es NEEDED de nada—, el bus
activa dunst y dunst DIBUJA. Cinco piezas y la unica forma de saber que estan las cinco es verlo.

Para que entrara, la lista pasa a llevar el COMANDO de cada guardian en vez de su nombre de fichero:
lo que lo tenia afuera era el despacho por extension, no una decision.

Corrida entera de los diecinueve sobre `b3:e556024b`: **17 verdes, 2 rojos, 32,2 min**, que es
exactamente lo que la cabecera predice — y la cabecera es el control, no un adorno.

Los caros: sct 242 s, archivo semantico 238 s, ia 182 s, instalacion 180 s, notificaciones 180 s.
Los cuatro primeros salen en 5 s y no tocan el navegador.
2026-09-16 14:05:51 +00:00

148 lines
9.4 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-15) el resultado CORRECTO es **17 en verde y DOS en rojo**: `vigia-atuq-verbos` y
# `test-atuq-boveda-coherente`, los dos por la MISMA causa —la receta de `puriy-costura` pinea un
# host anterior a los verbos de la bóveda, abierto y medido en el SDD 26 §7.quinquies—. **Si esto
# sale todo verde, lo roto es esto**: un cuadro entero en verde puede ser un producto sano o un
# runner que no corre nada, y se ven igual.
#
# ⚠ Esta cabecera decía «un rojo» hasta que la primera corrida la desmintió: el segundo guardián
# lleva el mismo chequeo del cable ADENTRO. Queda escrito porque es la trampa de siempre —predecir
# el resultado y no volver a mirarlo—, y porque el número es el control: si mañana hay UN rojo, o
# tres, cambió algo que hay que ir a ver.
#
# ══ LO QUE CUESTA ═════════════════════════════════════════════════════════════════════════════
# **~32 min** en gioser, en serie (medido 2026-09-15). 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 ]