code wiki / _hdl_build / nx_vizsla_jobs.nx
nx_vizsla_jobs.nx source
↩ module page · 665 lines · 24120 B
1// nx_vizsla_jobs.nx -- NISHI VIZSLA V2a: the job-search engine (career domain).
2// Fills career/AUTHOR (job-search-engine) + career/EDITOR (application-tracker)
3// from the V0 gap profile. V2a = match scoring + tracker + cadence against a
4// FIXTURE-ORACLE corpus; V2b (named follow-on, Market Researcher lane) = live
5// posting census via own-TLS entity-gather feeding the same postings format.
6//
7// Commands (argv[1]):
8// match <profile> <postings> [log] score every posting for every SEEK
9// member: score = sum of that member's
10// SKILL weights whose term appears in
11// the posting's term list. Rank rows
12// score-desc (file order breaks ties);
13// zero-score postings are PRINTED not
14// dropped (matched= counts score>0).
15// track <appfile> <prefix> [segid] APP rows -> canonical records -> CID
16// keys "app:nxc1-..." on seg_store =
17// IDEMPOTENT additive application
18// history (same law/substrate as V1).
19// cadence <prefix> <profile> walk the app history chronologically;
20// LAST status per posting wins; posting
21// whose last status is not in the
22// profile's CLOSED set gets a follow-up
23// row. Closed apps are suppressed from
24// cadence but stay in history (additive).
25//
26// File formats (line records, # comments; ALL model data in files, law 11/25):
27// profile: SEEK <member>
28// SKILL <member> <weight> <term>
29// CLOSED <status> (statuses that need no follow-up)
30// postings: POST <id> <pay_cents> <term> <term> ...
31// apps: APP <date> <post-id> <member> <status> <note>
32//
33// Determinism: stdout has no clocks; epoch headers go to logs only (match log
34// argv-overridable; track/cadence log derived from store prefix = fixture
35// isolation). Loud-fail law: missing files, SKILL for unknown member,
36// non-digit pay/weight = exit 1 named.
37// EXCEED (V2a): ranking is the FAMILY'S fit function -- data-edited skill
38// weights -- not an ad-funded board's pay-to-play order; cadence is the
39// editor-fill that closes application loops. Reach EXCEED lands with V2b.
40// spec: knowledge/specs/2026-06-10-nishi-vizsla-ladder.md license_tier: ORIGINAL
41import "nx_syscalls.nx"
42import "nx_canon_cid.nx"
43import "nx_seg_store.nx"
44const K_MAGIC_4096: i64 = 4096
45const K_MAGIC_131072: i64 = 131072
46const K_MAGIC_2048: i64 = 2048
47const K_MAGIC_65536: i64 = 65536
48
49func vj_slen(s: *u8) -> i64 {
50 var n: i64 = 0
51 while s[n] != (0 as u8) { n = n + 1 }
52 return n
53}
54
55func vj_p(s: *u8) -> i64 {
56 sys_write(1, s, vj_slen(s))
57 return 0
58}
59
60func vj_eq(a: *u8, b: *u8) -> i64 {
61 var i: i64 = 0
62 var go: i64 = 1
63 while go == 1 {
64 if a[i] != b[i] { return 0 }
65 if a[i] == (0 as u8) { return 1 }
66 i = i + 1
67 }
68 return 0
69}
70
71func vj_dup(s: *u8) -> *u8 {
72 let n: i64 = vj_slen(s)
73 let d: *u8 = sys_mmap(n + 2)
74 var i: i64 = 0
75 while i <= n { d[i] = s[i]; i = i + 1 }
76 return d
77}
78
79func vj_atoi(s: *u8) -> i64 {
80 var v: i64 = 0
81 var i: i64 = 0
82 while s[i] != (0 as u8) {
83 let d: i64 = (s[i] as i64) - 48
84 if d >= 0 { if d <= 9 { v = v * 10 + d } }
85 i = i + 1
86 }
87 return v
88}
89
90func vj_digits(s: *u8) -> i64 {
91 if s[0] == (0 as u8) { return 0 }
92 var i: i64 = 0
93 while s[i] != (0 as u8) {
94 let d: i64 = (s[i] as i64) - 48
95 if d < 0 { return 0 }
96 if d > 9 { return 0 }
97 i = i + 1
98 }
99 return 1
100}
101
102func vj_isws(c: i64) -> i64 {
103 if c == 32 { return 1 }
104 if c == 13 { return 1 }
105 if c == 9 { return 1 }
106 return 0
107}
108
109func vj_tok(b: *u8, off: i64, lend: i64, dst: *u8, cap: i64) -> i64 {
110 var p: i64 = off
111 var go: i64 = 1
112 while go == 1 {
113 if p >= lend { go = 0 } else {
114 if vj_isws(b[p] as i64) == 1 { p = p + 1 } else { go = 0 }
115 }
116 }
117 var t: i64 = 0
118 go = 1
119 while go == 1 {
120 if p >= lend { go = 0 } else {
121 if vj_isws(b[p] as i64) == 1 { go = 0 } else {
122 if t < cap - 1 { dst[t] = b[p]; t = t + 1 }
123 p = p + 1
124 }
125 }
126 }
127 dst[t] = 0 as u8
128 return p
129}
130
131func vj_cat(dst: *u8, off: i64, s: *u8) -> i64 {
132 var i: i64 = 0
133 while s[i] != (0 as u8) { dst[off + i] = s[i]; i = i + 1 }
134 return off + i
135}
136
137func vj_catn(dst: *u8, off: i64, v: i64) -> i64 {
138 var o: i64 = off
139 var m: i64 = v
140 if m < 0 { dst[o] = 45 as u8; o = o + 1; m = 0 - m }
141 let t: *u8 = sys_mmap(28)
142 var k: i64 = 0
143 if m == 0 { t[0] = 48 as u8; k = 1 }
144 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
145 var i: i64 = 0
146 while i < k { dst[o + i] = t[k - 1 - i]; i = i + 1 }
147 return o + k
148}
149
150func vj_find(list: *i64, n: i64, s: *u8) -> i64 {
151 var i: i64 = 0
152 while i < n {
153 if vj_eq(list[i] as *u8, s) == 1 { return i }
154 i = i + 1
155 }
156 return 0 - 1
157}
158
159func vj_kmemeq(b: *u8, off: i64, n: i64, s: *u8) -> i64 {
160 if vj_slen(s) != n { return 0 }
161 var i: i64 = 0
162 while i < n {
163 if b[off + i] != s[i] { return 0 }
164 i = i + 1
165 }
166 return 1
167}
168
169func vj_field(rec: *u8, rl: i64, want: *u8, out: *u8, cap: i64) -> i64 {
170 if rl < 8 { return 0 }
171 let nf: i64 = ss_r32(rec, 4)
172 var off: i64 = 8
173 var fi: i64 = 0
174 while fi < nf {
175 if off + 8 > rl { return 0 }
176 let kl: i64 = ss_r32(rec, off)
177 let koff: i64 = off + 4
178 let vl: i64 = ss_r32(rec, koff + kl)
179 let voff: i64 = koff + kl + 4
180 if vj_kmemeq(rec, koff, kl, want) == 1 {
181 var t: i64 = 0
182 while t < vl {
183 if t < cap - 1 { out[t] = rec[voff + t] }
184 t = t + 1
185 }
186 if t > cap - 1 { t = cap - 1 }
187 out[t] = 0 as u8
188 return 1
189 }
190 off = voff + vl
191 fi = fi + 1
192 }
193 return 0
194}
195
196func vj_isapp(b: *u8, koff: i64, kl: i64) -> i64 {
197 if kl <= 4 { return 0 }
198 return vj_kmemeq(b, koff, 4, "app:" as *u8)
199}
200
201func vj_log(lpath: *u8, tag: *u8, rep: *u8, o: i64) -> i64 {
202 let fd: i64 = sys_openat_append(lpath, 0x1a4)
203 if fd <= 0 { return 0 }
204 let hdr: *u8 = sys_mmap(256)
205 var ho: i64 = 0
206 ho = vj_cat(hdr, ho, "VIZSLA-JOBS epoch=" as *u8)
207 ho = vj_catn(hdr, ho, sys_now_realtime_sec())
208 ho = vj_cat(hdr, ho, " cmd=" as *u8)
209 ho = vj_cat(hdr, ho, tag)
210 ho = vj_cat(hdr, ho, "\n" as *u8)
211 sys_write(fd, hdr, ho)
212 sys_write(fd, rep, o)
213 sys_close(fd)
214 return 0
215}
216
217func vj_prefixlog(prefix: *u8, out: *u8) -> i64 {
218 var o: i64 = 0
219 o = vj_cat(out, o, prefix)
220 o = vj_cat(out, o, "jobs.log" as *u8)
221 out[o] = 0 as u8
222 return o
223}
224
225// score one member's skills against a posting's term slice
226// sk: [0]=sk_mem [1]=sk_w [2]=sk_term [3]=nskill ; terms = ptr-list slice
227func vj_score(sk: *i64, mi: i64, terms: *i64, nterm: i64) -> i64 {
228 let sk_mem: *i64 = sk[0] as *i64
229 let sk_w: *i64 = sk[1] as *i64
230 let sk_term: *i64 = sk[2] as *i64
231 var sum: i64 = 0
232 var si: i64 = 0
233 while si < sk[3] {
234 if sk_mem[si] == mi {
235 if vj_find(terms, nterm, sk_term[si] as *u8) >= 0 { sum = sum + sk_w[si] }
236 }
237 si = si + 1
238 }
239 return sum
240}
241
242// ---------------- MATCH ----------------
243func vj_cmd_match(argc: i64, argv: *i64) -> i64 {
244 if argc < 4 { vj_p("VIZSLA-JOBS match needs <profile> <postings> -- fail loud\n" as *u8); return 1 }
245 let ppath: *u8 = argv[2] as *u8
246 let opath: *u8 = argv[3] as *u8
247 var lpath: *u8 = "knowledge/status/vizsla_jobs.log" as *u8
248 if argc > 4 { lpath = argv[4] as *u8 }
249
250 let szp: *i64 = sys_mmap(16) as *i64
251 let pb: *u8 = ss_readall(ppath, szp)
252 let psz: i64 = szp[0]
253 if psz <= 0 { vj_p("VIZSLA-JOBS profile MISSING/EMPTY -- fail loud\n" as *u8); return 1 }
254 let ob: *u8 = ss_readall(opath, szp)
255 let osz: i64 = szp[0]
256 if osz <= 0 { vj_p("VIZSLA-JOBS postings MISSING/EMPTY -- fail loud\n" as *u8); return 1 }
257
258 // profile tables (capacities = buffer sizes, model shape = file content)
259 let seeks: *i64 = sys_mmap(8 * 16) as *i64
260 var nseek: i64 = 0
261 let sk: *i64 = sys_mmap(8 * 8) as *i64
262 sk[0] = sys_mmap(8 * 128)
263 sk[1] = sys_mmap(8 * 128)
264 sk[2] = sys_mmap(8 * 128)
265 sk[3] = 0
266 let sk_mem: *i64 = sk[0] as *i64
267 let sk_w: *i64 = sk[1] as *i64
268 let sk_term: *i64 = sk[2] as *i64
269
270 let t0: *u8 = sys_mmap(128)
271 let t1: *u8 = sys_mmap(128)
272 let t2: *u8 = sys_mmap(128)
273 let t3: *u8 = sys_mmap(128)
274
275 var i: i64 = 0
276 while i < psz {
277 var e: i64 = i
278 var go: i64 = 1
279 while go == 1 {
280 if e >= psz { go = 0 } else {
281 if pb[e] == (10 as u8) { go = 0 } else { e = e + 1 }
282 }
283 }
284 var p: i64 = vj_tok(pb, i, e, t0, 128)
285 if t0[0] == (35 as u8) { t0[0] = 0 as u8 }
286 if vj_eq(t0, "SEEK" as *u8) == 1 {
287 p = vj_tok(pb, p, e, t1, 128)
288 if nseek < 16 { seeks[nseek] = vj_dup(t1) as i64; nseek = nseek + 1 }
289 }
290 if vj_eq(t0, "SKILL" as *u8) == 1 {
291 p = vj_tok(pb, p, e, t1, 128)
292 p = vj_tok(pb, p, e, t2, 128)
293 p = vj_tok(pb, p, e, t3, 128)
294 let mi: i64 = vj_find(seeks, nseek, t1)
295 if mi < 0 { vj_p("VIZSLA-JOBS SKILL references unknown member -- fail loud\n" as *u8); return 1 }
296 if vj_digits(t2) == 0 { vj_p("VIZSLA-JOBS SKILL weight not pure digits -- fail loud\n" as *u8); return 1 }
297 if sk[3] < 128 {
298 sk_mem[sk[3]] = mi
299 sk_w[sk[3]] = vj_atoi(t2)
300 sk_term[sk[3]] = vj_dup(t3) as i64
301 sk[3] = sk[3] + 1
302 }
303 }
304 i = e + 1
305 }
306 if nseek < 1 { vj_p("VIZSLA-JOBS no SEEK members in profile -- fail loud\n" as *u8); return 1 }
307 if sk[3] < 1 { vj_p("VIZSLA-JOBS no SKILL rows in profile -- fail loud\n" as *u8); return 1 }
308
309 // postings: ids, pay, flat term ptr-list with per-post start/count
310 let po_id: *i64 = sys_mmap(8 * 256) as *i64
311 let po_pay: *i64 = sys_mmap(8 * 256) as *i64
312 let po_ts: *i64 = sys_mmap(8 * 256) as *i64
313 let po_tn: *i64 = sys_mmap(8 * 256) as *i64
314 var npost: i64 = 0
315 let terms: *i64 = sys_mmap(8 * K_MAGIC_4096) as *i64
316 var nterm: i64 = 0
317
318 i = 0
319 while i < osz {
320 var e2: i64 = i
321 var go2: i64 = 1
322 while go2 == 1 {
323 if e2 >= osz { go2 = 0 } else {
324 if ob[e2] == (10 as u8) { go2 = 0 } else { e2 = e2 + 1 }
325 }
326 }
327 var p2: i64 = vj_tok(ob, i, e2, t0, 128)
328 if t0[0] == (35 as u8) { t0[0] = 0 as u8 }
329 if vj_eq(t0, "POST" as *u8) == 1 {
330 p2 = vj_tok(ob, p2, e2, t1, 128)
331 p2 = vj_tok(ob, p2, e2, t2, 128)
332 if t1[0] == (0 as u8) { vj_p("VIZSLA-JOBS POST missing id -- fail loud\n" as *u8); return 1 }
333 if vj_digits(t2) == 0 { vj_p("VIZSLA-JOBS POST pay not pure digits -- fail loud\n" as *u8); return 1 }
334 if npost < 256 {
335 po_id[npost] = vj_dup(t1) as i64
336 po_pay[npost] = vj_atoi(t2)
337 po_ts[npost] = nterm
338 var tn: i64 = 0
339 var more: i64 = 1
340 while more == 1 {
341 p2 = vj_tok(ob, p2, e2, t3, 128)
342 if t3[0] == (0 as u8) { more = 0 } else {
343 if nterm < K_MAGIC_4096 { terms[nterm] = vj_dup(t3) as i64; nterm = nterm + 1; tn = tn + 1 }
344 }
345 }
346 po_tn[npost] = tn
347 npost = npost + 1
348 }
349 }
350 i = e2 + 1
351 }
352 if npost < 1 { vj_p("VIZSLA-JOBS no POST rows -- fail loud\n" as *u8); return 1 }
353
354 // rank per member: selection over score desc, file order breaks ties
355 let rep: *u8 = sys_mmap(K_MAGIC_131072)
356 var o: i64 = 0
357 let score: *i64 = sys_mmap(8 * 256) as *i64
358 let used: *i64 = sys_mmap(8 * 256) as *i64
359 var mi2: i64 = 0
360 while mi2 < nseek {
361 var pi: i64 = 0
362 var matched: i64 = 0
363 while pi < npost {
364 let slice: *i64 = ((terms as i64) + po_ts[pi] * 8) as *i64
365 score[pi] = vj_score(sk, mi2, slice, po_tn[pi])
366 if score[pi] > 0 { matched = matched + 1 }
367 used[pi] = 0
368 pi = pi + 1
369 }
370 var rank: i64 = 1
371 while rank <= npost {
372 var best: i64 = 0 - 1
373 var bs: i64 = 0 - 1
374 pi = 0
375 while pi < npost {
376 var take: i64 = 0
377 if used[pi] == 0 { if score[pi] > bs { take = 1 } }
378 if take == 1 { bs = score[pi]; best = pi }
379 pi = pi + 1
380 }
381 used[best] = 1
382 o = vj_cat(rep, o, "VIZSLA-JOBS-MATCH member=" as *u8)
383 o = vj_cat(rep, o, seeks[mi2] as *u8)
384 o = vj_cat(rep, o, " rank=" as *u8)
385 o = vj_catn(rep, o, rank)
386 o = vj_cat(rep, o, " post=" as *u8)
387 o = vj_cat(rep, o, po_id[best] as *u8)
388 o = vj_cat(rep, o, " score=" as *u8)
389 o = vj_catn(rep, o, score[best])
390 o = vj_cat(rep, o, " pay=" as *u8)
391 o = vj_catn(rep, o, po_pay[best])
392 o = vj_cat(rep, o, "\n" as *u8)
393 rank = rank + 1
394 }
395 o = vj_cat(rep, o, "VIZSLA-JOBS-VERDICT member=" as *u8)
396 o = vj_cat(rep, o, seeks[mi2] as *u8)
397 o = vj_cat(rep, o, " postings=" as *u8)
398 o = vj_catn(rep, o, npost)
399 o = vj_cat(rep, o, " matched=" as *u8)
400 o = vj_catn(rep, o, matched)
401 o = vj_cat(rep, o, "\n" as *u8)
402 mi2 = mi2 + 1
403 }
404 sys_write(1, rep, o)
405 vj_log(lpath, "match" as *u8, rep, o)
406 return 0
407}
408
409// ---------------- TRACK (additive application history) ----------------
410func vj_cmd_track(argc: i64, argv: *i64) -> i64 {
411 if argc < 4 { vj_p("VIZSLA-JOBS track needs <appfile> <prefix> -- fail loud\n" as *u8); return 1 }
412 let apath: *u8 = argv[2] as *u8
413 let prefix: *u8 = argv[3] as *u8
414 var segid: i64 = 0
415 if argc > 4 { segid = vj_atoi(argv[4] as *u8) }
416 if segid == 0 { segid = sys_now_us() }
417
418 let szp: *i64 = sys_mmap(16) as *i64
419 let b: *u8 = ss_readall(apath, szp)
420 let sz: i64 = szp[0]
421 if sz <= 0 { vj_p("VIZSLA-JOBS appfile MISSING/EMPTY -- fail loud\n" as *u8); return 1 }
422
423 let keys: *i64 = sys_mmap(8 * 8) as *i64
424 let vals: *i64 = sys_mmap(8 * 8) as *i64
425 keys[0] = "kind" as *u8 as i64
426 keys[1] = "date" as *u8 as i64
427 keys[2] = "post" as *u8 as i64
428 keys[3] = "member" as *u8 as i64
429 keys[4] = "status" as *u8 as i64
430 keys[5] = "note" as *u8 as i64
431 vals[0] = "app" as *u8 as i64
432
433 let t0: *u8 = sys_mmap(128)
434 let dt: *u8 = sys_mmap(128)
435 let po: *u8 = sys_mmap(128)
436 let me: *u8 = sys_mmap(128)
437 let stt: *u8 = sys_mmap(128)
438 let nt: *u8 = sys_mmap(256)
439 let pp: *i64 = sys_mmap(16) as *i64
440 let ll: *i64 = sys_mmap(16) as *i64
441
442 let w: *i64 = ss_begin()
443 let seen: *i64 = sys_mmap(8 * K_MAGIC_2048) as *i64
444 var nseen: i64 = 0
445 var scanned: i64 = 0
446 var added: i64 = 0
447 var dup_infile: i64 = 0
448 var dup_instore: i64 = 0
449
450 var i: i64 = 0
451 while i < sz {
452 var e: i64 = i
453 var go: i64 = 1
454 while go == 1 {
455 if e >= sz { go = 0 } else {
456 if b[e] == (10 as u8) { go = 0 } else { e = e + 1 }
457 }
458 }
459 var p: i64 = vj_tok(b, i, e, t0, 128)
460 if t0[0] == (35 as u8) { t0[0] = 0 as u8 }
461 if vj_eq(t0, "APP" as *u8) == 1 {
462 scanned = scanned + 1
463 p = vj_tok(b, p, e, dt, 128)
464 p = vj_tok(b, p, e, po, 128)
465 p = vj_tok(b, p, e, me, 128)
466 p = vj_tok(b, p, e, stt, 128)
467 p = vj_tok(b, p, e, nt, 256)
468 if dt[0] == (0 as u8) { vj_p("VIZSLA-JOBS APP missing date -- fail loud\n" as *u8); return 1 }
469 if po[0] == (0 as u8) { vj_p("VIZSLA-JOBS APP missing post-id -- fail loud\n" as *u8); return 1 }
470 if me[0] == (0 as u8) { vj_p("VIZSLA-JOBS APP missing member -- fail loud\n" as *u8); return 1 }
471 if stt[0] == (0 as u8) { vj_p("VIZSLA-JOBS APP missing status -- fail loud\n" as *u8); return 1 }
472 if nt[0] == (0 as u8) { vj_p("VIZSLA-JOBS APP missing note -- fail loud\n" as *u8); return 1 }
473 vals[1] = dt as i64
474 vals[2] = po as i64
475 vals[3] = me as i64
476 vals[4] = stt as i64
477 vals[5] = nt as i64
478 let enc: *u8 = sys_mmap(K_MAGIC_2048)
479 let el: i64 = canon_encode(keys, vals, 6, enc)
480 let cid: *u8 = sys_mmap(96)
481 cid_of(enc, el, cid)
482 let kbuf: *u8 = sys_mmap(128)
483 var ko: i64 = 0
484 ko = vj_cat(kbuf, ko, "app:" as *u8)
485 ko = vj_cat(kbuf, ko, cid)
486 kbuf[ko] = 0 as u8
487 var fresh: i64 = 1
488 if vj_find(seen, nseen, kbuf) >= 0 { fresh = 0; dup_infile = dup_infile + 1 }
489 if fresh == 1 {
490 if nseen < K_MAGIC_2048 { seen[nseen] = vj_dup(kbuf) as i64; nseen = nseen + 1 }
491 }
492 if fresh == 1 {
493 if ss_get_idx(prefix, kbuf, pp, ll) == 1 { fresh = 0; dup_instore = dup_instore + 1 }
494 }
495 if fresh == 1 {
496 if ss_add(w, 1, kbuf, enc, el) != 0 { vj_p("VIZSLA-JOBS writer full -- fail loud\n" as *u8); return 1 }
497 added = added + 1
498 }
499 }
500 i = e + 1
501 }
502
503 var committed: i64 = 0
504 if added > 0 {
505 if ss_commit(prefix, w, segid) != 0 { vj_p("VIZSLA-JOBS commit FAILED -- fail loud\n" as *u8); return 1 }
506 committed = 1
507 }
508
509 let rep: *u8 = sys_mmap(K_MAGIC_4096)
510 var o: i64 = 0
511 o = vj_cat(rep, o, "VIZSLA-JOBS-TRACK scanned=" as *u8)
512 o = vj_catn(rep, o, scanned)
513 o = vj_cat(rep, o, " new=" as *u8)
514 o = vj_catn(rep, o, added)
515 o = vj_cat(rep, o, " dup_infile=" as *u8)
516 o = vj_catn(rep, o, dup_infile)
517 o = vj_cat(rep, o, " dup_instore=" as *u8)
518 o = vj_catn(rep, o, dup_instore)
519 o = vj_cat(rep, o, " segment=" as *u8)
520 if committed == 1 {
521 o = vj_cat(rep, o, "seg-" as *u8)
522 o = vj_catn(rep, o, segid)
523 } else {
524 o = vj_cat(rep, o, "none" as *u8)
525 }
526 o = vj_cat(rep, o, "\n" as *u8)
527 sys_write(1, rep, o)
528 let lp: *u8 = sys_mmap(512)
529 vj_prefixlog(prefix, lp)
530 vj_log(lp, "track" as *u8, rep, o)
531 return 0
532}
533
534// ---------------- CADENCE (last status wins; CLOSED set from data) ----------------
535func vj_cmd_cadence(argc: i64, argv: *i64) -> i64 {
536 if argc < 4 { vj_p("VIZSLA-JOBS cadence needs <prefix> <profile> -- fail loud\n" as *u8); return 1 }
537 let prefix: *u8 = argv[2] as *u8
538 let ppath: *u8 = argv[3] as *u8
539
540 let szp: *i64 = sys_mmap(16) as *i64
541 let pb: *u8 = ss_readall(ppath, szp)
542 let psz: i64 = szp[0]
543 if psz <= 0 { vj_p("VIZSLA-JOBS profile MISSING/EMPTY -- fail loud\n" as *u8); return 1 }
544
545 // CLOSED statuses from the profile (data-driven, never code)
546 let closed: *i64 = sys_mmap(8 * 16) as *i64
547 var nclosed: i64 = 0
548 let t0: *u8 = sys_mmap(128)
549 let t1: *u8 = sys_mmap(128)
550 var i: i64 = 0
551 while i < psz {
552 var e: i64 = i
553 var go: i64 = 1
554 while go == 1 {
555 if e >= psz { go = 0 } else {
556 if pb[e] == (10 as u8) { go = 0 } else { e = e + 1 }
557 }
558 }
559 var p: i64 = vj_tok(pb, i, e, t0, 128)
560 if t0[0] == (35 as u8) { t0[0] = 0 as u8 }
561 if vj_eq(t0, "CLOSED" as *u8) == 1 {
562 p = vj_tok(pb, p, e, t1, 128)
563 if nclosed < 16 { closed[nclosed] = vj_dup(t1) as i64; nclosed = nclosed + 1 }
564 }
565 i = e + 1
566 }
567 if nclosed < 1 { vj_p("VIZSLA-JOBS profile has no CLOSED rows -- fail loud\n" as *u8); return 1 }
568
569 // chronological walk: last status per post wins (first-seen post order)
570 let segs: *i64 = sys_mmap(8 * 260) as *i64
571 let ns: i64 = ss_manifest(prefix, segs)
572 if ns == 0 { vj_p("VIZSLA-JOBS cadence: no manifest/segments -- fail loud\n" as *u8); return 1 }
573 let posts: *i64 = sys_mmap(8 * 256) as *i64
574 let lastst: *i64 = sys_mmap(8 * 256) as *i64
575 let lastme: *i64 = sys_mmap(8 * 256) as *i64
576 var nposts: i64 = 0
577 var apps: i64 = 0
578 let fpo: *u8 = sys_mmap(128)
579 let fme: *u8 = sys_mmap(128)
580 let fst: *u8 = sys_mmap(128)
581 var s: i64 = 0
582 while s < ns {
583 let path: *u8 = sys_mmap(512)
584 var po2: i64 = 0
585 po2 = vj_cat(path, po2, prefix)
586 po2 = vj_cat(path, po2, segs[s] as *u8)
587 po2 = vj_cat(path, po2, ".docs" as *u8)
588 path[po2] = 0 as u8
589 let szp2: *i64 = sys_mmap(16) as *i64
590 let b: *u8 = ss_readall(path, szp2)
591 let sz: i64 = szp2[0]
592 var j: i64 = 0
593 while j + 9 <= sz {
594 let kind: i64 = b[j]
595 let kl: i64 = ss_r32(b, j + 1)
596 let koff: i64 = j + 5
597 let vl: i64 = ss_r32(b, koff + kl)
598 let voff: i64 = koff + kl + 4
599 var take: i64 = 0
600 if kind == 1 { take = vj_isapp(b, koff, kl) }
601 if take == 1 {
602 let rec: *u8 = (b as i64 + voff) as *u8
603 var okf: i64 = vj_field(rec, vl, "post" as *u8, fpo, 128)
604 okf = okf + vj_field(rec, vl, "member" as *u8, fme, 128)
605 okf = okf + vj_field(rec, vl, "status" as *u8, fst, 128)
606 if okf == 3 {
607 apps = apps + 1
608 var ci: i64 = vj_find(posts, nposts, fpo)
609 if ci < 0 {
610 if nposts < 256 { posts[nposts] = vj_dup(fpo) as i64; ci = nposts; nposts = nposts + 1 }
611 }
612 if ci >= 0 { lastst[ci] = vj_dup(fst) as i64; lastme[ci] = vj_dup(fme) as i64 }
613 }
614 }
615 j = voff + vl
616 }
617 s = s + 1
618 }
619
620 let rep: *u8 = sys_mmap(K_MAGIC_65536)
621 var o: i64 = 0
622 var nopen: i64 = 0
623 var ncl: i64 = 0
624 var pi: i64 = 0
625 while pi < nposts {
626 var iscl: i64 = 0
627 if vj_find(closed, nclosed, lastst[pi] as *u8) >= 0 { iscl = 1 }
628 if iscl == 1 { ncl = ncl + 1 }
629 if iscl == 0 {
630 nopen = nopen + 1
631 o = vj_cat(rep, o, "VIZSLA-JOBS-CADENCE post=" as *u8)
632 o = vj_cat(rep, o, posts[pi] as *u8)
633 o = vj_cat(rep, o, " member=" as *u8)
634 o = vj_cat(rep, o, lastme[pi] as *u8)
635 o = vj_cat(rep, o, " last=" as *u8)
636 o = vj_cat(rep, o, lastst[pi] as *u8)
637 o = vj_cat(rep, o, " action=follow-up\n" as *u8)
638 }
639 pi = pi + 1
640 }
641 o = vj_cat(rep, o, "VIZSLA-JOBS-CADENCE-VERDICT apps=" as *u8)
642 o = vj_catn(rep, o, apps)
643 o = vj_cat(rep, o, " posts=" as *u8)
644 o = vj_catn(rep, o, nposts)
645 o = vj_cat(rep, o, " open=" as *u8)
646 o = vj_catn(rep, o, nopen)
647 o = vj_cat(rep, o, " closed=" as *u8)
648 o = vj_catn(rep, o, ncl)
649 o = vj_cat(rep, o, "\n" as *u8)
650 sys_write(1, rep, o)
651 let lp: *u8 = sys_mmap(512)
652 vj_prefixlog(prefix, lp)
653 vj_log(lp, "cadence" as *u8, rep, o)
654 return 0
655}
656
657func main(argc: i64, argv: *i64) -> i64 {
658 if argc < 2 { vj_p("VIZSLA-JOBS usage: match|track|cadence -- fail loud\n" as *u8); return 1 }
659 let cmd: *u8 = argv[1] as *u8
660 if vj_eq(cmd, "match" as *u8) == 1 { return vj_cmd_match(argc, argv) }
661 if vj_eq(cmd, "track" as *u8) == 1 { return vj_cmd_track(argc, argv) }
662 if vj_eq(cmd, "cadence" as *u8) == 1 { return vj_cmd_cadence(argc, argv) }
663 vj_p("VIZSLA-JOBS unknown command (match|track|cadence) -- fail loud\n" as *u8)
664 return 1
665}