Commit Graph
493 Commits
Author SHA1 Message Date
sergioandClaude Opus 4.8 9305bb16e9 instalador: TUI interactivo (disco/identidad/locale/tamaños) sobre el autoinstalador
hammer-install crece una cara humana sin tocar la mecánica EFI/BIOS validada:
- sin device + TTY ⇒ interactive_setup: detecta discos (/sys/block, marca el
  montado como posible medio live), el usuario elige + confirma escribiendo el
  nombre del disco, y recoge hostname / credencial de root (contraseña vía
  cryptpw o authorized_keys) / zona horaria (best-effort si hay tzdata) /
  teclado / tamaños de / y /store.
- apply_post_install_config escribe hostname+hosts, reemplaza el hash de root en
  /etc/shadow, instala authorized_keys, symlinkea localtime y deja install.conf;
  se llama tras la copia en AMBAS ramas (EFI y BIOS).
- con device ⇒ autoinstalador de siempre (iso/efi-install-test intactos); la
  config sale de env (HAMMER_HOSTNAME/ROOT_PW/ROOT_AUTHKEYS/TZ/KEYMAP).
- iso-image.sh: ISO instalador sin AUTO_INSTALL ahora recibe con la TUI en la
  consola (INSTALLER_INTERACTIVE, default on) y ofrece reiniciar/caer al live.

Verificado: scripts/install-tui-test.sh (4/4, dry-run con sysfs+rootfs falsos)
+ iso-install-test.sh VERDE end-to-end en QEMU (autoinstalador con la config
nueva bajo busybox real → disco bootea solo y sirve SSH).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-10 22:22:21 -04:00
sergioandClaude Opus 4.8 494d3fd615 granja: cargar cola base-system — 18 esenciales del userland foundational
Los huecos reales para una distro completa (el sistema ya está: bootstrap/
self-host/kernel/init/EFI/paquetería). Cola aislada en incoming-clib:
git rsync bash ca-certificates sudo doas util-linux sed tzdata e2fsprogs
dosfstools parted iproute2 iputils dhcpcd vim dbus foot. Import 18/18
(17 alpine + 1 nix), deps ya-canónicas podadas. Patches musl viajan.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-10 21:53:47 -04:00
sergioandClaude Opus 4.8 a5be781ef6 arranque-grafo: hammer boot menu — orquestador del menú + wiring en el init (ADR 0010)
hammer boot menu ata las tres piezas del contrato: emite el grafo → lanza el
compositor (mirada, --compositor configurable) → activa el nodo que el usuario
dejó en boot-select. Graceful: sin compositor (servidor headless) emite el grafo
y sigue el arranque. Refactor: activate_and_report compartido con boot activate;
--out/--select configurables (testeable sin /run/hammer root-only).

Wiring: iso-image INSTALLER=1 + install-image-efi bundlean el CLI hammer (static
musl) al sistema instalado (el producto trae arje-zero/hammerd pero no el CLI);
el wrapper /sbin/init lo invoca tras hammer-recover, salida al serial (no pinta
tty0 ⇒ respeta cero-parpadeo). Cierra la pieza #3 del handoff mirada (quién
lanza el menú en el boot): lo ownea hammer, desde el hook de init.

Tests: boot_menu.rs (3 caminos del glue: graceful/sin-selección/selección→activate)
+ efi-disk-boot-test asevera que el menú corre. Validado en OVMF: pivote →
INIT-OK → menú (emite boot-graph.json + saltea sin mirada) → arje-zero.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-10 21:30:30 -04:00
sergioandClaude Opus 4.8 c7d1d9cf5c arranque-grafo: paso 4 (cero-parpadeo) cerrado en el ADR 0010 (pasos 1–5 )
Validado por captura de framebuffer OVMF-GOP: el kernel metal con deferred-
takeover + quiet no toca el framebuffer (Δ=0). Falta sólo el seamless i915 y el
metal real.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-10 21:10:39 -04:00
sergioandClaude Opus 4.8 3ac329ec8f arranque-grafo: cero-parpadeo VERDE + fix marcador INIT-OK tras switch_root
efi-flicker-test valida por CONTRIBUCIÓN del kernel al framebuffer (2 capturas:
handoff-firmware vs post-boot; Δ≈0 ⇒ el kernel no tocó el FB). Con el kernel
metal cero-parpadeo: Δ=0.000 VERDE — el splash de la firmware sobrevive intacto,
sin texto de boot ni cursor (el kernel viejo saltaba de ~3 a ~11). No mide negro
absoluto: el splash de OVMF (TianoCore) daría falso-positivo y no existe en metal.

