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>
This commit is contained in:
2026-07-05 17:57:12 -04:00
co-authored by Claude Opus 4.8
parent e72a630d31
commit 66241c31a4
+120 -3
View File
@@ -251,6 +251,115 @@ ambición máxima sigue abierta.
---
## H4 — Configuraciones compartidas: compatibles, completas y seguras (la aplicación)
**De dónde sale.** No de la revisión externa: del **uso**. Un usuario modifica su
sistema; cada configuración suya es un *conjunto de modificaciones*. Quiere compartirlas
por la malla y, al **buscar** una ajena, saber si puede adoptarla — que sea **compatible,
completa y segura**. H4 aterriza toda la maquinaria de H2/H3 sobre ese caso concreto.
**La observación que lo hace tratable.** "Compatible" parece semántica difusa, pero el
usuario lo definió con dos ejemplos que el modelo trata **mecánicamente distinto**:
- *Logo.* Ya cambié el logo; bajo una config que **también** cambia el logo. No es un
error: ambas **escriben la misma superficie** con contenido distinto. La resolución es
una **elección**, no un rechazo.
- *Wayland.* Modifiqué el protocolo de Wayland; bajo algo que **depende de** el Wayland
stock. Su dependencia **no resuelve** contra mi versión ⇒ incompatible.
Entonces "compatible" = **colisión sobre la misma superficie**, y son dos cosas: colisión
de *escritura* (elección) y dependencia *insatisfecha* (rechazo). El eje nuevo que H4
agrega es un **espacio de nombres de slots** que cada modificación **reclama** (escribe,
`slot → Id`) y **requiere** (depende, `slot → Id` a una versión exacta). Con esos dos
conjuntos, compatible queda **definido de forma dura**, y sus dos mitades **reusan
primitivas ya verdes**:
| propiedad del usuario | qué la garantiza | dónde (ya construido) |
|---|---|---|
| **segura** | verificar reproduciendo — rechaza el resultado envenenado | `verificar_paquete` (H2c) |
| **completa** | cierre transitivo presente — sin referencia colgante | `ingerir_paquete` (H3c) |
| **compatible** | requisitos resueltos + reclamos disjuntos | **H4, nuevo** |
La definición dura de compatibilidad de una config `C` contra mi estado `E`:
> (1) **Requisitos** (caso wayland): `∀ (slot, id) ∈ C.requiere : E[slot] = id`. Un slot que
> resuelve a otra versión (o falta) es **incompatible** — el análogo de sistema a la
> `RefColgante` de H3c: una superficie requerida que resuelve a otros bytes.
> (2) **Reclamos** (caso logo): `∀ slot ∈ C.reclama : E[slot]` ausente **o** igual en `Id`.
> Un slot ya ocupado por otro contenido es **colisión = elección**, no error.
**Tickets:**
- **H4a** ✅ — (prototipo, `wawa-memo/src/compat.rs` + `tests/h4.rs`, 7 tests; **52 verdes**
en el crate) El modelo de slots corriendo. `Config { reclama, requiere }` sobre el mismo
espacio de hashes que H3; `evaluar(estado, config) → Veredicto ∈ {Compatible, Colision,
Incompatible}` es el chequeo **local y reproducible** ("verificar, no confiar" de SDD 09,
ahora sobre la topología de superficies). Verificado: el caso **logo** da `Colision` (y la
vía por defecto no pisa sin elección explícita); el caso **wayland** da `Incompatible`
(requisito que no resuelve, o ausente); la compatibilidad **entre dos configs**
(`conflicto`) es simétrica y ve tanto reclamos que se pisan como requisitos cruzados; y
`filtrar` **particiona una búsqueda** de la malla en `{compatibles, elegibles,
incompatibles}` — la respuesta concreta a "cuando busco, saber cuáles puedo adoptar". El
test de composición muestra que *compatible no basta*: la misma config puede pasar el
chequeo de slots y ser inservible por **incompleta** (paquete manipulado ⇒ `RefColgante`)
o **insegura** (resultado afirmado falso ⇒ recomputar lo rechaza) — las tres propiedades,
un solo hash.
- **H4b** — (siguiente) subir el modelo de slots de `wawa-memo` (host/std) a la **receta**
real: que un `.swm`/receta declare `reclama`/`requiere` (fuera de `hash_inputs`, misma
disciplina que la evidencia de H1 y la procedencia de H3a). El `Estado` instalado es la
`InstalledDb` de Etapa F vista como `slot → Id`. Entonces `hammer install <config-de-malla>`
corre `filtrar` contra el estado local antes de tocar nada. Frontera: definir el
**espacio de slots** del sistema (qué es una "superficie": un fichero, un módulo wasm de
wawa, un componente) — ahí está el trabajo de diseño real, no en el álgebra de
compatibilidad (que ya está).
**Frontera honesta.** H4a demuestra el *álgebra* sobre hashes abstractos; lo que **no**
resuelve es la **granularidad de los slots** — dos configs pueden no colisionar en el slot
`wayland-protocol` pero sí en un byte compartido más fino si el slot está mal cortado. El
modelo es correcto para cualquier corte; **elegir el corte** (grano de superficie) es H4b y
es donde vive el juicio. Y la compatibilidad es **estructural** (¿resuelven los hashes?), no
**semántica** (¿las dos modificaciones *tienen sentido* juntas?): esto último sigue fuera
del alcance, como debe.
---
## La ambición, hasta el final: config = paquete = función = proceso
H4 no es un anexo: es la **prueba de que la tesis de §H3 sirve para lo que un usuario hace
de verdad.** Y empuja el colapso que H3 dejó abierto un paso más. Recapitulando lo que ya
está verde y unificado bajo **un solo tipo de objeto — el hash**:
- una **función** es `blake3(bytecode)` (H3b),
- un **programa** es `blake3(árbol de hashes)` (H3b) con dependencias por hash *dentro* del
bytecode (H3c: el Merkle-DAG),
- un **paquete** viaja como bytes canónicos con `blake3(bytes) = id` y se verifica standalone
(`wawa-verifica`, H3c),
- y ahora una **configuración** es un conjunto de `(slot → hash)`: reclamos y requisitos que
se resuelven exactamente como las `Ref` de H3c (una dependencia insatisfecha *es* una
referencia colgante, sólo que a nivel de sistema).
Es decir: **una config y un programa son el mismo objeto visto por dos lentes.** Un programa
compone funciones por hash; una config compone superficies del sistema por hash. `RefColgante`
gobierna la completitud de ambos; reproducir gobierna la seguridad de ambos. El colapso
*paquete = función* ya no es aspiración — H4 lo mostró incluyendo la config como caso.
**Lo que sigue abierto es el último lado: el proceso.** Un sistema configurado *corriendo* es
un proceso, y un proceso —en la visión H2— *es* su módulo más su log de entradas
(`MonotonicLog`, PLAN-OS-CRDT E1): mover o reconstruir un proceso = copiar `(módulo, log)` y
re-ejecutar determinísticamente (H2, regalo 3). Si un **estado del sistema** es un
`Estado = slot → Id` (H4) y su **historia** es un log monótono de configs aplicadas, entonces
un sistema-en-ejecución colapsa al mismo objeto: **un hash del código + un log de entradas**,
reproducible, migrable, memoizable. Ahí `config = paquete = función = proceso` deja de ser
lema y es *el mismo tipo direccionado por contenido en las cuatro lentes*.
Eso **no está construido** y no lo promete este doc: el lado "proceso" necesita el replay del
`MonotonicLog` sobre estado real (efectos, I/O), que es exactamente lo que H2 excluye de "puro"
y lo que vive en el plan OS-CRDT del otro agente. Pero la forma es clara y las tres primeras
lentes ya coinciden en el hash. La ambición máxima —**una distro donde instalar una config,
compilar una función, empaquetar y correr un proceso son la misma operación sobre el mismo
espacio de nombres**— sigue siendo ambición; su núcleo, cada vez menos.
---
## Orden y dependencias
```
@@ -260,6 +369,9 @@ H2a (auditar determinismo wasm) ──► gate de todo H2 (spike wawa)
H3a (design-doc) ──► registrar la visión, barato
└► H3b ✅ (experimento wasm-por-función) [sobre H2 puro: núcleo Unison verde]
└► H3c ✅ (linker de contenido: imports por hash, Merkle-DAG intra-función)
└► H4a ✅ (config = conjunto de slots por hash: compatible/completa/segura)
└► H4b (subir el modelo de slots a la receta/.swm real)
└► [proceso] replay del MonotonicLog ──► plan OS-CRDT (otro agente)
```
Recomendación: **H1 primero** (empuja la frontera que ya tenemos, sin apuestas). **H2a** en
@@ -274,6 +386,11 @@ no construir. H2c y H3b son futuro condicionado a verdes previos.
"verificado bajo supuestos", no "invulnerable".
- **No promete memoización de malla sin determinismo probado** (H2a es el gate).
- **No promete el colapso Unison.** H3b (✅) demostró el *núcleo* (definir por hash, nombres
como metadata, actualizar sin romper, componer por hash) y H3c (✅) el *grano intra-función*
(función llama función por hash: el Merkle-DAG de código); el colapso total
(paquete = función = proceso, grano sub-función) sigue siendo ambición, no promesa.
como metadata, actualizar sin romper, componer por hash), H3c (✅) el *grano intra-función*
(función llama función por hash: el Merkle-DAG de código) y H4a (✅) que una *config* es el
mismo objeto (superficies por hash; una dependencia insatisfecha = referencia colgante de
sistema). El colapso total (config = paquete = función = **proceso**, grano sub-función)
sigue siendo ambición, no promesa: falta el lado proceso (replay del `MonotonicLog`).
- **No promete compatibilidad semántica.** H4 decide compatibilidad **estructural** (¿resuelven
los hashes de las superficies?), no si dos modificaciones *tienen sentido* juntas. Y el
**grano de los slots** (qué es una "superficie") es diseño abierto (H4b), no resuelto.