code wiki / _hdl_build / nx_vizsla_relate.nx

nx_vizsla_relate.nx source

↩ module page · 1056 lines · 39928 B

1// nx_vizsla_relate.nx -- NISHI VIZSLA V4: the relationships / PRM keystone. 2// Operator directive 2026-06-14: "build the project management and PRM ... help 3// us manage our contacts, thank yous". This is the sovereign home of the old 4// nishi-prm "Tom Hagen consigliere" design: proactive counsel, a BIDIRECTIONAL 5// obligation ledger (debts I owe AND credits owed to me), and thank-you tracking 6// as a managed obligation -- folded onto the VIZSLA substrate (CID records on 7// seg_store, civil-date math, idempotent-by-construction) inherited from V2c. 8// 9// THEORY AS DATA (law 11/25): relationship tiers + their desired touch cadence, 10// and the "coming up soon" window, all live in contacts.txt -- refining the 11// model (a new tier, a tighter cadence) is a data edit, never a recompile. 12// 13// Commands (argv[1]): 14// load <relate_log> <prefix> [segid] TOUCH/OBLIGATION/SETTLE/THANKS/SENT 15// rows -> canonical records -> CID keys 16// "rel:nxc1-..." on seg_store = additive, 17// idempotent-by-construction (law 10). 18// cadence <prefix> <contacts> <today> per contact: LATEST touch date vs its 19// TIER cadence -> FRESH / DUE(reconnect) / 20// NEW(introduce). today via argv = 21// deterministic stdout. 22// ledger <prefix> <contacts> bidirectional obligation ledger: open 23// OWE (I owe) + open DUE (owed to me) 24// after applying SETTLE; per-direction 25// counts + cent totals. Closing is an 26// ADDITIVE settle event, never a delete. 27// thanks <prefix> <contacts> <today> open thank-yous (THANKS with no matching 28// SENT): days owed, PENDING(<=soon_days) / 29// OVERDUE. Gratitude as a tracked debt. 30// brief <prefix> <contacts> <today> the CONSIGLIERE daily brief: follow-ups 31// due + birthdays within soon_days + open 32// thank-yous + open obligations, composed 33// into one "what to do today". 34// 35// File formats (line records, # comments): 36// contacts: CONF soon_days <n> 37// TIER <name> <cadence_days> 38// CONTACT <id> <display> <tier> <birthday> (birthday MM-DD or "-") 39// relate_log: 40// TOUCH <date> <contact> <note> 41// OBLIGATION <date> <dir> <contact> <ref> <amount_cents> <desc> 42// (dir = OWE | DUE) 43// SETTLE <date> <ref> <note> (closes that ref) 44// THANKS <date> <contact> <occasion> 45// SENT <date> <contact> <occasion> (closes that thanks) 46// (date YYYY-MM-DD; note/desc/occasion = single hyphenated tokens this rung; 47// rich-text drafts are V4b / the thankyounotes.com product.) 48// 49// Determinism: stdout has no clocks (today via argv; epoch headers go to logs 50// only). Loud-fail law: missing files, CONTACT on an undeclared TIER, malformed 51// dates, OBLIGATION dir not OWE/DUE = exit 1. 52// EXCEED (honest, feature-class -- not a throughput claim): no consumer PRM 53// (Clay/Dex/Folk/Monica) models a BIDIRECTIONAL obligation ledger or thank-you- 54// as-managed-obligation, and none keep additive tamper-evident relationship 55// history with as-of time-travel. Outreach DRAFT prose = V4b. 56// 57// module: nishi-core.vizsla.relate 58// depends: nishi-core.lib.syscalls, nishi-core.lib.canon_cid, nishi-core.lib.seg_store 59// capability: VIZSLA_RELATE_PRM 60// spec: knowledge/specs/2026-06-10-nishi-vizsla-ladder.md license_tier: ORIGINAL 61import "nx_syscalls.nx" 62import "nx_canon_cid.nx" 63import "nx_seg_store.nx" 64const K_MAGIC_1970: i64 = 1970 65const K_MAGIC_146097: i64 = 146097 66const K_MAGIC_719468: i64 = 719468 67const K_MAGIC_4096: i64 = 4096 68const K_MAGIC_2048: i64 = 2048 69const K_MAGIC_65536: i64 = 65536 70const K_MAGIC_131072: i64 = 131072 71 72func rl_slen(s: *u8) -> i64 { 73 var n: i64 = 0 74 while s[n] != (0 as u8) { n = n + 1 } 75 return n 76} 77 78func rl_p(s: *u8) -> i64 { 79 sys_write(1, s, rl_slen(s)) 80 return 0 81} 82 83func rl_eq(a: *u8, b: *u8) -> i64 { 84 var i: i64 = 0 85 var go: i64 = 1 86 while go == 1 { 87 if a[i] != b[i] { return 0 } 88 if a[i] == (0 as u8) { return 1 } 89 i = i + 1 90 } 91 return 0 92} 93 94func rl_dup(s: *u8) -> *u8 { 95 let n: i64 = rl_slen(s) 96 let d: *u8 = sys_mmap(n + 2) 97 var i: i64 = 0 98 while i <= n { d[i] = s[i]; i = i + 1 } 99 return d 100} 101 102func rl_atoi(s: *u8) -> i64 { 103 var v: i64 = 0 104 var i: i64 = 0 105 while s[i] != (0 as u8) { 106 let d: i64 = (s[i] as i64) - 48 107 if d >= 0 { if d <= 9 { v = v * 10 + d } } 108 i = i + 1 109 } 110 return v 111} 112 113func rl_isws(c: i64) -> i64 { 114 if c == 32 { return 1 } 115 if c == 13 { return 1 } 116 if c == 9 { return 1 } 117 return 0 118} 119 120func rl_tok(b: *u8, off: i64, lend: i64, dst: *u8, cap: i64) -> i64 { 121 var p: i64 = off 122 var go: i64 = 1 123 while go == 1 { 124 if p >= lend { go = 0 } else { 125 if rl_isws(b[p] as i64) == 1 { p = p + 1 } else { go = 0 } 126 } 127 } 128 var t: i64 = 0 129 go = 1 130 while go == 1 { 131 if p >= lend { go = 0 } else { 132 if rl_isws(b[p] as i64) == 1 { go = 0 } else { 133 if t < cap - 1 { dst[t] = b[p]; t = t + 1 } 134 p = p + 1 135 } 136 } 137 } 138 dst[t] = 0 as u8 139 return p 140} 141 142func rl_cat(dst: *u8, off: i64, s: *u8) -> i64 { 143 var i: i64 = 0 144 while s[i] != (0 as u8) { dst[off + i] = s[i]; i = i + 1 } 145 return off + i 146} 147 148func rl_catn(dst: *u8, off: i64, v: i64) -> i64 { 149 var o: i64 = off 150 var m: i64 = v 151 if m < 0 { dst[o] = 45 as u8; o = o + 1; m = 0 - m } 152 let t: *u8 = sys_mmap(28) 153 var k: i64 = 0 154 if m == 0 { t[0] = 48 as u8; k = 1 } 155 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 156 var i: i64 = 0 157 while i < k { dst[o + i] = t[k - 1 - i]; i = i + 1 } 158 return o + k 159} 160 161func rl_find(list: *i64, n: i64, s: *u8) -> i64 { 162 var i: i64 = 0 163 while i < n { 164 if rl_eq(list[i] as *u8, s) == 1 { return i } 165 i = i + 1 166 } 167 return 0 - 1 168} 169 170func rl_kmemeq(b: *u8, off: i64, n: i64, s: *u8) -> i64 { 171 if rl_slen(s) != n { return 0 } 172 var i: i64 = 0 173 while i < n { 174 if b[off + i] != s[i] { return 0 } 175 i = i + 1 176 } 177 return 1 178} 179 180// decode a named field out of a canonical NXR1 value record (mirror of V2c) 181func rl_field(rec: *u8, rl: i64, want: *u8, out: *u8, cap: i64) -> i64 { 182 if rl < 8 { return 0 } 183 let nf: i64 = ss_r32(rec, 4) 184 var off: i64 = 8 185 var fi: i64 = 0 186 while fi < nf { 187 if off + 8 > rl { return 0 } 188 let kl: i64 = ss_r32(rec, off) 189 let koff: i64 = off + 4 190 let vl: i64 = ss_r32(rec, koff + kl) 191 let voff: i64 = koff + kl + 4 192 if rl_kmemeq(rec, koff, kl, want) == 1 { 193 var t: i64 = 0 194 while t < vl { 195 if t < cap - 1 { out[t] = rec[voff + t] } 196 t = t + 1 197 } 198 if t > cap - 1 { t = cap - 1 } 199 out[t] = 0 as u8 200 return 1 201 } 202 off = voff + vl 203 fi = fi + 1 204 } 205 return 0 206} 207 208func rl_isrel(b: *u8, koff: i64, kl: i64) -> i64 { 209 if kl <= 4 { return 0 } 210 return rl_kmemeq(b, koff, 4, "rel:" as *u8) 211} 212 213// civil date "YYYY-MM-DD" -> days since 1970-01-01 (Hinnant); -1 if malformed 214func rl_datedays(s: *u8) -> i64 { 215 let nums: *i64 = sys_mmap(8 * 4) as *i64 216 var nn: i64 = 0 217 var cur: i64 = 0 218 var indig: i64 = 0 219 var i: i64 = 0 220 var go: i64 = 1 221 while go == 1 { 222 let c: i64 = s[i] as i64 223 var isd: i64 = 0 224 if c >= 48 { if c <= 57 { isd = 1 } } 225 if isd == 1 { cur = cur * 10 + (c - 48); indig = 1 } 226 if isd == 0 { 227 if indig == 1 { 228 if nn < 4 { nums[nn] = cur; nn = nn + 1 } 229 cur = 0 230 indig = 0 231 } 232 } 233 if c == 0 { go = 0 } 234 i = i + 1 235 } 236 if nn != 3 { return 0 - 1 } 237 var y: i64 = nums[0] 238 let m: i64 = nums[1] 239 let d: i64 = nums[2] 240 if y < K_MAGIC_1970 { return 0 - 1 } 241 if m < 1 { return 0 - 1 } 242 if m > 12 { return 0 - 1 } 243 if d < 1 { return 0 - 1 } 244 if d > 31 { return 0 - 1 } 245 if m <= 2 { y = y - 1 } 246 let era: i64 = y / 400 247 let yoe: i64 = y - era * 400 248 var mp: i64 = m - 3 249 if m <= 2 { mp = m + 9 } 250 let doy: i64 = (153 * mp + 2) / 5 + d - 1 251 let doe: i64 = yoe * 365 + yoe / 4 - yoe / 100 + doy 252 return era * K_MAGIC_146097 + doe - K_MAGIC_719468 253} 254 255// leading integer (the year) out of a "YYYY-..." token 256func rl_yearof(s: *u8) -> i64 { 257 var v: i64 = 0 258 var i: i64 = 0 259 var go: i64 = 1 260 while go == 1 { 261 let c: i64 = s[i] as i64 262 if c >= 48 { if c <= 57 { v = v * 10 + (c - 48); i = i + 1; go = 2 } } 263 if go == 1 { go = 0 } 264 if go == 2 { go = 1 } 265 } 266 return v 267} 268 269// days until the next occurrence of a "MM-DD" birthday from today; -1 if "-" 270func rl_bday_until(today: *u8, today_days: i64, mmdd: *u8) -> i64 { 271 if mmdd[0] == (45 as u8) { if mmdd[1] == (0 as u8) { return 0 - 1 } } 272 let yr: i64 = rl_yearof(today) 273 if yr < K_MAGIC_1970 { return 0 - 1 } 274 let cand: *u8 = sys_mmap(32) 275 var co: i64 = 0 276 co = rl_catn(cand, co, yr) 277 cand[co] = 45 as u8; co = co + 1 278 co = rl_cat(cand, co, mmdd) 279 cand[co] = 0 as u8 280 var bdd: i64 = rl_datedays(cand) 281 if bdd < 0 { return 0 - 1 } 282 if bdd < today_days { 283 var c2: i64 = 0 284 c2 = rl_catn(cand, c2, yr + 1) 285 cand[c2] = 45 as u8; c2 = c2 + 1 286 c2 = rl_cat(cand, c2, mmdd) 287 cand[c2] = 0 as u8 288 bdd = rl_datedays(cand) 289 if bdd < 0 { return 0 - 1 } 290 } 291 return bdd - today_days 292} 293 294func rl_log(lpath: *u8, tag: *u8, rep: *u8, o: i64) -> i64 { 295 let fd: i64 = sys_openat_append(lpath, 0x1a4) 296 if fd <= 0 { return 0 } 297 let hdr: *u8 = sys_mmap(256) 298 var ho: i64 = 0 299 ho = rl_cat(hdr, ho, "VIZSLA-RELATE epoch=" as *u8) 300 ho = rl_catn(hdr, ho, sys_now_realtime_sec()) 301 ho = rl_cat(hdr, ho, " cmd=" as *u8) 302 ho = rl_cat(hdr, ho, tag) 303 ho = rl_cat(hdr, ho, "\n" as *u8) 304 sys_write(fd, hdr, ho) 305 sys_write(fd, rep, o) 306 sys_close(fd) 307 return 0 308} 309 310func rl_prefixlog(prefix: *u8, out: *u8) -> i64 { 311 var o: i64 = 0 312 o = rl_cat(out, o, prefix) 313 o = rl_cat(out, o, "relate.log" as *u8) 314 out[o] = 0 as u8 315 return o 316} 317 318// contacts table packed in one heap-mmap state block: 319// cf[0]=ct_id cf[1]=ct_disp cf[2]=ct_tier(idx) cf[3]=ct_bday cf[4]=nct 320// cf[5]=tr_name cf[6]=tr_days cf[7]=ntr cf[8]=(reserved) cf[9]=soon_days 321func rl_load_contacts(cpath: *u8) -> *i64 { 322 let szp: *i64 = sys_mmap(16) as *i64 323 let cb: *u8 = ss_readall(cpath, szp) 324 let csz: i64 = szp[0] 325 if csz <= 0 { return 0 as *i64 } 326 let cf: *i64 = sys_mmap(8 * 16) as *i64 327 cf[0] = sys_mmap(8 * 256) 328 cf[1] = sys_mmap(8 * 256) 329 cf[2] = sys_mmap(8 * 256) 330 cf[3] = sys_mmap(8 * 256) 331 cf[4] = 0 332 cf[5] = sys_mmap(8 * 16) 333 cf[6] = sys_mmap(8 * 16) 334 cf[7] = 0 335 cf[8] = 0 336 cf[9] = 14 337 let ct_id: *i64 = cf[0] as *i64 338 let ct_disp: *i64 = cf[1] as *i64 339 let ct_tier: *i64 = cf[2] as *i64 340 let ct_bday: *i64 = cf[3] as *i64 341 let tr_name: *i64 = cf[5] as *i64 342 let tr_days: *i64 = cf[6] as *i64 343 let t0: *u8 = sys_mmap(128) 344 let t1: *u8 = sys_mmap(128) 345 let t2: *u8 = sys_mmap(128) 346 let t3: *u8 = sys_mmap(128) 347 var i: i64 = 0 348 while i < csz { 349 var e: i64 = i 350 var go: i64 = 1 351 while go == 1 { 352 if e >= csz { go = 0 } else { 353 if cb[e] == (10 as u8) { go = 0 } else { e = e + 1 } 354 } 355 } 356 var p: i64 = rl_tok(cb, i, e, t0, 128) 357 if t0[0] == (35 as u8) { t0[0] = 0 as u8 } 358 if rl_eq(t0, "CONF" as *u8) == 1 { 359 p = rl_tok(cb, p, e, t1, 128) 360 p = rl_tok(cb, p, e, t2, 128) 361 if rl_eq(t1, "soon_days" as *u8) == 1 { cf[9] = rl_atoi(t2) } 362 } 363 if rl_eq(t0, "TIER" as *u8) == 1 { 364 p = rl_tok(cb, p, e, t1, 128) 365 p = rl_tok(cb, p, e, t2, 128) 366 if cf[7] < 16 { tr_name[cf[7]] = rl_dup(t1) as i64; tr_days[cf[7]] = rl_atoi(t2); cf[7] = cf[7] + 1 } 367 } 368 if rl_eq(t0, "CONTACT" as *u8) == 1 { 369 p = rl_tok(cb, p, e, t1, 128) 370 p = rl_tok(cb, p, e, t2, 128) 371 p = rl_tok(cb, p, e, t3, 128) 372 let ti: i64 = rl_find(tr_name, cf[7], t3) 373 if ti < 0 { return 0 as *i64 } 374 let bd: *u8 = sys_mmap(16) 375 rl_tok(cb, p, e, bd, 16) 376 if bd[0] == (0 as u8) { bd[0] = 45 as u8; bd[1] = 0 as u8 } 377 if cf[4] < 256 { 378 ct_id[cf[4]] = rl_dup(t1) as i64 379 ct_disp[cf[4]] = rl_dup(t2) as i64 380 ct_tier[cf[4]] = ti 381 ct_bday[cf[4]] = rl_dup(bd) as i64 382 cf[4] = cf[4] + 1 383 } 384 } 385 i = e + 1 386 } 387 if cf[7] < 1 { return 0 as *i64 } 388 if cf[4] < 1 { return 0 as *i64 } 389 return cf 390} 391 392// ---------------- LOAD (additive event journal -> CID records) ---------------- 393func rl_cmd_load(argc: i64, argv: *i64) -> i64 { 394 if argc < 4 { rl_p("VIZSLA-RELATE load needs <relate_log> <prefix> -- fail loud\n" as *u8); return 1 } 395 let lpath: *u8 = argv[2] as *u8 396 let prefix: *u8 = argv[3] as *u8 397 var segid: i64 = 0 398 if argc > 4 { segid = rl_atoi(argv[4] as *u8) } 399 if segid == 0 { segid = sys_now_us() } 400 401 let szp: *i64 = sys_mmap(16) as *i64 402 let b: *u8 = ss_readall(lpath, szp) 403 let sz: i64 = szp[0] 404 if sz <= 0 { rl_p("VIZSLA-RELATE relate_log MISSING/EMPTY -- fail loud\n" as *u8); return 1 } 405 406 let keys: *i64 = sys_mmap(8 * 8) as *i64 407 let vals: *i64 = sys_mmap(8 * 8) as *i64 408 keys[0] = "k" as *u8 as i64 409 keys[1] = "date" as *u8 as i64 410 keys[2] = "a" as *u8 as i64 411 keys[3] = "b" as *u8 as i64 412 keys[4] = "c" as *u8 as i64 413 keys[5] = "d" as *u8 as i64 414 keys[6] = "e" as *u8 as i64 415 416 let t0: *u8 = sys_mmap(128) 417 let f1: *u8 = sys_mmap(128) 418 let f2: *u8 = sys_mmap(128) 419 let f3: *u8 = sys_mmap(128) 420 let f4: *u8 = sys_mmap(128) 421 let f5: *u8 = sys_mmap(128) 422 let f6: *u8 = sys_mmap(256) 423 let pp: *i64 = sys_mmap(16) as *i64 424 let ll: *i64 = sys_mmap(16) as *i64 425 426 let w: *i64 = ss_begin() 427 let seen: *i64 = sys_mmap(8 * K_MAGIC_4096) as *i64 428 var nseen: i64 = 0 429 var scanned: i64 = 0 430 var added: i64 = 0 431 var dup_infile: i64 = 0 432 var dup_instore: i64 = 0 433 434 var i: i64 = 0 435 while i < sz { 436 var e: i64 = i 437 var go: i64 = 1 438 while go == 1 { 439 if e >= sz { go = 0 } else { 440 if b[e] == (10 as u8) { go = 0 } else { e = e + 1 } 441 } 442 } 443 var p: i64 = rl_tok(b, i, e, t0, 128) 444 if t0[0] == (35 as u8) { t0[0] = 0 as u8 } 445 var nf: i64 = 0 446 if rl_eq(t0, "TOUCH" as *u8) == 1 { 447 p = rl_tok(b, p, e, f1, 128); p = rl_tok(b, p, e, f2, 128); p = rl_tok(b, p, e, f3, 256) 448 vals[0] = "touch" as *u8 as i64; vals[1] = f1 as i64; vals[2] = f2 as i64; vals[3] = f3 as i64 449 nf = 4 450 } 451 if rl_eq(t0, "OBLIGATION" as *u8) == 1 { 452 p = rl_tok(b, p, e, f1, 128); p = rl_tok(b, p, e, f2, 128); p = rl_tok(b, p, e, f3, 128) 453 p = rl_tok(b, p, e, f4, 128); p = rl_tok(b, p, e, f5, 128); p = rl_tok(b, p, e, f6, 256) 454 if rl_eq(f2, "OWE" as *u8) == 0 { if rl_eq(f2, "DUE" as *u8) == 0 { rl_p("VIZSLA-RELATE OBLIGATION dir not OWE/DUE -- fail loud\n" as *u8); return 1 } } 455 vals[0] = "oblig" as *u8 as i64; vals[1] = f1 as i64; vals[2] = f2 as i64; vals[3] = f3 as i64 456 vals[4] = f4 as i64; vals[5] = f5 as i64; vals[6] = f6 as i64 457 nf = 7 458 } 459 if rl_eq(t0, "SETTLE" as *u8) == 1 { 460 p = rl_tok(b, p, e, f1, 128); p = rl_tok(b, p, e, f2, 128); p = rl_tok(b, p, e, f3, 256) 461 vals[0] = "settle" as *u8 as i64; vals[1] = f1 as i64; vals[2] = f2 as i64; vals[3] = f3 as i64 462 nf = 4 463 } 464 if rl_eq(t0, "THANKS" as *u8) == 1 { 465 p = rl_tok(b, p, e, f1, 128); p = rl_tok(b, p, e, f2, 128); p = rl_tok(b, p, e, f3, 128) 466 vals[0] = "thanks" as *u8 as i64; vals[1] = f1 as i64; vals[2] = f2 as i64; vals[3] = f3 as i64 467 nf = 4 468 } 469 if rl_eq(t0, "SENT" as *u8) == 1 { 470 p = rl_tok(b, p, e, f1, 128); p = rl_tok(b, p, e, f2, 128); p = rl_tok(b, p, e, f3, 128) 471 vals[0] = "sent" as *u8 as i64; vals[1] = f1 as i64; vals[2] = f2 as i64; vals[3] = f3 as i64 472 nf = 4 473 } 474 if nf > 0 { 475 scanned = scanned + 1 476 if rl_datedays(f1) < 0 { rl_p("VIZSLA-RELATE bad date (YYYY-MM-DD) -- fail loud\n" as *u8); return 1 } 477 let enc: *u8 = sys_mmap(K_MAGIC_2048) 478 let el: i64 = canon_encode(keys, vals, nf, enc) 479 let cid: *u8 = sys_mmap(96) 480 cid_of(enc, el, cid) 481 let kbuf: *u8 = sys_mmap(128) 482 var ko: i64 = 0 483 ko = rl_cat(kbuf, ko, "rel:" as *u8) 484 ko = rl_cat(kbuf, ko, cid) 485 kbuf[ko] = 0 as u8 486 var fresh: i64 = 1 487 if rl_find(seen, nseen, kbuf) >= 0 { fresh = 0; dup_infile = dup_infile + 1 } 488 if fresh == 1 { 489 if nseen < K_MAGIC_4096 { seen[nseen] = rl_dup(kbuf) as i64; nseen = nseen + 1 } 490 } 491 if fresh == 1 { 492 if ss_get_idx(prefix, kbuf, pp, ll) == 1 { fresh = 0; dup_instore = dup_instore + 1 } 493 } 494 if fresh == 1 { 495 if ss_add(w, 1, kbuf, enc, el) != 0 { rl_p("VIZSLA-RELATE writer full -- fail loud\n" as *u8); return 1 } 496 added = added + 1 497 } 498 } 499 i = e + 1 500 } 501 502 var committed: i64 = 0 503 if added > 0 { 504 if ss_commit(prefix, w, segid) != 0 { rl_p("VIZSLA-RELATE commit FAILED -- fail loud\n" as *u8); return 1 } 505 committed = 1 506 } 507 508 let rep: *u8 = sys_mmap(K_MAGIC_4096) 509 var o: i64 = 0 510 o = rl_cat(rep, o, "VIZSLA-RELATE-LOAD scanned=" as *u8) 511 o = rl_catn(rep, o, scanned) 512 o = rl_cat(rep, o, " new=" as *u8) 513 o = rl_catn(rep, o, added) 514 o = rl_cat(rep, o, " dup_infile=" as *u8) 515 o = rl_catn(rep, o, dup_infile) 516 o = rl_cat(rep, o, " dup_instore=" as *u8) 517 o = rl_catn(rep, o, dup_instore) 518 o = rl_cat(rep, o, " segment=" as *u8) 519 if committed == 1 { 520 o = rl_cat(rep, o, "seg-" as *u8) 521 o = rl_catn(rep, o, segid) 522 } else { 523 o = rl_cat(rep, o, "none" as *u8) 524 } 525 o = rl_cat(rep, o, "\n" as *u8) 526 sys_write(1, rep, o) 527 let lp: *u8 = sys_mmap(512) 528 rl_prefixlog(prefix, lp) 529 rl_log(lp, "load" as *u8, rep, o) 530 return 0 531} 532 533// fill latest-touch (days,date) per contact idx by walking the store 534func rl_latest_touch(prefix: *u8, cf: *i64, a_days: *i64, a_date: *i64) -> i64 { 535 let ct_id: *i64 = cf[0] as *i64 536 var i0: i64 = 0 537 while i0 < cf[4] { a_days[i0] = 0 - 1; a_date[i0] = "never" as *u8 as i64; i0 = i0 + 1 } 538 let segs: *i64 = sys_mmap(8 * 260) as *i64 539 let ns: i64 = ss_manifest(prefix, segs) 540 let fk: *u8 = sys_mmap(64) 541 let fa: *u8 = sys_mmap(128) 542 let fd: *u8 = sys_mmap(128) 543 var touches: i64 = 0 544 var s: i64 = 0 545 while s < ns { 546 let path: *u8 = sys_mmap(512) 547 var po: i64 = 0 548 po = rl_cat(path, po, prefix); po = rl_cat(path, po, segs[s] as *u8); po = rl_cat(path, po, ".docs" as *u8) 549 path[po] = 0 as u8 550 let szp: *i64 = sys_mmap(16) as *i64 551 let b: *u8 = ss_readall(path, szp) 552 let sz: i64 = szp[0] 553 var j: i64 = 0 554 while j + 9 <= sz { 555 let kind: i64 = b[j] 556 let kl: i64 = ss_r32(b, j + 1) 557 let koff: i64 = j + 5 558 let vl: i64 = ss_r32(b, koff + kl) 559 let voff: i64 = koff + kl + 4 560 var take: i64 = 0 561 if kind == 1 { take = rl_isrel(b, koff, kl) } 562 if take == 1 { 563 let rec: *u8 = (b as i64 + voff) as *u8 564 if rl_field(rec, vl, "k" as *u8, fk, 64) == 1 { 565 if rl_eq(fk, "touch" as *u8) == 1 { 566 if rl_field(rec, vl, "a" as *u8, fa, 128) == 1 { 567 if rl_field(rec, vl, "date" as *u8, fd, 128) == 1 { 568 touches = touches + 1 569 let aix: i64 = rl_find(ct_id, cf[4], fa) 570 if aix >= 0 { 571 let dd: i64 = rl_datedays(fd) 572 if dd > a_days[aix] { a_days[aix] = dd; a_date[aix] = rl_dup(fd) as i64 } 573 } 574 } 575 } 576 } 577 } 578 } 579 j = voff + vl 580 } 581 s = s + 1 582 } 583 return touches 584} 585 586// ---------------- CADENCE (tier-driven follow-up) ---------------- 587func rl_cmd_cadence(argc: i64, argv: *i64) -> i64 { 588 if argc < 5 { rl_p("VIZSLA-RELATE cadence needs <prefix> <contacts> <today> -- fail loud\n" as *u8); return 1 } 589 let prefix: *u8 = argv[2] as *u8 590 let cf: *i64 = rl_load_contacts(argv[3] as *u8) 591 if (cf as i64) == 0 { rl_p("VIZSLA-RELATE contacts MISSING/MALFORMED -- fail loud\n" as *u8); return 1 } 592 let today: i64 = rl_datedays(argv[4] as *u8) 593 if today < 0 { rl_p("VIZSLA-RELATE bad today date (YYYY-MM-DD) -- fail loud\n" as *u8); return 1 } 594 595 let ct_id: *i64 = cf[0] as *i64 596 let ct_tier: *i64 = cf[2] as *i64 597 let tr_name: *i64 = cf[5] as *i64 598 let tr_days: *i64 = cf[6] as *i64 599 let a_days: *i64 = sys_mmap(8 * 256) as *i64 600 let a_date: *i64 = sys_mmap(8 * 256) as *i64 601 rl_latest_touch(prefix, cf, a_days, a_date) 602 603 let rep: *u8 = sys_mmap(K_MAGIC_65536) 604 var o: i64 = 0 605 var nfresh: i64 = 0 606 var ndue: i64 = 0 607 var nnew: i64 = 0 608 var i: i64 = 0 609 while i < cf[4] { 610 let cad: i64 = tr_days[ct_tier[i]] 611 o = rl_cat(rep, o, "VIZSLA-RELATE-CADENCE contact=" as *u8) 612 o = rl_cat(rep, o, ct_id[i] as *u8) 613 o = rl_cat(rep, o, " tier=" as *u8) 614 o = rl_cat(rep, o, tr_name[ct_tier[i]] as *u8) 615 o = rl_cat(rep, o, " last=" as *u8) 616 o = rl_cat(rep, o, a_date[i] as *u8) 617 o = rl_cat(rep, o, " days=" as *u8) 618 if a_days[i] < 0 { o = rl_catn(rep, o, 0 - 1) } else { o = rl_catn(rep, o, today - a_days[i]) } 619 o = rl_cat(rep, o, " cadence=" as *u8) 620 o = rl_catn(rep, o, cad) 621 if a_days[i] < 0 { 622 nnew = nnew + 1 623 o = rl_cat(rep, o, " state=NEW action=introduce\n" as *u8) 624 } else { 625 if today - a_days[i] <= cad { 626 nfresh = nfresh + 1 627 o = rl_cat(rep, o, " state=FRESH action=none\n" as *u8) 628 } else { 629 ndue = ndue + 1 630 o = rl_cat(rep, o, " state=DUE action=reconnect\n" as *u8) 631 } 632 } 633 i = i + 1 634 } 635 o = rl_cat(rep, o, "VIZSLA-RELATE-CADENCE-VERDICT contacts=" as *u8) 636 o = rl_catn(rep, o, cf[4]) 637 o = rl_cat(rep, o, " fresh=" as *u8) 638 o = rl_catn(rep, o, nfresh) 639 o = rl_cat(rep, o, " due=" as *u8) 640 o = rl_catn(rep, o, ndue) 641 o = rl_cat(rep, o, " new=" as *u8) 642 o = rl_catn(rep, o, nnew) 643 o = rl_cat(rep, o, "\n" as *u8) 644 sys_write(1, rep, o) 645 let lp: *u8 = sys_mmap(512) 646 rl_prefixlog(prefix, lp) 647 rl_log(lp, "cadence" as *u8, rep, o) 648 return 0 649} 650 651// collect OPEN obligations (after SETTLE) into an ob block: 652// ob[0]=ct ob[1]=dir ob[2]=ref ob[3]=amt(str) ob[4]=desc ob[5]=nopen ob[6]=settled 653func rl_collect_obligs(prefix: *u8) -> *i64 { 654 let ob: *i64 = sys_mmap(8 * 8) as *i64 655 ob[0] = sys_mmap(8 * 256); ob[1] = sys_mmap(8 * 256); ob[2] = sys_mmap(8 * 256) 656 ob[3] = sys_mmap(8 * 256); ob[4] = sys_mmap(8 * 256); ob[5] = 0; ob[6] = 0 657 let o_ct: *i64 = ob[0] as *i64 658 let o_dir: *i64 = ob[1] as *i64 659 let o_ref: *i64 = ob[2] as *i64 660 let o_amt: *i64 = ob[3] as *i64 661 let o_desc: *i64 = ob[4] as *i64 662 // temp store of all obligations + the settled-ref set 663 let t_ct: *i64 = sys_mmap(8 * 256) as *i64 664 let t_dir: *i64 = sys_mmap(8 * 256) as *i64 665 let t_ref: *i64 = sys_mmap(8 * 256) as *i64 666 let t_amt: *i64 = sys_mmap(8 * 256) as *i64 667 let t_desc: *i64 = sys_mmap(8 * 256) as *i64 668 var nt: i64 = 0 669 let settled: *i64 = sys_mmap(8 * 256) as *i64 670 var nset: i64 = 0 671 672 let segs: *i64 = sys_mmap(8 * 260) as *i64 673 let ns: i64 = ss_manifest(prefix, segs) 674 let fk: *u8 = sys_mmap(64) 675 let fa: *u8 = sys_mmap(128) 676 let fb: *u8 = sys_mmap(128) 677 let fc: *u8 = sys_mmap(128) 678 let fd: *u8 = sys_mmap(128) 679 let fe: *u8 = sys_mmap(256) 680 var s: i64 = 0 681 while s < ns { 682 let path: *u8 = sys_mmap(512) 683 var po: i64 = 0 684 po = rl_cat(path, po, prefix); po = rl_cat(path, po, segs[s] as *u8); po = rl_cat(path, po, ".docs" as *u8) 685 path[po] = 0 as u8 686 let szp: *i64 = sys_mmap(16) as *i64 687 let b: *u8 = ss_readall(path, szp) 688 let sz: i64 = szp[0] 689 var j: i64 = 0 690 while j + 9 <= sz { 691 let kind: i64 = b[j] 692 let kl: i64 = ss_r32(b, j + 1) 693 let koff: i64 = j + 5 694 let vl: i64 = ss_r32(b, koff + kl) 695 let voff: i64 = koff + kl + 4 696 var take: i64 = 0 697 if kind == 1 { take = rl_isrel(b, koff, kl) } 698 if take == 1 { 699 let rec: *u8 = (b as i64 + voff) as *u8 700 if rl_field(rec, vl, "k" as *u8, fk, 64) == 1 { 701 if rl_eq(fk, "oblig" as *u8) == 1 { 702 rl_field(rec, vl, "a" as *u8, fb, 128) 703 rl_field(rec, vl, "b" as *u8, fa, 128) 704 rl_field(rec, vl, "c" as *u8, fc, 128) 705 rl_field(rec, vl, "d" as *u8, fd, 128) 706 rl_field(rec, vl, "e" as *u8, fe, 256) 707 if nt < 256 { 708 t_dir[nt] = rl_dup(fb) as i64 709 t_ct[nt] = rl_dup(fa) as i64 710 t_ref[nt] = rl_dup(fc) as i64 711 t_amt[nt] = rl_dup(fd) as i64 712 t_desc[nt] = rl_dup(fe) as i64 713 nt = nt + 1 714 } 715 } 716 if rl_eq(fk, "settle" as *u8) == 1 { 717 rl_field(rec, vl, "a" as *u8, fc, 128) 718 if nset < 256 { settled[nset] = rl_dup(fc) as i64; nset = nset + 1 } 719 } 720 } 721 } 722 j = voff + vl 723 } 724 s = s + 1 725 } 726 ob[6] = nset 727 var k: i64 = 0 728 while k < nt { 729 if rl_find(settled, nset, t_ref[k] as *u8) < 0 { 730 let n: i64 = ob[5] 731 o_ct[n] = t_ct[k]; o_dir[n] = t_dir[k]; o_ref[n] = t_ref[k]; o_amt[n] = t_amt[k]; o_desc[n] = t_desc[k] 732 ob[5] = n + 1 733 } 734 k = k + 1 735 } 736 return ob 737} 738 739// ---------------- LEDGER (bidirectional obligation ledger) ---------------- 740func rl_cmd_ledger(argc: i64, argv: *i64) -> i64 { 741 if argc < 4 { rl_p("VIZSLA-RELATE ledger needs <prefix> <contacts> -- fail loud\n" as *u8); return 1 } 742 let prefix: *u8 = argv[2] as *u8 743 let cf: *i64 = rl_load_contacts(argv[3] as *u8) 744 if (cf as i64) == 0 { rl_p("VIZSLA-RELATE contacts MISSING/MALFORMED -- fail loud\n" as *u8); return 1 } 745 746 let ob: *i64 = rl_collect_obligs(prefix) 747 let o_ct: *i64 = ob[0] as *i64 748 let o_dir: *i64 = ob[1] as *i64 749 let o_ref: *i64 = ob[2] as *i64 750 let o_amt: *i64 = ob[3] as *i64 751 let o_desc: *i64 = ob[4] as *i64 752 753 let rep: *u8 = sys_mmap(K_MAGIC_65536) 754 var o: i64 = 0 755 var nowe: i64 = 0 756 var ndue: i64 = 0 757 var owe_amt: i64 = 0 758 var due_amt: i64 = 0 759 var i: i64 = 0 760 while i < ob[5] { 761 let amt: i64 = rl_atoi(o_amt[i] as *u8) 762 o = rl_cat(rep, o, "VIZSLA-RELATE-OBLIG contact=" as *u8) 763 o = rl_cat(rep, o, o_ct[i] as *u8) 764 o = rl_cat(rep, o, " dir=" as *u8) 765 o = rl_cat(rep, o, o_dir[i] as *u8) 766 o = rl_cat(rep, o, " ref=" as *u8) 767 o = rl_cat(rep, o, o_ref[i] as *u8) 768 o = rl_cat(rep, o, " amount=" as *u8) 769 o = rl_catn(rep, o, amt) 770 o = rl_cat(rep, o, " desc=" as *u8) 771 o = rl_cat(rep, o, o_desc[i] as *u8) 772 o = rl_cat(rep, o, " state=OPEN\n" as *u8) 773 if rl_eq(o_dir[i] as *u8, "OWE" as *u8) == 1 { nowe = nowe + 1; owe_amt = owe_amt + amt } else { ndue = ndue + 1; due_amt = due_amt + amt } 774 i = i + 1 775 } 776 o = rl_cat(rep, o, "VIZSLA-RELATE-OBLIG-VERDICT open=" as *u8) 777 o = rl_catn(rep, o, ob[5]) 778 o = rl_cat(rep, o, " owe=" as *u8) 779 o = rl_catn(rep, o, nowe) 780 o = rl_cat(rep, o, " due=" as *u8) 781 o = rl_catn(rep, o, ndue) 782 o = rl_cat(rep, o, " owe_amount=" as *u8) 783 o = rl_catn(rep, o, owe_amt) 784 o = rl_cat(rep, o, " due_amount=" as *u8) 785 o = rl_catn(rep, o, due_amt) 786 o = rl_cat(rep, o, " settled=" as *u8) 787 o = rl_catn(rep, o, ob[6]) 788 o = rl_cat(rep, o, "\n" as *u8) 789 sys_write(1, rep, o) 790 let lp: *u8 = sys_mmap(512) 791 rl_prefixlog(prefix, lp) 792 rl_log(lp, "ledger" as *u8, rep, o) 793 return 0 794} 795 796// collect OPEN thank-yous (THANKS with no matching SENT contact|occasion): 797// th[0]=ct th[1]=occ th[2]=dt th[3]=nopen th[4]=sent 798func rl_collect_thanks(prefix: *u8) -> *i64 { 799 let th: *i64 = sys_mmap(8 * 8) as *i64 800 th[0] = sys_mmap(8 * 256); th[1] = sys_mmap(8 * 256); th[2] = sys_mmap(8 * 256); th[3] = 0; th[4] = 0 801 let h_ct: *i64 = th[0] as *i64 802 let h_occ: *i64 = th[1] as *i64 803 let h_dt: *i64 = th[2] as *i64 804 let t_ct: *i64 = sys_mmap(8 * 256) as *i64 805 let t_occ: *i64 = sys_mmap(8 * 256) as *i64 806 let t_dt: *i64 = sys_mmap(8 * 256) as *i64 807 var nt: i64 = 0 808 let sent: *i64 = sys_mmap(8 * 256) as *i64 809 var nsent: i64 = 0 810 811 let segs: *i64 = sys_mmap(8 * 260) as *i64 812 let ns: i64 = ss_manifest(prefix, segs) 813 let fk: *u8 = sys_mmap(64) 814 let fa: *u8 = sys_mmap(128) 815 let fb: *u8 = sys_mmap(128) 816 let fd: *u8 = sys_mmap(128) 817 var s: i64 = 0 818 while s < ns { 819 let path: *u8 = sys_mmap(512) 820 var po: i64 = 0 821 po = rl_cat(path, po, prefix); po = rl_cat(path, po, segs[s] as *u8); po = rl_cat(path, po, ".docs" as *u8) 822 path[po] = 0 as u8 823 let szp: *i64 = sys_mmap(16) as *i64 824 let b: *u8 = ss_readall(path, szp) 825 let sz: i64 = szp[0] 826 var j: i64 = 0 827 while j + 9 <= sz { 828 let kind: i64 = b[j] 829 let kl: i64 = ss_r32(b, j + 1) 830 let koff: i64 = j + 5 831 let vl: i64 = ss_r32(b, koff + kl) 832 let voff: i64 = koff + kl + 4 833 var take: i64 = 0 834 if kind == 1 { take = rl_isrel(b, koff, kl) } 835 if take == 1 { 836 let rec: *u8 = (b as i64 + voff) as *u8 837 if rl_field(rec, vl, "k" as *u8, fk, 64) == 1 { 838 if rl_eq(fk, "thanks" as *u8) == 1 { 839 rl_field(rec, vl, "a" as *u8, fa, 128) 840 rl_field(rec, vl, "b" as *u8, fb, 128) 841 rl_field(rec, vl, "date" as *u8, fd, 128) 842 if nt < 256 { t_ct[nt] = rl_dup(fa) as i64; t_occ[nt] = rl_dup(fb) as i64; t_dt[nt] = rl_dup(fd) as i64; nt = nt + 1 } 843 } 844 if rl_eq(fk, "sent" as *u8) == 1 { 845 rl_field(rec, vl, "a" as *u8, fa, 128) 846 rl_field(rec, vl, "b" as *u8, fb, 128) 847 let key: *u8 = sys_mmap(256) 848 var ko: i64 = 0 849 ko = rl_cat(key, ko, fa); key[ko] = 124 as u8; ko = ko + 1; ko = rl_cat(key, ko, fb); key[ko] = 0 as u8 850 if nsent < 256 { sent[nsent] = rl_dup(key) as i64; nsent = nsent + 1 } 851 } 852 } 853 } 854 j = voff + vl 855 } 856 s = s + 1 857 } 858 th[4] = nsent 859 var k: i64 = 0 860 while k < nt { 861 let key: *u8 = sys_mmap(256) 862 var ko: i64 = 0 863 ko = rl_cat(key, ko, t_ct[k] as *u8); key[ko] = 124 as u8; ko = ko + 1; ko = rl_cat(key, ko, t_occ[k] as *u8); key[ko] = 0 as u8 864 if rl_find(sent, nsent, key) < 0 { 865 let n: i64 = th[3] 866 h_ct[n] = t_ct[k]; h_occ[n] = t_occ[k]; h_dt[n] = t_dt[k] 867 th[3] = n + 1 868 } 869 k = k + 1 870 } 871 return th 872} 873 874// ---------------- THANKS (gratitude as a tracked debt) ---------------- 875func rl_cmd_thanks(argc: i64, argv: *i64) -> i64 { 876 if argc < 5 { rl_p("VIZSLA-RELATE thanks needs <prefix> <contacts> <today> -- fail loud\n" as *u8); return 1 } 877 let prefix: *u8 = argv[2] as *u8 878 let cf: *i64 = rl_load_contacts(argv[3] as *u8) 879 if (cf as i64) == 0 { rl_p("VIZSLA-RELATE contacts MISSING/MALFORMED -- fail loud\n" as *u8); return 1 } 880 let today: i64 = rl_datedays(argv[4] as *u8) 881 if today < 0 { rl_p("VIZSLA-RELATE bad today date (YYYY-MM-DD) -- fail loud\n" as *u8); return 1 } 882 let soon: i64 = cf[9] 883 884 let th: *i64 = rl_collect_thanks(prefix) 885 let h_ct: *i64 = th[0] as *i64 886 let h_occ: *i64 = th[1] as *i64 887 let h_dt: *i64 = th[2] as *i64 888 889 let rep: *u8 = sys_mmap(K_MAGIC_65536) 890 var o: i64 = 0 891 var npend: i64 = 0 892 var nover: i64 = 0 893 var i: i64 = 0 894 while i < th[3] { 895 let dd: i64 = rl_datedays(h_dt[i] as *u8) 896 let days: i64 = today - dd 897 o = rl_cat(rep, o, "VIZSLA-RELATE-THANKS contact=" as *u8) 898 o = rl_cat(rep, o, h_ct[i] as *u8) 899 o = rl_cat(rep, o, " occasion=" as *u8) 900 o = rl_cat(rep, o, h_occ[i] as *u8) 901 o = rl_cat(rep, o, " owed=" as *u8) 902 o = rl_cat(rep, o, h_dt[i] as *u8) 903 o = rl_cat(rep, o, " days=" as *u8) 904 o = rl_catn(rep, o, days) 905 if days > soon { 906 nover = nover + 1 907 o = rl_cat(rep, o, " state=OVERDUE\n" as *u8) 908 } else { 909 npend = npend + 1 910 o = rl_cat(rep, o, " state=PENDING\n" as *u8) 911 } 912 i = i + 1 913 } 914 o = rl_cat(rep, o, "VIZSLA-RELATE-THANKS-VERDICT open=" as *u8) 915 o = rl_catn(rep, o, th[3]) 916 o = rl_cat(rep, o, " pending=" as *u8) 917 o = rl_catn(rep, o, npend) 918 o = rl_cat(rep, o, " overdue=" as *u8) 919 o = rl_catn(rep, o, nover) 920 o = rl_cat(rep, o, " sent=" as *u8) 921 o = rl_catn(rep, o, th[4]) 922 o = rl_cat(rep, o, "\n" as *u8) 923 sys_write(1, rep, o) 924 let lp: *u8 = sys_mmap(512) 925 rl_prefixlog(prefix, lp) 926 rl_log(lp, "thanks" as *u8, rep, o) 927 return 0 928} 929 930// ---------------- BRIEF (the consigliere daily counsel) ---------------- 931func rl_cmd_brief(argc: i64, argv: *i64) -> i64 { 932 if argc < 5 { rl_p("VIZSLA-RELATE brief needs <prefix> <contacts> <today> -- fail loud\n" as *u8); return 1 } 933 let prefix: *u8 = argv[2] as *u8 934 let cf: *i64 = rl_load_contacts(argv[3] as *u8) 935 if (cf as i64) == 0 { rl_p("VIZSLA-RELATE contacts MISSING/MALFORMED -- fail loud\n" as *u8); return 1 } 936 let tstr: *u8 = argv[4] as *u8 937 let today: i64 = rl_datedays(tstr) 938 if today < 0 { rl_p("VIZSLA-RELATE bad today date (YYYY-MM-DD) -- fail loud\n" as *u8); return 1 } 939 let soon: i64 = cf[9] 940 941 let ct_id: *i64 = cf[0] as *i64 942 let ct_tier: *i64 = cf[2] as *i64 943 let ct_bday: *i64 = cf[3] as *i64 944 let tr_days: *i64 = cf[6] as *i64 945 let a_days: *i64 = sys_mmap(8 * 256) as *i64 946 let a_date: *i64 = sys_mmap(8 * 256) as *i64 947 rl_latest_touch(prefix, cf, a_days, a_date) 948 949 let rep: *u8 = sys_mmap(K_MAGIC_131072) 950 var o: i64 = 0 951 o = rl_cat(rep, o, "VIZSLA-RELATE-BRIEF date=" as *u8) 952 o = rl_cat(rep, o, tstr) 953 o = rl_cat(rep, o, "\n" as *u8) 954 955 // 1) follow-ups due (tier cadence exceeded) or NEW 956 var nfollow: i64 = 0 957 var i: i64 = 0 958 while i < cf[4] { 959 let cad: i64 = tr_days[ct_tier[i]] 960 var flag: i64 = 0 961 if a_days[i] < 0 { flag = 2 } else { if today - a_days[i] > cad { flag = 1 } } 962 if flag > 0 { 963 nfollow = nfollow + 1 964 o = rl_cat(rep, o, " FOLLOWUP contact=" as *u8) 965 o = rl_cat(rep, o, ct_id[i] as *u8) 966 if flag == 2 { 967 o = rl_cat(rep, o, " (NEW)\n" as *u8) 968 } else { 969 o = rl_cat(rep, o, " days=" as *u8) 970 o = rl_catn(rep, o, today - a_days[i]) 971 o = rl_cat(rep, o, " (DUE)\n" as *u8) 972 } 973 } 974 i = i + 1 975 } 976 977 // 2) upcoming birthdays within soon_days 978 var nbday: i64 = 0 979 var bi: i64 = 0 980 while bi < cf[4] { 981 let until: i64 = rl_bday_until(tstr, today, ct_bday[bi] as *u8) 982 if until >= 0 { 983 if until <= soon { 984 nbday = nbday + 1 985 o = rl_cat(rep, o, " BIRTHDAY contact=" as *u8) 986 o = rl_cat(rep, o, ct_id[bi] as *u8) 987 o = rl_cat(rep, o, " on=" as *u8) 988 o = rl_cat(rep, o, ct_bday[bi] as *u8) 989 o = rl_cat(rep, o, " in=" as *u8) 990 o = rl_catn(rep, o, until) 991 o = rl_cat(rep, o, "d\n" as *u8) 992 } 993 } 994 bi = bi + 1 995 } 996 997 // 3) open thank-yous 998 let th: *i64 = rl_collect_thanks(prefix) 999 let h_ct: *i64 = th[0] as *i64 1000 let h_occ: *i64 = th[1] as *i64 1001 let h_dt: *i64 = th[2] as *i64 1002 var ti: i64 = 0 1003 while ti < th[3] { 1004 let dd: i64 = rl_datedays(h_dt[ti] as *u8) 1005 o = rl_cat(rep, o, " THANKYOU contact=" as *u8) 1006 o = rl_cat(rep, o, h_ct[ti] as *u8) 1007 o = rl_cat(rep, o, " occasion=" as *u8) 1008 o = rl_cat(rep, o, h_occ[ti] as *u8) 1009 if today - dd > soon { o = rl_cat(rep, o, " (OVERDUE)\n" as *u8) } else { o = rl_cat(rep, o, " (PENDING)\n" as *u8) } 1010 ti = ti + 1 1011 } 1012 1013 // 4) open obligations 1014 let ob: *i64 = rl_collect_obligs(prefix) 1015 let o_ct: *i64 = ob[0] as *i64 1016 let o_dir: *i64 = ob[1] as *i64 1017 let o_ref: *i64 = ob[2] as *i64 1018 var oi: i64 = 0 1019 while oi < ob[5] { 1020 o = rl_cat(rep, o, " OBLIGATION contact=" as *u8) 1021 o = rl_cat(rep, o, o_ct[oi] as *u8) 1022 o = rl_cat(rep, o, " dir=" as *u8) 1023 o = rl_cat(rep, o, o_dir[oi] as *u8) 1024 o = rl_cat(rep, o, " ref=" as *u8) 1025 o = rl_cat(rep, o, o_ref[oi] as *u8) 1026 o = rl_cat(rep, o, "\n" as *u8) 1027 oi = oi + 1 1028 } 1029 1030 o = rl_cat(rep, o, "VIZSLA-RELATE-BRIEF-VERDICT followups=" as *u8) 1031 o = rl_catn(rep, o, nfollow) 1032 o = rl_cat(rep, o, " birthdays=" as *u8) 1033 o = rl_catn(rep, o, nbday) 1034 o = rl_cat(rep, o, " thankyous=" as *u8) 1035 o = rl_catn(rep, o, th[3]) 1036 o = rl_cat(rep, o, " obligations=" as *u8) 1037 o = rl_catn(rep, o, ob[5]) 1038 o = rl_cat(rep, o, "\n" as *u8) 1039 sys_write(1, rep, o) 1040 let lp: *u8 = sys_mmap(512) 1041 rl_prefixlog(prefix, lp) 1042 rl_log(lp, "brief" as *u8, rep, o) 1043 return 0 1044} 1045 1046func main(argc: i64, argv: *i64) -> i64 { 1047 if argc < 2 { rl_p("VIZSLA-RELATE usage: load|cadence|ledger|thanks|brief -- fail loud\n" as *u8); return 1 } 1048 let cmd: *u8 = argv[1] as *u8 1049 if rl_eq(cmd, "load" as *u8) == 1 { return rl_cmd_load(argc, argv) } 1050 if rl_eq(cmd, "cadence" as *u8) == 1 { return rl_cmd_cadence(argc, argv) } 1051 if rl_eq(cmd, "ledger" as *u8) == 1 { return rl_cmd_ledger(argc, argv) } 1052 if rl_eq(cmd, "thanks" as *u8) == 1 { return rl_cmd_thanks(argc, argv) } 1053 if rl_eq(cmd, "brief" as *u8) == 1 { return rl_cmd_brief(argc, argv) } 1054 rl_p("VIZSLA-RELATE unknown command (load|cadence|ledger|thanks|brief) -- fail loud\n" as *u8) 1055 return 1 1056}