code wiki / _hdl_build / nx_connect_api_gate.nx
nx_connect_api_gate.nx source
↩ module page · 192 lines · 12194 B
1// nx_connect_api_gate.nx -- gate for the CONNECT MCP front door. Drives ca_dispatch with synthetic argv
2// arrays (exactly as the tools daemon will pass params.arguments.argv) and asserts on the emitted JSON.
3// This proves the MCP surface is faithful to the 8 gated engines and that its contract holds.
4// license_tier: ORIGINAL expect_exit: 0
5import "nx_syscalls.nx"
6import "nx_connect_api_lib.nx"
7
8func ag_w(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
9func ag_n(v: i64) -> i64 { let t: *u8=sys_mmap(32); let o: i64=ca_putn(t,0,v); t[o]=0 as u8; ag_w(t); return 0 }
10func ag_check(pass: i64, label: *u8, fails: *i64) -> i64 {
11 ag_w(" " as *u8); ag_w(label); ag_w(": " as *u8)
12 if pass==1 { ag_w("PASS\n" as *u8) } else { ag_w("FAIL\n" as *u8); fails[0]=fails[0]+1 }
13 return 0
14}
15func ag_has(buf: *u8, n: i64, needle: *u8) -> i64 {
16 let m: i64 = ca_slen(needle)
17 if m==0 { return 0 }
18 var i: i64=0
19 while i+m<=n {
20 var k: i64=0
21 var hit: i64=1
22 while k<m { if buf[i+k]!=needle[k] { hit=0; k=m } else { k=k+1 } }
23 if hit==1 { return 1 }
24 i=i+1
25 }
26 return 0
27}
28// build a synthetic argv from up to 14 NUL-terminated string args (0 to stop)
29func ag_argv(a0:*u8,a1:*u8,a2:*u8,a3:*u8,a4:*u8,a5:*u8,a6:*u8,a7:*u8,a8:*u8,a9:*u8,a10:*u8,a11:*u8,a12:*u8,a13:*u8, outc: *i64) -> *i64 {
30 let av: *i64 = sys_mmap(16*8) as *i64
31 var c: i64=0
32 if (a0 as i64)!=0 { av[c]=a0 as i64; c=c+1 } else { outc[0]=c; return av }
33 if (a1 as i64)!=0 { av[c]=a1 as i64; c=c+1 } else { outc[0]=c; return av }
34 if (a2 as i64)!=0 { av[c]=a2 as i64; c=c+1 } else { outc[0]=c; return av }
35 if (a3 as i64)!=0 { av[c]=a3 as i64; c=c+1 } else { outc[0]=c; return av }
36 if (a4 as i64)!=0 { av[c]=a4 as i64; c=c+1 } else { outc[0]=c; return av }
37 if (a5 as i64)!=0 { av[c]=a5 as i64; c=c+1 } else { outc[0]=c; return av }
38 if (a6 as i64)!=0 { av[c]=a6 as i64; c=c+1 } else { outc[0]=c; return av }
39 if (a7 as i64)!=0 { av[c]=a7 as i64; c=c+1 } else { outc[0]=c; return av }
40 if (a8 as i64)!=0 { av[c]=a8 as i64; c=c+1 } else { outc[0]=c; return av }
41 if (a9 as i64)!=0 { av[c]=a9 as i64; c=c+1 } else { outc[0]=c; return av }
42 if (a10 as i64)!=0 { av[c]=a10 as i64; c=c+1 } else { outc[0]=c; return av }
43 if (a11 as i64)!=0 { av[c]=a11 as i64; c=c+1 } else { outc[0]=c; return av }
44 if (a12 as i64)!=0 { av[c]=a12 as i64; c=c+1 } else { outc[0]=c; return av }
45 if (a13 as i64)!=0 { av[c]=a13 as i64; c=c+1 } else { outc[0]=c; return av }
46 outc[0]=c
47 return av
48}
49
50func main() -> i64 {
51 let fails: *i64 = sys_mmap(16) as *i64
52 fails[0]=0
53 let out: *u8 = sys_mmap(65536)
54 let c: *i64 = sys_mmap(8) as *i64
55 let Z: *u8 = 0 as *u8
56 ag_w("=== nx_connect_api_gate -- the CONNECT MCP front door, JSON contract over 8 engines ===\n" as *u8)
57
58 // T1: help catalog is self-describing (agentic/workflow discovery) + carries the version envelope
59 var av: *i64 = ag_argv("help" as *u8, Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z, c)
60 var n: i64 = ca_dispatch(c[0], av, out)
61 var t1: i64=1
62 if ag_has(out, n, "\"v\":1" as *u8)==0 { t1=0 }
63 if ag_has(out, n, "\"tool\":\"nx_connect\"" as *u8)==0 { t1=0 }
64 if ag_has(out, n, "\"stateless\":1" as *u8)==0 { t1=0 }
65 if ag_has(out, n, "\"name\":\"match\"" as *u8)==0 { t1=0 }
66 if ag_has(out, n, "\"name\":\"group_remove\"" as *u8)==0 { t1=0 }
67 ag_check(t1, "T1 help: versioned envelope + self-describing verb catalog (8 verbs, stateless flag)" as *u8, fails)
68
69 // T2: match agrees with mx_match_weight -- reciprocal pair 45, one-sided 0, minor+date excluded
70 av = ag_argv("match" as *u8,"30" as *u8,"16" as *u8,"1" as *u8,"5" as *u8,"27" as *u8,"1" as *u8,"16" as *u8,"9" as *u8,"0" as *u8,Z,Z,Z,Z, c)
71 n = ca_dispatch(c[0], av, out)
72 var t2: i64=1
73 if ag_has(out, n, "\"weight\":45" as *u8)==0 { t2=0 }
74 av = ag_argv("match" as *u8,"30" as *u8,"16" as *u8,"1" as *u8,"5" as *u8,"29" as *u8,"4" as *u8,"16" as *u8,"1" as *u8,"0" as *u8,Z,Z,Z,Z, c)
75 n = ca_dispatch(c[0], av, out)
76 if ag_has(out, n, "\"weight\":0" as *u8)==0 { t2=0 } // Lena: learns French, one-sided
77 av = ag_argv("match" as *u8,"30" as *u8,"16" as *u8,"1" as *u8,"5" as *u8,"14" as *u8,"1" as *u8,"16" as *u8,"5" as *u8,"3" as *u8,Z,Z,Z,Z, c)
78 n = ca_dispatch(c[0], av, out)
79 if ag_has(out, n, "\"excluded\":1" as *u8)==0 { t2=0 } // minor on the DATE lane
80 ag_check(t2, "T2 match: 45 / 0 / excluded match the engine (reciprocal, one-sided, minor+date)" as *u8, fails)
81
82 // T3: lane refuses unilateral escalation and names the active lane
83 av = ag_argv("lane" as *u8,"3" as *u8,"0" as *u8,"1" as *u8,"1" as *u8,"0" as *u8,Z,Z,Z,Z,Z,Z,Z,Z, c)
84 n = ca_dispatch(c[0], av, out)
85 var t3: i64=1
86 if ag_has(out, n, "\"lane\":0" as *u8)==0 { t3=0 }
87 if ag_has(out, n, "\"name\":\"Language exchange\"" as *u8)==0 { t3=0 }
88 ag_check(t3, "T3 lane: unilateral Dating request stays Language exchange (mutual-min), lane named" as *u8, fails)
89
90 // T4: youth wall -- a non-guardian adult<->minor 1:1 DM is blocked; two-deep group is allowed
91 av = ag_argv("youth" as *u8,"1" as *u8,"0" as *u8,"0" as *u8,"0" as *u8,"0" as *u8,Z,Z,Z,Z,Z,Z,Z,Z, c)
92 n = ca_dispatch(c[0], av, out)
93 var t4: i64=1
94 if ag_has(out, n, "\"allowed\":0" as *u8)==0 { t4=0 }
95 av = ag_argv("youth" as *u8,"1" as *u8,"0" as *u8,"0" as *u8,"1" as *u8,"2" as *u8,Z,Z,Z,Z,Z,Z,Z,Z, c)
96 n = ca_dispatch(c[0], av, out)
97 if ag_has(out, n, "\"allowed\":1" as *u8)==0 { t4=0 }
98 ag_check(t4, "T4 youth: 1:1 adult<->minor blocked, two-deep group allowed" as *u8, fails)
99
100 // T5: wards -- our 5 community-safe fields = 0 forbidden; an admin model with 3 = forbidden 3
101 av = ag_argv("wards" as *u8,"5" as *u8,"0" as *u8,"0" as *u8,"0" as *u8,"0" as *u8,"0" as *u8,Z,Z,Z,Z,Z,Z,Z, c)
102 n = ca_dispatch(c[0], av, out)
103 var t5: i64=1
104 if ag_has(out, n, "\"forbidden\":0" as *u8)==0 { t5=0 }
105 if ag_has(out, n, "\"community_safe\":1" as *u8)==0 { t5=0 }
106 av = ag_argv("wards" as *u8,"5" as *u8,"0" as *u8,"0" as *u8,"3" as *u8,"1" as *u8,"5" as *u8,Z,Z,Z,Z,Z,Z,Z, c)
107 n = ca_dispatch(c[0], av, out)
108 if ag_has(out, n, "\"forbidden\":3" as *u8)==0 { t5=0 }
109 ag_check(t5, "T5 wards: community schema 0 forbidden, admin model 3 (boundary is load-bearing)" as *u8, fails)
110
111 // T6: events -- capacity refuses when full; a minor on a non-youth event is -4
112 av = ag_argv("events_rsvp" as *u8,"6" as *u8,"0" as *u8,"6" as *u8,"0" as *u8,Z,Z,Z,Z,Z,Z,Z,Z,Z, c)
113 n = ca_dispatch(c[0], av, out)
114 var t6: i64=1
115 if ag_has(out, n, "\"code\":-2" as *u8)==0 { t6=0 } // full (6 present, cap 6)
116 av = ag_argv("events_rsvp" as *u8,"6" as *u8,"0" as *u8,"0" as *u8,"1" as *u8,Z,Z,Z,Z,Z,Z,Z,Z,Z, c)
117 n = ca_dispatch(c[0], av, out)
118 if ag_has(out, n, "\"code\":-4" as *u8)==0 { t6=0 } // minor on a non-youth event
119 av = ag_argv("events_rsvp" as *u8,"6" as *u8,"1" as *u8,"1" as *u8,"1" as *u8,Z,Z,Z,Z,Z,Z,Z,Z,Z, c)
120 n = ca_dispatch(c[0], av, out)
121 if ag_has(out, n, "\"code\":-3" as *u8)==0 { t6=0 } // youth event, only 1 adult -> two-deep
122 ag_check(t6, "T6 events_rsvp: -2 full, -4 minor-on-adult-event, -3 two-deep (real ev_rsvp verdicts)" as *u8, fails)
123
124 // T7: poll -- a voter on opt0 re-votes opt1; opt0 falls, opt1 rises, total unchanged (replace)
125 av = ag_argv("poll" as *u8,"2" as *u8,"1" as *u8,"0" as *u8,"1" as *u8,Z,Z,Z,Z,Z,Z,Z,Z,Z, c)
126 n = ca_dispatch(c[0], av, out)
127 var t7: i64=1
128 if ag_has(out, n, "\"tally\":[1,2,0]" as *u8)==0 { t7=0 } // was [2,1,0]; one opt0 voter moved to opt1
129 if ag_has(out, n, "\"total\":3" as *u8)==0 { t7=0 } // total unchanged -> replace not append
130 ag_check(t7, "T7 poll: revote REPLACES ([2,1,0]->[1,2,0], total stays 3)" as *u8, fails)
131
132 // T8: group_remove -- admin removes member (1); admin cannot remove a peer admin (0); owner unremovable (0)
133 av = ag_argv("group_remove" as *u8,"2" as *u8,"1" as *u8,"0" as *u8,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z, c)
134 n = ca_dispatch(c[0], av, out)
135 var t8: i64=1
136 if ag_has(out, n, "\"removed\":1" as *u8)==0 { t8=0 } // admin removes member
137 av = ag_argv("group_remove" as *u8,"2" as *u8,"2" as *u8,"0" as *u8,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z, c)
138 n = ca_dispatch(c[0], av, out)
139 if ag_has(out, n, "\"removed\":0" as *u8)==0 { t8=0 } // no peer-admin coup
140 av = ag_argv("group_remove" as *u8,"2" as *u8,"3" as *u8,"1" as *u8,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z, c)
141 n = ca_dispatch(c[0], av, out)
142 if ag_has(out, n, "\"removed\":0" as *u8)==0 { t8=0 } // owner unremovable
143 ag_check(t8, "T8 group_remove: admin removes member=1, peer-admin=0, owner=0 (no coup)" as *u8, fails)
144
145 // T9: STRUCTURED ERRORS -- unknown verb and a short arg list both return ok:0 with a slug, never crash
146 av = ag_argv("bogus" as *u8,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z, c)
147 n = ca_dispatch(c[0], av, out)
148 var t9: i64=1
149 if ag_has(out, n, "\"ok\":0" as *u8)==0 { t9=0 }
150 if ag_has(out, n, "\"error\":\"unknown_verb\"" as *u8)==0 { t9=0 }
151 av = ag_argv("match" as *u8,"1" as *u8,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z, c)
152 n = ca_dispatch(c[0], av, out)
153 if ag_has(out, n, "\"error\":\"usage\"" as *u8)==0 { t9=0 }
154 ag_check(t9, "T9 structured errors: unknown verb + short args return ok:0 + slug (never a crash)" as *u8, fails)
155
156 // T10: translate -- the language-exchange core, original preserved beside the translation
157 av = ag_argv("translate" as *u8,"1" as *u8,"0" as *u8,"привет друг" as *u8,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z, c)
158 n = ca_dispatch(c[0], av, out)
159 var t10: i64=1
160 if ag_has(out, n, "\"translation\":\"hello friend\"" as *u8)==0 { t10=0 }
161 if ag_has(out, n, "\"original\":\"привет друг\"" as *u8)==0 { t10=0 } // original kept, JSON-escaped clean
162 if ag_has(out, n, "\"unlimited\":1" as *u8)==0 { t10=0 }
163 av = ag_argv("translate" as *u8,"9" as *u8,"0" as *u8,"x" as *u8,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z, c)
164 n = ca_dispatch(c[0], av, out)
165 if ag_has(out, n, "\"error\":\"range\"" as *u8)==0 { t10=0 } // bad lang -> structured error
166 ag_check(t10, "T10 translate: ru->en 'hello friend' with original preserved; bad lang = structured error" as *u8, fails)
167
168 // T11: graph -- cross-silo unification. A and C share NO language but share hobby+faith+place: the
169 // language lane returns 0, the friendship lane finds them (84). The whole product thesis in one call.
170 // node = band teach learn hob faith optin place. A: teach EN(1) learn ES(2) hob MUSIC+COOK(5) faith 1 optin place 10.
171 // C: teach FR(4) learn DE(8) hob 21 faith 1 optin place 10 -> no reciprocal lang, shared hobby+faith+place.
172 // graph needs verb + 15 fields = 16 argv entries, beyond ag_argv's 14-slot helper, so build it manually.
173 let g: *i64 = sys_mmap(20*8) as *i64
174 g[0]="graph" as *u8 as i64
175 g[1]="1" as *u8 as i64; g[2]="1" as *u8 as i64; g[3]="2" as *u8 as i64; g[4]="5" as *u8 as i64; g[5]="1" as *u8 as i64; g[6]="1" as *u8 as i64; g[7]="10" as *u8 as i64
176 g[8]="1" as *u8 as i64; g[9]="4" as *u8 as i64; g[10]="8" as *u8 as i64; g[11]="21" as *u8 as i64; g[12]="1" as *u8 as i64; g[13]="1" as *u8 as i64; g[14]="10" as *u8 as i64
177 g[15]="1" as *u8 as i64 // FRIEND lane
178 n = ca_dispatch(16, g, out)
179 var t11: i64=1
180 if ag_has(out, n, "\"verb\":\"graph\"" as *u8)==0 { t11=0 }
181 if ag_has(out, n, "\"score\":84" as *u8)==0 { t11=0 } // cross-silo friendship found
182 g[15]="0" as *u8 as i64 // LANGUAGE lane
183 n = ca_dispatch(16, g, out)
184 if ag_has(out, n, "\"score\":0" as *u8)==0 { t11=0 } // no shared language -> 0 in the language lane
185 ag_check(t11, "T11 graph: cross-silo pair scores 84 in FRIEND lane, 0 in LANGUAGE lane (one model, the thesis)" as *u8, fails)
186
187 ag_w(" fails=" as *u8); ag_n(fails[0]); ag_w("\n" as *u8)
188 if fails[0]==0 { ag_w("VERDICT: verdict=GREEN (MCP front door: 8 engines behind one versioned, self-describing, stateless JSON contract)\n" as *u8); sys_exit(0) }
189 ag_w("VERDICT: verdict=RED\n" as *u8)
190 sys_exit(1)
191 return 1
192}