Commit Graph
15 Commits
Author SHA1 Message Date
sergioandClaude Opus 4.8 25e3878331 farm: JOBS=1 en el worker-loop mientras el ADR 0012 esté sin decidir
`build-farm.sh` usa `xargs -P$JOBS`; con >1, dos recetas que comparten dep disparan la carrera del
árbol de fuentes del ADR 0012 y el árbol queda roto para siempre. Se vio a escala: al invalidar
libdrm, 118 de las 205 recetas KDE pasaron de cache-hit a rebuild real y ~93 murieron con
"/src/.zwrap/cc is not a full path to an existing compiler tool" — el wrapper de zig que la receta
deja en el ÁRBOL DE FUENTE, barrido por el fetch concurrente de otra receta sobre el mismo qtbase.
El reintento serial de build-farm tampoco las recupera: el árbol ya quedó inconsistente.

La caché estaba ocultando la carrera, no evitándola. Serializar es la única mitigación correcta
hasta que el ADR 0012 elija salida.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 18:15:38 -04:00
sergioandClaude Opus 4.8 142c417d36 farm: que el loop DIGA que está esperando el lock, en vez de parecer que trabaja
El `echo "ciclo: N recetas en $Q"` sale ANTES de pedir el lock, así que con la campaña corriendo el
journal mostraba el anuncio del ciclo y después nada: parece un loop trabajando y es un loop
bloqueado. Es la misma clase de problema que el "no encuentro el ejecutable zig" apuntando al
directorio equivocado — un log que miente cuesta horas de diagnóstico.

`flock -n` primero, y sólo si falla se anuncia la espera y se bloquea. Sin coste cuando el lock
está libre, que es el caso normal.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 17:21:24 -04:00
sergioandClaude Opus 4.8 1b436a717f farm: lock compartido entre campana-deuda y el worker-loop
Los dos construyen sobre el MISMO work/, y `fetch` nombra el árbol de fuentes de forma determinista
(`work/sources/<receta>-<sha16>`, sin nada que dependa de QUIÉN construye) ⇒ dos procesos que
necesiten la misma DEP apuntan al mismo directorio: uno hace `remove_dir_all` mientras el otro
corre `tar -x`. El árbol queda a medias y devuelve "Directory not empty" (os error 39), y así se
queda hasta que alguien lo borra a mano.

No es teórico: la campaña de deuda y el loop pidieron `mesa` a la vez (el loop lo arrastraba desde
la cola KDE al invalidarse libdrm) y se llevó puesta media cascada GUI, con un error que no nombra
la causa. Casi borro ese árbol a mano antes de ver que había un bwrap montándolo.

Grano: la campaña toma el lock para toda su corrida; el loop, por ciclo de cola. Más fino rompería
el `xargs -P2` de build-farm.sh.

Dos honestidades en los comentarios, para no prometer de más:
  - `flock` NO es FIFO. El loop vuelve a pedirlo enseguida y le gana a la campaña que espera:
    medido, la campaña entra al terminar TODAS las colas, no entre dos. La ventana real es el
    IDLE_SLEEP. Por eso espera con techo (LOCK_WAIT=7200) y sale limpia en vez de colgarse.
  - Esto NO cierra la carrera del todo: el `-P2` interno del loop puede correr dos recetas de la
    misma cola que compartan dep, y ésas se siguen pisando. El arreglo de fondo es un lock POR
    ÁRBOL dentro de `fetch`, que cubriría los dos casos.

Verificado con flock real: exclusión mutua (la campaña entra justo cuando el loop suelta), salida
limpia por timeout con rc=0, y la no-equidad de flock medida en vez de supuesta.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 17:06:42 -04:00
sergioandClaude Opus 4.8 19a3cda8ca granja: el worker recompila hammer al arrancar (evita el fósil de la golden)
Raíz de una noche de KDE atascada: la golden del 29-jun horneaba un hammer SIN el fix del
overlay lowerdir (e69eaaa, 12-jul) ⇒ toda receta de muchas deps (kio=52, kwin, plasma-*)
desbordaba el límite de 4KB de mount options y el sandbox ni arrancaba. 43 recetas 'en cola'
que en realidad reventaban al instante. El source llega fresco por farm-sync pero nadie
recompilaba. Ahora el worker-loop hace 'cargo build --release --bin hammer' al arrancar
(~24s cacheado). Binario del worker vivo ya rebuildeado a mano y verificado: kio cruza el
mount (funde 52 deps en una capa) y configura.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 05:07:13 -04:00
sergioandClaude Opus 4.8 fa8dff08b1 granja: borrar la cola gráfica obsoleta de incoming/ (no había otro agente)
Las 7 recetas del stack gráfico (libdrm/mesa/meson/samurai/seatd/wayland/wayland-protocols) +
6 patches eran imports crudos de Alpine, redundantes: las 7 ya tienen receta CANÓNICA en recipes/
(mesa pineada a 24.0.9 iris-only A PROPÓSITO, no la 26.1.1 cruda con FIXME-sha256). Su trabajo
aterrizó por la vía canónica (7131cd4) hace 3 semanas; la cola quedó de cruft rompiendo cada ciclo.

