code wiki / _hdl_build / nx_ws_board_html.nx
nx_ws_board_html.nx source
↩ module page · 194 lines · 10002 B
1// nx_ws_board_html.nx -- WMS rung M2.5: the VIEWABLE board (Language-Export HAL last-mile).
2//
3// module: nishi-core.wms.ws_board_html
4// capability: CORE_COMPUTE (a Nishi-EMITTED last-mile HTML view of the M2 derived board)
5//
6// WHAT THIS CLOSES: the M2 charter says the live board "REPLACES the stale THREADS
7// worksheet". nx_ws_board renders to stdout + a log -- not a VIEWABLE artifact. This
8// additive organ produces the viewable form WITHOUT violating sovereign/NO-BLEED: the
9// HTML is the genuine last-mile wire format (HTML is to a browser what a syscall is to
10// the OS) and EVERY byte is EMITTED BY this Nishi organ -- never hand-authored, never a
11// node/playwright dependency. This is the wheeler flip the Language-Export HAL encodes
12// (nx_lang_export): Nishi is the TRUTH; the emitted artifact is a verified OUTPUT.
13//
14// TRUTH-PRESERVING: the table is derived by calling the SAME wb_board_p that the M2 gate
15// proved correct -- the HTML cannot disagree with the board (single source of truth, no
16// re-derivation). And it honors the board's refusals: if wb_board_p returns a negative
17// WB_* code (incomplete registry / torn reflog), this organ emits a REFUSED banner page,
18// NOT a wrong table. A silently-wrong viewable board would defeat the whole point.
19//
20// REUSE / lineage: wb_board_p / WB_ROWW / WB_MAXEMP / WB_INCOMPLETE / WB_TORNREFLOG
21// (nx_ws_board, WMS-M2); fa_cat / fa_catn / fa_appendz (nx_framed_append, WMS-R0b -- the
22// one-buffer-one-locked-write discipline for the evidence channel); the byte-emit + wfile
23// idiom mirrors nx_lang_export (Language-Export HAL). Additive: no organ modified.
24// Sovereign: imports only the WMS/HAL stack + nx_syscalls (no gcc/openssl/node).
25// license_tier: ORIGINAL
26import "nx_ws_board.nx"
27import "nx_framed_append.nx"
28import "nx_syscalls.nx"
29
30const WBH_OUT: *u8 = "web_assets/_ws_build/ws_board.html"
31const WBH_LOG: *u8 = "knowledge/status/ws_board_html.log"
32const WBH_RECCAP: i64 = 512
33const WBH_HTMLCAP: i64 = 65536 // bounded HTML buffer (no magic number)
34
35// emit-status codes the gate asserts (data-driven; no magic numbers).
36const WBH_TABLE: i64 = 1 // a real per-empire table was emitted
37const WBH_REFUSED: i64 = 2 // a REFUSED banner was emitted (board refused)
38
39func wbh_len(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
40
41// append nul-terminated string into the HTML buffer at off; return new off (fa_cat alias
42// kept local so the HTML builder reads like the lang_export `cat` idiom).
43func wbh_cat(dst: *u8, off: i64, s: *u8) -> i64 { return fa_cat(dst, off, s) }
44func wbh_catn(dst: *u8, off: i64, v: i64) -> i64 { return fa_catn(dst, off, v) }
45
46// one-write-out of the assembled HTML buffer (last-mile file sink, like lang_export wfile).
47func wbh_wfile(path: *u8, buf: *u8, n: i64) -> i64 {
48 let fd: i64 = sys_openat_wr(path, 420) // 0644
49 if fd < 0 { return 0 - 1 }
50 var off: i64 = 0
51 while off < n {
52 let tail: *u8 = ((buf as i64) + off) as *u8
53 let wr: i64 = sys_write(fd, tail, n - off)
54 if wr <= 0 { sys_close(fd); return 0 - 2 }
55 off = off + wr
56 }
57 sys_close(fd)
58 return n
59}
60
61// emit the HTML <head> + open <body> into out at off; returns new off.
62func wbh_head(out: *u8, off: i64) -> i64 {
63 var o: i64 = off
64 o = wbh_cat(out, o, "<!DOCTYPE html>\n<html><head><meta charset=\"utf-8\">\n" as *u8)
65 o = wbh_cat(out, o, "<title>Nishi WMS Live Status Board</title>\n" as *u8)
66 o = wbh_cat(out, o, "<style>body{font-family:monospace;background:#0b0e14;color:#cdd6f4}" as *u8)
67 o = wbh_cat(out, o, "table{border-collapse:collapse}td,th{border:1px solid #45475a;padding:4px 10px}" as *u8)
68 o = wbh_cat(out, o, "th{background:#181825}.done{color:#a6e3a1}.active{color:#f9e2af}.blocked{color:#f38ba8}" as *u8)
69 o = wbh_cat(out, o, ".refused{color:#f38ba8;font-weight:bold}</style></head>\n<body>\n" as *u8)
70 return o
71}
72
73// THE EMITTER. Derives the board via wb_board_p (the M2 truth), then emits a viewable
74// HTML artifact. Parameterized by prefix+refpath so the gate drives HERMETIC stores.
75// returns WBH_TABLE (1) when a real per-empire table was emitted,
76// WBH_REFUSED (2) when the board refused and a REFUSED banner was emitted,
77// negative on a hard emit/file error.
78// status_out[]: [0]=board rc (wb_board_p return) [1]=empire count emitted [2]=total streams.
79func wbh_emit_p(prefix: *u8, refpath: *u8, outpath: *u8, status_out: *i64) -> i64 {
80 let rows: *i64 = sys_mmap(8 * WB_MAXEMP * WB_ROWW) as *i64
81 let ec: *i64 = sys_mmap(16) as *i64
82 let sm: *i64 = sys_mmap(64) as *i64
83 let rc: i64 = wb_board_p(prefix, refpath, rows, WB_MAXEMP, ec, sm)
84
85 let html: *u8 = sys_mmap(WBH_HTMLCAP)
86 var o: i64 = wbh_head(html, 0)
87
88 status_out[0] = rc
89 status_out[1] = 0
90 status_out[2] = 0
91
92 // ---- REFUSAL PATH: the board refused -> emit a REFUSED banner, NOT a wrong table. ----
93 if rc < 0 {
94 o = wbh_cat(html, o, "<h1>Nishi WMS Status Board</h1>\n" as *u8)
95 o = wbh_cat(html, o, "<p class=\"refused\">BOARD REFUSED rc=" as *u8)
96 o = wbh_catn(html, o, rc)
97 if rc == WB_INCOMPLETE { o = wbh_cat(html, o, " reason=registry-incomplete (lost segment) -- NOT rendered" as *u8) }
98 if rc == WB_NOIDS { o = wbh_cat(html, o, " reason=no-ws:ids -- nothing registered" as *u8) }
99 if rc == WB_TORNREFLOG { o = wbh_cat(html, o, " reason=torn/old-reflog -- view REJECTED" as *u8) }
100 o = wbh_cat(html, o, "</p>\n</body></html>\n" as *u8)
101 html[o] = 0 as u8
102 let wrr: i64 = wbh_wfile(outpath, html, o)
103 if wrr < 0 { return wrr }
104 return WBH_REFUSED
105 }
106
107 // ---- TABLE PATH: derive-from-truth per-empire rollup. ----
108 let necount: i64 = ec[0]
109 o = wbh_cat(html, o, "<h1>Nishi WMS Live Status Board</h1>\n" as *u8)
110 o = wbh_cat(html, o, "<p>derived from WMS-R1 registry + WMS-R2 reflog overlay</p>\n" as *u8)
111 o = wbh_cat(html, o, "<table>\n<tr><th>empire</th><th>streams</th>" as *u8)
112 o = wbh_cat(html, o, "<th class=\"done\">done</th><th class=\"active\">active</th><th class=\"blocked\">blocked</th></tr>\n" as *u8)
113 var e: i64 = 0
114 while e < necount {
115 let base: i64 = e * WB_ROWW
116 let empire: *u8 = rows[base + 0] as *u8
117 o = wbh_cat(html, o, "<tr><td>" as *u8)
118 o = wbh_cat(html, o, empire)
119 o = wbh_cat(html, o, "</td><td>" as *u8); o = wbh_catn(html, o, rows[base + 1])
120 o = wbh_cat(html, o, "</td><td class=\"done\">" as *u8); o = wbh_catn(html, o, rows[base + 2])
121 o = wbh_cat(html, o, "</td><td class=\"active\">" as *u8); o = wbh_catn(html, o, rows[base + 3])
122 o = wbh_cat(html, o, "</td><td class=\"blocked\">" as *u8); o = wbh_catn(html, o, rows[base + 4])
123 o = wbh_cat(html, o, "</td></tr>\n" as *u8)
124 e = e + 1
125 }
126 // summary footer row.
127 o = wbh_cat(html, o, "<tr><th>SUMMARY</th><th>" as *u8); o = wbh_catn(html, o, sm[0])
128 o = wbh_cat(html, o, "</th><th class=\"done\">" as *u8); o = wbh_catn(html, o, sm[1])
129 o = wbh_cat(html, o, "</th><th class=\"active\">" as *u8); o = wbh_catn(html, o, sm[2])
130 o = wbh_cat(html, o, "</th><th class=\"blocked\">" as *u8); o = wbh_catn(html, o, sm[3])
131 o = wbh_cat(html, o, "</th></tr>\n</table>\n</body></html>\n" as *u8)
132 html[o] = 0 as u8
133
134 status_out[1] = necount
135 status_out[2] = sm[0]
136 let wrt: i64 = wbh_wfile(outpath, html, o)
137 if wrt < 0 { return wrt }
138 return WBH_TABLE
139}
140
141// convenience: live ws- prefix -> the real web asset path.
142func wbh_emit(refpath: *u8, status_out: *i64) -> i64 {
143 return wbh_emit_p(WS_PREFIX, refpath, WBH_OUT, status_out)
144}
145
146// MANDATORY WRITE DISCIPLINE: one evidence line into one buffer, ONE locked fa_appendz.
147func wbh_emit_log(emitcode: i64, empires: i64, total: i64) -> i64 {
148 let buf: *u8 = sys_mmap(WBH_RECCAP + 16)
149 var o: i64 = 0
150 o = fa_cat(buf, o, "WS-BOARD-HTML emit=\x00" as *u8)
151 if emitcode == WBH_TABLE { o = fa_cat(buf, o, "TABLE\x00" as *u8) }
152 if emitcode == WBH_REFUSED { o = fa_cat(buf, o, "REFUSED\x00" as *u8) }
153 o = fa_cat(buf, o, " empires=\x00" as *u8); o = fa_catn(buf, o, empires)
154 o = fa_cat(buf, o, " total=\x00" as *u8); o = fa_catn(buf, o, total)
155 o = fa_cat(buf, o, " file=web_assets/_ws_build/ws_board.html END\x00" as *u8)
156 buf[o] = 0 as u8
157 return fa_appendz(WBH_LOG, buf, WBH_RECCAP)
158}
159
160func wbh_p(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
161func wbh_pn(v: i64) -> i64 {
162 let bb: *u8 = sys_mmap(28); var m: i64 = v
163 if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m }
164 let t: *u8 = sys_mmap(28); var k: i64 = 0
165 if m == 0 { t[0] = 48 as u8; k = 1 }
166 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
167 var i: i64 = 0; while i < k { bb[i] = t[k - 1 - i]; i = i + 1 }
168 sys_write(1, bb, k); return 0
169}
170
171// main(): emit the LIVE board to web_assets/_ws_build/ws_board.html. Reflog overlay
172// skipped (refpath=0) for the same reason nx_ws_board's main does -- the live transition
173// log is an OPTIONAL freshness check; the R1 registry is the SSOT.
174func main() -> i64 {
175 wbh_p("=== WMS-M2.5 BOARD->HTML (Language-Export HAL last-mile, Nishi-emitted) ===\n" as *u8)
176 let st: *i64 = sys_mmap(64) as *i64
177 let code: i64 = wbh_emit(0 as *u8, st)
178 if code < 0 {
179 wbh_p(" EMIT FAILED rc=\x00" as *u8); wbh_pn(code); wbh_p("\n\x00" as *u8)
180 sys_exit(1); return 1
181 }
182 if code == WBH_TABLE {
183 wbh_p(" emitted TABLE empires=\x00" as *u8); wbh_pn(st[1])
184 wbh_p(" total=\x00" as *u8); wbh_pn(st[2])
185 wbh_p(" -> web_assets/_ws_build/ws_board.html\n\x00" as *u8)
186 }
187 if code == WBH_REFUSED {
188 wbh_p(" emitted REFUSED banner (board rc=\x00" as *u8); wbh_pn(st[0])
189 wbh_p(") -> web_assets/_ws_build/ws_board.html\n\x00" as *u8)
190 }
191 wbh_emit_log(code, st[1], st[2])
192 sys_exit(0)
193 return 0
194}