nx_tools_api_regression_gate_v3_t316.nx source
↩ module page · 350 lines · 26262 B
1// nx_tools_api_gate.nx -- drives ta_handle_pfx IN-PROCESS (no socket, no curl): register two test tools, then
2// assert the REST surface (/api/tools) and the MCP surface (/mcp: tools/list, initialize, error) are well-formed.
3// Proves R0 = MCP-compatible + superset, sovereignly. license_tier: ORIGINAL
4//
5// D001 MIGRATION 2026-08-25. This gate used to hand-roll pass/tot and sys_exit(0|1) while printing NO
6// verdict= line at all, so nx_gate_green read it UNJUDGEABLE and /api/gate_run could not report on it.
7// It now inherits nx_gate_verdict: one gv_check per tooth, so declared == executed BY CONSTRUCTION and
8// the counter moves by itself when a tooth is added. Every tooth condition is byte-for-byte the one it
9// had before the migration; only the counting and the verdict emission changed.
10//
11// WHY THIS MATTERED MORE THAN THE USUAL D001 ROW: the migration forces a rebuild, and a rebuild is the
12// only thing that relinks nx_tools_api.nx. The PROMOTED binary (331,191 B) still carried the pre-fix
13// job-start text "poll: nx_fs read _jobs/job_<id>.done (absent = RUNNING)" while the production daemon
14// has been emitting "Do NOT wait on .done: current jobs do not write it." -- so the live gate was scoring
15// 25/25 against a STALE in-process copy of the very library it exists to test.
16// *A GATE LINKED AGAINST A FROZEN COPY OF ITS SUBJECT REPORTS ON THE COPY, AND ITS GREEN NAMES THE WRONG
17// SUBJECT.* The freshness of an in-process gate is a property of its BUILD, not of its source.
18import "nx_tools_api_recovery_candidate_v3_t316.nx"
19import "nx_gate.nx"
20import "nx_gate_verdict.nx"
21
22func tg_has(out: *u8, n: i64, needle: *u8) -> i64 { if ta_indexof(out, n, needle) >= 0 { return 1 } return 0 }
23// occurrences of needle in out[0,n) (non-overlapping) -- the partition ruler for the list-order teeth
24func tg_count(out: *u8, n: i64, needle: *u8) -> i64 {
25 var nl: i64 = 0
26 while needle[nl] != (0 as u8) { nl = nl + 1 }
27 if nl == 0 { return 0 }
28 var cnt: i64 = 0
29 var i: i64 = 0
30 while i + nl <= n {
31 var k: i64 = 0
32 var ok: i64 = 1
33 while k < nl { if out[i + k] != needle[k] { ok = 0; k = nl } else { k = k + 1 } }
34 if ok == 1 { cnt = cnt + 1; i = i + nl } else { i = i + 1 }
35 }
36 return cnt
37}
38// NUL-terminated string at pointer `p` (an argv entry, stored as i64) equals the NUL-terminated `expect`?
39func tg_streq(p: i64, expect: *u8) -> i64 {
40 let a: *u8 = p as *u8
41 var i: i64 = 0
42 while expect[i] != (0 as u8) { if a[i] != expect[i] { return 0 } i = i + 1 }
43 if a[i] != (0 as u8) { return 0 }
44 return 1
45}
46// buf[o2[0], o2[0]+o2[1]) equals the NUL-terminated expect? (for offset/len pairs like ta_query_cap emits)
47func tg_slice_eq(buf: *u8, o2: *i64, expect: *u8) -> i64 {
48 var n: i64 = 0
49 while expect[n] != (0 as u8) { n = n + 1 }
50 if o2[1] != n { return 0 }
51 var i: i64 = 0
52 while i < n { if buf[o2[0] + i] != expect[i] { return 0 } i = i + 1 }
53 return 1
54}
55func tg_write(path: *u8, content: *u8) -> i64 {
56 let fd: i64 = __syscall(257, 0 - 100, path, 0x241, 0x1a4, 0, 0) // O_WRONLY|O_CREAT|O_TRUNC, 0644
57 if fd < 0 { return 0 - 1 }
58 var n: i64 = 0; while content[n] != (0 as u8) { n = n + 1 }
59 sys_write(fd, content, n); sys_close(fd)
60 return 0
61}
62
63func main() -> i64 {
64 let ctr: *i64 = gv_ctr()
65 gv_head("=== nx_tools_api_gate: sovereign agent-facing API (MCP-compatible + superset) ===" as *u8)
66 let TP: *u8 = "knowledge/toolreg-test-tapi-" as *u8
67 tool_register_pfx(TP, "nx_http_probe" as *u8, "sovereign HTTP GET probe" as *u8, "nx_http_probe <path>" as *u8, "gate-proven" as *u8)
68 tool_register_pfx(TP, "nx_mgmt_client" as *u8, "drive the control-plane over TLS-1.3" as *u8, "nx_mgmt_client <url> call ..." as *u8, "gate-10/10" as *u8)
69
70 let out: *u8 = sys_mmap(1048576)
71
72 // T1: GET /api/tools -> 200 + BOTH tools + the superset gate-status field (beyond MCP)
73 let r1: *u8 = "GET /api/tools HTTP/1.1\r\nHost: x\r\nConnection: close\r\n\r\n" as *u8
74 let n1: i64 = ta_handle_pfx(TP, r1, ta_slen(r1), out)
75 var t1: i64 = 0
76 if tg_has(out, n1, "200 OK" as *u8) == 1 { if tg_has(out, n1, "nx_http_probe" as *u8) == 1 { if tg_has(out, n1, "nx_mgmt_client" as *u8) == 1 { if tg_has(out, n1, "\"status\":\"gate-proven\"" as *u8) == 1 { t1 = 1 } } } }
77 gv_check("T1 REST /api/tools: 200 + both tools + gate-status (the beyond-MCP field)" as *u8, t1, ctr)
78
79 // T2: POST /mcp tools/list -> JSON-RPC 2.0, id echoed, MCP-shaped tools with inputSchema
80 let r2: *u8 = "POST /mcp HTTP/1.1\r\nHost: x\r\nContent-Type: application/json\r\nContent-Length: 47\r\n\r\n{\"jsonrpc\":\"2.0\",\"id\":7,\"method\":\"tools/list\"}" as *u8
81 let n2: i64 = ta_handle_pfx(TP, r2, ta_slen(r2), out)
82 var t2: i64 = 0
83 if tg_has(out, n2, "\"jsonrpc\":\"2.0\"" as *u8) == 1 { if tg_has(out, n2, "\"id\":7" as *u8) == 1 { if tg_has(out, n2, "\"inputSchema\"" as *u8) == 1 { if tg_has(out, n2, "nx_http_probe" as *u8) == 1 { t2 = 1 } } } }
84 gv_check("T2 MCP tools/list: JSON-RPC 2.0, id echoed, MCP-shaped tools" as *u8, t2, ctr)
85
86 // T3: POST /mcp initialize -> protocolVersion + serverInfo (handshake)
87 let r3: *u8 = "POST /mcp HTTP/1.1\r\nHost: x\r\nContent-Length: 46\r\n\r\n{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"initialize\"}" as *u8
88 let n3: i64 = ta_handle_pfx(TP, r3, ta_slen(r3), out)
89 var t3: i64 = 0
90 if tg_has(out, n3, "\"protocolVersion\"" as *u8) == 1 { if tg_has(out, n3, "\"serverInfo\"" as *u8) == 1 { t3 = 1 } }
91 gv_check("T3 MCP initialize: protocolVersion + serverInfo" as *u8, t3, ctr)
92
93 // T4: unknown method -> JSON-RPC error -32601 (fail-closed), id still echoed
94 let r4: *u8 = "POST /mcp HTTP/1.1\r\nHost: x\r\nContent-Length: 44\r\n\r\n{\"jsonrpc\":\"2.0\",\"id\":9,\"method\":\"bogus/x\"}" as *u8
95 let n4: i64 = ta_handle_pfx(TP, r4, ta_slen(r4), out)
96 var t4: i64 = 0
97 if tg_has(out, n4, "-32601" as *u8) == 1 { if tg_has(out, n4, "\"id\":9" as *u8) == 1 { t4 = 1 } }
98 gv_check("T4 MCP unknown method: JSON-RPC error -32601" as *u8, t4, ctr)
99
100 // T5: unknown path -> 404 not_found
101 let r5: *u8 = "GET /nope HTTP/1.1\r\nHost: x\r\n\r\n" as *u8
102 let n5: i64 = ta_handle_pfx(TP, r5, ta_slen(r5), out)
103 var t5: i64 = 0
104 if tg_has(out, n5, "404" as *u8) == 1 { t5 = 1 }
105 gv_check("T5 unknown path: 404 not_found" as *u8, t5, ctr)
106
107 // ---- R3: MCP resources (not tools-only) -- initialize advertises the capability; list + read serve content ----
108 let rr1: *u8 = "POST /mcp HTTP/1.1\r\nHost: x\r\n\r\n{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"initialize\"}" as *u8
109 let nr1: i64 = ta_handle_pfx(TP, rr1, ta_slen(rr1), out)
110 var tr1: i64 = 0
111 if tg_has(out, nr1, "\"resources\"" as *u8) == 1 { if tg_has(out, nr1, "\"prompts\"" as *u8) == 1 { tr1 = 1 } }
112 gv_check("T-R3a MCP initialize advertises the resources + prompts capabilities" as *u8, tr1, ctr)
113
114 let rr2: *u8 = "POST /mcp HTTP/1.1\r\nHost: x\r\n\r\n{\"jsonrpc\":\"2.0\",\"id\":2,\"method\":\"resources/list\"}" as *u8
115 let nr2: i64 = ta_handle_pfx(TP, rr2, ta_slen(rr2), out)
116 var tr2: i64 = 0
117 if tg_has(out, nr2, "nishi://sota/ecosystem-maturity" as *u8) == 1 { if tg_has(out, nr2, "nishi://doctrine/operating" as *u8) == 1 { tr2 = 1 } }
118 gv_check("T-R3b MCP resources/list -> 2 resource URIs (grade + doctrine)" as *u8, tr2, ctr)
119
120 let rr3: *u8 = "POST /mcp HTTP/1.1\r\nHost: x\r\n\r\n{\"jsonrpc\":\"2.0\",\"id\":3,\"method\":\"resources/read\",\"params\":{\"uri\":\"nishi://doctrine/operating\"}}" as *u8
121 let nr3: i64 = ta_handle_pfx(TP, rr3, ta_slen(rr3), out)
122 var tr3: i64 = 0
123 if tg_has(out, nr3, "\"contents\"" as *u8) == 1 { if tg_has(out, nr3, "nx_ship" as *u8) == 1 { tr3 = 1 } }
124 gv_check("T-R3c MCP resources/read doctrine -> contents with the operating text" as *u8, tr3, ctr)
125
126 let rp1: *u8 = "POST /mcp HTTP/1.1\r\nHost: x\r\n\r\n{\"jsonrpc\":\"2.0\",\"id\":4,\"method\":\"prompts/list\"}" as *u8
127 let np1: i64 = ta_handle_pfx(TP, rp1, ta_slen(rp1), out)
128 var tp1: i64 = 0
129 if tg_has(out, np1, "operate-nishi" as *u8) == 1 { if tg_has(out, np1, "ship-target" as *u8) == 1 { tp1 = 1 } }
130 gv_check("T-R3d MCP prompts/list -> 2 prompt templates" as *u8, tp1, ctr)
131
132 let rp2: *u8 = "POST /mcp HTTP/1.1\r\nHost: x\r\n\r\n{\"jsonrpc\":\"2.0\",\"id\":5,\"method\":\"prompts/get\",\"params\":{\"name\":\"ship-target\",\"arguments\":{\"target\":\"nx_widget\"}}}" as *u8
133 let np2: i64 = ta_handle_pfx(TP, rp2, ta_slen(rp2), out)
134 var tp2: i64 = 0
135 if tg_has(out, np2, "\"messages\"" as *u8) == 1 { if tg_has(out, np2, "nx_widget" as *u8) == 1 { tp2 = 1 } }
136 gv_check("T-R3e MCP prompts/get ship-target -> messages with the target arg filled" as *u8, tp2, ctr)
137
138 // ---- R2 argv passing: params.arguments.argv (JSON string array) -> native argv (multi-arg tools/call) ----
139 let av: *i64 = sys_mmap(8192) as *i64
140 let sb: *u8 = sys_mmap(65536)
141
142 // T6: a realistic 4-element argv is parsed positionally (this is exactly the nx_mgmt_client call shape)
143 let jb6: *u8 = "{\"params\":{\"name\":\"nx_mgmt_client\",\"arguments\":{\"argv\":[\"https://nishifamily.com\",\"call\",\"GET\",\"/api/health\"]}}}" as *u8
144 let ac6: i64 = ta_json_str_array(jb6, ta_slen(jb6), "\"argv\"" as *u8, av, 1, 250, sb, 65536)
145 var t6: i64 = 0
146 if ac6 == 4 { if tg_streq(av[1], "https://nishifamily.com" as *u8) == 1 { if tg_streq(av[2], "call" as *u8) == 1 { if tg_streq(av[3], "GET" as *u8) == 1 { if tg_streq(av[4], "/api/health" as *u8) == 1 { t6 = 1 } } } } }
147 gv_check("T6 tools/call argv: params.arguments.argv -> 4-element native argv (multi-arg organs callable)" as *u8, t6, ctr)
148
149 // T7: no argv key -> 0 args (argless back-compat: already-working no-arg tools are unaffected)
150 let jb7: *u8 = "{\"params\":{\"name\":\"nx_http_probe\",\"arguments\":{}}}" as *u8
151 let ac7: i64 = ta_json_str_array(jb7, ta_slen(jb7), "\"argv\"" as *u8, av, 1, 250, sb, 65536)
152 var t7: i64 = 0
153 if ac7 == 0 { t7 = 1 }
154 gv_check("T7 tools/call no argv -> 0 args (argless back-compat preserved)" as *u8, t7, ctr)
155
156 // T8: empty array [] -> 0 args (not treated as one empty arg)
157 let jb8: *u8 = "{\"argv\":[]}" as *u8
158 let ac8: i64 = ta_json_str_array(jb8, ta_slen(jb8), "\"argv\"" as *u8, av, 1, 250, sb, 65536)
159 var t8: i64 = 0
160 if ac8 == 0 { t8 = 1 }
161 gv_check("T8 tools/call empty argv [] -> 0 args" as *u8, t8, ctr)
162
163 // T9: an escaped quote inside an arg must NOT terminate the string early. Build the input as RAW BYTES so no
164 // backslash source-literal is needed: {"argv":["a\"b"]} -> exactly one arg whose value is a"b (3 bytes).
165 let eb: *u8 = sys_mmap(64)
166 var eo: i64 = ta_cat(eb, 0, "{\"argv\":[\"a" as *u8)
167 eb[eo] = 92 as u8; eo = eo + 1 // literal backslash
168 eb[eo] = 34 as u8; eo = eo + 1 // literal quote
169 eo = ta_cat(eb, eo, "b\"]}" as *u8)
170 let ac9: i64 = ta_json_str_array(eb, eo, "\"argv\"" as *u8, av, 1, 250, sb, 65536)
171 var t9: i64 = 0
172 if ac9 == 1 { if tg_streq(av[1], "a\"b" as *u8) == 1 { t9 = 1 } }
173 gv_check("T9 tools/call argv JSON-unescape: an escaped quote inside an arg does not split it" as *u8, t9, ctr)
174
175 // T10: maxn is honored -- a 4-element array with maxn=2 is REFUSED (-1), never silently truncated to 2.
176 // 2026-09-15: this tooth used to expect 2 while ta_json_str_array had moved to `if k >= maxn { return -1 }`
177 // (an argv cut at the cap would drop arguments in silence -- the NO SILENT CAPS law), so the source-fresh
178 // gate read RED on the laptop while the PROMOTED gate on the NAS read 25/25 GREEN: that binary was linked
179 // against the OLDER parser, exactly the frozen-copy class this gate's own header names. Migrated onto the
180 // value-emitting check so the count that came back is printed beside the expectation.
181 let ac10: i64 = ta_json_str_array(jb6, ta_slen(jb6), "\"argv\"" as *u8, av, 1, 2, sb, 65536)
182 gv_check_eq("T10 tools/call argv over the maxn cap (4 elems, maxn=2) is REFUSED -1, never silently truncated" as *u8, ac10, 0 - 1, ctr)
183
184 // ---- R1 rich MCP tool schemas: title + annotations (safety hints) + outputSchema, data-driven ----
185 tg_write("/tmp/tg_schemas.conf" as *u8, "argecho\tEcho Args\t1\t0\t1\t0\tnewline argv echo\n" as *u8)
186 let sb2: *u8 = sys_mmap(4096)
187
188 // T11: a KNOWN tool emits its title + ACCURATE annotations (read-only, non-destructive, idempotent) + outputSchema
189 let l11: i64 = ta_emit_mcp_schema_from("/tmp/tg_schemas.conf" as *u8, "argecho" as *u8, 7, sb2, 0)
190 var t11: i64 = 0
191 if tg_has(sb2, l11, "\"title\":\"Echo Args\"" as *u8) == 1 { if tg_has(sb2, l11, "\"readOnlyHint\":true" as *u8) == 1 { if tg_has(sb2, l11, "\"destructiveHint\":false" as *u8) == 1 { if tg_has(sb2, l11, "\"outputSchema\"" as *u8) == 1 { t11 = 1 } } } }
192 gv_check("T11 MCP rich schema: known tool -> title + accurate annotations + outputSchema (MCP tools-spec parity)" as *u8, t11, ctr)
193
194 // T12: an UNKNOWN tool -> MCP-safe DEFAULT annotations (NOT read-only, POSSIBLY destructive) + NO title (cautious)
195 let l12: i64 = ta_emit_mcp_schema_from("/tmp/tg_schemas.conf" as *u8, "nosuchtool" as *u8, 10, sb2, 0)
196 var t12: i64 = 0
197 if tg_has(sb2, l12, "\"readOnlyHint\":false" as *u8) == 1 { if tg_has(sb2, l12, "\"destructiveHint\":true" as *u8) == 1 { if tg_has(sb2, l12, "\"title\"" as *u8) == 0 { t12 = 1 } } }
198 gv_check("T12 MCP rich schema: unknown tool -> cautious default annotations, no title (safe-by-default)" as *u8, t12, ctr)
199
200 // ---- 07-30 QUERY-STRING CAP PRESENTER (ta_query_cap) + HONEST DENY -----------------------------------
201 // Closes the measured root cause of the shell-fallback cascade (debt seq1235): a client that drops the
202 // X-Nishi-Cap header denies EVERY call for a whole session, and the old deny text was indistinguishable
203 // from a missing tool. T14-T18 prove the parser; T19-T21 prove it is WIRED and the deny is honest.
204 let qo: *i64 = sys_mmap(16) as *i64
205
206 // T14: ?cap=<token> is extracted verbatim, and the presenter is COMPILED IN (liveness marker)
207 let q14: *u8 = "POST /mcp?cap=abc~123~7.def HTTP/1.1\r\nHost: x\r\n\r\n{}" as *u8
208 var t14: i64 = 0
209 if ta_query_cap_available() == 1 { if ta_query_cap(q14, ta_slen(q14), qo) == 1 { if tg_slice_eq(q14, qo, "abc~123~7.def" as *u8) == 1 { t14 = 1 } } }
210 gv_check("T14 query cap: ?cap=<token> extracted verbatim from the request line" as *u8, t14, ctr)
211
212 // T15: no query string at all -> absent (0), never a garbage slice
213 let q15: *u8 = "POST /mcp HTTP/1.1\r\nHost: x\r\n\r\n{}" as *u8
214 var t15: i64 = 0
215 if ta_query_cap(q15, ta_slen(q15), qo) == 0 { t15 = 1 }
216 gv_check("T15 query cap: no query string -> absent (fail-closed)" as *u8, t15, ctr)
217
218 // T16: a query with other params but no cap -> absent
219 let q16: *u8 = "POST /mcp?other=1&x=2 HTTP/1.1\r\nHost: x\r\n\r\n{}" as *u8
220 var t16: i64 = 0
221 if ta_query_cap(q16, ta_slen(q16), qo) == 0 { t16 = 1 }
222 gv_check("T16 query cap: query without a cap param -> absent" as *u8, t16, ctr)
223
224 // T17 NEG-CONTROL (the seq1293 substring-shadowing class): the key must match EXACTLY cap. A lookalike
225 // param must NEVER authorize -- otherwise recap= or capx= would silently present a capability.
226 let q17: *u8 = "POST /mcp?capx=zzz&recap=yyy&scap=www HTTP/1.1\r\nHost: x\r\n\r\n{}" as *u8
227 var t17: i64 = 0
228 if ta_query_cap(q17, ta_slen(q17), qo) == 0 { t17 = 1 }
229 gv_check("T17 neg-control query cap: capx/recap/scap lookalikes do NOT authorize (exact key only)" as *u8, t17, ctr)
230
231 // T18: cap as a NON-FIRST pair is found, and its value stops at & (not swallowing the rest of the query)
232 let q18: *u8 = "POST /mcp?a=1&cap=TOK99&z=9 HTTP/1.1\r\nHost: x\r\n\r\n{}" as *u8
233 var t18: i64 = 0
234 if ta_query_cap(q18, ta_slen(q18), qo) == 1 { if tg_slice_eq(q18, qo, "TOK99" as *u8) == 1 { t18 = 1 } }
235 gv_check("T18 query cap: found as a non-first pair, value terminates at &" as *u8, t18, ctr)
236
237 // T19: tools/call with NO cap -> the deny SAYS SO, says the tool exists, and says not to fall back to shell
238 let d19: *u8 = "POST /mcp HTTP/1.1\r\nHost: x\r\n\r\n{\"jsonrpc\":\"2.0\",\"id\":11,\"method\":\"tools/call\",\"params\":{\"name\":\"nx_http_probe\"}}" as *u8
239 let n19: i64 = ta_handle_pfx(TP, d19, ta_slen(d19), out)
240 var t19: i64 = 0
241 if tg_has(out, n19, "-32001" as *u8) == 1 { if tg_has(out, n19, "capability-absent" as *u8) == 1 { if tg_has(out, n19, "\"presented\":0" as *u8) == 1 { if tg_has(out, n19, "after-auth-correction" as *u8) == 1 { t19 = 1 } } } }
242 gv_check("T19 honest deny: no cap -> NO-capability-presented + presented:0 + do-not-shell (not no-such-tool)" as *u8, t19, ctr)
243
244 // T20: a PRESENTED-but-invalid cap gets the OPPOSITE message -- the two cases have opposite remedies
245 let d20: *u8 = "POST /mcp HTTP/1.1\r\nHost: x\r\n\r\n{\"jsonrpc\":\"2.0\",\"id\":12,\"method\":\"tools/call\",\"params\":{\"name\":\"nx_http_probe\",\"_cap\":\"bogus~1~1.zzz\"}}" as *u8
246 let n20: i64 = ta_handle_pfx(TP, d20, ta_slen(d20), out)
247 var t20: i64 = 0
248 if tg_has(out, n20, "\"presented\":1" as *u8) == 1 { if tg_has(out, n20, "single-presenter" as *u8) == 1 { if tg_has(out, n20, "capability-absent" as *u8) == 0 { t20 = 1 } } }
249 gv_check("T20 honest deny: invalid cap -> presented:1 + does-not-grant (distinct remedy)" as *u8, t20, ctr)
250
251 // T21 NON-VACUITY: the SAME bogus cap delivered ONLY via ?cap= must also report presented:1. This is the
252 // test that FAILS if ta_query_cap exists but is never called from ta_mcp_call -- it proves the WIRE.
253 let d21: *u8 = "POST /mcp?cap=bogus~1~1.zzz HTTP/1.1\r\nHost: x\r\n\r\n{\"jsonrpc\":\"2.0\",\"id\":13,\"method\":\"tools/call\",\"params\":{\"name\":\"nx_http_probe\"}}" as *u8
254 let n21: i64 = ta_handle_pfx(TP, d21, ta_slen(d21), out)
255 var t21: i64 = 0
256 if tg_has(out, n21, "\"presented\":1" as *u8) == 1 { if tg_has(out, n21, "capability-absent" as *u8) == 0 { t21 = 1 } }
257 gv_check("T21 non-vacuity: a cap presented ONLY via ?cap= reaches ta_mcp_call (presented:1) -- the wire is live" as *u8, t21, ctr)
258
259 // ---- 2026-09-15 LIST ORDER IS DATA (cap-first, most-called, newest) ------------------------------------
260 // The fixture plane TP holds nx_http_probe (registered first) and nx_mgmt_client (second); register a THIRD,
261 // newest tool. The rank file is derived from the plane prefix (ta_rank_path), so this gate ranks its own
262 // fixture plane and production's knowledge/status/toolrank-toolreg-.tsv is never touched.
263 tool_register_pfx(TP, "nx_zz_newest" as *u8, "newest fixture tool" as *u8, "nx_zz_newest" as *u8, "gate-proven" as *u8)
264 let rkp: *u8 = sys_mmap(512)
265 ta_rank_path(TP, rkp)
266 sys_unlinkat(rkp)
267 // T22: no cap, no rank file -> NEWEST registration first (a fresh tool lands inside any client window)
268 let o22: *u8 = "POST /mcp HTTP/1.1\r\nHost: x\r\n\r\n{\"jsonrpc\":\"2.0\",\"id\":22,\"method\":\"tools/list\"}" as *u8
269 let n22: i64 = ta_handle_pfx(TP, o22, ta_slen(o22), out)
270 let p22a: i64 = ta_indexof(out, n22, "\"name\":\"nx_zz_newest\"" as *u8)
271 let p22b: i64 = ta_indexof(out, n22, "\"name\":\"nx_mgmt_client\"" as *u8)
272 let p22c: i64 = ta_indexof(out, n22, "\"name\":\"nx_http_probe\"" as *u8)
273 var t22: i64 = 0
274 if p22a >= 0 { if p22b > p22a { if p22c > p22b { t22 = 1 } } }
275 gv_check("T22 list order: no cap, no rank -> NEWEST registration first (a fresh tool lands inside any client window)" as *u8, t22, ctr)
276 // T23: a rank row for the OLDEST tool lifts it ahead of the never-invoked tools, which stay newest-first
277 tg_write(rkp, "nx_http_probe\t5\t1789500000\n" as *u8)
278 let n23: i64 = ta_handle_pfx(TP, o22, ta_slen(o22), out)
279 let p23c: i64 = ta_indexof(out, n23, "\"name\":\"nx_http_probe\"" as *u8)
280 let p23a: i64 = ta_indexof(out, n23, "\"name\":\"nx_zz_newest\"" as *u8)
281 let p23b: i64 = ta_indexof(out, n23, "\"name\":\"nx_mgmt_client\"" as *u8)
282 var t23: i64 = 0
283 if p23c >= 0 { if p23a > p23c { if p23b > p23a { t23 = 1 } } }
284 gv_check("T23 list order: a most-called tool (rank tsv) precedes the never-invoked, which stay newest-first" as *u8, t23, ctr)
285 // T24: the presented ?cap= grants nx_mgmt_client -> it comes FIRST, ahead of the ranked and the newest
286 let o24: *u8 = "POST /mcp?cap=nx_mgmt_client~1~1.zzz HTTP/1.1\r\nHost: x\r\n\r\n{\"jsonrpc\":\"2.0\",\"id\":24,\"method\":\"tools/list\"}" as *u8
287 let n24: i64 = ta_handle_pfx(TP, o24, ta_slen(o24), out)
288 let p24b: i64 = ta_indexof(out, n24, "\"name\":\"nx_mgmt_client\"" as *u8)
289 let p24c: i64 = ta_indexof(out, n24, "\"name\":\"nx_http_probe\"" as *u8)
290 let p24a: i64 = ta_indexof(out, n24, "\"name\":\"nx_zz_newest\"" as *u8)
291 var t24: i64 = 0
292 if p24b >= 0 { if p24c > p24b { if p24a > p24c { t24 = 1 } } }
293 gv_check("T24 list order: the ?cap= grantee precedes the ranked and the newest -- a seat sees its own surface first" as *u8, t24, ctr)
294 // T25 PARTITION: every registered tool is emitted exactly once whatever the order (3 registered -> 3 rows)
295 var t25: i64 = 0
296 if tg_count(out, n24, "{\"name\":\"" as *u8) == 3 { if tg_count(out, n23, "{\"name\":\"" as *u8) == 3 { if tg_count(out, n22, "{\"name\":\"" as *u8) == 3 { t25 = 1 } } }
297 gv_check("T25 partition: cap + ranked + newest emit every registered tool exactly once (3 of 3, all three orders)" as *u8, t25, ctr)
298 // T26 NEG-CONTROL: a rank row naming an UNREGISTERED tool adds nothing -- the rank can reorder, never invent
299 tg_write(rkp, "nx_phantom_tool\t99\t1789500000\n" as *u8)
300 let n26: i64 = ta_handle_pfx(TP, o22, ta_slen(o22), out)
301 var t26: i64 = 0
302 if tg_has(out, n26, "nx_phantom_tool" as *u8) == 0 { if tg_count(out, n26, "{\"name\":\"" as *u8) == 3 { t26 = 1 } }
303 gv_check("T26 neg-control: a rank row for an unregistered name emits no phantom tool" as *u8, t26, ctr)
304 // T27: initialize announces the order (a feature that does not announce itself is indistinguishable from one never compiled in)
305 let n27: i64 = ta_handle_pfx(TP, r3, ta_slen(r3), out)
306 var t27: i64 = 0
307 if tg_has(out, n27, "\"listOrder\":\"cap-first,most-called,newest\"" as *u8) == 1 { t27 = 1 }
308 gv_check("T27 initialize announces listOrder=cap-first,most-called,newest" as *u8, t27, ctr)
309 sys_unlinkat(rkp)
310
311 // ---- EC50: a row registered AFTER the client listed reaches it by the protocol ----
312 let e1: *u8 = "POST /mcp HTTP/1.1\r\nHost: x\r\n\r\n{\"jsonrpc\":\"2.0\",\"id\":50,\"method\":\"initialize\"}" as *u8
313 let ne1: i64 = ta_handle_pfx(TP, e1, ta_slen(e1), out)
314 gv_check("T-EC50a initialize advertises tools.listChanged=true" as *u8, tg_has(out, ne1, "\"tools\":{\"listChanged\":true}" as *u8), ctr)
315 let e2: *u8 = "POST /mcp HTTP/1.1\r\nHost: x\r\n\r\n{\"jsonrpc\":\"2.0\",\"id\":51,\"method\":\"tools/list\"}" as *u8
316 let ne2: i64 = ta_handle_pfx(TP, e2, ta_slen(e2), out)
317 let g0: i64 = ta_reg_gen(TP)
318 let g0b: i64 = ta_reg_gen(TP)
319 gv_check("neg-control-T-EC50b two reads of the generation with no registration between them agree" as *u8, (g0 == g0b) as i64, ctr)
320 gv_check("T-EC50b2 the generation is readable (not the unreadable or over-bound sentinel)" as *u8, (g0 > 0) as i64, ctr)
321 tool_register_pfx(TP, "nx_ec50_fixture" as *u8, "registered after the client listed" as *u8, "nx_ec50_fixture" as *u8, "gate-fixture" as *u8)
322 let g1: i64 = ta_reg_gen(TP)
323 gv_check("T-EC50c a registration moves the generation" as *u8, (g1 != g0) as i64, ctr)
324 let e3: *u8 = "POST /mcp HTTP/1.1\r\nHost: x\r\nAccept: application/json, text/event-stream\r\n\r\n{\"jsonrpc\":\"2.0\",\"id\":52,\"method\":\"prompts/list\"}" as *u8
325 let ne3: i64 = ta_handle_pfx(TP, e3, ta_slen(e3), out)
326 var te3: i64 = 0
327 if tg_has(out, ne3, "Content-Type: text/event-stream" as *u8) == 1 { if tg_has(out, ne3, "notifications/tools/list_changed" as *u8) == 1 { if tg_has(out, ne3, "\"id\":52" as *u8) == 1 { te3 = 1 } } }
328 gv_check("T-EC50d after a registration an SSE-accepting request is answered as an event stream carrying list_changed and its result" as *u8, te3, ctr)
329 gv_check("T-EC50e the notification precedes the result in the stream" as *u8, (ta_indexof(out, ne3, "list_changed" as *u8) < ta_indexof(out, ne3, "\"id\":52" as *u8)) as i64, ctr)
330 let e3l: *u8 = "POST /mcp HTTP/1.1\r\nHost: x\r\naccept: text/event-stream\r\n\r\n{\"jsonrpc\":\"2.0\",\"id\":56,\"method\":\"prompts/list\"}" as *u8
331 let ne3l: i64 = ta_handle_pfx(TP, e3l, ta_slen(e3l), out)
332 gv_check("T-EC50d2 a lower-case accept header (a stock fetch client) is honoured too" as *u8, tg_has(out, ne3l, "notifications/tools/list_changed" as *u8), ctr)
333 let e4: *u8 = "POST /mcp HTTP/1.1\r\nHost: x\r\n\r\n{\"jsonrpc\":\"2.0\",\"id\":53,\"method\":\"prompts/list\"}" as *u8
334 let ne4: i64 = ta_handle_pfx(TP, e4, ta_slen(e4), out)
335 var te4: i64 = 0
336 if tg_has(out, ne4, "Content-Type: application/json" as *u8) == 1 { if tg_has(out, ne4, "list_changed" as *u8) == 0 { if tg_has(out, ne4, "\"id\":53" as *u8) == 1 { te4 = 1 } } }
337 gv_check("neg-control-T-EC50f a JSON-only client gets the plain JSON reply with no notification even on a moved generation" as *u8, te4, ctr)
338 let e5: *u8 = "POST /mcp HTTP/1.1\r\nHost: x\r\n\r\n{\"jsonrpc\":\"2.0\",\"id\":54,\"method\":\"tools/list\"}" as *u8
339 let ne5: i64 = ta_handle_pfx(TP, e5, ta_slen(e5), out)
340 gv_check("T-EC50g the re-list carries the freshly registered row" as *u8, tg_has(out, ne5, "nx_ec50_fixture" as *u8), ctr)
341 let e6: *u8 = "POST /mcp HTTP/1.1\r\nHost: x\r\nAccept: text/event-stream\r\n\r\n{\"jsonrpc\":\"2.0\",\"id\":55,\"method\":\"prompts/list\"}" as *u8
342 let ne6: i64 = ta_handle_pfx(TP, e6, ta_slen(e6), out)
343 var te6: i64 = 0
344 if tg_has(out, ne6, "Content-Type: application/json" as *u8) == 1 { if tg_has(out, ne6, "list_changed" as *u8) == 0 { te6 = 1 } }
345 gv_check("T-EC50h once the client has re-listed, the next SSE-accepting request carries no notification" as *u8, te6, ctr)
346
347 let rc: i64 = gv_verdict("TOOLS-API" as *u8, ctr, "in-process against the nx_tools_api linked into this binary -- no socket, no curl" as *u8)
348 sys_exit(rc)
349 return rc
350}