Fix: busybox switch_root NO mueve /dev ⇒ los wrappers /sbin/init montan devtmpfs
antes de tee'ar HAMMER-EFI-INIT-OK a /dev/ttyS0 (si no, el nodo no existe y el
marcador se perdía). efi-disk-boot-test VERDE con el kernel quiet.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-10 21:04:05 -04:00
sergioandClaude Opus 4.8 fd033fb920 efi-flicker-test: media de brillo vía %[fx:mean] normalizado (0..1)
El 1er número de identify -verbose varía por quantum (10.99 en PPM vs 0.129 en
PNG para la misma imagen); el normalizado 0..1 es fiable. Validado: negro→0,
texto→11, umbral 1.5 los separa.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-10 20:21:48 -04:00
sergioandClaude Opus 4.8 548f30b3ef linux-metal: cero-parpadeo — deferred-takeover + cmdline quiet (ADR 0010 paso 4)
CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER=y (fbcon no toca el framebuffer
hasta el primer output ⇒ pantalla negra desde la firmware hasta que mirada abre
el DRM). Cmdline horneada: quiet loglevel=3 vt.global_cursor_default=0, sin el
earlyprintk=efi,keep ignore_loglevel de bringup (forzaban salida y rompían el
deferred-takeover). Orden de consola: ttyS0 ÚLTIMO ⇒ /dev/console=serie ⇒ la
shell de arje-zero sale por serial, no pinta tty0 (pantalla). CONFIG_LOGO ya off.

Fix diagnosticado por captura de framebuffer en OVMF-GOP. Rebuild en curso.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-10 20:18:16 -04:00
sergioandClaude Opus 4.8 e80f15b6bc arranque-grafo: harness EFI robustos a quiet + efi-flicker-test (ADR 0010 paso 4)
Con el kernel metal cero-parpadeo (quiet), los marcadores serie kernel-side
(EFI-stub/Linux-version/EXT4) desaparecen. Los /init de pivote + /sbin/init
real ahora tee'an marcadores a /dev/ttyS0 (escritura al puerto directo, sortea
el printk ⇒ sobreviven quiet): HAMMER-EFI-DISK-PIVOT-OK + HAMMER-EFI-INIT-OK.
efi-disk-boot-test y efi-install-test pasan a apoyarse en ésos (kernel-side =
informativos). Compatible con el kernel viejo (verbose) también.

efi-flicker-test.sh: valida cero-parpadeo por captura de framebuffer OVMF-GOP
(media de brillo < umbral ⇒ pantalla negra, sin texto de boot). El seamless
i915 queda para metal Intel real.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-10 20:13:45 -04:00
sergioandClaude Opus 4.8 72af9a802f arranque-grafo: diagnóstico preciso del cero-parpadeo (ADR 0010 paso 4)
Evidencia por captura de framebuffer en OVMF-GOP: el kernel metal pinta todo
el log de boot sobre el FB gráfico (simpledrm 160x50). Quitar console=tty0 no
alcanza (VT_CONSOLE=y auto-registra); quiet/loglevel por LoadOptions no frena
(fbcon redibuja el ring buffer + ignore_loglevel horneado fuerza salida).

Fix identificado (requiere rebuild del kernel metal, cambia hash firmado):
CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER=y + cmdline horneada quiet
loglevel=3 vt.global_cursor_default=0 sin earlyprintk/ignore_loglevel
(CONFIG_LOGO ya off). Seamless i915 sólo validable en metal Intel real.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-10 20:02:17 -04:00
sergioandClaude Opus 4.8 6921dfead3 arranque-grafo: validación 2-stage del instalador live EFI en OVMF (ADR 0010 paso 5)
efi-install-test.sh cierra el lazo completo bajo UEFI (hermano de
iso-install-test.sh que es BIOS): (1) ISO live EFI=1 INSTALLER=1 AUTO_INSTALL
en OVMF con disco en blanco → hammer-install detecta /sys/firmware/efi y toma
la rama EFI (MBR+ESP-0xEF) desatendido → HAMMER-INSTALL-OK; (2) el disco
instalado bootea SOLO en OVMF → firmware → BOOTX64.EFI → pivote → arje-zero
PID1, sin GRUB. VERDE end-to-end.

