code wiki / _hdl_build / nx_vizsla_digest.nx
nx_vizsla_digest.nx source
↩ module page · 537 lines · 22251 B
1// nx_vizsla_digest.nx -- NISHI VIZSLA V5: the proactive DAILY DIGEST.
2// Operator directive 2026-06-14: make the assistant PROACTIVE -- it tells you
3// what to do today before you ask. This is the consigliere's daily brief
4// ACROSS the whole assistant: it COMPOSES the already-gated organs (it does NOT
5// re-implement them -- rule 22, composition over duplication) into one report:
6// 1) RELATIONSHIPS to tend -> nx_vizsla_relate brief
7// 2) NOTES to send (drafted) -> nx_vizsla_notes draftdue
8// 3) BILLS due/overdue -> nx_vizsla_bills status (OPTIONAL: only if the
9// conf names BILLS_PREFIX + BILLS_FILE)
10// -- ENGAGEMENT-PARTNER sections (2026-07-08, operator: "engagement partner ...
11// birthday and important event reminder"), each OPTIONAL like bills:
12// 4) TODAY'S CALENDAR -> nx_vizsla_calendar day (CAL_PREFIX)
13// 5) REMINDERS DUE -> nx_vizsla_remind due (REMIND_CONTACTS +
14// REMIND_LEADS; calendar side = CAL_PREFIX if set;
15// optional REMIND_SENT ledger dedups delivery)
16// 6) PLAN status -> nx_vizsla_plan board (PLAN_PREFIX + PLAN_NAME)
17// 7) VENUE hunt -> nx_vizsla_venue board (VENUE_PREFIX + VENUE_EVENT)
18// designed to be run on a pulse/schedule each day; the consolidated verdict
19// aggregates the sub-reports' counts. Determinism: today via argv.
20//
21// Command: digest <digest.conf> <today>
22// digest.conf (line records, # comments) names where the data lives:
23// RELATE_PREFIX <store-prefix> (nx_vizsla_relate store)
24// RELATE_CONTACTS <contacts.txt>
25// NOTES_PREFIX <store-prefix> (nx_vizsla_notes store)
26// NOTES_CONF <notes_conf.txt> (occasions + windows)
27// NOTES_TEMPLATES <note_templates.txt>
28// It forks the BLESSED organs _offc/nx_vizsla_relate.elf + _offc/nx_vizsla_notes.elf
29// (so run from the nxc2 dir). Loud-fail: missing conf / missing key /
30// a sub-organ that errors.
31//
32// HONEST SCOPE: the digest PRODUCES the day's actionable report + logs it; the
33// actual PUSH (email/notification to your phone) is an outward-facing boundary
34// step (consent-gated). "Automatic each day" = this organ on a pulse/cron.
35//
36// module: nishi-core.vizsla.digest
37// depends: nishi-core.lib.syscalls
38// capability: VIZSLA_DAILY_DIGEST
39// spec: knowledge/specs/2026-06-10-nishi-vizsla-ladder.md license_tier: ORIGINAL
40import "nx_syscalls.nx"
41const K_MAGIC_65536: i64 = 65536
42const K_MAGIC_262144: i64 = 262144
43
44func dg_slen(s: *u8) -> i64 {
45 var n: i64 = 0
46 while s[n] != (0 as u8) { n = n + 1 }
47 return n
48}
49
50func dg_p(s: *u8) -> i64 {
51 sys_write(1, s, dg_slen(s))
52 return 0
53}
54
55func dg_eq(a: *u8, b: *u8) -> i64 {
56 var i: i64 = 0
57 var go: i64 = 1
58 while go == 1 {
59 if a[i] != b[i] { return 0 }
60 if a[i] == (0 as u8) { return 1 }
61 i = i + 1
62 }
63 return 0
64}
65
66func dg_isws(c: i64) -> i64 {
67 if c == 32 { return 1 }
68 if c == 13 { return 1 }
69 if c == 9 { return 1 }
70 return 0
71}
72
73func dg_tok(b: *u8, off: i64, lend: i64, dst: *u8, cap: i64) -> i64 {
74 var p: i64 = off
75 var go: i64 = 1
76 while go == 1 {
77 if p >= lend { go = 0 } else {
78 if dg_isws(b[p] as i64) == 1 { p = p + 1 } else { go = 0 }
79 }
80 }
81 var t: i64 = 0
82 go = 1
83 while go == 1 {
84 if p >= lend { go = 0 } else {
85 if dg_isws(b[p] as i64) == 1 { go = 0 } else {
86 if t < cap - 1 { dst[t] = b[p]; t = t + 1 }
87 p = p + 1
88 }
89 }
90 }
91 dst[t] = 0 as u8
92 return p
93}
94
95func dg_cat(dst: *u8, off: i64, s: *u8) -> i64 {
96 var i: i64 = 0
97 while s[i] != (0 as u8) { dst[off + i] = s[i]; i = i + 1 }
98 return off + i
99}
100
101func dg_catn(dst: *u8, off: i64, v: i64) -> i64 {
102 var o: i64 = off
103 var m: i64 = v
104 if m < 0 { dst[o] = 45 as u8; o = o + 1; m = 0 - m }
105 let t: *u8 = sys_mmap(28)
106 var k: i64 = 0
107 if m == 0 { t[0] = 48 as u8; k = 1 }
108 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
109 var i: i64 = 0
110 while i < k { dst[o + i] = t[k - 1 - i]; i = i + 1 }
111 return o + k
112}
113
114func dg_readall(path: *u8, szout: *i64) -> *u8 {
115 let fd: i64 = sys_openat_rd(path)
116 if fd < 0 { szout[0] = 0 - 1; return 0 as *u8 }
117 let sz: i64 = sys_lseek(fd, 0, 2)
118 sys_lseek(fd, 0, 0)
119 let buf: *u8 = sys_mmap(sz + 64)
120 var got: i64 = 0
121 var n: i64 = 1
122 while n > 0 {
123 n = sys_read(fd, (buf as i64 + got) as *u8, K_MAGIC_65536)
124 if n > 0 { got = got + n }
125 }
126 sys_close(fd)
127 szout[0] = got
128 return buf
129}
130
131// fork/exec a blessed organ with up to 4 args after the command; child stdout+
132// stderr -> outpath. returns the child exit code.
133func dg_run(elf: *u8, a0: *u8, a1: *u8, a2: *u8, a3: *u8, a4: *u8, outpath: *u8) -> i64 {
134 let pid: i64 = sys_fork()
135 if pid == 0 {
136 let ofd: i64 = sys_openat_wr(outpath, 0x1a4)
137 if ofd >= 0 { sys_dup3(ofd, 1, 0); sys_dup3(ofd, 2, 0) }
138 let argv: *i64 = sys_mmap(64) as *i64
139 argv[0] = elf as i64
140 var i: i64 = 1
141 if (a0 as i64) != 0 { argv[i] = a0 as i64; i = i + 1 }
142 if (a1 as i64) != 0 { argv[i] = a1 as i64; i = i + 1 }
143 if (a2 as i64) != 0 { argv[i] = a2 as i64; i = i + 1 }
144 if (a3 as i64) != 0 { argv[i] = a3 as i64; i = i + 1 }
145 if (a4 as i64) != 0 { argv[i] = a4 as i64; i = i + 1 }
146 argv[i] = 0
147 let envp: *i64 = sys_mmap(16) as *i64
148 envp[0] = 0
149 sys_execve(elf, argv, envp)
150 sys_exit(127)
151 }
152 let st: *i64 = sys_mmap(16) as *i64
153 sys_wait4(pid, st, 0)
154 let sig: i64 = st[0] & 0x7f
155 if sig != 0 { return 128 + sig }
156 return (st[0] >> 8) & 0xff
157}
158
159// dg_run with a 6th arg (nx_vizsla_remind due takes cmd+5 when the sent ledger is named)
160func dg_run6(elf: *u8, a0: *u8, a1: *u8, a2: *u8, a3: *u8, a4: *u8, a5: *u8, outpath: *u8) -> i64 {
161 let pid: i64 = sys_fork()
162 if pid == 0 {
163 let ofd: i64 = sys_openat_wr(outpath, 0x1a4)
164 if ofd >= 0 { sys_dup3(ofd, 1, 0); sys_dup3(ofd, 2, 0) }
165 let argv: *i64 = sys_mmap(64) as *i64
166 argv[0] = elf as i64
167 var i: i64 = 1
168 if (a0 as i64) != 0 { argv[i] = a0 as i64; i = i + 1 }
169 if (a1 as i64) != 0 { argv[i] = a1 as i64; i = i + 1 }
170 if (a2 as i64) != 0 { argv[i] = a2 as i64; i = i + 1 }
171 if (a3 as i64) != 0 { argv[i] = a3 as i64; i = i + 1 }
172 if (a4 as i64) != 0 { argv[i] = a4 as i64; i = i + 1 }
173 if (a5 as i64) != 0 { argv[i] = a5 as i64; i = i + 1 }
174 argv[i] = 0
175 let envp: *i64 = sys_mmap(16) as *i64
176 envp[0] = 0
177 sys_execve(elf, argv, envp)
178 sys_exit(127)
179 }
180 let st: *i64 = sys_mmap(16) as *i64
181 sys_wait4(pid, st, 0)
182 let sig: i64 = st[0] & 0x7f
183 if sig != 0 { return 128 + sig }
184 return (st[0] >> 8) & 0xff
185}
186
187// find "key" in buf and return the integer immediately following it; -1 if the
188// key is absent (a missing sub-report shows as -1 in the digest -- visible, not hidden)
189func dg_extract(buf: *u8, sz: i64, key: *u8) -> i64 {
190 let n: i64 = dg_slen(key)
191 var i: i64 = 0
192 while i + n <= sz {
193 var ok: i64 = 1
194 var j: i64 = 0
195 while j < n {
196 if buf[i + j] != key[j] { ok = 0; j = n } else { j = j + 1 }
197 }
198 if ok == 1 {
199 var p: i64 = i + n
200 var neg: i64 = 0
201 if p < sz { if buf[p] == (45 as u8) { neg = 1; p = p + 1 } }
202 var v: i64 = 0
203 var got: i64 = 0
204 var go: i64 = 1
205 while go == 1 {
206 if p >= sz { go = 0 } else {
207 let d: i64 = (buf[p] as i64) - 48
208 if d >= 0 { if d <= 9 { v = v * 10 + d; got = 1; p = p + 1 } else { go = 0 } } else { go = 0 }
209 }
210 }
211 if got == 0 { return 0 - 1 }
212 if neg == 1 { return 0 - v }
213 return v
214 }
215 i = i + 1
216 }
217 return 0 - 1
218}
219
220// offset of the first occurrence of needle in buf, or -1
221func dg_find(buf: *u8, sz: i64, needle: *u8) -> i64 {
222 let n: i64 = dg_slen(needle)
223 var i: i64 = 0
224 while i + n <= sz {
225 var ok: i64 = 1
226 var j: i64 = 0
227 while j < n {
228 if buf[i + j] != needle[j] { ok = 0; j = n } else { j = j + 1 }
229 }
230 if ok == 1 { return i }
231 i = i + 1
232 }
233 return 0 - 1
234}
235
236// read digest.conf and copy the value for <key> into out; returns 1 if found
237func dg_conf_get(cb: *u8, csz: i64, key: *u8, out: *u8, cap: i64) -> i64 {
238 let t0: *u8 = sys_mmap(256)
239 let t1: *u8 = sys_mmap(512)
240 var i: i64 = 0
241 while i < csz {
242 var e: i64 = i
243 var go: i64 = 1
244 while go == 1 {
245 if e >= csz { go = 0 } else {
246 if cb[e] == (10 as u8) { go = 0 } else { e = e + 1 }
247 }
248 }
249 var p: i64 = dg_tok(cb, i, e, t0, 256)
250 if t0[0] == (35 as u8) { t0[0] = 0 as u8 }
251 if dg_eq(t0, key) == 1 {
252 dg_tok(cb, p, e, t1, 512)
253 if t1[0] != (0 as u8) {
254 var k: i64 = 0
255 while t1[k] != (0 as u8) { if k < cap - 1 { out[k] = t1[k] }; k = k + 1 }
256 out[k] = 0 as u8
257 return 1
258 }
259 }
260 i = e + 1
261 }
262 return 0
263}
264
265func dg_cmd_digest(argc: i64, argv: *i64) -> i64 {
266 if argc < 4 { dg_p("VIZSLA-DIGEST digest needs <digest.conf> <today> -- fail loud\n" as *u8); return 1 }
267 let szp: *i64 = sys_mmap(16) as *i64
268 let cb: *u8 = dg_readall(argv[2] as *u8, szp)
269 let csz: i64 = szp[0]
270 if csz <= 0 { dg_p("VIZSLA-DIGEST conf MISSING/EMPTY -- fail loud\n" as *u8); return 1 }
271 let today: *u8 = argv[3] as *u8
272
273 let rprefix: *u8 = sys_mmap(512)
274 let rcontacts: *u8 = sys_mmap(512)
275 let nprefix: *u8 = sys_mmap(512)
276 let nconf: *u8 = sys_mmap(512)
277 let ntmpl: *u8 = sys_mmap(512)
278 if dg_conf_get(cb, csz, "RELATE_PREFIX" as *u8, rprefix, 512) == 0 { dg_p("VIZSLA-DIGEST conf missing RELATE_PREFIX -- fail loud\n" as *u8); return 1 }
279 if dg_conf_get(cb, csz, "RELATE_CONTACTS" as *u8, rcontacts, 512) == 0 { dg_p("VIZSLA-DIGEST conf missing RELATE_CONTACTS -- fail loud\n" as *u8); return 1 }
280 if dg_conf_get(cb, csz, "NOTES_PREFIX" as *u8, nprefix, 512) == 0 { dg_p("VIZSLA-DIGEST conf missing NOTES_PREFIX -- fail loud\n" as *u8); return 1 }
281 if dg_conf_get(cb, csz, "NOTES_CONF" as *u8, nconf, 512) == 0 { dg_p("VIZSLA-DIGEST conf missing NOTES_CONF -- fail loud\n" as *u8); return 1 }
282 if dg_conf_get(cb, csz, "NOTES_TEMPLATES" as *u8, ntmpl, 512) == 0 { dg_p("VIZSLA-DIGEST conf missing NOTES_TEMPLATES -- fail loud\n" as *u8); return 1 }
283
284 // compose: run the two blessed organs over the named data
285 let rc_b: i64 = dg_run("_offc/nx_vizsla_relate.elf" as *u8, "brief" as *u8, rprefix, rcontacts, today, 0 as *u8, "/tmp/dg_brief.txt" as *u8)
286 if rc_b != 0 { dg_p("VIZSLA-DIGEST relate brief FAILED -- fail loud\n" as *u8); return 1 }
287 let rc_n: i64 = dg_run("_offc/nx_vizsla_notes.elf" as *u8, "draftdue" as *u8, nprefix, ntmpl, today, nconf, "/tmp/dg_notes.txt" as *u8)
288 if rc_n != 0 { dg_p("VIZSLA-DIGEST notes draftdue FAILED -- fail loud\n" as *u8); return 1 }
289
290 let bsz: *i64 = sys_mmap(16) as *i64
291 let bbuf: *u8 = dg_readall("/tmp/dg_brief.txt" as *u8, bsz)
292 let nsz: *i64 = sys_mmap(16) as *i64
293 let nbuf: *u8 = dg_readall("/tmp/dg_notes.txt" as *u8, nsz)
294
295 // OPTIONAL bills section: if the conf names BILLS_PREFIX + BILLS_FILE, run
296 // the bills tracker too (keeps digest backward-compatible without bills)
297 let bprefix: *u8 = sys_mmap(512)
298 let bfile: *u8 = sys_mmap(512)
299 var has_bills: i64 = 0
300 if dg_conf_get(cb, csz, "BILLS_PREFIX" as *u8, bprefix, 512) == 1 {
301 if dg_conf_get(cb, csz, "BILLS_FILE" as *u8, bfile, 512) == 1 { has_bills = 1 }
302 }
303 let blsz: *i64 = sys_mmap(16) as *i64
304 var blbuf: *u8 = 0 as *u8
305 var bills_due: i64 = 0
306 var bills_over: i64 = 0
307 var bills_owed: i64 = 0
308 if has_bills == 1 {
309 let rc_bl: i64 = dg_run("_offc/nx_vizsla_bills.elf" as *u8, "status" as *u8, bprefix, bfile, today, 0 as *u8, "/tmp/dg_bills.txt" as *u8)
310 if rc_bl != 0 { dg_p("VIZSLA-DIGEST bills status FAILED -- fail loud\n" as *u8); return 1 }
311 blbuf = dg_readall("/tmp/dg_bills.txt" as *u8, blsz)
312 let voff: i64 = dg_find(blbuf, blsz[0], "VIZSLA-BILL-VERDICT" as *u8)
313 if voff >= 0 {
314 let vt: *u8 = (blbuf as i64 + voff) as *u8
315 let vl: i64 = blsz[0] - voff
316 bills_due = dg_extract(vt, vl, "due=" as *u8)
317 bills_over = dg_extract(vt, vl, "overdue=" as *u8)
318 bills_owed = dg_extract(vt, vl, "owed_cents=" as *u8)
319 }
320 }
321
322 // OPTIONAL calendar section: CAL_PREFIX -> today's events + free/busy
323 let calpfx: *u8 = sys_mmap(512)
324 var has_cal: i64 = 0
325 if dg_conf_get(cb, csz, "CAL_PREFIX" as *u8, calpfx, 512) == 1 { has_cal = 1 }
326 let calsz: *i64 = sys_mmap(16) as *i64
327 var calbuf: *u8 = 0 as *u8
328 var cal_events: i64 = 0
329 var cal_free: i64 = 0
330 if has_cal == 1 {
331 let rc_c: i64 = dg_run("_offc/nx_vizsla_calendar.elf" as *u8, "day" as *u8, calpfx, today, 0 as *u8, 0 as *u8, "/tmp/dg_cal.txt" as *u8)
332 if rc_c != 0 { dg_p("VIZSLA-DIGEST calendar day FAILED -- fail loud\n" as *u8); return 1 }
333 calbuf = dg_readall("/tmp/dg_cal.txt" as *u8, calsz)
334 let cvoff: i64 = dg_find(calbuf, calsz[0], "VIZSLA-CAL-DAY-VERDICT" as *u8)
335 if cvoff >= 0 {
336 let cvt: *u8 = (calbuf as i64 + cvoff) as *u8
337 let cvl: i64 = calsz[0] - cvoff
338 cal_events = dg_extract(cvt, cvl, "events=" as *u8)
339 cal_free = dg_extract(cvt, cvl, "free_min=" as *u8)
340 }
341 }
342
343 // OPTIONAL reminders section: REMIND_CONTACTS + REMIND_LEADS (+ REMIND_SENT ledger);
344 // the calendar side rides CAL_PREFIX when present
345 let rcontacts2: *u8 = sys_mmap(512)
346 let rleads: *u8 = sys_mmap(128)
347 let rsent: *u8 = sys_mmap(512)
348 var has_rem: i64 = 0
349 if dg_conf_get(cb, csz, "REMIND_CONTACTS" as *u8, rcontacts2, 512) == 1 {
350 if dg_conf_get(cb, csz, "REMIND_LEADS" as *u8, rleads, 128) == 1 { has_rem = 1 }
351 }
352 var has_sent: i64 = 0
353 if dg_conf_get(cb, csz, "REMIND_SENT" as *u8, rsent, 512) == 1 { has_sent = 1 }
354 let remsz: *i64 = sys_mmap(16) as *i64
355 var rembuf: *u8 = 0 as *u8
356 var rem_due: i64 = 0
357 var rem_bd: i64 = 0
358 if has_rem == 1 {
359 var remcal: *u8 = "-" as *u8
360 if has_cal == 1 { remcal = calpfx }
361 var rc_r: i64 = 0
362 if has_sent == 1 {
363 rc_r = dg_run6("_offc/nx_vizsla_remind.elf" as *u8, "due" as *u8, remcal, rcontacts2, today, rleads, rsent, "/tmp/dg_rem.txt" as *u8)
364 } else {
365 rc_r = dg_run("_offc/nx_vizsla_remind.elf" as *u8, "due" as *u8, remcal, rcontacts2, today, rleads, "/tmp/dg_rem.txt" as *u8)
366 }
367 if rc_r != 0 { dg_p("VIZSLA-DIGEST remind due FAILED -- fail loud\n" as *u8); return 1 }
368 rembuf = dg_readall("/tmp/dg_rem.txt" as *u8, remsz)
369 let rvoff: i64 = dg_find(rembuf, remsz[0], "VIZSLA-REM-VERDICT" as *u8)
370 if rvoff >= 0 {
371 let rvt: *u8 = (rembuf as i64 + rvoff) as *u8
372 let rvl: i64 = remsz[0] - rvoff
373 rem_due = dg_extract(rvt, rvl, " due=" as *u8)
374 rem_bd = dg_extract(rvt, rvl, "due_birthdays=" as *u8)
375 }
376 }
377
378 // OPTIONAL plan section: PLAN_PREFIX + PLAN_NAME -> ready/blocked/late
379 let pprefix: *u8 = sys_mmap(512)
380 let pname: *u8 = sys_mmap(256)
381 var has_plan: i64 = 0
382 if dg_conf_get(cb, csz, "PLAN_PREFIX" as *u8, pprefix, 512) == 1 {
383 if dg_conf_get(cb, csz, "PLAN_NAME" as *u8, pname, 256) == 1 { has_plan = 1 }
384 }
385 let plsz: *i64 = sys_mmap(16) as *i64
386 var plbuf: *u8 = 0 as *u8
387 var plan_ready: i64 = 0
388 var plan_blocked: i64 = 0
389 var plan_late: i64 = 0
390 if has_plan == 1 {
391 let rc_p: i64 = dg_run("_offc/nx_vizsla_plan.elf" as *u8, "board" as *u8, pprefix, pname, today, 0 as *u8, "/tmp/dg_plan.txt" as *u8)
392 if rc_p != 0 { dg_p("VIZSLA-DIGEST plan board FAILED -- fail loud\n" as *u8); return 1 }
393 plbuf = dg_readall("/tmp/dg_plan.txt" as *u8, plsz)
394 let pvoff: i64 = dg_find(plbuf, plsz[0], "VIZSLA-PLAN-VERDICT" as *u8)
395 if pvoff >= 0 {
396 let pvt: *u8 = (plbuf as i64 + pvoff) as *u8
397 let pvl: i64 = plsz[0] - pvoff
398 plan_ready = dg_extract(pvt, pvl, "ready=" as *u8)
399 plan_blocked = dg_extract(pvt, pvl, "blocked=" as *u8)
400 plan_late = dg_extract(pvt, pvl, "late=" as *u8)
401 }
402 }
403
404 // OPTIONAL venue section: VENUE_PREFIX + VENUE_EVENT -> the hire pipeline board
405 let vprefix: *u8 = sys_mmap(512)
406 let vevent: *u8 = sys_mmap(256)
407 var has_ven: i64 = 0
408 if dg_conf_get(cb, csz, "VENUE_PREFIX" as *u8, vprefix, 512) == 1 {
409 if dg_conf_get(cb, csz, "VENUE_EVENT" as *u8, vevent, 256) == 1 { has_ven = 1 }
410 }
411 let vnsz: *i64 = sys_mmap(16) as *i64
412 var vnbuf: *u8 = 0 as *u8
413 var ven_count: i64 = 0
414 var ven_booked: i64 = 0
415 if has_ven == 1 {
416 let rc_v: i64 = dg_run("_offc/nx_vizsla_venue.elf" as *u8, "board" as *u8, vprefix, vevent, 0 as *u8, 0 as *u8, "/tmp/dg_ven.txt" as *u8)
417 if rc_v != 0 { dg_p("VIZSLA-DIGEST venue board FAILED -- fail loud\n" as *u8); return 1 }
418 vnbuf = dg_readall("/tmp/dg_ven.txt" as *u8, vnsz)
419 let vvoff: i64 = dg_find(vnbuf, vnsz[0], "VIZSLA-VEN-VERDICT" as *u8)
420 if vvoff >= 0 {
421 let vvt: *u8 = (vnbuf as i64 + vvoff) as *u8
422 let vvl: i64 = vnsz[0] - vvoff
423 ven_count = dg_extract(vvt, vvl, "venues=" as *u8)
424 ven_booked = 1
425 if dg_find(vvt, vvl, "booked=none" as *u8) >= 0 { ven_booked = 0 }
426 }
427 }
428
429 let followups: i64 = dg_extract(bbuf, bsz[0], "followups=" as *u8)
430 let birthdays: i64 = dg_extract(bbuf, bsz[0], "birthdays=" as *u8)
431 let thankyous: i64 = dg_extract(bbuf, bsz[0], "thankyous=" as *u8)
432 let obligations: i64 = dg_extract(bbuf, bsz[0], "obligations=" as *u8)
433 let drafted: i64 = dg_extract(nbuf, nsz[0], "drafted=" as *u8)
434
435 let rep: *u8 = sys_mmap(K_MAGIC_262144)
436 var o: i64 = 0
437 o = dg_cat(rep, o, "VIZSLA-DIGEST date=" as *u8)
438 o = dg_cat(rep, o, today)
439 o = dg_cat(rep, o, "\n== RELATIONSHIPS (who to tend today) ==\n" as *u8)
440 var bi: i64 = 0
441 while bi < bsz[0] { rep[o] = bbuf[bi]; o = o + 1; bi = bi + 1 }
442 o = dg_cat(rep, o, "== NOTES TO SEND (drafts ready) ==\n" as *u8)
443 var ni: i64 = 0
444 while ni < nsz[0] { rep[o] = nbuf[ni]; o = o + 1; ni = ni + 1 }
445 if has_bills == 1 {
446 o = dg_cat(rep, o, "== BILLS (due / overdue) ==\n" as *u8)
447 var bli: i64 = 0
448 while bli < blsz[0] { rep[o] = blbuf[bli]; o = o + 1; bli = bli + 1 }
449 }
450 if has_cal == 1 {
451 o = dg_cat(rep, o, "== CALENDAR TODAY ==\n" as *u8)
452 var ci: i64 = 0
453 while ci < calsz[0] { rep[o] = calbuf[ci]; o = o + 1; ci = ci + 1 }
454 }
455 if has_rem == 1 {
456 o = dg_cat(rep, o, "== REMINDERS (birthdays + important events) ==\n" as *u8)
457 var ri: i64 = 0
458 while ri < remsz[0] { rep[o] = rembuf[ri]; o = o + 1; ri = ri + 1 }
459 }
460 if has_plan == 1 {
461 o = dg_cat(rep, o, "== PLAN (ready / blocked / late) ==\n" as *u8)
462 var pli: i64 = 0
463 while pli < plsz[0] { rep[o] = plbuf[pli]; o = o + 1; pli = pli + 1 }
464 }
465 if has_ven == 1 {
466 o = dg_cat(rep, o, "== VENUE HUNT ==\n" as *u8)
467 var vni: i64 = 0
468 while vni < vnsz[0] { rep[o] = vnbuf[vni]; o = o + 1; vni = vni + 1 }
469 }
470 o = dg_cat(rep, o, "VIZSLA-DIGEST-VERDICT followups=" as *u8)
471 o = dg_catn(rep, o, followups)
472 o = dg_cat(rep, o, " birthdays=" as *u8)
473 o = dg_catn(rep, o, birthdays)
474 o = dg_cat(rep, o, " thankyous=" as *u8)
475 o = dg_catn(rep, o, thankyous)
476 o = dg_cat(rep, o, " obligations=" as *u8)
477 o = dg_catn(rep, o, obligations)
478 o = dg_cat(rep, o, " notes_drafted=" as *u8)
479 o = dg_catn(rep, o, drafted)
480 if has_bills == 1 {
481 o = dg_cat(rep, o, " bills_due=" as *u8)
482 o = dg_catn(rep, o, bills_due)
483 o = dg_cat(rep, o, " bills_overdue=" as *u8)
484 o = dg_catn(rep, o, bills_over)
485 o = dg_cat(rep, o, " bills_owed_cents=" as *u8)
486 o = dg_catn(rep, o, bills_owed)
487 }
488 if has_cal == 1 {
489 o = dg_cat(rep, o, " cal_events=" as *u8)
490 o = dg_catn(rep, o, cal_events)
491 o = dg_cat(rep, o, " cal_free_min=" as *u8)
492 o = dg_catn(rep, o, cal_free)
493 }
494 if has_rem == 1 {
495 o = dg_cat(rep, o, " reminders_due=" as *u8)
496 o = dg_catn(rep, o, rem_due)
497 o = dg_cat(rep, o, " reminders_birthdays=" as *u8)
498 o = dg_catn(rep, o, rem_bd)
499 }
500 if has_plan == 1 {
501 o = dg_cat(rep, o, " plan_ready=" as *u8)
502 o = dg_catn(rep, o, plan_ready)
503 o = dg_cat(rep, o, " plan_blocked=" as *u8)
504 o = dg_catn(rep, o, plan_blocked)
505 o = dg_cat(rep, o, " plan_late=" as *u8)
506 o = dg_catn(rep, o, plan_late)
507 }
508 if has_ven == 1 {
509 o = dg_cat(rep, o, " venues=" as *u8)
510 o = dg_catn(rep, o, ven_count)
511 o = dg_cat(rep, o, " venue_booked=" as *u8)
512 o = dg_catn(rep, o, ven_booked)
513 }
514 o = dg_cat(rep, o, "\n" as *u8)
515 sys_write(1, rep, o)
516
517 let fd: i64 = sys_openat_append("knowledge/status/vizsla_digest.log" as *u8, 0x1a4)
518 if fd > 0 {
519 let hdr: *u8 = sys_mmap(128)
520 var ho: i64 = 0
521 ho = dg_cat(hdr, ho, "VIZSLA-DIGEST epoch=" as *u8)
522 ho = dg_catn(hdr, ho, sys_now_realtime_sec())
523 ho = dg_cat(hdr, ho, "\n" as *u8)
524 sys_write(fd, hdr, ho)
525 sys_write(fd, rep, o)
526 sys_close(fd)
527 }
528 return 0
529}
530
531func main(argc: i64, argv: *i64) -> i64 {
532 if argc < 2 { dg_p("VIZSLA-DIGEST usage: digest <digest.conf> <today> -- fail loud\n" as *u8); return 1 }
533 let cmd: *u8 = argv[1] as *u8
534 if dg_eq(cmd, "digest" as *u8) == 1 { return dg_cmd_digest(argc, argv) }
535 dg_p("VIZSLA-DIGEST unknown command (digest) -- fail loud\n" as *u8)
536 return 1
537}