code wiki / _hdl_build / nx_autofix_ensemble.nx

nx_autofix_ensemble.nx source

↩ module page · 138 lines · 5964 B

1// nx_autofix_ensemble.nx -- THE LIVE ENSEMBLE (autonomous-builder lane, 2026-07-20). One command 2// for the measured neuro-symbolic climb: run maker#1 over the whole manifest, auto-run each later 3// maker ONLY on the previous stage's misses, then union the property-verified greens (nx_autofix_cascade). 4// SOUND because the judge (nx_symjudge, autofix stage 5b) property-verifies every green, so unioning 5// diverse makers can never admit a wrong fix. Forks the proven _offc/nx_autofix_auto.elf (per model) 6// + _offc/nx_autofix_cascade.elf (union) -- pure orchestration, miss-extraction in nx_autofix_ens_lib. 7// 8// N-MAKER (2026-07-23, F960 consume half): argv[2..] is a MODEL LIST, not a fixed pair, so the 9// hardware router feeds it directly -- `nx_autofix_ensemble <manifest> $(nx_hw_envelope makers)` runs 10// whatever maker set this host's hwtier- row declares (phone->supercomputer, code unchanged). The 11// measured 3-maker 92% union is now ONE command instead of three runs plus a manual cascade. 12// BACK-COMPAT (rule 19, additive): with exactly two models the staging, prompts, ledger paths and 13// cascade inputs are IDENTICAL to the 2-maker organ -- the old invocation is byte-for-byte the old run. 14// PER-MAKER PROMPT LAW (NB11): maker#1 = the tuned primary -> `clean`; every later maker = general 15// fallback -> `strict`. Bounded by construction: at most AE_MAXMK makers, and the cap is DECLARED in 16// the output (a silently-truncated maker list would read as a complete ensemble). 17// argv: <manifest> <model1> [model2 ...] (manifest rows: name|path) 18// exit: 0. Prints per-stage summaries + the final NX-AUTOFIX-CASCADE ensemble line. 19// license_tier: ORIGINAL No hw writes (Rule 26). 20import "nx_autofix_ens_lib.nx" 21import "nx_seg_store.nx" 22import "nx_deploy_lib.nx" 23import "nx_syscalls.nx" 24 25const AE_CAP: i64 = 1048576 26const AE_MAXMK: i64 = 8 27const AE_PATH: i64 = 64 28const AE_ARGV: i64 = 128 29const AE_ZERO: i64 = 48 30 31func ae_w(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 32func ae_wn(v: i64) -> i64 { 33 var m: i64 = v 34 if m < 0 { ae_w("-" as *u8); m = 0 - m } 35 let t: *u8 = sys_mmap(24) 36 var k: i64 = 0 37 if m == 0 { t[0] = AE_ZERO as u8; k = 1 } 38 while m > 0 { t[k] = (AE_ZERO + (m % 10)) as u8; m = m / 10; k = k + 1 } 39 let o: *u8 = sys_mmap(24) 40 var i: i64 = 0 41 while i < k { o[i] = t[k - 1 - i]; i = i + 1 } 42 sys_write(1, o, k) 43 return 0 44} 45func ae_readfile(path: *u8, box: *i64) -> *u8 { 46 let lb: *i64 = sys_mmap(8) as *i64 47 let b: *u8 = sys_read_file(path, lb) 48 if (b as i64) == 0 { box[0] = 0; return 0 as *u8 } 49 box[0] = lb[0] 50 return b 51} 52func ae_dump(path: *u8) -> i64 { 53 let box: *i64 = sys_mmap(8) as *i64 54 let b: *u8 = ae_readfile(path, box) 55 if (b as i64) != 0 { sys_write(1, b, box[0]) } 56 return 0 57} 58 59// per-stage scratch path; the BUILDER lives in nx_autofix_ens_lib so the gate proves it (a stage-path 60// collision would let maker#3 clobber maker#2's ledger and the union would silently lose a maker). 61func ae_path(pre: *u8, k: i64, suf: *u8) -> *u8 { 62 let dst: *u8 = sys_mmap(AE_PATH) 63 ael_stage_path(dst, pre, k, suf) 64 return dst 65} 66 67func main(argc: i64, argv: *i64) -> i64 { 68 if argc < 3 { ae_w("usage: nx_autofix_ensemble <manifest> <model1> [model2 ...]\n" as *u8); sys_exit(2); return 2 } 69 let manp: *u8 = argv[1] as *u8 70 let loopelf: *u8 = "_offc/nx_autofix_auto.elf" as *u8 71 let casc: *u8 = "_offc/nx_autofix_cascade.elf" as *u8 72 73 var nmk: i64 = argc - 2 74 var capped: i64 = 0 75 if nmk > AE_MAXMK { capped = nmk - AE_MAXMK; nmk = AE_MAXMK } 76 ae_w("=== NX-AUTOFIX-ENSEMBLE makers=" as *u8) 77 ae_wn(nmk) 78 if capped > 0 { ae_w(" CAPPED-DROPPED=" as *u8); ae_wn(capped) } 79 ae_w(" (maker#1 clean prompt, later makers strict)\n" as *u8) 80 81 let av: *i64 = sys_mmap(AE_ARGV) as *i64 82 let lps: *i64 = sys_mmap(AE_MAXMK * 8) as *i64 83 var work: *u8 = manp 84 var stages: i64 = 0 85 var k: i64 = 0 86 while k < nmk { 87 let lp: *u8 = ae_path("/tmp/ens_l" as *u8, k + 1, ".ledger" as *u8) 88 let op: *u8 = ae_path("/tmp/ens_s" as *u8, k + 1, ".out" as *u8) 89 ae_w("=== stage " as *u8) 90 ae_wn(k + 1) 91 ae_w(": maker#" as *u8) 92 ae_wn(k + 1) 93 ae_w("\n" as *u8) 94 av[0] = argv[2 + k] 95 av[1] = work as i64 96 av[2] = lp as i64 97 if k == 0 { av[3] = "clean" as *u8 as i64 } else { av[3] = "strict" as *u8 as i64 } 98 dep_run_capture(loopelf, av, 4, op) 99 lps[stages] = lp as i64 100 stages = stages + 1 101 102 // hand the NEXT maker only what this stage missed (chains: misses-of-misses) 103 let lbox: *i64 = sys_mmap(8) as *i64 104 let lg: *u8 = ae_readfile(lp, lbox) 105 let wbox: *i64 = sys_mmap(8) as *i64 106 let wm: *u8 = ae_readfile(work, wbox) 107 var nmiss: i64 = 0 108 let miss: *u8 = sys_mmap(AE_CAP) 109 let missbox: *i64 = sys_mmap(8) as *i64 110 missbox[0] = 0 111 if (lg as i64) != 0 { if (wm as i64) != 0 { nmiss = ael_extract_misses(lg, lbox[0], wm, wbox[0], miss, missbox) } } 112 ae_w("stage " as *u8) 113 ae_wn(k + 1) 114 ae_w(" misses handed on: " as *u8) 115 ae_wn(nmiss) 116 ae_w("\n" as *u8) 117 if nmiss > 0 { 118 let mp: *u8 = ae_path("/tmp/ens_miss" as *u8, k + 1, ".txt" as *u8) 119 ss_writefile(mp, miss, missbox[0]) 120 work = mp 121 } else { 122 if k + 1 < nmk { ae_w("all instances resolved -- remaining makers SKIPPED (not run, not counted)\n" as *u8) } 123 k = nmk 124 } 125 k = k + 1 126 } 127 128 ae_w("=== NX-AUTOFIX-ENSEMBLE union over " as *u8) 129 ae_wn(stages) 130 ae_w(" ledger(s) ===\n" as *u8) 131 av[0] = manp as i64 132 var j: i64 = 0 133 while j < stages { av[1 + j] = lps[j]; j = j + 1 } 134 dep_run_capture(casc, av, 1 + stages, "/tmp/ens_cascade.out" as *u8) 135 ae_dump("/tmp/ens_cascade.out" as *u8) 136 sys_exit(0) 137 return 0 138}