fa45978 las sacó de QUEUES creyéndolas de 'otro agente' (5126a8b). Confirmado que NO hay otro
agente ⇒ borradas. recipes/incoming/ vuelve a ser cola de staging general y REGRESA a QUEUES; el
guard ls-vacío la salta si no hay nada. recipes/incoming/.deferred/ (24 recetas aparcadas con
diagnóstico, git con muro en libgit.a) NO se toca: el glob de QUEUES es top-level, no la muele.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 11:26:42 -04:00
sergioandClaude Opus 4.8 fa459784e4 granja: dejar de moler la cola del OTRO agente (los 6 'No such file' de cada farm-down)
recipes/incoming/ es la cola del stack gráfico tawasuyu, de otro agente. Sus 7 recetas son
imports crudos de Alpine con sha256='FIXME-sha256' y deps sin expandir (clang$_llvmver, _dev,
py3-gpep517) ⇒ NO construibles por construcción. El worker las fallaba en CADA vuelta (CPU
pagada) y farm-down repetía los 6 errores al bajar, con pinta de ser nuestros.

Su trabajo YA aterrizó por la vía canónica (7131cd4 'MESA iris-only CONSTRUIDA — stack gráfico
COMPLETO'), así que la cola quedó obsoleta. Pero NO es nuestra para borrarla: 370e7b7 ya la
parqueó una vez como cruft y 5126a8b tuvo que revertirlo. Dejamos sus ficheros en paz y sólo
los sacamos de QUEUES.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 09:22:01 -04:00
sergioandClaude Opus 4.8 071be00396 kde/H-Qt: receta qtbase de-Alpinizada (gate campaña KDE) + cola incoming-kde al worker
qt6-qtbase 6.11.1 desde Alpine community: conserva sus 3 parches de musl (LFS64/
DNS-resolver/symlinks), reescribe abuild→CMake/Ninja explícito. link=DINÁMICO
(política capa GUI, ADR 0011). Minimal para el gate: Wayland-only (xcb OFF),
icu/vulkan/cups/libproxy/libinput/accessibility OFF, double-conversion+libb2
bundled ⇒ compila reusando SOLO deps ya selladas, cero recetas nuevas.
sha256 pinneado (sha512 cotejado con Alpine). farm-worker-loop añade
recipes/incoming-kde a QUEUES.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 14:05:23 -04:00
sergioandClaude Opus 4.8 114a02b597 Etapa G (granja): watchdog protege árboles calientes — cura corrupción de deps transitivas
El watchdog de disco purgaba work/sources/* protegiendo solo árboles bind-montados
por bwrap (prot.1) o cuyo nombre coincide con la receta en vuelo (prot.2). Una dep
transitiva (cairo bajo pango/gtk4) se extrae host-side ANTES del bwrap y con nombre
que no coincide con la receta ⇒ el rm -rf competía con el tar y dejaba el árbol a
medias: 'Cannot mkdir' durante la extracción, luego 'Directory not empty' para
siempre (falla rápido antes de bwrap, nunca se recupera). Prot.3: no purgar árboles
modificados hace <2 min (extrayéndose ahora); los fríos se purgan y re-extraen limpio.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 06:30:29 -04:00
sergio 27fb9d4812 Etapa G: worker muele 3ª cola recipes/incoming-clib (libs C toolkit; el cron-go la ignora) 2026-06-29 22:56:01 -04:00
sergio c381e1b0c7 Etapa G: modo finde desatendido — worker muele incoming-go/ + harvest-go.sh (cosecha-only gated)
- farm-worker-loop.sh: construye QUEUES='recipes/incoming recipes/incoming-go' (en serie por vuelta;
  la cola Go aislada se muele 24/7 sin pisar el incoming/ del otro agente).
- scripts/farm/harvest-go.sh: cosecha determinista sin IA (cron del laptop). Baja el store sellado,
  y por cada receta SELLADA (cache-hit bajo timeout, NO compila en el hub) hace SMOKE-TEST del binario
  (existe + corre version/--help sin panic/segfault) antes de promover+firmar. Lo que falla el smoke va
  a tandas/needs-review-weekend/ para el lunes. add explícito (nunca -A), push con reintento.
2026-06-27 06:41:28 -04:00
sergio c270edade7 Etapa G: watchdog no purga caches Go con CUALQUIER hammer build en vuelo (no solo vendor)
vault (go-15) falló en 'go mod vendor' con '~/.cache/go-build/...: no such file': durante el compile
de telegraf el disco cruzó DISK_HIGH, el watchdog corrió 'go clean -cache', y el vendor de vault (que
usa esa cache) arrancó en la ventana siguiente sin ficheros. El guard anterior solo miraba 'go mod
vendor' activo en ese instante; ahora difiere la purga si hay cualquier 'hammer build' en vuelo.
2026-06-27 03:30:50 -04:00
sergio ad7ec4aea4 Etapa G: watchdog protege árboles con 'hammer build' en vuelo (fase host vendor/resolve)
go-13 (dnscontrol/lazysql, árboles de deps Go enormes) destapó otra race del watchdog: durante el
fetch/'go mod vendor'/resolve_phases (host-side, antes del bwrap) el árbol no está bind-montado ⇒ el
watchdog lo borraba a mitad del vendor → go.mod desaparecía → 'receta sin compile, heurística no
encontró build system'. Ahora además protege work/sources/<name>-* si <name> tiene un proceso
'hammer build' activo (cubre toda la vida del build, no solo la fase sandbox).
2026-06-27 01:07:09 -04:00
sergio 06ba417336 Etapa G: granja Go pesada — watchdog no purga modcache con vendor activo + syncthing main en cmd/
go-12 (terraform/k8s) destapó la race: con árboles de deps de varios GB en paralelo, el disco
cruza DISK_HIGH y el watchdog corría 'go clean -modcache' a mitad de los 'go mod vendor' en vuelo
(.partial: no such file) ⇒ 5 recetas no convergían. Ahora difiere la purga del modcache si hay un
vendor de host activo (la purga de work/sources ya libera lo grueso y es segura). syncthing: main
real en ./cmd/syncthing (la raíz tiene build-constraints que excluyen todo).
2026-06-26 23:32:12 -04:00
sergioandClaude Opus 4.8 64f4a20072 granja: watchdog purga caches Go cuando disco >=82%
El 'go mod vendor' acumula GOMODCACHE (~/go/pkg/mod) sin tope: una tanda Go
grande lo llevo a 31G y lleno el disco de 80G -> I/O-wait disparo el load a 23
(cuello real, no CPU/RAM). El watchdog ahora purga 'go clean -modcache/-cache'
cuando el disco supera DISK_HIGH% (def 82). El vendor/ local de cada receta ya
tiene lo necesario; si pisa un vendor en curso, esa receta reintenta.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 17:36:05 -04:00
sergioandClaude Opus 4.8 d949d10dcd Etapa G: kit de granja distribuida (worker VPS hub-and-spoke)
Paraleliza el build a un/varios VPS sin exponer gitea ni la clave de firma.
Modelo: el laptop es el HUB (firma + gitea); el worker sólo construye la cola
incoming/ y sella al store local (PROMOTE=0). Reproducibilidad bit-a-bit +
content-addressing ⇒ el store del worker es byte-idéntico, se rsync-ea de vuelta
y el hash valida solo (no hay que confiar en el VPS).

- vps-setup.sh: provisiona Debian/Ubuntu (deps, userns p/bwrap, swap 16G,
  rustup, build hammer, bootstrap-devfs rootfs Alpine edge, systemd unit).
- farm-worker-loop.sh: loop autónomo 24/7, PROMOTE=0, watchdog de disco
  integrado; muele lo que haya sin esperar al hub.
- hammer-farm.service: systemd, JOBS=2 (CCX13 = 2 vCPU dedicado), Nice/idle-io.
- farm-sync.sh (hub): rsync código+cola arriba, store sellado abajo,
  promote+firma+commit+push. Acceso único laptop->VPS por SSH.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 03:50:43 -04:00