Prueba el instalador live REAL corriendo dentro del live, no sólo sus
artefactos. ADR 0010: paso 5 cerrado salvo metal.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-10 18:32:13 -04:00
sergioandClaude Opus 4.8 4e00178fc5 arranque-grafo: rama EFI-stub en el instalador live (ADR 0010 paso 5)
hammer-live-install.sh detecta /sys/firmware/efi y ramifica a EFI-stub soberano:
MBR con ESP tipo 0xEF (UEFI arranca una ESP MBR igual que GPT ⇒ sólo busybox
fdisk/mkfs.vfat/mount, sin GPT-tool ni mtools en el live). Arma el mismo
initramfs de pivote (findfs LABEL=hammer-root → switch_root) que el builder
host-side; /sbin/init = wrapper hammer-recover→arje-zero (el pivote ya montó
store/estado por LABEL). La rama BIOS+GRUB queda intacta tras la detección.

iso-image.sh INSTALLER=1 bundlea el kernel metal EFI-stub (bzImage-efi) en el
payload; el genérico no sirve (no hornea initrd=/rdinit= en la cmdline).

MBR+ESP-EF spot-checked en OVMF (firmware → BOOTX64.EFI → pivote → arje-zero).
ADR 0010 actualizado: pasos 2 y 5 .

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-10 18:11:06 -04:00
sergioandClaude Opus 4.8 11ff41d614 arranque-grafo: install-to-disk EFI-stub soberano (ADR 0010 paso 5)
install-image-efi.sh arma una imagen GPT+ESP donde el bzImage metal ES el
binario EFI (\EFI\BOOT\BOOTX64.EFI, ruta fallback removible) — sin GRUB ni
systemd-boot. La cmdline horneada del kernel (initrd=/initramfs.cpio.gz
rdinit=/init) se activa al no haber LoadOptions; un initramfs mínimo de pivote
resuelve hammer-root por LABEL (findfs) y hace switch_root a la ext4 real.
Layout: ESP + hammer-root/store/state ext4 (mke2fs -d bajo unshare -r, ESP con
mtools de hammer). Cierra el paso 2 (initrd chico destraba EFI-stub) y el 5.

efi-disk-boot-test.sh valida en OVMF (sin -kernel): VERDE — firmware →
BOOTX64.EFI → pivote → arje-zero PID1. Marcadores serie deterministas (los dos
primeros bytes del handoff firmware→kernel son informativos; el veredicto se
apoya en el montaje/re-mount aguas abajo, prueba concluyente de la cadena).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-10 18:03:47 -04:00
sergioandClaude Opus 4.8 cf2e8bf44d mirada-usb: modo hardware nouveau para GTX 1060 (Pascal/GP106)
- Hornea firmware nvidia/gp106 (ctxsw/acr/sec2) descomprimido a .bin (nouveau da GL 3D).
- init: modo HARDWARE por defecto (WGPU_BACKEND=gl sobre gallium-nouveau, que da float16
  vía unpackHalf2x16; tapa lavapipe). Pascal no tiene NVK ⇒ greeter va por GL, no Vulkan.
- cmdline default = hardware; 'mirada.sw nouveau.modeset=0' = fallback software.
- CHIP/FW_SRC parametrizables para otras GPUs.

Regresión: el fallback software sigue levantando el compositor en la imagen final.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-10 17:05:23 -04:00
sergioandClaude Opus 4.8 c82588ced8 mirada-usb: imagen USB de prueba de mirada en GPU ajena (NVIDIA)
- recipes/mesa-swrast.toml: mesa softpipe hammer-nativo (sin LLVM) para render software.
- scripts/mirada-usb.sh: ensambla rootfs (dev-fs musl + hydrate mirada/seatd/libinput/
  mesa + overlay Alpine llvmpipe/lavapipe/nouveau + XKB + PAM + init seatd+compositor) y
  empaqueta la USB con linux-generic vía systemd-boot.
- docs/mirada-usb-nvidia.md: uso + estado.

