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 "<a href=" appears ANYWHERE -- the post-
176 // markdown pass emits the anchor RAW, so it is NOT the dead <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, "<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}