code wiki / (root) / nx_writer_serve.nx

nx_writer_serve.nx source

↩ module page · 432 lines · 27439 B

1// nx_writer_serve.nx -- WRITING HUB rung R6: the SOVEREIGN LIVE SURFACE. Operator: "api nishi ecosystem based, 2// surface it to nishifamily.com/writer." A sovereign HTTP server (nx_syscalls, the nx_gallery_serve pattern) 3// exposing the writing hub as REAL APIs + a page -- the page calls the ACTUAL organs, not JS copies: 4// GET / (and /writer) -> the writer page (Score prose + Verify claim) 5// POST /score -> body=prose; nx_writehub_score.whl_eval -> JSON {quality,verdict,directive,...} 6// POST /factcheck -> body=claim; nx_writehub_factlib.fcl_check (composes nx_research_corroborate over 7// the banked corpus) -> JSON {verdict,classes,sources[]} (grounded, cited) 8// GET /health -> ok 9// 100% sovereign+local (no cloud, no seat). Bash is only ever a LAUNCHER. Default port 8098; test: nx_writer_serve <port>. 10// license_tier: ORIGINAL module: nishi-core.writehub.serve 11import "nx_syscalls.nx" 12import "nx_writehub_score.nx" 13import "nx_writehub_factlib.nx" 14import "nx_lane_conf.nx" 15const K_MAGIC_200000: i64 = 200000 16const K_MAGIC_3000: i64 = 3000 17const K_MAGIC_60000: i64 = 60000 18const K_MAGIC_65536: i64 = 65536 19const K_MAGIC_4096: i64 = 4096 20const K_MAGIC_2097152: i64 = 2097152 21const K_MAGIC_8192: i64 = 8192 22const K_MAGIC_4094: i64 = 4094 23const K_MAGIC_8098: i64 = 8098 24const K_MAGIC_16384: i64 = 16384 25const K_MAGIC_262144: i64 = 262144 26 27func ws_strlen(s: *u8) -> i64 { var i: i64=0; while s[i]!=(0 as u8){i=i+1} return i } 28func ws_cat(dst: *u8, off: i64, s: *u8) -> i64 { var i: i64=0; while s[i]!=(0 as u8){dst[off+i]=s[i];i=i+1} return off+i } 29func ws_u(dst: *u8, off: i64, v: i64) -> i64 { 30 var m: i64=v; if m<0 { dst[off]=45 as u8; return ws_u(dst, off+1, 0-m) } 31 let t: *u8=sys_mmap(28); var k: i64=0; if m==0 { t[0]=48 as u8; k=1 } 32 while m>0 { t[k]=(48+(m-(m/10)*10)) as u8; m=m/10; k=k+1 } 33 var o: i64=off; var i: i64=0; while i<k { dst[o]=t[k-1-i]; o=o+1; i=i+1 } return o 34} 35func ws_qs(dst: *u8, off: i64, s: *u8) -> i64 { var o: i64=off; dst[o]=34 as u8; o=o+1; o=ws_cat(dst,o,s); dst[o]=34 as u8; o=o+1; return o } 36func ws_write_all(fd: i64, buf: *u8, n: i64) -> i64 { 37 var off: i64=0 38 while off<n { let p: *u8=((buf as i64)+off) as *u8; let w: i64=sys_write(fd, p, n-off); if w<=0 { return 0 } off=off+w } 39 return 0 40} 41func ws_find(buf: *u8, n: i64, pat: *u8, plen: i64) -> i64 { 42 var i: i64=0 43 while i+plen<=n { var j: i64=0; var ok: i64=1; while j<plen { if buf[i+j]!=pat[j] { ok=0; j=plen } else { j=j+1 } } if ok==1 { return 1 } i=i+1 } 44 return 0 45} 46func ws_body(buf: *u8, n: i64) -> i64 { 47 var i: i64=0 48 while i+3<n { if buf[i]==(13 as u8) { if buf[i+1]==(10 as u8) { if buf[i+2]==(13 as u8) { if buf[i+3]==(10 as u8) { return i+4 } } } } i=i+1 } 49 return 0-1 50} 51func ws_wrap(rbuf: *u8, ctype: *u8, body: *u8, blen: i64) -> i64 { 52 var o: i64=ws_cat(rbuf, 0, "HTTP/1.1 200 OK\r\nContent-Type: " as *u8) 53 o=ws_cat(rbuf, o, ctype) 54 o=ws_cat(rbuf, o, "\r\nCache-Control: no-store\r\nConnection: close\r\nContent-Length: " as *u8) 55 o=ws_u(rbuf, o, blen) 56 o=ws_cat(rbuf, o, "\r\n\r\n" as *u8) 57 var i: i64=0; while i<blen { rbuf[o+i]=body[i]; i=i+1 } 58 return o+blen 59} 60func ws_404(rbuf: *u8) -> i64 { return ws_cat(rbuf, 0, "HTTP/1.1 404 Not Found\r\nContent-Type: text/plain\r\nContent-Length: 9\r\nConnection: close\r\n\r\nnot found" as *u8) } 61func ws_health(rbuf: *u8) -> i64 { return ws_cat(rbuf, 0, "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: 2\r\nConnection: close\r\n\r\nok" as *u8) } 62 63// conf capture cap, CLAMPED to the K_MAGIC_262144 buffers it fills -- a conf row may TUNE the lane 64// but must never be able to overflow a fixed buffer (config is a boundary input too, rule 12). 65func ws_capcap() -> i64 { 66 var c: i64=lc_write_lane("writer_capture_cap" as *u8, K_MAGIC_200000) 67 if c > K_MAGIC_262144-K_MAGIC_8192 { c = K_MAGIC_262144-K_MAGIC_8192 } 68 if c < K_MAGIC_8192 { c = K_MAGIC_8192 } 69 return c 70} 71 72// the /writer page -- single-quotes ONLY inside (no double-quote so the .nx literal stays valid) 73func ws_page(rbuf: *u8) -> i64 { 74 let b: *u8=sys_mmap(K_MAGIC_65536) 75 var o: i64=0 76 o=ws_cat(b,o,"<!doctype html><html><head><meta charset='utf-8'><meta name='viewport' content='width=device-width,initial-scale=1'><title>Nishi Writer</title>" as *u8) 77 o=ws_cat(b,o,"<style>body{background:#0b0d12;color:#e6e6e6;font-family:system-ui,sans-serif;max-width:820px;margin:0 auto;padding:24px;line-height:1.5}h1{color:#7cc7ff;margin-bottom:2px}h2{color:#7cc7ff;margin-top:30px}a{color:#7cc7ff}textarea{width:100%;height:130px;background:#11151c;color:#e6e6e6;border:1px solid #2a3340;border-radius:8px;padding:12px;font-size:15px;box-sizing:border-box}button{background:#2b6cb0;color:#fff;border:0;border-radius:8px;padding:10px 20px;font-size:15px;cursor:pointer;margin-top:10px}.r{margin-top:16px;padding:16px;background:#11151c;border:1px solid #2a3340;border-radius:8px}.keep{border-color:#2f855a}.rev{border-color:#c05621}.m{color:#8aa0b4;font-size:13px}.tag{display:inline-block;background:#182130;color:#7cc7ff;border-radius:6px;padding:2px 8px;margin:2px;font-size:12px}</style></head><body>" as *u8) 78 o=ws_cat(b,o,"<h1>Nishi Writer</h1><div class='m'>the sovereign writing hub &mdash; live. 100% Nishi: no cloud, no seat, no shell. Every result below comes from a real Nishi organ over HTTP.</div><div id='cen' class='m' style='margin-top:6px'>loading census...</div>" as *u8) 79 o=ws_cat(b,o,"<h2>Score prose</h2><div class='m'>readability + adverb / passive / weak / hard-sentence, via nx_writehub_score &mdash; KEEP or REVISE with a directive.</div>" as *u8) 80 o=ws_cat(b,o,"<textarea id='t'>The door was opened slowly by the very frightened woman as she walked quietly and carefully through the extremely dark and absolutely silent hallway that seemed to stretch endlessly before her.</textarea>" as *u8) 81 o=ws_cat(b,o,"<div><button onclick='sc()'>Score my prose</button></div><div id='out' class='r' style='display:none'></div>" as *u8) 82 o=ws_cat(b,o,"<h2>Generate (swarm)</h2><div class='m'>prompt &rarr; nx_write &rarr; swarm SSOT &rarr; the GPU engine &mdash; the writer swarms exactly like /gen. Mode/register/lane come from the write_modes.tsv registry.</div>" as *u8) 83 o=ws_cat(b,o,"<div class='m' style='margin-top:8px'>mode (from the registry, all registers -- the seam is enforced inside nx_write, not by this page): <select id='wm' style='background:#11151c;color:#e6e6e6;border:1px solid #2a3340;border-radius:6px;padding:4px'></select></div>" as *u8) 84 o=ws_cat(b,o,"<textarea id='wp'>A lighthouse keeper on a remote island discovers the nightly fog is erasing her memories one at a time. Write the opening beat.</textarea>" as *u8) 85 o=ws_cat(b,o,"<div><button onclick='wg()'>Generate</button></div><div id='wout' class='r' style='display:none;white-space:pre-wrap'></div>" as *u8) 86 o=ws_cat(b,o,"<h2>Grounded fact-check</h2><div class='m'>a claim is checked against the sovereign-banked corpus with independence-aware corroboration (nx_research_corroborate) &mdash; CONFIRMED only if independent source-classes attest, with citations. The field ships an empty fact-check box; this one grounds.</div>" as *u8) 87 o=ws_cat(b,o,"<textarea id='c'>narrative writing involves characters, scenes, and dialogue</textarea>" as *u8) 88 o=ws_cat(b,o,"<div><button onclick='fc()'>Verify claim</button></div><div id='fout' class='r' style='display:none'></div>" as *u8) 89 o=ws_cat(b,o,"<p class='m' style='margin-top:28px'>Hub organs (census nx_writehub_census, self-ratcheted to 684&#8240;): <span class='tag'>research-ingest</span><span class='tag'>census</span><span class='tag'>seat-wire</span><span class='tag'>autonomy-loop</span><span class='tag'>data-growth</span><span class='tag'>grounded-fact-check</span><span class='tag'>self-improve-conductor</span></p>" as *u8) 90 o=ws_cat(b,o,"<script>function sc(){var t=document.getElementById('t').value;fetch('/score',{method:'POST',body:t}).then(function(r){return r.json()}).then(function(d){var o=document.getElementById('out');o.style.display='block';o.className='r '+(d.verdict==='KEEP'?'keep':'rev');o.innerHTML='Quality: <b>'+d.quality+'&#8240;</b> &mdash; <b>'+d.verdict+'</b><br><span class=m>directive: '+d.directive+'</span><br><span class=m>words '+d.words+' &middot; sentences '+d.sents+' &middot; FK-grade '+(d.fk/1000).toFixed(1)+' &middot; adverbs '+d.adv+' &middot; passive '+d.pass+' &middot; weak '+d.weak+' &middot; hard '+d.hard+'</span>'}).catch(function(e){var o=document.getElementById('out');o.style.display='block';o.textContent='error: '+e})}" as *u8) 91 o=ws_cat(b,o,"function fc(){var c=document.getElementById('c').value;fetch('/factcheck',{method:'POST',body:c}).then(function(r){return r.json()}).then(function(d){var o=document.getElementById('fout');o.style.display='block';o.className='r '+(d.verdict==='CONFIRMED'?'keep':(d.verdict==='UNSUPPORTED'?'rev':''));var s='';var i;for(i=0;i<d.sources.length;i++){s+='<span class=tag>'+d.sources[i]+'</span>'}o.innerHTML='<b>'+d.verdict+'</b> <span class=m>('+d.classes+' independent source-classes)</span><br>'+(d.sources.length>0?('<span class=m>cited:</span><br>'+s):'<span class=m>no banked source attests</span>')}).catch(function(e){var o=document.getElementById('fout');o.style.display='block';o.textContent='error: '+e})}fetch('/modes').then(function(r){return r.text()}).then(function(t){var s=document.getElementById('wm');s.innerHTML='';var L=t.split(String.fromCharCode(10));var i;for(i=0;i<L.length;i++){var ln=L[i];if(ln&&ln.charAt(0)!=='#'){var f=ln.split(String.fromCharCode(9));if(f.length>=2){var op=document.createElement('option');op.value=f[0];op.textContent=f[0]+' ('+f[1]+')';op.title=f[4]||'';s.appendChild(op)}}}}).catch(function(e){var s=document.getElementById('wm');var fb=['scenario','erotica','roleplay','campaign','correspondence','manga','paper','social','language'];var k;for(k=0;k<fb.length;k++){var op=document.createElement('option');op.textContent=fb[k];s.appendChild(op)}});function wg(){var m=document.getElementById('wm').value;var p=document.getElementById('wp').value;var o=document.getElementById('wout');o.style.display='block';o.textContent='generating via the swarm...';fetch('/write',{method:'POST',body:m+String.fromCharCode(10)+p}).then(function(r){return r.json()}).then(function(d){if(!d.job){o.textContent='error: no job id';return}var n=0;var tm=setInterval(function(){n++;if(n>" as *u8); o=ws_u(b,o,lc_write_lane("writer_page_poll_tries" as *u8, 60)); o=ws_cat(b,o,"){clearInterval(tm);o.textContent='timed out';return}fetch('/writeget?id='+d.job).then(function(r){return r.text()}).then(function(x){if(x!=='PENDING'){clearInterval(tm);o.textContent=x}}).catch(function(e){})}," as *u8); o=ws_u(b,o,lc_write_lane("writer_page_poll_ms" as *u8, K_MAGIC_3000)); o=ws_cat(b,o,")}).catch(function(e){o.textContent='error: '+e})}fetch('/census').then(function(r){return r.json()}).then(function(d){document.getElementById('cen').textContent='hub census: '+d.census})</script>" as *u8) 92 o=ws_cat(b,o,"</body></html>" as *u8) 93 return ws_wrap(rbuf, "text/html; charset=utf-8" as *u8, b, o) 94} 95 96// POST /write -> body line1=mode, rest=prompt; forks ./nx_write.elf (the swarm-dispatching generator: 97// endpoint resolved per call from knowledge/swarm_nodes.conf, register/lane seam enforced by the 98// write_modes.tsv registry INSIDE nx_write, not here). The surface swarms the writer the way /gen 99// swarms images. u26a0single-threaded accept loop: a generation blocks siblings for its duration. 100func ws_write_gen(rbuf: *u8, req: *u8, rn: i64, cfd: i64) -> i64 { 101 let bo: i64=ws_body(req, rn) 102 if bo<0 { return ws_404(rbuf) } 103 var blen: i64=rn-bo 104 if blen<=0 { return ws_404(rbuf) } 105 if blen>K_MAGIC_8192 { blen=K_MAGIC_8192 } 106 let body: *u8=((req as i64)+bo) as *u8 107 let mode: *u8=sys_mmap(48) 108 var i: i64=0 109 var mo: i64=0 110 var run: i64=1 111 while run==1 { 112 if i>=blen { run=0 } else { 113 let ch: u8=body[i] 114 if ch==(10 as u8) { run=0; i=i+1 } else { 115 if mo<40 { 116 var okc: i64=0 117 if ch>=(97 as u8) { if ch<=(122 as u8) { okc=1 } } 118 if ch>=(48 as u8) { if ch<=(57 as u8) { okc=1 } } 119 if ch==(95 as u8) { okc=1 } 120 if okc==1 { mode[mo]=ch; mo=mo+1 } 121 } 122 i=i+1 123 } 124 } 125 } 126 mode[mo]=0 as u8 127 if mo==0 { return ws_404(rbuf) } 128 let prompt: *u8=sys_mmap(K_MAGIC_8192) 129 var po: i64=0 130 while i<blen { let c2: u8=body[i]; if c2!=(13 as u8) { prompt[po]=c2; po=po+1 } i=i+1 } 131 prompt[po]=0 as u8 132 if po==0 { return ws_404(rbuf) } 133 // ASYNC: a scene takes 20-90s, the edge window is ~15s (bit us live 2026-08-05, exactly the 134 // problem /gen solved with cids+poll). Mint an id, DETACH the generation, answer immediately. 135 // The worker writes .part then renameat's to .txt -- the rename IS the done-marker, so a poll 136 // can never read a half-written file. 137 let ts: *i64=sys_mmap(16) as *i64 138 ts[0]=0; ts[1]=0 139 sys_clock_gettime_real(ts) 140 let jid: *u8=sys_mmap(64) 141 var jo: i64=ws_u(jid, 0, ts[0]) 142 jid[jo]=95 as u8; jo=jo+1 143 jo=ws_u(jid, jo, ts[1]) 144 jid[jo]=0 as u8 145 let part: *u8=sys_mmap(K_MAGIC_4096) 146 var po2: i64=ws_cat(part, 0, "knowledge/staging/writejob_" as *u8) 147 po2=ws_cat(part, po2, jid) 148 po2=ws_cat(part, po2, ".txt.part" as *u8) 149 part[po2]=0 as u8 150 let fin: *u8=sys_mmap(K_MAGIC_4096) 151 var fo2: i64=ws_cat(fin, 0, "knowledge/staging/writejob_" as *u8) 152 fo2=ws_cat(fin, fo2, jid) 153 fo2=ws_cat(fin, fo2, ".txt" as *u8) 154 fin[fo2]=0 as u8 155 // DURABLE QUEUE (operator 2026-08-05: the hub stores requests and runs them later rather than 156 // dying or dropping): the request itself is banked as <id>.req and the id appended to the 157 // append-only writejobs.queue ledger BEFORE any GPU work. A deferred/failed generation leaves 158 // the ticket queued; nx_writejob_sweep drains it when the GPU frees. 159 let reqp: *u8=sys_mmap(K_MAGIC_4096) 160 var ro2: i64=ws_cat(reqp, 0, "knowledge/staging/writejob_" as *u8) 161 ro2=ws_cat(reqp, ro2, jid) 162 ro2=ws_cat(reqp, ro2, ".req" as *u8) 163 reqp[ro2]=0 as u8 164 let rfd0: i64=sys_openat_wr(reqp, 420) 165 if rfd0>=0 { 166 ws_write_all(rfd0, mode, ws_strlen(mode)) 167 ws_write_all(rfd0, "\n" as *u8, 1) 168 ws_write_all(rfd0, prompt, ws_strlen(prompt)) 169 sys_close(rfd0) 170 } 171 let qfd: i64=sys_openat_append("knowledge/staging/writejobs.queue" as *u8, 420) 172 if qfd>=0 { ws_write_all(qfd, jid, ws_strlen(jid)); ws_write_all(qfd, "\n" as *u8, 1); sys_close(qfd) } 173 let gpid: i64=sys_fork() 174 if gpid==0 { 175 // detached worker (orphaned deliberately; init reaps): generate; finalize ONLY real prose. 176 // An organ error ("nx_write ...") or a yield ("NX-WRITE-DEFERRED ...") leaves the job 177 // QUEUED (poll stays PENDING, .req survives for the sweeper) instead of masquerading as 178 // a finished result. 179 sys_close(cfd) 180 let ob: *u8=sys_mmap(K_MAGIC_262144) 181 let got: i64=ws_fork_nx_write(mode, prompt, ob, ws_capcap()) 182 var real: i64=1 183 if got<=0 { real=0 } 184 if real==1 { if ob[0]==(110 as u8) { if ob[1]==(120 as u8) { if ob[2]==(95 as u8) { real=0 } } } } 185 if real==1 { if ob[0]==(78 as u8) { if ob[1]==(88 as u8) { if ob[2]==(45 as u8) { real=0 } } } } 186 if real==1 { 187 let wfd2: i64=sys_openat_wr(part, 420) 188 if wfd2>=0 { ws_write_all(wfd2, ob, got); sys_close(wfd2); sys_renameat(part, fin) } 189 } 190 sys_exit(0) 191 } 192 let j: *u8=sys_mmap(256) 193 var o: i64=ws_cat(j, 0, "{" as *u8) 194 o=ws_qs(j,o,"job" as *u8); o=ws_cat(j,o,":" as *u8); o=ws_qs(j,o,jid) 195 o=ws_cat(j,o,"}" as *u8) 196 return ws_wrap(rbuf, "application/json" as *u8, j, o) 197} 198 199// GET /writeget?id=<sec>_<nsec> -> the finished text, or the literal PENDING while the worker runs. 200func ws_writeget(rbuf: *u8, req: *u8, rn: i64) -> i64 { 201 // find "id=" then copy [0-9_] (cap 40) 202 var i: i64=0 203 var s: i64=0-1 204 while i+3<=rn { if req[i]==(105 as u8) { if req[i+1]==(100 as u8) { if req[i+2]==(61 as u8) { s=i+3; i=rn } } } if s<0 { i=i+1 } } 205 if s<0 { return ws_404(rbuf) } 206 let jid: *u8=sys_mmap(48) 207 var jo: i64=0 208 var run: i64=1 209 while run==1 { 210 if s>=rn { run=0 } else { 211 let ch: u8=req[s] 212 var okc: i64=0 213 if ch>=(48 as u8) { if ch<=(57 as u8) { okc=1 } } 214 if ch==(95 as u8) { okc=1 } 215 if okc==1 { if jo<40 { jid[jo]=ch; jo=jo+1; s=s+1 } else { run=0 } } else { run=0 } 216 } 217 } 218 jid[jo]=0 as u8 219 if jo==0 { return ws_404(rbuf) } 220 let fin: *u8=sys_mmap(K_MAGIC_4096) 221 var fo2: i64=ws_cat(fin, 0, "knowledge/staging/writejob_" as *u8) 222 fo2=ws_cat(fin, fo2, jid) 223 fo2=ws_cat(fin, fo2, ".txt" as *u8) 224 fin[fo2]=0 as u8 225 let rfd2: i64=sys_openat_rd(fin) 226 if rfd2<0 { 227 let msg: *u8="PENDING" as *u8 228 return ws_wrap(rbuf, "text/plain; charset=utf-8" as *u8, msg, ws_strlen(msg)) 229 } 230 let ob: *u8=sys_mmap(K_MAGIC_262144) 231 let rcap: i64=ws_capcap() 232 var got: i64=0 233 var rd: i64=1 234 while rd==1 { 235 let n: i64=sys_read(rfd2, ((ob as i64)+got) as *u8, rcap-got) 236 if n<=0 { rd=0 } else { got=got+n; if got>=rcap { rd=0 } } 237 } 238 sys_close(rfd2) 239 return ws_wrap(rbuf, "text/plain; charset=utf-8" as *u8, ob, got) 240} 241 242// fork ./nx_write.elf with 1 or 2 args, capture stdout into ob (at most cap bytes -- the cap MUST 243// match the buffer the caller allocated, or this helper writes past it). Returns bytes captured. 244func ws_fork_nx_write(a1: *u8, a2: *u8, ob: *u8, cap: i64) -> i64 { 245 let pf: *i64=sys_mmap(32) as *i64 246 if sys_pipe2(pf, 0)<0 { return 0-1 } 247 // u2605pipe2 fills int[2] -- TWO 32-BIT fds packed in 8 bytes (the creatorfit wedge); unpack both. 248 let packed: i64=pf[0] 249 let rfd: i64=packed & 0xFFFFFFFF 250 let wfd: i64=(packed>>32) & 0xFFFFFFFF 251 let pid: i64=sys_fork() 252 if pid==0 { 253 sys_close(rfd) 254 sys_dup3(wfd, 1, 0) 255 let av: *i64=sys_mmap(40) as *i64 256 av[0]="./nx_write.elf" as i64 257 av[1]=a1 as i64 258 av[2]=a2 as i64 259 av[3]=0 260 if (a2 as i64)==0 { av[2]=0 } 261 sys_execve("./nx_write.elf" as *u8, av as *i64, 0 as *i64) 262 sys_exit(127) 263 } 264 if pid<0 { sys_close(rfd); sys_close(wfd); return 0-1 } 265 sys_close(wfd) 266 var got: i64=0 267 var rd: i64=1 268 while rd==1 { 269 let n: i64=sys_read(rfd, ((ob as i64)+got) as *u8, cap-got) 270 if n<=0 { rd=0 } else { got=got+n; if got>=cap { rd=0 } } 271 } 272 sys_close(rfd) 273 let stw: *i64=sys_mmap(16) as *i64 274 stw[0]=0 275 sys_wait4(pid, stw, 0) 276 return got 277} 278 279// GET /modes -> the raw write_modes.tsv via `nx_write modes` (the registry IS the UI's source; a 280// mode row-add appears on the page with zero code here). 281func ws_modes(rbuf: *u8) -> i64 { 282 let ob: *u8=sys_mmap(K_MAGIC_65536) 283 let got: i64=ws_fork_nx_write("modes" as *u8, 0 as *u8, ob, K_MAGIC_60000) 284 if got<=0 { return ws_404(rbuf) } 285 return ws_wrap(rbuf, "text/plain; charset=utf-8" as *u8, ob, got) 286} 287 288// POST /score -> score the request body, return JSON 289func ws_score(rbuf: *u8, req: *u8, rn: i64) -> i64 { 290 let bo: i64=ws_body(req, rn) 291 var pptr: i64=0; var plen: i64=0 292 if bo>=0 { pptr=(req as i64)+bo; plen=rn-bo } 293 let prose: *u8=pptr as *u8 294 let rep: *i64=sys_mmap(256) as *i64 295 if plen>0 { whl_eval(prose, plen, rep) } else { var z: i64=0; while z<16 { rep[z]=0; z=z+1 } rep[14]=0; rep[15]=5 } 296 var vstr: *u8="REVISE" as *u8 297 if rep[14]>=WHL_KEEP { vstr="KEEP" as *u8 } 298 let j: *u8=sys_mmap(K_MAGIC_4096) 299 var o: i64=0 300 o=ws_cat(j,o,"{" as *u8) 301 o=ws_qs(j,o,"quality" as *u8); o=ws_cat(j,o,":" as *u8); o=ws_u(j,o,rep[14]) 302 o=ws_cat(j,o,"," as *u8); o=ws_qs(j,o,"verdict" as *u8); o=ws_cat(j,o,":" as *u8); o=ws_qs(j,o,vstr) 303 o=ws_cat(j,o,"," as *u8); o=ws_qs(j,o,"directive" as *u8); o=ws_cat(j,o,":" as *u8); o=ws_qs(j,o,whl_directive(rep[15])) 304 o=ws_cat(j,o,"," as *u8); o=ws_qs(j,o,"words" as *u8); o=ws_cat(j,o,":" as *u8); o=ws_u(j,o,rep[0]) 305 o=ws_cat(j,o,"," as *u8); o=ws_qs(j,o,"sents" as *u8); o=ws_cat(j,o,":" as *u8); o=ws_u(j,o,rep[1]) 306 o=ws_cat(j,o,"," as *u8); o=ws_qs(j,o,"fk" as *u8); o=ws_cat(j,o,":" as *u8); o=ws_u(j,o,rep[2]) 307 o=ws_cat(j,o,"," as *u8); o=ws_qs(j,o,"adv" as *u8); o=ws_cat(j,o,":" as *u8); o=ws_u(j,o,rep[3]) 308 o=ws_cat(j,o,"," as *u8); o=ws_qs(j,o,"pass" as *u8); o=ws_cat(j,o,":" as *u8); o=ws_u(j,o,rep[4]) 309 o=ws_cat(j,o,"," as *u8); o=ws_qs(j,o,"weak" as *u8); o=ws_cat(j,o,":" as *u8); o=ws_u(j,o,rep[5]) 310 o=ws_cat(j,o,"," as *u8); o=ws_qs(j,o,"hard" as *u8); o=ws_cat(j,o,":" as *u8); o=ws_u(j,o,rep[8]) 311 o=ws_cat(j,o,"}" as *u8) 312 return ws_wrap(rbuf, "application/json" as *u8, j, o) 313} 314 315// POST /factcheck -> ground the claim in the banked corpus, return JSON {verdict,classes,sources[]} 316func ws_factcheck(rbuf: *u8, req: *u8, rn: i64) -> i64 { 317 let bo: i64=ws_body(req, rn) 318 var cptr: i64=0; var clen: i64=0 319 if bo>=0 { cptr=(req as i64)+bo; clen=rn-bo } 320 let claim: *u8=cptr as *u8 321 // load the corpus manifest 322 let mfd: i64=sys_openat_rd("knowledge/registry/writehub_corpus.tsv" as *u8) 323 let mbuf: *u8=sys_mmap(K_MAGIC_65536) 324 var mn: i64=0 325 if mfd>=0 { mn=sys_read(mfd, mbuf, K_MAGIC_65536); sys_close(mfd) } 326 let srcpath: *i64=sys_mmap(8*64) as *i64 327 let srcclass: *i64=sys_mmap(8*64) as *i64 328 var nsrc: i64=0 329 if mn>0 { nsrc=fc_parse_manifest(mbuf, mn, srcpath, srcclass, 64) } 330 let srcbuf: *u8=sys_mmap(K_MAGIC_2097152) 331 let cites: *i64=sys_mmap(8*64) as *i64 332 let ncp: *i64=sys_mmap(16) as *i64 333 let indp: *i64=sys_mmap(16) as *i64 334 ncp[0]=0; indp[0]=0 335 var conf: i64=0 336 if clen>0 { if nsrc>0 { conf=fcl_check(claim, clen, srcpath, srcclass, nsrc, srcbuf, K_MAGIC_2097152, cites, 64, ncp, indp) } } 337 var vstr: *u8="UNSUPPORTED" as *u8 338 if conf==NX_CORR_CONFIRMED { vstr="CONFIRMED" as *u8 } 339 if conf==NX_CORR_SINGLE { vstr="SINGLE" as *u8 } 340 let j: *u8=sys_mmap(K_MAGIC_8192) 341 var o: i64=0 342 o=ws_cat(j,o,"{" as *u8) 343 o=ws_qs(j,o,"verdict" as *u8); o=ws_cat(j,o,":" as *u8); o=ws_qs(j,o,vstr) 344 o=ws_cat(j,o,"," as *u8); o=ws_qs(j,o,"classes" as *u8); o=ws_cat(j,o,":" as *u8); o=ws_u(j,o,indp[0]) 345 o=ws_cat(j,o,"," as *u8); o=ws_qs(j,o,"sources" as *u8); o=ws_cat(j,o,":" as *u8); o=ws_cat(j,o,"[" as *u8) 346 var ci: i64=0 347 while ci<ncp[0] { if ci>0 { o=ws_cat(j,o,"," as *u8) } o=ws_qs(j,o, srcpath[cites[ci]] as *u8); ci=ci+1 } 348 o=ws_cat(j,o,"]" as *u8) 349 o=ws_cat(j,o,"}" as *u8) 350 return ws_wrap(rbuf, "application/json" as *u8, j, o) 351} 352 353// GET /census -> the live hub census (latest WRITEHUB-CENSUS line from writehub_census.log) 354func ws_census(rbuf: *u8) -> i64 { 355 let szp: *i64 = sys_mmap(16) as *i64 356 let cb: *u8 = sys_read_file("knowledge/status/writehub_census.log" as *u8, szp) 357 let cl: *u8 = sys_mmap(K_MAGIC_4096); cl[0]=0 as u8 358 if (cb as i64) != 0 { 359 let n: i64 = szp[0] 360 var i: i64=0; var ls: i64=0 361 while i<=n { 362 var eol: i64=0 363 if i==n { eol=1 } else { if cb[i]==(10 as u8) { eol=1 } } 364 if eol==1 { 365 if ws_find(((cb as i64)+ls) as *u8, i-ls, "WRITEHUB-CENSUS " as *u8, 16)==1 { 366 var k: i64=0; let ll: i64=i-ls 367 while k<ll { if k<K_MAGIC_4094 { cl[k]=cb[ls+k] } k=k+1 } 368 var e: i64=ll; if e>K_MAGIC_4094 { e=K_MAGIC_4094 } cl[e]=0 as u8 369 } 370 ls=i+1 371 } 372 i=i+1 373 } 374 } 375 if cl[0]==(0 as u8) { let m: *u8="census not run yet" as *u8; var k: i64=0; while m[k]!=(0 as u8){ cl[k]=m[k]; k=k+1 } cl[k]=0 as u8 } 376 let j: *u8=sys_mmap(K_MAGIC_4096); var o: i64=0 377 o=ws_cat(j,o,"{" as *u8); o=ws_qs(j,o,"census" as *u8); o=ws_cat(j,o,":" as *u8); o=ws_qs(j,o,cl); o=ws_cat(j,o,"}" as *u8) 378 return ws_wrap(rbuf, "application/json" as *u8, j, o) 379} 380 381func main(argc: i64, argv: *i64) -> i64 { 382 var port: i64=K_MAGIC_8098 383 if argc>=2 { var pv: i64=0; var pi: i64=0; let pa: *u8=argv[1] as *u8; while pa[pi]!=(0 as u8) { if pa[pi]>=(48 as u8) { if pa[pi]<=(57 as u8) { pv=pv*10+((pa[pi] as i64)-48) } } pi=pi+1 } if pv>0 { port=pv } } 384 let addr: *u8=sys_mmap(16) 385 addr[0]=2 as u8; addr[1]=0 as u8; addr[2]=((port>>8)&0xff) as u8; addr[3]=(port&0xff) as u8 386 addr[4]=0 as u8; addr[5]=0 as u8; addr[6]=0 as u8; addr[7]=0 as u8 387 addr[8]=0 as u8; addr[9]=0 as u8; addr[10]=0 as u8; addr[11]=0 as u8; addr[12]=0 as u8; addr[13]=0 as u8; addr[14]=0 as u8; addr[15]=0 as u8 388 let lfd: i64=sys_socket(2, 1 | 0x80000, 0) 389 if lfd<0 { return 10 } 390 let optval: *u8=sys_mmap(4); optval[0]=1 as u8; optval[1]=0 as u8; optval[2]=0 as u8; optval[3]=0 as u8 391 sys_setsockopt(lfd, 1, 2, optval, 4) 392 if sys_bind(lfd, addr, 16)<0 { return 20 } 393 if sys_listen(lfd, 64)<0 { return 30 } 394 let up: *u8="nx_writer_serve: LIVE sovereign writer (score+factcheck) on 0.0.0.0:" as *u8 395 sys_write(2, up, ws_strlen(up)); let pb: *u8=sys_mmap(16); let pn: i64=ws_u(pb,0,port); sys_write(2, pb, pn); sys_write(2, "\n" as *u8, 1) 396 let req: *u8=sys_mmap(K_MAGIC_16384) 397 let rbuf: *u8=sys_mmap(K_MAGIC_262144) 398 // fork-per-connection (the nx_sites_daemon pattern): a 60s generation must not block the page 399 // for every other visitor -- the single-threaded loop 503'd the operator mid-generation 2026-08-05. 400 let reap: *i64=sys_mmap(16) as *i64 401 var live: i64=0 402 while 1==1 { 403 var rp: i64=1 404 while rp>0 { reap[0]=0; rp=sys_wait4(0-1, reap, 1); if rp>0 { live=live-1 } } 405 let cfd: i64=sys_accept(lfd) 406 if cfd<0 { } else { 407 if live>=lc_write_lane("writer_max_children" as *u8, 8) { if sys_wait4(0-1, reap, 0)>0 { live=live-1 } } 408 let pid: i64=sys_fork() 409 if pid==0 { 410 sys_close(lfd) 411 sys_set_socket_timeout(cfd, lc_write_lane("writer_conn_timeout_sec" as *u8, 300)) 412 let rn: i64=sys_read(cfd, req, K_MAGIC_16384) 413 var rlen: i64=0 414 if ws_find(req, rn, "POST /factcheck" as *u8, 15)==1 { rlen=ws_factcheck(rbuf, req, rn) } 415 if rlen==0 { if ws_find(req, rn, "POST /score" as *u8, 11)==1 { rlen=ws_score(rbuf, req, rn) } } 416 if rlen==0 { if ws_find(req, rn, "POST /write" as *u8, 11)==1 { rlen=ws_write_gen(rbuf, req, rn, cfd) } } 417 if rlen==0 { if ws_find(req, rn, "GET /writeget" as *u8, 13)==1 { rlen=ws_writeget(rbuf, req, rn) } } 418 if rlen==0 { if ws_find(req, rn, "GET /modes" as *u8, 10)==1 { rlen=ws_modes(rbuf) } } 419 if rlen==0 { if ws_find(req, rn, "GET /census" as *u8, 11)==1 { rlen=ws_census(rbuf) } } 420 if rlen==0 { if ws_find(req, rn, "GET /health" as *u8, 11)==1 { rlen=ws_health(rbuf) } } 421 if rlen==0 { if ws_find(req, rn, "GET /" as *u8, 5)==1 { rlen=ws_page(rbuf) } } 422 if rlen==0 { rlen=ws_404(rbuf) } 423 ws_write_all(cfd, rbuf, rlen) 424 sys_close(cfd) 425 sys_exit(0) 426 } 427 if pid>0 { live=live+1 } 428 sys_close(cfd) 429 } 430 } 431 return 0 432}