nx_image_index_gate.nx source
↩ module page · 206 lines · 10553 B
1// nx_image_index_gate.nx -- referee for the REAL-CORPUS ingestor (nx_image_index).
2// Unlike the search gate (synthetic raw-gray buffers), this builds REAL encoded PNG files at runtime
3// (valid signature + IHDR + zlib stored-block IDAT + IEND, with chunk CRC-32s and the zlib Adler-32
4// computed by the shipped substrate primitives -- same technique as nx_png_real_smoke), writes them to
5// /tmp, forks+execs the REAL /tmp/nx_image_index.sov.elf over them, and verifies the produced
6// fingerprint index. Because each PNG is filled RGB=(v,v,v), Rec.709 luma == v, so the FULL decode path
7// (inflate -> unfilter -> RGB -> gray -> dHash) must reproduce the KNOWN dHashes proven in the search
8// gate -- a true end-to-end KAT, checkable by pure string match:
9// row1 grad-up -> dHash 0000000000000000 (decode->gray->dHash correct, end to end)
10// row2 +bright -> dHash 0000000000000000 (brightness invariance survives a real PNG round-trip)
11// row3 grad-down -> dHash ffffffffffffffff (second KAT, opposite extreme)
12// row4 mid -> present and DISTINCT from grad-up
13// row5 corrupt -> SKIPPED (graceful degradation, Cardinal 14 -- one bad file can't abort a crawl)
14// row6 summary -> ingestor exit 0, indexed=4 skipped=1
15// GREEN iff 6/6. Durable verdict appends to knowledge/status/image_index_gate.log. license_tier: ORIGINAL
16import "nx_syscalls.nx"
17import "nx_crc32.nx"
18import "nx_adler32.nx"
19
20func g_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
21func 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 }
22func 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 }
23func 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 }
24func g_strlen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
25
26func g_write_bytes(path: *u8, buf: *u8, n: i64) -> i64 {
27 let fd: i64=sys_openat_wr(path, 0x1a4)
28 if fd<0 { return 0-1 }
29 sys_write(fd, buf, n)
30 sys_close(fd)
31 return 0
32}
33func g_write_file(path: *u8, data: *u8) -> i64 { return g_write_bytes(path, data, g_strlen(data)) }
34func g_read_small(path: *u8, buf: *u8, cap: i64) -> i64 {
35 let fd: i64=sys_openat_rd(path)
36 if fd<0 { return 0 }
37 var total: i64=0
38 var nrd: i64=sys_read(fd, buf, cap)
39 while nrd>0 { total=total+nrd; if total>=cap { nrd=0 } else { nrd=sys_read(fd, ((buf as i64)+total) as *u8, cap-total) } }
40 sys_close(fd)
41 return total
42}
43func g_find(hay: *u8, n: i64, needle: *u8) -> i64 {
44 let nl: i64=g_strlen(needle)
45 if nl==0 { return 0-1 }
46 var i: i64=0
47 while i+nl<=n {
48 var j: i64=0; var hit: i64=1
49 while j<nl { if hay[i+j]!=needle[j] { hit=0; j=nl } else { j=j+1 } }
50 if hit==1 { return i }
51 i=i+1
52 }
53 return 0-1
54}
55func g_contains(hay: *u8, n: i64, needle: *u8) -> i64 { if g_find(hay,n,needle)>=0 { return 1 } return 0 }
56
57// ===== runtime PNG builder (stored zlib block, RGB 8-bit) =====
58func gp_wbe(buf: *u8, off: i64, val: i64) -> i64 {
59 buf[off]=((val>>24)&255) as u8
60 buf[off+1]=((val>>16)&255) as u8
61 buf[off+2]=((val>>8)&255) as u8
62 buf[off+3]=(val&255) as u8
63 return 0
64}
65func gp_val(kind: i64, x: i64, w: i64, bright: i64) -> i64 {
66 var v: i64=0
67 if kind==0 { v=x*4 }
68 if kind==1 { v=(w-1-x)*4 }
69 if kind==3 { v=(x&2)*30 }
70 v=v+bright
71 if v<0 { v=0 }
72 if v>255 { v=255 }
73 return v
74}
75func gp_build(out: *u8, w: i64, h: i64, kind: i64, bright: i64) -> i64 {
76 out[0]=137 as u8; out[1]=80 as u8; out[2]=78 as u8; out[3]=71 as u8
77 out[4]=13 as u8; out[5]=10 as u8; out[6]=26 as u8; out[7]=10 as u8
78 var pos: i64=8
79 // IHDR
80 gp_wbe(out,pos,13); pos=pos+4
81 let ihdr_t: i64=pos
82 out[pos]=73 as u8; out[pos+1]=72 as u8; out[pos+2]=68 as u8; out[pos+3]=82 as u8; pos=pos+4
83 gp_wbe(out,pos,w); pos=pos+4
84 gp_wbe(out,pos,h); pos=pos+4
85 out[pos]=8 as u8; out[pos+1]=2 as u8; out[pos+2]=0 as u8; out[pos+3]=0 as u8; out[pos+4]=0 as u8; pos=pos+5
86 gp_wbe(out,pos, nx_crc32(((out as i64)+ihdr_t) as *u8, 17)); pos=pos+4
87 // IDAT (zlib stored block)
88 let payload_len: i64=h*(1+w*3)
89 let zlib_len: i64=2+5+payload_len+4
90 gp_wbe(out,pos,zlib_len); pos=pos+4
91 let idat_t: i64=pos
92 out[pos]=73 as u8; out[pos+1]=68 as u8; out[pos+2]=65 as u8; out[pos+3]=84 as u8; pos=pos+4
93 out[pos]=0x78 as u8; out[pos+1]=0x01 as u8; pos=pos+2
94 out[pos]=0x01 as u8; pos=pos+1
95 out[pos]=(payload_len&255) as u8; out[pos+1]=((payload_len>>8)&255) as u8; pos=pos+2
96 let nlen: i64=(payload_len^0xFFFF)&0xFFFF
97 out[pos]=(nlen&255) as u8; out[pos+1]=((nlen>>8)&255) as u8; pos=pos+2
98 let payload_off: i64=pos
99 var y: i64=0
100 while y<h {
101 out[pos]=0 as u8; pos=pos+1
102 var x: i64=0
103 while x<w {
104 let v: i64=gp_val(kind,x,w,bright)
105 out[pos]=v as u8; out[pos+1]=v as u8; out[pos+2]=v as u8; pos=pos+3
106 x=x+1
107 }
108 y=y+1
109 }
110 gp_wbe(out,pos, adler32(((out as i64)+payload_off) as *u8, payload_len)); pos=pos+4
111 gp_wbe(out,pos, nx_crc32(((out as i64)+idat_t) as *u8, 4+zlib_len)); pos=pos+4
112 // IEND
113 gp_wbe(out,pos,0); pos=pos+4
114 let iend_t: i64=pos
115 out[pos]=73 as u8; out[pos+1]=69 as u8; out[pos+2]=78 as u8; out[pos+3]=68 as u8; pos=pos+4
116 gp_wbe(out,pos, nx_crc32(((out as i64)+iend_t) as *u8, 4)); pos=pos+4
117 return pos
118}
119
120func g_run(corpus: *u8, outidx: *u8, outcap: *u8) -> i64 {
121 let pid: i64=sys_fork()
122 if pid==0 {
123 let out: i64=sys_openat_wr(outcap, 0x1a4)
124 if out>=0 { sys_dup3(out, 1, 0) }
125 let argv: *i64=sys_mmap(8*6) as *i64
126 argv[0]="/tmp/nx_image_index.sov.elf" as *u8 as i64
127 argv[1]=corpus as i64; argv[2]=outidx as i64; argv[3]=0
128 let envp: *i64=sys_mmap(16) as *i64; envp[0]="PATH=/usr/bin:/bin" as *u8 as i64; envp[1]=0
129 sys_execve("/tmp/nx_image_index.sov.elf" as *u8, argv, envp)
130 sys_exit(127)
131 }
132 let st: *i64=sys_mmap(16) as *i64
133 sys_wait4(pid, st, 0)
134 if (st[0]&0x7f)!=0 { return 128+(st[0]&0x7f) }
135 return (st[0]>>8)&0xff
136}
137
138func main() -> i64 {
139 g_puts("=== IMAGE INDEX GATE (real PNG decode -> gray -> dHash KAT + brightness invariance + graceful skip) ===\n" as *u8)
140 let W: i64=16
141 let H: i64=16
142 let pb: *u8=sys_mmap(4096)
143 var sz: i64=0
144
145 sz=gp_build(pb, W, H, 0, 0); g_write_bytes("/tmp/im_up.png" as *u8, pb, sz)
146 sz=gp_build(pb, W, H, 0, 40); g_write_bytes("/tmp/im_bright.png" as *u8, pb, sz)
147 sz=gp_build(pb, W, H, 1, 0); g_write_bytes("/tmp/im_down.png" as *u8, pb, sz)
148 sz=gp_build(pb, W, H, 3, 0); g_write_bytes("/tmp/im_mid.png" as *u8, pb, sz)
149 // corrupt / not-a-PNG file (graceful-skip neg-control)
150 g_write_file("/tmp/im_junk.bin" as *u8, "not-a-png" as *u8)
151
152 g_write_file("/tmp/im_corpus.tsv" as *u8,
153 "/C/up\t/tmp/im_up.png\n/C/bright\t/tmp/im_bright.png\n/C/down\t/tmp/im_down.png\n/C/mid\t/tmp/im_mid.png\n/C/junk\t/tmp/im_junk.bin\n" as *u8)
154
155 let rc: i64=g_run("/tmp/im_corpus.tsv" as *u8, "/tmp/im_real.idx" as *u8, "/tmp/im_idx_out.txt" as *u8)
156
157 let ibuf: *u8=sys_mmap(65536)
158 let ni: i64=g_read_small("/tmp/im_real.idx" as *u8, ibuf, 65536)
159 let obuf: *u8=sys_mmap(8192)
160 let no: i64=g_read_small("/tmp/im_idx_out.txt" as *u8, obuf, 8192)
161
162 g_puts("---- produced fingerprint index ----\n" as *u8)
163 sys_write(1, ibuf, ni)
164 g_puts("---- ingestor stdout ----\n" as *u8)
165 sys_write(1, obuf, no)
166 g_puts("----\n" as *u8)
167
168 var pass: i64=0
169 let rows: i64=6
170
171 let r1: i64=g_contains(ibuf, ni, "/C/up\t0000000000000000\t" as *u8)
172 g_puts(" row1 grad-up KAT -> dHash 0000..0? " as *u8); g_num(r1)
173 if r1==1 { pass=pass+1; g_puts(" PASS (decode->gray->dHash correct end-to-end)\n" as *u8) } else { g_puts(" FAIL\n" as *u8) }
174
175 let r2: i64=g_contains(ibuf, ni, "/C/bright\t0000000000000000\t" as *u8)
176 g_puts(" row2 +brightness PNG -> dHash 0000..0? " as *u8); g_num(r2)
177 if r2==1 { pass=pass+1; g_puts(" PASS (invariance survives full PNG round-trip)\n" as *u8) } else { g_puts(" FAIL\n" as *u8) }
178
179 let r3: i64=g_contains(ibuf, ni, "/C/down\tffffffffffffffff\t" as *u8)
180 g_puts(" row3 grad-down KAT -> dHash ffff..f? " as *u8); g_num(r3)
181 if r3==1 { pass=pass+1; g_puts(" PASS\n" as *u8) } else { g_puts(" FAIL\n" as *u8) }
182
183 let r4a: i64=g_contains(ibuf, ni, "/C/mid\t" as *u8)
184 let r4b: i64=g_contains(ibuf, ni, "/C/mid\t0000000000000000" as *u8)
185 g_puts(" row4 mid distinct -> present? " as *u8); g_num(r4a); g_puts(" !=grad-up? " as *u8); g_num(1-r4b)
186 if r4a==1 { if r4b==0 { pass=pass+1; g_puts(" PASS\n" as *u8) } else { g_puts(" FAIL\n" as *u8) } } else { g_puts(" FAIL\n" as *u8) }
187
188 let r5: i64=g_contains(ibuf, ni, "/C/junk" as *u8)
189 g_puts(" row5 corrupt skipped -> absent? " as *u8); g_num(1-r5)
190 if r5==0 { pass=pass+1; g_puts(" PASS (graceful degradation)\n" as *u8) } else { g_puts(" FAIL (corrupt file leaked into index!)\n" as *u8) }
191
192 let r6a: i64=g_contains(obuf, no, "indexed=4" as *u8)
193 let r6b: i64=g_contains(obuf, no, "skipped=1" as *u8)
194 g_puts(" row6 summary -> exit " as *u8); g_num(rc); g_puts(" indexed=4? " as *u8); g_num(r6a); g_puts(" skipped=1? " as *u8); g_num(r6b)
195 if rc==0 { if r6a==1 { if r6b==1 { pass=pass+1; g_puts(" PASS\n" as *u8) } else { g_puts(" FAIL\n" as *u8) } } else { g_puts(" FAIL\n" as *u8) } } else { g_puts(" FAIL\n" as *u8) }
196
197 g_puts("----\nIMAGE-INDEX-GATE rows=" as *u8); g_num(rows); g_puts(" pass=" as *u8); g_num(pass); g_puts("\n" as *u8)
198 let lg: i64=sys_openat_append("knowledge/status/image_index_gate.log" as *u8, 0x1a4)
199 if lg>=0 {
200 g_w(lg, "IMAGE-INDEX-GATE rows=" as *u8); g_wn(lg, rows); g_w(lg, " pass=" as *u8); g_wn(lg, pass)
201 if pass==rows { g_w(lg, " verdict=GREEN\n" as *u8) } else { g_w(lg, " verdict=RED\n" as *u8) }
202 sys_close(lg)
203 }
204 if pass==rows { g_puts("IMAGE-INDEX-GATE GREEN\n" as *u8); sys_exit(0); return 0 }
205 g_puts("IMAGE-INDEX-GATE RED\n" as *u8); sys_exit(1); return 1
206}