Estructura de módulos (§5) sin lógica todavía: cell, nerve, sheaf, cohomology, verdict, oracle, más error y linalg (trait LinAlg con impl f64 vacía). Deps petgraph/nalgebra/thiserror + proptest dev-dep. main imprime "hello sheaf"; test dummy pasa. DESIGN.md (antes sdd.txt). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
431 lines
21 KiB
Markdown
431 lines
21 KiB
Markdown
# SDD — Motor de Consistencia sin Coordinación
|
||
|
||
**Nombre en clave:** `sheafsync`
|
||
**Lenguaje:** Rust (edición 2021)
|
||
**Autor del diseño:** (tú)
|
||
**Estado:** Diseño v1 — listo para scaffolding con Claude Code
|
||
**Última edición:** 2026-07-01
|
||
|
||
---
|
||
|
||
## 0. Cómo usar este documento con Claude Code
|
||
|
||
Este SDD está escrito para ser el contexto raíz de un proyecto en Claude Code (CLI).
|
||
La forma recomendada de trabajarlo:
|
||
|
||
1. Coloca este archivo en la raíz del repo como `DESIGN.md`.
|
||
2. Arranca Claude Code en esa carpeta y dile: *"Lee DESIGN.md completo. No escribas código todavía; primero resúmeme el plan de módulos y confírmame que entendiste el hito M1."*
|
||
3. Trabaja **un módulo por sesión**, en el orden de la sección 8. No dejes que genere todo de golpe: pídele un módulo, corre `cargo test`, revisa, y solo entonces avanza.
|
||
4. La sección 12 (Apéndice) trae los "tickets" ya redactados para copiar/pegar como tareas.
|
||
|
||
Regla de oro para dirigirlo: **el criterio de éxito de cada pieza es un test que pasa, no que "se ve bien".** Este proyecto vive o muere por la corrección matemática, no por la estética.
|
||
|
||
---
|
||
|
||
## 1. Resumen ejecutivo
|
||
|
||
`sheafsync` es un motor en Rust que responde, con demostración y no a ojo, una pregunta central de los sistemas soberanos / local-first:
|
||
|
||
> Dado un conjunto de réplicas que editan copias locales de un estado compartido,
|
||
> ¿cuándo se pueden fundir esas copias en un estado global coherente **sin coordinación**,
|
||
> y cuándo existe una obstrucción que obliga a sincronizar?
|
||
|
||
La herramienta modela el estado distribuido como un **haz celular** (cellular sheaf) sobre el
|
||
grafo de comunicación entre réplicas (el "nervio"), y calcula su **cohomología** `H⁰` y `H¹`:
|
||
|
||
- `H⁰` = secciones globales = los estados globales consistentes que existen.
|
||
- `H¹` = obstrucciones = los "nudos" donde lo local es consistente por pares pero no pega globalmente.
|
||
|
||
El motor cruza ese resultado topológico con dos anclas conocidas del mundo de sistemas:
|
||
|
||
- **CRDTs** (tipos de datos que ya convergen solos; retículos join-semilattice).
|
||
- **Teorema CALM** (un cómputo tiene implementación libre de coordinación **si y solo si** es monótono).
|
||
|
||
**Salida práctica:** dada una configuración de réplicas + datos, el motor imprime
|
||
`H¹ = 0 → corre libre (sin jefe)` o `H¹ ≠ 0 → nudo localizado entre réplicas X e Y → coordina aquí`.
|
||
|
||
---
|
||
|
||
## 2. Fundamento teórico (preciso pero legible)
|
||
|
||
### 2.1 Las tres piezas
|
||
|
||
**CRDTs (Shapiro et al., 2011).** Estructuras de datos que se pegan solas porque su operación
|
||
de fusión es un `join` sobre un retículo (conmutativa, asociativa, idempotente). El ejemplo mínimo
|
||
es el *G-Counter*: cada réplica solo incrementa su propia casilla; fusionar = tomar el máximo casilla
|
||
por casilla. Nunca hay conflicto porque nunca se resta.
|
||
|
||
**Teorema CALM (Hellerstein, "Keeping CALM").** Formaliza la intuición anterior:
|
||
un programa admite una implementación consistente **sin coordinación** exactamente cuando es
|
||
*monótono* (solo agrega conocimiento, nunca lo retracta). En cuanto aparece una operación no monótona
|
||
(borrar, resetear, sobrescribir, negar), la coordinación se vuelve necesaria.
|
||
|
||
**Haces celulares y cohomología (Hansen & Ghrist, "Toward a spectral theory of cellular sheaves").**
|
||
Un haz celular sobre un grafo asigna:
|
||
- a cada **vértice** `v` (una réplica) un espacio de estado local, la *stalk* `F(v)`;
|
||
- a cada **arista** `e` (dos réplicas que comparten datos) un espacio `F(e)`;
|
||
- a cada incidencia vértice→arista un *mapa de restricción* lineal `F(v ⊴ e): F(v) → F(e)`
|
||
(la proyección del estado de la réplica sobre el dato que comparte en esa arista).
|
||
|
||
Con eso se construye un complejo de cocadenas y su **coboundary** `δ: C⁰ → C¹`.
|
||
La cohomología es:
|
||
- `H⁰ = ker δ` — asignaciones locales que coinciden en TODA arista compartida = estados globales coherentes.
|
||
- `H¹ = coker δ = C¹ / im δ` — las obstrucciones a pegar. `dim H¹ = dim C¹ − rank δ`.
|
||
|
||
### 2.2 El puente (la hipótesis central del proyecto)
|
||
|
||
La apuesta intelectual de `sheafsync` es que **la cohomología del haz de sincronización coincide
|
||
con lo que CALM predice sobre la coordinación**:
|
||
|
||
> **Hipótesis H:** para un estado compartido codificado linealmente,
|
||
> `H¹ = 0` sobre el grafo de réplicas ⟺ la configuración admite fusión libre de coordinación
|
||
> (i.e. el caso monótono / CALM-libre).
|
||
|
||
**Esto NO es un teorema publicado.** Es la conjetura que el proyecto explora y valida empíricamente.
|
||
Por eso el corazón de la validación (sección 9) es: en los casos donde YA conocemos la respuesta por
|
||
CRDT/CALM, comprobar que el `H¹` calculado concuerda. Si concuerda en los casos fáciles, ganamos
|
||
confianza para usarlo en los casos difíciles donde ya no es obvio a ojo. Ese es el valor de la herramienta,
|
||
y también su honestidad: no vendemos un teorema, construimos y probamos una correspondencia.
|
||
|
||
### 2.3 La brecha de modelado que hay que respetar
|
||
|
||
La cohomología de haces es **lineal** (sobre un cuerpo o anillo). Los retículos de los CRDTs son
|
||
**de orden** (join-semilattices), no espacios vectoriales. Reconciliar ambos es la parte de frontera.
|
||
|
||
Estrategia:
|
||
- **MVP:** trabajar con haces *valuados en espacios vectoriales*, donde la cohomología es álgebra
|
||
lineal estándar. Esto cubre limpiamente los datos que embeben en un grupo (un G-Counter embebe en
|
||
`ℤⁿ`; la pertenencia a conjuntos sobre `GF(2)`), y las restricciones son proyecciones lineales.
|
||
- **Extensión de investigación:** haces valuados en retículos / posets (la generalización "de Tarski"),
|
||
necesaria para capturar operaciones que no embeben en un grupo. Fuera del alcance del MVP; ver §11.
|
||
|
||
---
|
||
|
||
## 3. Objetivos y no-objetivos
|
||
|
||
### 3.1 Objetivos (MVP)
|
||
- G1. Representar réplicas, datos compartidos y su grafo de sincronización (nervio).
|
||
- G2. Construir el haz celular y su matriz de coboundary `δ`.
|
||
- G3. Calcular `rank δ`, `dim H⁰`, `dim H¹` de forma exacta.
|
||
- G4. Localizar la obstrucción: no solo decir *que* hay un nudo, sino *entre qué aristas/réplicas*.
|
||
- G5. Reportar el veredicto en lenguaje de sistemas: "corre libre" vs "coordina aquí".
|
||
- G6. Validar contra un oráculo CRDT/CALM en una batería de casos conocidos.
|
||
|
||
### 3.2 No-objetivos (explícitos, para no dispersarse)
|
||
- N1. NO es un motor de replicación en producción. No hay red real, ni persistencia, ni wire protocol.
|
||
Es un *analizador* de configuraciones.
|
||
- N2. NO implementa haces sobre retículos generales en el MVP (solo espacios vectoriales).
|
||
- N3. NO resuelve la coordinación cuando hace falta; solo *detecta y localiza* dónde hace falta.
|
||
- N4. NO busca rendimiento a gran escala en v1. Corrección > velocidad. Grafos de decenas de réplicas.
|
||
- N5. NO integra con Tawasuyu/Hammer todavía. Eso es un hito posterior (M4), con API estable primero.
|
||
|
||
---
|
||
|
||
## 4. Modelo de dominio
|
||
|
||
Vocabulario que usa todo el código y este documento:
|
||
|
||
| Término | Significado |
|
||
|---|---|
|
||
| **Réplica** | Un nodo que tiene una copia local del estado. Vértice del grafo. |
|
||
| **Nervio** | El grafo de qué réplicas comparten datos con cuáles. Aristas. |
|
||
| **Stalk** | El espacio de estado local de una réplica (o de una arista). |
|
||
| **Dato compartido** | La porción del estado que dos réplicas deben mantener coherente en su arista. |
|
||
| **Mapa de restricción** | Proyección lineal del estado de una réplica sobre el dato de una arista. |
|
||
| **Coboundary `δ`** | Operador lineal que mide desacuerdos en todas las aristas a la vez. |
|
||
| **Sección global (`H⁰`)** | Un estado global coherente: todos concuerdan en todo lo compartido. |
|
||
| **Obstrucción (`H¹`)** | Un nudo: coherencia por pares que no se puede globalizar. |
|
||
|
||
---
|
||
|
||
## 5. Arquitectura
|
||
|
||
Crate único (`sheafsync`) con módulos claros. Es un binario + librería (`src/lib.rs` + `src/main.rs`).
|
||
|
||
```
|
||
Réplicas + datos ──► módulo `cell` (qué es un dato local que sabe fundirse)
|
||
Quién comparte con quién ──► módulo `nerve` (el grafo)
|
||
Pegar lo local ──► módulo `sheaf` (haz + coboundary δ)
|
||
Detector de choques ──► módulo `cohomology` (rank, H⁰, H¹, localización)
|
||
Veredicto ──► módulo `verdict` (traducción a lenguaje de sistemas)
|
||
Oráculo de validación ──► módulo `oracle` (CRDT/CALM de referencia)
|
||
```
|
||
|
||
Cada módulo corresponde exactamente a una caja del diagrama de tubería del diseño conceptual.
|
||
|
||
### 5.1 Principios de diseño de código
|
||
- Núcleo matemático **puro y determinista**: sin I/O, sin aleatoriedad, sin estado global.
|
||
- Los tipos de datos compartidos entran por un `trait`; el motor no sabe (ni le importa) si son
|
||
contadores, conjuntos o registros.
|
||
- El álgebra lineal se aísla tras una interfaz `LinAlg`, con dos implementaciones intercambiables:
|
||
`f64` (rápida, para arrancar) y `GF(2)` exacta (para el sabor topológico puro).
|
||
- Errores explícitos con `thiserror`. Nada de `unwrap()` en rutas de librería.
|
||
|
||
---
|
||
|
||
## 6. Modelo de tipos (bocetos de Rust)
|
||
|
||
Estos son bocetos de *forma*, no código final. Claude Code debe completarlos y ajustarlos.
|
||
|
||
### 6.1 `cell` — el dato local
|
||
|
||
```rust
|
||
/// Un pedacito de estado local que sabe cómo intentar fundirse con otro,
|
||
/// y cómo proyectarse al espacio de una arista compartida.
|
||
pub trait Cell: Clone + PartialEq {
|
||
/// El vector que representa este estado en el espacio de la stalk.
|
||
fn to_vector(&self) -> Vec<Scalar>;
|
||
|
||
/// Fusión de retículo (join). Debe ser conmutativa, asociativa, idempotente.
|
||
fn join(&self, other: &Self) -> Self;
|
||
|
||
/// ¿Esta operación es monótona? (marca para el oráculo CALM)
|
||
fn is_monotone() -> bool;
|
||
}
|
||
|
||
/// CRDT mínimo del MVP: cuenta por réplica, fusiona por máximo. Siempre monótono.
|
||
pub struct GCounter { pub slots: Vec<u64> }
|
||
|
||
/// CRDT no monótono para el caso "difícil": permite reset/borrado.
|
||
/// Sirve para provocar H¹ ≠ 0 deliberadamente.
|
||
pub struct ResettableRegister { /* ... */ }
|
||
```
|
||
|
||
`Scalar` es un alias que resuelve la implementación de álgebra lineal elegida (ver §7).
|
||
|
||
### 6.2 `nerve` — el grafo
|
||
|
||
```rust
|
||
use petgraph::graph::UnGraph;
|
||
|
||
pub struct Nerve {
|
||
/// Grafo no dirigido: vértices = réplicas, aristas = pares que comparten datos.
|
||
pub graph: UnGraph<ReplicaId, SharedLink>,
|
||
}
|
||
|
||
pub struct ReplicaId(pub usize);
|
||
pub struct SharedLink { /* qué coordenadas se comparten en esta arista */ }
|
||
```
|
||
|
||
### 6.3 `sheaf` — el haz y el coboundary
|
||
|
||
```rust
|
||
pub struct Sheaf {
|
||
/// Para cada réplica: su espacio local (dimensión de la stalk).
|
||
pub vertex_stalks: Vec<usize>,
|
||
/// Para cada arista: su espacio (dimensión).
|
||
pub edge_stalks: Vec<usize>,
|
||
/// Mapas de restricción: por arista, dos matrices (una por extremo).
|
||
pub restrictions: Vec<(RestrictionMap, RestrictionMap)>,
|
||
}
|
||
|
||
impl Sheaf {
|
||
/// Ensambla la matriz global de coboundary δ: C⁰ → C¹.
|
||
/// Convención: para arista e=(u→v), (δx)_e = R_{u⊴e}·x_u − R_{v⊴e}·x_v.
|
||
pub fn coboundary(&self) -> Matrix { /* ... */ }
|
||
}
|
||
```
|
||
|
||
### 6.4 `cohomology` — la única cuenta que importa
|
||
|
||
```rust
|
||
pub struct Cohomology {
|
||
pub dim_c0: usize,
|
||
pub dim_c1: usize,
|
||
pub rank_delta: usize,
|
||
pub dim_h0: usize, // = dim_c0 - rank_delta
|
||
pub dim_h1: usize, // = dim_c1 - rank_delta
|
||
/// Si dim_h1 > 0, una base del cokernel: cada vector señala aristas
|
||
/// que participan en la obstrucción (para localizar el nudo).
|
||
pub obstruction_basis: Vec<Vec<Scalar>>,
|
||
}
|
||
|
||
pub fn compute(sheaf: &Sheaf) -> Cohomology { /* rank vía eliminación gaussiana */ }
|
||
```
|
||
|
||
### 6.5 `verdict` — traducción a lenguaje humano
|
||
|
||
```rust
|
||
pub enum Verdict {
|
||
RunsFree, // H¹ = 0
|
||
NeedsCoordination { knots: Vec<Knot> } // H¹ ≠ 0, con localización
|
||
}
|
||
|
||
pub struct Knot {
|
||
pub replicas: Vec<ReplicaId>, // réplicas implicadas en el nudo
|
||
pub edges: Vec<usize>, // aristas del ciclo obstruido
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 7. La cuenta de cohomología, paso a paso
|
||
|
||
Esto es lo que Claude Code debe implementar en `cohomology::compute`, y es TODO el corazón:
|
||
|
||
1. Ensamblar `δ` como una matriz de tamaño `(Σ dim F(e)) × (Σ dim F(v))`.
|
||
Bloque de la arista `e=(u,v)`: `+R_{u⊴e}` en las columnas de `u`, `−R_{v⊴e}` en las de `v`.
|
||
2. Calcular `rank(δ)` por eliminación gaussiana.
|
||
3. `dim H⁰ = dim C⁰ − rank(δ)` (núcleo del coboundary).
|
||
4. `dim H¹ = dim C¹ − rank(δ)` (cokernel).
|
||
5. Si `dim H¹ > 0`, extraer una base del cokernel (vectores de `C¹` que no están en `im δ`).
|
||
Las aristas con soporte no nulo en esos vectores son el nudo → poblar `Knot`.
|
||
|
||
### 7.1 Dos aritméticas, misma interfaz
|
||
- `Scalar = f64` con `nalgebra`: rápido, para tener algo corriendo ya. Riesgo: rango numérico
|
||
aproximado (tolerancia epsilon). Suficiente para el MVP y demos.
|
||
- `Scalar = GF2` (bit-packed, eliminación gaussiana sobre `𝔽₂`): **exacto**, sin epsilon, y es la
|
||
versión "topológica pura". Recomendado en cuanto el MVP funcione. Se implementa a mano con `u64`
|
||
como filas de bits; es código corto y muy robusto.
|
||
|
||
Ambas detrás de un `trait LinAlg { fn rank(&Matrix) -> usize; fn cokernel_basis(&Matrix) -> ...; }`.
|
||
|
||
### 7.2 Prueba de cordura obligatoria (¡implementar primero!)
|
||
Para el **haz constante** (todas las stalks iguales, todas las restricciones = identidad), la cohomología
|
||
DEBE coincidir con la topología del grafo:
|
||
- `dim H⁰ = (#componentes conexas) × d`
|
||
- `dim H¹ = (#ciclos independientes, i.e. primer número de Betti) × d`
|
||
donde `d` es la dimensión de la stalk. Si esto no cuadra, el coboundary está mal ensamblado.
|
||
Este test es el andamio: hazlo pasar antes de tocar CRDTs.
|
||
|
||
---
|
||
|
||
## 8. Plan de hitos
|
||
|
||
### M0 — Scaffolding (día 1)
|
||
`cargo new`, estructura de módulos vacía, `LinAlg` con la impl `f64`, `petgraph` y `thiserror` como deps.
|
||
Un `main` que imprime "hello sheaf". Test dummy que pasa.
|
||
|
||
### M1 — EL HITO DE DOS SEMANAS (el que prueba el núcleo entero)
|
||
Objetivo: dos corridas, una que da cero y otra que no.
|
||
|
||
- Implementar `cohomology::compute` + la prueba de cordura del haz constante (§7.2).
|
||
- **Corrida A (monótona):** 3 réplicas, un `GCounter` compartido, cada una incrementa por su lado.
|
||
El motor construye el haz, calcula `H¹`, y **debe imprimir `H¹ = 0 → corre libre`**.
|
||
- **Corrida B (no monótona):** mismas 3 réplicas en ciclo, pero con `ResettableRegister` y una
|
||
configuración de constraints cíclica inconsistente. El motor **debe imprimir
|
||
`H¹ ≠ 0 → nudo entre réplicas 2 y 3 → coordina aquí`**, con localización correcta.
|
||
|
||
Criterio de éxito: A da 0, B da ≠0, y la localización de B apunta al ciclo correcto.
|
||
Si logras esto, el núcleo está probado. Todo lo demás es crecer, no reinventar.
|
||
|
||
### M2 — Aritmética exacta y localización robusta
|
||
Añadir la impl `GF(2)`. Migrar los tests a exacto (sin epsilon). Mejorar `Knot` para reportar todos
|
||
los ciclos obstruidos, no solo el primero. Property-based tests con `proptest`.
|
||
|
||
### M3 — Oráculo y batería de validación
|
||
Implementar `oracle`: un evaluador CRDT/CALM de referencia que, para cada caso de prueba, dice
|
||
independientemente si es coordination-free. Batería de ≥20 casos (monótonos y no monótonos, con y sin
|
||
ciclos). Test maestro: **el veredicto del haz coincide con el del oráculo en todos**. Esto valida la
|
||
Hipótesis H (§2.2) empíricamente. Documentar cualquier caso donde discrepen — esos son oro científico.
|
||
|
||
### M4 — API estable + puente a Tawasuyu/Hammer (posterior)
|
||
Congelar la API pública de `verdict`. Adaptador que tome un estado real de tus sistemas soberanos y lo
|
||
codifique como haz. Recién aquí se conecta a lo tuyo.
|
||
|
||
### Extensión de investigación (sin fecha)
|
||
Haces valuados en retículos/posets para cubrir datos no embebibles en grupos (§2.3). Aquí es donde el
|
||
proyecto deja de replicar lo conocido y aporta algo nuevo de verdad.
|
||
|
||
---
|
||
|
||
## 9. Estrategia de pruebas
|
||
|
||
Tres capas, de más barata a más valiosa:
|
||
|
||
1. **Unitarias de álgebra lineal.** `rank`, `cokernel_basis` sobre matrices con respuesta conocida a mano.
|
||
2. **Cordura topológica.** Haz constante sobre grafos con Betti conocido (árbol → H¹=0; triángulo →
|
||
H¹ de dimensión 1; dos triángulos pegados → dimensión 2). No negociable (§7.2).
|
||
3. **Oráculo CRDT/CALM.** El corazón de la validación (M3). Cada caso trae su respuesta "verdadera"
|
||
calculada por un camino independiente (monotonicidad de las operaciones + estructura del grafo), y el
|
||
motor debe coincidir. `proptest` para generar configuraciones aleatorias y verificar invariantes
|
||
(p.ej. "toda configuración puramente monótona sobre grafo arbitrario ⟹ H¹=0").
|
||
|
||
Invariantes que `proptest` debe intentar romper:
|
||
- Solo-suma sobre cualquier grafo ⟹ `H¹ = 0`.
|
||
- Añadir una arista nunca reduce `dim H⁰` (más restricciones, no menos).
|
||
- El haz constante siempre reproduce los números de Betti del grafo.
|
||
|
||
---
|
||
|
||
## 10. Dependencias
|
||
|
||
| Crate | Para qué | Nota |
|
||
|---|---|---|
|
||
| `petgraph` | El nervio (grafo de réplicas) | Maduro, estándar. |
|
||
| `nalgebra` | Álgebra lineal `f64` del MVP | Para arrancar; rango con tolerancia. |
|
||
| `thiserror` | Errores de librería tipados | Sin `unwrap` en rutas públicas. |
|
||
| `proptest` | Tests basados en propiedades | Clave para la validación de invariantes. |
|
||
| (propio) | `GF(2)` bit-packed | Implementación a mano, ~1 archivo. Sin dependencia externa. |
|
||
|
||
Deliberadamente mínimo. Los CRDTs del MVP (`GCounter`, `ResettableRegister`) se implementan inline para
|
||
controlar su semántica exacta; no se depende de un crate de CRDTs en v1.
|
||
|
||
---
|
||
|
||
## 11. Riesgos y preguntas abiertas (honestas)
|
||
|
||
- **R1 (el grande).** La Hipótesis H puede fallar en casos sutiles. La codificación lineal de datos de
|
||
retículo puede perder información (§2.3), haciendo que el haz "vea" obstrucciones que CALM no, o
|
||
viceversa. *Mitigación:* M3 está diseñado justo para cazar esas discrepancias; son el resultado
|
||
científico, no un bug a esconder.
|
||
- **R2.** La localización del nudo (`obstruction_basis` → `Knot`) es interpretable de forma limpia solo
|
||
cuando la base del cokernel es "esparcida". En casos densos, señalar "las réplicas culpables" puede ser
|
||
ambiguo. *Mitigación:* empezar con localización por ciclos del grafo, refinar después.
|
||
- **R3.** Rango en `f64` es aproximado. *Mitigación:* migrar a `GF(2)` exacto en M2; no confiar en el
|
||
MVP `f64` para conclusiones finas.
|
||
- **Q1.** ¿Qué codificación lineal de cada CRDT preserva exactamente la monotonicidad? Es una decisión de
|
||
diseño por tipo de dato, no automática.
|
||
- **Q2.** Para datos no monótonos, ¿el haz sobre `GF(2)` basta, o hace falta ya la generalización a
|
||
retículos? Probable que baste para el MVP; confirmar empíricamente en M3.
|
||
|
||
---
|
||
|
||
## 12. Apéndice — Tickets para Claude Code
|
||
|
||
Copia/pega estos como tareas, en orden. Uno por sesión. Corre `cargo test` entre cada uno.
|
||
|
||
**T0.** "Crea el scaffold del crate `sheafsync` según §5: módulos `cell`, `nerve`, `sheaf`,
|
||
`cohomology`, `verdict`, `oracle`, más `lib.rs` y `main.rs`. Añade deps `petgraph`, `nalgebra`,
|
||
`thiserror`, y `proptest` como dev-dependency. Define el trait `LinAlg` con una impl `f64` vacía.
|
||
Deja todo compilando con un test dummy que pase. No implementes lógica aún."
|
||
|
||
**T1.** "Implementa `cohomology::compute` según §7, sobre la impl `f64` de `LinAlg`. Implementa la
|
||
prueba de cordura del haz constante de §7.2 como tests: árbol (H¹=0), triángulo (H¹ dim 1), dos
|
||
triángulos pegados (H¹ dim 2). Que pasen."
|
||
|
||
**T2.** "Implementa `GCounter` y `ResettableRegister` en `cell` según §6.1, con `is_monotone`
|
||
correcto. Escribe el ejemplo del hito M1 (§8): Corrida A (GCounter, 3 réplicas) que debe dar H¹=0, y
|
||
Corrida B (ResettableRegister en ciclo inconsistente) que debe dar H¹≠0 con nudo localizado.
|
||
Muéstralos desde `main`."
|
||
|
||
**T3.** "Añade la impl `GF(2)` de `LinAlg` (bit-packed con u64, eliminación gaussiana exacta). Migra
|
||
los tests a exacto. Extrae `Knot` con localización de todos los ciclos obstruidos según §6.5."
|
||
|
||
**T4.** "Implementa `oracle` (§8 M3): un evaluador CRDT/CALM de referencia independiente. Crea una
|
||
batería de ≥20 casos y un test maestro que verifique que el veredicto del haz coincide con el del
|
||
oráculo. Añade los invariantes `proptest` de §9. Documenta cualquier discrepancia en un archivo
|
||
`DISCREPANCIES.md`."
|
||
|
||
---
|
||
|
||
## 13. Glosario mínimo
|
||
|
||
- **Coordination-free / libre de coordinación:** que las réplicas pueden converger sin un protocolo
|
||
de consenso ni un coordinador central.
|
||
- **Monótono:** una operación que solo agrega información y nunca la retracta (base de CALM).
|
||
- **Cohomología (`H⁰`, `H¹`):** invariantes lineales del haz; aquí, "estados globales coherentes" y
|
||
"obstrucciones a la coherencia global".
|
||
- **Cokernel:** `C¹ / im δ`; lo que "sobra" en el espacio de aristas y no proviene de ningún estado
|
||
global — la firma matemática de una obstrucción.
|
||
- **Betti (primer número de):** cantidad de ciclos independientes de un grafo; sirve de patrón de
|
||
cordura para el haz constante.
|
||
|
||
## 14. Referencias
|
||
|
||
- M. Shapiro, N. Preguiça, C. Baquero, M. Zawirski — *A Comprehensive Study of Convergent and
|
||
Commutative Replicated Data Types* (2011).
|
||
- J. M. Hellerstein, P. Alvaro — *Keeping CALM: When Distributed Consistency is Easy* (CACM).
|
||
- J. Hansen, R. Ghrist — *Toward a Spectral Theory of Cellular Sheaves* (2019).
|
||
- R. Ghrist — *Elementary Applied Topology* (para el andamiaje de cohomología celular).
|