Validado en QEMU virtio-gpu: el COMPOSITOR arranca entero (libseat→card0→GBM+EGL+
GlesRenderer→[8/8]→escritorio, acepta clientes, dibuja la ventana del greeter). El
GREETER (Vello) exige shaders float16 que llvmpipe/lavapipe NO dan ⇒ su login sólo
pinta con GPU real (nouveau+firmware, v2).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-10 14:20:46 -04:00
sergioandClaude Opus 4.8 4aaefa53e4 granja: mise 2026.7.0 al catálogo firmado (713) — cierra el bug vendor-clobber
El fix cargo_vendor_dir (b580c5b) destrabó mise: selló (ELF estático funcional,
mise 2026.7.0) y se promovió. Sale del diferido; queda en recipes/mise.toml con
[source] cargo_vendor_dir=.hammer-cargo-vendor. README del diferido actualizado.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-10 12:18:32 -04:00
sergioandClaude Opus 4.8 b580c5bfc5 fetch: cargo_vendor_dir per-receta — no pisar el vendor/ propio del proyecto
`cargo vendor vendor` borra lo que no reconoce del dir destino; proyectos que
commitean su PROPIO vendor/ (mise → vendor/aqua-registry, 3.1MB que build.rs lee)
lo perdían → build.rs falla 'No such file'. Nuevo campo opcional [source]
cargo_vendor_dir (default 'vendor', sin cambios para las ~200 recetas selladas)
manda el vendoreo cargo a otro dir; el .cargo/config.toml que emite cargo vendor
ya apunta ahí. mise.toml usa '.hammer-cargo-vendor'. Validado en vivo: aqua-registry
sobrevive + compila 591 crates pasando los muros previos (openssl vía rustls + AR).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-10 03:18:16 -04:00
sergio cee652717e granja: diagnóstico mise — bug de fetch (cargo vendor clobbea vendor/aqua-registry), no openssl
mise compila las 828 crates con rustls (openssl resuelto); el muro real es que
`cargo vendor vendor` de hammer borra el vendor/aqua-registry que mise commitea
(3.1MB que build.rs:357 lee). Documentado en el README del diferido. Fix pendiente:
override per-receta del destino de vendoreo cargo.
2026-07-09 23:50:41 -04:00
sergioandClaude Opus 4.8 5e8ff2348f granja: feroxbuster al catálogo firmado (712) — fix wrapper AR para Rust+sys-crate C
El default zig-cc exporta AR="zig ar" (con espacio); el crate `cc` lo ejecuta
como binario único y falla. Wrapper `.hammer-zig-ar` per-receta destraba el
sys-crate C. feroxbuster construye+sella; mise pasa openssl vía feature rustls
pero su bin final falla (giant aws-sdk/rattler, a diagnosticar). mdcat (openssl
transitivo) y jless (clipboard X11) diferidos a tandas/deferred-openssl-xcb/.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-09 22:42:32 -04:00
sergioandClaude Opus 4.8 ef86e4f986 arranque-grafo: current/default siempre presentes — interop con el lector de mirada
Verificado contra el parser REAL del otro agente (mirada-boot-core::BootGraph,
recién commiteado en tawasuyu): su struct declara `current: String` y
`default: String` OBLIGATORIOS (sin Option, sin default). Mi emisor los omitía
(`skip_serializing_if`) cuando no hay generación viva ⇒ en un sistema recién
instalado (cero upgrades) el JSON era `{"version":1,"nodes":[]}` y mirada
fallaba al parsear con "missing field `current`".

Fix del lado productor (adaptar la salida a la forma publicada del contrato):
BootGraph.current/default pasan a String, presentes siempre, cadena vacía = "sin
generación viva" (degrada limpio: default_index() de mirada cae al primer
bootable). Probado e2e pasando el JSON real de `hammer boot graph` (vacío +
poblado) por mirada-boot-core::BootGraph::from_path → ambos OK.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 22:34:49 -04:00
sergioandClaude Opus 4.8 3c343bee9a arranque-grafo: paso 3 del ADR 0010 — grafo de estados + hammer boot
El menú de arranque como navegación del grafo content-addressed de estados
(no una lista de kernels). Sube el modelo de generaciones in-place a un grafo
navegable y define el contrato de datos con mirada.

- hammer_upgrade::boot_graph: BootGraph/BootNode (formato exacto del contrato),
  build() arma el DAG desde las generaciones (id = of_tree sin b3:, parents =
  of_tree del padre, Base para la raíz del linaje), nodo Recovery sintético
  colgando de la viva, emit() atómico a /run/hammer/boot-graph.json.
