nx_vizsla_mcp_gate.nx source
↩ module page · 262 lines · 10858 B
1// nx_vizsla_mcp_gate.nx -- GATE: the VIZSLA coordination tools are REAL MCP-level APIs. Drives the
2// EXACT execution layer /mcp tools/call uses (nx_tool_exec_allow tea_resolve/tea_run_argv over the
3// PRODUCTION tool_allowlist.conf) + the discovery registry readback (what tools/list serves) + the
4// rich-schema conf rows. Nothing is mocked: the resolved blessed ELFs run with a real argv and their
5// real stdout comes back through the capture path -- exactly what an MCP client receives.
6//
7// Rows:
8// 1 registry-discovery tool_get readback for vizsla_plan + vizsla_doc (tools/list source)
9// 2 allowlist-resolve tea_resolve(production conf) vizsla_plan -> TEA_OK + the blessed elf path
10// 3 mcp-exec-plan tea_run_argv board over the demo store -> VIZSLA-PLAN-VERDICT captured
11// 4 mcp-exec-ics tea_run_argv ics export -> real .ics on disk + BEGIN:VCALENDAR + verdict
12// 5 mcp-exec-doc tea_run_argv doc put -> list captures docs=1 (mutating tool works e2e)
13// 6 blocked-non-green nx_http_probe row is RED -> TEA_BLOCKED, nothing executed [neg control]
14// 7 notfound-unknown ghost tool -> TEA_NOTFOUND [negative control]
15// 8 schema-rows tool_schemas.conf carries vizsla_plan + vizsla_doc annotation rows
16// Evidence: VIZSLA-MCP-GATE -> stdout + knowledge/status/vizsla_gate.log; exit 0 iff 8/8.
17// expect_exit: 0 license_tier: ORIGINAL
18import "nx_tool_exec_allow.nx"
19import "nx_tool_registry.nx"
20import "nx_gate_verdict.nx"
21
22func mg_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
23func mg_p(s: *u8) -> i64 { sys_write(1, s, mg_slen(s)); return 0 }
24
25func mg_cat(dst: *u8, off: i64, s: *u8) -> i64 {
26 var i: i64 = 0
27 while s[i] != (0 as u8) { dst[off + i] = s[i]; i = i + 1 }
28 return off + i
29}
30
31func mg_catn(dst: *u8, off: i64, v: i64) -> i64 {
32 var o: i64 = off
33 var m: i64 = v
34 if m < 0 { dst[o] = 45 as u8; o = o + 1; m = 0 - m }
35 let t: *u8 = sys_mmap(28)
36 var k: i64 = 0
37 if m == 0 { t[0] = 48 as u8; k = 1 }
38 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
39 var i: i64 = 0
40 while i < k { dst[o + i] = t[k - 1 - i]; i = i + 1 }
41 return o + k
42}
43
44func mg_readall(path: *u8, szout: *i64) -> *u8 {
45 let fd: i64 = sys_openat_rd(path)
46 if fd < 0 { szout[0] = 0 - 1; return 0 as *u8 }
47 let sz: i64 = sys_lseek(fd, 0, 2)
48 sys_lseek(fd, 0, 0)
49 let buf: *u8 = sys_mmap(sz + 64)
50 var got: i64 = 0
51 var n: i64 = 1
52 while n > 0 {
53 n = sys_read(fd, (buf as i64 + got) as *u8, 65536)
54 if n > 0 { got = got + n }
55 }
56 sys_close(fd)
57 szout[0] = got
58 return buf
59}
60
61func mg_memhas(b: *u8, sz: i64, needle: *u8) -> i64 {
62 let n: i64 = mg_slen(needle)
63 if sz < n { return 0 }
64 var i: i64 = 0
65 while i + n <= sz {
66 var ok: i64 = 1
67 var j: i64 = 0
68 while j < n {
69 if b[i + j] != needle[j] { ok = 0; j = n } else { j = j + 1 }
70 }
71 if ok == 1 { return 1 }
72 i = i + 1
73 }
74 return 0
75}
76
77func mg_filehas(path: *u8, needle: *u8) -> i64 {
78 let szp: *i64 = sys_mmap(16) as *i64
79 let b: *u8 = mg_readall(path, szp)
80 if szp[0] <= 0 { return 0 }
81 return mg_memhas(b, szp[0], needle)
82}
83
84func mg_row(name: *u8, pass: i64) -> i64 {
85 mg_p("ROW " as *u8)
86 mg_p(name)
87 if pass == 1 { mg_p(" PASS\n" as *u8) } else { mg_p(" FAIL\n" as *u8) }
88 return pass
89}
90
91func main(argc: i64, argv: *i64) -> i64 {
92 mg_p("=== VIZSLA MCP GATE: coordination tools live on the tools/call execution plane ===\n" as *u8)
93 let conf: *u8 = "tool_allowlist.conf" as *u8
94 var pass: i64 = 0
95 var r: i64 = 0
96
97 // row 1: discovery registry readback (the tools/list source)
98 let p1: *i64 = sys_mmap(8) as *i64
99 let l1: *i64 = sys_mmap(8) as *i64
100 let g1: i64 = tool_get("vizsla_plan" as *u8, p1, l1)
101 let g2: i64 = tool_get("vizsla_doc" as *u8, p1, l1)
102 r = 0
103 if g1 == 1 { if g2 == 1 { r = 1 } }
104 pass = pass + mg_row("registry-discovery" as *u8, r)
105
106 // row 2: production allowlist resolves the tool NAME to the blessed elf
107 let path: *u8 = sys_mmap(4096)
108 let code: i64 = tea_resolve_from(conf, "vizsla_plan" as *u8, 11, path, 4096)
109 r = 0
110 if code == TEA_OK {
111 if mg_memhas(path, mg_slen(path), "_offc/nx_vizsla_plan.elf" as *u8) == 1 { r = 1 }
112 }
113 pass = pass + mg_row("allowlist-resolve" as *u8, r)
114
115 // row 3: EXECUTE vizsla_plan board over the demo store via the tools/call layer
116 let av: *i64 = sys_mmap(8 * 12) as *i64
117 av[0] = 0
118 av[1] = "board" as *u8 as i64
119 av[2] = "knowledge/vizsla/demo/plan-" as *u8 as i64
120 av[3] = "summer" as *u8 as i64
121 av[4] = "2026-07-08" as *u8 as i64
122 av[5] = 0
123 let out: *u8 = sys_mmap(16384)
124 let outlen: *i64 = sys_mmap(16) as *i64
125 let rc: *i64 = sys_mmap(16) as *i64
126 let x3: i64 = tea_run_argv_from(conf, "vizsla_plan" as *u8, 11, av, out, 16384, outlen, rc)
127 r = 0
128 if x3 == 0 { if rc[0] == TEA_OK {
129 if mg_memhas(out, outlen[0], "VIZSLA-PLAN-VERDICT plan=summer" as *u8) == 1 {
130 if mg_memhas(out, outlen[0], "VIZSLA-PLAN-CRITICAL plan=summer" as *u8) == 1 { r = 1 }
131 }
132 } }
133 pass = pass + mg_row("mcp-exec-plan" as *u8, r)
134
135 // row 4: EXECUTE vizsla_ics export -- a side-effectful tool writes a REAL artifact
136 let av4: *i64 = sys_mmap(8 * 12) as *i64
137 av4[0] = 0
138 av4[1] = "export" as *u8 as i64
139 av4[2] = "knowledge/vizsla/demo/cal-" as *u8 as i64
140 av4[3] = "2026-07-01" as *u8 as i64
141 av4[4] = "2026-12-31" as *u8 as i64
142 av4[5] = "/tmp/vzm_mcp.ics" as *u8 as i64
143 av4[6] = 0
144 let x4: i64 = tea_run_argv_from(conf, "vizsla_ics" as *u8, 10, av4, out, 16384, outlen, rc)
145 r = 0
146 if x4 == 0 { if rc[0] == TEA_OK {
147 if mg_memhas(out, outlen[0], "VIZSLA-ICS-VERDICT events=3 rules=2" as *u8) == 1 {
148 if mg_filehas("/tmp/vzm_mcp.ics" as *u8, "BEGIN:VCALENDAR" as *u8) == 1 {
149 if mg_filehas("/tmp/vzm_mcp.ics" as *u8, "RRULE:FREQ=YEARLY" as *u8) == 1 { r = 1 }
150 }
151 }
152 } }
153 pass = pass + mg_row("mcp-exec-ics" as *u8, r)
154
155 // row 5: EXECUTE vizsla_doc put then list -- a MUTATING tool works end-to-end
156 let fdw: i64 = sys_openat_wr("/tmp/vzm_doc.txt" as *u8, 0x1a4)
157 if fdw >= 0 { sys_write(fdw, "mcp-plane document body\n" as *u8, 24); sys_close(fdw) }
158 let pfx: *u8 = sys_mmap(128)
159 var po: i64 = 0
160 po = mg_cat(pfx, po, "/tmp/vzmD" as *u8)
161 po = mg_catn(pfx, po, sys_now_us())
162 po = mg_cat(pfx, po, "-" as *u8)
163 pfx[po] = 0 as u8
164 let av5: *i64 = sys_mmap(8 * 12) as *i64
165 av5[0] = 0
166 av5[1] = "put" as *u8 as i64
167 av5[2] = pfx as i64
168 av5[3] = "mcpdoc" as *u8 as i64
169 av5[4] = "/tmp/vzm_doc.txt" as *u8 as i64
170 av5[5] = "note" as *u8 as i64
171 av5[6] = "plan:summer" as *u8 as i64
172 av5[7] = "2026-07-08" as *u8 as i64
173 av5[8] = "7401" as *u8 as i64
174 av5[9] = 0
175 let x5a: i64 = tea_run_argv_from(conf, "vizsla_doc" as *u8, 10, av5, out, 16384, outlen, rc)
176 var ok5: i64 = 0
177 if x5a == 0 { if mg_memhas(out, outlen[0], " new=1 segment=seg-7401" as *u8) == 1 { ok5 = 1 } }
178 let av5b: *i64 = sys_mmap(8 * 8) as *i64
179 av5b[0] = 0
180 av5b[1] = "list" as *u8 as i64
181 av5b[2] = pfx as i64
182 av5b[3] = "-" as *u8 as i64
183 av5b[4] = 0
184 let x5b: i64 = tea_run_argv_from(conf, "vizsla_doc" as *u8, 10, av5b, out, 16384, outlen, rc)
185 r = 0
186 if ok5 == 1 { if x5b == 0 {
187 if mg_memhas(out, outlen[0], "VIZSLA-DOC-LIST rel=- docs=1" as *u8) == 1 {
188 if mg_memhas(out, outlen[0], "docid=mcpdoc doctype=note rel=plan:summer" as *u8) == 1 { r = 1 }
189 }
190 } }
191 pass = pass + mg_row("mcp-exec-doc" as *u8, r)
192 // NOTE: the COMPOSING tool vizsla_notify (which double-forks: tools/call -> notify -> remind) is proven
193 // over tools/call by the SEPARATE nx_vizsla_notify_mcp_gate (3/3), kept in a fresh minimal process so the
194 // degraded WSL box's fork-accumulation flake (a 5th+ tr_run_capture fork can transiently fail) never
195 // masks a real result. Splitting keeps both gates deterministically GREEN and honest.
196
197 // row 6: RED-status tool is BLOCKED (negative control -- allowlist status is load-bearing)
198 let code6: i64 = tea_resolve_from(conf, "nx_http_probe" as *u8, 13, path, 4096)
199 r = 0
200 if code6 == TEA_BLOCKED { r = 1 }
201 pass = pass + mg_row("blocked-non-green" as *u8, r)
202
203 // row 7: unknown tool -> NOTFOUND (negative control)
204 let code7: i64 = tea_resolve_from(conf, "vizsla_ghost" as *u8, 12, path, 4096)
205 r = 0
206 if code7 == TEA_NOTFOUND { r = 1 }
207 pass = pass + mg_row("notfound-unknown" as *u8, r)
208
209 // row 8: rich MCP annotation rows present (tab-separated -- needles built with real TABs)
210 let nd: *u8 = sys_mmap(64)
211 var no: i64 = 0
212 no = mg_cat(nd, no, "vizsla_plan" as *u8)
213 nd[no] = 9 as u8; no = no + 1
214 no = mg_cat(nd, no, "Vizsla Planner" as *u8)
215 nd[no] = 0 as u8
216 let nd2: *u8 = sys_mmap(64)
217 no = 0
218 no = mg_cat(nd2, no, "vizsla_doc" as *u8)
219 nd2[no] = 9 as u8; no = no + 1
220 no = mg_cat(nd2, no, "Vizsla Documents" as *u8)
221 nd2[no] = 0 as u8
222 r = 0
223 if mg_filehas("knowledge/tool_schemas.conf" as *u8, nd) == 1 {
224 if mg_filehas("knowledge/tool_schemas.conf" as *u8, nd2) == 1 { r = 1 }
225 }
226 pass = pass + mg_row("schema-rows" as *u8, r)
227
228 let permil: i64 = (pass * 1000) / 8
229 let logfd: i64 = sys_openat_append("knowledge/status/vizsla_gate.log" as *u8, 0x1a4)
230 var fdi: i64 = 0
231 while fdi < 2 {
232 var fd: i64 = 1
233 if fdi == 1 { fd = logfd }
234 if fd > 0 {
235 let line: *u8 = sys_mmap(256)
236 var o: i64 = 0
237 o = mg_cat(line, o, "VIZSLA-MCP-GATE epoch=" as *u8)
238 o = mg_catn(line, o, sys_now_realtime_sec())
239 o = mg_cat(line, o, " rows=8 pass=" as *u8)
240 o = mg_catn(line, o, pass)
241 o = mg_cat(line, o, " permil=" as *u8)
242 o = mg_catn(line, o, permil)
243 if pass == 8 {
244 o = mg_cat(line, o, " verdict=GREEN\n" as *u8)
245 } else {
246 o = mg_cat(line, o, " verdict=RED\n" as *u8)
247 }
248 sys_write(fd, line, o)
249 }
250 fdi = fdi + 1
251 }
252 if logfd > 0 { sys_close(logfd) }
253 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check
254 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled
255 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify.
256 let ctr__dry: *i64 = gv_ctr()
257 ctr__dry[0] = pass
258 ctr__dry[1] = 8
259 let rc__dry: i64 = gv_verdict("VIZSLA-MCP-GATE" as *u8, ctr__dry, "teeth unchanged; verdict emission migrated onto the shared base class" as *u8)
260 sys_exit(rc__dry)
261 return rc__dry
262}