code wiki / _hdl_build / nx_doc_view_gate.nx
nx_doc_view_gate.nx source
↩ module page · 132 lines · 8077 B
1// nx_doc_view_gate.nx -- gate for the document-viewer DISPATCH (the browser omnitool core). Proves nx_doc_view
2// reads the registry (knowledge/doc_viewers.conf) and routes each extension to the right sovereign renderer,
3// producing inline 0-JS HTML: docx->nx_docx, md->nx_md, csv->nx_csv. Negative control: an unregistered extension
4// is refused (not silently mis-rendered). Requires the renderers blessed in _offc. license_tier: ORIGINAL
5import "nx_syscalls.nx"
6import "nx_gate_verdict.nx"
7
8func dg_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8) { n=n+1 } return n }
9func dg_p(s: *u8) -> i64 { sys_write(1, s, dg_slen(s)); return 0 }
10func dg_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 }
11func dg_catn(dst: *u8, off: i64, v: i64) -> i64 {
12 var o: i64=off; var m: i64=v; if m<0 { dst[o]=45 as u8; o=o+1; m=0-m }
13 let t: *u8=sys_mmap(28); var k: i64=0; if m==0 { t[0]=48 as u8; k=1 }
14 while m>0 { t[k]=(48+(m%10)) as u8; m=m/10; k=k+1 }
15 var i: i64=0; while i<k { dst[o+i]=t[k-1-i]; i=i+1 } return o+k
16}
17func dg_write(path: *u8, content: *u8) -> i64 {
18 let fd: i64=sys_openat_wr(path, 0x1a4); if fd<0 { return 0-1 }
19 sys_write(fd, content, dg_slen(content)); sys_close(fd); return 0
20}
21func dg_readall(path: *u8, szout: *i64) -> *u8 {
22 let fd: i64=sys_openat_rd(path); if fd<0 { szout[0]=0-1; return 0 as *u8 }
23 let buf: *u8=sys_mmap(4194304); var got: i64=0; var n: i64=1
24 while n>0 { n=sys_read(fd,(buf as i64+got) as *u8,131072); if n>0 { got=got+n } }
25 sys_close(fd); szout[0]=got; return buf
26}
27func dg_runv(elf: *u8, args: *i64, outpath: *u8) -> i64 {
28 let pid: i64=sys_fork()
29 if pid==0 {
30 if (outpath as i64)!=0 { let ofd: i64=sys_openat_wr(outpath,0x1a4); if ofd>=0 { sys_dup3(ofd,1,0); sys_dup3(ofd,2,0) } }
31 let argv: *i64=sys_mmap(128) as *i64
32 argv[0]=elf as i64; var i: i64=0; var go: i64=1
33 while go==1 { if args[i]==0 { go=0 } else { argv[i+1]=args[i]; i=i+1 } }
34 argv[i+1]=0
35 let envp: *i64=sys_mmap(16) as *i64; envp[0]=0
36 sys_execve(elf, argv, envp); sys_exit(127)
37 }
38 let st: *i64=sys_mmap(16) as *i64; sys_wait4(pid, st, 0)
39 let sig: i64=st[0]&0x7f; if sig!=0 { return 128+sig }
40 return (st[0]>>8)&0xff
41}
42func dg_has(path: *u8, needle: *u8) -> i64 {
43 let szp: *i64=sys_mmap(16) as *i64; let b: *u8=dg_readall(path, szp); let sz: i64=szp[0]
44 let n: i64=dg_slen(needle); if sz<n { return 0 }
45 var i: i64=0
46 while i+n<=sz { var ok: i64=1; var j: i64=0; while j<n { if b[i+j]!=needle[j] { ok=0; j=n } else { j=j+1 } } if ok==1 { return 1 } i=i+1 }
47 return 0
48}
49func dg_args(a1: *u8, a2: *u8, a3: *u8) -> *i64 {
50 let a: *i64=sys_mmap(64) as *i64; a[0]=a1 as i64; a[1]=a2 as i64; a[2]=a3 as i64; a[3]=0; return a
51}
52func dg_row(name: *u8, pass: i64) -> i64 {
53 dg_p("ROW " as *u8); dg_p(name); if pass==1 { dg_p(" PASS\n" as *u8) } else { dg_p(" FAIL\n" as *u8) } return pass
54}
55
56func main(argc: i64, argv: *i64) -> i64 {
57 dg_p("=== DOC-VIEW DISPATCH GATE: browser omnitool -- registry routes docx/md/csv to renderers, inline HTML ===\n" as *u8)
58 let dv: *u8="buildroot/_build/nx_doc_view.sov.elf" as *u8
59 let pr: i64=sys_openat_rd(dv)
60 if pr>=0 { sys_close(pr) } else {
61 dg_p(" instrument missing -> rebuilding\n" as *u8)
62 dg_runv("_offc/nx_sov_build_run.elf" as *u8, dg_args("nx_doc_view" as *u8, "--build-only" as *u8, 0 as *u8), "/tmp/dv_rebuild.out" as *u8)
63 }
64 // test inputs
65 dg_write("/tmp/dv_t.md" as *u8, "# Title\n\nHello **world** and *emphasis*.\n\n- one\n- two\n" as *u8)
66 dg_write("/tmp/dv_t.csv" as *u8, "Name,Role,City\nAlice,Lead,Denver\nBob,Eng,Provo\n" as *u8)
67 // Author the .docx fixture at RUNTIME via the real renderer, exactly as the md/csv rows do.
68 // This row previously pointed at web_assets/vizsla_agreement_demo.docx, which does not exist
69 // ANYWHERE in the estate (nx_shelltool find: matches=0 corpus_complete=1) -- a tooth whose
70 // fixture is absent can never pass, and it fails identically to a broken dispatcher, so the
71 // gate was accusing its own subject. Building the fixture here also removes the dependency on
72 // a checked-in asset that can move.
73 dg_write("/tmp/dv_docx_spec.txt" as *u8, "H Venue Booking Agreement\nP Between the venue and the client.\nT Item|Owner\nT Deposit|Client\n" as *u8)
74 dg_runv("_offc/nx_docx.elf" as *u8, dg_args("writerich" as *u8, "/tmp/dv_t.docx" as *u8, "/tmp/dv_docx_spec.txt" as *u8), "/tmp/dv_docx_mk.txt" as *u8)
75
76 var pass: i64=0; var r: i64=0
77
78 // row 1: markdown dispatch
79 let rc1: i64=dg_runv(dv, dg_args("/tmp/dv_t.md" as *u8, "/tmp/dv_md.html" as *u8, "/dv_t.md" as *u8), "/tmp/dv_r1.txt" as *u8)
80 r=0; if rc1==0 { if dg_has("/tmp/dv_r1.txt" as *u8, "DOC-VIEW-OK ext=md viewer=Markdown" as *u8)==1 { if dg_has("/tmp/dv_md.html" as *u8, "<h1>Title</h1>" as *u8)==1 { if dg_has("/tmp/dv_md.html" as *u8, "<b>world</b>" as *u8)==1 { r=1 } } } }
81 pass=pass+dg_row("md-dispatch" as *u8, r)
82
83 // row 2: csv dispatch
84 let rc2: i64=dg_runv(dv, dg_args("/tmp/dv_t.csv" as *u8, "/tmp/dv_csv.html" as *u8, "/dv_t.csv" as *u8), "/tmp/dv_r2.txt" as *u8)
85 r=0; if rc2==0 { if dg_has("/tmp/dv_r2.txt" as *u8, "DOC-VIEW-OK ext=csv" as *u8)==1 { if dg_has("/tmp/dv_csv.html" as *u8, "<th>Name</th>" as *u8)==1 { if dg_has("/tmp/dv_csv.html" as *u8, "<td>Denver</td>" as *u8)==1 { r=1 } } } }
86 pass=pass+dg_row("csv-dispatch" as *u8, r)
87
88 // row 3: docx dispatch
89 let rc3: i64=dg_runv(dv, dg_args("/tmp/dv_t.docx" as *u8, "/tmp/dv_docx.html" as *u8, "/vizsla_agreement.docx" as *u8), "/tmp/dv_r3.txt" as *u8)
90 r=0; if rc3==0 { if dg_has("/tmp/dv_r3.txt" as *u8, "DOC-VIEW-OK ext=docx viewer=Word document" as *u8)==1 { if dg_has("/tmp/dv_docx.html" as *u8, "<h2>Venue Booking Agreement</h2>" as *u8)==1 { r=1 } } }
91 pass=pass+dg_row("docx-dispatch" as *u8, r)
92
93 // row 4: all outputs sovereign (0-JS)
94 r=1
95 if dg_has("/tmp/dv_md.html" as *u8, "<script" as *u8)==1 { r=0 }
96 if dg_has("/tmp/dv_csv.html" as *u8, "<script" as *u8)==1 { r=0 }
97 if dg_has("/tmp/dv_docx.html" as *u8, "<script" as *u8)==1 { r=0 }
98 pass=pass+dg_row("all-sovereign-0js" as *u8, r)
99
100 // row 5 (neg): unregistered extension refused
101 dg_write("/tmp/dv_t.xyz" as *u8, "nope\n" as *u8)
102 let rc5: i64=dg_runv(dv, dg_args("/tmp/dv_t.xyz" as *u8, "/tmp/dv_x.html" as *u8, 0 as *u8), "/tmp/dv_r5.txt" as *u8)
103 r=0; if rc5==3 { if dg_has("/tmp/dv_r5.txt" as *u8, "DOC-VIEW-UNSUPPORTED ext=xyz" as *u8)==1 { r=1 } }
104 pass=pass+dg_row("unsupported-refused" as *u8, r)
105
106 let permil: i64=(pass*1000)/5
107 let logfd: i64=sys_openat_append("knowledge/status/vizsla_gate.log" as *u8, 0x1a4)
108 var fdi: i64=0
109 while fdi<2 {
110 var fd: i64=1; if fdi==1 { fd=logfd }
111 if fd>0 {
112 let line: *u8=sys_mmap(256); var o: i64=0
113 o=dg_cat(line,o,"DOC-VIEW-GATE epoch=" as *u8); o=dg_catn(line,o,sys_now_realtime_sec())
114 o=dg_cat(line,o," rows=5 pass=" as *u8); o=dg_catn(line,o,pass)
115 o=dg_cat(line,o," permil=" as *u8); o=dg_catn(line,o,permil)
116 if pass==5 { o=dg_cat(line,o," verdict=GREEN\n" as *u8) } else { o=dg_cat(line,o," verdict=RED\n" as *u8) }
117 sys_write(fd, line, o)
118 }
119 fdi=fdi+1
120 }
121 if logfd>0 { sys_close(logfd) }
122 // MIGRATED onto nx_gate_verdict by hand (D001). The local helpers were renamed gv_->dg_ because
123 // this gate had named its OWN helpers gv_*, colliding with the base class -- which is exactly why
124 // it could never be migrated automatically. Every check row above is untouched, so the PASS/FAIL
125 // vector cannot change; only the hand-rolled verdict emission is replaced by the shared base class.
126 let ctr__dry: *i64 = gv_ctr()
127 ctr__dry[0] = pass
128 ctr__dry[1] = 5
129 let rc__dry: i64 = gv_verdict("DOC-VIEW-GATE" as *u8, ctr__dry, "teeth unchanged; verdict emission migrated onto the shared base class" as *u8)
130 sys_exit(rc__dry)
131 return rc__dry
132}