code wiki / _hdl_build / nx_uigen_refine.nx

nx_uigen_refine.nx source

↩ module page · 131 lines · 6578 B

1// nx_uigen_refine.nx -- R-refine-live front door: apply ONE spec-delta refine command to a generated 2// site's design and emit the refined INDEX page. The v0 chat-loop analog, rule-based and deterministic: 3// the SAME l3_refine grammar the refine gate measured 8/8 (targeted change + preservation + refusal), 4// lifted to site level -- the spec is derived from the brief exactly as nx_uigen_sitegen derives it, the 5// command mutates one axis, and the page re-emits with the site's real nav + requirements copy intact. 6// usage: nx_uigen_refine <brief> <cmd> <outdir> [title] [brand] [domain] [reqfile] 7// cmds: "hue N" | "accent analog|complement|triad" | "rounder"|"sharper" | "compact"|"airy" | 8// "add <band>" | "drop <band>" (bands: features split steps pricing quote faq trust) 9// An invalid or validity-breaking command is REFUSED loudly (exit 5, nothing written) -- never a silent 10// no-op. expect_exit: 0 license_tier: ORIGINAL 11import "nx_syscalls.nx" 12import "nx_uigen_site.nx" 13import "nx_emit_guard.nx" 14 15// one page buffer (a page is ~20KB; 1MiB is 50x headroom) and one path buffer -- named so the 16// magic-number ratchet stays satisfied and the sizes are stated once (rule 11). 17const K_PAGEBUF: i64 = 1048576 18const K_PATHBUF: i64 = 1024 19 20 21func rp(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 22func rjoin(dst: *u8, dir: *u8, name: *u8) -> i64 { 23 var o: i64 = 0 24 var i: i64 = 0 25 while dir[i] != (0 as u8) { dst[o] = dir[i]; o = o + 1; i = i + 1 } 26 dst[o] = 47 as u8 27 o = o + 1 28 i = 0 29 while name[i] != (0 as u8) { dst[o] = name[i]; o = o + 1; i = i + 1 } 30 dst[o] = 0 as u8 31 return o 32} 33func rn(v: i64) -> i64 { if v==0 { sys_write(1,"0" as *u8,1); return 0 } var m: i64=v; if m<0 { sys_write(1,"-" as *u8,1); m=0-m } let t: *u8=sys_mmap(28); var k: i64=0; while m>0 { t[k]=(48+(m%10)) as u8; m=m/10; k=k+1 } while k>0 { k=k-1; sys_write(1,(((t as i64)+k) as *u8),1) } return 0 } 34 35func main(argc: i64, argv: *i64) -> i64 { 36 if argc < 4 { 37 rp("usage: nx_uigen_refine <brief> <cmd> <outdir> [title] [brand] [domain] [reqfile]\n" as *u8) 38 rp(" applies ONE refine command to the brief's generated design and re-emits the WHOLE site\n" as *u8) 39 rp(" <cmd> is ONE argv token: 'hue <0-359>' | 'accent analog|complement|triad' | 'sharper' |\n" as *u8) 40 rp(" 'rounder' | 'compact' | 'airy' | 'add <section>' | 'drop <section>' (quote two-word cmds)\n" as *u8) 41 sys_exit(2) 42 return 2 43 } 44 let brief: *u8 = argv[1] as *u8 45 let cmd: *u8 = argv[2] as *u8 46 let outpath: *u8 = argv[3] as *u8 47 var title: *u8 = "Generated Site" as *u8 48 if argc > 4 { title = argv[4] as *u8 } 49 var brand: *u8 = title 50 if argc > 5 { brand = argv[5] as *u8 } 51 var domain: *u8 = "example.com" as *u8 52 if argc > 6 { domain = argv[6] as *u8 } 53 var req: *u8 = 0 as *u8 54 if argc > 7 { 55 let rlen: *i64 = sys_mmap(8) as *i64 56 let raw: *u8 = sys_read_file(argv[7] as *u8, rlen) 57 if (raw as i64) == 0 { rp("REFINE-FAIL cannot read reqfile\n" as *u8); sys_exit(4); return 4 } 58 let rl: i64 = rlen[0] 59 req = sys_mmap(rl + 1) 60 var ci: i64 = 0 61 while ci < rl { req[ci] = raw[ci]; ci = ci + 1 } 62 req[rl] = 0 as u8 63 } 64 65 let plan: *i64 = sys_mmap(64) as *i64 66 let n: i64 = us_plan(brief, plan) 67 let spec: *i64 = sys_mmap(128) as *i64 68 us_spec(brief, spec) 69 let applied: i64 = l3_refine(spec, cmd) 70 if applied == 0 { 71 rp("REFINE-REFUSED cmd=" as *u8); rp(cmd) 72 rp(" (unknown command or it would break grammar validity); nothing written\n" as *u8) 73 sys_exit(5) 74 return 5 75 } 76 // ★ refine the WHOLE SITE, not just the index. Rewriting only index.html left every subpage on the 77 // OLD palette -- a refined site that contradicts itself, which is precisely the site-wide coherence 78 // this lane advertises. outpath is a DIRECTORY; sitemap+robots re-derive from the same plan. 79 let mk: i64 = sys_mkdir(outpath, 493) 80 // guards live in nx_emit_guard (one home, both emitter CLIs) 81 let buf: *u8 = eg_buf(K_PAGEBUF, "refine page buffer" as *u8) 82 let path: *u8 = eg_buf(K_PATHBUF, "refine path buffer" as *u8) 83 rp("REFINE-DIAG mkdir=" as *u8); rn(mk); rp(" pages=" as *u8); rn(n); rp(" lens=" as *u8) 84 var total: i64 = 0 85 var pi: i64 = 0 86 while pi < n { 87 var len: i64 = 0 88 if plan[pi] == 0 { len = us_page_index_routed(buf, 0, brief, spec, title, brand, plan, n, req) } 89 else { len = us_emit_page_req_spec(buf, 0, brief, spec, title, brand, plan, n, plan[pi], req) } 90 rn(len); rp("," as *u8) 91 eg_assert_size(len, "refined page" as *u8) 92 rjoin(path, outpath, us_slug(plan[pi])) 93 let fd: i64 = sys_openat_wr(path, 420) 94 if fd < 0 { rp("REFINE-FAIL cannot write " as *u8); rp(path); rp("\n" as *u8); sys_exit(3); return 3 } 95 let w: i64 = sys_write(fd, buf, len) 96 sys_close(fd) 97 if w != len { rp("REFINE-FAIL short write\n" as *u8); sys_exit(3); return 3 } 98 total = total + len 99 pi = pi + 1 100 } 101 var ml: i64 = us_sitemap(buf, 0, domain, plan, n) 102 rjoin(path, outpath, "sitemap.xml" as *u8) 103 let mfd: i64 = sys_openat_wr(path, 420) 104 if mfd < 0 { rp("REFINE-FAIL cannot write sitemap\n" as *u8); sys_exit(3); return 3 } 105 sys_write(mfd, buf, ml); sys_close(mfd) 106 ml = us_robots(buf, 0, domain) 107 rjoin(path, outpath, "robots.txt" as *u8) 108 let rfd: i64 = sys_openat_wr(path, 420) 109 if rfd < 0 { rp("REFINE-FAIL cannot write robots\n" as *u8); sys_exit(3); return 3 } 110 sys_write(rfd, buf, ml); sys_close(rfd) 111 // ★ POST-WRITE SET ASSERTION: every planned slug must exist on disk before success is printed. 112 // A tool that emits a SET must prove the SET, not each file in isolation (the round-18 law). 113 var vi: i64 = 0 114 while vi < n { 115 rjoin(path, outpath, us_slug(plan[vi])) 116 eg_assert_present(path) 117 vi = vi + 1 118 } 119 let len: i64 = total 120 rp("\n" as *u8) 121 rp("{\"organ\":\"nx_uigen_refine\",\"v\":1,\"cmd\":\"" as *u8); rp(cmd) 122 rp("\",\"applied\":1,\"hue\":" as *u8); rn(spec[0]) 123 rp(",\"accent_rel\":" as *u8); rn(spec[1]) 124 rp(",\"radius_idx\":" as *u8); rn(spec[2]) 125 rp(",\"density\":" as *u8); rn(spec[3]) 126 rp(",\"nmid\":" as *u8); rn(spec[4]) 127 rp(",\"bytes\":" as *u8); rn(len) 128 rp(",\"env\":\"one command per call off the brief-derived spec; deterministic; grammar-refusal is loud (exit 5)\"}\n" as *u8) 129 sys_exit(0) 130 return 0 131}