Commit Graph
754 Commits
Author SHA1 Message Date
sergioandClaude Fable 5 2e85dfc8a3 joyas #1 composefs: prototipo medido — hydrate 28ms vs mkcomposefs 507ms (métrica equivocada: lo que compra es verity por lectura + RO real + manifiesto 136KB firmable); hallazgo: objects/ por sha256-verity ⇒ mapa b3→verity al sellar
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 23:12:55 -04:00
sergioandClaude Fable 5 7f310005ea variantes-cpu T5 MEDIDO: zstd cortado (dispatch runtime, v3/v4=ruido con i7); zlib inconcluso pero la respuesta es zlib-ng; la lista caliente se concentra en mesa/códecs
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 23:09:50 -04:00
sergioandClaude Fable 5 9c4ef8561c linux-metal: perfil escritorio/juego — NTSYNC, PREEMPT full+HZ_1000 explícitos, MGLRU, ZRAM, EROFS+FS_VERITY (sustrato composefs), split_lock_detect=off; sched-ext DIFERIDO (exige BTF que la receta apaga a propósito)
Deps de Kconfig verificadas contra el tag v6.16.12 (kernel.org):
NTSYNC sin deps; SCHED_CLASS_EXT depende de DEBUG_INFO_BTF ⇒ tarea propia
(receta dwarves + repro de BTF). Re-sellado disparado en el worker.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 22:26:46 -04:00
sergioandClaude Opus 4.8 ec7ceb0915 harkaq: Q1-copy.fail RESPONDIDA — fs-verity mata el vector page-cache
El SDD 16 dejó abierto: '¿el vector page-cache de copy.fail sobrevive a un
ruleset que deniegue escritura a nivel de inode? Investigar antes de afirmar
nada'. Investigado en un fs AISLADO (loop en un worker efímero, nunca el fs del
usuario):

  escribir al artefacto sellado              → EPERM
  dd como ROOT                               → Operation not permitted (ni root)
  machacar los bytes POR DEBAJO (device)+leer→ Input/output error

El tercero ES el vector de copy.fail: modificar el fichero por debajo del fs. El
kernel detecta la corrupción AL LEER (el Merkle no cuadra) y rechaza la lectura.
⇒ fs-verity mata el vector. Landlock read-only no alcanzaba; fs-verity sí.

Costo medido, y corrige al SDD 17 §5: 'hash = identidad' es FALSO — fs-verity usa
Merkle SHA-256, hammer direcciona con BLAKE3 ⇒ son DOS hashes, no uno. Y ext4
exige -O verity Y blocksize = PAGE_SIZE (con 1024 el mount falla:
'Unsupported blocksize for fs-verity'). No es gratis, pero es barato para lo que da.

NO se tocó el fs del laptop (habilitar verity pediría tune2fs sobre la partición
del usuario): el experimento corrió en un loop device de un worker descartable.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 22:17:01 -04:00
sergioandClaude Fable 5 272125b93a joyas reusables: composefs, PGO/BOLT con perfil sellado, mimalloc, MGLRU, uutils, corpus Clear Linux, reglas ananicy — cada una con su pieza receptora
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 22:16:02 -04:00
sergioandClaude Fable 5 4aa436ceb8 libarchive 3.8.1: receta mínima (bsdtar estático, sólo zlib) + tanda para el worker — plan-freebsd T3.1, sha256 verificado
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 22:16:02 -04:00
sergioandClaude Fable 5 6ef9f2b4a8 cierre §3: lección casper aterrizada — clases de servicio declaradas + mapa clase→permiso musl (plan-freebsd T2.1-T2.2 HECHAS)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 22:16:02 -04:00
sergioandClaude Fable 5 6e1ebfd001 plan jaula-juegos: kernel (NTSYNC/sched-ext/cmdline), nativos (gamescope/scx/mesa-RADV), jaula glibc por fases (flatpak → SLR sellado) con política harkaq
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 22:10:35 -04:00
sergioandClaude Fable 5 ed99fcf1ee plan variantes-cpu: x86-64-v3 sobre el CAS — selección en hydrate (musl sin hwcaps), lista caliente estilo Solus, piloto zlib/zstd
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 22:10:35 -04:00
sergioandClaude Opus 4.8 4374d2b591 cierres §4: CVE por grafo — frontera mínima de rebuild (dirty_cone + topo_order)
`scripts/affected.py <pkg> [--agenda] [--sellados]`. Un CVE no obliga a
reconstruir el catálogo: obliga a reconstruir el CONO de lo que depende del
paquete, y nada más. El grafo declarado ya lo sabe.

  CVE en zlib  → 65 de 761 recetas (8%) — el resto NO se toca
  CVE en expat → 20 de 761 (2%), las 20 selladas = el trabajo real
                 agenda: fontconfig → fcft → cairo → pango → dbus → wayland…

Es el `dirty_cone` de `dataflow` (crate no_std de tawasuyu) + `topo_order` como
agenda (una dep antes que su consumidor), calculados sobre las deps declaradas.
`--sellados` separa lo que hay que reconstruir de verdad (tiene artefacto) de lo
que no existe aún.

CAE SOLO DEL INVARIANTE: las deps están declaradas por hash ⇒ el cono es
computable y EXACTO. Una distro sin clausura declarada tiene que adivinar o
reconstruir todo por las dudas. Ésa es la tesis del SDD 17.

Honestidad grabada en el propio output: la frontera es exacta respecto de lo
DECLARADO. Lo que una receta usa sin declarar queda FUERA del cono — y ese es el
agujero que harkaq cierra (SDD 16). La campaña de esta semana declaró ~84 deps
que el kernel midió y nadie había escrito: sin eso, este cono habría sido
optimista. **El cono es tan bueno como la clausura**, y por eso los dos frentes
se necesitan.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 22:09:59 -04:00
sergioandClaude Fable 5 8ff8c1b820 plan freebsd: traza positiva (filemon/META MODE) + taxonomía casper para cierre §3 + libarchive al catálogo
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 22:03:24 -04:00
sergioandClaude Opus 4.8 be52e735ab cierres §3: política de runtime derivada por medición (sin tocar la cripto)
El #3 decía "la clausura medida por harkaq en build = permisos del binario
instalado". MEDIDO: es falso en dos ejes, y por eso NO se implementó así.

1. SUJETO: la clausura de BUILD (zlib.h, make, gcc) no es la de RUNTIME. Un build
   lee headers; el binario resultante no. Dos clausuras, dos sujetos.
2. GRANULARIDAD/CRIPTO: lo que la ConcesionCapacidad firma NO es card-core::
   Permissions (struct) sino format::Permisos = u32 bitmask, dentro de
   `mensaje_capacidad` = hash(32)||permisos_le(4) = 36 bytes canónicos, zero-alloc,
   con espejo no_std en wawa-kernel (Ring 0). Meterle paths rompería TODAS las
   firmas y contradice el "capacidad = frontera física, no tabla" que el propio
   plan cita como referencia.

⇒ Camino elegido: la concesión firmada QUEDA INTACTA (frontera gruesa, Ring 0) y
la clausura granular se deriva por MEDICIÓN como política Landlock en userspace,
donde Vec<String> sí cabe. Coexisten: el kernel verifica la frontera, Landlock
aplica el detalle.

