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}