code wiki / _hdl_build / nx_tokgate.nx
nx_tokgate.nx source
↩ module page · 597 lines · 28235 B
1// nx_tokgate.nx -- TOKEN PRE-FLIGHT (engineshift ES17): the cheaper read is named BEFORE the expensive one lands.
2//
3// Operator 2026-09-02: "design the llm capabilities around minimizing unnecessary token usage autonomously
4// without my need for engagement as part of our standard ways of working without making the design and
5// coding and other stuff worse." MEASURED the same day by nx_seat_meter_beat residue over 40 days of this
6// seat's transcripts: reasoning 56 permil, authored 245 permil, MECHANICAL 668 permil -- two thirds of every
7// token is tool output re-read into context. The lever is the read, not the thinking.
8//
9// So this rides PreToolUse on Read and on the estate's nx_fs read. It sizes the subject and, when a whole-file
10// read would land more than the floor, names the digest that answers the same question in fewer bytes.
11// It NEVER blocks and emits nothing under the floor: (law) A PRE-FLIGHT THAT CAN REFUSE WILL BE DISABLED; ONE
12// THAT ONLY INFORMS SURVIVES -- and one that fires on every small read becomes noise that gets switched off.
13// (ASCII only in this file: a non-ASCII byte in the source arrived on the NAS twin 2 bytes longer through the
14// JSON argv lane, so the two trees could not be proven identical by hash.)
15// The floor is DATA (hooks/tokgate.conf, floor_bytes|N); when the conf is unreadable the bootstrap floor is
16// used and the message SAYS floor_src=bootstrap, so a silent default can never masquerade as a measurement.
17//
18// NO POWERSHELL IN THE PATH: this organ parses the hook JSON itself. Sibling of nx_memnew / nx_organnew.
19// nx_tokgate [conf-path] [shellverb-conf-path] stdin = the PreToolUse payload; stdout = {"systemMessage":...} or nothing
20//
21// ES22 / sovereignty SV3 (2026-09-05) -- THE SHELL INTERLOCK, tg_shell_interlock. Operator, verbatim: "stop using its own
22// tools when it loads and to use these and nishi estate only and if there is a gap to build into the nishi estate from
23// the first byte, no more ps1 and python and shell". The same organ now also rides PreToolUse on Bash and PowerShell:
24// it reads the command and, from DATA (hooks/shellverb.conf: tree | allow | verb rows), names the estate verb that does
25// the same work -- one row per DISTINCT verb, each stat'd against the declared source trees so the advisory can never
26// name a verb the tree cannot show (source=present / ABSENT / unverified) -- or prints GAP when no row matches, never
27// a guess. The sanctioned launcher (wsl -e _offc/<organ>.elf) is allow-listed by needle and draws nothing. Advisory
28// only: the interlock exists because the law was prose in two channels, and the estate has measured what happens to
29// an invariant that depends on a seat remembering (nx_memnew: the same doctrine written 4x with the organ one call away).
30// license_tier: ORIGINAL. No writes. No hw writes (Rule 26).
31import "nx_syscalls.nx"
32import "nx_gatekit_lib.nx"
33
34const TG_IN: i64 = 262144
35const TG_MSG: i64 = 65536
36const TG_PATH: i64 = 4096
37const TG_ROW: i64 = 256
38const TG_CONF_DEFAULT: *u8 = "/mnt/c/Users/elder/nishi-ops/hooks/tokgate.conf"
39const TG_FLOOR_BOOTSTRAP: i64 = 3072 // ONLY when the conf is unreadable, and the message names that source
40const TG_BYTES_PER_TOKEN: i64 = 4 // the estimate the message prints, declared as an estimate
41const TG_SRC_BOOTSTRAP: i64 = 0
42const TG_SRC_CONF: i64 = 1
43// ---- ES22 shell interlock ----
44const TG_SHELLCONF_DEFAULT: *u8 = "/mnt/c/Users/elder/nishi-ops/hooks/shellverb.conf"
45const TG_CMD: i64 = 65536 // a harness command body (the payload buffer TG_IN bounds it anyway)
46const TG_FIELD: i64 = 1024 // one conf field: needle, verb, note or source name
47const TG_VERB_TABLE: i64 = 64 // distinct verbs one advisory names before it says verbs_capped=1
48const TG_EXCERPT: i64 = 96 // bytes of the command echoed back so the reader sees WHICH call drew this
49const TG_MSG_RESERVE: i64 = 4096 // headroom kept for the closing lines; verb rows stop (announced) before it
50const TG_VS_ABSENT: i64 = 0 // tg_verb_source: no tree row holds <source>.nx
51const TG_VS_PRESENT: i64 = 1 // a tree row holds it
52const TG_VS_UNVERIFIED: i64 = 2 // the conf declares no tree row, so nothing could be checked
53// ---- bytes and shapes the code spells out, each named for its meaning (rule 11) ----
54const TG_CH_QUOTE: i64 = 34
55const TG_CH_BACKSLASH: i64 = 92
56const TG_CH_SLASH: i64 = 47
57const TG_CH_SPACE: i64 = 32
58const TG_CH_LF: i64 = 10
59const TG_CH_CR: i64 = 13
60const TG_CH_HASH: i64 = 35 // a comment row in a conf
61const TG_CH_PIPE: i64 = 124
62const TG_CH_COLON: i64 = 58
63const TG_CH_RBRACKET: i64 = 93
64const TG_CH_QMARK: i64 = 63 // what a unicode escape reads as for matching
65const TG_CH_n: i64 = 110
66const TG_CH_u: i64 = 117
67const TG_UPPER_A: i64 = 65
68const TG_UPPER_Z: i64 = 90
69const TG_CASE_DELTA: i64 = 32
70const TG_ZERO: i64 = 48
71const TG_NINE: i64 = 57
72const TG_DECIMAL: i64 = 10
73const TG_UESC_HEX_DIGITS: i64 = 4 // the four hex digits after backslash-u
74const TG_I64_BYTES: i64 = 8
75const TG_NUMBUF: i64 = 64
76const TG_MISMATCH: i64 = 9 // added to kl so the compare loop leaves on the first differing byte (never equals kl)
77const TG_FOUND_EOF: i64 = 2 // tg_strval: the key was seen but the payload ended before its value
78const TG_DRIVE_COLON_AT: i64 = 1 // X:/... -- where the colon and the slash of a Windows drive path sit
79const TG_DRIVE_SLASH_AT: i64 = 2
80const TG_DRIVE_PREFIX_LEN: i64 = 3
81const TG_ARGV_VERB: i64 = 0 // nx_fs argv: verb, path, byte cap
82const TG_ARGV_PATH: i64 = 1
83const TG_ARGV_CAP: i64 = 2
84const TG_ARG_CONF: i64 = 1 // this organ's own argv: the tokgate conf, then the shellverb conf
85const TG_ARG_SHELLCONF: i64 = 2
86const TG_COL_KIND: i64 = 0 // shellverb.conf columns
87const TG_COL_NEEDLE: i64 = 1
88const TG_COL_TREEDIR: i64 = 1 // a tree row carries its directory in the needle column
89const TG_COL_VERB: i64 = 2
90const TG_COL_NOTE: i64 = 3
91const TG_COL_SOURCE: i64 = 4
92
93// read all of stdin
94func tg_slurp(b: *u8, cap: i64) -> i64 {
95 var n: i64 = 0
96 var go: i64 = 1
97 while go == 1 {
98 let r: i64 = sys_read(0, (b as i64 + n) as *u8, cap - n - 1)
99 if r <= 0 { go = 0 }
100 if r > 0 {
101 n = n + r
102 if n >= cap - 1 { go = 0 }
103 }
104 }
105 b[n] = 0 as u8
106 return n
107}
108
109// the string value of a JSON key (`key` includes its quotes, e.g. "\"file_path\""). Not a JSON parser: the keys
110// this organ reads are unique in a hook payload and their values are plain strings, so a scan is exact.
111func tg_strval(b: *u8, n: i64, key: *u8, out: *u8, cap: i64) -> i64 {
112 let kl: i64 = gk_len(key)
113 var i: i64 = 0
114 while i + kl < n {
115 var j: i64 = 0
116 while j < kl {
117 if b[i + j] != key[j] { j = kl + TG_MISMATCH }
118 if j < kl { j = j + 1 }
119 }
120 if j == kl {
121 var p: i64 = i + kl
122 var found: i64 = 0
123 while found == 0 {
124 if p >= n { found = TG_FOUND_EOF }
125 if found == 0 {
126 if b[p] == TG_CH_QUOTE as u8 { found = 1 }
127 if found == 0 { p = p + 1 }
128 }
129 }
130 if found == 1 {
131 p = p + 1
132 var k: i64 = 0
133 var end: i64 = 0
134 while end == 0 {
135 if p >= n { end = 1 }
136 if end == 0 {
137 if b[p] == TG_CH_QUOTE as u8 { end = 1 }
138 if end == 0 {
139 var c: i64 = b[p] as i64
140 if c == TG_CH_BACKSLASH {
141 c = TG_CH_SLASH
142 if p + 1 < n {
143 if b[p + 1] == TG_CH_BACKSLASH as u8 { p = p + 1 }
144 }
145 }
146 if k < cap - 1 { out[k] = c as u8; k = k + 1 }
147 p = p + 1
148 }
149 }
150 }
151 out[k] = 0 as u8
152 return k
153 }
154 }
155 i = i + 1
156 }
157 out[0] = 0 as u8
158 return 0
159}
160
161// the idx-th string inside "argv":[ ... ]; -1 when the array ends first
162func tg_argv_str(b: *u8, n: i64, idx: i64, out: *u8, cap: i64) -> i64 {
163 let key: *u8 = "\"argv\":[" as *u8
164 let s: i64 = gk_out_pos(b, n, key)
165 out[0] = 0 as u8
166 if s < 0 { return 0 - 1 }
167 var p: i64 = s + gk_len(key)
168 var got: i64 = 0
169 while got <= idx {
170 // seek the next quote or the closing bracket
171 var seek: i64 = 1
172 while seek == 1 {
173 if p >= n { return 0 - 1 }
174 if b[p] == TG_CH_RBRACKET as u8 { return 0 - 1 }
175 if b[p] == TG_CH_QUOTE as u8 { seek = 0 } else { p = p + 1 }
176 }
177 p = p + 1
178 var k: i64 = 0
179 var end: i64 = 0
180 while end == 0 {
181 if p >= n { end = 1 }
182 if end == 0 {
183 if b[p] == TG_CH_QUOTE as u8 { end = 1 }
184 if end == 0 {
185 var c: i64 = b[p] as i64
186 if c == TG_CH_BACKSLASH { if p + 1 < n { p = p + 1; c = b[p] as i64 } }
187 if got == idx { if k < cap - 1 { out[k] = c as u8; k = k + 1 } }
188 p = p + 1
189 }
190 }
191 }
192 if got == idx { out[k] = 0 as u8; return k }
193 p = p + 1
194 got = got + 1
195 }
196 return 0 - 1
197}
198
199// the hook speaks WINDOWS paths; this organ runs in WSL. Every filesystem question is asked in /mnt/<drive>/ form.
200func tg_wsl(src: *u8, out: *u8, cap: i64) -> i64 {
201 let l: i64 = gk_len(src)
202 if l < TG_DRIVE_PREFIX_LEN { out[0] = 0 as u8; return 0 }
203 var drive: i64 = 0
204 if src[TG_DRIVE_COLON_AT] == TG_CH_COLON as u8 { if src[TG_DRIVE_SLASH_AT] == TG_CH_SLASH as u8 { drive = 1 } }
205 if drive == 0 {
206 var q: i64 = 0
207 while q < l { if q < cap - 1 { out[q] = src[q] } q = q + 1 }
208 out[l] = 0 as u8
209 return l
210 }
211 var o: i64 = gk_cat(out, 0, "/mnt/" as *u8)
212 var c: i64 = src[0] as i64
213 if c >= TG_UPPER_A { if c <= TG_UPPER_Z { c = c + TG_CASE_DELTA } }
214 out[o] = c as u8
215 o = o + 1
216 var i: i64 = TG_DRIVE_SLASH_AT
217 while i < l {
218 if o < cap - 1 { out[o] = src[i]; o = o + 1 }
219 i = i + 1
220 }
221 out[o] = 0 as u8
222 return o
223}
224
225func tg_base(p: *u8) -> *u8 {
226 let l: i64 = gk_len(p)
227 var i: i64 = l - 1
228 var s: i64 = 0
229 while i >= 0 {
230 if p[i] == TG_CH_SLASH as u8 { s = i + 1; i = 0 - 1 }
231 if i >= 0 { i = i - 1 }
232 }
233 return (p as i64 + s) as *u8
234}
235
236// the path ends in .jsonl (the suffix is bound ONCE and its length derived, so the two cannot drift)
237func tg_is_jsonl(p: *u8) -> i64 {
238 let suf: *u8 = ".jsonl" as *u8
239 let sl: i64 = gk_len(suf)
240 let l: i64 = gk_len(p)
241 if l < sl { return 0 }
242 var i: i64 = 0
243 while i < sl { if p[l - sl + i] != suf[i] { return 0 } i = i + 1 }
244 return 1
245}
246
247// JSON string body escapes for the message
248func tg_esc(dst: *u8, o: i64, src: *u8, n: i64) -> i64 {
249 var i: i64 = 0
250 var p: i64 = o
251 while i < n {
252 let c: i64 = src[i] as i64
253 if c == TG_CH_QUOTE { dst[p] = TG_CH_BACKSLASH as u8; p = p + 1; dst[p] = TG_CH_QUOTE as u8; p = p + 1 }
254 if c == TG_CH_BACKSLASH { dst[p] = TG_CH_BACKSLASH as u8; p = p + 1; dst[p] = TG_CH_BACKSLASH as u8; p = p + 1 }
255 if c == TG_CH_LF { dst[p] = TG_CH_BACKSLASH as u8; p = p + 1; dst[p] = TG_CH_n as u8; p = p + 1 }
256 if c != TG_CH_QUOTE { if c != TG_CH_BACKSLASH { if c != TG_CH_LF { if c != TG_CH_CR {
257 dst[p] = c as u8; p = p + 1
258 } } } }
259 i = i + 1
260 }
261 return p
262}
263func tg_escs(dst: *u8, o: i64, src: *u8) -> i64 { return tg_esc(dst, o, src, gk_len(src)) }
264func tg_escn(dst: *u8, o: i64, v: i64) -> i64 {
265 let t: *u8 = sys_mmap(TG_NUMBUF)
266 let tl: i64 = gk_catn(t, 0, v)
267 t[tl] = 0 as u8
268 return tg_esc(dst, o, t, tl)
269}
270
271// the floor from the conf row `floor_bytes|N`; src[0] = TG_SRC_CONF or TG_SRC_BOOTSTRAP
272func tg_floor(conf: *u8, src: *i64) -> i64 {
273 src[0] = TG_SRC_BOOTSTRAP
274 let lp: *i64 = sys_mmap(TG_I64_BYTES) as *i64
275 let b: *u8 = sys_read_file(conf, lp)
276 if (b as i64) == 0 { return TG_FLOOR_BOOTSTRAP }
277 let n: i64 = lp[0]
278 let key: *u8 = "floor_bytes|" as *u8
279 let kl: i64 = gk_len(key)
280 var i: i64 = 0
281 while i < n {
282 let e: i64 = gk_eol(b, i, n)
283 if e - i > kl { if b[i] != TG_CH_HASH as u8 {
284 var j: i64 = 0
285 var same: i64 = 1
286 while j < kl { if b[i + j] != key[j] { same = 0 } j = j + 1 }
287 if same == 1 {
288 var v: i64 = 0
289 var q: i64 = i + kl
290 while q < e { let c: i64 = b[q] as i64; if c >= TG_ZERO { if c <= TG_NINE { v = v * TG_DECIMAL + (c - TG_ZERO) } } q = q + 1 }
291 if v > 0 { src[0] = TG_SRC_CONF; return v }
292 }
293 } }
294 i = e + 1
295 }
296 return TG_FLOOR_BOOTSTRAP
297}
298
299func tg_emit(msg: *u8, m: i64) -> i64 {
300 var o: i64 = m
301 o = gk_cat(msg, o, "\"}" as *u8)
302 gk_write_all(1, msg, o)
303 return 0
304}
305
306// ES17 tg_advise: THE decision. Given the hook payload and the floor, build the advisory into msg and return its
307// length, or return 0 for silence. Pure over its inputs apart from one stat of the Read subject.
308func tg_advise(inb: *u8, n: i64, tool: *u8, floor: i64, fsrc: *i64, msg: *u8) -> i64 {
309 var m: i64 = gk_cat(msg, 0, "{\"systemMessage\":\"" as *u8)
310
311 // ---- Read: size the subject on disk ----
312 if gk_streq(tool, "Read" as *u8) == 1 {
313 let fp: *u8 = sys_mmap(TG_PATH)
314 if tg_strval(inb, n, "\"file_path\"" as *u8, fp, TG_PATH) == 0 { return 0 }
315 // a bounded read is already the cheap form
316 if gk_out_has(inb, n, "\"limit\"" as *u8) == 1 { return 0 }
317 let wp: *u8 = sys_mmap(TG_PATH)
318 tg_wsl(fp, wp, TG_PATH)
319 let sz: i64 = gk_size(wp)
320 if sz <= floor { return 0 }
321 m = tg_escs(msg, m, "TOKEN PRE-FLIGHT (ES17, advisory): " as *u8)
322 m = tg_escs(msg, m, tg_base(fp))
323 m = tg_escs(msg, m, " is " as *u8)
324 m = tg_escn(msg, m, sz)
325 m = tg_escs(msg, m, " B, about " as *u8)
326 m = tg_escn(msg, m, sz / TG_BYTES_PER_TOKEN)
327 m = tg_escs(msg, m, " tokens if read whole (floor " as *u8)
328 m = tg_escn(msg, m, floor)
329 m = tg_escs(msg, m, " B, floor_src=" as *u8)
330 if fsrc[0] == TG_SRC_CONF { m = tg_escs(msg, m, "conf" as *u8) } else { m = tg_escs(msg, m, "bootstrap" as *u8) }
331 m = tg_escs(msg, m, ").\nCheaper reads that answer most questions: Read with offset and limit on the region you need; Grep -n for the symbol first, then read that window; " as *u8)
332 if tg_is_jsonl(fp) == 1 { m = tg_escs(msg, m, "a .jsonl transcript belongs to nx_seat resume_map or nx_seat_meter_beat, not to a Read; " as *u8) }
333 m = tg_escs(msg, m, "an organ source usually answers from its header (Read limit 40). Measured 2026-09-02: 668 permil of this seat's tokens were tool output re-read into context. This message never blocks." as *u8)
334 return m
335 }
336
337 // ---- nx_fs read: the subject is on the NAS, so the byte cap is the whole question ----
338 if gk_streq(tool, "mcp__nishi__nx_fs" as *u8) == 1 {
339 let verb: *u8 = sys_mmap(TG_ROW)
340 if tg_argv_str(inb, n, TG_ARGV_VERB, verb, TG_ROW) < 0 { return 0 }
341 if gk_streq(verb, "read" as *u8) == 0 { return 0 }
342 let path: *u8 = sys_mmap(TG_PATH)
343 if tg_argv_str(inb, n, TG_ARGV_PATH, path, TG_PATH) < 0 { return 0 }
344 let capS: *u8 = sys_mmap(TG_ROW)
345 var cap: i64 = 0
346 if tg_argv_str(inb, n, TG_ARGV_CAP, capS, TG_ROW) > 0 {
347 var q: i64 = 0
348 while capS[q] != (0 as u8) { let c: i64 = capS[q] as i64; if c >= TG_ZERO { if c <= TG_NINE { cap = cap * TG_DECIMAL + (c - TG_ZERO) } } q = q + 1 }
349 }
350 if cap > 0 { if cap <= floor { return 0 } }
351 m = tg_escs(msg, m, "TOKEN PRE-FLIGHT (ES17, advisory): nx_fs read " as *u8)
352 m = tg_escs(msg, m, path)
353 if cap == 0 { m = tg_escs(msg, m, " with NO byte cap" as *u8) } else { m = tg_escs(msg, m, " with cap " as *u8); m = tg_escn(msg, m, cap); m = tg_escs(msg, m, " B" as *u8) }
354 m = tg_escs(msg, m, " (floor " as *u8)
355 m = tg_escn(msg, m, floor)
356 m = tg_escs(msg, m, " B, floor_src=" as *u8)
357 if fsrc[0] == TG_SRC_CONF { m = tg_escs(msg, m, "conf" as *u8) } else { m = tg_escs(msg, m, "bootstrap" as *u8) }
358 m = tg_escs(msg, m, ").\nCheaper: nx_fs size <path> first; then a window at most the floor at the offset you need (nx_fs read <path> <bytes> <offset>) or nx_fs lines <path> <start> <count>; " as *u8)
359 if gk_out_pos(path, gk_len(path), "_jobs/" as *u8) >= 0 { m = tg_escs(msg, m, "for a job artifact read _jobs/<id>.claim first: state=DONE bytes=N says whether it finished and how big it is; " as *u8) }
360 m = tg_escs(msg, m, "a receipt you already hold (bytes, hashes, prev=) needs no re-read. This message never blocks." as *u8)
361 return m
362 }
363 return 0
364}
365
366// ---------------------------------------------------------------------------------------------------------------
367// ES22 SHELL INTERLOCK (sovereignty SV3 shares the contract)
368// ---------------------------------------------------------------------------------------------------------------
369func tg_is_shell_tool(tool: *u8) -> i64 {
370 if gk_streq(tool, "Bash" as *u8) == 1 { return 1 }
371 if gk_streq(tool, "PowerShell" as *u8) == 1 { return 1 }
372 return 0
373}
374
375// the JSON string body of `key` (quotes included) with escapes DECODED for matching: backslash-quote is a quote, a
376// doubled backslash and an escaped slash both read as a slash (a needle never has to spell a backslash, and a Windows
377// path matches the same as a WSL one), control escapes read as a space, a unicode escape as a question mark.
378// tg_strval is deliberately NOT changed: the ES17 path relies on its slash convention for Windows file paths.
379func tg_jstr(b: *u8, n: i64, key: *u8, out: *u8, cap: i64) -> i64 {
380 out[0] = 0 as u8
381 let s: i64 = gk_out_pos(b, n, key)
382 if s < 0 { return 0 }
383 var p: i64 = s + gk_len(key)
384 var seek: i64 = 1
385 while seek == 1 {
386 if p >= n { return 0 }
387 if b[p] == TG_CH_QUOTE as u8 { seek = 0 } else { p = p + 1 }
388 }
389 p = p + 1
390 var k: i64 = 0
391 var end: i64 = 0
392 while end == 0 {
393 if p >= n { end = 1 }
394 if end == 0 {
395 var c: i64 = b[p] as i64
396 if c == TG_CH_QUOTE { end = 1 }
397 if end == 0 {
398 if c == TG_CH_BACKSLASH {
399 p = p + 1
400 if p >= n { end = 1 }
401 if end == 0 {
402 let e: i64 = b[p] as i64
403 c = TG_CH_SPACE
404 if e == TG_CH_QUOTE { c = TG_CH_QUOTE }
405 if e == TG_CH_BACKSLASH { c = TG_CH_SLASH }
406 if e == TG_CH_SLASH { c = TG_CH_SLASH }
407 if e == TG_CH_u { c = TG_CH_QMARK; p = p + TG_UESC_HEX_DIGITS }
408 }
409 }
410 }
411 if end == 0 {
412 if k < cap - 1 { out[k] = c as u8; k = k + 1 }
413 p = p + 1
414 }
415 }
416 }
417 out[k] = 0 as u8
418 return k
419}
420
421// the idx-th pipe-separated field of the row [s,e) into out (CR stripped, so a CRLF conf reads the same); its length
422func tg_field(b: *u8, s: i64, e: i64, idx: i64, out: *u8, cap: i64) -> i64 {
423 var p: i64 = s
424 var f: i64 = 0
425 var k: i64 = 0
426 var done: i64 = 0
427 while done == 0 {
428 if p >= e { done = 1 }
429 if done == 0 {
430 let c: i64 = b[p] as i64
431 if c == TG_CH_PIPE {
432 if f == idx { done = 1 }
433 f = f + 1
434 } else {
435 if f == idx { if c != TG_CH_CR { if k < cap - 1 { out[k] = c as u8; k = k + 1 } } }
436 }
437 p = p + 1
438 }
439 }
440 out[k] = 0 as u8
441 return k
442}
443
444// does <name>.nx exist under any tree| row of the conf? TG_VS_PRESENT / TG_VS_ABSENT / TG_VS_UNVERIFIED (no tree row
445// declared, so nothing could be looked at -- an advisory must say it could not look, never imply it did)
446func tg_verb_source(cb: *u8, cn: i64, name: *u8, kind: *u8, root: *u8, path: *u8) -> i64 {
447 var trees: i64 = 0
448 var i: i64 = 0
449 while i < cn {
450 let e: i64 = gk_eol(cb, i, cn)
451 if e > i { if cb[i] != TG_CH_HASH as u8 {
452 tg_field(cb, i, e, TG_COL_KIND, kind, TG_FIELD)
453 if gk_streq(kind, "tree" as *u8) == 1 {
454 trees = trees + 1
455 tg_field(cb, i, e, TG_COL_TREEDIR, root, TG_FIELD)
456 var o: i64 = gk_cat(path, 0, root)
457 o = gk_cat(path, o, name)
458 o = gk_cat(path, o, ".nx" as *u8)
459 path[o] = 0 as u8
460 if gk_exists(path) == 1 { return TG_VS_PRESENT }
461 }
462 } }
463 i = e + 1
464 }
465 if trees == 0 { return TG_VS_UNVERIFIED }
466 return TG_VS_ABSENT
467}
468
469// ES22 tg_shell_interlock: THE decision for a Bash or PowerShell call. Builds the advisory into msg and returns its
470// length; 0 is silence (no command in the payload, or the sanctioned launcher). Pure over the payload and the conf
471// apart from one stat per DISTINCT verb named.
472func tg_shell_interlock(inb: *u8, n: i64, tool: *u8, shellconf: *u8, msg: *u8) -> i64 {
473 let cmd: *u8 = sys_mmap(TG_CMD)
474 let cl: i64 = tg_jstr(inb, n, "\"command\"" as *u8, cmd, TG_CMD)
475 if cl <= 0 { return 0 }
476 var m: i64 = gk_cat(msg, 0, "{\"systemMessage\":\"" as *u8)
477 let lp: *i64 = sys_mmap(TG_I64_BYTES) as *i64
478 let cb: *u8 = sys_read_file(shellconf, lp)
479 if (cb as i64) == 0 {
480 m = tg_escs(msg, m, "SHELL PRE-FLIGHT (ES22, advisory): shellverb.conf unreadable at " as *u8)
481 m = tg_escs(msg, m, shellconf)
482 m = tg_escs(msg, m, " -- no verb table, so this " as *u8)
483 m = tg_escs(msg, m, tool)
484 m = tg_escs(msg, m, " call reads GAP by construction (conf_src=unreadable). Restore the table before trusting any silence from this hook. This message never blocks." as *u8)
485 return m
486 }
487 let cn: i64 = lp[0]
488 let kind: *u8 = sys_mmap(TG_FIELD)
489 let needle: *u8 = sys_mmap(TG_FIELD)
490 let note: *u8 = sys_mmap(TG_FIELD)
491 let srcn: *u8 = sys_mmap(TG_FIELD)
492 let root: *u8 = sys_mmap(TG_FIELD)
493 let path: *u8 = sys_mmap(TG_PATH)
494 // pass 1: the sanctioned launcher draws nothing
495 var i: i64 = 0
496 while i < cn {
497 let e: i64 = gk_eol(cb, i, cn)
498 if e > i { if cb[i] != TG_CH_HASH as u8 {
499 tg_field(cb, i, e, TG_COL_KIND, kind, TG_FIELD)
500 if gk_streq(kind, "allow" as *u8) == 1 {
501 if tg_field(cb, i, e, TG_COL_NEEDLE, needle, TG_FIELD) > 0 {
502 if gk_out_pos(cmd, cl, needle) >= 0 { return 0 }
503 }
504 }
505 } }
506 i = e + 1
507 }
508 // pass 2: every verb row whose needle is in the command -- one row per DISTINCT verb, each source stat'd
509 let seen: *u8 = sys_mmap(TG_VERB_TABLE * TG_FIELD)
510 var nseen: i64 = 0
511 var capped: i64 = 0
512 var truncated: i64 = 0
513 let body: *u8 = sys_mmap(TG_MSG)
514 var bm: i64 = 0
515 i = 0
516 while i < cn {
517 let e: i64 = gk_eol(cb, i, cn)
518 if e > i { if cb[i] != TG_CH_HASH as u8 {
519 tg_field(cb, i, e, TG_COL_KIND, kind, TG_FIELD)
520 if gk_streq(kind, "verb" as *u8) == 1 {
521 if tg_field(cb, i, e, TG_COL_NEEDLE, needle, TG_FIELD) > 0 {
522 if gk_out_pos(cmd, cl, needle) >= 0 {
523 if nseen >= TG_VERB_TABLE { capped = 1 } else {
524 let slot: *u8 = (seen as i64 + nseen * TG_FIELD) as *u8
525 tg_field(cb, i, e, TG_COL_VERB, slot, TG_FIELD)
526 var dup: i64 = 0
527 var s: i64 = 0
528 while s < nseen { if gk_streq((seen as i64 + s * TG_FIELD) as *u8, slot) == 1 { dup = 1 } s = s + 1 }
529 if dup == 0 {
530 if bm >= TG_MSG - TG_MSG_RESERVE { truncated = 1 } else {
531 tg_field(cb, i, e, TG_COL_NOTE, note, TG_FIELD)
532 if tg_field(cb, i, e, TG_COL_SOURCE, srcn, TG_FIELD) == 0 { let sl: i64 = gk_cat(srcn, 0, slot); srcn[sl] = 0 as u8 }
533 bm = tg_escs(body, bm, "\n " as *u8)
534 bm = tg_escs(body, bm, needle)
535 bm = tg_escs(body, bm, " -> mcp__nishi__" as *u8)
536 bm = tg_escs(body, bm, slot)
537 let pres: i64 = tg_verb_source(cb, cn, srcn, kind, root, path)
538 if pres == TG_VS_PRESENT { bm = tg_escs(body, bm, " source=present" as *u8) }
539 if pres == TG_VS_ABSENT { bm = tg_escs(body, bm, " source=ABSENT (no tree row holds its .nx: this row names a verb the tree cannot show -- fix the row, never trust it)" as *u8) }
540 if pres == TG_VS_UNVERIFIED { bm = tg_escs(body, bm, " source=unverified (the conf declares no tree row)" as *u8) }
541 if gk_len(note) > 0 { bm = tg_escs(body, bm, " -- " as *u8); bm = tg_escs(body, bm, note) }
542 }
543 nseen = nseen + 1
544 }
545 }
546 }
547 }
548 }
549 } }
550 i = e + 1
551 }
552 m = tg_escs(msg, m, "SHELL PRE-FLIGHT (ES22, advisory): the seat has one surface, the estate, and this " as *u8)
553 m = tg_escs(msg, m, tool)
554 m = tg_escs(msg, m, " call reaches for a shell. command: " as *u8)
555 var ex: i64 = cl
556 if ex > TG_EXCERPT { ex = TG_EXCERPT }
557 m = tg_esc(msg, m, cmd, ex)
558 if cl > TG_EXCERPT { m = tg_escs(msg, m, " ..." as *u8) }
559 if nseen == 0 {
560 m = tg_escs(msg, m, "\nGAP -- no verb row in " as *u8)
561 m = tg_escs(msg, m, shellconf)
562 m = tg_escs(msg, m, " matches this command. Declare it: a verb row (verb|needle|organ|note) there, and when no organ does this work yet, a rung on /compare/engineshift naming the build. Never a guessed verb." as *u8)
563 } else {
564 m = tg_escs(msg, m, "\nverbs=" as *u8)
565 m = tg_escn(msg, m, nseen)
566 m = tg_escs(msg, m, " -- the estate does this work:" as *u8)
567 var q: i64 = 0
568 while q < bm { msg[m] = body[q]; m = m + 1; q = q + 1 }
569 if capped == 1 { m = tg_escs(msg, m, "\nverbs_capped=1 (the table holds " as *u8); m = tg_escn(msg, m, TG_VERB_TABLE); m = tg_escs(msg, m, " distinct verbs; rows beyond it were counted, not shown)" as *u8) }
570 if truncated == 1 { m = tg_escs(msg, m, "\nrows_truncated=1 (message reserve reached; the verb count above is still complete)" as *u8) }
571 }
572 m = tg_escs(msg, m, "\nconf_src=conf. A denied MCP tool takes the cap token as the sibling parameter _cap. This message never blocks." as *u8)
573 return m
574}
575
576func main(argc: i64, argv: *i64) -> i64 {
577 var conf: *u8 = TG_CONF_DEFAULT
578 if argc > TG_ARG_CONF { conf = argv[TG_ARG_CONF] as *u8 }
579 var shellconf: *u8 = TG_SHELLCONF_DEFAULT
580 if argc > TG_ARG_SHELLCONF { shellconf = argv[TG_ARG_SHELLCONF] as *u8 }
581 let inb: *u8 = sys_mmap(TG_IN)
582 let n: i64 = tg_slurp(inb, TG_IN)
583 if n <= 0 { return 0 }
584 let tool: *u8 = sys_mmap(TG_ROW)
585 if tg_strval(inb, n, "\"tool_name\"" as *u8, tool, TG_ROW) == 0 { return 0 }
586 let msg: *u8 = sys_mmap(TG_MSG)
587 var m: i64 = 0
588 if tg_is_shell_tool(tool) == 1 {
589 m = tg_shell_interlock(inb, n, tool, shellconf, msg)
590 } else {
591 let fsrc: *i64 = sys_mmap(TG_I64_BYTES) as *i64
592 let floor: i64 = tg_floor(conf, fsrc)
593 m = tg_advise(inb, n, tool, floor, fsrc, msg)
594 }
595 if m > 0 { tg_emit(msg, m) }
596 return 0
597}