nx_manga_bubble_gate.nx source
↩ module page · 147 lines · 7435 B
1// nx_manga_bubble_gate.nx -- REFEREE for R2 (nx_manga_bubble). END-TO-END: forks the PROMOTED elf with a
2// real argv and reads the PNG it produced back through our own decoder, so it measures the shipped binary
3// and not a convenient in-process copy of the logic.
4// It proves the DONE-RULE that was pre-declared on /compare/mangagen before the organ existed:
5// "Bubble geometry + tails + sovereign TTF raster; overflow REFUSES, never silently clips."
6// TWO NEGATIVE CONTROLS, because a green that never had a red is unverified:
7// neg-control-white -- the same ink counter over a known-blank buffer must return ZERO, so the
8// drew-something teeth cannot be tautologies that pass on any image.
9// neg-control-overflow -- text that cannot fit must REFUSE (non-zero) AND leave NO output file,
10// which is the difference between refusing and clipping.
11// license_tier: ORIGINAL expect_exit: 0
12import "nx_str.nx"
13import "nx_syscalls.nx"
14import "nx_tool_run.nx"
15import "nx_img_to_rgb.nx"
16import "nx_gate_verdict.nx"
17const MBG_CAP: i64 = 65536
18const MBG_W: i64 = 900
19const MBG_H: i64 = 600
20// count pixels darker than a threshold inside a rect -- the ink detector both teeth and the control share
21func mbg_ink(rgb: *u8, w: i64, h: i64, x0: i64, y0: i64, x1: i64, y1: i64) -> i64 {
22 var c: i64 = 0
23 var y: i64 = y0
24 while y < y1 {
25 if y >= 0 { if y < h {
26 var x: i64 = x0
27 while x < x1 {
28 if x >= 0 { if x < w {
29 let o: i64 = (y * w + x) * 3
30 let r: i64 = rgb[o] as i64
31 let g: i64 = rgb[o+1] as i64
32 let b: i64 = rgb[o+2] as i64
33 if r + g + b < 300 { c = c + 1 }
34 } }
35 x = x + 1
36 }
37 } }
38 y = y + 1
39 }
40 return c
41}
42func mbg_exists(p: *u8) -> i64 {
43 let fd: i64 = sys_openat_rd(p)
44 if fd < 0 { return 0 }
45 sys_close(fd)
46 return 1
47}
48func main(argc: i64, argv: *i64) -> i64 {
49 let ctr: *i64 = gv_ctr()
50 gv_head("nx_manga_bubble -- a bubble with a tail and real lettering, and an overflow that REFUSES" as *u8)
51 // ⚠ABSOLUTE, deliberately. A relative "../" resolved against whatever CWD the runner chose, the fork
52 // failed, and EVERY run came back non-zero -- which made the two neg-controls pass VACUOUSLY while the
53 // gate measured nothing at all. ★A GUARD THAT REFUSES EVERYTHING PASSES EVERY NEGATIVE TEST; only the
54 // positive tooth (T1) could tell the difference, and it is why T1 exists.
55 // SUBJECT PATH: argv[1] when handed one, else the promoted elf. Same fix, same reason as
56 // nx_manga_script_gate (MEASURED 2026-09-05): nx_gate_bite rebuilds the SUBJECT per mutant and
57 // hands its path as argv[1]. A gate that declares argv and then forks a HARDCODED serving-root
58 // path re-tests the PRISTINE promoted binary every time, so every mutant SURVIVES and the gate
59 // reads GREEN while proving nothing. On the sibling gate that pattern measured 7 valid mutants /
60 // 0 killed; the one-line fix took it to a real KILL and verdict=GREEN non-vacuity proven.
61 // The fallback keeps every existing caller working: no argv means the promoted binary, as before.
62 var ELF: *u8 = "/volume1/homes/elderwesto/nishihost/nx_manga_bubble.elf" as *u8
63 if argc > 1 { ELF = argv[1] as *u8 }
64 let OUT: *u8 = "/tmp/mbg_fit.png" as *u8
65 let OUT2: *u8 = "/tmp/mbg_overflow.png" as *u8
66 let out: *u8 = sys_mmap(MBG_CAP)
67 let ol: *i64 = sys_mmap(16) as *i64
68 let av: *i64 = sys_mmap(256) as *i64
69 sys_unlinkat(OUT)
70 sys_unlinkat(OUT2)
71 // ---- run 1: dialogue that FITS -------------------------------------------------------------
72 av[0] = ELF as i64
73 av[1] = "blank:900x600" as i64
74 av[2] = OUT as i64
75 av[3] = "450" as i64
76 av[4] = "240" as i64
77 av[5] = "250" as i64
78 av[6] = "150" as i64
79 av[7] = "430" as i64
80 av[8] = "520" as i64
81 av[9] = "6" as i64
82 av[10] = "22" as i64
83 av[11] = "WE SHIP" as i64
84 av[12] = "OR WE" as i64
85 av[13] = "REFUSE" as i64
86 av[14] = 0
87 let rc1: i64 = tr_run_capture(ELF, av, out, MBG_CAP, ol)
88 var t1: i64 = 0
89 if rc1 == 0 { t1 = 1 }
90 gv_check("T1 BITE: a bubble whose text fits is drawn and the organ exits clean" as *u8, t1, ctr)
91 var t2: i64 = 0
92 if mbg_exists(OUT) == 1 { t2 = 1 }
93 gv_check("T2 the page artifact actually reached disk" as *u8, t2, ctr)
94 // ---- decode the shipped artifact back through our own decoder ------------------------------
95 let wh: *i64 = sys_mmap(32) as *i64
96 wh[0] = 0
97 wh[1] = 0
98 var rgb: *u8 = 0 as *u8
99 if t2 == 1 { rgb = nx_img_to_rgb(OUT, wh) }
100 var t3: i64 = 0
101 if (rgb as i64) != 0 { if wh[0] == MBG_W { if wh[1] == MBG_H { t3 = 1 } } }
102 gv_check("T3 it decodes at the page geometry it was asked for" as *u8, t3, ctr)
103 // ---- the drawing teeth --------------------------------------------------------------------
104 var ring: i64 = 0
105 var letter: i64 = 0
106 var tail: i64 = 0
107 if t3 == 1 {
108 // a band across the LEFT edge of the ring: cx-rx is 200, so 190..215 straddles the stroke
109 ring = mbg_ink(rgb, MBG_W, MBG_H, 190, 230, 215, 250)
110 // the inner box, where the lettering lives
111 letter = mbg_ink(rgb, MBG_W, MBG_H, 330, 180, 570, 300)
112 // between the ring bottom (cy+ry = 390) and the tip (520): only the tail can ink this
113 tail = mbg_ink(rgb, MBG_W, MBG_H, 410, 400, 450, 500)
114 }
115 var t4: i64 = 0
116 if ring > 0 { t4 = 1 }
117 gv_check("T4 GEOMETRY: the bubble outline is inked on the ring" as *u8, t4, ctr)
118 var t5: i64 = 0
119 if letter > 0 { t5 = 1 }
120 gv_check("T5 LETTERING: sovereign glyphs are inked inside the bubble" as *u8, t5, ctr)
121 var t6: i64 = 0
122 if tail > 0 { t6 = 1 }
123 gv_check("T6 TAIL: ink between the ring and the tip -- the balloon points at its speaker" as *u8, t6, ctr)
124 // ---- neg-control-white: the SAME counter over a known-blank buffer must return ZERO ---------
125 let white: *u8 = sys_mmap(MBG_W * MBG_H * 3 + 64)
126 var i: i64 = 0
127 let n3: i64 = MBG_W * MBG_H * 3
128 while i < n3 { white[i] = 255 as u8; i = i + 1 }
129 let ctrl: i64 = mbg_ink(white, MBG_W, MBG_H, 190, 230, 215, 250) + mbg_ink(white, MBG_W, MBG_H, 330, 180, 570, 300) + mbg_ink(white, MBG_W, MBG_H, 410, 400, 450, 500)
130 var t7: i64 = 0
131 if ctrl == 0 { t7 = 1 }
132 gv_check("T7 neg-control-white: the ink counter returns ZERO on blank paper, so T4-T6 are not tautologies" as *u8, t7, ctr)
133 // ---- neg-control-overflow: text that cannot fit must REFUSE, and leave nothing behind -------
134 av[2] = OUT2 as i64
135 av[5] = "90" as i64
136 av[6] = "60" as i64
137 av[11] = "THIS SENTENCE IS FAR TOO LONG TO EVER FIT INSIDE A BALLOON THIS SMALL AND MUST BE REFUSED" as i64
138 av[12] = 0
139 let rc2: i64 = tr_run_capture(ELF, av, out, MBG_CAP, ol)
140 var t8: i64 = 0
141 if rc2 != 0 { t8 = 1 }
142 gv_check("T8 neg-control-overflow: text that cannot fit REFUSES instead of returning success" as *u8, t8, ctr)
143 var t9: i64 = 0
144 if mbg_exists(OUT2) == 0 { t9 = 1 }
145 gv_check("T9 the refusal wrote NO page -- refusing is not clipping, and leaves no half-drawn artifact" as *u8, t9, ctr)
146 return gv_verdict("MANGA-BUBBLE-GATE" as *u8, ctr, "tails, sovereign lettering, and an overflow that refuses rather than clips" as *u8)
147}