nx_medbill_cli.nx source
↩ module page · 627 lines · 26705 B
1// nx_medbill_cli.nx -- M1 front door: drive the medical-billing code-pack store from the command line
2// (features-must-be-frontend-testable). Two verbs over the DURABLE store knowledge/store/medbill-:
3// nx_medbill_cli ingest -- load knowledge/medbill/codes_seed.list (data): 3-field rows
4// ingest official NLM responses, 4-field rows store curated
5// entries with visible provenance. Idempotent (latest-wins).
6// nx_medbill_cli lookup <code> -- decode one code: CODE (SYSTEM): descriptor [source: cite]
7// unknown code prints UNKNOWN and exits 1 (never fabricates).
8// license_tier: ORIGINAL
9import "nx_syscalls.nx"
10import "nx_itoa_lib.nx" // shared MSB-first emitter (zero-alloc)
11import "nx_medbill_codes.nx"
12import "nx_medbill_recon.nx"
13import "nx_fin_audit.nx"
14import "nx_fin_dispute.nx"
15import "nx_medbill_charity.nx"
16import "nx_medbill_appeal.nx"
17import "nx_medbill_nsa.nx"
18import "nx_medbill_civic.nx"
19import "nx_healthhelp_site.nx"
20const K_MAGIC_262144: i64 = 262144
21const K_MAGIC_1024: i64 = 1024
22const K_MAGIC_4096: i64 = 4096
23const K_MAGIC_10000: i64 = 10000
24const K_MAGIC_2048: i64 = 2048
25const K_MAGIC_16384: i64 = 16384
26const K_MAGIC_19000101: i64 = 19000101
27const K_MAGIC_40000: i64 = 40000
28const K_MAGIC_65536: i64 = 65536
29
30func c_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
31// MIGRATED to the shared emitter (debt 1785563586). The old body mmapped a scratch buffer
32// per call and never freed it. At PAGE granularity that is 4096B leaked PER CALL -- the
33// defect that took 28.5GB of a 36GB host in nx_ts_lumadiff (2MB input, ~3.66M calls).
34// nxi_* is MSB-first, allocates NOTHING, and emits identical bytes including the sign.
35func c_putn(v: i64) -> i64 { nxi_out(v); return 0 }
36
37// copy line[a..b) field split on '|': fill up to 4 field buffers, return field count
38func cli_split(line: *u8, ln: i64, f0: *u8, f1: *u8, f2: *u8, f3: *u8) -> i64 {
39 var fi: i64 = 0
40 var o: i64 = 0
41 var i: i64 = 0
42 while i < ln {
43 if line[i] == (0x7c as u8) {
44 if fi == 0 { f0[o] = 0 as u8 }
45 if fi == 1 { f1[o] = 0 as u8 }
46 if fi == 2 { f2[o] = 0 as u8 }
47 if fi == 3 { f3[o] = 0 as u8 }
48 fi = fi + 1
49 o = 0
50 } else {
51 if fi == 0 { f0[o] = line[i]; o = o + 1 }
52 if fi == 1 { f1[o] = line[i]; o = o + 1 }
53 if fi == 2 { f2[o] = line[i]; o = o + 1 }
54 if fi == 3 { f3[o] = line[i]; o = o + 1 }
55 }
56 i = i + 1
57 }
58 if fi == 0 { f0[o] = 0 as u8 }
59 if fi == 1 { f1[o] = 0 as u8 }
60 if fi == 2 { f2[o] = 0 as u8 }
61 if fi == 3 { f3[o] = 0 as u8 }
62 return fi + 1
63}
64
65func cli_ingest(prefix: *u8) -> i64 {
66 let cap: i64 = K_MAGIC_262144
67 let buf: *u8 = sys_mmap(cap)
68 let n: i64 = mbc_read_all("knowledge/medbill/codes_seed.list\x00" as *u8, buf, cap)
69 if n <= 0 { c_puts("SEED-LIST READ-FAIL knowledge/medbill/codes_seed.list\n" as *u8); return 1 }
70 let f0: *u8 = sys_mmap(K_MAGIC_1024)
71 let f1: *u8 = sys_mmap(K_MAGIC_1024)
72 let f2: *u8 = sys_mmap(K_MAGIC_1024)
73 let f3: *u8 = sys_mmap(K_MAGIC_1024)
74 let line: *u8 = sys_mmap(K_MAGIC_4096)
75 var ok: i64 = 0
76 var miss: i64 = 0
77 var i: i64 = 0
78 while i < n {
79 var e: i64 = i
80 var stop: i64 = 0
81 while stop == 0 {
82 if e >= n { stop = 1 } else {
83 if buf[e] == (0x0a as u8) { stop = 1 } else { e = e + 1 }
84 }
85 }
86 let ln: i64 = e - i
87 if ln > 2 {
88 if buf[i] != (35 as u8) {
89 var j: i64 = 0
90 while j < ln { line[j] = buf[i + j]; j = j + 1 }
91 line[ln] = 0 as u8
92 let nf: i64 = cli_split(line, ln, f0, f1, f2, f3)
93 if nf == 3 {
94 let r: i64 = mbc_ingest_nlm(prefix, f2, f0, f1)
95 if r == 1 { ok = ok + 1; c_puts(" ingested " as *u8); c_puts(f0); c_puts(" (" as *u8); c_puts(f1); c_puts(") official NLM\n" as *u8) }
96 else { miss = miss + 1; c_puts(" MISS " as *u8); c_puts(f0); c_puts(" rc=" as *u8); c_putn(r); c_puts("\n" as *u8) }
97 }
98 if nf == 4 {
99 let r2: i64 = mbc_put(prefix, f0, f1, f2, f3)
100 if r2 == 0 { ok = ok + 1; c_puts(" stored " as *u8); c_puts(f0); c_puts(" (" as *u8); c_puts(f1); c_puts(") curated\n" as *u8) }
101 else { miss = miss + 1; c_puts(" STORE-FAIL " as *u8); c_puts(f0); c_puts("\n" as *u8) }
102 }
103 }
104 }
105 i = e + 1
106 }
107 c_puts("nx_medbill ingest: ok=" as *u8)
108 c_putn(ok)
109 c_puts(" miss=" as *u8)
110 c_putn(miss)
111 c_puts("\n" as *u8)
112 if miss == 0 { return 0 }
113 return 1
114}
115
116// cents -> $D.CC
117func c_money(v: i64) -> i64 {
118 c_puts("$" as *u8)
119 c_putn(v / 100)
120 c_puts("." as *u8)
121 let cc: i64 = v % 100
122 if cc < 10 { c_puts("0" as *u8) }
123 c_putn(cc)
124 return 0
125}
126// yyyymmdd -> MM/DD/YYYY
127func c_date(d: i64) -> i64 {
128 let mo: i64 = (d / 100) % 100
129 let dy: i64 = d % 100
130 if mo < 10 { c_puts("0" as *u8) }
131 c_putn(mo)
132 c_puts("/" as *u8)
133 if dy < 10 { c_puts("0" as *u8) }
134 c_putn(dy)
135 c_puts("/" as *u8)
136 c_putn(d / K_MAGIC_10000)
137 return 0
138}
139// numeric code string -> i64, or -1 if not all digits
140func c_codenum(s: *u8) -> i64 {
141 var v: i64 = 0
142 var i: i64 = 0
143 while s[i] != (0 as u8) { if mbr_is_digit(s[i]) == 0 { return 0 - 1 } v = v * 10 + ((s[i] as i64) - 48); i = i + 1 }
144 return v
145}
146
147// print one parsed claim line + its M1 decode from the durable pack
148func cli_rline(prefix: *u8, ctx: *i64, i: i64, rec: *u8) -> i64 {
149 c_puts(" " as *u8)
150 c_date(mbr_geti(ctx, 2, i))
151 c_puts(" " as *u8)
152 let code: *u8 = mbr_code_at(ctx, i)
153 c_puts(code)
154 c_puts(" x" as *u8)
155 c_putn(mbr_geti(ctx, 3, i))
156 c_puts(" " as *u8)
157 c_money(mbr_geti(ctx, 6, i))
158 let l: i64 = mbc_get(prefix, code, rec, K_MAGIC_2048)
159 if l < 0 { c_puts(" -- (code not in local pack)" as *u8) } else {
160 let fld: *u8 = sys_mmap(K_MAGIC_1024)
161 mbc_field(rec, 1, fld, K_MAGIC_1024)
162 c_puts(" -- " as *u8)
163 c_puts(fld)
164 }
165 c_puts("\n" as *u8)
166 return 0
167}
168
169func cli_review(prefix: *u8, billpath: *u8, eobpath: *u8, haveeob: i64) -> i64 {
170 let cap: i64 = K_MAGIC_262144
171 let btxt: *u8 = sys_mmap(cap)
172 let bn: i64 = mbc_read_all(billpath, btxt, cap)
173 if bn <= 0 { c_puts("BILL READ-FAIL\n" as *u8); return 1 }
174 let b: *i64 = mbr_ctx_new(256)
175 let nb: i64 = mbr_parse(btxt, bn, b)
176 c_puts("BILL " as *u8)
177 c_puts(billpath)
178 c_puts(": " as *u8)
179 c_putn(nb)
180 c_puts(" claim lines\n" as *u8)
181 let rec: *u8 = sys_mmap(K_MAGIC_2048)
182 var i: i64 = 0
183 while i < nb { cli_rline(prefix, b, i, rec); i = i + 1 }
184
185 // R5 duplicate audit always runs (needs no rule pack)
186 let ncodes: *i64 = sys_mmap(8 * 256) as *i64
187 var ci: i64 = 0
188 while ci < nb { let cv: i64 = c_codenum(mbr_code_at(b, ci)); ncodes[ci] = cv; ci = ci + 1 }
189 let didx: *i64 = sys_mmap(8 * 64) as *i64
190 let damt: *i64 = sys_mmap(8 * 64) as *i64
191 let doc: *i64 = sys_mmap(8 * 64) as *i64
192 let dup: i64 = aud_duplicates(ncodes, b[2] as *i64, b[6] as *i64, nb, didx, damt, doc)
193 var pot: i64 = 0
194 if dup > 0 {
195 c_puts("AUDIT duplicates: " as *u8)
196 c_putn(dup)
197 c_puts(" repeat line(s)\n" as *u8)
198 var di: i64 = 0
199 while di < dup {
200 c_puts(" DUPLICATE line " as *u8)
201 c_putn(didx[di])
202 c_puts(" (" as *u8)
203 let dcode: *u8 = mbr_code_at(b, didx[di])
204 c_puts(dcode)
205 c_puts(") repeat charge " as *u8)
206 c_money(doc[di])
207 c_puts("\n" as *u8)
208 pot = pot + doc[di]
209 di = di + 1
210 }
211 } else { c_puts("AUDIT duplicates: none\n" as *u8) }
212
213 if haveeob == 1 {
214 let etxt: *u8 = sys_mmap(cap)
215 let en: i64 = mbc_read_all(eobpath, etxt, cap)
216 if en <= 0 { c_puts("EOB READ-FAIL\n" as *u8); return 1 }
217 let e: *i64 = mbr_ctx_new(256)
218 let ne: i64 = mbr_parse(etxt, en, e)
219 c_puts("EOB " as *u8)
220 c_puts(eobpath)
221 c_puts(": " as *u8)
222 c_putn(ne)
223 c_puts(" claim lines\n" as *u8)
224 let ftyp: *i64 = sys_mmap(8 * 128) as *i64
225 let fidx: *i64 = sys_mmap(8 * 128) as *i64
226 let famt: *i64 = sys_mmap(8 * 128) as *i64
227 let nf: i64 = mbr_recon(b, e, ftyp, fidx, famt)
228 c_puts("RECON flags: " as *u8)
229 c_putn(nf)
230 c_puts("\n" as *u8)
231 var rtot: i64 = 0
232 var fi: i64 = 0
233 while fi < nf {
234 c_puts(" FLAG line " as *u8)
235 c_putn(fidx[fi])
236 c_puts(" (" as *u8)
237 let fcode: *u8 = mbr_code_at(b, fidx[fi])
238 c_puts(fcode)
239 c_puts(") " as *u8)
240 if ftyp[fi] == 1 { c_puts("NOT ON EOB " as *u8) }
241 if ftyp[fi] == 2 { c_puts("BILLED MISMATCH vs EOB " as *u8) }
242 if ftyp[fi] == 3 { c_puts("ABOVE EOB-ALLOWED " as *u8) }
243 c_money(famt[fi])
244 c_puts("\n" as *u8)
245 rtot = rtot + famt[fi]
246 fi = fi + 1
247 }
248 c_puts("TOTAL flagged vs EOB: " as *u8)
249 c_money(rtot)
250 c_puts("\n" as *u8)
251 }
252 c_puts("NOTE decision-support only, not professional or legal advice; verify findings with your provider and plan before disputing.\n" as *u8)
253 return 0
254}
255
256// M2c: parse bill+EOB, assemble a NON-OVERLAPPING finding set (duplicate wins over its own NOT-ON-EOB
257// flag so no line is double-counted), render the R8 dispute letter to stdout. Placeholders keep the
258// patient's specifics out of the tool (PRIVACY: operator fills them in when reviewing). disp_build can
259// never send anything -- it writes text into a buffer; the human decides (never-brick #26).
260func cli_letter(billpath: *u8, eobpath: *u8) -> i64 {
261 let cap: i64 = K_MAGIC_262144
262 let btxt: *u8 = sys_mmap(cap)
263 let bn: i64 = mbc_read_all(billpath, btxt, cap)
264 if bn <= 0 { c_puts("BILL READ-FAIL\n" as *u8); return 1 }
265 let etxt: *u8 = sys_mmap(cap)
266 let en: i64 = mbc_read_all(eobpath, etxt, cap)
267 if en <= 0 { c_puts("EOB READ-FAIL\n" as *u8); return 1 }
268 let b: *i64 = mbr_ctx_new(256)
269 let e: *i64 = mbr_ctx_new(256)
270 let nb: i64 = mbr_parse(btxt, bn, b)
271 mbr_parse(etxt, en, e)
272
273 // duplicate audit findings first (structural, strongest ground)
274 let ncodes: *i64 = sys_mmap(8 * 256) as *i64
275 var ci: i64 = 0
276 while ci < nb { let cv: i64 = c_codenum(mbr_code_at(b, ci)); ncodes[ci] = cv; ci = ci + 1 }
277 let didx: *i64 = sys_mmap(8 * 64) as *i64
278 let damt: *i64 = sys_mmap(8 * 64) as *i64
279 let doc: *i64 = sys_mmap(8 * 64) as *i64
280 let dup: i64 = aud_duplicates(ncodes, b[2] as *i64, b[6] as *i64, nb, didx, damt, doc)
281
282 let reasons: *i64 = sys_mmap(8 * 128) as *i64
283 let cpts: *i64 = sys_mmap(8 * 128) as *i64
284 let fdates: *i64 = sys_mmap(8 * 128) as *i64
285 let amounts: *i64 = sys_mmap(8 * 128) as *i64
286 let dupline: *i64 = sys_mmap(8 * 256) as *i64
287 var nf: i64 = 0
288 var di: i64 = 0
289 while di < dup {
290 let ln: i64 = didx[di]
291 if ncodes[ln] >= 0 {
292 reasons[nf] = 1
293 cpts[nf] = ncodes[ln]
294 fdates[nf] = mbr_geti(b, 2, ln)
295 amounts[nf] = doc[di]
296 dupline[ln] = 1
297 nf = nf + 1
298 }
299 di = di + 1
300 }
301
302 // reconciliation flags (skip lines already claimed as duplicates -- no double-count)
303 let ftyp: *i64 = sys_mmap(8 * 128) as *i64
304 let fidx: *i64 = sys_mmap(8 * 128) as *i64
305 let famt: *i64 = sys_mmap(8 * 128) as *i64
306 let nr: i64 = mbr_recon(b, e, ftyp, fidx, famt)
307 var skipped: i64 = 0
308 var fi: i64 = 0
309 while fi < nr {
310 let ln2: i64 = fidx[fi]
311 if dupline[ln2] == 1 { fi = fi + 1 } else {
312 if ncodes[ln2] < 0 { skipped = skipped + 1; fi = fi + 1 } else {
313 var rs: i64 = 0
314 if ftyp[fi] == 3 { rs = 5 }
315 if ftyp[fi] == 1 { rs = 6 }
316 if rs > 0 {
317 reasons[nf] = rs
318 cpts[nf] = ncodes[ln2]
319 fdates[nf] = mbr_geti(b, 2, ln2)
320 amounts[nf] = famt[fi]
321 nf = nf + 1
322 }
323 fi = fi + 1
324 }
325 }
326 }
327 if nf == 0 { c_puts("No disputable findings; no letter generated.\n" as *u8); return 0 }
328 if skipped > 0 { c_puts("NOTE: alpha-code lines were flagged but omitted from the letter (numeric CPT only in v1).\n" as *u8) }
329
330 let letter: *u8 = sys_mmap(K_MAGIC_16384)
331 let ll: i64 = disp_build("[PATIENT NAME]\x00" as *u8, "[PROVIDER NAME]\x00" as *u8, "[ACCOUNT NUMBER]\x00" as *u8, reasons, cpts, fdates, amounts, nf, letter)
332 c_puts("----- dispute letter (review, fill placeholders, then send yourself) -----\n" as *u8)
333 sys_write(1, letter, ll)
334 c_puts("----- end letter -----\n" as *u8)
335 c_puts("NOTE decision-support only, not professional or legal advice; verify findings with your provider and plan before sending.\n" as *u8)
336 return 0
337}
338
339func c_atoi(s: *u8) -> i64 {
340 var v: i64 = 0
341 var i: i64 = 0
342 while s[i] != (0 as u8) { if mbr_is_digit(s[i]) == 0 { return 0 - 1 } v = v * 10 + ((s[i] as i64) - 48); i = i + 1 }
343 return v
344}
345
346// M-ADV1: charity-care screen + 501(r) FAP request letter
347func cli_charity(income: i64, household: i64, region: *u8) -> i64 {
348 let fpl: i64 = mbch_fpl("knowledge/medbill/fpl.list\x00" as *u8, region, household)
349 if fpl < 0 { c_puts("FPL lookup failed (region or household invalid)\n" as *u8); return 1 }
350 let pct: i64 = mbch_pct(income, fpl)
351 c_puts("CHARITY-CARE SCREEN: income $" as *u8)
352 c_putn(income)
353 c_puts(", household " as *u8)
354 c_putn(household)
355 c_puts(" -> HHS poverty guideline $" as *u8)
356 c_putn(fpl)
357 c_puts(" -> " as *u8)
358 c_putn(pct)
359 c_puts(" percent of FPL\n" as *u8)
360 c_puts("Common hospital FAP tiers: free care around/below 200 percent, discounted care to 300-400 percent (each hospital sets its own policy - ask for theirs).\n" as *u8)
361 let letter: *u8 = sys_mmap(K_MAGIC_16384)
362 let ll: i64 = mbch_letter(income, household, pct, letter)
363 c_puts("----- financial assistance request letter (review, fill placeholders, send yourself) -----\n" as *u8)
364 sys_write(1, letter, ll)
365 c_puts("----- end letter -----\n" as *u8)
366 c_puts("NOTE decision-support only, not professional or legal advice.\n" as *u8)
367 return 0
368}
369
370// M-ADV2: denial internal-appeal letter with computed deadline
371func cli_appeal(reason: i64, denial: i64) -> i64 {
372 if denial < K_MAGIC_19000101 { c_puts("denial date must be YYYYMMDD\n" as *u8); return 1 }
373 let letter: *u8 = sys_mmap(K_MAGIC_16384)
374 let ll: i64 = mba_letter(reason, denial, letter)
375 c_puts("----- internal appeal letter (review, fill placeholders, send yourself) -----\n" as *u8)
376 sys_write(1, letter, ll)
377 c_puts("----- end letter -----\n" as *u8)
378 c_puts("Reasons: 1 not-medically-necessary, 2 experimental, 3 out-of-network, 4 prior-auth-missing, 5 coding-error.\n" as *u8)
379 c_puts("NOTE decision-support only, not professional or legal advice.\n" as *u8)
380 return 0
381}
382
383// ADV3: classify the billing situation to its federal protection and render the matching letter
384func cli_nsa(flags: *i64, over: i64, bill: i64) -> i64 {
385 let route: i64 = nsa_classify(flags, over, K_MAGIC_40000)
386 c_puts("NSA SITUATION ROUTE: " as *u8)
387 c_putn(route)
388 if route == 1 { c_puts(" (No Surprises Act - emergency: balance billing prohibited)\n" as *u8) }
389 if route == 2 { c_puts(" (No Surprises Act - OON provider at in-network facility)\n" as *u8) }
390 if route == 3 { c_puts(" (Patient-Provider Dispute Resolution - uninsured, billed over the Good Faith Estimate)\n" as *u8) }
391 if route == 4 { c_puts(" (no situation-specific shield - use review/letter/appeal/charity)\n" as *u8) }
392 let letter: *u8 = sys_mmap(K_MAGIC_16384)
393 let ll: i64 = nsa_letter(route, over, bill, letter)
394 c_puts("----- letter/guidance (review, fill placeholders, send yourself) -----\n" as *u8)
395 sys_write(1, letter, ll)
396 c_puts("----- end -----\nNOTE decision-support only, not professional or legal advice.\n" as *u8)
397 return 0
398}
399
400// ADV5: civic escalation -- route + letter, opt-in case ledger, accountability board
401func cli_civic_route(issue: i64) -> i64 {
402 let ch: i64 = cv_route(issue)
403 if ch < 0 { c_puts("unknown issue (1 insurer-misconduct, 2 NSA-violation, 3 charity-501r, 4 collections-credit, 5 fraud, 6 reform-story)\n" as *u8); return 1 }
404 let days: i64 = cv_expect("knowledge/medbill/civic_channels.list\x00" as *u8, ch)
405 c_puts("CIVIC ROUTE: channel " as *u8)
406 c_putn(ch)
407 c_puts(", expected response window " as *u8)
408 c_putn(days)
409 c_puts(" days (data pack)\n" as *u8)
410 let letter: *u8 = sys_mmap(K_MAGIC_16384)
411 let ll: i64 = cv_letter(issue, letter)
412 c_puts("----- complaint pattern (YOURS to review, complete, and send - nothing is sent for you) -----\n" as *u8)
413 sys_write(1, letter, ll)
414 c_puts("----- end -----\nNOTE decision-support only, not professional or legal advice. Facts only; you choose what to share and where.\n" as *u8)
415 return 0
416}
417func cli_civic_open(prefix: *u8, id: *u8, issue: i64, sent: i64) -> i64 {
418 let rc: i64 = cv_case_open(prefix, id, issue, sent)
419 if rc != 0 { c_puts("open failed (unknown issue or store error)\n" as *u8); return 1 }
420 let man: *u8 = sys_mmap(K_MAGIC_4096)
421 let ml: i64 = cv_get(prefix, "_manifest\x00" as *u8, man, K_MAGIC_4096)
422 if ml < 0 { man[0] = 0 as u8 }
423 if mbc_contains(man, id) == 0 {
424 let man2: *u8 = sys_mmap(K_MAGIC_4096)
425 var o: i64 = mbc_app(man2, 0, man)
426 man2[o] = 32 as u8
427 o = o + 1
428 o = mbc_app(man2, o, id)
429 man2[o] = 0 as u8
430 cv_w(prefix, "_manifest\x00" as *u8, man2)
431 }
432 c_puts("CASE OPENED (you sent it; the ledger only records your action): " as *u8)
433 c_puts(id)
434 c_puts("\n" as *u8)
435 return 0
436}
437func cli_civic_board(prefix: *u8, today: i64) -> i64 {
438 let man: *u8 = sys_mmap(K_MAGIC_4096)
439 if cv_get(prefix, "_manifest\x00" as *u8, man, K_MAGIC_4096) < 0 { c_puts("no civic cases yet\n" as *u8); return 0 }
440 let CH: *u8 = "knowledge/medbill/civic_channels.list\x00" as *u8
441 let rec: *u8 = sys_mmap(512)
442 let id: *u8 = sys_mmap(128)
443 let tal: *i64 = sys_mmap(8 * 8) as *i64
444 c_puts("CIVIC ACCOUNTABILITY BOARD (are they moving?)\n" as *u8)
445 var i: i64 = 0
446 var go: i64 = 1
447 while go == 1 {
448 while man[i] == (32 as u8) { i = i + 1 }
449 if man[i] == (0 as u8) { go = 0 } else {
450 var k: i64 = 0
451 var t: i64 = 1
452 while t == 1 {
453 if man[i] == (0 as u8) { t = 0 } else {
454 if man[i] == (32 as u8) { t = 0 } else {
455 if k < 120 { id[k] = man[i]; k = k + 1 }
456 i = i + 1
457 }
458 }
459 }
460 id[k] = 0 as u8
461 if k > 0 {
462 if cv_get(prefix, id, rec, 512) > 0 {
463 let ch: i64 = cv_f(rec, 1)
464 let sent: i64 = cv_f(rec, 2)
465 let status: i64 = cv_f(rec, 3)
466 let days: i64 = cv_expect(CH, ch)
467 let v: i64 = cv_verdict(status, sent, days, today)
468 c_puts(" " as *u8)
469 c_puts(id)
470 c_puts(": channel " as *u8)
471 c_putn(ch)
472 c_puts(" sent " as *u8)
473 c_putn(sent)
474 c_puts(" status " as *u8)
475 c_putn(status)
476 c_puts(" follow-up " as *u8)
477 c_putn(cv_followup(sent, days))
478 if v == 1 { c_puts(" MOVING\n" as *u8) }
479 if v == 2 { c_puts(" PENDING\n" as *u8) }
480 if v == 3 { c_puts(" OVERDUE-UNRESPONSIVE\n" as *u8) }
481 if v == 4 { c_puts(" CLOSED-NO-ACTION\n" as *u8) }
482 tal[v] = tal[v] + 1
483 }
484 }
485 }
486 }
487 c_puts("TALLY: moving=" as *u8)
488 c_putn(tal[1])
489 c_puts(" pending=" as *u8)
490 c_putn(tal[2])
491 c_puts(" overdue=" as *u8)
492 c_putn(tal[3])
493 c_puts(" no-action=" as *u8)
494 c_putn(tal[4])
495 c_puts("\nMeasured from your own sent/response dates - the movement verdict is mechanical, not asserted.\n" as *u8)
496 return 0
497}
498
499// ADV4: append a deadline EVENT to the medbill calendar file (the vizsla-calendar record contract:
500// EVENT <id> <YYYY-MM-DD> <start_min> <dur_min> <title>). The GATED vizsla engines do the rest:
501// nx_vizsla_calendar load -> cal: records; nx_vizsla_remind due -> lead-day notices, sent-once ledger.
502// Loose coupling by artifact contract; the system remembers the window so the patient does not.
503func cli_deadline(kind: *u8, base: i64, channel: i64) -> i64 {
504 var days: i64 = 0 - 1
505 if mbc_streq(kind, "appeal\x00" as *u8) == 1 { days = 180 }
506 if mbc_streq(kind, "ppdr\x00" as *u8) == 1 { days = 120 }
507 if mbc_streq(kind, "civic\x00" as *u8) == 1 { days = cv_expect("knowledge/medbill/civic_channels.list\x00" as *u8, channel) }
508 if days < 0 { c_puts("kind must be appeal|ppdr|civic <channel>\n" as *u8); return 1 }
509 let due: i64 = mba_add_days(base, days)
510 let path: *u8 = "knowledge/medbill/deadlines.cal\x00" as *u8
511 let cap: i64 = K_MAGIC_262144
512 let buf: *u8 = sys_mmap(cap)
513 var n: i64 = mbc_read_all(path, buf, cap)
514 if n < 0 { n = 0 }
515 var o: i64 = n
516 o = mbc_app(buf, o, "EVENT mb-\x00" as *u8)
517 o = mbc_app(buf, o, kind)
518 buf[o] = 45 as u8
519 o = o + 1
520 o = mba_date(buf, o, base)
521 buf[o] = 32 as u8
522 o = o + 1
523 o = mba_date(buf, o, due)
524 o = mbc_app(buf, o, " 540 30 medbill-\x00" as *u8)
525 o = mbc_app(buf, o, kind)
526 o = mbc_app(buf, o, "-deadline-act-now\x00" as *u8)
527 buf[o] = 10 as u8
528 o = o + 1
529 let fd: i64 = sys_openat_wr(path, 0x1a4)
530 if fd < 0 { c_puts("deadline file WRITE-FAIL\n" as *u8); return 1 }
531 sys_write(fd, buf, o)
532 sys_close(fd)
533 c_puts("DEADLINE FILED: " as *u8)
534 c_puts(kind)
535 c_puts(" window ends " as *u8)
536 let d2: *u8 = sys_mmap(32)
537 let dl: i64 = mba_date(d2, 0, due)
538 sys_write(1, d2, dl)
539 c_puts(" -> knowledge/medbill/deadlines.cal (load into the vizsla calendar; remind engine surfaces it at 14/7/1/0-day leads)\n" as *u8)
540 return 0
541}
542
543func cli_lookup(prefix: *u8, code: *u8) -> i64 {
544 let rec: *u8 = sys_mmap(K_MAGIC_2048)
545 let fld: *u8 = sys_mmap(K_MAGIC_1024)
546 let l: i64 = mbc_get(prefix, code, rec, K_MAGIC_2048)
547 if l < 0 {
548 c_puts(code)
549 c_puts(": UNKNOWN (not in the local code pack; the decoder never fabricates)\n" as *u8)
550 return 1
551 }
552 c_puts(code)
553 c_puts(" (" as *u8)
554 mbc_field(rec, 0, fld, K_MAGIC_1024)
555 c_puts(fld)
556 c_puts("): " as *u8)
557 mbc_field(rec, 1, fld, K_MAGIC_1024)
558 c_puts(fld)
559 c_puts(" [source: " as *u8)
560 mbc_field(rec, 2, fld, K_MAGIC_1024)
561 c_puts(fld)
562 c_puts("]\n" as *u8)
563 return 0
564}
565
566func main(argc: i64, argv: *i64) -> i64 {
567 let prefix: *u8 = "knowledge/store/medbill-\x00" as *u8
568 if argc >= 2 {
569 let verb: *u8 = argv[1] as *u8
570 if mbc_streq(verb, "ingest\x00" as *u8) == 1 { return cli_ingest(prefix) }
571 if mbc_streq(verb, "lookup\x00" as *u8) == 1 {
572 if argc >= 3 { return cli_lookup(prefix, argv[2] as *u8) }
573 }
574 if mbc_streq(verb, "review\x00" as *u8) == 1 {
575 if argc >= 4 { return cli_review(prefix, argv[2] as *u8, argv[3] as *u8, 1) }
576 if argc >= 3 { return cli_review(prefix, argv[2] as *u8, "\x00" as *u8, 0) }
577 }
578 if mbc_streq(verb, "letter\x00" as *u8) == 1 {
579 if argc >= 4 { return cli_letter(argv[2] as *u8, argv[3] as *u8) }
580 }
581 if mbc_streq(verb, "charity\x00" as *u8) == 1 {
582 if argc >= 4 {
583 var reg: *u8 = "contiguous\x00" as *u8
584 if argc >= 5 { reg = argv[4] as *u8 }
585 return cli_charity(c_atoi(argv[2] as *u8), c_atoi(argv[3] as *u8), reg)
586 }
587 }
588 if mbc_streq(verb, "appeal\x00" as *u8) == 1 {
589 if argc >= 4 { return cli_appeal(c_atoi(argv[2] as *u8), c_atoi(argv[3] as *u8)) }
590 }
591 if mbc_streq(verb, "nsa\x00" as *u8) == 1 {
592 if argc >= 9 {
593 let f: *i64 = sys_mmap(8 * 8) as *i64
594 f[0] = c_atoi(argv[2] as *u8)
595 f[1] = c_atoi(argv[3] as *u8)
596 f[2] = c_atoi(argv[4] as *u8)
597 f[3] = c_atoi(argv[5] as *u8)
598 f[4] = c_atoi(argv[6] as *u8)
599 return cli_nsa(f, c_atoi(argv[7] as *u8), c_atoi(argv[8] as *u8))
600 }
601 }
602 if mbc_streq(verb, "civic\x00" as *u8) == 1 {
603 if argc >= 3 {
604 let sub: *u8 = argv[2] as *u8
605 if mbc_streq(sub, "route\x00" as *u8) == 1 { if argc >= 4 { return cli_civic_route(c_atoi(argv[3] as *u8)) } }
606 if mbc_streq(sub, "open\x00" as *u8) == 1 { if argc >= 6 { return cli_civic_open(prefix, argv[3] as *u8, c_atoi(argv[4] as *u8), c_atoi(argv[5] as *u8)) } }
607 if mbc_streq(sub, "update\x00" as *u8) == 1 { if argc >= 6 { if cv_case_set(prefix, argv[3] as *u8, c_atoi(argv[4] as *u8), c_atoi(argv[5] as *u8)) == 0 { c_puts("updated\n" as *u8); return 0 } c_puts("update failed\n" as *u8); return 1 } }
608 if mbc_streq(sub, "board\x00" as *u8) == 1 { if argc >= 4 { return cli_civic_board(prefix, c_atoi(argv[3] as *u8)) } }
609 }
610 }
611 if mbc_streq(verb, "portal\x00" as *u8) == 1 {
612 let pg: *u8 = sys_mmap(K_MAGIC_65536)
613 let pl: i64 = hh_page(pg)
614 sys_write(1, pg, pl)
615 return 0
616 }
617 if mbc_streq(verb, "deadline\x00" as *u8) == 1 {
618 if argc >= 4 {
619 var chn: i64 = 0
620 if argc >= 5 { chn = c_atoi(argv[4] as *u8) }
621 return cli_deadline(argv[2] as *u8, c_atoi(argv[3] as *u8), chn)
622 }
623 }
624 }
625 c_puts("usage: nx_medbill_cli ingest | lookup <code> | review <bill.txt> [eob.txt] | letter <bill.txt> <eob.txt> | charity <income> <household> [region] | appeal <reason> <denialYYYYMMDD> | nsa <emerg> <oon> <innetfac> <insured> <gfe> <over_cents> <billYYYYMMDD> | civic route <issue> / open <id> <issue> <sentYMD> / update <id> <status> <YMD> / board <todayYMD>\n" as *u8)
626 return 1
627}