- activate(): resuelve el id content-addressed a una generación y deja el
  sistema en ese nodo — no-op si ya viva, rollback paso a paso a un ancestro
  (reusa el rollback E4), recovery = un rollback, error honesto ante un "redo"
  hacia una generación huérfana (pide re-aplicar el árbol).
- CLI `hammer boot graph [--out|--stdout]` y `hammer boot activate <id>
  [--from-select]` (lee el id que mirada deja en /run/hammer/boot-select).
- Tests: DAG + activate a ancestro + recovery + redo-falla; rfc3339 sin deps.
  Validado e2e por el binario (3 generaciones → grafo → activar → recovery).

Cierra el lado `proceso` de SDD 15 §H4 (arrancar = activar un nodo del DAG).
mirada ya puede maquetar contra el grafo real (HANDOFF-arranque-grafo.md).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 20:36:04 -04:00
sergioandClaude Opus 4.8 7e21b0184b docs: ADR 0010 — arranque por grafo (menú de boot = navegación del grafo de estados, mirada+hammer)
El menú de arranque soberano (sin systemd-boot, sin GRUB) no es un port de GRUB: es la
navegación del grafo content-addressed de estados del sistema, renderizado por mirada
sobre KMS y respaldado por las generaciones/DAG de hammer. Cierra el lado 'proceso' de
SDD 15 §H4 (arrancar = activar un nodo). Fija la división de labores, el contrato de
datos (/run/hammer/boot-graph.json + hammer boot activate), el invariante cero-parpadeo
(simpledrm→i915 seamless) y la vía del loader (squashfs+overlay → initrd chico → EFI-stub
directo viable). Espejo en tawasuyu/HANDOFF-arranque-grafo.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 20:23:25 -04:00
sergioandClaude Opus 4.8 d9d891a64a granja: tanda VPS efímero 2026-07-06 — 7 promovidos al catálogo firmado (714)
dalfox/templ/errcheck/ineffassign/unconvert (Go) + dprint (Rust) + kyverno (Go),
construidos en un worker efímero hcloud, cosechados y firmados. Binarios musl-static
verificados: dalfox 3.1.2, templ v0.3.1020, dprint 0.55.1, ineffassign, y los
analizadores Go corren. feroxbuster/jless/mdcat/mise quedan staged (frontera *-sys:
openssl-sys/xcb desde fuente).

Fix farm-down: el promote final ahora recorre TODAS las colas del worker
(incoming/incoming-go/incoming-clib), no sólo recipes/incoming — los artefactos de
las otras colas se cosechaban pero no se firmaban.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 07:31:05 -04:00
sergioandClaude Opus 4.8 e2e5bc6f04 granja: fix host-key en workers efímeros — known_hosts a /dev/null
Los workers efímeros reciclan IPs de Hetzner. accept-new RECHAZA una clave de host
cambiada ⇒ el 'until ssh true' de farm-up colgaba para siempre en una IP reusada.
Como el modelo es hub-and-spoke (worker sin secretos, compute descartable) no hay
superficie MITM: saltamos verificación de host y no ensuciamos known_hosts.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 06:56:25 -04:00
sergioandClaude Opus 4.8 b90855dc30 granja: farm-run.sh — el ciclo efímero desatendido (up→esperar-ciclo→cosecha+destruye)
Encadena farm-up + farm-down con detección de fin-de-ciclo por el marcador 'ciclo
terminado' del worker-loop (cuenta ocurrencias en el journal, robusto a skew de reloj
y builds largos). 'Subí la cola, corré esto, se apaga solo al terminar.'

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 06:47:11 -04:00
sergioandClaude Opus 4.8 7891654810 granja: cola fresca para prueba VPS efímero — 11 recetas nuevas (dalfox/templ/errcheck/ineffassign/unconvert/kyverno Go + jless/dprint/mdcat/feroxbuster/mise Rust), purga cola stale ya-en-catálogo
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 06:46:39 -04:00
sergioandClaude Opus 4.8 3e520d4477 H4e: requires OBSERVADOS — dep de runtime divergida = incompatible (SDD 15 §H4)
Cierra la simetría de la vía observada: además de observar lo que un paquete escribe (H4c),
observa de qué depende A UNA VERSIÓN. Fuente observable sin declaración: el paquete se
construyó contra la versión de sus deps que hay en el repo (deps.runtime del .swm +
expected_hash de cada dep en el índice); si el usuario tiene esa dep instalada a OTRO hash,
la divergió -> rechazo duro. Es el caso wayland DERIVADO (el que H4b captura cuando el autor
declara requires, ahora leído del cierre).

