code wiki / _hdl_build / nx_mailmerge_gate.nx

nx_mailmerge_gate.nx source

↩ module page · 100 lines · 7187 B

1// nx_mailmerge_gate.nx -- proves sovereign mail merge by driving the REAL elfs (/tmp/nx_docx.sov.elf + 2// /tmp/nx_mailmerge.sov.elf) fully within the Nishi ecosystem (the gate authors the template via nx_docx and 3// writes the TSV itself via syscalls -- no third-party tools): 4// SUBSTITUTION : {{name}}/{{asset}}/{{firm}} are replaced from each TSV record (per-heir documents) 5// DATA ESCAPE : a '&' inside a data value survives the merge ('The house & land') 6// TEMPLATE TEXT: a '&' in the template's own text survives ('Smith LLP & partners') 7// COMPLETE : no '{{' placeholder remains in any output; the count matches the data rows 8// GREEN iff 7/7. Requires /tmp/nx_docx.sov.elf + /tmp/nx_mailmerge.sov.elf. Durable knowledge/status/mailmerge_gate.log 9// license_tier: ORIGINAL 10import "nx_syscalls.nx" 11import "nx_g_puts_lib.nx" 12 13func g_num(v: i64) -> i64 { let bb: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m;sys_write(1,"-" as *u8,1)}; let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=(48 as u8);k=1}; while m>0{t[k]=((48+(m%10)) as u8);m=m/10;k=k+1}; var i: i64=0; while i<k{bb[i]=t[k-1-i];i=i+1}; sys_write(1,bb,k); return 0 } 14func g_w(fd: i64, s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(fd,s,n); return 0 } 15func g_wn(fd: i64, v: i64) -> i64 { let bb: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m}; let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=(48 as u8);k=1}; while m>0{t[k]=((48+(m%10)) as u8);m=m/10;k=k+1}; var i: i64=0; while i<k{bb[i]=t[k-1-i];i=i+1}; sys_write(fd,bb,k); return 0 } 16func g_strlen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n } 17func g_cat(dst: *u8, off: i64, s: *u8) -> i64 { var i: i64=0; while s[i]!=(0 as u8){ dst[off+i]=s[i]; i=i+1 } return off+i } 18func g_read(path: *u8, buf: *u8, cap: i64) -> i64 { 19 let fd: i64=sys_openat_rd(path); if fd<0 { return 0 } 20 var total: i64=0; var nrd: i64=sys_read(fd, buf, cap) 21 while nrd>0 { total=total+nrd; if total>=cap { nrd=0 } else { nrd=sys_read(fd, ((buf as i64)+total) as *u8, cap-total) } } 22 sys_close(fd); return total 23} 24func g_contains(hay: *u8, n: i64, needle: *u8) -> i64 { 25 let nl: i64=g_strlen(needle); if nl==0 { return 0 } 26 var i: i64=0 27 while i+nl<=n { var j: i64=0; var hit: i64=1; while j<nl { if hay[i+j]!=needle[j] { hit=0; j=nl } else { j=j+1 } } if hit==1 { return 1 } i=i+1 } 28 return 0 29} 30func g_run(elf: *u8, args: *i64, nargs: i64, out_path: *u8) -> i64 { 31 let pid: i64=sys_fork() 32 if pid==0 { 33 let o: i64=sys_openat_wr(out_path, 0x1a4); if o>=0 { sys_dup3(o,1,0) } 34 let argv: *i64=sys_mmap(8*16) as *i64 35 argv[0]=elf as i64 36 var i: i64=0; while i<nargs { argv[1+i]=args[i]; i=i+1 } argv[1+nargs]=0 37 let envp: *i64=sys_mmap(16) as *i64; envp[0]="PATH=/usr/bin:/bin" as *u8 as i64; envp[1]=0 38 sys_execve(elf, argv, envp); sys_exit(127) 39 } 40 let st: *i64=sys_mmap(16) as *i64; sys_wait4(pid, st, 0); return (st[0]>>8)&0xff 41} 42// author the data source TSV (header + 2 records) with real TAB/newline bytes 43func g_write_tsv(path: *u8) -> i64 { 44 let b: *u8=sys_mmap(4096); var o: i64=0 45 o=g_cat(b,o,"name" as *u8); b[o]=9 as u8; o=o+1; o=g_cat(b,o,"asset" as *u8); b[o]=9 as u8; o=o+1; o=g_cat(b,o,"firm" as *u8); b[o]=10 as u8; o=o+1 46 o=g_cat(b,o,"Alice Heir" as *u8); b[o]=9 as u8; o=o+1; o=g_cat(b,o,"The house & land" as *u8); b[o]=9 as u8; o=o+1; o=g_cat(b,o,"Smith LLP" as *u8); b[o]=10 as u8; o=o+1 47 o=g_cat(b,o,"Bob Heir" as *u8); b[o]=9 as u8; o=o+1; o=g_cat(b,o,"The car" as *u8); b[o]=9 as u8; o=o+1; o=g_cat(b,o,"Smith LLP" as *u8); b[o]=10 as u8; o=o+1 48 let fd: i64=sys_openat_wr(path, 0x1a4); if fd<0 { return 0-1 } 49 sys_write(fd, b, o); sys_close(fd); return o 50} 51 52func main() -> i64 { 53 g_puts("=== MAIL MERGE GATE (sovereign template + data -> per-heir documents) ===\n" as *u8) 54 let DOCX: *u8="/tmp/nx_docx.sov.elf" as *u8 55 let MM: *u8="/tmp/nx_mailmerge.sov.elf" as *u8 56 let T: *u8="/tmp/mm_gate_tmpl.docx" as *u8 57 let DATA: *u8="/tmp/mm_gate.tsv" as *u8 58 let OUT: *u8="/tmp/mm_gate_out_" as *u8 59 let O1: *u8="/tmp/mm_gate_out_1.docx" as *u8 60 let O2: *u8="/tmp/mm_gate_out_2.docx" as *u8 61 let scratch: *u8="/tmp/mm_gate_scratch.txt" as *u8 62 let obuf: *u8=sys_mmap(262144) 63 let a: *i64=sys_mmap(8*8) as *i64 64 65 // author template (placeholders + a '&' in template text) 66 a[0]="write" as *u8 as i64; a[1]=T as i64 67 a[2]="Dear {{name}}," as *u8 as i64 68 a[3]="Bequest: {{asset}}." as *u8 as i64 69 a[4]="From {{firm}} & partners." as *u8 as i64 70 g_run(DOCX, a, 5, scratch) 71 // author data source 72 g_write_tsv(DATA) 73 // run the merge (capture stdout for the count) 74 a[0]=T as i64; a[1]=DATA as i64; a[2]=OUT as i64 75 g_run(MM, a, 3, scratch) 76 var sn: i64=g_read(scratch, obuf, 262144) 77 78 var pass: i64=0; let rows: i64=7 79 g_puts(" R1 merge reports documents=2? " as *u8); if g_contains(obuf,sn,"documents=2" as *u8)==1 { pass=pass+1; g_puts("YES PASS\n" as *u8) } else { g_puts("NO FAIL\n" as *u8) } 80 81 // read merged doc 1 82 a[0]="read" as *u8 as i64; a[1]=O1 as i64 83 g_run(DOCX, a, 2, scratch); var n1: i64=g_read(scratch, obuf, 262144) 84 g_puts(" R2 doc1 substituted name ('Dear Alice Heir,')? " as *u8); if g_contains(obuf,n1,"Dear Alice Heir," as *u8)==1 { pass=pass+1; g_puts("YES PASS\n" as *u8) } else { g_puts("NO FAIL\n" as *u8) } 85 g_puts(" R3 doc1 DATA '&' survived ('The house & land')? " as *u8); if g_contains(obuf,n1,"The house & land" as *u8)==1 { pass=pass+1; g_puts("YES PASS\n" as *u8) } else { g_puts("NO FAIL\n" as *u8) } 86 g_puts(" R4 doc1 TEMPLATE '&' survived ('Smith LLP & partners')? " as *u8); if g_contains(obuf,n1,"Smith LLP & partners" as *u8)==1 { pass=pass+1; g_puts("YES PASS\n" as *u8) } else { g_puts("NO FAIL\n" as *u8) } 87 g_puts(" R5 doc1 has NO leftover '{{' placeholder? " as *u8); if g_contains(obuf,n1,"{{" as *u8)==0 { pass=pass+1; g_puts("YES PASS\n" as *u8) } else { g_puts("NO FAIL\n" as *u8) } 88 89 // read merged doc 2 90 a[0]="read" as *u8 as i64; a[1]=O2 as i64 91 g_run(DOCX, a, 2, scratch); var n2: i64=g_read(scratch, obuf, 262144) 92 g_puts(" R6 doc2 second record ('Dear Bob Heir,')? " as *u8); if g_contains(obuf,n2,"Dear Bob Heir," as *u8)==1 { pass=pass+1; g_puts("YES PASS\n" as *u8) } else { g_puts("NO FAIL\n" as *u8) } 93 g_puts(" R7 doc2 its own asset ('Bequest: The car.')? " as *u8); if g_contains(obuf,n2,"Bequest: The car." as *u8)==1 { pass=pass+1; g_puts("YES PASS\n" as *u8) } else { g_puts("NO FAIL\n" as *u8) } 94 95 g_puts("----\nMAILMERGE rows=" as *u8); g_num(rows); g_puts(" pass=" as *u8); g_num(pass); g_puts("\n" as *u8) 96 let lg: i64=sys_openat_append("knowledge/status/mailmerge_gate.log" as *u8, 0x1a4) 97 if lg>=0 { g_w(lg, "MAILMERGE rows=" as *u8); g_wn(lg, rows); g_w(lg, " pass=" as *u8); g_wn(lg, pass); if pass==rows { g_w(lg, " verdict=GREEN\n" as *u8) } else { g_w(lg, " verdict=RED\n" as *u8) } sys_close(lg) } 98 if pass==rows { g_puts("MAILMERGE GREEN (sovereign per-heir document generation from template + estate data)\n" as *u8); sys_exit(0); return 0 } 99 g_puts("MAILMERGE RED\n" as *u8); sys_exit(1); return 1 100}