nx_companion_rel_gate.nx source
↩ module page · 106 lines · 7078 B
1// nx_companion_rel_gate.nx -- GATE for R1d (nx_companion_rel): relationship state evolves correctly and safely.
2// Proves: (T1) round-trip; (T2) facts APPEND additively (a new fact never erases a prior one); (T3) trust is
3// CLAMPED to 0..100 at both ends (never-brick numeric bound); (T4) a mutation preserves the other fields
4// (read-modify-write is lossless); (T5) the projected context carries stage + facts; (T6) neg -- unknown
5// (persona,user) yields empty context; (T7) ISOLATION -- one persona's relationship with a user is independent
6// of another persona's. Timestamp-fresh /tmp store -> deterministic re-runs. license_tier: ORIGINAL expect_exit: 0
7import "nx_companion_rel.nx"
8import "nx_gate_verdict.nx"
9
10func rw(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
11func rn(v: i64) -> i64 { let bb: *u8=sys_mmap(28); var m: i64=v; if m<0{sys_write(1,"-" as *u8,1);m=0-m} let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} var i: i64=0; while i<k{bb[i]=t[k-1-i];i=i+1} sys_write(1,bb,k); return 0 }
12func r_streq(a: *u8, b: *u8) -> i64 { var i: i64=0; while a[i]!=(0 as u8){ if a[i]!=b[i]{return 0} i=i+1 } if b[i]!=(0 as u8){return 0} return 1 }
13func r_find(hay: *u8, hlen: i64, needle: *u8) -> i64 {
14 var nl: i64=0; while needle[nl]!=(0 as u8){nl=nl+1}
15 if nl==0 { return 1 }
16 if hlen<nl { return 0 }
17 var i: i64=0
18 while i<=hlen-nl { var m: i64=1; var c: i64=0; while c<nl { if hay[i+c]!=needle[c]{m=0;c=nl} else {c=c+1} } if m==1 {return 1} i=i+1 }
19 return 0
20}
21func r_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
22
23func main() -> i64 {
24 rw("=== nx_companion_rel_gate (R1d: relationship state -- evolving, additive, clamped, isolated) ===\n" as *u8)
25 let EPT: *u8 = sys_mmap(256)
26 var po: i64 = 0
27 var i: i64=0; let pre: *u8="/tmp/rel-test-" as *u8; while pre[i]!=(0 as u8){EPT[po]=pre[i];po=po+1;i=i+1}
28 var ms: i64 = sys_now_ms() % 100000000; var d: i64=7
29 while d>=0 { EPT[po+d]=(48+(ms%10)) as u8; ms=ms/10; d=d-1 } po=po+8
30 EPT[po]=0x2D as u8; po=po+1; EPT[po]=0 as u8
31
32 let cap: i64 = 8192
33 let sb: *u8 = sys_mmap(cap); let fb: *u8 = sys_mmap(cap); let mb: *u8 = sys_mmap(cap); let hb: *u8 = sys_mmap(cap)
34 var pass: i64 = 0
35 var tot: i64 = 0
36
37 // seed the (aria, ellery) relationship
38 rel_update_pfx(EPT, "aria" as *u8, "ellery" as *u8, "acquaintance" as *u8, 20, "likes gardenias" as *u8, "content" as *u8, "met in spring" as *u8)
39
40 // T1 round-trip
41 tot = tot + 1
42 var t1: i64 = 0
43 var tr: i64 = rel_read5(EPT, "aria" as *u8, "ellery" as *u8, sb, fb, mb, hb, cap)
44 if tr == 20 { if r_streq(sb, "acquaintance" as *u8) == 1 { t1 = 1 } }
45 if t1 == 1 { pass=pass+1; rw("PASS T1 round-trip: stage=acquaintance, trust=20\n" as *u8) } else { rw("FAIL T1 tr=" as *u8); rn(tr); rw(" stage=" as *u8); rw(sb); rw("\n" as *u8) }
46
47 // T2 additive facts
48 rel_note_fact_pfx(EPT, "aria" as *u8, "ellery" as *u8, "has a dog named Max" as *u8)
49 tot = tot + 1
50 rel_read5(EPT, "aria" as *u8, "ellery" as *u8, sb, fb, mb, hb, cap)
51 var t2: i64 = 0
52 if r_find(fb, r_slen(fb), "gardenias" as *u8) == 1 { if r_find(fb, r_slen(fb), "Max" as *u8) == 1 { t2 = 1 } }
53 if t2 == 1 { pass=pass+1; rw("PASS T2 additive facts: both 'gardenias' and 'Max' retained (no loss)\n" as *u8) } else { rw("FAIL T2 facts=" as *u8); rw(fb); rw("\n" as *u8) }
54
55 // T3 trust clamp -- high then low
56 rel_bump_trust_pfx(EPT, "aria" as *u8, "ellery" as *u8, 90) // 20+90=110 -> 100
57 tot = tot + 1
58 var thi: i64 = rel_read5(EPT, "aria" as *u8, "ellery" as *u8, sb, fb, mb, hb, cap)
59 rel_bump_trust_pfx(EPT, "aria" as *u8, "ellery" as *u8, 0 - 500) // ->0
60 var tlo: i64 = rel_read5(EPT, "aria" as *u8, "ellery" as *u8, sb, fb, mb, hb, cap)
61 if thi == 100 { if tlo == 0 { pass=pass+1; rw("PASS T3 trust clamp: +90 -> 100 (max), -500 -> 0 (min)\n" as *u8) } else { rw("FAIL T3 tlo=" as *u8); rn(tlo); rw("\n" as *u8) } } else { rw("FAIL T3 thi=" as *u8); rn(thi); rw("\n" as *u8) }
62
63 // restore a realistic trust, then change stage -- proving RMW preserves the other fields
64 rel_bump_trust_pfx(EPT, "aria" as *u8, "ellery" as *u8, 75) // 0+75=75
65 rel_set_stage_pfx(EPT, "aria" as *u8, "ellery" as *u8, "close" as *u8)
66 tot = tot + 1
67 var tfin: i64 = rel_read5(EPT, "aria" as *u8, "ellery" as *u8, sb, fb, mb, hb, cap)
68 var t4: i64 = 0
69 if r_streq(sb, "close" as *u8) == 1 { if tfin == 75 { if r_find(fb, r_slen(fb), "gardenias" as *u8) == 1 { if r_find(fb, r_slen(fb), "Max" as *u8) == 1 { t4 = 1 } } } }
70 if t4 == 1 { pass=pass+1; rw("PASS T4 lossless RMW: set stage=close, trust=75 preserved, facts intact\n" as *u8) } else { rw("FAIL T4 stage=" as *u8); rw(sb); rw(" trust=" as *u8); rn(tfin); rw("\n" as *u8) }
71
72 // T5 context projection
73 tot = tot + 1
74 let ctx: *u8 = sys_mmap(4096)
75 let cl: i64 = rel_context_pfx(EPT, "aria" as *u8, "ellery" as *u8, ctx, 4096)
76 var t5: i64 = 0
77 if cl > 0 { if r_find(ctx, cl, "close" as *u8) == 1 { if r_find(ctx, cl, "gardenias" as *u8) == 1 { if r_find(ctx, cl, "Max" as *u8) == 1 { t5 = 1 } } } }
78 if t5 == 1 { pass=pass+1; rw("PASS T5 context projection: carries stage + durable facts\n" as *u8) } else { rw("FAIL T5 ctx=" as *u8); rw(ctx); rw("\n" as *u8) }
79
80 // T6 neg -- unknown relationship
81 tot = tot + 1
82 let cl2: i64 = rel_context_pfx(EPT, "vera" as *u8, "nobody" as *u8, ctx, 4096)
83 if cl2 == 0 { pass=pass+1; rw("PASS T6 neg-control: unknown (persona,user) -> empty context\n" as *u8) } else { rw("FAIL T6 cl2=" as *u8); rn(cl2); rw("\n" as *u8) }
84
85 // T7 ISOLATION -- vera's relationship with ellery is independent of aria's
86 rel_update_pfx(EPT, "vera" as *u8, "ellery" as *u8, "stranger" as *u8, 5, "guards her privacy" as *u8, "reserved" as *u8, "just met" as *u8)
87 tot = tot + 1
88 var t7: i64 = 0
89 rel_read5(EPT, "aria" as *u8, "ellery" as *u8, sb, fb, mb, hb, cap) // aria unchanged?
90 if r_streq(sb, "close" as *u8) == 1 {
91 rel_read5(EPT, "vera" as *u8, "ellery" as *u8, sb, fb, mb, hb, cap)
92 if r_streq(sb, "stranger" as *u8) == 1 { t7 = 1 }
93 }
94 if t7 == 1 { pass=pass+1; rw("PASS T7 isolation: (aria,ellery)=close is independent of (vera,ellery)=stranger\n" as *u8) } else { rw("FAIL T7 stage=" as *u8); rw(sb); rw("\n" as *u8) }
95
96 rw("nx_companion_rel_gate pass=" as *u8); rn(pass); rw("/" as *u8); rn(tot)
97 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check
98 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled
99 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify.
100 let ctr__dry: *i64 = gv_ctr()
101 ctr__dry[0] = pass
102 ctr__dry[1] = tot
103 let rc__dry: i64 = gv_verdict("COMPANION-REL-GATE" as *u8, ctr__dry, "Elder's relationship state evolves per-user: additive facts, clamped trust, lossless, isolated)" as *u8)
104 sys_exit(rc__dry)
105 return rc__dry
106}