runtime-policy.sh: corre el binario bajo la jaula con política mínima DERIVADA
(harkaq-base-closure, no a mano) y resta el BASELINE del lanzador (el sh deniega
locale/ld.so.cache; sin restarlo, la política del binario se lleva esa basura).

Demo real — htop (musl-estático): baseline 3 paths del sh; htop --version no tocó
NADA propio ⇒ su política de runtime es sólo `ro <su binario>`. Medido, no supuesto.
htop tiene 0 NEEDED: para un estático la política NO sale de las libs, sólo de
correrlo — lo que confirma que la técnica de harkaq es la única vía para el #3.

+ FIX del lector (lo cazó el chequeo anti-pérdida `nº ACCESS == denials`): descartaba
los ACCESS previos al canario porque hasta verlo no sabe su domain= — pero el sh
deniega ANTES del probe y esas son suyas. El kernel contaba 4 y el lector recibía 1.
Ahora se bufferizan con su domain y se rescatan retroactivamente al ver el canario.
Sin ese chequeo habría emitido una política con 1 de 4 accesos, perfectamente creíble.
(Primer intento de fix —drenar el socket al ver el deallocated— era plausible y NO
era la causa: el contador siguió en 4 vs 1.)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 22:02:05 -04:00
sergioandClaude Opus 4.8 e9b6283722 cierres §2: why-differs — explica POR QUÉ dos artefactos no reproducen
El #2 de SDD 17, y encadena con el #1: cuando  da DIVERGENCIA, esto
dice qué difiere y por qué. Hoy debuggear una no-reproducción es artesanal; esto
la vuelve mecánica y legible por máquina (lo que el bucle agéntico necesita).

Algoritmo (cruce con  de tawasuyu): árbol = grafo blob+árbol hasheado ⇒
dos subárboles idénticos colapsan al mismo hash ⇒ descender SÓLO donde difiere.
O(diferencia), no O(tamaño).

Clasifica la causa, que es lo que decide la acción: solo-en-A/B (no-determinismo
de estructura) · tamaño · build-id · timestamp · path-embebido · codegen ·
contenido.

Probado: control (A vs A) → 'árboles IDÉNTICOS' ✓. Caso real (bzip2 gcc vs zig):
de 21 ficheros sólo difieren los 4 binarios → causa .

DOS VECES tuve que arreglar el diagnóstico por confundir SÍNTOMA con causa:
  1. Chequeaba build-id PRIMERO ⇒ reportaba 'build-id' cuando la causa era el
     codegen. El build-id es un HASH DEL CONTENIDO: difiere siempre que difiera
     el código.
  2. El umbral era '<1% del binario' — sonaba bien y clasificaba 1196 bytes como
     build-id. Un build-id son 20 bytes (sha1). Atado al TAMAÑO REAL (<=64).
Un diagnóstico plausible no es un diagnóstico correcto.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 20:33:51 -04:00
sergioandClaude Opus 4.8 8b1eea8911 cierres §1: consenso de reconstrucción — funcionando (2/2 builders, mismo hash)
El top-1 de SDD 17 (mayor ventaja competitiva por esfuerzo). N builders
INDEPENDIENTES reproducen el mismo hash ⇒ el binario es confiable SIN FIRMA.
Convierte la repro de QA en primitiva de distribución: cualquiera puede ser
mirror, nadie puede envenenar el repo.

  scripts/consenso.sh recipes/bzip2.toml 2
    builder 1: hub local (Artix)     → b3:86a33b76…
    builder 2: worker efímero (Ubuntu) → b3:86a33b76…
     CONSENSO (2/2, bit a bit)

Dos máquinas físicas, dos distros, mismo hash byte a byte. Nix/Debian no pueden
ofrecerlo (repro incompleta). Cae SOLO del invariante que hammer ya paga — que es
la tesis del SDD 17: buscar qué cae del invariante, no qué frontera agregar.

Lo originó una observación accidental: al hacer el rollout de cmake noté que el
laptop y el worker daban el MISMO hash sin que nadie lo buscara. Eso ya era
consenso ocurriendo; esto sólo lo formaliza.

Divergencia ⇒ exit 1 y apunta a why-differs (§2): una divergencia YA es
información (un canal impuro encontrado). NO firma ni publica: sólo el veredicto.
El log de transparencia (fork-proof: hash-encadenado + detección de equivocation)
ya está escrito en tawasuyu — no hay que construir un rekor.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 20:26:03 -04:00
sergioandClaude Opus 4.8 2d8514555c matar-gcc: riesgo GUI VERIFICADO — el ABI de las libs migradas es idéntico
Debí evaluar esto ANTES de migrar, no después: las 29 tienen 36 consumidores,
incl. toda la cadena GUI (cairo/gtk4/pango/harfbuzz/fontconfig/libadwaita) +
mesa/mirada. 6 migradas son deps de ese stack, que por regla no se rebuildea en
el laptop.

No se pudo construir la GUI completa en ninguna máquina (laptop: python3 no
construye — gotcha conocido, verificado que es PREEXISTENTE revirtiendo mis deps;
worker golden: busybox no construye — store parcial). Así que se verificó lo que
decide el link: el ABI.

  freetype 90 · expat 12 · libpng/libpng16 385 · libffi 68 símbolos globales
  → IDÉNTICOS entre gcc y zig ⇒ la GUI linkea igual.

Dos falsos positivos cazados al medir: . comparaba libpng.a contra
libpng16.a (libs distintas), y  cuenta símbolos INTERNOS de los
.o que difieren entre compiladores sin tocar el ABI (294 'diferencias' espurias).
Lo correcto: mismo fichero + --extern-only.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 20:03:35 -04:00
sergioandClaude Fable 5 2b7c7015eb kernels: LANDLOCK+AUDIT+IO_URING+BPF_SYSCALL explícitos en linux-metal/linux-generic (contrato kikin)
PLAN-KIKIN §4.bis + HANDOFF-KIKIN-DESDE-HAMMER: el sustrato que kikin asume
(J4 = io_uring, J4b = Landlock/seccomp del anfitrión, eBPF = observabilidad)
tiene que venir COMPILADO en los kernels que hammer distribuye — «al azar del
defconfig» no es un contrato.

- linux-generic 7.1.2: re-sellado en el worker (5c5ef06c) y VALIDADO en QEMU:
  config =y los cuatro, landlock_create_ruleset/io_uring_setup/bpf_prog_load
  en kallsyms, y el re-test de input de mirada pasa (5 dispositivos, salida de
  emergencia procesada). Imagen mirada-usb re-empaquetada con este kernel.
- linux-metal: mismos flags; se re-sella en el próximo build de imagen metal.
- linux.toml (soberano): NO tocado — su of_tree es load-bearing del
  selfhost-verify; deuda anotada en la receta para el próximo re-ancle.
- SECURITYFS queda fuera (introspección opcional; harkaq usa el probe
  landlock_create_ruleset(VERSION), que no lo necesita).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 18:45:48 -04:00
sergioandClaude Fable 5 e8e25fb88e boot: activate --from-select idempotente — el hook de apagado de arje-zero lo invoca incondicional
Contrato PLAN-KIKIN §9 (respondido en HANDOFF-KIKIN-DESDE-HAMMER.md): mirada
escribe /run/hammer/boot-select y dispara el reboot SIN salir; /run es tmpfs,
así que la selección se aplica en el apagado o nunca. arje-zero corre esto en
toda secuencia de apagado:
- sin fichero o vacío → no-op limpio (exit 0)
- con selección → activa (rollback E4) y CONSUME el canal; si falla, el fichero
  queda para diagnóstico
