code wiki / _hdl_build / nx_vizsla_digest_gate.nx
nx_vizsla_digest_gate.nx source
↩ module page · 358 lines · 18249 B
1// nx_vizsla_digest_gate.nx -- VIZSLA V5 gate: the daily DIGEST composes the
2// blessed nx_vizsla_relate (brief) + nx_vizsla_notes (draftdue) over fixture
3// data and is proven to consolidate + aggregate them correctly. No mocks: it
4// loads real seg_store fixtures via the real organs and runs the real digest.
5//
6// fixtures (today=2026-06-14):
7// relate: mom(inner,06-20) alex(close,03-15) sam(network,12-01) pat(close,-);
8// TOUCH mom 06-10, alex 02-01; OBLIG OWE alex book-loan, DUE pat loan-50;
9// THANKS mom 06-12, alex 05-01.
10// brief => followups=3 (alex DUE, sam/pat NEW), birthdays=1 (mom in 6d),
11// thankyous=2 (mom PENDING, alex OVERDUE), obligations=2.
12// notes: e1 mom birthday 06-20, e2 alex surgery 07-01, e3 sam wedding 06-10;
13// n1 birthday BEFORE 7, n2 surgery BEFORE 3, n3 wedding AFTER 2;
14// occasions: birthday win 7, wedding win 90 -> n1 DUE + n3 DUE => drafted=2.
15// => VIZSLA-DIGEST-VERDICT followups=3 birthdays=1 thankyous=2 obligations=2 notes_drafted=2
16//
17// Rows:
18// 1 loud-fail-missing-conf digest on absent conf => exit 1
19// 2 loud-fail-missing-key conf missing NOTES_PREFIX => exit 1
20// 3 digest-relationships FOLLOWUP alex + BIRTHDAY mom present
21// 4 digest-notes-drafts the wedding draft prose present
22// 5 digest-verdict-aggregates consolidated verdict 3/1/2/2 + notes_drafted=2
23// 6 digest-determinism byte-identical twice
24// Evidence: VIZSLA-DIGEST-GATE -> stdout + knowledge/status/vizsla_gate.log; exit 0 iff 6/6.
25// Tamper: bogus instrument argv[1] => all rows FAIL => RED.
26// spec: knowledge/specs/2026-06-10-nishi-vizsla-ladder.md license_tier: ORIGINAL
27import "nx_syscalls.nx"
28
29func rg_slen(s: *u8) -> i64 {
30 var n: i64 = 0
31 while s[n] != (0 as u8) { n = n + 1 }
32 return n
33}
34
35func rg_p(s: *u8) -> i64 {
36 sys_write(1, s, rg_slen(s))
37 return 0
38}
39
40func rg_cat(dst: *u8, off: i64, s: *u8) -> i64 {
41 var i: i64 = 0
42 while s[i] != (0 as u8) { dst[off + i] = s[i]; i = i + 1 }
43 return off + i
44}
45
46func rg_catn(dst: *u8, off: i64, v: i64) -> i64 {
47 var o: i64 = off
48 var m: i64 = v
49 if m < 0 { dst[o] = 45 as u8; o = o + 1; m = 0 - m }
50 let t: *u8 = sys_mmap(28)
51 var k: i64 = 0
52 if m == 0 { t[0] = 48 as u8; k = 1 }
53 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
54 var i: i64 = 0
55 while i < k { dst[o + i] = t[k - 1 - i]; i = i + 1 }
56 return o + k
57}
58
59func rg_write(path: *u8, content: *u8) -> i64 {
60 let fd: i64 = sys_openat_wr(path, 0x1a4)
61 if fd < 0 { return 0 - 1 }
62 sys_write(fd, content, rg_slen(content))
63 sys_close(fd)
64 return 0
65}
66
67func rg_readall(path: *u8, szout: *i64) -> *u8 {
68 let fd: i64 = sys_openat_rd(path)
69 if fd < 0 { szout[0] = 0 - 1; return 0 as *u8 }
70 let sz: i64 = sys_lseek(fd, 0, 2)
71 sys_lseek(fd, 0, 0)
72 let buf: *u8 = sys_mmap(sz + 64)
73 var got: i64 = 0
74 var n: i64 = 1
75 while n > 0 {
76 n = sys_read(fd, (buf as i64 + got) as *u8, 65536)
77 if n > 0 { got = got + n }
78 }
79 sys_close(fd)
80 szout[0] = got
81 return buf
82}
83
84func rg_run(elf: *u8, a1: *u8, a2: *u8, a3: *u8, a4: *u8, outpath: *u8) -> i64 {
85 let pid: i64 = sys_fork()
86 if pid == 0 {
87 if (outpath as i64) != 0 {
88 let ofd: i64 = sys_openat_wr(outpath, 0x1a4)
89 if ofd >= 0 { sys_dup3(ofd, 1, 0); sys_dup3(ofd, 2, 0) }
90 }
91 let argv: *i64 = sys_mmap(64) as *i64
92 argv[0] = elf as i64
93 var i: i64 = 1
94 if (a1 as i64) != 0 { argv[i] = a1 as i64; i = i + 1 }
95 if (a2 as i64) != 0 { argv[i] = a2 as i64; i = i + 1 }
96 if (a3 as i64) != 0 { argv[i] = a3 as i64; i = i + 1 }
97 if (a4 as i64) != 0 { argv[i] = a4 as i64; i = i + 1 }
98 argv[i] = 0
99 let envp: *i64 = sys_mmap(16) as *i64
100 envp[0] = 0
101 sys_execve(elf, argv, envp)
102 sys_exit(127)
103 }
104 let st: *i64 = sys_mmap(16) as *i64
105 sys_wait4(pid, st, 0)
106 let sig: i64 = st[0] & 0x7f
107 if sig != 0 { return 128 + sig }
108 return (st[0] >> 8) & 0xff
109}
110
111func rg_has(path: *u8, needle: *u8) -> i64 {
112 let szp: *i64 = sys_mmap(16) as *i64
113 let b: *u8 = rg_readall(path, szp)
114 let sz: i64 = szp[0]
115 let n: i64 = rg_slen(needle)
116 if sz < n { return 0 }
117 var i: i64 = 0
118 while i + n <= sz {
119 var ok: i64 = 1
120 var j: i64 = 0
121 while j < n {
122 if b[i + j] != needle[j] { ok = 0; j = n } else { j = j + 1 }
123 }
124 if ok == 1 { return 1 }
125 i = i + 1
126 }
127 return 0
128}
129
130func rg_fileeq(p1: *u8, p2: *u8) -> i64 {
131 let s1: *i64 = sys_mmap(16) as *i64
132 let s2: *i64 = sys_mmap(16) as *i64
133 let b1: *u8 = rg_readall(p1, s1)
134 let b2: *u8 = rg_readall(p2, s2)
135 if s1[0] != s2[0] { return 0 }
136 if s1[0] <= 0 { return 0 }
137 var i: i64 = 0
138 while i < s1[0] {
139 if b1[i] != b2[i] { return 0 }
140 i = i + 1
141 }
142 return 1
143}
144
145func rg_row(name: *u8, pass: i64) -> i64 {
146 rg_p("ROW " as *u8)
147 rg_p(name)
148 if pass == 1 { rg_p(" PASS\n" as *u8) } else { rg_p(" FAIL\n" as *u8) }
149 return pass
150}
151
152func main(argc: i64, argv: *i64) -> i64 {
153 rg_p("=== VIZSLA DIGEST GATE: the daily digest composes brief + notes-due ===\n" as *u8)
154 var rb: *u8 = "/tmp/nx_vizsla_digest.sov.elf" as *u8
155 if argc > 1 { rb = argv[1] as *u8 }
156 let pr: i64 = sys_openat_rd(rb)
157 if pr >= 0 { sys_close(pr) }
158 else {
159 rg_p(" instrument missing -> rebuilding via durable runner\n" as *u8)
160 rg_run("_offc/nx_sov_build_run.elf" as *u8, "nx_vizsla_digest" as *u8, 0 as *u8, 0 as *u8, 0 as *u8, "/tmp/dgg_rebuild.out" as *u8)
161 }
162
163 // epoch-unique virgin store prefixes
164 let rpfx: *u8 = sys_mmap(128)
165 var ro: i64 = 0
166 ro = rg_cat(rpfx, ro, "/tmp/dggR" as *u8); ro = rg_catn(rpfx, ro, sys_now_us()); ro = rg_cat(rpfx, ro, "-" as *u8); rpfx[ro] = 0 as u8
167 let npfx: *u8 = sys_mmap(128)
168 var no: i64 = 0
169 no = rg_cat(npfx, no, "/tmp/dggN" as *u8); no = rg_catn(npfx, no, sys_now_us()); no = rg_cat(npfx, no, "-" as *u8); npfx[no] = 0 as u8
170
171 rg_write("/tmp/dgg_contacts.txt" as *u8, "CONF soon_days 14\nTIER inner 30\nTIER close 90\nTIER network 180\nCONTACT mom Mom inner 06-20\nCONTACT alex Alex-Mentor close 03-15\nCONTACT sam Sam-Colleague network 12-01\nCONTACT pat Pat-Friend close -\n" as *u8)
172 rg_write("/tmp/dgg_relog.txt" as *u8, "TOUCH 2026-06-10 mom weekly-call\nTOUCH 2026-02-01 alex lunch\nOBLIGATION 2026-05-01 OWE alex book-loan 0 borrowed-book\nOBLIGATION 2026-05-05 DUE pat loan-50 5000 lent-cash\nTHANKS 2026-06-12 mom birthday-gift\nTHANKS 2026-05-01 alex referral\n" as *u8)
173 rg_write("/tmp/dgg_nlog.txt" as *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\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\n" as *u8)
174 rg_write("/tmp/dgg_nconf.txt" as *u8, "CONF window_days 3\nOCCASION birthday BEFORE 3 7 arrive-by-the-day\nOCCASION wedding AFTER 0 90 thank-you-within-3-months\nOCCASION surgery BEFORE 2 7 before-procedure\n" as *u8)
175 rg_write("/tmp/dgg_ntmpl.txt" as *u8, "TMPL birthday BEFORE Happy early birthday, {contact}! Wishing you a wonderful day on {date}. Enclosed: {personal}\nTMPL wedding AFTER Dear {contact}, thank you for including us in your wedding -- it was a joy. Enclosed: {personal}\n" as *u8)
176
177 // load fixtures into the two stores via the blessed organs
178 rg_run("_offc/nx_vizsla_relate.elf" as *u8, "load" as *u8, "/tmp/dgg_relog.txt" as *u8, rpfx, "6001" as *u8, "/tmp/dgg_rl.txt" as *u8)
179 rg_run("_offc/nx_vizsla_notes.elf" as *u8, "load" as *u8, "/tmp/dgg_nlog.txt" as *u8, npfx, "6001" as *u8, "/tmp/dgg_nl.txt" as *u8)
180 // bills store + fixtures (for the optional bills section)
181 let bpfx: *u8 = sys_mmap(128)
182 var bpo: i64 = 0
183 bpo = rg_cat(bpfx, bpo, "/tmp/dggB" as *u8); bpo = rg_catn(bpfx, bpo, sys_now_us()); bpo = rg_cat(bpfx, bpo, "-" as *u8); bpfx[bpo] = 0 as u8
184 rg_write("/tmp/dgg_bills.txt" as *u8, "CONF soon_days 7\nBILL rent Landlord 180000 1 MONTHLY MANUAL\nBILL electric PowerCo 12000 15 MONTHLY MANUAL\nBILL netflix Netflix 1599 20 MONTHLY AUTO\nBILL water CityWater 4500 10 MONTHLY MANUAL\nBILL phone TelCo 6000 25 MONTHLY MANUAL\n" as *u8)
185 rg_write("/tmp/dgg_bllog.txt" as *u8, "PAID 2026-06-02 rent 180000 june-rent\nPAID 2026-05-20 netflix 1599 may-auto\n" as *u8)
186 rg_run("_offc/nx_vizsla_bills.elf" as *u8, "load" as *u8, "/tmp/dgg_bllog.txt" as *u8, bpfx, "5001" as *u8, "/tmp/dgg_bl.txt" as *u8)
187
188 // good digest.conf (built with the generated prefixes)
189 let conf: *u8 = sys_mmap(2048)
190 var co: i64 = 0
191 co = rg_cat(conf, co, "RELATE_PREFIX " as *u8); co = rg_cat(conf, co, rpfx); co = rg_cat(conf, co, "\n" as *u8)
192 co = rg_cat(conf, co, "RELATE_CONTACTS /tmp/dgg_contacts.txt\n" as *u8)
193 co = rg_cat(conf, co, "NOTES_PREFIX " as *u8); co = rg_cat(conf, co, npfx); co = rg_cat(conf, co, "\n" as *u8)
194 co = rg_cat(conf, co, "NOTES_CONF /tmp/dgg_nconf.txt\n" as *u8)
195 co = rg_cat(conf, co, "NOTES_TEMPLATES /tmp/dgg_ntmpl.txt\n" as *u8)
196 conf[co] = 0 as u8
197 rg_write("/tmp/dgg.conf" as *u8, conf)
198 // a second conf that ALSO enables bills (= the good conf + BILLS keys)
199 let bconf: *u8 = sys_mmap(2048)
200 var bco: i64 = 0
201 bco = rg_cat(bconf, bco, conf)
202 bco = rg_cat(bconf, bco, "BILLS_PREFIX " as *u8); bco = rg_cat(bconf, bco, bpfx); bco = rg_cat(bconf, bco, "\n" as *u8)
203 bco = rg_cat(bconf, bco, "BILLS_FILE /tmp/dgg_bills.txt\n" as *u8)
204 bconf[bco] = 0 as u8
205 rg_write("/tmp/dgg_bills.conf" as *u8, bconf)
206 // engagement-partner fixtures: calendar + plan + venue stores via the BLESSED organs
207 let cpfx: *u8 = sys_mmap(128)
208 var cpo: i64 = 0
209 cpo = rg_cat(cpfx, cpo, "/tmp/dggC" as *u8); cpo = rg_catn(cpfx, cpo, sys_now_us()); cpo = rg_cat(cpfx, cpo, "-" as *u8); cpfx[cpo] = 0 as u8
210 rg_write("/tmp/dgg_cal.txt" as *u8, "EVENT mtg 2026-06-14 600 60 standup-mtg\n" as *u8)
211 rg_run("_offc/nx_vizsla_calendar.elf" as *u8, "load" as *u8, "/tmp/dgg_cal.txt" as *u8, cpfx, "7001" as *u8, "/tmp/dgg_cl.txt" as *u8)
212 let ppfx: *u8 = sys_mmap(128)
213 var ppo: i64 = 0
214 ppo = rg_cat(ppfx, ppo, "/tmp/dggP" as *u8); ppo = rg_catn(ppfx, ppo, sys_now_us()); ppo = rg_cat(ppfx, ppo, "-" as *u8); ppfx[ppo] = 0 as u8
215 rg_write("/tmp/dgg_plan.txt" as *u8, "TASK dg venue2 jason 2026-06-16 60 5 - book-venue2\n" as *u8)
216 rg_run("_offc/nx_vizsla_plan.elf" as *u8, "load" as *u8, "/tmp/dgg_plan.txt" as *u8, ppfx, "7002" as *u8, "/tmp/dgg_pl.txt" as *u8)
217 let vpfx: *u8 = sys_mmap(128)
218 var vpo: i64 = 0
219 vpo = rg_cat(vpfx, vpo, "/tmp/dggV" as *u8); vpo = rg_catn(vpfx, vpo, sys_now_us()); vpo = rg_cat(vpfx, vpo, "-" as *u8); vpfx[vpo] = 0 as u8
220 rg_write("/tmp/dgg_ven.txt" as *u8, "REQ dgparty 10 20000 2026-06-20 600 120\nVENUE dgparty spot-x 12 15000 555-9 corner-hall\nSTAGE 2026-06-10 dgparty spot-x contacted\n" as *u8)
221 rg_run("_offc/nx_vizsla_venue.elf" as *u8, "load" as *u8, "/tmp/dgg_ven.txt" as *u8, vpfx, "7003" as *u8, "/tmp/dgg_vl.txt" as *u8)
222 // the ENGAGE conf = good conf + calendar/reminders/plan/venue sections
223 let econf: *u8 = sys_mmap(4096)
224 var eco: i64 = 0
225 eco = rg_cat(econf, eco, conf)
226 eco = rg_cat(econf, eco, "CAL_PREFIX " as *u8); eco = rg_cat(econf, eco, cpfx); eco = rg_cat(econf, eco, "\n" as *u8)
227 eco = rg_cat(econf, eco, "REMIND_CONTACTS /tmp/dgg_contacts.txt\n" as *u8)
228 eco = rg_cat(econf, eco, "REMIND_LEADS 6,0\n" as *u8)
229 eco = rg_cat(econf, eco, "PLAN_PREFIX " as *u8); eco = rg_cat(econf, eco, ppfx); eco = rg_cat(econf, eco, "\n" as *u8)
230 eco = rg_cat(econf, eco, "PLAN_NAME dg\n" as *u8)
231 eco = rg_cat(econf, eco, "VENUE_PREFIX " as *u8); eco = rg_cat(econf, eco, vpfx); eco = rg_cat(econf, eco, "\n" as *u8)
232 eco = rg_cat(econf, eco, "VENUE_EVENT dgparty\n" as *u8)
233 econf[eco] = 0 as u8
234 rg_write("/tmp/dgg_engage.conf" as *u8, econf)
235
236 // bad conf: omit NOTES_PREFIX
237 let bad: *u8 = sys_mmap(2048)
238 var bo: i64 = 0
239 bo = rg_cat(bad, bo, "RELATE_PREFIX " as *u8); bo = rg_cat(bad, bo, rpfx); bo = rg_cat(bad, bo, "\n" as *u8)
240 bo = rg_cat(bad, bo, "RELATE_CONTACTS /tmp/dgg_contacts.txt\n" as *u8)
241 bo = rg_cat(bad, bo, "NOTES_CONF /tmp/dgg_nconf.txt\n" as *u8)
242 bo = rg_cat(bad, bo, "NOTES_TEMPLATES /tmp/dgg_ntmpl.txt\n" as *u8)
243 bad[bo] = 0 as u8
244 rg_write("/tmp/dgg_bad.conf" as *u8, bad)
245
246 var pass: i64 = 0
247 var r: i64 = 0
248
249 // row 1: loud-fail on missing conf
250 let rc1: i64 = rg_run(rb, "digest" as *u8, "/tmp/dgg_NOPE.conf" as *u8, "2026-06-14" as *u8, 0 as *u8, "/tmp/dgg_o1.txt" as *u8)
251 r = 0
252 if rc1 == 1 { r = 1 }
253 pass = pass + rg_row("loud-fail-missing-conf" as *u8, r)
254
255 // row 2: loud-fail on a conf missing a required key
256 let rc2: i64 = rg_run(rb, "digest" as *u8, "/tmp/dgg_bad.conf" as *u8, "2026-06-14" as *u8, 0 as *u8, "/tmp/dgg_o2.txt" as *u8)
257 r = 0
258 if rc2 == 1 { r = 1 }
259 pass = pass + rg_row("loud-fail-missing-key" as *u8, r)
260
261 // row 3-6: the real digest
262 let rc3: i64 = rg_run(rb, "digest" as *u8, "/tmp/dgg.conf" as *u8, "2026-06-14" as *u8, 0 as *u8, "/tmp/dgg_dig.txt" as *u8)
263 r = 0
264 if rc3 == 0 {
265 if rg_has("/tmp/dgg_dig.txt" as *u8, " FOLLOWUP contact=alex days=133 (DUE)" as *u8) == 1 {
266 if rg_has("/tmp/dgg_dig.txt" as *u8, " BIRTHDAY contact=mom on=06-20 in=6d" as *u8) == 1 { r = 1 }
267 }
268 }
269 pass = pass + rg_row("digest-relationships" as *u8, r)
270
271 r = rg_has("/tmp/dgg_dig.txt" as *u8, "Dear sam, thank you for including us in your wedding" as *u8)
272 pass = pass + rg_row("digest-notes-drafts" as *u8, r)
273
274 r = rg_has("/tmp/dgg_dig.txt" as *u8, "VIZSLA-DIGEST-VERDICT followups=3 birthdays=1 thankyous=2 obligations=2 notes_drafted=2" as *u8)
275 pass = pass + rg_row("digest-verdict-aggregates" as *u8, r)
276
277 rg_run(rb, "digest" as *u8, "/tmp/dgg.conf" as *u8, "2026-06-14" as *u8, 0 as *u8, "/tmp/dgg_dig2.txt" as *u8)
278 r = rg_fileeq("/tmp/dgg_dig.txt" as *u8, "/tmp/dgg_dig2.txt" as *u8)
279 pass = pass + rg_row("digest-determinism" as *u8, r)
280
281 // row 7: the bills-enabled conf adds a BILLS section
282 let rc7: i64 = rg_run(rb, "digest" as *u8, "/tmp/dgg_bills.conf" as *u8, "2026-06-14" as *u8, 0 as *u8, "/tmp/dgg_digb.txt" as *u8)
283 r = 0
284 if rc7 == 0 {
285 if rg_has("/tmp/dgg_digb.txt" as *u8, "VIZSLA-BILL id=water payee=CityWater amount=4500 due=2026-06-10 autopay=MANUAL state=OVERDUE" as *u8) == 1 { r = 1 }
286 }
287 pass = pass + rg_row("digest-bills-section" as *u8, r)
288
289 // row 8: the consolidated verdict aggregates bills (due/overdue/owed)
290 r = rg_has("/tmp/dgg_digb.txt" as *u8, "VIZSLA-DIGEST-VERDICT followups=3 birthdays=1 thankyous=2 obligations=2 notes_drafted=2 bills_due=2 bills_overdue=1 bills_owed_cents=24099" as *u8)
291 pass = pass + rg_row("digest-bills-verdict" as *u8, r)
292
293 // row 9: bills are OPTIONAL -- the no-bills conf produces NO bills fields
294 r = 0
295 if rg_has("/tmp/dgg_dig.txt" as *u8, "bills_owed_cents" as *u8) == 0 {
296 if rg_has("/tmp/dgg_dig.txt" as *u8, "notes_drafted=2" as *u8) == 1 { r = 1 }
297 }
298 pass = pass + rg_row("digest-bills-optional" as *u8, r)
299
300 // rows 10-14: the ENGAGEMENT-PARTNER digest (calendar + reminders + plan + venue)
301 let rc10: i64 = rg_run(rb, "digest" as *u8, "/tmp/dgg_engage.conf" as *u8, "2026-06-14" as *u8, 0 as *u8, "/tmp/dgg_dige.txt" as *u8)
302 r = 0
303 if rc10 == 0 {
304 if rg_has("/tmp/dgg_dige.txt" as *u8, "== CALENDAR TODAY ==" as *u8) == 1 {
305 if rg_has("/tmp/dgg_dige.txt" as *u8, "VIZSLA-CAL-EVENT date=2026-06-14 start=10:00 end=11:00 dur=60 id=mtg title=standup-mtg" as *u8) == 1 { r = 1 }
306 }
307 }
308 pass = pass + rg_row("digest-engage-calendar" as *u8, r)
309
310 r = 0
311 if rg_has("/tmp/dgg_dige.txt" as *u8, "VIZSLA-REM-DUE kind=birthday id=mom date=2026-06-20 in=6 title=Mom" as *u8) == 1 {
312 if rg_has("/tmp/dgg_dige.txt" as *u8, "VIZSLA-REM-DUE kind=event id=mtg date=2026-06-14 in=0 title=standup-mtg" as *u8) == 1 { r = 1 }
313 }
314 pass = pass + rg_row("digest-engage-reminders" as *u8, r)
315
316 r = 0
317 if rg_has("/tmp/dgg_dige.txt" as *u8, "VIZSLA-PLAN-TASK plan=dg id=venue2 owner=jason due=2026-06-16 state=READY urg=4 imp=5 score=50 late=0 title=book-venue2" as *u8) == 1 {
318 if rg_has("/tmp/dgg_dige.txt" as *u8, "VIZSLA-VEN-CAND event=dgparty id=spot-x stage=contacted cap=12 cost=15000 score=85 over_budget=0 too_small=0 contact=555-9 name=corner-hall" as *u8) == 1 { r = 1 }
319 }
320 pass = pass + rg_row("digest-engage-plan-venue" as *u8, r)
321
322 r = rg_has("/tmp/dgg_dige.txt" as *u8, "VIZSLA-DIGEST-VERDICT followups=3 birthdays=1 thankyous=2 obligations=2 notes_drafted=2 cal_events=1 cal_free_min=1380 reminders_due=2 reminders_birthdays=1 plan_ready=1 plan_blocked=0 plan_late=0 venues=1 venue_booked=0" as *u8)
323 pass = pass + rg_row("digest-engage-verdict" as *u8, r)
324
325 r = 0
326 if rg_has("/tmp/dgg_dig.txt" as *u8, "cal_events=" as *u8) == 0 {
327 if rg_has("/tmp/dgg_dig.txt" as *u8, "reminders_due=" as *u8) == 0 { r = 1 }
328 }
329 pass = pass + rg_row("digest-engage-optional" as *u8, r)
330
331 let permil: i64 = (pass * 1000) / 14
332 let logfd: i64 = sys_openat_append("knowledge/status/vizsla_gate.log" as *u8, 0x1a4)
333 var fdi: i64 = 0
334 while fdi < 2 {
335 var fd: i64 = 1
336 if fdi == 1 { fd = logfd }
337 if fd > 0 {
338 let line: *u8 = sys_mmap(256)
339 var o: i64 = 0
340 o = rg_cat(line, o, "VIZSLA-DIGEST-GATE epoch=" as *u8)
341 o = rg_catn(line, o, sys_now_realtime_sec())
342 o = rg_cat(line, o, " rows=14 pass=" as *u8)
343 o = rg_catn(line, o, pass)
344 o = rg_cat(line, o, " permil=" as *u8)
345 o = rg_catn(line, o, permil)
346 if pass == 14 {
347 o = rg_cat(line, o, " verdict=GREEN\n" as *u8)
348 } else {
349 o = rg_cat(line, o, " verdict=RED\n" as *u8)
350 }
351 sys_write(fd, line, o)
352 }
353 fdi = fdi + 1
354 }
355 if logfd > 0 { sys_close(logfd) }
356 if pass == 14 { return 0 }
357 return 1
358}