code wiki / _hdl_build / nx_aw_browser_gate.nx
nx_aw_browser_gate.nx source
↩ module page · 212 lines · 11283 B
1// nx_aw_browser_gate.nx -- SOVEREIGN-BROWSER referee for the andelinwest client surfaces (operator:
2// "make sure that everything can work on the nishi os and nishi browser sovereign"). Drives the REAL
3// browser core (br_layout / br_draw_fb_at / br_hit_link -- the ONE core Linux/Windows/NishiOS ship)
4// over the REAL emitted pages (web_assets/sites/andelinwest, the same bytes nx_siteedit publishes):
5// T1 index.html LAYS OUT (ok=1, real page height)
6// T2 the whole-site NAV is CLICKABLE: a doc-coordinate sweep of br_hit_link finds ALL FOUR
7// /practice/<slug>.html links (what a NishiOS user can click to navigate -- GET-nav needs no JS)
8// T3 a practice page lays out (ok=1) -- the click target renders
9// T4 index RENDERS to a framebuffer with real ink (drawn px > threshold), receipt PNG written to
10// knowledge/status/aw_browser_index.png (eyeball evidence)
11// T5 NEG: a click in the dead gutter hits NO link (hit-testing is real, not always-true)
12// T6 HONEST GAP ROWS (documented, not asserted green): the portals' INTERACTIVE flows (login
13// typing, form POST, fetch/sessionStorage JS) are BROWSER-ENGINE rungs the core lacks today --
14// text-input + form-submit + a session carrier. Public GET surfaces (site pages, /search SERPs,
15// /doc views, portal shells as READ-ONLY pages) are what works now. This gate prints the map.
16// GREEN iff T1-T5 pass. Appends knowledge/status/aw_browser_gate.log. license_tier: ORIGINAL
17// expect_exit: 0
18import "nx_browser_render.nx"
19
20func g_w(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_n(v: i64) -> i64 { let b: *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{b[i]=t[k-1-i];i=i+1} sys_write(1,b,k); return 0 }
22func g_lw(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_len(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
24// href bytes at (off,len) in buf equal NUL-terminated lit?
25func g_href_eq(buf: *u8, off: i64, len: i64, lit: *u8) -> i64 {
26 let ln: i64 = g_len(lit)
27 if len != ln { return 0 }
28 var i: i64 = 0
29 while i < ln { if (buf[off+i] as i64) != (lit[i] as i64) { return 0 } i = i + 1 }
30 return 1
31}
32
33const AWB_W: i64 = 500
34
35// Walk the layout-box table (the SAME table the shipped browser click path consults via
36// br_hit_link) and return 1 iff a box carries `href` AND a real clickable rect, ALSO
37// verifying br_hit_link resolves at that box's own coordinates (the true click).
38func g_link_clickable(p: *Page, href: *u8) -> i64 {
39 let ho: *i64 = sys_mmap(16) as *i64
40 let hl: *i64 = sys_mmap(16) as *i64
41 var i: i64 = 0
42 while i < p.tree.count {
43 if p.bhref_off[i] >= 0 {
44 if g_href_eq(p.buf, p.bhref_off[i], p.bhref_len[i], href) == 1 {
45 let bb: *LayoutBox = ((p.tree.boxes as i64) + i*NX_LAYOUT_BOX_BYTES) as *LayoutBox
46 // a user clicks somewhere on the VISIBLE card: probe a small band from the
47 // anchor's origin downward (container-anchor content starts a line below it).
48 var dy: i64 = 2
49 while dy < 96 {
50 if br_hit_link(p, bb.x + 10, bb.y + dy, ho, hl) == 1 {
51 if g_href_eq(p.buf, ho[0], hl[0], href) == 1 { return 1 }
52 }
53 dy = dy + 6
54 }
55 }
56 }
57 i = i + 1
58 }
59 return 0
60}
61
62// D-probe: does a page shape leave the card link clickable? Reports BOTH halves:
63// href-in-box-table (with the box rect) AND hit-resolution at that rect.
64func d_probe(label: *u8, htm: *u8) -> i64 {
65 let p: *Page = sys_mmap(NX_PAGE_BYTES) as *Page
66 p.raw = htm
67 var n: i64 = 0
68 while htm[n] != (0 as u8) { n = n + 1 }
69 p.raw_len = n
70 br_layout(p, 500)
71 let href: *u8 = "/practice/family-law.html" as *u8
72 var in_table: i64 = 0
73 var bx: i64 = 0 - 1
74 var by: i64 = 0 - 1
75 var bw: i64 = 0 - 1
76 var bh: i64 = 0 - 1
77 var i: i64 = 0
78 while i < p.tree.count {
79 if p.bhref_off[i] >= 0 {
80 if g_href_eq(p.buf, p.bhref_off[i], p.bhref_len[i], href) == 1 {
81 in_table = 1
82 let bb: *LayoutBox = ((p.tree.boxes as i64) + i*NX_LAYOUT_BOX_BYTES) as *LayoutBox
83 bx = bb.x; by = bb.y; bw = bb.w; bh = bb.h
84 }
85 }
86 i = i + 1
87 }
88 let ok: i64 = g_link_clickable(p, href)
89 g_w(" D " as *u8); g_w(label); g_w(": in_table=" as *u8); g_n(in_table)
90 g_w(" rect=" as *u8); g_n(bx); g_w("," as *u8); g_n(by); g_w("," as *u8); g_n(bw); g_w("x" as *u8); g_n(bh)
91 g_w(" clickable=" as *u8); g_n(ok); g_w(" (boxes=" as *u8); g_n(p.tree.count); g_w(")\n" as *u8)
92 // topology dump: idx parent kind rect href?
93 var d: i64 = 0
94 while d < p.tree.count {
95 let db: *LayoutBox = ((p.tree.boxes as i64) + d*NX_LAYOUT_BOX_BYTES) as *LayoutBox
96 g_w(" box " as *u8); g_n(d); g_w(" par=" as *u8); g_n(db.parent_idx)
97 g_w(" kind=" as *u8); g_n(db.kind)
98 g_w(" rect=" as *u8); g_n(db.x); g_w("," as *u8); g_n(db.y); g_w("," as *u8); g_n(db.w); g_w("x" as *u8); g_n(db.h)
99 g_w(" href=" as *u8); if p.bhref_off[d] >= 0 { g_n(1) } else { g_n(0) }
100 g_w("\n" as *u8)
101 d = d + 1
102 }
103 return ok
104}
105
106func main() -> i64 {
107 g_w("=== AW BROWSER GATE: the client surfaces on the SOVEREIGN browser core (the NishiOS core) ===\n" as *u8)
108 var pass: i64 = 0
109
110 // localize: two sibling cards -- do the anchors share a parent, or wrap individually?
111 d_probe("two-cards " as *u8, "<!doctype html><html><head><title>t</title></head><body><div class=\"grid\"><a class=\"card\" href=\"/practice/family-law.html\"><h3>Family Law</h3><p>desc one</p></a><a class=\"card\" href=\"/practice/estate-planning.html\"><h3>Estate</h3><p>desc two</p></a></div></body></html>\x00" as *u8)
112
113
114 // T1: the REAL emitted index lays out (the same bytes nx_siteedit publishes)
115 let lp: *i64 = sys_mmap(16) as *i64
116 let html: *u8 = sys_read_file("web_assets/sites/andelinwest/index.html\x00" as *u8, lp)
117 var t1: i64 = 0
118 let page: *Page = sys_mmap(NX_PAGE_BYTES) as *Page
119 if lp[0] > 0 {
120 page.raw = html
121 page.raw_len = lp[0]
122 br_layout(page, AWB_W)
123 if page.ok == 1 { if page.page_h > 400 { t1 = 1 } }
124 }
125 pass = pass + t1
126 g_w(" T1 index.html lays out (ok, page_h=" as *u8); g_n(page.page_h); g_w("): " as *u8)
127 if t1 == 1 { g_w("PASS\n" as *u8) } else { g_w("FAIL\n" as *u8) }
128
129 // T2: every practice link exists as a box the browser click path resolves at its own rect
130 // (the exact navigation a NishiOS user performs -- box-walk + br_hit_link, the U5 idiom)
131 let f_fam: i64 = g_link_clickable(page, "/practice/family-law.html" as *u8)
132 let f_est: i64 = g_link_clickable(page, "/practice/estate-planning.html" as *u8)
133 let f_bus: i64 = g_link_clickable(page, "/practice/business-law.html" as *u8)
134 let f_inj: i64 = g_link_clickable(page, "/practice/personal-injury.html" as *u8)
135 var t2: i64 = 0
136 if f_fam == 1 { if f_est == 1 { if f_bus == 1 { if f_inj == 1 { t2 = 1 } } } }
137 pass = pass + t2
138 g_w(" T2 all 4 practice links click-resolve at their boxes (fam/est/bus/inj=" as *u8)
139 g_n(f_fam); g_n(f_est); g_n(f_bus); g_n(f_inj); g_w("): " as *u8)
140 if t2 == 1 { g_w("PASS\n" as *u8) } else { g_w("FAIL\n" as *u8) }
141
142 // T3: the click target (family-law page) lays out
143 let lp2: *i64 = sys_mmap(16) as *i64
144 let html2: *u8 = sys_read_file("web_assets/sites/andelinwest/practice/family-law.html\x00" as *u8, lp2)
145 var t3: i64 = 0
146 let p2: *Page = sys_mmap(NX_PAGE_BYTES) as *Page
147 if lp2[0] > 0 {
148 p2.raw = html2
149 p2.raw_len = lp2[0]
150 br_layout(p2, AWB_W)
151 if p2.ok == 1 { if p2.page_h > 300 { t3 = 1 } }
152 }
153 pass = pass + t3
154 g_w(" T3 practice page lays out (page_h=" as *u8); g_n(p2.page_h); g_w("): " as *u8)
155 if t3 == 1 { g_w("PASS\n" as *u8) } else { g_w("FAIL\n" as *u8) }
156
157 // T4: render the index viewport; count drawn (non-white) pixels; write the receipt PNG
158 let W: i64 = AWB_W
159 let H: i64 = 400
160 let fb: *Framebuffer = sys_mmap(NX_FRAMEBUFFER_BYTES) as *Framebuffer
161 let px: *u8 = sys_mmap(W*H*4 + 64)
162 nx_framebuffer_init(fb, px, W, H)
163 br_draw_fb_at(fb, page, W, "https://andelinwest.com/\x00" as *u8, 24, 1, 0)
164 var ink: i64 = 0
165 var iy: i64 = 0
166 while iy < H {
167 var ix: i64 = 0
168 while ix < W {
169 let o: i64 = (iy*W + ix)*4
170 if (px[o] as i64) < 240 { ink = ink + 1 }
171 ix = ix + 1
172 }
173 iy = iy + 1
174 }
175 let rgb: *u8 = sys_mmap(W*H*3 + 64)
176 var pxi: i64 = 0
177 while pxi < W*H { rgb[pxi*3]=px[pxi*4]; rgb[pxi*3+1]=px[pxi*4+1]; rgb[pxi*3+2]=px[pxi*4+2]; pxi=pxi+1 }
178 nx_png_write_rgb("knowledge/status/aw_browser_index.png\x00" as *u8, rgb, W, H)
179 var t4: i64 = 0
180 if ink > 5000 { t4 = 1 }
181 pass = pass + t4
182 g_w(" T4 index renders with real ink (drawn px=" as *u8); g_n(ink); g_w(", PNG receipt written): " as *u8)
183 if t4 == 1 { g_w("PASS\n" as *u8) } else { g_w("FAIL\n" as *u8) }
184
185 // T5 NEG: a click far right of the content column hits nothing
186 var t5: i64 = 0
187 if br_hit_link(page, AWB_W - 2, page.page_h - 2, ho, hl) == 0 { t5 = 1 }
188 pass = pass + t5
189 g_w(" T5 NEG dead-gutter click hits no link: " as *u8)
190 if t5 == 1 { g_w("PASS\n" as *u8) } else { g_w("FAIL\n" as *u8) }
191
192 // T6: the honest interaction-gap map (documented rows, not asserted)
193 g_w(" T6 GAP MAP (browser-engine rungs, not portal defects):\n" as *u8)
194 g_w(" works NOW on the sovereign core: site pages + nav clicks, /search SERPs + /doc views\n" as *u8)
195 g_w(" (server-rendered GET), portal shells render read-only.\n" as *u8)
196 g_w(" NEEDS BROWSER RUNGS: text input, form submit (GET/POST), session carrier -> then the\n" as *u8)
197 g_w(" portals' login/upload/compose work JS-free (their APIs are already plain forms + tokens).\n" as *u8)
198
199 g_w("----\nAW-BROWSER rows=5 pass=" as *u8); g_n(pass); g_w("\n" as *u8)
200 let lg: i64 = sys_openat_append("knowledge/status/aw_browser_gate.log" as *u8, 0x1a4)
201 if lg >= 0 {
202 g_lw(lg, "AW-BROWSER index_layout=" as *u8); if t1==1 { g_lw(lg,"1" as *u8) } else { g_lw(lg,"0" as *u8) }
203 g_lw(lg, " nav_links_clickable=" as *u8); if t2==1 { g_lw(lg,"1" as *u8) } else { g_lw(lg,"0" as *u8) }
204 g_lw(lg, " practice_layout=" as *u8); if t3==1 { g_lw(lg,"1" as *u8) } else { g_lw(lg,"0" as *u8) }
205 g_lw(lg, " render_ink=" as *u8); if t4==1 { g_lw(lg,"1" as *u8) } else { g_lw(lg,"0" as *u8) }
206 g_lw(lg, " neg_miss=" as *u8); if t5==1 { g_lw(lg,"1" as *u8) } else { g_lw(lg,"0" as *u8) }
207 if pass == 5 { g_lw(lg, " verdict=GREEN\n" as *u8) } else { g_lw(lg, " verdict=RED\n" as *u8) }
208 sys_close(lg)
209 }
210 if pass == 5 { g_w("AW-BROWSER GREEN (client site navigable on the sovereign core; interaction rungs named)\n" as *u8); sys_exit(0); return 0 }
211 g_w("AW-BROWSER RED\n" as *u8); sys_exit(1); return 1
212}