- --select parametrizable (testeable); 3 tests nuevos (d/e/f)
- 'boot menu' documentado como HARNESS de dev/VM: en producción mirada no sale

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 17:12:35 -04:00
sergioandClaude Opus 4.8 6c864dcee3 matar-gcc: balance final — 29 migradas, 4 matraca dura diagnosticada
Cerré el frente C-puras. Las 4 que no migran son matraca DURA con gcc
justificado (no inercia):
  file      → el binario zig SEGFAULTEA generando magic.mgc (persiste con -O0
              ⇒ codegen, no optimización)
  linux-pam → 'cannot run C compiled programs' (binario zig no corre)
  libgcrypt/libsodium → no construyen (asm criptográfico)

De 47 compiler=gcc: 29 migradas + 4 matraca dura (gueto gcc legítimo) + 11 Rust
diferidas + 3 no medidas. compiler=gcc: 47 → 18.

harkaq hizo el ciclo completo: reveló las 47 (invisibles bajo 'gcc esperada'),
midió cuáles migran, y el residuo quedó JUSTIFICADO con diagnóstico, no supuesto.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 15:40:48 -04:00
sergio 49fd38d53b arje-link: resync del espejo con arje-bus (Subscribe 13→14 + Parked/Refloored
arje inserto StopCardFromDisk en el medio de BusRequest el 2026-06-26 y
corrio Subscribe a indice 14 — el puente estaba suscribiendose con el byte
viejo desde entonces (roto en silencio; lo delato el golden test de arje-bus
el 2026-07-16, lado tawasuyu 41f4accc7). Ademas el espejo de BusEvent no
conocia EnteParked/EnteRefloored: se agregan como consumo-sin-senal
(to_lifecycle -> Option). Tests unit+e2e actualizados y verdes.
2026-07-16 15:39:58 -04:00
sergioandClaude Opus 4.8 87634f3196 matar-gcc: libevdev + mtdev migradas a zig-cc (generan la lib con zig)
Las 2 'sin confirmar' del balance: el smoke-test no las verificaba por ser libs
sin binario, pero generan la lib con zig (libevdev.so, libmtdev.a). Migradas.

mtdev queda COMPLETAMENTE de-Alpinizado: config.sub soberano (patch de esta
sesión) + zig compiler ⇒ cero dependencia de Alpine. Era la única deuda de
soberanía del barrido harkaq y ahora está cerrada por entero.

Total matar-gcc: 29 recetas C migradas. Quedan 18 compiler=gcc (4 matraca-C
dura + 11 Rust + 3 no medidas).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 15:33:50 -04:00
sergioandClaude Opus 4.8 c6ff858f23 harkaq: cpp/getent en las sondas del provisioning (coherente con base.policy)
Faltaba persistir en harkaq-farm-setup.sh las 2 sondas que añadí a base.policy
al revisar needs-review (cpp=frontend gcc, getent=NSS musl). Sin esto, un worker
nuevo derivaría una base.policy sin ellas y volvería a marcar irreducibles
falsos (dhcpcd/strace).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 15:22:39 -04:00
sergioandClaude Opus 4.8 bf840915f7 matar-gcc: curl+libevent migradas + BALANCE final (27 recetas C a zig)
curl (dep de muchos) y libevent verificadas en laptop: construyen+corren con zig.
Total sesión: 27 recetas C migradas gcc→zig-cc.

BALANCE de las 47 que harkaq nombró:
  27 MIGRADAS  (deuda histórica: zig 0.13/0.16 segfaultaba, zig mejoró)
   4 matraca real: libgcrypt/libsodium (crypto asm), file (magic), linux-pam
   2 sin confirmar: libevdev, mtdev (libs, smoke-test no verifica)
  11 Rust diferidas (gcc para el C embebido de sys-crates, otra evaluación)

matar-gcc pasó de '47 invisibles' (harkaq las reveló al leer el compiler=) a
27 cerradas + cola nombrada. Reporte: tandas/needs-review-harkaq/migracion-zig.md

OJO: re-hashea las 27 del índice firmado 748 ⇒ re-firma en próximo packaging.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 13:42:06 -04:00
sergioandClaude Opus 4.8 322d528888 matar-gcc: 14 recetas C más migradas gcc→zig-cc (verificadas en laptop, store completo)
Segunda tanda. Candidatas que el VPS marcó migrable; re-verificadas en el LAPTOP
(store completo, fiable) build+corre — 14/14, cero matraca:

  freetype jq libassuan libgpg-error libssh2 libuv libxml2 nano pcre2 pigz socat
  tig tmux vim

pcre2 tuvo una discrepancia transitoria (falló en una prueba local temprana con
"linker version script", migró en el VPS); re-verificado limpio en el laptop:
construye Y corre. Era estado transitorio, no incompatibilidad.

Confirma el patrón: el VPS acierta en las MIGRABLES (build+corre son evidencia
real); sólo erraba en las matraca (build-falla espurio por store parcial). La
medición fiable es el laptop.

Total matar-gcc esta sesión: 25 recetas C migradas (11+14). El frente pasa de 47
compiler=gcc a ~22 (las 25 migradas + las que faltan medir + las 11 Rust). OJO:
re-hashea, índice firmado 748 necesita re-firma en el próximo packaging.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 13:30:05 -04:00
sergioandClaude Opus 4.8 c671ae840d matar-gcc: 11 recetas C migradas gcc→zig-cc (medido: construyen y corren)
Primera tanda del rollout aprobado. harkaq nombró 47 recetas compiler=gcc;
migra-zig.sh midió que las C-puras migran a zig (~85%). Estas 11 se verificaron
en el LAPTOP (store completo, fiable): construyen con zig-cc Y —las que tienen
binario— corren limpio.

  bzip2 expat json-c gzip htop less libpng libyaml zstd libffi xz

El compiler=gcc era deuda histórica: se marcaron con zig 0.13/0.16 (que
segfaultaban C clásicos), zig mejoró, el gcc quedó por inercia. Verificado
in-place: bzip2→b3:86a33b76, json-c→b3:9cbe76e3.

11 dependencias menos del gcc de Alpine. Quedan ~25 C-puras candidatas del VPS
por verificar en el laptop (el store parcial del VPS daba build-falla espurios
por deps faltantes — la medición fiable es la del laptop) + las 11 Rust
(sys-crate C, otra evaluación).

OJO: re-hashea estas 11 (estaban en el índice firmado 748); el índice necesita
re-firma en el próximo packaging.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 13:11:18 -04:00
sergioandClaude Fable 5 81a5d8d746 mirada-usb: el overlay de mesa pisaba libudev-zero con el libudev de eudev — input muerto en el tester NVIDIA
Causa raíz del viaje 2026-07-16 (pantalla viva, teclado/mouse muertos): el apk
de mesa arrastra eudev-libs y el 'cp *.so*' del overlay pisaba el libudev.so.1
de libudev-zero. Sin udevd, el libudev de eudev no expone ID_INPUT y libinput
ignora TODOS los dispositivos en silencio; la GPU no lo delata porque smithay
la encuentra por syspath. Reproducido y verificado A/B en QEMU (usb-kbd):
eudev = 0 dispositivos; libudev-zero = 5 y Ctrl+Alt+BackSpace corta el
compositor al instante.

- 5c-bis: restaurar libudev-zero tras el overlay + aserción cmp (regresión = build roto)
- MIRADA_DEBUG_DIR → run-NNNN del pendrive (eventos.log y panics ya no mueren en RAM)
- imagen re-empaquetada con el fix + gpt en la cmdline

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 13:02:17 -04:00
sergioandClaude Opus 4.8 2d1d40a6f1 matar-gcc: migra-zig.sh + veredicto medido — las C-puras SON granjeables (~85%)
¿Las 47 compiler=gcc que harkaq nombró son factibles de migrar a zig, o hay que
matracar? MEDIDO, no adivinado.

migra-zig.sh: para cada receta, build con zig-cc + SMOKE-TEST del binario —
porque el motivo del gcc era segfault en RUNTIME, no fallo de build; un artefacto
que sella pero segfaultea es peor que gcc. Idempotente, acumula por lotes (probar
47 no cabe en un timeout).

Muestra de 13 C-puras: 11 MIGRAN (bzip2 expat json-c gzip htop less libpng
libyaml zstd libffi xz), 2 MATRACA (pcre2: linker version script que zig ld no
soporta; file: subdir magic). ≈85% yield.

VEREDICTO: es GRANJEADA para las ~36 C-puras. El compiler=gcc era deuda histórica
— marcadas con zig 0.13/0.16 (que segfaultaban C clásicos), zig mejoró, el gcc
quedó por inercia. ~85% migran solas; el residuo (~15%) es matraca individual por
causas concretas del build-system.

Las 11 Rust con sys-crate C son otra evaluación (gcc para el C embebido de
libgit2-sys, no el Rust) — se deja para después.

Rollout = decisión del usuario (re-hashea recetas del índice firmado 748). Correr
migra-zig.sh sobre las 47 en la granja VPS da la lista final; promover las
migrables re-firma el índice. Reporte: tandas/needs-review-harkaq/migracion-zig.md

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 12:31:53 -04:00
sergio 0f6c841782 mirada-usb: force_gpt en la cmdline + post-mortem del viaje NVIDIA
El firmware del tester reparo el GPT dd-eado en el POST y dejo el header
primario invalido (entradas apuntadas a LBA 2016, presentes en LBA 2):
Linux sin gpt en cmdline no cae al respaldo, no vio particiones y la
telemetria MIRADALOG murio en RAM. Con gpt el kernel usa el respaldo.
Documentado: greeter por nouveau GL validado en metal; input muerto queda
abierto con el plan de evidencia para el proximo viaje.
2026-07-16 12:16:04 -04:00
sergioandClaude Opus 4.8 71ec92345f harkaq: el clasificador distingue gcc-compilador de gcc-sonda — matar-gcc son 47 recetas
El límite del modelo que mtdev destapó, cerrado. harkaq clasificaba /usr/bin/gcc
como "sonda esperada" SIEMPRE, así que marcaba `Hermetico` a las recetas que
compilan CON el gcc de Alpine (compiler=gcc = CC=gcc, musl+GNU ld). Estuvo ciego
a la deuda de compilador todo el barrido.

Fix en harkaq-suggest: 5º arg = la receta medida. Si usa compiler=gcc, los
frontends de gcc (gcc/cpp/c89/c99/g++/cc/ld/as) dejan de ser "esperada" y pasan a
DEUDA DE COMPILADOR (matar-gcc). Para compiler=zig-cc (default, 714 recetas) gcc
sigue siendo sonda de configure — esperada, como antes. Verificado: mtdev(gcc) →
deuda de compilador; zlib(zig) → sin deuda.

EL HALLAZGO: matar-gcc no es "{kernel, cmake}" como creía la memoria del proyecto.
Son 47 recetas (36 C puro + 11 Rust con sys-crate C) que dependen del gcc de
Alpine. harkaq lo reveló sólo cuando aprendió a leer el compiler= de la receta —
antes gcc-como-sonda-esperada ocultaba una deuda mayor que toda la que sí detectó.
Reporte: tandas/needs-review-harkaq/deuda-compilador-matar-gcc.md.

Cada una usa gcc porque zig-cc la miscompila (documentado en su receta). Acción
por receta: migrar a zig cuando zig mejore, o aceptar el escape como deuda
conocida. Ahora es una deuda NOMBRADA y contada, no invisible.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 09:43:06 -04:00
sergioandClaude Opus 4.8 a1ab8774c5 harkaq: mtdev — deuda de config.sub CERRADA con patch soberano (+ límite del modelo descubierto)
El único caso de deuda de soberanía del barrido: mtdev copiaba el config.sub/guess
del autoconf de ALPINE (/usr/share/autoconf/build-aux/) porque el suyo (1.1.6) no
conoce *-musl. harkaq lo cazó como lectura no declarada del rootfs.

CERRADO con recipes/mtdev-config-sub-musl.patch: 11 líneas, +`-musl*` a la
whitelist de OS del config.sub DEL PROPIO TARBALL. Ahora es input soberano
(hasheado con la receta), sin leer Alpine. Se quitó el `cp /usr/share/autoconf/...`
del configure. Verificado: mtdev construye (b3:47708e40) sin tocar /usr/share/autoconf.

Método (con un tropiezo honesto): casi afirmo que el `cp` era espurio porque el
config.sub en work/sources/mtdev daba exit 0 con musl — pero ese source estaba
MUTADO por un build previo (el cp lo había reemplazado por el de Alpine). El
tarball ORIGINAL fresco NO conoce musl (exit 1). Casi valido sobre un source
contaminado; me salvó chequear el exit code, no el output.

DESCUBIERTO AL CERRARLO: mtdev tenía DOS deudas de Alpine, no una. También usa
`compiler = "gcc"` (gcc de Alpine, no zig). Bajo la jaula la política deniega
/usr/bin/gcc (sonda esperada) y el configure da "C compiler cannot create
executables". Es parte de matar-gcc (kernel, cmake, mtdev), frente aparte.

LÍMITE DEL MODELO (nuevo, documentado en needs-review): harkaq clasifica gcc como
"sonda esperada" SIEMPRE, así que marca la fase Hermetico — pero para una receta
compiler=gcc, gcc es ESENCIAL y el build no compila sin él. harkaq no distingue
"gcc sondeado (ignorable)" de "gcc = el compilador". Caso límite real del
clasificador; no invalida el cierre de config.sub (producción no usa la jaula).

make declarado en mtdev (deuda declarable restante). config.sub fuera de
needs-review; queda anotado el gcc-compilador.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 08:04:03 -04:00
sergioandClaude Opus 4.8 35f58aa75b harkaq: granja con volumen + auto-shutdown VALIDADA end-to-end
Test real (worker + volumen + helper), no en el papel. Las 3 piezas:
  1. worker midió lz4+bzip2 → volumen
  2. tras 1 ciclo idle SE AUTO-ELIMINÓ (verificado: el server desapareció solo)
  3. volumen SOBREVIVIÓ con los 2 verdicts; helper efímero ccx13 los recogió al
     hub y se auto-destruyó

3 bugs cazados EN EL TEST (no adivinados):
  - falta --exclude /work: work/=69GB colgó el rsync del up horas
  - cpx11 'unsupported' en hel1 (AMD sin stock) → ccx13
  - collect llamaba harvest con 'local' (rsync a un worker inexistente): ahora
    sólo recoge; clasificar es paso aparte (worker mide, hub clasifica)

+ auto-delete por API REST (curl+metadata), NO hcloud CLI (la golden no lo trae).
El ID propio sale del metadata service, no del nombre.

Cierra los 2 huecos de la 1ª campaña: idle cobrando (ahora auto-delete) y
dependencia de que yo esté viva (ahora el volumen persiste). Runbook:
docs/runbooks/harkaq-granja-volumen.md. Volumen clausurado tras el test (€0).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 07:47:36 -04:00
sergioandClaude Opus 4.8 f7916b5ee9 harkaq: granja con volumen persistente + workers auto-terminantes
La arquitectura que la 1ª campaña pidió a gritos (el worker quedó idle ~4h
cobrando). Tres piezas en harkaq-vol.sh {up|collect|close|status}:

1. VOLUMEN persistente (harkaq-cosecha): los workers escriben verdicts a
   /mnt/cosecha, que sobrevive a su destrucción ⇒ NO dependo de estar viva para
   no perder el trabajo.
2. AUTO-SHUTDOWN (harkaq-campana-vol.sh): tras IDLE_CICLOS ciclos con 0
   mediciones nuevas, el worker SE AUTO-ELIMINA. En Hetzner un server apagado
   sigue cobrando ⇒ apagar de verdad es delete. Vía API REST + curl + metadata
   service (NO hcloud CLI: la golden Ubuntu no lo trae; curl siempre está). El
   ID propio sale del metadata, no del nombre.
3. collect: monta el volumen en un helper barato efímero (o un worker vivo),
   rsync al hub, corre el harvest, destruye el helper. close: detach+delete del
   volumen (deja de cobrar, ~€0.44/mes mientras exista).

+ dos fixes de la 1ª campaña horneados en el bucle: borra el artefacto -hkm tras
medir (envenenaba la caché) y los dos gates (ABI>=7 + binario-con-jaula).

El token va al worker (para auto-delete): riesgo acotado — worker efímero, sin
servicios entrantes salvo SSH-por-clave, destruido al terminar.

Bug cazado antes de gastar: las llaves {..} dentro del mensaje de ${1:?...}
cerraban la expansión (CMD salía 'status}').

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 07:23:02 -04:00
sergioandClaude Opus 4.8 7d760f274e harkaq: declarar deps medidas por el kernel (cosecha automática)
Cosecha desatendida de la campaña harkaq. Cada dep de acá la denunció el audit de
Landlock en un build real: el kernel vio al build usarla sin declararla, y el
store del hub confirma qué artefacto la provee (deuda DECLARABLE, §4.5).

Recetas:bash binutils busybox bzip2

No se tocó ninguna receta con deuda IRREDUCIBLE: declarar algo que el store no
provee rompería el build en vez de arreglarlo. Esas van a tandas/needs-review-harkaq.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 07:12:47 -04:00
sergioandClaude Opus 4.8 fecdeab8f1 harkaq: declarar deps medidas por el kernel (cosecha automática)
Cosecha desatendida de la campaña harkaq. Cada dep de acá la denunció el audit de
Landlock en un build real: el kernel vio al build usarla sin declararla, y el
store del hub confirma qué artefacto la provee (deuda DECLARABLE, §4.5).

Recetas:dhcpcd strace

No se tocó ninguna receta con deuda IRREDUCIBLE: declarar algo que el store no
provee rompería el build en vez de arreglarlo. Esas van a tandas/needs-review-harkaq.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 07:04:58 -04:00
sergioandClaude Opus 4.8 895e8202fa harkaq: revisadas las 5 irreducibles — 2 recuperadas, 3 casos genuinos diagnosticados
Ninguna de las 5 necesitaba una receta nueva. Eran falsos irreducibles por
política incompleta + un caso real de de-Alpinización.

FALTABAN 2 SONDAS EN LA POLÍTICA: /usr/bin/cpp (frontend del preprocesador de
gcc, mismo grupo que gcc/c89/c99) y /usr/bin/getent (utilidad NSS de musl).
hammer NO las construye ⇒ se deniegan y clasifican (D3), como gcc. Sin ellas en
`# expect`, arrastraban la receta entera a irreducible. Añadidas a base.policy y
a harkaq-farm-setup.sh (para los próximos workers). Re-clasifiqué SIN re-medir
(la clasificación lee la política; los veredictos crudos no cambian).

nm/ranlib NO se añadieron como sondas: los provee binutils ⇒ son DECLARABLES.
Ponerlos como esperadas dejaría a una receta usar el ranlib de Alpine en vez de
decir "declará binutils" — lo contrario de lo que se busca.

RECUPERADAS (declaradas y fuera de needs-review):
  dhcpcd → make, pkgconf     strace → make

QUEDAN 3, cada una una historia distinta (README en needs-review):
  ncurses  fs.make_dir /usr/lib — ESCRITURA en install, no lectura de Alpine
           (DESTDIR de la receta), NO de-Alpinización.
  mtdev    config.guess/sub del autoconf de Alpine — LA ÚNICA deuda de soberanía
           genuina del barrido (parchar mtdev o escribir recipes/autoconf.toml).
  perl     /etc/hosts,/etc/resolv.conf — config de sistema para tests de red; el
           build completa igual. Runtime base o denegación benigna, no Alpine.

Resultado del barrido completo: de 83 recetas, la deuda de soberanía REAL es UN
caso (mtdev/autoconf). Todo lo demás era declarable o sondas.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 06:44:20 -04:00
sergioandClaude Opus 4.8 7206626e25 harkaq: el disparo de cosecha es loop nohup, NO cron (arje-zero es PID1)
El laptop corre arje-zero como init (no systemd, systemctl no existe) y no tiene
crond activo. El crontab que instalé anoche corrió 0 veces: validé que la LÍNEA
corría a mano, nunca que un daemon fuera a dispararla. Mismo patrón que me mordió
toda la sesión — validar la pieza, no el sistema.

Disparo real: scripts/farm/harvest-loop.sh con setsid nohup. Sobrevive el fin de
sesión, no un reboot (eso pediría un servicio /etc/init.d, con root).

+ 2 bugs del harvest arreglados: flock anti-solape (dos ciclos editando+commiteando
a la vez = árbol corrupto) y el rescate rechazaba recetas legítimas por la línea
en blanco que add-deps añade (el + vacío no matcheaba [deps].build).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 06:31:34 -04:00
sergioandClaude Opus 4.8 7ec2e86b7b harkaq: declarar deps medidas por el kernel (cosecha automática)
Cosecha desatendida de la campaña harkaq. Cada dep de acá la denunció el audit de
Landlock en un build real: el kernel vio al build usarla sin declararla, y el
store del hub confirma qué artefacto la provee (deuda DECLARABLE, §4.5).

Recetas:coreutils elfutils expat file flex gawk

No se tocó ninguna receta con deuda IRREDUCIBLE: declarar algo que el store no
provee rompería el build en vez de arreglarlo. Esas van a tandas/needs-review-harkaq.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 06:30:36 -04:00
sergioandClaude Opus 4.8 8f94b8a251 harkaq: declarar deps medidas por el kernel (cosecha automática)
Cosecha desatendida de la campaña harkaq. Cada dep de acá la denunció el audit de
Landlock en un build real: el kernel vio al build usarla sin declararla, y el
store del hub confirma qué artefacto la provee (deuda DECLARABLE, §4.5).

Recetas:sassc scdoc sed shadow socat sqlite tar tmux tree tzdata util-linux vim wget when which wpa_supplicant xorriso xz zlib

No se tocó ninguna receta con deuda IRREDUCIBLE: declarar algo que el store no
provee rompería el build en vez de arreglarlo. Esas van a tandas/needs-review-harkaq.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 06:21:14 -04:00
sergioandClaude Opus 4.8 21ac060c4b harkaq: declarar deps medidas por el kernel (cosecha automática)
Cosecha desatendida de la campaña harkaq. Cada dep de acá la denunció el audit de
Landlock en un build real: el kernel vio al build usarla sin declararla, y el
store del hub confirma qué artefacto la provee (deuda DECLARABLE, §4.5).

Recetas:gettext-tiny giflib git gnupg gperf gzip htop iproute2 jq kbd libassuan libcap libevent libffi libgcrypt libgpg-error libksba libnl libpng libsass libsodium libssh2 libudev-zero libusb libwebp libxml2 libyaml linux-generic linux-headers linux-metal linux-pam linux lz4 mandoc mtools musl nano npth openssh openssl parted pciutils pcre2 pigz procps-ng python3 readline rsync samurai ca-certificates curl doas dosfstools e2fsprogs fontconfig freetype

No se tocó ninguna receta con deuda IRREDUCIBLE: declarar algo que el store no
provee rompería el build en vez de arreglarlo. Esas van a tandas/needs-review-harkaq.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 23:27:57 -04:00
sergioandClaude Opus 4.8 593a11c034 harkaq: gate 2 de la campaña — ¿el binario TIENE la jaula dentro?
La golden hornea un target/release/hammer viejo y el rsync excluye /target ⇒ si
el cargo build del provisioning no corre, el worker construye alegremente SIN
JAULA y produce cero veredictos.

PASÓ: la primera corrida molió 2 recetas con un binario del 29/06 (0 ocurrencias
de 'harkaq' en strings) y las marcó 'sin veredicto' como si fuera culpa de las
recetas. Ocho horas así son la noche entera perdida, y el log habría dicho
'salteada' — nunca 'estoy ciego'. Es el falso Hermetico de D9 mudado al
orquestador: la ausencia como respuesta tranquilizadora.

Ahora aborta si strings no encuentra harkaq en el binario. Mismo criterio que el
gate del ABI: no medir es mejor que creer que se mide.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 23:24:58 -04:00
sergioandClaude Opus 4.8 32e8ac557d harkaq: runbook de la campaña desatendida (worker + cron, para retomar sin mí)
Estado escrito en el repo y no en mi cabeza: la campaña tiene que sobrevivir a
que yo desaparezca al final del turno. Qué corre, dónde, cómo revisarlo por la
mañana, cómo pararlo, y los rastrillos que ya se pagaron (el cd del cron, el
pull sucio, cargo fuera del PATH).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 23:09:32 -04:00
sergioandClaude Opus 4.8 052f4f765e harkaq: Cargo.lock — libc en hammer-build (SIGTERM para el lector)
Sin esto el `git pull --rebase` del cron de cosecha falla con 'unstaged changes'
y la cosecha nunca sincroniza con el otro agente: idle silencioso de noche, que
es justo lo que la campaña existe para no tener.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 23:07:25 -04:00
sergioandClaude Opus 4.8 f783f0107d harkaq: campaña desatendida — medir→declarar→verificar, sin regex y sin preguntas
El problema real no es el coste de la tanda: es que una pregunta a las 3am son 8
horas de idle. Estas 3 piezas están hechas para que la noche no se desperdicie.

  harkaq-campana.sh   (worker) bucle autónomo: construye cada receta bajo la
                      jaula y guarda los veredictos crudos. Idempotente, saltea
                      lo medido, duerme y re-escanea. NUNCA bloquea esperando: un
                      build que falla no detiene la cola (y su veredicto interesa
                      igual — es cuando más importa saber qué tocó fuera). Gatea
                      por ABI>=7: moler la noche para producir "no sabemos" es
                      peor que no moler.
  harvest-harkaq.sh   (hub, cron) hermano de harvest-go.sh: baja veredictos,
                      clasifica contra el store COMPLETO, aplica las deps
                      DECLARABLES y commitea con `git add` explícito. La deuda
                      IRREDUCIBLE NO se toca (declarar algo que el store no
                      provee rompe el build en vez de arreglarlo) → needs-review.
  harkaq-add-deps.py  editor de recetas conservador: idempotente, preserva las
                      deps existentes, y ANTE LA DUDA NO TOCA (valida que el
                      resultado siga parseando como TOML y no encoja). Corre de
                      noche sobre la fuente de verdad del catálogo: un fichero mal
                      editado a las 3am no da un error, da una receta corrupta que
                      nadie mira hasta el lunes.

POR QUÉ NO HAY REGEX EN EL CAMINO CRÍTICO: intenté sacar la lista de "a quién le
falta declarar make" con uno y falló dos veces en la misma tarde. `\bmake\b`
colaba `cargo-make` (el guión ES límite de palabra). La versión estrecha perdía
LAS CINCO recetas donde harkaq había medido la deuda de verdad (`compile = "make
…"`: el carácter previo es una comilla). El número bailó 69→45→99 según el
retoque. Construí una herramienta de medición y después intenté adivinar con un
regex — la lista buena la da el kernel. El regex queda sólo para ORDENAR la cola.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 22:53:57 -04:00
sergioandClaude Opus 4.8 1e0bc98ad4 matar gcc: rollout de cmake HECHO en la granja — y los consumidores no hacían falta
cmake reconstruido en un worker efímero (regla: la cadena GUI no se rebuildea en
el laptop, el zig-skew rompe cairo) y cosechado al hub:
    b3:834132e7…-cmake   NEEDED = sólo libc.musl-x86_64.so.1
El viejo (99864dcc…, con libstdc++.so.6 + libgcc_s.so.1) queda en el store por si
algo lo referencia.

LOS 10 CONSUMIDORES NO SE RECONSTRUYERON, Y NO HACE FALTA. El fix quita la
dependencia de RUNTIME del artefacto DE CMAKE. Los consumidores sólo lo usaron
como HERRAMIENTA DE BUILD — sus artefactos no linkean libstdc++. Rebuildearlos
sólo daría frescura de hash, y eso pasa solo en su próximo build. Confundir "usó
la herramienta" con "linkea la librería" habría costado un rebuild de gtk4 para
nada. (Yo mismo había propuesto los 11; el radio real es 1.)

REGALO DEL ROLLOUT: el worker (Ubuntu 24.04, ccx23) y el laptop (CachyOS)
produjeron cmake con el MISMO HASH, bit a bit — el invariante central de hammer
confirmándose entre dos máquinas distintas sin que nadie lo buscara. Y como los
bytes son idénticos, el NEEDED del worker queda verificado por transitividad: no
hizo falta readelf allá (que además no está instalado en la golden).

Limpieza: removido store/834132e7…-cmake-nogcc (mi artefacto experimental).
harkaq-suggest INDEXA el store, así que un artefacto huérfano aparecería como
"proveedor" de paths y ensuciaría los diagnósticos.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 20:53:11 -04:00
sergioandClaude Opus 4.8 ee51e5d596 harkaq: el kernel de hammer ya trae Landlock — ABI 7 verificado BOOTEANDO (Fase 1 precond. 1)
recipes/linux.toml: -e SECURITY -e SECURITY_LANDLOCK -e AUDIT. Era lo único que
faltaba para que harkaq corra DENTRO de hammer (VM/metal) y no sólo en el laptop
y la granja. El CONFIG_LSM del defconfig ya lista `landlock` de primero ⇒ bastó
encenderlo, sin tocar la cadena de LSMs.

AUDIT se fija explícito aunque ya viniera =y por defconfig: sin él el kernel no
emite un solo registro y harkaq certificaría TODO como hermético en silencio
(§3.4). Es la precondición de la que cuelga la evidencia; no se deja al azar de
un default.

VERIFICADO BOOTEANDO, no leyendo el .config — que dice lo que se compiló, no lo
que el kernel hace al arrancar. Misma disciplina de §3.1 (el ABI se consulta por
syscall, jamás por versión) llevada a la verificación: el único que sabe si
Landlock está vivo es el kernel vivo. scripts/harkaq/vm-abi-probe.c es un /init
de initramfs mínimo que pregunta y apaga:

    ===== HARKAQ EN EL KERNEL DE HAMMER =====
    LANDLOCK ABI = 7
    audit de denegaciones (>=7): SI
    =========================================

Kernel nuevo: b3:f2583d61… (el hash cambia, como se esperaba; el viejo
34755ff2… decía "# CONFIG_SECURITY_LANDLOCK is not set").

Con esto las 4 precondiciones de la Fase 1 están cerradas y harkaq corre en las
tres máquinas del proyecto: laptop (ABI 10), granja (ABI 7 tras el bump de la
golden) y el kernel propio de hammer (ABI 7).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 20:13:39 -04:00
sergioandClaude Opus 4.8 caa23f9ab7 harkaq: seccomp implementado (D4) — denylist, no allowlist; el hash no se mueve
D4 declaraba seccomp "obligatorio, no opcional" y harkaq-exec tenía CERO
seccomp: el documento afirmaba algo que el código no hacía. Cerrado.

CORRECCIÓN DELIBERADA A D4: pedía ALLOWLIST por syscall, se implementó DENYLIST.
Un allowlist para builds ARBITRARIOS (compiladores, make, shells, linkers, perl)
es un blanco móvil que cada herramienta nueva rompe — el riesgo del §7 ("los
falsos positivos matan proyectos de sandboxing") aplicado a las syscalls, y con
peor final: un build que muere por una syscall legítima no da un diagnóstico
útil, da un misterio. Lo PELIGROSO sí es enumerable y estable: no hay build
honesto que cargue módulos, haga kexec o attachee un ptrace.

Denegadas: io_uring_*, ptrace, process_vm_{readv,writev}, bpf, userfaultfd,
keyctl/add_key/request_key, {init,finit,delete}_module, kexec_*,
perf_event_open, mount/umount2, open_tree/move_mount/fs*, setns.
pivot_root NO: bwrap lo usa ANTES de llegar a harkaq-exec.

EPERM y no KILL: matar deja un cadáver sin explicación; EPERM deja al build
fallar donde corresponde y al log decir por qué. Se instala DESPUÉS de
no_new_privs y de Landlock, justo antes del exec, y se hereda por fork/exec como
el dominio (D5). Si el kernel lo rechaza NO se corre el build (D7: media jaula
creyéndose entera es peor que ninguna).

Chequeo de arquitectura antes del número de syscall: los nros son POR ARCH y sin
el check un binario i386 podría colar otra syscall con el mismo número — el error
clásico de los filtros seccomp a mano.

COMPROBADO: ptrace → EPERM bajo la jaula (control positivo), y un build REAL de
zlib sale Hermetico ×3 con el hash del artefacto IDÉNTICO al de antes de seccomp
(b3:adc5c251…). Añadir media jaula no movió un byte — como debe ser: esto recorta
superficie de escape, no cambia el build.

El --seccomp <fd> de bwrap quedó SIN USAR: harkaq-exec ya corre dentro y con
no_new_privs puesto, así que instala el filtro él mismo — una pieza menos de
plumbing y el filtro queda al lado de la política que lo justifica.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 19:31:58 -04:00
sergioandClaude Opus 4.8 8f7109f4e9 harkaq: el barrido queda en 0 IRREDUCIBLES — perl ya existía (§4.11)
La única deuda irreducible del barrido (§4.10) era /usr/bin/perl en
ca-certificates y curl. Dos hallazgos al abrirla:

1. EL COMENTARIO DE ca-certificates.toml YA LO DECÍA, escrito por quien la portó:
   "El resto del build (mk-ca-bundle.pl → cert.pem → split-ca-bundle.sh) usa el
   perl + coreutils del rootfs". La deuda estaba escrita EN PROSA y era invisible
   para el sistema; harkaq la convirtió en un veredicto. Es la tesis del §0 en una
   línea: no hace falta que nadie DESCUBRA nada, hace falta que la máquina pueda
   VER lo que ya se sabía.

2. LA RECETA TAMBIÉN EXISTÍA: recipes/incoming-kde/perl.toml, importada el 13/07
   para la campaña KDE (syntax-highlighting e intltool exigen perl). CUARTA
   convergencia independiente: dos campañas necesitaban el mismo binario y
   llegaron por caminos que no se hablan.

Construye tal cual (b3:c7a899bd…) y con el artefacto en el store:
    /usr/bin/perl → declarar dep: perl     exit=0 ⇒ CERO deuda irreducible

EL BARRIDO DE 24 RECETAS QUEDA EN 0 IRREDUCIBLES. La métrica del §7 (<5%) se
cumple midiendo lo que la métrica quería medir: cosas que no sabemos construir.
Resultado: ninguna.

Receta promovida a recipes/perl.toml (no había canónica ⇒ sin colisión). Lo que
queda es mecánico y no es diseño: declarar `make` en las ~10 recetas que lo usan
y `perl` en ca-certificates/curl. OJO: eso re-hashea sus artefactos y son
paquetes del base-system (índice firmado 748) ⇒ decisión de rollout, no un sed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 18:51:32 -04:00
sergioandClaude Opus 4.8 13233ee4e9 harkaq: primer barrido en la granja — la deuda irreducible de la muestra es perl (§4.10)
harkaq-farm-setup.sh: provisiona un worker para barrer (idempotente; gatea por
ABI>=7 y aborta si no llega — con la golden vieja el barrido daría SinEvidencia
en TODO). Deriva el runtime base DEL ROOTFS DEL WORKER, no copia el del laptop:
es por-rootfs (§4.3) y los sonames dependen de la versión de Alpine.

Barrido: 24 recetas, 14 con veredicto. Primer número crudo: 4 irreducibles (29%).
ERA FALSO, y por dos motivos propios:

1. GAP DE POLÍTICA. Los `list` salían sólo de los ancestros de la clausura ⇒ una
   receta SIN deps (bash) no generaba ni uno y todo escaneo del árbol caía como
   denegación (/usr/lib). Listar NO es leer: Landlock separa READ_DIR de
   READ_FILE ⇒ la estructura del árbol es CONTRATO. Se puede `ls /usr/lib` sin
   leer un solo fichero no declarado; la deuda es leer lo ajeno, no saber que
   existe. Idem /var/tmp: con --tmp-overlay / es scratch descartable, como /tmp.
2. La heurística del catálogo es por NOMBRE y un fichero no se llama como su
   paquete: /usr/bin/ranlib lo trae `binutils`, /usr/bin/diff lo trae
   `diffutils`. El único que sabe la verdad es el STORE (conoce la lista de
   ficheros de cada artefacto) — y el worker tiene 103 artefactos contra los
   cientos del hub.

⇒ EL WORKER MIDE, EL HUB CLASIFICA. Misma separación que lector/clasificador: el
que tiene el privilegio —o los datos— hace lo mínimo. Reclasificado en el hub:
    bash             ranlib,/usr/lib,/var/tmp → nada (gap de política)
    doas             /usr/bin/diff            → nada (diffutils lo provee)
    ca-certificates  /usr/bin/perl            → /usr/bin/perl
    curl             /usr/bin/perl            → /usr/bin/perl

RESULTADO: la deuda irreducible de toda la muestra es UN path — /usr/bin/perl
(2 de 14 = 14%). No hay recipes/perl.toml ni artefacto: deuda genuina y nombrada.
Todo lo demás era declarable (make ×10, ranlib→binutils, diff→diffutils).

Sigue por encima del <5% del §7, pero el perfil es el que importa: NO hay cola
larga de sorpresas. La deuda de un catálogo entero se resume en "declarar make" y
"no tenemos perl".

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 17:50:34 -04:00
sergioandClaude Fable 5 ea28a3dbcc docs: SDD 17 — cierres de frontera priorizados × cruce con crates de tawasuyu
Los 10 cierres que caen solos de los 3 invariantes (bit-repro, CAS,
clausura-como-política), cada uno cruzado con el crate/arquitectura
reusable de tawasuyu que lo abarata. Top-2: consenso de reconstrucción
(fork-proof+umbral) y hammer why-differs (format+reconcile).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-15 17:36:13 -04:00
sergioandClaude Opus 4.8 cba59e829b harkaq: la granja VPS ya puede ser el compilador continuo — golden bumpeada a 6.17 (ABI 7)
El VPS va a ser el compilador permanente ⇒ harkaq TIENE que correr ahí o el
frente queda como decoración de laptop. Verificado de punta a punta en un worker
efímero desde la golden, no en el papel:

  antes:   kernel 6.8.0-134  →  Landlock ABI 4  →  sin audit  →  SinEvidencia siempre
  después: kernel 6.17.0-40  →  Landlock ABI 7  →  AUDIT ✓

`apt install linux-image-generic-hwe-24.04` (archivo estándar de Ubuntu 24.04, sin
PPA ni cambiar distro), reboot, y la cadena COMPLETA de evidencia corre igual que
en el laptop:
    same-exec 2 registros · new-exec 0 (el ciego) · new-exec-logon 4
    domain=14e9f83c2 blockers=fs.read_file path="/etc/passwd" dev="sda1" ino=133259
El store del catálogo (103 artefactos) sobrevivió el bump intacto.

NUEVA GOLDEN: snapshot 408909310 "hammer-golden-harkaq-6.17-2026-07-15".
farm-up.sh pasa a usarla por defecto. La vieja (405120842) queda como fallback.

+ harkaq-uapi.h — EL HALLAZGO QUE IMPORTA para un compilador continuo: **el kernel
y los headers envejecen por separado**. El worker corre 6.17 pero su
linux-libc-dev es 6.8 y NO define NADA de lo necesario: ni los flags de log de ABI
7/8, ni AUDIT_LANDLOCK_ACCESS/DOMAIN (¡los tipos de registro!), ni IOCTL_DEV de
ABI 5. El kernel puede; el compilador no sabe pedírselo.

Es el mismo error de §3.1 al revés: allá, deducir el ABI de la versión del kernel;
acá, de la versión de los headers. NINGUNA de las dos dice la verdad — la única
fuente es el syscall en runtime. Estas constantes son números de contrato de UAPI,
estables por definición, seguros de fijar con #ifndef.

Sin esto harkaq sólo compila en distros con headers al día, que es justo lo que un
compilador continuo NO puede exigir. Y el modo de falla habría sido el peor: sin
AUDIT_LANDLOCK_ACCESS el lector filtraría por un número que no conoce y vería CERO
denegaciones — el falso `Hermetico` de D9, esta vez por headers viejos.

Nota: ABI 7 da el audit (lo que el proyecto necesita); TSYNC (ABI 8) pide 7.0 y no
está — es robustez opcional de D5, no un bloqueo.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 17:33:14 -04:00
sergioandClaude Opus 4.8 b122ded31f matar gcc: cmake deja de arrastrar el runtime C++ de Alpine (§4.9) + /proc es contrato
harkaq (§4.6) dejó UN solo caso irreducible en el primer barrido: brotli pidiendo
libstdc++.so.6.0.34 + libgcc_s.so.1. Pero brotli es C, no C++ — la libstdc++ no
era suya: era de `cmake`, su dep de build.

  store/99864dcc…-cmake/usr/bin/cmake
      NEEDED: libstdc++.so.6, libgcc_s.so.1, libc.so

"gcc retenido para {kernel, cmake}" no era una concesión de BUILD-TIME como
sonaba: el artefacto de cmake arrastraba el runtime C++ de Alpine hacia dentro de
CADA build que lo declarara como dep. Un agujero de soberanía viajando por el
grafo de deps, invisible en la receta del consumidor. harkaq lo señaló desde el
consumidor, que es donde se ve.

EL ARREGLO NO TOCA EL COMPILADOR — gcc sigue compilando cmake (camino
conocido-bueno; zig c++ segfaultea el cmake mínimo). Sólo deja de enlazar su
runtime en dinámico:
    CXX='g++ -static-libstdc++ -static-libgcc'  LDFLAGS='-static-libstdc++ -static-libgcc'

Medido:
  antes   NEEDED: libstdc++.so.6, libgcc_s.so.1, libc.so
  después NEEDED: libc.musl-x86_64.so.1     (y corre: cmake version 3.31.6)

EL PAGO: brotli —el único irreducible del barrido— pasa a Hermetico ×3 fases,
artefacto sellado b3:bc900676…. El barrido queda 0 irreducibles de 6. El caso que
iba a contar contra el <5% no era una receta mal escrita: era una herramienta de
hammer filtrando Alpine.

+ /proc como superficie de CONTRATO (lo destapó el configure de brotli, que lee
/proc/cpuinfo y /proc/meminfo): bwrap monta un /proc FRESCO dentro del pidns, no
sale del rootfs Alpine y no ve al host ⇒ contrato, no deuda. Mismo caso que
/cache. El hash del artefacto es idéntico antes y después de añadirlo: cambia el
veredicto, no el build.

COSTO DEL ROLLOUT: cambiar recipes/cmake.toml re-hashea cmake y sus 3
consumidores (brotli, libjpeg-turbo, libtiff = 6 sellados). Radio chico, PERO
libjpeg-turbo y libtiff son la cadena GUI y la regla es no rebuildearla en el
laptop (zig-skew rompe cairo) ⇒ el rebuild va al worker.

LO QUE NO CIERRA: /usr/bin/gcc, c89, c99, ldd y el plugin LTO (§4.7) siguen
siendo SONDAS — la jaula las deniega, los builds completan igual, y denegarlas es
lo correcto. El gcc de Alpine sigue en el rootfs y sigue haciendo falta para
{kernel, cmake} en BUILD-TIME. Lo cerrado es la filtración a RUNTIME, que es la
que contaminaba artefactos.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 17:19:50 -04:00