code wiki / wiki / nx_pipeline_route.nx

nx_pipeline_route.nx source

↩ module page · 332 lines · 15388 B

1// nx_pipeline_route.nx -- V2.0 P-3: /wiki/pipeline HTTP route. 2// 3// Renders NxArtifactStore (V2.0 P-2) as a tabular pipeline view. Operator 4// visits /wiki/pipeline and sees all ~230 substrate artifacts classified 5// by 5-stage pipeline (UNSTRUCTURED..REPEATABLE) with operator-existing 6// 6-field V5 taxonomy (Quadrant + Topic Type + Status + Trust + Competitive). 7// 8// COMPOSES: 9// wiki/nx_artifact_store (V2.0 P-2; data source) 10// nx_html_escape (safe value emission) 11// nx_syscalls (sys_mmap) 12// 13// COMPOSED BY: 14// wiki/nx_wiki_routes.nx (dispatches /wiki/pipeline + /wiki/pipeline/<stage>) 15// 16// V2.0 SCOPE: 17// - GET /wiki/pipeline -> all artifacts; stage histogram + per-stage counts 18// - GET /wiki/pipeline/<stage-name> -> filter by stage (uppercase stage name) 19// - V1 page format conformant HTML (wiki chrome + nishi-* meta) 20// - Bounded by NX_PROUTE_MAX_ROWS_RENDER per page 21// 22// V3+ SCOPE (TODO): 23// - Pagination + sort 24// - Filter combos (stage + kind + trust + competitive) 25// - JSON API at /wiki/pipeline.json for ops scrapers 26// - Auto-refresh on file change (V2.5 inotify hook) 27// 28// Status: V2.0. 2026-05-27. 29 30import "nx_syscalls.nx" 31import "nx_html_escape.nx" 32import "wiki/nx_artifact_store.nx" 33 34// ===== Sealed verdict surface (codes 2970-2979) ================================================= 35const NX_PROUTE_OK: i64 = 0 36const NX_PROUTE_BAD_INPUT: i64 = 2970 37const NX_PROUTE_RESP_OVERFLOW: i64 = 2971 38const NX_PROUTE_BAD_STAGE_FILTER: i64 = 2972 39 40// ===== Named constants (M7) ================================================= 41const NX_PROUTE_BODY_CAP: i64 = 524288 // 512 KB body 42const NX_PROUTE_MAX_ROWS_RENDER: i64 = 500 // hard cap per page 43const NX_PROUTE_INT_BUF_CAP: i64 = 32 44 45// Sealed wiki chrome (reused; matches dashboard + archive router conventions). 46const NX_PROUTE_HEAD: *u8 = 47 "<!DOCTYPE html>\n<html lang=\"en\"><head><meta charset=\"utf-8\"><title>Pipeline | Nishi Wiki</title><meta name=\"nishi-canonical\" content=\"https://nishifamily.com/wiki/pipeline\"><meta name=\"nishi-title\" content=\"Pipeline\"><meta name=\"nishi-summary\" content=\"Substrate self-audit dashboard. All artifacts classified by 5-stage pipeline.\"><meta name=\"nishi-tags\" content=\"wiki,pipeline,dashboard,audit\"><meta name=\"nishi-last-modified\" content=\"2026-05-27T00:00:00Z\"><meta name=\"nishi-content-hash\" content=\"0000000000000000\"><meta name=\"nishi-page-version\" content=\"1.0.0\"><meta name=\"nishi-license\" content=\"nishi-substrate-public\"><meta name=\"nishi-author\" content=\"elderwesto\"></head><body><header><a href=\"/wiki/\">Wiki</a><a href=\"/wiki/dashboard\">Dashboard</a><a href=\"/wiki/search\">Search</a><a href=\"/wiki/pipeline\">Pipeline</a><a href=\"/wiki/archive\">Archive</a><a href=\"/wiki/admin\">Admin</a></header><main>" as *u8 48const NX_PROUTE_HEAD_N: i64 = 1107 49 50const NX_PROUTE_FOOT: *u8 = "</main></body></html>" as *u8 51const NX_PROUTE_FOOT_N: i64 = 21 52 53// ===== Decimal int helper (M7 + M10) ================================================= 54 55func nx_proute_int_to_dec(v: i64, out: *u8, cap: i64) -> i64 { 56 if cap < 2 { return 0 } 57 if v == 0 { out[0] = 0x30 as u8; return 1 } 58 var n: i64 = v 59 var neg: i64 = 0 60 if n < 0 { neg = 1; n = 0 - n } 61 let tmp: *u8 = sys_mmap(NX_PROUTE_INT_BUF_CAP) 62 var k: i64 = 0 63 while n > 0 { 64 if k >= NX_PROUTE_INT_BUF_CAP - 2 { return 0 } 65 tmp[k] = (0x30 + (n % 10)) as u8 66 n = n / 10 67 k = k + 1 68 } 69 var off: i64 = 0 70 if neg == 1 { out[off] = 0x2D as u8; off = off + 1 } 71 var j: i64 = k - 1 72 while j >= 0 { out[off] = tmp[j]; off = off + 1; j = j - 1 } 73 return off 74} 75 76// ===== Output writer (bounded; M5) ================================================= 77 78func nx_proute_put_raw(out: *u8, cap: i64, off: i64, 79 src: *u8, n: i64) -> i64 { 80 if off < 0 { return 0 - NX_PROUTE_BAD_INPUT } 81 if off + n > cap { return 0 - NX_PROUTE_RESP_OVERFLOW } 82 var i: i64 = 0 83 while i < n { out[off + i] = src[i]; i = i + 1 } 84 return off + n 85} 86 87func nx_proute_put_z(out: *u8, cap: i64, off: i64, s: *u8) -> i64 { 88 var n: i64 = 0 89 while s[n] != (0 as u8) { 90 if n >= cap { return 0 - NX_PROUTE_RESP_OVERFLOW } 91 n = n + 1 92 } 93 return nx_proute_put_raw(out, cap, off, s, n) 94} 95 96func nx_proute_put_escaped(out: *u8, cap: i64, off: i64, 97 src: *u8, n: i64) -> i64 { 98 if n < 1 { return off } 99 if cap - off < n * 6 + 1 { return 0 - NX_PROUTE_RESP_OVERFLOW } 100 let w: i64 = html_escape((out as i64 + off) as *u8, cap - off, src, n) 101 if w < 0 { return 0 - NX_PROUTE_RESP_OVERFLOW } 102 return off + w 103} 104 105// ===== Sealed stage filter parser ================================================= 106// 107// Path-suffix sealed enum: NONE / UNSTRUCTURED / STRUCTURED / MEANINGFUL 108// / ACTIONABLE / REPEATABLE. Returns -1 on bad input. 109 110func nx_proute_parse_stage_filter(suffix: *u8, suffix_n: i64) -> i64 { 111 if suffix_n < 1 { return 0 - 1 } // -1 = no filter 112 // Match longest-first 113 if suffix_n == 12 { 114 if suffix[0] == (0x55 as u8) { 115 // "UNSTRUCTURED" 116 return NX_ART_STAGE_UNSTRUCTURED 117 } 118 } 119 if suffix_n == 11 { 120 if suffix[0] == (0x55 as u8) { return 0 - NX_PROUTE_BAD_STAGE_FILTER } 121 if suffix[0] == (0x4D as u8) { return 0 - NX_PROUTE_BAD_STAGE_FILTER } 122 } 123 if suffix_n == 10 { 124 if suffix[0] == (0x53 as u8) { return NX_ART_STAGE_STRUCTURED } 125 if suffix[0] == (0x4D as u8) { return NX_ART_STAGE_MEANINGFUL } 126 if suffix[0] == (0x41 as u8) { return NX_ART_STAGE_ACTIONABLE } 127 if suffix[0] == (0x52 as u8) { return NX_ART_STAGE_REPEATABLE } 128 } 129 return 0 - NX_PROUTE_BAD_STAGE_FILTER 130} 131 132// ===== Render histogram (count per stage) ================================================= 133 134func nx_proute_render_histogram(out: *u8, cap: i64, off: i64, 135 s: *NxArtifactStore) -> i64 { 136 var o: i64 = off 137 o = nx_proute_put_z(out, cap, o, 138 "<table><thead><tr><th>Stage</th><th>Count</th></tr></thead><tbody>" as *u8) 139 if o < 0 { return o } 140 141 var stage: i64 = 0 142 while stage < NX_ART_STAGE_N { 143 o = nx_proute_put_z(out, cap, o, "<tr><td><a href=\"/wiki/pipeline/" as *u8); if o < 0 { return o } 144 o = nx_proute_put_z(out, cap, o, nx_art_stage_name(stage)); if o < 0 { return o } 145 o = nx_proute_put_z(out, cap, o, "\">" as *u8); if o < 0 { return o } 146 o = nx_proute_put_z(out, cap, o, nx_art_stage_name(stage)); if o < 0 { return o } 147 o = nx_proute_put_z(out, cap, o, "</a></td><td>" as *u8); if o < 0 { return o } 148 let buf: *u8 = sys_mmap(NX_PROUTE_INT_BUF_CAP) 149 let n: i64 = nx_proute_int_to_dec(nx_artifact_store_count_by_stage(s, stage), buf, NX_PROUTE_INT_BUF_CAP) 150 o = nx_proute_put_raw(out, cap, o, buf, n); if o < 0 { return o } 151 o = nx_proute_put_z(out, cap, o, "</td></tr>\n" as *u8); if o < 0 { return o } 152 stage = stage + 1 153 } 154 o = nx_proute_put_z(out, cap, o, "</tbody></table>\n" as *u8); if o < 0 { return o } 155 return o 156} 157 158// ===== Render artifact table (filtered or all) ================================================= 159 160func nx_proute_render_table(out: *u8, cap: i64, off: i64, 161 s: *NxArtifactStore, 162 stage_filter: i64) -> i64 { 163 var o: i64 = off 164 o = nx_proute_put_z(out, cap, o, 165 "<table><thead><tr><th>Path</th><th>Kind</th><th>Stage</th><th>Lines</th><th>Composes</th></tr></thead><tbody>\n" as *u8) 166 if o < 0 { return o } 167 168 let total: i64 = nx_artifact_store_count(s) 169 var i: i64 = 0 170 var rendered: i64 = 0 171 while i < total { 172 if rendered >= NX_PROUTE_MAX_ROWS_RENDER { i = total + 1 } 173 if i < total { 174 let stage: i64 = nx_artifact_store_stage_at(s, i) 175 if stage_filter < 0 { 176 // No filter; render all 177 o = nx_proute_render_row(out, cap, o, s, i); if o < 0 { return o } 178 rendered = rendered + 1 179 } 180 if stage_filter >= 0 { 181 if stage == stage_filter { 182 o = nx_proute_render_row(out, cap, o, s, i); if o < 0 { return o } 183 rendered = rendered + 1 184 } 185 } 186 i = i + 1 187 } 188 } 189 o = nx_proute_put_z(out, cap, o, "</tbody></table>\n" as *u8); if o < 0 { return o } 190 191 // Footer: rendered count + cap warning 192 o = nx_proute_put_z(out, cap, o, "<p><small>Rendered <b>" as *u8); if o < 0 { return o } 193 let cb: *u8 = sys_mmap(NX_PROUTE_INT_BUF_CAP) 194 let cn: i64 = nx_proute_int_to_dec(rendered, cb, NX_PROUTE_INT_BUF_CAP) 195 o = nx_proute_put_raw(out, cap, o, cb, cn); if o < 0 { return o } 196 o = nx_proute_put_z(out, cap, o, "</b> of <b>" as *u8); if o < 0 { return o } 197 let tb: *u8 = sys_mmap(NX_PROUTE_INT_BUF_CAP) 198 let tn: i64 = nx_proute_int_to_dec(total, tb, NX_PROUTE_INT_BUF_CAP) 199 o = nx_proute_put_raw(out, cap, o, tb, tn); if o < 0 { return o } 200 o = nx_proute_put_z(out, cap, o, "</b> artifacts. Hard cap: 500 rows per page.</small></p>\n" as *u8); if o < 0 { return o } 201 return o 202} 203 204// ===== Render one table row ================================================= 205 206func nx_proute_render_row(out: *u8, cap: i64, off: i64, 207 s: *NxArtifactStore, rowid: i64) -> i64 { 208 var o: i64 = off 209 210 // Path 211 let path_ptr: *i64 = (sys_mmap(8)) as *i64 212 let path_n: *i64 = (sys_mmap(8)) as *i64 213 path_ptr[0] = 0; path_n[0] = 0 214 let rc_p: i64 = nx_artifact_store_path_at(s, rowid, path_ptr, path_n) 215 if rc_p != NX_ART_OK { return o } // skip on lookup failure 216 217 o = nx_proute_put_z(out, cap, o, "<tr><td><code>" as *u8); if o < 0 { return o } 218 o = nx_proute_put_escaped(out, cap, o, path_ptr[0] as *u8, path_n[0]); if o < 0 { return o } 219 o = nx_proute_put_z(out, cap, o, "</code></td><td>" as *u8); if o < 0 { return o } 220 221 // Kind 222 o = nx_proute_put_z(out, cap, o, nx_art_kind_name(nx_artifact_store_kind_at(s, rowid))); if o < 0 { return o } 223 o = nx_proute_put_z(out, cap, o, "</td><td>" as *u8); if o < 0 { return o } 224 225 // Stage badge with class 226 let stage: i64 = nx_artifact_store_stage_at(s, rowid) 227 o = nx_proute_put_z(out, cap, o, "<span class=\"stage-" as *u8); if o < 0 { return o } 228 o = nx_proute_put_z(out, cap, o, nx_art_stage_name(stage)); if o < 0 { return o } 229 o = nx_proute_put_z(out, cap, o, "\">" as *u8); if o < 0 { return o } 230 o = nx_proute_put_z(out, cap, o, nx_art_stage_name(stage)); if o < 0 { return o } 231 o = nx_proute_put_z(out, cap, o, "</span></td><td>" as *u8); if o < 0 { return o } 232 233 // Lines + composes (direct field read; if accessor not exposed, walk fields) 234 let lb: *u8 = sys_mmap(NX_PROUTE_INT_BUF_CAP) 235 let ln: i64 = nx_proute_int_to_dec(s.line_count[rowid], lb, NX_PROUTE_INT_BUF_CAP) 236 o = nx_proute_put_raw(out, cap, o, lb, ln); if o < 0 { return o } 237 o = nx_proute_put_z(out, cap, o, "</td><td>" as *u8); if o < 0 { return o } 238 let cb: *u8 = sys_mmap(NX_PROUTE_INT_BUF_CAP) 239 let cn: i64 = nx_proute_int_to_dec(s.composes_count[rowid], cb, NX_PROUTE_INT_BUF_CAP) 240 o = nx_proute_put_raw(out, cap, o, cb, cn); if o < 0 { return o } 241 o = nx_proute_put_z(out, cap, o, "</td></tr>\n" as *u8); if o < 0 { return o } 242 243 return o 244} 245 246// ===== Top-level: dispatch /wiki/pipeline + /wiki/pipeline/<stage> ================================================= 247 248func nx_pipeline_route(s: *NxArtifactStore, 249 url_path: *u8, url_path_n: i64, 250 resp_buf: *u8, resp_cap: i64, 251 out_resp_n: *i64) -> i64 { 252 if (s as i64) == 0 { return 0 - NX_PROUTE_BAD_INPUT } 253 if s.valid != 1 { return 0 - NX_PROUTE_BAD_INPUT } 254 255 // Allocate body buffer 256 let body: *u8 = sys_mmap(NX_PROUTE_BODY_CAP) 257 var o: i64 = 0 258 o = nx_proute_put_raw(body, NX_PROUTE_BODY_CAP, o, NX_PROUTE_HEAD, NX_PROUTE_HEAD_N) 259 if o < 0 { return o } 260 261 // Determine if this is /wiki/pipeline (root) or /wiki/pipeline/<stage> 262 var stage_filter: i64 = 0 - 1 // -1 = no filter 263 264 if url_path_n > 15 { // "/wiki/pipeline/" = 15 chars 265 // Has a stage suffix 266 let suffix_ptr: *u8 = (url_path as i64 + 15) as *u8 267 let suffix_n: i64 = url_path_n - 15 268 let parsed: i64 = nx_proute_parse_stage_filter(suffix_ptr, suffix_n) 269 if parsed < 0 { 270 // Bad stage filter; render with no filter + warning 271 o = nx_proute_put_z(body, NX_PROUTE_BODY_CAP, o, 272 "<p><strong>Warning:</strong> unrecognized stage filter; showing all.</p>\n" as *u8) 273 if o < 0 { return o } 274 } 275 if parsed >= 0 { stage_filter = parsed } 276 } 277 278 // Title 279 o = nx_proute_put_z(body, NX_PROUTE_BODY_CAP, o, "<h1>Substrate Pipeline</h1>\n" as *u8); if o < 0 { return o } 280 o = nx_proute_put_z(body, NX_PROUTE_BODY_CAP, o, 281 "<p>Per <a href=\"/wiki/nishi-intelligent-wiki-charter\">NISHI_INTELLIGENT_WIKI_CHARTER</a> 5-stage pipeline. Derived from operator-existing V5 living-docs taxonomy (Quadrant + Topic Type + Status + Trust State + Competitive State + Composes).</p>\n" as *u8) 282 if o < 0 { return o } 283 284 // Histogram 285 o = nx_proute_put_z(body, NX_PROUTE_BODY_CAP, o, "<h2>Stage Distribution</h2>\n" as *u8); if o < 0 { return o } 286 o = nx_proute_render_histogram(body, NX_PROUTE_BODY_CAP, o, s); if o < 0 { return o } 287 288 // Filter heading 289 if stage_filter >= 0 { 290 o = nx_proute_put_z(body, NX_PROUTE_BODY_CAP, o, "<h2>Artifacts in stage <code>" as *u8); if o < 0 { return o } 291 o = nx_proute_put_z(body, NX_PROUTE_BODY_CAP, o, nx_art_stage_name(stage_filter)); if o < 0 { return o } 292 o = nx_proute_put_z(body, NX_PROUTE_BODY_CAP, o, "</code></h2>\n" as *u8); if o < 0 { return o } 293 } 294 if stage_filter < 0 { 295 o = nx_proute_put_z(body, NX_PROUTE_BODY_CAP, o, "<h2>All Artifacts</h2>\n" as *u8); if o < 0 { return o } 296 } 297 298 // Table 299 o = nx_proute_render_table(body, NX_PROUTE_BODY_CAP, o, s, stage_filter); if o < 0 { return o } 300 301 // Footer chrome 302 o = nx_proute_put_raw(body, NX_PROUTE_BODY_CAP, o, NX_PROUTE_FOOT, NX_PROUTE_FOOT_N); if o < 0 { return o } 303 304 let body_len: i64 = o 305 306 // HTTP wrap (same pattern as nx_wiki_dashboard) 307 let hdr: *u8 = "HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=utf-8\r\nContent-Length: " as *u8 308 let hdr_n: i64 = 71 309 let crlf2: *u8 = "\r\n\r\n" as *u8 310 311 let len_buf: *u8 = sys_mmap(NX_PROUTE_INT_BUF_CAP) 312 let ld: i64 = nx_proute_int_to_dec(body_len, len_buf, NX_PROUTE_INT_BUF_CAP) 313 let need: i64 = hdr_n + ld + 4 + body_len 314 if need > resp_cap { return 0 - NX_PROUTE_RESP_OVERFLOW } 315 316 var off: i64 = 0 317 var i: i64 = 0 318 while i < hdr_n { resp_buf[off + i] = hdr[i]; i = i + 1 } 319 off = off + hdr_n 320 i = 0 321 while i < ld { resp_buf[off + i] = len_buf[i]; i = i + 1 } 322 off = off + ld 323 i = 0 324 while i < 4 { resp_buf[off + i] = crlf2[i]; i = i + 1 } 325 off = off + 4 326 i = 0 327 while i < body_len { resp_buf[off + i] = body[i]; i = i + 1 } 328 off = off + body_len 329 330 out_resp_n[0] = off 331 return NX_PROUTE_OK 332}