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>
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>
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>
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>
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>
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>
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>
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>
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>
El repo temporalio/cli tiene 3 mains bajo cmd/ (gen-commands, gen-docs,
temporal); detect_go_main elegía gen-commands ⇒ binario equivocado, quedó
en needs-review. Fix: flags=["./cmd/temporal"] apunta al CLI real (verificado
vía API de GitHub en el commit fijado). El binario se llama `temporal`, así
que agrego el alias temporal-cli→temporal al gate de harvest-go.sh (mismo
patrón que opentofu→tofu). Vuelve a recipes/incoming-go para que el worker
lo selle y la cosecha lo promueva.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Cierra la tesis de §H3: un programa entero viaja como Paquete verificable
en dos capas — integridad del código por el hash (tamper-evident sin firmar)
+ verdad del resultado por reproducción (H2c). Implementación en tawasuyu
wawa-memo/src/programa.rs (8 tests, total wawa-memo 30).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
El núcleo del modelo Unison (definir por hash, nombres como metadata,
actualizar sin romper, componer por hash) se sostiene sobre el runtime
de wawa. Implementación en tawasuyu wawa-memo/src/base.rs (8 tests verdes).
Frontera: es el subconjunto que wasm+BLAKE3+H2 sostienen, no el colapso
total paquete=función=proceso (sigue ambición, no promesa).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
En wawa-memo: sellado de portabilidad (Portable/SoloLocal, sella el vector
NaN cross-arch) + modelo de confianza (ingerir_ajeno verifica reproduciendo,
rechaza envenenamiento). Transporte de malla diferido al otro agente
(PLAN-OS-CRDT E3). Tests h2c.rs verdes.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
El prototipo vive en tawasuyu/03_ukupacha/wawa/wawa-memo (crate host/std):
reproduce la vía pura del kernel y monta la clave del contrato §4 sobre un
LwwMap. Test §5 verde (72 casos byte-idénticos, Hit/Miss, fallas cacheadas,
E-invalidación, merge de malla). Desbloquea H2c.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Extiende el parser ELF (parse_elf_needed→parse_elf_info): además de DT_NEEDED,
recorre .dynsym (DT_SYMTAB) y extrae los símbolos EXPORTADOS (defined +
global/weak). Nuevo término `exports:<path>` en el mini-lenguaje de queries;
fluye por el bus (query expr) sin cambios. Metadata descriptiva, fuera de
hash_inputs (misma disciplina que la evidencia de H1). Refactor: helper
vaddr_to_file_off compartido por strtab/symtab + cstr_at.
nsyms vía layout convencional (strtab sigue a symtab); best-effort → [] si no
se puede acotar con seguridad. Validado end-to-end: 2873 símbolos reales de
/lib/libc.so.6 (aguanta glibc y musl). Tests: term-parse + missing-file +
host-gated real-.so. Workspace verde (33 suites).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Design-doc de la idea 3 (SDD 15 §H3): decide NO reescribir la unidad de
compilación. Puente barato = procedencia por-símbolo como metadata (extender
el parser ELF parse_elf_needed para emitir exports de .dynsym), fuera de
hash_inputs — misma disciplina que la evidencia de H1. El grano fino real
(función-por-hash) se difiere a H3b sobre wasm, gateado por el determinismo H2.
Marca §H3a ✅ en la frontera.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
El subconjunto puro ya existe (ejecutar_dinamico/_v2, linker vacío); H2a lo
sella con un contrato de clave de caché + hash-de-entorno. Deliverable en
tawasuyu/03_ukupacha/wawa/SDD-determinismo.md. Desbloquea H2b (prototipo de
memoización local blake3(módulo)⊕blake3(entrada)→salida).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
La evidencia corre del lado del BUILD (hammer-agent no depende de hammer-build:
separación PROPONE/CONSTRUYE). Piezas:
- proto: RecipeInline lleva `evidence`; Event::BuildReady lleva
`verdict: Option<EvidenceVerdict>` (+ EvidenceCheckVerdict). Ambos con
skip_serializing_if ⇒ wire compatible con clientes pre-H1c.
- hammerd/bus: run_compile ejecuta la evidencia declarada tras sellar el
artefacto (run_evidence vía swm_bridge::recipe_from_source_patch) y adjunta
el veredicto en BuildReady. Si ni se pudo ejecutar ⇒ veredicto fallido
sintético (no pasa en silencio). El lab reporta; el gate vive en el agente.
- client: compile() devuelve CompileOutcome { artifact, verdict }.
- orchestrator: VERIFY lee el veredicto; si all_passed=false empuja
VerifyCheck::fail y ABORTA antes de hidratar (artefacto sellado, no toca el
sistema). Nuevo constructor VerifyCheck::fail.
Tests: roundtrip del veredicto en proto; stub-bus refleja evidencia→verdict;
nueva prueba de integración orchestrator_evidence_gate (veredicto fallido ⇒
run() aborta con "no se propone" y no hidrata). Suite completa verde (33 suites).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
El verificador que corre cada check en el sandbox reproducible y falla ⇒ no proponer
(SDD 15 §H1). Piezas: (1) hammer-core: EvidenceCheck::evaluate(exit, stdout) -> CheckOutcome
(pura, testeada: exige expected_exit y, si hay, blake3(stdout)==expected_output) +
ArtifactHash::of_bytes. (2) hammer-build: Sandbox::run_capture -> CmdOutcome (captura stdout
completo + exit, tee de stderr) + run_evidence(recipe,cfg,store) -> EvidenceReport que
reproduce el artefacto (cache-hit), levanta un sandbox con fuente+build-deps+el artefacto
instalado como capa overlay (binarios en PATH) y corre cada check. (3) CLI: swm-verify
--evidence reconstruye cada source_patch y corre run_evidence; imprime veredicto por check +
estrato máximo alcanzado; exit != 0 si algún check falla. Es un runner de comandos con hash
del output, no un framework — la confianza vive en el checker.
Verificado e2e: tree con [[evidence.checks]] cmd-exit 'tree --version' → pack cache-hitea
(evidencia no cambia el hash) → swm-verify --evidence corre el check en el sandbox: pasa (exit
0) y falla con expected_exit=7 (exit 1, 'NO proponer'). Núcleo puro con tests unitarios.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Frontera AI-nativa SDD 15 §H1. Agrega `Evidence { checks: Vec<EvidenceCheck> }` a Recipe
(TOML) y a Mutation::SourcePatch (.swm YAML): cada check es {kind, cmd, expected_exit,
expected_output?} con kind ∈ {cmd-exit, proptest, contract, kani} (estratos de confianza
crecientes, EvidenceKind: Ord). DECISIÓN CLAVE: la evidencia NO entra en hash_inputs —
certifica comportamiento, no identidad ⇒ no mueve el artifact_hash (baseline de
reproducibilidad intacto). Round-trip completo: from_recipe (forward) + swm_bridge
synthesize_recipe (reverse) + camino de pack (cli). verify_schema valida forma (cmd no
vacío, expected_output con prefijo b3:). El checker que EJECUTA la evidencia es H1b; el
cableado al Orchestrator VERIFY es H1c (marcado con evidence: _). Tests: recipe + swm,
incl. que la evidencia no cambia el hash. Sin warnings clippy nuevos.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
appstream (dep compartida de libadwaita + demos GTK) usa libcurl en su meson (meson.build:171)
y declaraba curl+zlib sin openssl; libcurl.pc trae Requires: zlib,openssl ⇒ sin openssl.pc en
el sandbox, appstream falla y bloquea toda la cadena aguas arriba. Raíz real del muro que se
veía como 'libadwaita openssl not found' (el que fallaba era appstream, dep de libadwaita).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Las 4 recetas que dependen de curl (libadwaita + adwaita-hello/hammer-edit/sourceview-hello)
declaraban curl+zlib pero no openssl; libcurl.pc trae Requires.private: openssl (y libcurl.pc
sin openssl.pc en el sandbox ⇒ meson falla 'Dependency lookup for libcurl failed: openssl not
found'). Mismo patrón que harfbuzz/fontconfig. openssl ya está en el catálogo (recipes/openssl.toml).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
El patch anterior desactivaba el subdir cairo-script ENTERO para esquivar el link de pixman de
los ejecutables csi-*, pero eso quitaba libcairoscript + cairo-script-interpreter.pc, que los
demos GTK (gtk4-hello/adwaita-hello/sourceview-hello/hammer-edit) piden por pkg-config. Ahora el
subdir se construye (librería estática + .pc) y solo los EJECUTABLES csi-* se envuelven en
if false. cairo-trace queda saltado (nada pide su .pc). Verificado: cairo-script-interpreter.pc
presente en el artefacto sellado.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
build-farm.sh asumía 'sin colisión entre recetas distintas', falso para deps transitivas
compartidas no selladas: dos consumidores (p.ej. libadwaita/gtksourceview) construyen gtk4 a
la vez en el mismo sources/gtk4-<sha>/output ⇒ 'Some other Meson process is already using this
build directory'. Fase 1b: tras el pool paralelo, reintenta EN SERIE los fallos con firma de
colisión — la dep ya la selló el ganador ⇒ cache-hit y compila. Un pase basta (cada build
arrastra sus deps). Sólo reintenta colisiones, no MSRV/dep-faltante reales.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
freetype se compila --with-png ⇒ freetype2.pc trae Requires: zlib, libpng. harfbuzz tenía
zlib pero no libpng ⇒ pkg-config no resolvía freetype2 y meson setup abortaba
('freetype2 required but not found'). Mismo patrón que fontconfig (80a9cac). Con cairo ya
construyendo (patch ctime_r), esto destraba harfbuzz→pango (ambos sellan).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
El probe has_function('ctime_r') de meson corre sin prefix de header ⇒ prototipo desnudo
que bajo zig-cc/gcc+musl choca con el builtin y FALLA ⇒ cairo-ps-surface.c:105 define un
fallback static que colisiona con <time.h> (error duro, tanto zig como gcc; _GNU_SOURCE en
c_args no alcanza). El patch fuerza HAVE_CTIME_R=1 tras el loop. Segundo hunk: salta los
ejecutables util csi-*/cairo-trace, que no linkean libpixman-1.a bajo la estrategia
no_fallback de zig — son dev-tools, no la librería que pango/gtk4 consumen. Resultado:
cairo 1.18.4 sella desde fuente (store c7b8703f), destraba el rebuild de la cadena GUI que
el drift de fontconfig/freetype había forzado. Cierra la Opción A (inviable) con la B real.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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>
freetype se compila --with-png ⇒ freetype2.pc trae `Requires: libpng` (y libpng→zlib).
Sin esos .pc en el sandbox, pkg-config no resuelve freetype2 y ./configure aborta con
"freetype2 >= 21.0.15 not met". Reproducible sólo al rebuildear freetype canónica (antes
tapado por cache-hit). fontconfig vuelve a construir desde fuente.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
recipes/freetype.toml referencia pcf-family-names/subpixel/table-validation-modules.patch
pero vivían solo en incoming-clib/ (patch-huérfano) ⇒ freetype no packeaba y bloqueaba
toda la cadena GUI (pango/gtk4/... dependen de freetype). Copiados a recipes/.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sus deps foundational ya publicadas ⇒ el orden de dependencias resolvió y packean+firman.
Sin colisión con canónicas. Quedan en incoming-clib las 8 GUI meson pesadas (gtk4/pango/
libadwaita/gtksourceview + demos) y las 13 variantes colisionantes.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sus recetas canónicas referenciaban cmake-version.patch / fix-test-musl.patch pero los
ficheros habían quedado en tandas/staged-2026-06-26/ (patch-huérfano de una promoción
vieja) ⇒ pack fallaba. Movidos junto a su receta; ambos publican+firman ahora.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Cierra el desfase receta/repo: 15 recetas que ya construyen y están publicadas+firmadas
en dist/repo pero seguían en la cola de staging. Sin colisión con canónicas (guarda de
build-farm). Los .patch viajan con su receta. Quedan en incoming-clib las 13 variantes
colisionantes (build-deps del stack GUI) y las 14 GUI deep-dep sin publicar aún.
brotli fribidi gettext-tiny giflib glib gperf graphene harfbuzz itstool
libjpeg-turbo libsass libtiff libxmlb lz4 sassc
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>