code wiki / _hdl_build / _wiki_integrate_gate.nx

_wiki_integrate_gate.nx source

↩ module page · 274 lines · 14362 B

1// _wiki_integrate_gate.nx -- WIKI R4 INTEGRATION GATE. 2// 3// Re-proves, from a REAL run (never a fabricated GREEN), that the wiki R4 4// navigation organs are WIRED INTO THE LIVE SERVED PAGE and that the latent 5// wikilink-scan render bug is dead. Judged on GROUND-TRUTH SUBSTRINGS in the 6// actually-served HTML (driven through the SAME handlers the daemon forks -- 7// nx_wiki_doc_handle + the /wiki/graph route handler), never a bare rc==const. 8// 9// SEED a doc store with two pages: 10// doc-one -- "# Doc One Title\n## Section A\n...[[doc-two]]..." (has a 11// heading hierarchy AND a wikilink to doc-two; the page under 12// test for TOC + wikilink rendering). 13// doc-two -- "# Doc Two\nDoc two links back to [[doc-one]]." (links TO 14// doc-one, so doc-one's served page shows a backlink to it). 15// 16// toc_live doc-one's served <article> carries <nav class="nx-toc" AND a 17// heading stamped id="section-a" (the TOC built from the body + 18// the anchor id injected onto <h2>Section A</h2>). 19// backlinks_live doc-one's served HTML carries <aside class="nx-backlinks" AND 20// the linking slug "doc-two" (the "what links here" inversion, 21// computed from the real page bodies in the store). 22// wikilink_fixed the [[doc-two]] in doc-one renders to a correct 23// <a href="/wiki/doc-two... OR a clean broken-span 24// <span class="wikilink-broken">[[doc-two]]</span>, with NO 25// garbled bytes -- proving the single-exit scan froze the link 26// end correctly (the bug emitted a wrong name length -> garble). 27// graph_route driving the /wiki/graph handler returns HTML with <svg and 28// NO <script (the static, JS-free link-graph view). 29// 30// Verdict line (stdout + knowledge/status/wiki_integrate_gate.log): 31// WIKIINTEGRATE toc_live=<0|1> backlinks_live=<0|1> wikilink_fixed=<0|1> 32// graph_route=<0|1> verdict=GREEN|RED 33// 34// Pure NishiLang, NO SQL, NO .sh/.py/.js, no new .tsv/.conf. nx_sites_daemon 35// UNTOUCHED. Imports the served handler + the route library under test; each 36// shared base module resolves via a single canonical path (the resolver 37// canonicalizes wiki/-prefixed vs bare) to avoid the nxasm rc6 double-import. 38// license_tier: ORIGINAL 39import "nx_syscalls.nx" 40import "wiki/nx_wiki_index_builder.nx" 41import "wiki/nx_wiki_doc_handler.nx" 42import "wiki/nx_wiki_routes.nx" 43import "wiki/nx_artifact_store.nx" 44 45const WIG_LOG: *u8 = "knowledge/status/wiki_integrate_gate.log" 46const WIG_RESP_CAP: i64 = 2097152 // 2 MiB served-response buffer 47 48// ===== io helpers (mirror _wiki_backlinks_gate.nx) =========================== 49func wig_w(fd: i64, s: *u8) -> i64 { 50 var n: i64 = 0 51 while s[n] != (0 as u8) { n = n + 1 } 52 sys_write(fd, s, n) 53 return 0 54} 55func wig_n(fd: i64, v: i64) -> i64 { 56 let bb: *u8 = sys_mmap(28) 57 var m: i64 = v 58 if m < 0 { m = 0 - m; sys_write(fd, "-" as *u8, 1) } 59 let t: *u8 = sys_mmap(28) 60 var k: i64 = 0 61 if m == 0 { t[0] = 48 as u8; k = 1 } 62 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 63 var i: i64 = 0 64 while i < k { bb[i] = t[k - 1 - i]; i = i + 1 } 65 sys_write(fd, bb, k) 66 return 0 67} 68// write to BOTH stdout (gate evidence) and the durable log 69func wig_w2(lfd: i64, s: *u8) -> i64 { wig_w(1, s); if lfd >= 0 { wig_w(lfd, s) } return 0 } 70func wig_n2(lfd: i64, v: i64) -> i64 { wig_n(1, v); if lfd >= 0 { wig_n(lfd, v) } return 0 } 71func wig_p(s: *u8) -> i64 { wig_w(1, s); return 0 } 72func wig_pn(v: i64) -> i64 { wig_n(1, v); return 0 } 73func wig_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 74 75// ===== GROUND-TRUTH substring search ========================================= 76func wig_find(hay: *u8, hn: i64, needle: *u8) -> i64 { 77 let nn: i64 = wig_slen(needle) 78 if nn == 0 { return 0 - 1 } 79 if nn > hn { return 0 - 1 } 80 var i: i64 = 0 81 let last: i64 = hn - nn 82 while i <= last { 83 var j: i64 = 0 84 var eq: i64 = 1 85 while j < nn { 86 if eq == 1 { if hay[i + j] != needle[j] { eq = 0 } } 87 j = j + 1 88 } 89 if eq == 1 { return i } 90 i = i + 1 91 } 92 return 0 - 1 93} 94func wig_has(hay: *u8, hn: i64, needle: *u8) -> i64 { 95 if wig_find(hay, hn, needle) >= 0 { return 1 } 96 return 0 97} 98 99func main() -> i64 { 100 wig_p("WIKIINTEGRATE-GATE: start (R4 nav wired into served page + scan-bug kill)\n" as *u8) 101 102 // ===== SEED a doc store with doc-one / doc-two =========================== 103 let store: *NxWikiDocStore = sys_mmap(2048) as *NxWikiDocStore 104 let rc_init: i64 = nx_wiki_doc_store_init(store, 16, 4096, 4096, 65536) 105 wig_p(" store_init rc=" as *u8); wig_pn(rc_init); wig_p("\n" as *u8) 106 107 // doc-one: heading hierarchy (# Title / ## Section A) + a [[doc-two]] link. 108 // Lengths computed (never hardcoded) so the body is never truncated mid-link. 109 let one_body: *u8 = "# Doc One Title\n\n## Section A\n\nBody of section a. See [[doc-two]] for more.\n\n## Section B\n\nMore body.\n" as *u8 110 let one_rid: i64 = nx_wiki_doc_store_add(store, 111 "Doc One Title" as *u8, 13, "/wiki/doc-one" as *u8, 13, one_body, wig_slen(one_body)) 112 // doc-two: links BACK to doc-one (so doc-one shows a backlink from doc-two). 113 let two_body: *u8 = "# Doc Two\n\nDoc two links back to [[doc-one]] here.\n" as *u8 114 let two_rid: i64 = nx_wiki_doc_store_add(store, 115 "Doc Two" as *u8, 7, "/wiki/doc-two" as *u8, 13, two_body, wig_slen(two_body)) 116 wig_p(" seeded rowids: doc-one=" as *u8); wig_pn(one_rid) 117 wig_p(" doc-two=" as *u8); wig_pn(two_rid) 118 wig_p(" doc_count=" as *u8); wig_pn(nx_wiki_doc_store_count(store)); wig_p("\n" as *u8) 119 120 // ===== RENDER doc-one via the REAL served handler ======================== 121 let url: *u8 = "/wiki/doc-one" as *u8 122 let url_n: i64 = 13 123 let resp: *u8 = sys_mmap(WIG_RESP_CAP) 124 let resp_n: *i64 = (sys_mmap(8)) as *i64 125 resp_n[0] = 0 126 // artifact_store = 0: the doc handler treats a null artifact store as a 127 // graceful no-op (no pipeline banner), per Cardinal 14 -- the page still 128 // renders. This keeps the gate focused on the R4 nav wiring. 129 let h_rc: i64 = nx_wiki_doc_handle(store, 0 as *NxArtifactStore, url, url_n, 130 resp, WIG_RESP_CAP, resp_n) 131 let hn: i64 = resp_n[0] 132 wig_p(" doc-one handle rc=" as *u8); wig_pn(h_rc); wig_p(" resp_len=" as *u8); wig_pn(hn); wig_p("\n" as *u8) 133 134 // ---- toc_live: <nav class="nx-toc" present AND id="section-a" injected ---- 135 var toc_live: i64 = 0 136 let nav_at: i64 = wig_find(resp, hn, "<nav class=\"nx-toc\"" as *u8) 137 let id_at: i64 = wig_find(resp, hn, "id=\"section-a\"" as *u8) 138 let toclink_at: i64 = wig_find(resp, hn, "href=\"#section-a\"" as *u8) 139 if nav_at >= 0 { if id_at >= 0 { toc_live = 1 } } 140 wig_p(" toc: nav@" as *u8); wig_pn(nav_at) 141 wig_p(" id=section-a@" as *u8); wig_pn(id_at) 142 wig_p(" toc-link@" as *u8); wig_pn(toclink_at) 143 wig_p(" -> toc_live=" as *u8); wig_pn(toc_live); wig_p("\n" as *u8) 144 145 // ---- backlinks_live: <aside class="nx-backlinks" present AND links doc-two ---- 146 // NOTE (post wikilink-live fix): doc-one's body [[doc-two]] now resolves to a 147 // LIVE <a href="/wiki/doc-two"> in the ARTICLE (the fix), so "/wiki/doc-two" 148 // appears EARLIER than the aside too. We therefore scope the panel-link check 149 // to the aside REGION: find the aside, then search for the doc-two link STARTING 150 // FROM the aside offset (the panel emits <li><a href="/wiki/doc-two">). 151 var backlinks_live: i64 = 0 152 let aside_at: i64 = wig_find(resp, hn, "<aside class=\"nx-backlinks\"" as *u8) 153 let bl_in_aside: i64 = wig_find(resp, hn, "<aside class=\"nx-backlinks\"><h2>What links here</h2>" as *u8) 154 var bl_slug_at: i64 = 0 - 1 155 if aside_at >= 0 { 156 // search the aside tail region for the panel's doc-two link. 157 let tail: *u8 = (resp as i64 + aside_at) as *u8 158 let tail_n: i64 = hn - aside_at 159 let rel: i64 = wig_find(tail, tail_n, "/wiki/doc-two" as *u8) 160 if rel >= 0 { bl_slug_at = aside_at + rel } 161 } 162 if aside_at >= 0 { if bl_slug_at >= aside_at { backlinks_live = 1 } } 163 wig_p(" backlinks: aside@" as *u8); wig_pn(aside_at) 164 wig_p(" doc-two-slug-in-aside@" as *u8); wig_pn(bl_slug_at) 165 wig_p(" header@" as *u8); wig_pn(bl_in_aside) 166 wig_p(" -> backlinks_live=" as *u8); wig_pn(backlinks_live); wig_p("\n" as *u8) 167 168 // ---- wikilink_fixed: prove served [[doc-two]] is a LIVE clickable link with 169 // NO html-escaping (the two render bugs are dead), on THREE real ground truths: 170 // 171 // (1) SERVED HTML, resolved branch: doc-two IS a real page in this store, so 172 // the handler's store-derived doc-names set RESOLVES [[doc-two]] -> a LIVE 173 // <a href="/wiki/doc-two"> in the served article (bug #2 dead: no longer 174 // always-broken). Found in the ARTICLE region (before the backlinks aside). 175 // (2) SERVED HTML, NOT escaped: no "&lt;a href=" appears ANYWHERE -- the post- 176 // markdown pass emits the anchor RAW, so it is NOT the dead &lt;a... text 177 // the pre-markdown preprocessor used to produce (bug #1 dead). 178 // (3) POST-PASS unit: drive nx_wiki_doc_postpass_wikilinks directly over a tiny 179 // rendered-HTML fragment with a doc-names entry naming "doc-two"; its output 180 // must hold the literal <a href="/wiki/doc-two">doc-two</a> -- proving the 181 // resolver + RAW anchor emit with a correct name length (no garble). 182 var wikilink_fixed: i64 = 0 183 // (1) served LIVE resolved anchor for doc-two, located in the ARTICLE (before aside). 184 var served_live_at: i64 = 0 - 1 185 let article_n: i64 = aside_at // article region ends where the aside begins 186 if aside_at >= 0 { 187 served_live_at = wig_find(resp, article_n, "<a href=\"/wiki/doc-two\"" as *u8) 188 } 189 // (2) NO escaped anchor anywhere in the served bytes. 190 let served_esc_at: i64 = wig_find(resp, hn, "&lt;a href=" as *u8) 191 // (3) post-markdown pass unit check with a populated doc-names set -> resolved anchor. 192 let pp_ctx: *NxWikiDocCtx = (sys_mmap(512)) as *NxWikiDocCtx 193 let pp_scratch: *u8 = sys_mmap(65536) 194 let pp_out: *u8 = sys_mmap(65536) 195 // doc-names buffer: one 64-byte slot. byte0=name_len(7), bytes1..="doc-two". 196 let pp_names: *u8 = sys_mmap(64) 197 pp_names[0] = 7 as u8 198 pp_names[1] = 0x64 as u8 // d 199 pp_names[2] = 0x6F as u8 // o 200 pp_names[3] = 0x63 as u8 // c 201 pp_names[4] = 0x2D as u8 // - 202 pp_names[5] = 0x74 as u8 // t 203 pp_names[6] = 0x77 as u8 // w 204 pp_names[7] = 0x6F as u8 // o 205 // a fragment as markdown WOULD leave it: literal [[doc-two]] inside a <p>. 206 let pp_src: *u8 = "<p>See [[doc-two]] now.</p>" as *u8 207 let pp_rci: i64 = nx_wiki_doc_ctx_init(pp_ctx, 208 pp_out, 65536, pp_src, wig_slen(pp_src), pp_names, 64, 1, pp_scratch, 65536) 209 let pp_used: *i64 = (sys_mmap(8)) as *i64 210 pp_used[0] = 0 211 let pp_pre: i64 = nx_wiki_doc_postpass_wikilinks(pp_ctx, pp_src, wig_slen(pp_src), 212 pp_out, 65536, pp_used) 213 var anchor_at: i64 = 0 - 1 214 if pp_pre == NX_WIKI_DOC_OK { 215 anchor_at = wig_find(pp_out, pp_used[0], "<a href=\"/wiki/doc-two\">doc-two</a>" as *u8) 216 } 217 if served_live_at >= 0 { if served_esc_at < 0 { if anchor_at >= 0 { wikilink_fixed = 1 } } } 218 wig_p(" wikilink: served-live-anchor@" as *u8); wig_pn(served_live_at) 219 wig_p(" served-escaped-anchor@(should be -1)=" as *u8); wig_pn(served_esc_at) 220 wig_p(" postpass_rc=" as *u8); wig_pn(pp_pre) 221 wig_p(" unit-resolved-anchor@" as *u8); wig_pn(anchor_at) 222 wig_p(" -> wikilink_fixed=" as *u8); wig_pn(wikilink_fixed); wig_p("\n" as *u8) 223 224 // EVIDENCE: echo a body chunk around the TOC + wikilink + backlinks. 225 wig_p(" ---- served doc-one HTML (first 1400 bytes) ----\n" as *u8) 226 var dh: i64 = hn 227 if dh > 1400 { dh = 1400 } 228 sys_write(1, resp, dh) 229 wig_p("\n ---- /served ----\n" as *u8) 230 231 // ===== DRIVE the /wiki/graph route handler =============================== 232 // Calls the SAME handler the dispatcher invokes for GET /wiki/graph; asserts 233 // a well-formed HTML page carrying a JS-FREE <svg> (no <script>). 234 let gresp: *u8 = sys_mmap(WIG_RESP_CAP) 235 let gresp_n: *i64 = (sys_mmap(8)) as *i64 236 gresp_n[0] = 0 237 let g_rc: i64 = nx_wiki_route_serve_graph(store, gresp, WIG_RESP_CAP, gresp_n) 238 let gn: i64 = gresp_n[0] 239 var graph_route: i64 = 0 240 let svg_at: i64 = wig_find(gresp, gn, "<svg" as *u8) 241 let script_at: i64 = wig_find(gresp, gn, "<script" as *u8) 242 let http200_at: i64 = wig_find(gresp, gn, "HTTP/1.1 200 OK" as *u8) 243 if g_rc == NX_WIKI_ROUTE_OK { if svg_at >= 0 { if script_at < 0 { graph_route = 1 } } } 244 wig_p(" graph: serve_rc=" as *u8); wig_pn(g_rc) 245 wig_p(" resp_len=" as *u8); wig_pn(gn) 246 wig_p(" http200@" as *u8); wig_pn(http200_at) 247 wig_p(" <svg@" as *u8); wig_pn(svg_at) 248 wig_p(" <script@(should be -1)=" as *u8); wig_pn(script_at) 249 wig_p(" -> graph_route=" as *u8); wig_pn(graph_route); wig_p("\n" as *u8) 250 wig_p(" ---- /wiki/graph HTML (first 900 bytes) ----\n" as *u8) 251 var gh: i64 = gn 252 if gh > 900 { gh = 900 } 253 sys_write(1, gresp, gh) 254 wig_p("\n ---- /graph ----\n" as *u8) 255 256 // ===== VERDICT =========================================================== 257 var green: i64 = 1 258 if toc_live != 1 { green = 0 } 259 if backlinks_live != 1 { green = 0 } 260 if wikilink_fixed != 1 { green = 0 } 261 if graph_route != 1 { green = 0 } 262 263 let lfd: i64 = sys_openat_append(WIG_LOG, 420) 264 wig_w2(lfd, "WIKIINTEGRATE toc_live=" as *u8); wig_n2(lfd, toc_live) 265 wig_w2(lfd, " backlinks_live=" as *u8); wig_n2(lfd, backlinks_live) 266 wig_w2(lfd, " wikilink_fixed=" as *u8); wig_n2(lfd, wikilink_fixed) 267 wig_w2(lfd, " graph_route=" as *u8); wig_n2(lfd, graph_route) 268 if green == 1 { wig_w2(lfd, " verdict=GREEN\n" as *u8) } else { wig_w2(lfd, " verdict=RED\n" as *u8) } 269 if lfd >= 0 { sys_close(lfd) } 270 271 if green == 1 { sys_exit(0); return 0 } 272 sys_exit(1) 273 return 1 274}