- compat::observed_requires(swm, index) + version_conflicts(db, req) — reusan deps del .swm,
  expected_hash del índice e InstalledDb.hash (cero declaración nueva).
- Cableado en install (rechazo duro, no lo salva --force-slots) y en `hammer compat`.
- Verificado e2e real: `hammer compat` marca app INCOMPATIBLE por su dep wayland-protocol
  instalada a un hash divergido del repo (read-only, ve el source_patch sin construirlo).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 06:29:22 -04:00
sergioandClaude Opus 4.8 bbf4411af0 H4d: hammer compat <repo> — la búsqueda que particiona un repo contra lo instalado (SDD 15 §H4)
Responde la pregunta que arrancó §H4 ("cuando busco, ¿cuáles puedo adoptar?"): es el `filtrar`
del prototipo wawa-memo, ahora sobre el repo real y READ-ONLY (no construye ni toca nada).
Evalúa cada paquete contra el estado instalado y lo parte en {compatibles, requieren-elección,
incompatibles}, combinando la vía declarada (slots, H4b) con la observada (paths, H4c):
incompatible domina, colisión (de slot o fichero) -> elección, si no compatible.

Verificado e2e real (tests/compat_gate.rs): un repo de dos paquetes se parte correctamente
(uno choca de fichero con lo instalado -> elección; otro limpio -> compatible).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 20:23:19 -04:00
sergioandClaude Opus 4.8 9be7bdd707 H4c: superficies OBSERVADAS — colisión de fichero en install sin declarar slots (SDD 15 §H4)
La misma subida de H1 (prometer -> verificar), ahora sobre topología: la superficie más
común de un paquete es el conjunto de paths que escribe, y esos paths ya están declarados
en el .swm (target_bin + file_drop.path), conocidos ANTES de hidratar.

- compat::output_paths(swm) lee esos paths; compat::path_collisions(db, name, paths) detecta
  cuáles ya posee OTRO paquete instalado (reusa InstalledDb.files + owner_of, cero declaración
  nueva). Reinstalar el mismo paquete sobre sus propios paths NO colisiona (upgrade).
- Gate en `install` corre el chequeo observado JUNTO al declarado (H4b): pisar el fichero de
  otro paquete = caso logo a nivel de fichero (elección) -> aborta salvo --force-slots.
- Verificado e2e REAL (tests/compat_gate.rs, shell-ea al binario hammer): dos paquetes
  escriben /share/logo.png; el 2do aborta con "COLISIÓN de fichero" sin escribir nada; con
  --force-slots la elección se respeta y el fichero se escribe.

Un paquete SIN declarar slots ya participa del gate por lo que de verdad toca.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 20:17:17 -04:00
sergioandClaude Opus 4.8 27066776b3 H4b: gate de compatibilidad de configs en la receta real + hammer install (SDD 15 §H4)
Sube el modelo de slots de wawa-memo (prototipo host) a hammer:
- Recipe + source_patch del .swm llevan bloque `slots` {claims, requires} (slot->b3:…),
  FUERA de hash_inputs (topología ≠ identidad, no mueve el artifact_hash). Viaja intacto
  por los dos sentidos del puente (Recipe->.swm->Recipe): test de round-trip.
- InstalledDb registra claims por paquete + system_state() -> slot->hash (el Estado del gate).
- hammer-core::compat::evaluar(estado, slots) -> Veredicto {Compatible, Colision, Incompatible}
  (el álgebra probada en wawa-memo, sobre tipos de hammer).
- Gate en `hammer install`: antes de tocar nada evalúa el paquete contra el estado instalado.
  Incompatible (requisito sin resolver, caso wayland) -> aborta; Colisión (caso logo) ->
  aborta pidiendo elección salvo --force-slots; Compatible -> procede y registra los claims.

Plumbing propagado por los 5 sitios de Mutation::SourcePatch (from_recipe, swm_bridge,
export, bus, orchestrator). Tests: compat (4) + slots-no-en-hash/round-trip (2) +
system_state (1) + puente receta<->swm (1). Workspace compila y verde.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 20:10:02 -04:00
sergioandClaude Opus 4.8 66241c31a4 docs: SDD 15 §H4 — configs compartidas (compatible/completa/segura) + la ambición hasta config=paquete=función=proceso
Aterriza H2/H3 sobre el caso de uso real del usuario: compartir configuraciones
por la malla y, al buscar, saber que son compatibles/completas/seguras.
- H4a  (prototipo en wawa-memo): el modelo de slots reclama/requiere; compatible
  = colisión sobre la misma superficie (logo=elección, wayland=rechazo); completa y
  segura reusan H3c/H2c.
