1# sheafsync
2
3Motor en Rust para decidir, **con demostración y no a ojo**, cuándo un conjunto de
4réplicas local-first puede operar **sin coordinación** y cuándo no — y, cuando la
5respuesta es "sí, dentro de límites", proveer el mecanismo que lo garantiza.
6
7**Estado: CERRADO.** La API de M4 (`adapter::SovereignAccount`) está **congelada y
8en producción** (consumida por Tawasuyu). El resto es historia de diseño y
9exploración, documentada con honestidad. Ver [Trabajo opcional](#trabajo-opcional-eventual)
10para lo que queda por tocar, si algún día hace falta.
11
12- **89 tests** (unitarios + `proptest` + integración), `cargo clippy` limpio.
13- Rust edición 2021. Dependencias: `petgraph`, `nalgebra`, `thiserror`, `proptest` (dev).
14
15---
16
17## Qué es (y qué terminó siendo)
18
19El proyecto nació como una apuesta topológica: modelar el estado distribuido como
20un **haz celular** y usar su cohomología (`H¹`) para detectar obstrucciones a la
21consistencia. Esa apuesta **se puso a prueba honestamente** y, capa tras capa, el
22resultado fue humillante y valioso a la vez: **la maquinaria de haces casi nunca
23fue lo que sostuvo la garantía.** El valor real vino de implementar bien prior-art
24de sistemas (CRDTs, CALM, I-confluence, escrow / Bounded Counter) y de **nombrar
25con precisión las fronteras** (CAP, supuestos físicos).
26
27El registro completo de ese arco —incluyendo cada reclamo que hubo que retirar—
28está en los documentos de diseño. Se conserva a propósito: **un cuaderno de
29laboratorio confiable vale más que un resultado fuerte reclamado de más.**
30
31### El arco, sin adornos
32
33| Fase | Prometía | Terminó siendo | Doc |
34|---|---|---|---|
35| MVP lineal (M0–M3) | detectar coordinación vía `H¹` | medía **topología** (`H¹=β₁`); falso-positivo en ciclos | `DESIGN.md`, `DISCREPANCIES.md` |
36| Retículos / Tarski (T5–T7) | cerrar la brecha | **circular** — el encoding leía la etiqueta | `ADDENDUM.md`, `FLIPS.md` |
37| I-confluence (T8) | superar a CALM | **detección**, no evitación; punto ciego | `T8.md`, `STRONG_RESULT.md` |
38| Escrow (T9) | evitación real | **certificado** sobre el politopo, ruteo por el grafo | `T9.md`, `COMPARISON.md` |
39| Escrow dinámico (T10) | seguro en snapshot | seguro bajo **concurrencia / partición / crash** | `T10.md`, `AVAILABILITY.md` |
40| Fuente monótona (T11) | seguro sin más | seguro **módulo un supuesto físico nombrado** (CAP) | `T11.md`, `BOUNDARY.md` |
41| Adaptador (M4) | — | **API congelada, contrato honesto, rehúsa sin durabilidad** | `M4.md` |
42| Reach multi-invariante | novedad vía haces | corrección = escrow; el haz colapsa al router escalar | `REACH.md` |
43
44### El terminus honesto
45
46> **Seguridad coordination-free módulo un supuesto físico nombrado:** cada celda de
47> presupuesto tiene un único escritor durable. Bajo él, el certificado aplica sin
48> coordinación. Roto (clon), el daño está **acotado a una celda por clon no
49> detectado y se detecta al reconectar** — nunca silencioso ni ilimitado.
50
51No "seguro pase lo que pase", sino "seguro salvo esta condición, y aquí está
52exactamente qué cuesta romperla".
53
54---
55
56## La contribución real y defendible
57
58Lo que sí queda en pie, probado:
59
60- **Evitación de coordinación por escrow**, con **certificado dinámico** que
61 aguanta concurrencia, partición y crash (`escrow`, `durable`, `router`).
62- **Ruteo y localización de presupuesto por el grafo de comunicación real** — el
63 único uso legítimo del Laplaciano (el mismo que en el MVP era un detector
64 defectuoso, reciclado como ruteador).
65- **Fronteras dichas, no escondidas:** disponibilidad limitada bajo partición
66 (`AVAILABILITY.md`), doble gasto por clon acotado+delatado pero no prevenible
67 (`BOUNDARY.md`).
68
69Nada de esto es novedad teórica (es O'Neil 1986 / Balegas 2015 / Bailis 2014 bien
70implementado); la aportación es la **implementación correcta, topología-consciente
71y honesta sobre sus límites**.
72
73---
74
75## Mapa de módulos (`src/`)
76
77**Motor lineal (MVP, control histórico):**
78`cell` · `nerve` · `sheaf` · `cohomology` · `verdict` · `oracle` · `linalg` · `gf2` · `error`
79
80**Pista de retículos (T5–T7, control histórico):**
81`lattice` · `tarski` · `native`
82
83**Evitación real (T8–T11, el núcleo vivo):**
84`invariant` (I-confluence + `GlobalInvariant`) · `escrow` (`EscrowState`, `Budget`,
85`Identity`) · `router` (`BudgetRouter`) · `durable` (WAL) · `fencing` (época + clon)
86
87**Fachada en producción:**
88`adapter` (`SovereignAccount` — **API congelada**)
89
90**Experimental (no en producción):**
91`reach` (multi-invariante + Laplaciano de haces vectorial)
92
93---
94
95## Contrato de M4 (lo que Tawasuyu consume)
96
97`adapter::SovereignAccount` — detalle completo en `M4.md`:
98
99- **Requiere** WAL durable de `spent` por dispositivo, e identidad como conjunto de
100 dispositivos. Si el sustrato no lo da, `open` **rehúsa** (`AdapterError`) — no
101 entrega una cuenta insegura.
102- **Garantiza** seguridad coordination-free del invariante (`value ≥ floor`).
103- **Acota y detecta** (no previene) el doble gasto por clon: `sync` devuelve
104 `CloneDetected` como **alarma**, no recuperación.
105- **Limita** la disponibilidad bajo partición al presupuesto local; `spend`
106 devuelve `Rejected { spendable }` en vez de sobregirar o colgarse.
107
108```rust
109let cuenta = SovereignAccount::open(caps, invariante, pesos, aristas)?; // o rehúsa
110match cuenta.spend(dispositivo, monto) {
111 SpendOutcome::Spent => { /* local o rebalanceado */ }
112 SpendOutcome::Rejected { spendable } => { /* fail-safe: gasta ≤ spendable */ }
113}
114```
115
116---
117
118## Build y test
119
120```sh
121cargo build
122cargo test # 89 tests
123cargo clippy --all-targets
124cargo run # demo del arco: M1 lineal → contraste Tarski → discrepancia buena
125```
126
127---
128
129## Trabajo opcional (eventual)
130
131Nada urgente. Si algún día hace falta:
132
1331. **Multi-invariante para Tawasuyu.** Si aparece la necesidad de varios contadores
134 acoplados, endurecer `reach::CoupledInvariants` (el certificado del politopo) +
135 `d_r` routers escalares hacia una API estable. **No** vía el Laplaciano de haces
136 (colapsa al router escalar con restricciones identidad — ver `REACH.md`), salvo
137 que surja un caso real de coupling en bases incompatibles.
1382. **Restricciones no monótonas** (`C` con signos mixtos): el escrow no las cubre;
139 es un problema abierto que necesitaría reservas de otro tipo (`REACH.md`).
1403. **`diffuse` proactivo en producción:** el ruteo que mitiga (no elimina) el límite
141 de disponibilidad bajo partición existe y está probado (`router`), pero no está
142 cableado en el ciclo de vida del adaptador. Es rendimiento, no corrección.
143
144Cada uno está descrito con su frontera honesta en el doc citado. Ninguno cambia el
145terminus: la garantía es la que es, con los límites nombrados.
README.md
sheafsync
Motor en Rust para decidir, con demostración y no a ojo, cuándo un conjunto de
réplicas local-first puede operar sin coordinación y cuándo no — y, cuando la
respuesta es "sí, dentro de límites", proveer el mecanismo que lo garantiza.
Estado: CERRADO. La API de M4 (adapter::SovereignAccount) está congelada y
en producción (consumida por Tawasuyu). El resto es historia de diseño y
exploración, documentada con honestidad. Ver Trabajo opcional
para lo que queda por tocar, si algún día hace falta.
- 89 tests (unitarios +
proptest + integración), cargo clippy limpio.
- Rust edición 2021. Dependencias:
petgraph, nalgebra, thiserror, proptest (dev).
Qué es (y qué terminó siendo)
El proyecto nació como una apuesta topológica: modelar el estado distribuido como
un haz celular y usar su cohomología (H¹) para detectar obstrucciones a la
consistencia. Esa apuesta se puso a prueba honestamente y, capa tras capa, el
resultado fue humillante y valioso a la vez: la maquinaria de haces casi nunca
fue lo que sostuvo la garantía. El valor real vino de implementar bien prior-art
de sistemas (CRDTs, CALM, I-confluence, escrow / Bounded Counter) y de nombrar
con precisión las fronteras (CAP, supuestos físicos).
El registro completo de ese arco —incluyendo cada reclamo que hubo que retirar—
está en los documentos de diseño. Se conserva a propósito: un cuaderno de
laboratorio confiable vale más que un resultado fuerte reclamado de más.
El arco, sin adornos
| Fase | Prometía | Terminó siendo | Doc |
| MVP lineal (M0–M3) | detectar coordinación vía H¹ | medía topología (H¹=β₁); falso-positivo en ciclos | DESIGN.md, DISCREPANCIES.md |
| Retículos / Tarski (T5–T7) | cerrar la brecha | circular — el encoding leía la etiqueta | ADDENDUM.md, FLIPS.md |
| I-confluence (T8) | superar a CALM | detección, no evitación; punto ciego | T8.md, STRONG_RESULT.md |
| Escrow (T9) | evitación real | certificado sobre el politopo, ruteo por el grafo | T9.md, COMPARISON.md |
| Escrow dinámico (T10) | seguro en snapshot | seguro bajo concurrencia / partición / crash | T10.md, AVAILABILITY.md |
| Fuente monótona (T11) | seguro sin más | seguro módulo un supuesto físico nombrado (CAP) | T11.md, BOUNDARY.md |
| Adaptador (M4) | — | API congelada, contrato honesto, rehúsa sin durabilidad | M4.md |
| Reach multi-invariante | novedad vía haces | corrección = escrow; el haz colapsa al router escalar | REACH.md |
El terminus honesto
Seguridad coordination-free módulo un supuesto físico nombrado: cada celda de
presupuesto tiene un único escritor durable. Bajo él, el certificado aplica sin
coordinación. Roto (clon), el daño está acotado a una celda por clon no
detectado y se detecta al reconectar — nunca silencioso ni ilimitado.
No "seguro pase lo que pase", sino "seguro salvo esta condición, y aquí está
exactamente qué cuesta romperla".
La contribución real y defendible
Lo que sí queda en pie, probado:
- Evitación de coordinación por escrow, con certificado dinámico que
aguanta concurrencia, partición y crash (
escrow, durable, router).
- Ruteo y localización de presupuesto por el grafo de comunicación real — el
único uso legítimo del Laplaciano (el mismo que en el MVP era un detector
defectuoso, reciclado como ruteador).
- Fronteras dichas, no escondidas: disponibilidad limitada bajo partición
(
AVAILABILITY.md), doble gasto por clon acotado+delatado pero no prevenible
(BOUNDARY.md).
Nada de esto es novedad teórica (es O'Neil 1986 / Balegas 2015 / Bailis 2014 bien
implementado); la aportación es la implementación correcta, topología-consciente
y honesta sobre sus límites.
Mapa de módulos (src/)
Motor lineal (MVP, control histórico):
cell · nerve · sheaf · cohomology · verdict · oracle · linalg · gf2 · error
Pista de retículos (T5–T7, control histórico):
lattice · tarski · native
Evitación real (T8–T11, el núcleo vivo):
invariant (I-confluence + GlobalInvariant) · escrow (EscrowState, Budget,
Identity) · router (BudgetRouter) · durable (WAL) · fencing (época + clon)
Fachada en producción:
adapter (SovereignAccount — API congelada)
Experimental (no en producción):
reach (multi-invariante + Laplaciano de haces vectorial)
Contrato de M4 (lo que Tawasuyu consume)
adapter::SovereignAccount — detalle completo en M4.md:
- Requiere WAL durable de
spent por dispositivo, e identidad como conjunto de
dispositivos. Si el sustrato no lo da, open rehúsa (AdapterError) — no
entrega una cuenta insegura.
- Garantiza seguridad coordination-free del invariante (
value ≥ floor).
- Acota y detecta (no previene) el doble gasto por clon:
sync devuelve
CloneDetected como alarma, no recuperación.
- Limita la disponibilidad bajo partición al presupuesto local;
spend
devuelve Rejected { spendable } en vez de sobregirar o colgarse.
let cuenta = SovereignAccount::open(caps, invariante, pesos, aristas)?; // o rehúsa
match cuenta.spend(dispositivo, monto) {
SpendOutcome::Spent => { /* local o rebalanceado */ }
SpendOutcome::Rejected { spendable } => { /* fail-safe: gasta ≤ spendable */ }
}
Build y test
cargo build
cargo test # 89 tests
cargo clippy --all-targets
cargo run # demo del arco: M1 lineal → contraste Tarski → discrepancia buena
Trabajo opcional (eventual)
Nada urgente. Si algún día hace falta:
- Multi-invariante para Tawasuyu. Si aparece la necesidad de varios contadores
acoplados, endurecer
reach::CoupledInvariants (el certificado del politopo) +
d_r routers escalares hacia una API estable. No vía el Laplaciano de haces
(colapsa al router escalar con restricciones identidad — ver REACH.md), salvo
que surja un caso real de coupling en bases incompatibles.
- Restricciones no monótonas (
C con signos mixtos): el escrow no las cubre;
es un problema abierto que necesitaría reservas de otro tipo (REACH.md).
diffuse proactivo en producción: el ruteo que mitiga (no elimina) el límite
de disponibilidad bajo partición existe y está probado (router), pero no está
cableado en el ciclo de vida del adaptador. Es rendimiento, no corrección.
Cada uno está descrito con su frontera honesta en el doc citado. Ninguno cambia el
terminus: la garantía es la que es, con los límites nombrados.