gioser

tawasuyu/hifas

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.

Rust 24Markdown 15TOML 1358 Definiciones

T8b: auditar y corregir el oráculo (monotonía de fusión, no de valor)

T8 §B/§F: el oracle_verdict de T4 usaba la etiqueta monotone = monotonía de
VALOR. Un LWW-register baja de valor pero es un CRDT (monótono en su orden
de fusión), luego CALM real lo declara libre. Separo:
- calm_syntactic: el check grueso por-programa (coordina ante cualquier op
  no monótona en valor). Es la respuesta a batir en T8c.
- oracle_verdict (corregido): monotonía en el orden de FUSIÓN. Todo CRDT
  puro es CoordinationFree en cualquier grafo; la coordinación real solo la
  trae un invariante (T8c).

Tests históricos (lineal, labeled) repuntados a calm_syntactic (el oráculo
grueso que espejaban). Nuevo test t8b: oráculo corregido y haz nativo
coinciden en todo CRDT puro — acuerdo correcto (ambos ven que el merge
reconcilia), no circular como el de T7.

40 tests, clippy limpio.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

62995aa024335bf16c345ca18f2b310ca615140a · por Sergio · (hace 3 meses) · padre b666de794 · ver el árbol en este commit

Delta semántico · 8

1 archivos · +50 −15

diff --git a/src/oracle.rs b/src/oracle.rs
index c964f0e..5dc3489 100644
--- a/src/oracle.rs
+++ b/src/oracle.rs
@@ -68,10 +68,11 @@ impl Config {
         }
     }
 
-    /// **Oráculo CALM (independiente del haz).** Coordination-free ⟺ toda
-    /// operación compartida es monótona. En cuanto aparece una no monótona
-    /// compartida, CALM exige coordinación.
-    pub fn oracle_verdict(&self) -> OracleVerdict {
+    /// **CALM sintáctico por-programa** (el check grueso). Coordina si aparece
+    /// cualquier operación marcada no monótona en VALOR. Es la respuesta a batir:
+    /// la "discrepancia buena" que persigue T8c es `haz = libre` mientras esto
+    /// dice `coordina` (§D). No es el oráculo de corrección.
+    pub fn calm_syntactic(&self) -> OracleVerdict {
         if self.shares.iter().all(|s| s.monotone) {
             OracleVerdict::CoordinationFree
         } else {
@@ -79,6 +80,23 @@ impl Config {
         }
     }
 
+    /// **Oráculo CALM corregido** (T8b, §B/§F): la monotonía que importa es la del
+    /// **orden de fusión**, no la del valor. Un CRDT es, por definición, monótono
+    /// en su propio merge (join-semilattice); luego una configuración de CRDT
+    /// puros es libre de coordinación en cualquier grafo — ciclos incluidos.
+    ///
+    /// La etiqueta `monotone` era monotonía de VALOR (un LWW baja de valor pero es
+    /// un CRDT): por eso `calm_syntactic` clasificaba mal los reset. Aquí eso se
+    /// corrige. La coordinación real solo la introduce un **invariante** (T8c);
+    /// hasta entonces, el veredicto correcto es siempre `CoordinationFree`. Su
+    /// acuerdo con el haz nativo NO es circular: ambos reconocen, por caminos
+    /// independientes, que un merge de CRDT reconcilia.
+    pub fn oracle_verdict(&self) -> OracleVerdict {
+        // Todo `Share` está respaldado por un merge de CRDT genuino (GCounter o
+        // registro LWW), monótono en su orden de fusión ⇒ sin coordinación.
+        OracleVerdict::CoordinationFree
+    }
+
     /// Codificación lineal de la configuración como haz (la codificación honesta
     /// de la §2.3, sin colapsar ciclos monótonos):
     /// - cada dato compartido → una arista de acuerdo (restricción identidad);
@@ -314,28 +332,29 @@ pub fn casos_de_discrepancia() -> Vec<Config> {
 mod tests {
     use super::*;
 
-    /// Test maestro (§8 M3): el veredicto del haz coincide con el del oráculo en
-    /// toda la batería de acuerdo, que tiene ≥20 casos.
+    /// Control histórico del MVP (§8 M3): el haz LINEAL coincide con el CALM
+    /// **sintáctico** (grueso) en toda la batería. Ese acuerdo topológico
+    /// ↔ sintáctico es el que T8 pone en cuarentena; se conserva como control.
     #[test]
-    fn haz_coincide_con_oraculo() {
+    fn haz_lineal_coincide_con_calm_sintactico() {
         let casos = casos_de_acuerdo();
         assert!(casos.len() >= 20, "la batería debe tener ≥20 casos, tiene {}", casos.len());
         for c in &casos {
             assert_eq!(
                 c.sheaf_verdict(),
-                c.oracle_verdict(),
+                c.calm_syntactic(),
                 "discrepancia inesperada en el caso '{}'",
                 c.name
             );
         }
     }
 
-    /// Las discrepancias del MVP **lineal** (R1) son reales y esperadas: el haz
-    /// topológico dice coordinar donde CALM dice libre. Es el control histórico.
+    /// Las discrepancias del MVP **lineal** (R1): el haz topológico dice coordinar
+    /// donde el CALM sintáctico dice libre (ciclo monótono). Control histórico.
     #[test]
     fn discrepancias_del_lineal_persisten() {
         for c in casos_de_discrepancia() {
-            assert_eq!(c.oracle_verdict(), OracleVerdict::CoordinationFree);
+            assert_eq!(c.calm_syntactic(), OracleVerdict::CoordinationFree);
             assert_eq!(
                 c.sheaf_verdict(),
                 OracleVerdict::NeedsCoordination,
@@ -346,20 +365,36 @@ mod tests {
     }
 
     /// Control histórico: el encoding CIRCULAR de T7 (`_labeled`) coincide con el
-    /// oráculo por-etiqueta en toda la batería. Es justo esa coincidencia
-    /// perfecta lo que T8 §A denuncia como circular; se conserva para el flip.
+    /// CALM **sintáctico** en toda la batería. Es justo esa coincidencia perfecta
+    /// lo que T8 §A denuncia como circular; se conserva para el flip.
     #[test]
-    fn tarski_labeled_coincide_con_oraculo_es_circular() {
+    fn tarski_labeled_coincide_con_calm_sintactico_es_circular() {
         for c in &casos_de_acuerdo() {
             assert_eq!(
                 c.tarski_verdict_labeled(),
-                c.oracle_verdict(),
+                c.calm_syntactic(),
                 "el control circular debe coincidir en '{}'",
                 c.name
             );
         }
     }
 
+    /// **T8b — el oráculo corregido**: bajo monotonía-de-fusión, todo CRDT puro es
+    /// `CoordinationFree`, y el haz nativo coincide. El acuerdo es correcto (ambos
+    /// reconocen que un merge de CRDT reconcilia), no circular como el de T7.
+    #[test]
+    fn t8b_oraculo_corregido_coincide_con_nativo() {
+        for c in casos_de_acuerdo().iter().chain(&casos_de_discrepancia()) {
+            assert_eq!(c.oracle_verdict(), OracleVerdict::CoordinationFree);
+            assert_eq!(
+                c.tarski_verdict(),
+                c.oracle_verdict(),
+                "oráculo corregido y haz nativo deben coincidir en '{}'",
+                c.name
+            );
+        }
+    }
+
     /// **T8a — la de-circularización** (§B, `FLIPS.md`): bajo el orden nativo
     /// (derivado del merge, sin leer la etiqueta), los casos que el encoding
     /// circular de T7 llamaba `coordina` VUELVEN a `corre libre`. Cada flip es