- H4b: subir slots a la receta/.swm real (InstalledDb como slot->Id).
- Sección "la ambición hasta el final": config y programa son el mismo objeto (hash);
  el último lado abierto es el proceso (replay del MonotonicLog, plan OS-CRDT).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 17:57:12 -04:00
sergioandClaude Fable 5 e72a630d31 docs: SDD 15 §H3c — formato de viaje canónico del Paquete + wawa-verifica (el puente concreto paquete↔función)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-05 10:31:28 -04:00
sergioandClaude Opus 4.8 5658e9337c granja: ciclo de vida EFÍMERO por hcloud API (farm-up/farm-down) + baseline €0
Migración del worker pet-24/7 a workers efímeros on-demand. farm1 (ccx23 persistente que
idleaba quemando plata) → snapshot golden 'hammer-golden-2026-07-05' (img 405120842: toolchain
+ store sellado horneados) → destruido. Baseline ahora 0 cajas / €0.

- farm-up.sh [N]: crea N workers desde el snapshot (cache-hit instantáneo del catálogo baked),
  los alinea con la cola actual del laptop, registra la flota en scripts/farm/.fleet (gitignored).
- farm-down.sh [name...]: cosecha el store (CAS, merge seguro) al laptop y DESTRUYE; promueve+firma.
  Orden seguro: sólo destruye si el pull de store salió bien.
- Validado punta a punta: up 1 → boot+cache+toolchain OK → down (cosecha+destruye) OK.
- Cron laptop harvest-go contra farm1 removido (la cosecha ahora la hace farm-down).

