code wiki / _hdl_build / nx_vizsla_notes_gate.nx
nx_vizsla_notes_gate.nx source
↩ module page · 390 lines · 18038 B
1// nx_vizsla_notes_gate.nx -- VIZSLA V4b gate: the event-anchored timed
2// meaningful-note engine, proven against a HAND-COMPUTED fixture (oracle = this
3// header). No mocks: drives the real organ over real seg_store records.
4//
5// conf: window_days=3. today=2026-06-14.
6// events: e1 2026-06-20 mom birthday; e2 2026-07-01 alex surgery;
7// e3 2026-06-10 sam wedding; e4 2026-09-15 pat graduation.
8// notes:
9// n1 e1 BEFORE 7 card signature:img-mom -> release 06-13, deadline 06-20; SENT 06-14 -> SENT
10// n2 e2 BEFORE 3 text voice:vm-alex -> release 06-28, deadline 07-01; today<release -> WAITING
11// n3 e3 AFTER 2 card handwritten:scan-sam -> release 06-12, deadline 06-15; 06-12<=06-14<=06-15 -> DUE
12// n4 e4 ON 0 call text:congrats-pat -> release 09-15, deadline 09-18; today<release -> WAITING
13// n5 e3 BEFORE 7 card text:goodluck-sam -> release 06-03, deadline 06-10 (event); today>deadline -> LATE
14// => notes=5 waiting=2 due=1 late=1 sent=1 ; due-only = {n3}
15// DATA-DRIVEN: window_days=1 (only change) => n3 deadline 06-13, today 06-14 > -> LATE
16// => notes=5 waiting=2 due=0 late=2 sent=1, same binary.
17//
18// Rows:
19// 1 loud-fail-missing-conf schedule on absent conf => exit 1
20// 2 load-events scanned=10 new=10 segment=seg-7001
21// 3 idempotent-reload new=0 dup_instore=10 segment=none (law 10)
22// 4 before-waiting n2 BEFORE release=2026-06-28 WAITING
23// 5 after-due n3 AFTER release=2026-06-12 deadline=2026-06-15 DUE
24// 6 before-late n5 BEFORE release=2026-06-03 deadline=2026-06-10 LATE
25// 7 on-waiting n4 ON release=2026-09-15 WAITING
26// 8 sent-closes n1 SENT
27// 9 schedule-verdict notes=5 waiting=2 due=1 late=1 sent=1
28// 10 due-filter due lists n3 + DUE-VERDICT due=1 + WAITING absent
29// 11 release-date-inverse+personal n1 release=2026-06-13 + personal=signature:img-mom
30// 12 data-driven-window window=1 => verdict due=0 late=2 (same binary)
31// 13 loud-fail-unknown-event NOTE -> missing EVENT => schedule exit 1
32// 14 schedule-determinism byte-identical twice
33// Evidence: VIZSLA-NOTE-GATE -> stdout + knowledge/status/vizsla_gate.log; exit 0 iff 14/14.
34// Tamper: pass a bogus instrument path as argv[1] => all rows FAIL => RED.
35// spec: knowledge/specs/2026-06-14-thankyounotes-product-spec.md license_tier: ORIGINAL
36import "nx_syscalls.nx"
37
38func rg_slen(s: *u8) -> i64 {
39 var n: i64 = 0
40 while s[n] != (0 as u8) { n = n + 1 }
41 return n
42}
43
44func rg_p(s: *u8) -> i64 {
45 sys_write(1, s, rg_slen(s))
46 return 0
47}
48
49func rg_cat(dst: *u8, off: i64, s: *u8) -> i64 {
50 var i: i64 = 0
51 while s[i] != (0 as u8) { dst[off + i] = s[i]; i = i + 1 }
52 return off + i
53}
54
55func rg_catn(dst: *u8, off: i64, v: i64) -> i64 {
56 var o: i64 = off
57 var m: i64 = v
58 if m < 0 { dst[o] = 45 as u8; o = o + 1; m = 0 - m }
59 let t: *u8 = sys_mmap(28)
60 var k: i64 = 0
61 if m == 0 { t[0] = 48 as u8; k = 1 }
62 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
63 var i: i64 = 0
64 while i < k { dst[o + i] = t[k - 1 - i]; i = i + 1 }
65 return o + k
66}
67
68func rg_write(path: *u8, content: *u8) -> i64 {
69 let fd: i64 = sys_openat_wr(path, 0x1a4)
70 if fd < 0 { return 0 - 1 }
71 sys_write(fd, content, rg_slen(content))
72 sys_close(fd)
73 return 0
74}
75
76func rg_readall(path: *u8, szout: *i64) -> *u8 {
77 let fd: i64 = sys_openat_rd(path)
78 if fd < 0 { szout[0] = 0 - 1; return 0 as *u8 }
79 let sz: i64 = sys_lseek(fd, 0, 2)
80 sys_lseek(fd, 0, 0)
81 let buf: *u8 = sys_mmap(sz + 64)
82 var got: i64 = 0
83 var n: i64 = 1
84 while n > 0 {
85 n = sys_read(fd, (buf as i64 + got) as *u8, 65536)
86 if n > 0 { got = got + n }
87 }
88 sys_close(fd)
89 szout[0] = got
90 return buf
91}
92
93func rg_run(elf: *u8, a1: *u8, a2: *u8, a3: *u8, a4: *u8, outpath: *u8) -> i64 {
94 let pid: i64 = sys_fork()
95 if pid == 0 {
96 if (outpath as i64) != 0 {
97 let ofd: i64 = sys_openat_wr(outpath, 0x1a4)
98 if ofd >= 0 { sys_dup3(ofd, 1, 0); sys_dup3(ofd, 2, 0) }
99 }
100 let argv: *i64 = sys_mmap(64) as *i64
101 argv[0] = elf as i64
102 var i: i64 = 1
103 if (a1 as i64) != 0 { argv[i] = a1 as i64; i = i + 1 }
104 if (a2 as i64) != 0 { argv[i] = a2 as i64; i = i + 1 }
105 if (a3 as i64) != 0 { argv[i] = a3 as i64; i = i + 1 }
106 if (a4 as i64) != 0 { argv[i] = a4 as i64; i = i + 1 }
107 argv[i] = 0
108 let envp: *i64 = sys_mmap(16) as *i64
109 envp[0] = 0
110 sys_execve(elf, argv, envp)
111 sys_exit(127)
112 }
113 let st: *i64 = sys_mmap(16) as *i64
114 sys_wait4(pid, st, 0)
115 let sig: i64 = st[0] & 0x7f
116 if sig != 0 { return 128 + sig }
117 return (st[0] >> 8) & 0xff
118}
119
120func rg_has(path: *u8, needle: *u8) -> i64 {
121 let szp: *i64 = sys_mmap(16) as *i64
122 let b: *u8 = rg_readall(path, szp)
123 let sz: i64 = szp[0]
124 let n: i64 = rg_slen(needle)
125 if sz < n { return 0 }
126 var i: i64 = 0
127 while i + n <= sz {
128 var ok: i64 = 1
129 var j: i64 = 0
130 while j < n {
131 if b[i + j] != needle[j] { ok = 0; j = n } else { j = j + 1 }
132 }
133 if ok == 1 { return 1 }
134 i = i + 1
135 }
136 return 0
137}
138
139func rg_fileeq(p1: *u8, p2: *u8) -> i64 {
140 let s1: *i64 = sys_mmap(16) as *i64
141 let s2: *i64 = sys_mmap(16) as *i64
142 let b1: *u8 = rg_readall(p1, s1)
143 let b2: *u8 = rg_readall(p2, s2)
144 if s1[0] != s2[0] { return 0 }
145 if s1[0] <= 0 { return 0 }
146 var i: i64 = 0
147 while i < s1[0] {
148 if b1[i] != b2[i] { return 0 }
149 i = i + 1
150 }
151 return 1
152}
153
154func rg_row(name: *u8, pass: i64) -> i64 {
155 rg_p("ROW " as *u8)
156 rg_p(name)
157 if pass == 1 { rg_p(" PASS\n" as *u8) } else { rg_p(" FAIL\n" as *u8) }
158 return pass
159}
160
161func main(argc: i64, argv: *i64) -> i64 {
162 rg_p("=== VIZSLA NOTES GATE: hand-computed event-timed meaningful-note KATs (before/on/after) ===\n" as *u8)
163 var rb: *u8 = "/tmp/nx_vizsla_notes.sov.elf" as *u8
164 if argc > 1 { rb = argv[1] as *u8 }
165 let pr: i64 = sys_openat_rd(rb)
166 if pr >= 0 { sys_close(pr) }
167 else {
168 rg_p(" instrument missing -> rebuilding via durable runner\n" as *u8)
169 rg_run("_offc/nx_sov_build_run.elf" as *u8, "nx_vizsla_notes" as *u8, 0 as *u8, 0 as *u8, 0 as *u8, "/tmp/nt_rebuild.out" as *u8)
170 }
171
172 let pfx: *u8 = sys_mmap(128)
173 var po: i64 = 0
174 po = rg_cat(pfx, po, "/tmp/ntG" as *u8)
175 po = rg_catn(pfx, po, sys_now_us())
176 po = rg_cat(pfx, po, "-" as *u8)
177 pfx[po] = 0 as u8
178
179 let conf: *u8 = "CONF window_days 3\nCONF soon_days 14\n" as *u8
180 rg_write("/tmp/nt_conf.txt" as *u8, conf)
181 let conf1: *u8 = "CONF window_days 1\nCONF soon_days 14\n" as *u8
182 rg_write("/tmp/nt_conf1.txt" as *u8, conf1)
183 let log: *u8 = "EVENT e1 2026-06-20 mom birthday card-gift\nEVENT e2 2026-07-01 alex surgery recovery\nEVENT e3 2026-06-10 sam wedding congrats\nEVENT e4 2026-09-15 pat graduation milestone\nNOTE n1 e1 BEFORE 7 card signature:img-mom\nNOTE n2 e2 BEFORE 3 text voice:vm-alex\nNOTE n3 e3 AFTER 2 card handwritten:scan-sam\nNOTE n4 e4 ON 0 call text:congrats-pat\nNOTE n5 e3 BEFORE 7 card text:goodluck-sam\nSENT n1 2026-06-14\n" as *u8
184 rg_write("/tmp/nt_log.txt" as *u8, log)
185 let badlog: *u8 = "EVENT e1 2026-06-20 mom birthday card-gift\nNOTE nb e9 ON 0 card text:hi\n" as *u8
186 rg_write("/tmp/nt_badlog.txt" as *u8, badlog)
187 // templates (no graduation/ON row -> n4 draft must loud-fail naming the gap)
188 let tmpl: *u8 = "TMPL birthday BEFORE Happy early birthday {contact}! Thinking of you before {date}. Enclosed: {personal}\nTMPL wedding AFTER Dear {contact}, thank you for sharing your wedding with us. Enclosed: {personal}\nTMPL surgery BEFORE {contact}, wishing you strength before your surgery on {date}. Enclosed: {personal}\n" as *u8
189 rg_write("/tmp/nt_tmpl.txt" as *u8, tmpl)
190 // occasions catalog (TYN-003): wedding gets a TIGHT 1-day window -> n3 flips
191 // DUE(global 3)->LATE(occasion 1); proves per-occasion timing is data-driven
192 let occ: *u8 = "CONF window_days 3\nOCCASION birthday BEFORE 3 7 arrive-by-the-day\nOCCASION wedding AFTER 0 1 thank-you-window-tight\nOCCASION surgery BEFORE 2 5 before-procedure\n" as *u8
193 rg_write("/tmp/nt_occ.txt" as *u8, occ)
194
195 let fcf: *u8 = "/tmp/nt_conf.txt" as *u8
196 let flog: *u8 = "/tmp/nt_log.txt" as *u8
197 var pass: i64 = 0
198 var r: i64 = 0
199
200 // row 1: loud-fail on missing conf
201 let rc1: i64 = rg_run(rb, "schedule" as *u8, pfx, "/tmp/nt_NOPE.txt" as *u8, "2026-06-14" as *u8, "/tmp/nt_out1.txt" as *u8)
202 r = 0
203 if rc1 == 1 { r = 1 }
204 pass = pass + rg_row("loud-fail-missing-conf" as *u8, r)
205
206 // row 2: load 10 records into seg-7001
207 let rc2: i64 = rg_run(rb, "load" as *u8, flog, pfx, "7001" as *u8, "/tmp/nt_out2.txt" as *u8)
208 r = 0
209 if rc2 == 0 {
210 if rg_has("/tmp/nt_out2.txt" as *u8, "VIZSLA-NOTE-LOAD scanned=10 new=10 dup_infile=0 dup_instore=0 segment=seg-7001" as *u8) == 1 { r = 1 }
211 }
212 pass = pass + rg_row("load-events" as *u8, r)
213
214 // row 3: idempotent reload
215 let rc3: i64 = rg_run(rb, "load" as *u8, flog, pfx, "7009" as *u8, "/tmp/nt_out3.txt" as *u8)
216 r = 0
217 if rc3 == 0 {
218 if rg_has("/tmp/nt_out3.txt" as *u8, "VIZSLA-NOTE-LOAD scanned=10 new=0 dup_infile=0 dup_instore=10 segment=none" as *u8) == 1 { r = 1 }
219 }
220 pass = pass + rg_row("idempotent-reload" as *u8, r)
221
222 // rows 4-9: schedule
223 let rc4: i64 = rg_run(rb, "schedule" as *u8, pfx, fcf, "2026-06-14" as *u8, "/tmp/nt_sch.txt" as *u8)
224 r = 0
225 if rc4 == 0 {
226 if rg_has("/tmp/nt_sch.txt" as *u8, "id=n2 event=e2 contact=alex kind=surgery rel=BEFORE release=2026-06-28 deadline=2026-07-01 state=WAITING" as *u8) == 1 { r = 1 }
227 }
228 pass = pass + rg_row("before-waiting" as *u8, r)
229
230 r = rg_has("/tmp/nt_sch.txt" as *u8, "id=n3 event=e3 contact=sam kind=wedding rel=AFTER release=2026-06-12 deadline=2026-06-15 state=DUE" as *u8)
231 pass = pass + rg_row("after-due" as *u8, r)
232
233 r = rg_has("/tmp/nt_sch.txt" as *u8, "id=n5 event=e3 contact=sam kind=wedding rel=BEFORE release=2026-06-03 deadline=2026-06-10 state=LATE" as *u8)
234 pass = pass + rg_row("before-late" as *u8, r)
235
236 r = rg_has("/tmp/nt_sch.txt" as *u8, "id=n4 event=e4 contact=pat kind=graduation rel=ON release=2026-09-15 deadline=2026-09-18 state=WAITING" as *u8)
237 pass = pass + rg_row("on-waiting" as *u8, r)
238
239 r = rg_has("/tmp/nt_sch.txt" as *u8, "id=n1 event=e1 contact=mom kind=birthday rel=BEFORE release=2026-06-13 deadline=2026-06-20 state=SENT" as *u8)
240 pass = pass + rg_row("sent-closes" as *u8, r)
241
242 r = rg_has("/tmp/nt_sch.txt" as *u8, "VIZSLA-NOTE-VERDICT notes=5 waiting=2 due=1 late=1 sent=1" as *u8)
243 pass = pass + rg_row("schedule-verdict" as *u8, r)
244
245 // row 10: due filter -- only DUE notes, WAITING absent
246 let rc10: i64 = rg_run(rb, "due" as *u8, pfx, fcf, "2026-06-14" as *u8, "/tmp/nt_due.txt" as *u8)
247 r = 0
248 if rc10 == 0 {
249 if rg_has("/tmp/nt_due.txt" as *u8, "VIZSLA-NOTE-DUE-VERDICT due=1" as *u8) == 1 {
250 if rg_has("/tmp/nt_due.txt" as *u8, "id=n3 " as *u8) == 1 {
251 if rg_has("/tmp/nt_due.txt" as *u8, "state=WAITING" as *u8) == 0 { r = 1 }
252 }
253 }
254 }
255 pass = pass + rg_row("due-filter" as *u8, r)
256
257 // row 11: days->date inverse + personalization carried (the "signal" capture)
258 r = 0
259 if rg_has("/tmp/nt_sch.txt" as *u8, "id=n1 " as *u8) == 1 {
260 if rg_has("/tmp/nt_sch.txt" as *u8, "release=2026-06-13" as *u8) == 1 {
261 if rg_has("/tmp/nt_sch.txt" as *u8, "personal=signature:img-mom" as *u8) == 1 { r = 1 }
262 }
263 }
264 pass = pass + rg_row("release-date-inverse+personal" as *u8, r)
265
266 // row 12: DATA-DRIVEN window_days=1 file flips n3 DUE->LATE, same binary
267 let rc12: i64 = rg_run(rb, "schedule" as *u8, pfx, "/tmp/nt_conf1.txt" as *u8, "2026-06-14" as *u8, "/tmp/nt_sch1.txt" as *u8)
268 r = 0
269 if rc12 == 0 {
270 if rg_has("/tmp/nt_sch1.txt" as *u8, "VIZSLA-NOTE-VERDICT notes=5 waiting=2 due=0 late=2 sent=1" as *u8) == 1 { r = 1 }
271 }
272 pass = pass + rg_row("data-driven-window" as *u8, r)
273
274 // row 13: loud-fail on a NOTE referencing an unknown EVENT
275 let bpfx: *u8 = sys_mmap(128)
276 var bo: i64 = 0
277 bo = rg_cat(bpfx, bo, "/tmp/ntBAD" as *u8)
278 bo = rg_catn(bpfx, bo, sys_now_us())
279 bo = rg_cat(bpfx, bo, "-" as *u8)
280 bpfx[bo] = 0 as u8
281 rg_run(rb, "load" as *u8, "/tmp/nt_badlog.txt" as *u8, bpfx, "8001" as *u8, "/tmp/nt_bload.txt" as *u8)
282 let rc13: i64 = rg_run(rb, "schedule" as *u8, bpfx, fcf, "2026-06-14" as *u8, "/tmp/nt_bsch.txt" as *u8)
283 r = 0
284 if rc13 == 1 { r = 1 }
285 pass = pass + rg_row("loud-fail-unknown-event" as *u8, r)
286
287 // row 14: schedule determinism
288 rg_run(rb, "schedule" as *u8, pfx, fcf, "2026-06-14" as *u8, "/tmp/nt_sch2.txt" as *u8)
289 r = rg_fileeq("/tmp/nt_sch.txt" as *u8, "/tmp/nt_sch2.txt" as *u8)
290 pass = pass + rg_row("schedule-determinism" as *u8, r)
291
292 // row 15: draft fills the birthday/BEFORE template (slots contact/date/personal)
293 let rc15: i64 = rg_run(rb, "draft" as *u8, pfx, "/tmp/nt_tmpl.txt" as *u8, "n1" as *u8, "/tmp/nt_d1.txt" as *u8)
294 r = 0
295 if rc15 == 0 {
296 if rg_has("/tmp/nt_d1.txt" as *u8, "VIZSLA-DRAFT id=n1 kind=birthday rel=BEFORE channel=card personal=signature:img-mom" as *u8) == 1 {
297 if rg_has("/tmp/nt_d1.txt" as *u8, "Happy early birthday mom! Thinking of you before 2026-06-20. Enclosed: signature:img-mom" as *u8) == 1 { r = 1 }
298 }
299 }
300 pass = pass + rg_row("draft-fills-birthday" as *u8, r)
301
302 // row 16: draft fills the wedding/AFTER template
303 let rc16: i64 = rg_run(rb, "draft" as *u8, pfx, "/tmp/nt_tmpl.txt" as *u8, "n3" as *u8, "/tmp/nt_d3.txt" as *u8)
304 r = 0
305 if rc16 == 0 {
306 if rg_has("/tmp/nt_d3.txt" as *u8, "Dear sam, thank you for sharing your wedding with us. Enclosed: handwritten:scan-sam" as *u8) == 1 { r = 1 }
307 }
308 pass = pass + rg_row("draft-fills-wedding" as *u8, r)
309
310 // row 17: missing template (graduation/ON) = loud-fail naming the gap
311 let rc17: i64 = rg_run(rb, "draft" as *u8, pfx, "/tmp/nt_tmpl.txt" as *u8, "n4" as *u8, "/tmp/nt_d4.txt" as *u8)
312 r = 0
313 if rc17 == 1 { r = 1 }
314 pass = pass + rg_row("draft-missing-template-loud-fail" as *u8, r)
315
316 // row 18: draftdue drafts only the DUE notes (n3); n1 SENT so its draft absent
317 let rc18: i64 = rg_run(rb, "draftdue" as *u8, pfx, "/tmp/nt_tmpl.txt" as *u8, "2026-06-14" as *u8, "/tmp/nt_dd.txt" as *u8)
318 r = 0
319 if rc18 == 0 {
320 if rg_has("/tmp/nt_dd.txt" as *u8, "VIZSLA-NOTE-DRAFT-DUE-VERDICT drafted=1" as *u8) == 1 {
321 if rg_has("/tmp/nt_dd.txt" as *u8, "Dear sam, thank you for sharing your wedding" as *u8) == 1 {
322 if rg_has("/tmp/nt_dd.txt" as *u8, "Happy early birthday mom" as *u8) == 0 { r = 1 }
323 }
324 }
325 }
326 pass = pass + rg_row("draftdue-due-only" as *u8, r)
327
328 // row 19: occasions list = the etiquette / customary-timing reference
329 let rc19: i64 = rg_run(rb, "occasions" as *u8, "/tmp/nt_occ.txt" as *u8, 0 as *u8, 0 as *u8, "/tmp/nt_o19.txt" as *u8)
330 r = 0
331 if rc19 == 0 {
332 if rg_has("/tmp/nt_o19.txt" as *u8, "VIZSLA-OCCASION kind=wedding rel=AFTER offset=0 window=1 etiquette=thank-you-window-tight" as *u8) == 1 {
333 if rg_has("/tmp/nt_o19.txt" as *u8, "VIZSLA-OCCASION-VERDICT occasions=3" as *u8) == 1 { r = 1 }
334 }
335 }
336 pass = pass + rg_row("occasions-list" as *u8, r)
337
338 // row 20: suggest the customary timing + etiquette for a known kind
339 let rc20: i64 = rg_run(rb, "suggest" as *u8, "/tmp/nt_occ.txt" as *u8, "wedding" as *u8, 0 as *u8, "/tmp/nt_o20.txt" as *u8)
340 r = 0
341 if rc20 == 0 {
342 if rg_has("/tmp/nt_o20.txt" as *u8, "VIZSLA-SUGGEST kind=wedding rel=AFTER offset=0 window=1 etiquette=thank-you-window-tight" as *u8) == 1 { r = 1 }
343 }
344 pass = pass + rg_row("suggest-known" as *u8, r)
345
346 // row 21: suggest on an unknown kind = loud-fail naming the gap
347 let rc21: i64 = rg_run(rb, "suggest" as *u8, "/tmp/nt_occ.txt" as *u8, "zzz" as *u8, 0 as *u8, "/tmp/nt_o21.txt" as *u8)
348 r = 0
349 if rc21 == 1 { r = 1 }
350 pass = pass + rg_row("suggest-unknown-loud-fail" as *u8, r)
351
352 // row 22: PER-OCCASION window -- wedding's tight 1-day window flips n3
353 // DUE(global 3)->LATE; same binary, data-driven (TYN-003 intelligence)
354 let rc22: i64 = rg_run(rb, "schedule" as *u8, pfx, "/tmp/nt_occ.txt" as *u8, "2026-06-14" as *u8, "/tmp/nt_o22.txt" as *u8)
355 r = 0
356 if rc22 == 0 {
357 if rg_has("/tmp/nt_o22.txt" as *u8, "id=n3 event=e3 contact=sam kind=wedding rel=AFTER release=2026-06-12 deadline=2026-06-13 state=LATE" as *u8) == 1 {
358 if rg_has("/tmp/nt_o22.txt" as *u8, "VIZSLA-NOTE-VERDICT notes=5 waiting=2 due=0 late=2 sent=1" as *u8) == 1 { r = 1 }
359 }
360 }
361 pass = pass + rg_row("per-occasion-window" as *u8, r)
362
363 let permil: i64 = (pass * 1000) / 22
364 let logfd: i64 = sys_openat_append("knowledge/status/vizsla_gate.log" as *u8, 0x1a4)
365 var fdi: i64 = 0
366 while fdi < 2 {
367 var fd: i64 = 1
368 if fdi == 1 { fd = logfd }
369 if fd > 0 {
370 let line: *u8 = sys_mmap(256)
371 var o: i64 = 0
372 o = rg_cat(line, o, "VIZSLA-NOTE-GATE epoch=" as *u8)
373 o = rg_catn(line, o, sys_now_realtime_sec())
374 o = rg_cat(line, o, " rows=22 pass=" as *u8)
375 o = rg_catn(line, o, pass)
376 o = rg_cat(line, o, " permil=" as *u8)
377 o = rg_catn(line, o, permil)
378 if pass == 22 {
379 o = rg_cat(line, o, " verdict=GREEN\n" as *u8)
380 } else {
381 o = rg_cat(line, o, " verdict=RED\n" as *u8)
382 }
383 sys_write(fd, line, o)
384 }
385 fdi = fdi + 1
386 }
387 if logfd > 0 { sys_close(logfd) }
388 if pass == 22 { return 0 }
389 return 1
390}