code wiki / _hdl_build / nx_crdt_sync_gate.nx
nx_crdt_sync_gate.nx source
↩ module page · 113 lines · 6603 B
1// nx_crdt_sync_gate.nx -- proves the CRDT SYNC merge on the exact friction scenario: a shared base doc, TWO actors
2// make DIFFERENT concurrent edits (one inserts mid-doc, one appends), they exchange op-logs, and BOTH converge to a
3// document containing BOTH edits -- where naive last-writer-wins (git save-the-file / a lock) loses one and diverges.
4// This is the operational fix for "two Claude sessions edited the same file". license_tier: ORIGINAL expect_exit: 0
5import "nx_syscalls.nx"
6import "nx_crdt_seq.nx"
7import "nx_lamport_clock.nx"
8import "nx_crdt_sync.nx"
9
10func hw(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
11func pn(v: i64) -> i64 { let b: *u8=sys_mmap(32) as *u8; var x: i64=v; var ng: i64=0; if x<0{ng=1;x=0-x} var i: i64=31; if x==0{b[i]=48 as u8;i=i-1} while x>0{b[i]=(48+x%10) as u8;x=x/10;i=i-1} if ng==1{b[i]=45 as u8;i=i-1} sys_write(1,(b as i64+i+1) as *u8,31-i); return 0 }
12func hs(s: *u8, n: i64) -> i64 { sys_write(1, s, n); return 0 }
13func bufeq(a: *u8, an: i64, b: *u8, bn: i64) -> i64 {
14 if an != bn { return 0 }
15 var i: i64 = 0
16 while i < an { if a[i] != b[i] { return 0 } i = i + 1 }
17 return 1
18}
19func has(a: *u8, an: i64, c: i64) -> i64 {
20 var i: i64 = 0
21 while i < an { if (a[i] as i64) == c { return 1 } i = i + 1 }
22 return 0
23}
24func str2(a: *u8, an: i64, c0: i64, c1: i64) -> i64 {
25 if an != 2 { return 0 }
26 if (a[0] as i64) != c0 { return 0 }
27 if (a[1] as i64) != c1 { return 0 }
28 return 1
29}
30func str3(a: *u8, an: i64, c0: i64, c1: i64, c2: i64) -> i64 {
31 if an != 3 { return 0 }
32 if (a[0] as i64) != c0 { return 0 }
33 if (a[1] as i64) != c1 { return 0 }
34 if (a[2] as i64) != c2 { return 0 }
35 return 1
36}
37func str4(a: *u8, an: i64, c0: i64, c1: i64, c2: i64, c3: i64) -> i64 {
38 if an != 4 { return 0 }
39 if (a[0] as i64) != c0 { return 0 }
40 if (a[1] as i64) != c1 { return 0 }
41 if (a[2] as i64) != c2 { return 0 }
42 if (a[3] as i64) != c3 { return 0 }
43 return 1
44}
45
46func main() -> i64 {
47 hw("=== nx_crdt_sync_gate -- two agents edit one doc concurrently; CRDT merges both, git loses one ===\n" as *u8)
48 var fails: i64 = 0
49
50 // BASE (actor 0): 'A'=65 then 'C'=67 -> "AC"; ids A=(1,0) C=(2,0)
51 let base: *i64 = seq_new()
52 let baseLog: *i64 = oplog_new()
53 let clkBase: *i64 = lc_new(0)
54 sync_insert(base, baseLog, clkBase, 65, 0-1, 0-1)
55 sync_insert(base, baseLog, clkBase, 67, 1, 0)
56 let bufBase: *u8 = sys_mmap(64); let lBase: i64 = seq_materialize(base, bufBase)
57 hw(" base="); hs(bufBase, lBase); hw("\n" as *u8)
58 var t1: i64 = 0
59 if str2(bufBase, lBase, 65, 67) == 1 { t1 = 1 }
60 if t1 == 1 { hw("T1 PASS base doc 'AC'\n" as *u8) } else { fails=fails+1; hw("T1 FAIL base\n" as *u8) }
61
62 // FORK: two replicas each apply the base op-log
63 let docA: *i64 = seq_new(); let clkA: *i64 = lc_new(1); sync_apply_log(docA, clkA, baseLog); let logA: *i64 = oplog_new()
64 let docB: *i64 = seq_new(); let clkB: *i64 = lc_new(2); sync_apply_log(docB, clkB, baseLog); let logB: *i64 = oplog_new()
65
66 // CONCURRENT edits: A inserts 'B'=66 after A(1,0) [mid-doc]; B inserts 'D'=68 after C(2,0) [append]
67 sync_insert(docA, logA, clkA, 66, 1, 0)
68 sync_insert(docB, logB, clkB, 68, 2, 0)
69 let aPre: *u8 = sys_mmap(64); let laPre: i64 = seq_materialize(docA, aPre)
70 let bPre: *u8 = sys_mmap(64); let lbPre: i64 = seq_materialize(docB, bPre)
71 hw(" pre-sync replicaA="); hs(aPre, laPre); hw(" replicaB="); hs(bPre, lbPre); hw(" (DIVERGED = the collision)\n" as *u8)
72 var t2: i64 = 0
73 if str3(aPre, laPre, 65, 66, 67) == 1 { if str3(bPre, lbPre, 65, 67, 68) == 1 { if bufeq(aPre, laPre, bPre, lbPre) == 0 { t2 = 1 } } }
74 if t2 == 1 { hw("T2 PASS each replica saw only its own edit -> ABC vs ACD (the git collision state)\n" as *u8) } else { fails=fails+1; hw("T2 FAIL\n" as *u8) }
75
76 // SYNC: exchange op-logs (each applies the other's)
77 sync_apply_log(docA, clkA, logB)
78 sync_apply_log(docB, clkB, logA)
79 let aPost: *u8 = sys_mmap(64); let laPost: i64 = seq_materialize(docA, aPost)
80 let bPost: *u8 = sys_mmap(64); let lbPost: i64 = seq_materialize(docB, bPost)
81 hw(" post-sync replicaA="); hs(aPost, laPost); hw(" replicaB="); hs(bPost, lbPost); hw("\n" as *u8)
82 var t3: i64 = 0
83 if bufeq(aPost, laPost, bPost, lbPost) == 1 { if str4(aPost, laPost, 65, 66, 67, 68) == 1 { t3 = 1 } }
84 if t3 == 1 { hw("T3 PASS both replicas CONVERGE to 'ABCD' after exchanging op-logs\n" as *u8) } else { fails=fails+1; hw("T3 FAIL convergence\n" as *u8) }
85
86 var t4: i64 = 0
87 if laPost == 4 { if has(aPost, laPost, 66) == 1 { if has(aPost, laPost, 68) == 1 { t4 = 1 } } }
88 if t4 == 1 { hw("T4 PASS NO edit lost -- BOTH concurrent edits present (B and D)\n" as *u8) } else { fails=fails+1; hw("T4 FAIL an edit lost\n" as *u8) }
89
90 // NEG CONTROL: naive last-writer-wins (git save-the-file / a lock) keeps ONE version -> len 3 (loss) + it diverged
91 var t5: i64 = 0
92 if laPre == 3 { if lbPre == 3 { if bufeq(aPre, laPre, bPre, lbPre) == 0 { if laPost > laPre { t5 = 1 } } } }
93 if t5 == 1 { hw("T5 PASS neg-control BITES: naive LWW keeps 1 version (len 3<4 = an edit LOST) and diverged; the CRDT did not\n" as *u8) } else { fails=fails+1; hw("T5 FAIL neg-control\n" as *u8) }
94
95 // ARTIFACT
96 let rep: *u8 = sys_mmap(2048)
97 var q: i64 = 0
98 var s: *u8 = "NISHI CRDT SYNC -- V-COLLAB rung 2 (composes nx_crdt_seq + nx_lamport_clock). Two actors edit one base doc 'AC' concurrently: A inserts B mid-doc, B appends D. They exchange op-logs and BOTH converge to 'ABCD' -- both edits kept, zero collision, zero loss.\n" as *u8
99 var k: i64 = 0
100 while s[k] != (0 as u8) { rep[q] = s[k]; q = q + 1; k = k + 1 }
101 s = "Neg-control: naive last-writer-wins (a lock / git save-the-file) keeps only one version (len 3) and diverges = the exact 'file modified since read' collision. This op-log sync is the operational fix; next = a peer sync transport + wiring the real edit surface through it.\n" as *u8
102 k = 0
103 while s[k] != (0 as u8) { rep[q] = s[k]; q = q + 1; k = k + 1 }
104 rep[q] = 0 as u8
105 let fd: i64 = sys_openat_wr("knowledge/nx_crdt_sync.txt\x00" as *u8, 0x1a4)
106 sys_write(fd, rep, q); sys_close(fd)
107 hw("T6 artifact -> knowledge/nx_crdt_sync.txt ("); pn(q); hw(" bytes)\n" as *u8)
108
109 if fails == 0 { hw("NX-CRDT-SYNC GREEN -- concurrent multi-agent edits merge with zero loss; git-model neg-control loses+diverges\n" as *u8); sys_exit(0); return 0 }
110 hw("NX-CRDT-SYNC RED fails="); pn(fails); hw("\n" as *u8)
111 sys_exit(1)
112 return 1
113}