El worker sigue sin secretos (hub-and-spoke): compute puro y descartable.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 08:23:06 -04:00
sergioandClaude Opus 4.8 c516f9a5ea Etapa G (go): promovida tanda go-2026-07-05b al catálogo firmado (anew/chartmuseum/fortio/goldilocks/kluctl/nancy/pint/sake/timetrace) + gotools nuevo
Cosecha del ciclo que sacó al VPS del idle. Build-yield 20/22 en incoming-go (fallan
dolt/migrate, quedan staged). El resto de las 'frescas' del refeed resultaron duplicados
ya catalogados (hugo/delve/glow/sops/dnsx/kubeseal/dbmate/jsonnet-bundler/opa/scaleway-cli
promovidos en tandas previas).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 08:16:19 -04:00
sergioandClaude Opus 4.8 a917149116 Etapa G (go): re-alimento incoming-go — 13 recetas frescas al VPS idle (hugo/delve/glow/opa/scaleway-cli/kubeseal/dolt/dbmate/migrate/sops/gotools/dnsx/jsonnet-bundler)
El worker VPS estaba idle (load 0.01): las 3 colas eran 100% cache-hit (tanda go-2026-07-05b
sellada, incoming/ del otro agente, incoming-clib 21/21). Cosecho 13 attrs Go nuevos verificados
por nix eval (los alias de las listas de refeed daban 'ninguna fuente' por no ser attrs reales).
Import 13/13 nix + pin tag→SHA + rsync dirigido a la cola aislada incoming-go/.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 07:54:09 -04:00
sergioandClaude Fable 5 6e602707fd Etapa G (go): puredns diferido (go.mod 1.16 vs unsafe.Slice, clase gotop) — tanda 2026-07-05b queda 9/10 sellada
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-05 06:21:34 -04:00
sergioandClaude Fable 5 3ff1823e38 docs: SDD 15 §H3c hecho — el linker de contenido (grano intra-función por hash, Merkle-DAG de código)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-05 06:20:07 -04:00
sergioandClaude Fable 5 6c655642b6 Etapa G (go): re-cola kluctl (go build -o: main en ./cmd sellaba binario 'cmd') + tanda 2026-07-05b a mano (fortio/nancy/chartmuseum/sake/timetrace/anew/puredns/pint/goldilocks, tags por ls-remote) + werf diferido (gpgme como skopeo)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-05 05:57:09 -04:00
sergio b615adeaae Etapa G: cosecha-go finde (auto) — promovidos: bom crossplane-cli fabric-ai kn kubectl-neat oh-my-posh prometheus-blackbox-exporter prometheus-node-exporter timoni | review: kluctl(bin=cmd) 2026-07-05 05:55:34 -04:00
sergioandClaude Fable 5 3eda286806 Etapa G (go): +4 a la cola (kluctl/timoni/kubectl-neat/kn) — el corpus ya cubre 803 nombres, la cola larga adelgaza
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-05 05:43:27 -04:00
sergioandClaude Fable 5 f922450c62 Etapa G (go): bom flags=./cmd/bom (raíz = magefiles con build-tags que excluyen todo) + aws-vault/minikube diferidos (CGO: onepassword-sdk / libvirt)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-05 05:39:57 -04:00
sergioandClaude Fable 5 e4ef80b76e Etapa G (go): cosecha 20 + syft/traefik promovidos a mano (pack fallaba: patches no viajaban a recipes/ — fix en harvest-go) + pre-check por name interno del TOML (exporters) + re-cola crossplane-cli/fabric-ai/oh-my-posh con fixes (alias crossplane, ./cmd/fabric, -o oh-my-posh) + logs por-cola en build-farm
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-05 05:31:58 -04:00
sergio ec8bb17fd8 Etapa G: cosecha-go finde (auto) — promovidos: apko atlas crane flyctl go-migrate gomi grype jsonnet-bundler krew kubescape melange rekor-cli revive scorecard seaweedfs staticcheck step-ca tea trivy xq | review: crossplane-cli(bin=crossplane) fabric-ai(bin=code2context) oh-my-posh(bin=src) syft(pack) traefik(pack) 2026-07-05 05:27:49 -04:00
sergioandClaude Fable 5 5c4c2cd153 Etapa G (go): grype/traefik a vía Go auto (les faltaba deps.build=go, fases abuild llamaban go a ciegas) + dolt diferido (cgo→ICU externa, necesita receta icu4c)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-05 00:51:58 -04:00
sergioandClaude Fable 5 46a2d777d3 Etapa G (go): re-alimenta la granja — tanda 2026-07-05 (15 recetas: flyctl/kubescape/seaweedfs/melange/step-ca/scorecard/krew/…, 11 a mano por fetchgit-NAR + 4 import nix), aliases de gate (weed/migrate/jb/fabric/crank) y descarte flux=misimport DirectFB
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-05 00:47:09 -04:00
sergioandClaude Fable 5 3171dd59f9 Etapa G (go): triage cola envenenada del VPS — purga 25 (misimports/CGO/embed) + 10 fixes (subdir dolt-atlas-omp, crane ./cmd/crane, trivy GOEXPERIMENT=jsonv2, xq/tea/staticcheck/syft/apko a vía Go auto)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-05 00:35:40 -04:00
sergio ba1b91b225 Etapa G: cosecha-go finde (auto) — promovidos: ssh-vault talosctl | review: 2026-07-04 20:05:19 -04:00
sergio 83e41a2174 Etapa G: cosecha-go finde (auto) — promovidos: kubie skaffold | review: terrascan(smoke) 2026-07-04 08:05:32 -04:00
sergio 460a4bb7e3 Etapa G: cosecha-go finde (auto) — promovidos: gocron lego | review: flux(bin=fluxcomp) kics(bin=builder) 2026-07-04 07:35:16 -04:00
sergioandClaude Opus 4.8 d94544b34d Etapa G (go): re-alimenta la granja — tanda go-refeed (51 recetas) a incoming-go
Prioridad: el worker VPS nunca idle. Import de 108 candidatos Go nuevos (listas
fuel-go menos el corpus); 2 olas → 51 recetas importadas (yield ~47%), pusheadas
a la cola incoming-go del VPS. El worker las está moliendo (load ~17). Incluye
proyectos Go grandes (dolt/etcd/dagger/crane/gitlab-runner/forgejo) que vendorean
cientos de deps ⇒ builds largos. Crudas de nixpkgs (tag sin pin, algún misimport
Python que falla inocuo); la cosecha promueve sólo las que sellan + pasan smoke.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-04 07:33:19 -04:00
sergio 83219e17aa Etapa G: cosecha-go finde (auto) — promovidos: temporal-cli | review: 2026-07-04 07:12:09 -04:00