respaldados (manifiesto del Storage Box): 3686
en el store de la caja: 1320
de la caja, NO respaldados: 0 ← la cuenta que decide
errores y reintentos: 0 y 0
Pero la primera corrida no terminó, y el motivo vale por sí solo: se cayó 40 veces con el MISMO
fichero porque una transferencia interrumpida el 11-sep había dejado un parcial en el destino con el
modo del origen (-r--r--r--, el store es de sólo lectura por diseño). Ningún intento posterior puede
reescribirlo: esa ruta quedaba envenenada PARA SIEMPRE, y el bucle la golpeaba cada 60 s llamándola
«corte de red». Arreglado con --chmod=Fu+w (un corte a mitad se retoma) y dando al rsync 23 tres
intentos en vez de cuarenta, nombrando la causa probable al tercero.
🪤 Y dos veces el mismo error mío en la misma tarde: `pgrep -f <patrón>` SE ENCUENTRA A SÍ MISMO —el
patrón está en la línea de comando del propio pgrep y del ssh que lo lanza—, así que «sigue
corriendo» era verdad para siempre y el vigía que armé con esa condición nunca podía dispararse. La
forma correcta es el truco del corchete: `grep "[r]espaldo-storagebox"`. Hermano del `pkill -f` que
mata tu propia shell.
Lo que separa esto del borrado de gioser ya no es técnico: es la decisión del usuario, a mano y
nunca por automatización.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2 store entero ✅ 1320 artefactos, 0 vacíos, /store al 62 % tras el gc
4 la granja late allá ✅ §6.43 — con el lab pineado, y la caja gana por uno en los dos grafos
5 el host se instala de su repo ✅ §6.46 — 171 publicados, install --require-signed en verde
7 el respaldo desde la caja ⏳ primera corrida completa en marcha
1,3,6,8 ✅
Lo que separa esto del borrado de gioser ya no es técnico: es la corrida de respaldo terminando y la
decisión del usuario — a mano, con las ocho en verde, nunca por automatización. Y lo que queda vivo
en gioser es trabajo de la mudanza, no servicios: los ~10 G de árboles personales sin decidir.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Estaba a medias desde el §5.4 por el lab. Con el lab instalado (§6.43), cerrada en dos movimientos,
los dos en la caja:
publicar: 171 paquetes con expected_hash anclado, 3 sin ancla, índice verificado contra ./trust,
firmado con la clave de release que se mudó el 16-sep. Falló uno: os-release.
instalar: `takana install duf --require-signed --trust ./trust` ⇒ «release: trusted (by release)»,
deps resueltas, apply OK, registrado. Bajo --prefix y --db propios, sin tocar el sistema.
⚠ El matiz honesto vale más que el verde: el artefacto YA ESTABA en el store, así que se ejercitó
resolver + verificar firma + hidratar, NO reproducir desde fuente. Lo que el lab destrabó y sí quedó
probado aparte es el HASH (§6.43, cuatro de cuatro iguales a gioser), que es donde moría antes. Queda
sin ejercitar «paquete que no está en el store» — y en una caja de producción es discutible que se
quiera: un servidor no tiene por qué compilar.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
El paso de poda del latido moría con `/dev/fd/63: No such file or directory` y un `viejos: unbound
variable` de consecuencia. La causa no era el script: la sustitución de procesos de bash necesita
/dev/fd y UNA CAJA TAKANA NO LO TIENE (gioser sí). O sea que ningún `<(...)` de ningún script del hub
funcionaba allá; éste fue el primero en toparse.
Arreglado en los dos lados: /dev/fd -> /proc/self/fd en la caja con Card OneShot en el genesis
(comprobado: `cat <(echo funciona)` responde), y en el script fuera `<(...)` y fuera `df -B1
--output=avail`, que es GNU — sin eso corría pero decía «libres 0.0 G», y un 0 se lee como disco
lleno.
Resultado: 2 árboles podados, 5,4 G. Con el store-gc del §6.44 son 32,2 G recuperados hoy en la
caja: /store al 62 %, /work al 29 %.
⇒ Van dos parches con forma de Card OneShot para cosas que debería hacer el init (hostname y ahora
/dev/fd). Es una lista que conviene no alargar.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
/store pasó de 84,7 G usados (91 %) a 57,9 G (62 %): 337 superados borrados y VERIFICADOS, 1657 →
1320 artefactos. Los 150 huérfanos (11,4 G) quedan intactos por diseño: son el único ejemplar de su
nombre.
EL CONTROL QUE NO ES OBVIO: 11 binarios de /usr/bin de esa caja son symlinks que apuntan DENTRO del
store — los daemons instalados estos dos días. Un gc que borre el artefacto equivocado no rompe el
store, rompe el /usr/bin de una máquina en producción. Comprobado antes (los 11 enlazan al hash
vigente) y después (los 11 resuelven, 21 entes corriendo).
Y el gc no sabía decir sus dos números: `du --files0-from=-` es GNU y busybox no lo tiene; `df -h
/home` estaba cableado cuando el store vive en /store (sin /home, `tail -1` devolvía la CABECERA: de
ahí «libres: Available → Available»). El primer arreglo también estaba mal —`xargs -d` es otra
extensión GNU— y eso imprimió «huérfanos ?»: ese `?` es deliberado, un cero inventado habría dicho
«no hay nada que ganar» con 11,4 G en huérfanos. Con `xargs -0` la caja ya contesta 11.4G.
⇒ Cinco tropiezos del mismo día con la misma forma (/dev/tcp, llaves, find -newermt, sustitución de
procesos, y estos dos): un script del hub escrito en una máquina GNU no corre en la caja hasta que se
prueba ahí.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
El §6.42 dijo qué faltaba y el usuario eligió darle el lab a la caja. Hecho.
EL LAB NO SE COPIA, SE PINEA Y SE TRAE. `lab-image.sh` lo empaqueta determinista (--sort=name
--mtime=@1 --owner=0, excluyendo var/log/apk.log), lo publica al Storage Box con el sha en el nombre,
y `--traer` VERIFICA EL SHA ANTES DE EXTRAER. El empaquetado de hoy devolvió exactamente el sha que
el repo ya pineaba (d1e341d5…): o sea que el lab de gioser nunca derivó Y que el empaquetado es
reproducible de verdad, no una promesa del comentario.
LA PRUEBA QUE DECIDE no es que arranque: la caja calcula los MISMOS ArtifactHash que gioser en las
cuatro recetas de control (zlib, busybox, caddy, shuma-daemon). Con otro lab serían otros números y
el store no lo notaría.
⚠ Y UNA TRAMPA QUE ME TENDÍ SOLO: al copiar los 24 artefactos que le faltaban al store de la caja,
`rsync -a --files-from=<lista de DIRECTORIOS>` mandó 2.281 bytes y «total size is 0» — pero creó los
24 DIRECTORIOS VACÍOS. `--files-from` no recursa sin `-r`, y un directorio vacío en el store ES UN
CACHE-HIT (§3 de CLAUDE.md): `build` lo habría dado por sellado sin construir. Detectado contando,
borrados los 24, repetido con `-r`: 3,18 GB y 0 vacíos de 1655.
Stores convergidos (copiados también obs-studio y spectacle, justo los dos que el worker no logra
construir). La caja no empata, gana por uno: corpus 930 selladas / 1 deuda contra 929 / 2; KDE
1106 / 1 contra 1105 / 2.
Latido mudado: cron apagado en gioser, encendido en la caja, y un ciclo corrido a mano mirando lo que
publica — `repo al día (ff)` → `estado commiteado+pusheado` con los números buenos.
⚠ Lo que queda apretado es el disco: /store de la caja al 91%, 8,2 G libres. Un hub sella y cosecha:
ése es el próximo muro, y `store-gc.sh` no se corrió nunca allá.
⇒ PUERTA 4 EN VERDE. De las ocho quedan dos a medias (5 y 7) y ninguna en rojo.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
El ciclo que corrió desde la caja (commit 45b5685a) dejó en `main` un `build-state*.json` diciendo
`unhashable: 936` y `unhashable: 1112` — o sea, que NO SE PUDO CALCULAR el hash de ninguna receta,
porque el lab entra en el ArtifactHash y esa máquina no lo tiene (§6.42).
Regenerado desde gioser, que sí lo tiene: 929 selladas de 936 · KDE 1105 de 1112. El grafo CIERRA y
el topo-sort pasa en los dos.
⚠ Lo que esto enseña sobre el propio fichero: un `build-state` con `unhashable` en el total no es
«el corpus está mal», es «quien lo generó no podía mirarlo». Los dos se leen igual en un tablero.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Se intentó el último intercambio —cron de cosecha de gioser a la caja— y salió mal en el primer
ciclo. Vuelta atrás hecha en minutos; queda escrito porque el motivo no era ninguno de los previstos.
Funcionó todo lo mecánico: la caja sembró al worker, leyó su manifiesto, regeneró los ocho ficheros
de estado, pasó los vigías, se puso al día por fast-forward y commiteó+empujó. Lo que publicó es el
problema:
caja : {recipes: 1112, nodes: 1115, unhashable: 1112, ajeno: 3}
gioser: {recipes: 1112, nodes: 1115, sealed: 1105, never: 5, debt: 2}
`unhashable: 1112` no es «sin sellar»: es que NO SE PUDO CALCULAR el hash de ninguna receta, porque
EL LAB ENTRA EN EL ArtifactHash y una caja de producción no lo tiene — a propósito. El commit
45b5685a dejó en main un build-state que dice que el corpus entero no existe.
⇒ La puerta 4 NO era una línea de crontab, aunque todas las piezas que se miraron (git, python3,
rsync, ssh, takana, flock, .fleet, la llave) estuvieran. Un hub es la máquina que tiene el LAB: el
tercer paso del latido no es copiar, es PENSAR sobre el corpus. Tres salidas, y ninguna es «poner el
cron»: darle el lab a la caja · partir el latido (siembra/cosecha allá, grafo donde haya lab) · que
el hub sea otra máquina (el LXC ya tiene lab y muele 24/7). Es decisión del usuario, y es lo único
que queda entre esto y borrar gioser.
El latido de gioser, reactivado, repara el daño solo en su siguiente ciclo.
Y el ciclo destapó tres cosas en la caja: `poda-fuentes.sh` NO corre en takana (usa sustitución de
procesos, que busybox ash no tiene — cuarto tropiezo del día con la misma forma); los vigías
reportaron 1 ofensor nuevo de raíces (bzip2), 3 herramientas selladas no invocables y 7 errores en
servicios.txt; y `arjectl status | head -2` hace paniquear a arjectl con un EPIPE sin manejar.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Apagados en gioser (relay, serve y willay-crosscheck), encendidos en la caja: `tejido` en :4102 y
`willay-crosscheck` en :4103, los dos alcanzables desde fuera.
La prueba de que la identidad VIAJÓ no es que el servicio arranque —eso pasaría igual con semillas
nuevas, que es el fallo silencioso que esto existe para evitar— sino que la semilla sea la misma:
`device.seed` y `roster.postcard` con sha256 IDÉNTICO a los dos lados. El PeerId sale de ahí, así
que sigue siendo 12D3KooWBw2u….
⚠ LO QUE SÍ CAMBIA: el multiaddr que los clientes tienen configurado lleva la IP.
antes /ip4/204.168.193.248/tcp/4102/p2p/12D3KooWBw2u…
ahora /ip4/2.29.29.217/tcp/4102/p2p/12D3KooWBw2u… (mismo PeerId, otra IP)
🧱 SIN EL CORTAFUEGOS HABRÍA SIDO UN VERDE FALSO: el reglaset abría 80/443/1137/2345/22022 y nada
más. Con el relay encendido y el 4102 filtrado, `status` diría «corriendo · 0 reinicios» y la flota
no llegaría. Abiertos 4102 y 4103 con su ban por tasa; NO el 33097, que era el puerto efímero de un
`tejido serve` cliente. Y el fichero quedó IDEMPOTENTE (crear+borrar la tabla antes de definirla),
que era deuda del §6.33: 15 reglas dport antes, 21 después — no 36.
⚠ La política que genera ese reglaset NO EXISTE en ningún disco: ni la ruta que su cabecera nombra
ni el binario `cortafuegos`. El generado sobrevivió a su fuente, así que hoy se edita a mano.
🆔 Y takana acepta ULIDs que arje-zero RECHAZA: la card no encarnaba por `invalid character`, y era
la `L` de «RELAY» — carácter excluido del alfabeto Crockford. `service-cards` lo dio por bueno («26
alfanuméricos») y el consumidor lo tiró. El validador del productor más laxo que el del consumidor
siempre termina en un fallo lejos de donde se escribió.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
La tabla del §6.3 era del 10 de septiembre. Hoy, entera:
2 store entero ✅ 1632 artefactos, 0 vacíos (eran 1362) · ⚠ /store al 88%
4 la granja late allá ❌ el latido SIGUE en gioser
6 dominios vivos 200 ✅ los 8 contra 2.29.29.217, `sergio` incluido
7 respaldo desde allá ⬖ el script corre y LISTA el Storage Box desde la caja
1,3,8 ✅ · 5 ⬖ (sirve, no consume: reproducir exige el lab entero)
La puerta 4 es ahora UNA LÍNEA DE CRONTAB. La caja ya tiene git, python3, rsync, ssh, takana, flock,
la llave del worker y el `.fleet`; le faltaban dos costuras y están hechas: `store -> /store` (el
script espera ./store, acá es partición) y `target/release/takana -> /usr/bin/takana` (no hay árbol
de build en una caja instalada). Prueba de sólo lectura: `estado-granja.sh` desde la caja ve al
worker, lee el grafo KDE y dice «CRON DE COSECHA: NO instalado».
NO lo instalé, por el mismo motivo que tejido: con el cron en las dos máquinas, las dos harían
`rsync --delete` al worker y las dos cosecharían y commitearían. El latido se INTERCAMBIA, no se
duplica, y es el último movimiento antes del borrado.
De paso, el repo de /opt/takana estaba 5 días atrasado y quedó en origin/main exacto (0 diferencias),
con tar de respaldo de los 92 ficheros previos. ⚠ Esos 92 no eran trabajo local: era contenido que
YA estaba río arriba metido en el árbol sin commitear — un árbol que parece sucio y está atrasado.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>