code wiki / _hdl_build / nx_worldgen_refine.nx
nx_worldgen_refine.nx source
↩ module page · 334 lines · 15299 B
1// nx_worldgen_refine.nx -- TEAM-OWNED worldgen quality gate + AUTO-REFINE
2// loop (operator 2026-06-10: "s class exceed instead of our crummy proc gen
3// -- build the team to do the work"; operator 2026-05-16: "build an iterative
4// loop ... i dont want to have to manually check if you generate good maps").
5//
6// The loop nobody has to babysit:
7// nx_procgen_landscape(seed, preset, w, h, density) -- current generator
8// -> nx_world_quality_grade (8 axes, Q14, sealed F..S, refine_axis)
9// -> hill-climb the exposed knobs (preset x density x seed batch)
10// -> bank the BEST params to /tmp/nishi_worldgen_best.conf (data-driven;
11// the voxel build reads params, never hardcodes them -- Cardinal 11)
12//
13// HONEST BASELINE FIRST: the first sweep grades the CURRENT generator as-is.
14// "Crummy" becomes a NUMBER with named failing axes; every later rung
15// (composed primitives: causal rivers, erosion, constraint placement per
16// the procgen cardinals) must MOVE that number through this same gate.
17// Note the grader's own posture: Minecraft/No-Man's-Sky/Houdini have NO
18// mathematical world-quality verdict -- this instrument is itself the
19// EXCEED axis; S-class = the generator earns NX_GRADE_S under it.
20//
21// WORLDGEN lines -> stdout + /tmp/nishi_worldgen_gate.log.
22// Exit: 0 if best grade >= floor (argv[1], default C=2), else 1.
23// license_tier: ORIGINAL
24import "nx_syscalls.nx"
25import "nx_tier.nx"
26import "nx_worldgen_tunelib.nx"
27const WR_MAGIC_8192: i64 = 8192
28const WR_MAGIC_8191: i64 = 8191
29
30const WR_W: i64 = 64
31const WR_H: i64 = 64
32const WR_RELIEF: i64 = 1024 // Q10 full-scale elevation
33const WR_SEEDS_PER_CFG: i64 = 3 // median-ish stability without burning cycles
34const WR_DENSITY_STEPS: i64 = 4 // density_q10 in {512, 1024, 1536, 2048}
35
36func wr_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
37func wr_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 }
38func wr_cat_n(dst: *u8, off: i64, v: i64) -> i64 {
39 var o: i64 = off
40 var m: i64 = v
41 if m < 0 { dst[o] = 45; o = o + 1; m = 0 - m }
42 let t: *u8 = sys_mmap(28)
43 var k: i64 = 0
44 if m == 0 { t[0] = 48; k = 1 }
45 while m > 0 { t[k] = 48 + (m % 10); m = m / 10; k = k + 1 }
46 var i: i64 = 0
47 while i < k { dst[o+i] = t[k-1-i]; i = i + 1 }
48 return o + k
49}
50
51func wr_grade_name(g: i64) -> *u8 {
52 if g == NX_GRADE_F { return "F" as *u8 }
53 if g == NX_GRADE_D { return "D" as *u8 }
54 if g == NX_GRADE_C { return "C" as *u8 }
55 if g == NX_GRADE_B { return "B" as *u8 }
56 if g == NX_GRADE_A { return "A" as *u8 }
57 if g == NX_GRADE_S { return "S" as *u8 }
58 return "?" as *u8
59}
60
61func wr_refine_name(r: i64) -> *u8 {
62 if r == NX_WQG_REFINE_NONE { return "NONE" as *u8 }
63 if r == NX_WQG_REFINE_MORE_RELIEF { return "MORE_RELIEF" as *u8 }
64 if r == NX_WQG_REFINE_MORE_FEATURES { return "MORE_FEATURES" as *u8 }
65 if r == NX_WQG_REFINE_LESS_FLATNESS { return "LESS_FLATNESS" as *u8 }
66 if r == NX_WQG_REFINE_ADD_DETAIL { return "ADD_DETAIL" as *u8 }
67 if r == NX_WQG_REFINE_SMOOTH_NOISE { return "SMOOTH_NOISE" as *u8 }
68 if r == NX_WQG_REFINE_FIX_FRACTAL { return "FIX_FRACTAL" as *u8 }
69 if r == NX_WQG_REFINE_FIX_BIOMES { return "FIX_BIOMES" as *u8 }
70 if r == NX_WQG_REFINE_MORE_VARIETY { return "MORE_VARIETY" as *u8 }
71 if r == NX_WQG_REFINE_IMPROVE_READ { return "IMPROVE_READ" as *u8 }
72 return "?" as *u8
73}
74
75// grade ONE config (preset, density) over WR_SEEDS_PER_CFG seeds; returns the
76// WORST grade across seeds (a preset must be reliably good, not lucky) and
77// copies the worst-seed verdict into out12.
78func wr_eval_cfg(preset: i64, density_q10: i64, out12: *i64) -> i64 {
79 // The eval body lives in nx_worldgen_tunelib (tl_compose_world =
80 // P1 signature + P4 water + detail, knob-explicit; tl_eval feeds the
81 // P2 biome + P3 feature axes). Knobs come from the TUNER's banked
82 // conf (config hierarchy: banked > preset table), so the gate metric
83 // IS the tuned metric -- the tuner's win shows up here next beat.
84 let knobs: *i64 = sys_mmap(TL_K_COUNT * 8) as *i64
85 tl_load_knobs("knowledge/status/worldgen_knobs.conf" as *u8, preset, knobs)
86 return tl_eval(preset, density_q10, knobs, out12)
87}
88
89func wr_report(logfd: i64, ts: i64, preset: i64, density: i64, out12: *i64) -> i64 {
90 let line: *u8 = sys_mmap(512)
91 var o: i64 = 0
92 o = wr_cat(line, o, "WORLDGEN ts=" as *u8)
93 o = wr_cat_n(line, o, ts)
94 o = wr_cat(line, o, " preset=" as *u8)
95 o = wr_cat_n(line, o, preset)
96 o = wr_cat(line, o, " density=" as *u8)
97 o = wr_cat_n(line, o, density)
98 o = wr_cat(line, o, " grade=" as *u8)
99 o = wr_cat(line, o, wr_grade_name(out12[0]))
100 o = wr_cat(line, o, " div=" as *u8); o = wr_cat_n(line, o, out12[1])
101 o = wr_cat(line, o, " var=" as *u8); o = wr_cat_n(line, o, out12[2])
102 o = wr_cat(line, o, " ext=" as *u8); o = wr_cat_n(line, o, out12[3])
103 o = wr_cat(line, o, " flat=" as *u8); o = wr_cat_n(line, o, out12[4])
104 o = wr_cat(line, o, " frac=" as *u8); o = wr_cat_n(line, o, out12[5])
105 o = wr_cat(line, o, " biome=" as *u8); o = wr_cat_n(line, o, out12[6])
106 o = wr_cat(line, o, " feat=" as *u8); o = wr_cat_n(line, o, out12[7])
107 o = wr_cat(line, o, " read=" as *u8); o = wr_cat_n(line, o, out12[8])
108 o = wr_cat(line, o, " refine=" as *u8)
109 o = wr_cat(line, o, wr_refine_name(out12[9]))
110 o = wr_cat(line, o, "\n" as *u8)
111 sys_write(1, line, o)
112 if logfd >= 0 { sys_write(logfd, line, o) }
113 return 0
114}
115
116// OSCILLATION DETECTOR (2026-06-10): the verdict loop's own callout
117// handler. Each verdict CHANGE appends its axis to a durable history;
118// when the newest axis equals the one before last (A -> B -> A) while
119// the grade did not climb, knob-space is provably exhausted between the
120// two axes -- the loop files ONE STRUCTURAL escalation naming both,
121// instead of re-filing the same two assignments forever (the ext/read
122// ping-pong at grade C that motivated this).
123func wr_oscillation_check(ts: i64, grade: i64, axis: i64) -> i64 {
124 let hist: *u8 = "knowledge/status/worldgen_verdict_hist.log" as *u8
125 // append this change: "AXIS <id> GRADE <g>\n" (ids parse back as ints)
126 let hfd: i64 = sys_openat_append(hist, 0x1a4)
127 if hfd >= 0 {
128 let hl: *u8 = sys_mmap(64)
129 var ho: i64 = 0
130 ho = wr_cat(hl, ho, "AXIS " as *u8)
131 ho = wr_cat_n(hl, ho, axis)
132 ho = wr_cat(hl, ho, " GRADE " as *u8)
133 ho = wr_cat_n(hl, ho, grade)
134 ho = wr_cat(hl, ho, "\n" as *u8)
135 sys_write(hfd, hl, ho)
136 sys_fsync(hfd)
137 sys_close(hfd)
138 }
139 // read back the last 3 entries (axis, grade)
140 let buf: *u8 = sys_mmap(WR_MAGIC_8192)
141 let n: i64 = tl_read_file(hist, buf, WR_MAGIC_8191)
142 if n <= 0 { return 0 }
143 let ax: *i64 = sys_mmap(3 * 8) as *i64
144 let gr: *i64 = sys_mmap(3 * 8) as *i64
145 var cnt: i64 = 0
146 var i: i64 = 0
147 while i < n {
148 var at_start: i64 = 0
149 if i == 0 { at_start = 1 }
150 if i > 0 { if buf[i - 1] == (10 as u8) { at_start = 1 } }
151 if at_start == 1 {
152 if buf[i] == (65 as u8) { // 'A' of AXIS
153 var v: i64 = 0
154 var j: i64 = i + 5
155 while j < n {
156 let c: i64 = buf[j] as i64
157 if c >= 48 { if c <= 57 { v = v * 10 + (c - 48); j = j + 1 } else { j = n + 1 } } else { j = n + 1 }
158 }
159 // grade after " GRADE "
160 var g: i64 = 0 - 1
161 var k: i64 = i + 5
162 while k < n {
163 if buf[k] == (10 as u8) { k = n + 1 } else {
164 if buf[k] == (71 as u8) { // 'G'
165 var gv: i64 = 0
166 var m: i64 = k + 6
167 var any: i64 = 0
168 while m < n {
169 let c2: i64 = buf[m] as i64
170 if c2 >= 48 { if c2 <= 57 { gv = gv * 10 + (c2 - 48); any = 1; m = m + 1 } else { m = n + 1 } } else { m = n + 1 }
171 }
172 if any == 1 { g = gv }
173 k = n + 1
174 } else { k = k + 1 }
175 }
176 }
177 // shift-in (keep last 3)
178 if cnt < 3 {
179 ax[cnt] = v; gr[cnt] = g; cnt = cnt + 1
180 } else {
181 ax[0] = ax[1]; ax[1] = ax[2]; ax[2] = v
182 gr[0] = gr[1]; gr[1] = gr[2]; gr[2] = g
183 }
184 }
185 }
186 i = i + 1
187 }
188 if cnt < 3 { return 0 }
189 // A -> B -> A with no grade climb = structural escalation
190 if ax[2] != ax[0] { return 0 }
191 if ax[1] == ax[2] { return 0 }
192 if gr[2] > gr[0] { return 0 }
193 let pfd: i64 = sys_openat_append("knowledge/status/pm_plan_durable.log" as *u8, 0x1a4)
194 if pfd >= 0 {
195 let row: *u8 = sys_mmap(512)
196 var ro: i64 = 0
197 ro = wr_cat(row, ro, "arc=PROCGEN step=STRUCTURAL-ESCALATION ts=" as *u8)
198 ro = wr_cat_n(row, ro, ts)
199 ro = wr_cat(row, ro, " AUTO-FILED by nx_worldgen_refine OSCILLATION DETECTOR: verdict ping-pong " as *u8)
200 ro = wr_cat(row, ro, wr_refine_name(ax[0]))
201 ro = wr_cat(row, ro, " <-> " as *u8)
202 ro = wr_cat(row, ro, wr_refine_name(ax[1]))
203 ro = wr_cat(row, ro, " at grade=" as *u8)
204 ro = wr_cat(row, ro, wr_grade_name(grade))
205 ro = wr_cat(row, ro, " with no grade climb -- KNOB-SPACE EXHAUSTED between these axes; a composed-primitive STRUCTURAL rung is required (tuning cannot close this) owner=Builder\n" as *u8)
206 sys_write(pfd, row, ro)
207 sys_fsync(pfd)
208 sys_close(pfd)
209 }
210 return 1
211}
212
213func main(argc: i64, argv: *i64) -> i64 {
214 // Default floor = the measured 2026-06-10 BASELINE (D): the gate's job in
215 // the game-gate is REGRESSION protection (never ship worse than today).
216 // The CLIMB target (S, per the PROCGEN arc) lives in the PM plan and is
217 // asserted by running this gate with argv[1]=5 at each rung's close.
218 var floor_grade: i64 = NX_GRADE_D
219 if argc >= 2 {
220 let a: *u8 = argv[1] as *u8
221 if a[0] >= 48 { if a[0] <= 53 { floor_grade = (a[0] as i64) - 48 } }
222 }
223 let logfd: i64 = sys_openat_append("/tmp/nishi_worldgen_gate.log" as *u8, 0x1a4)
224 let ts: i64 = sys_now_realtime_sec()
225
226 let out12: *i64 = sys_mmap(8 * 12) as *i64
227 var best_grade: i64 = 0 - 1
228 var best_preset: i64 = 0
229 var best_density: i64 = 0
230 let best12: *i64 = sys_mmap(8 * 12) as *i64
231
232 // full sweep: every preset x density step. This IS the refine loop at
233 // Tier-1 (the only knobs the current generator exposes). When composed
234 // primitives land (rivers/erosion/constraints), their knobs join here.
235 var preset: i64 = 0
236 while preset <= NX_PROCGEN_PRESET_MOUNTAIN {
237 var d: i64 = 0
238 while d < WR_DENSITY_STEPS {
239 let density: i64 = 512 + d * 512
240 let g: i64 = wr_eval_cfg(preset, density, out12)
241 wr_report(logfd, ts, preset, density, out12)
242 if g > best_grade {
243 best_grade = g
244 best_preset = preset
245 best_density = density
246 var c: i64 = 0
247 while c < 12 { best12[c] = out12[c]; c = c + 1 }
248 }
249 d = d + 1
250 }
251 preset = preset + 1
252 }
253
254 // bank the best params (data-driven config -- consumers read, not hardcode)
255 let cl: *u8 = sys_mmap(256)
256 var co: i64 = 0
257 co = wr_cat(cl, co, "preset=" as *u8); co = wr_cat_n(cl, co, best_preset)
258 co = wr_cat(cl, co, "\ndensity_q10=" as *u8); co = wr_cat_n(cl, co, best_density)
259 co = wr_cat(cl, co, "\ngrade=" as *u8); co = wr_cat(cl, co, wr_grade_name(best_grade))
260 co = wr_cat(cl, co, "\nrefine_axis=" as *u8); co = wr_cat(cl, co, wr_refine_name(best12[9]))
261 co = wr_cat(cl, co, "\n" as *u8)
262
263 // VERDICT-CHANGE AUTONOMY (2026-06-10): the grader's directive is an
264 // ASSIGNMENT, not a suggestion. Compare against the DURABLE banked
265 // verdict (reboot-proof home); when it changed, auto-file one pm_plan
266 // row naming the next axis -- the team's backlog grows from gate
267 // evidence with no LLM in the loop. One row per CHANGE, never per
268 // beat (the durable conf is the dedup state).
269 let durable_conf: *u8 = "knowledge/status/worldgen_best.conf" as *u8
270 var changed: i64 = 1
271 let ofd: i64 = sys_openat_rd(durable_conf)
272 if ofd >= 0 {
273 let old: *u8 = sys_mmap(256)
274 let on: i64 = sys_read(ofd, old, 255)
275 sys_close(ofd)
276 if on == co {
277 changed = 0
278 var ci: i64 = 0
279 while ci < co {
280 if old[ci] != cl[ci] { changed = 1; ci = co } else { ci = ci + 1 }
281 }
282 }
283 }
284 if changed == 1 {
285 let pfd: i64 = sys_openat_append("knowledge/status/pm_plan_durable.log" as *u8, 0x1a4)
286 if pfd >= 0 {
287 let row: *u8 = sys_mmap(512)
288 var ro: i64 = 0
289 ro = wr_cat(row, ro, "arc=PROCGEN step=REFINE-VERDICT ts=" as *u8)
290 ro = wr_cat_n(row, ro, ts)
291 ro = wr_cat(row, ro, " AUTO-FILED by nx_worldgen_refine (verdict changed): best grade=" as *u8)
292 ro = wr_cat(row, ro, wr_grade_name(best_grade))
293 ro = wr_cat(row, ro, " preset=" as *u8)
294 ro = wr_cat_n(row, ro, best_preset)
295 ro = wr_cat(row, ro, " density=" as *u8)
296 ro = wr_cat_n(row, ro, best_density)
297 ro = wr_cat(row, ro, " next-refine=" as *u8)
298 ro = wr_cat(row, ro, wr_refine_name(best12[9]))
299 ro = wr_cat(row, ro, " -- the named axis is the next PROCGEN assignment owner=Builder\n" as *u8)
300 sys_write(pfd, row, ro)
301 sys_fsync(pfd)
302 sys_close(pfd)
303 }
304 wr_oscillation_check(ts, best_grade, best12[9])
305 }
306
307 // dual-write: durable home first (the dedup state), then the /tmp
308 // consumer contract (voxel build reads this path)
309 let dfd: i64 = sys_openat_wr(durable_conf, 0x1a4)
310 if dfd >= 0 { sys_write(dfd, cl, co); sys_fsync(dfd); sys_close(dfd) }
311 let cfd: i64 = sys_openat_wr("/tmp/nishi_worldgen_best.conf" as *u8, 0x1a4)
312 if cfd >= 0 { sys_write(cfd, cl, co); sys_close(cfd) }
313
314 let sline: *u8 = sys_mmap(384)
315 var o: i64 = 0
316 o = wr_cat(sline, o, "WORLDGEN SUMMARY ts=" as *u8)
317 o = wr_cat_n(sline, o, ts)
318 o = wr_cat(sline, o, " BEST grade=" as *u8)
319 o = wr_cat(sline, o, wr_grade_name(best_grade))
320 o = wr_cat(sline, o, " preset=" as *u8)
321 o = wr_cat_n(sline, o, best_preset)
322 o = wr_cat(sline, o, " density=" as *u8)
323 o = wr_cat_n(sline, o, best_density)
324 o = wr_cat(sline, o, " next-refine=" as *u8)
325 o = wr_cat(sline, o, wr_refine_name(best12[9]))
326 o = wr_cat(sline, o, " floor=" as *u8)
327 o = wr_cat(sline, o, wr_grade_name(floor_grade))
328 o = wr_cat(sline, o, "\n" as *u8)
329 sys_write(1, sline, o)
330 if logfd >= 0 { sys_write(logfd, sline, o); sys_close(logfd) }
331
332 if best_grade < floor_grade { return 1 }
333 return 0
334}