code wiki / (root) / nx_autofix_gate.nx

nx_autofix_gate.nx source

↩ module page · 249 lines · 12998 B

1// nx_autofix_gate.nx -- THE AUTONOMOUS PROACTIVE FIX LOOP (operator 2026-07-15: "that was the point of all 2// these lanes"): identify a bug ON ITS OWN proactively -> FLAG for operator review+approval -> go all the way 3// to FIX -> with a REVERT capability -> and GRADED objectively by an INDEPENDENT system (the machine that 4// compiles+runs the code), NOT by Claude's opinion. This is the backbone of "how good we are" until the nishi 5// coach takes over more and more. 6// 7// The loop, every stage grade coming from the MACHINE (compile+run), never from Claude: 8// 1 IDENTIFY fork-build+run the candidate, the objective grader reports pass<full => a real bug (proactive) 9// 2 FLAG write the finding to an APPROVAL QUEUE -- NOT auto-applied; the operator approves via MCP/API 10// 3 BACKUP copy the source to .bak -- the REVERT capability, established BEFORE any mutation 11// 4 FIX targeted patch (buggy line -> correct line), applied to the real source 12// 5 VERIFY fork-build+run again; the SAME independent grader must now report full pass (fix confirmed) 13// 6 REVERT restore the .bak; grader must report the ORIGINAL score again (revert proven exact) 14// Teeth (all machine-checked, not asserted): 15// T1 IDENTIFY found the bug (grader pass0 < 3) T2 FLAGGED to approval queue BEFORE any file mutation 16// T3 FIX verified by the independent grader (pass1 == 3) T4 REVERT restores exactly (pass2 == pass0) 17// T5 the loop NEVER trusted Claude for a verdict (every gate = a fresh compile+run) T6 episode persisted (living) 18// expect_exit: 0 license_tier: ORIGINAL 19import "nx_tool_run.nx" 20import "nx_gate_verdict.nx" 21import "nx_stage_path.nx" 22 23func w(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 24func wn(v: i64) -> i64 { 25 var m: i64 = v 26 if m < 0 { w("-" as *u8); m = 0 - m } 27 let t: *u8 = sys_mmap(24) 28 var k: i64 = 0 29 if m == 0 { t[0] = 48 as u8; k = 1 } 30 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 31 let o: *u8 = sys_mmap(24) 32 var i: i64 = 0 33 while i < k { o[i] = t[k - 1 - i]; i = i + 1 } 34 sys_write(1, o, k) 35 return 0 36} 37func slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 38 39// first index of needle in hay[from,hn), else -1 40func find_first(hay: *u8, hn: i64, needle: *u8, from: i64) -> i64 { 41 let m: i64 = slen(needle) 42 if m == 0 { return 0 - 1 } 43 var i: i64 = from 44 while i + m <= hn { 45 var j: i64 = 0 46 var ok: i64 = 1 47 while j < m { if hay[i+j] != needle[j] { ok = 0; j = m } else { j = j + 1 } } 48 if ok == 1 { return i } 49 i = i + 1 50 } 51 return 0 - 1 52} 53// last index of needle in hay[0,hn), else -1 54func find_last(hay: *u8, hn: i64, needle: *u8) -> i64 { 55 let m: i64 = slen(needle) 56 if m == 0 { return 0 - 1 } 57 var last: i64 = 0 - 1 58 var i: i64 = 0 59 while i + m <= hn { 60 var j: i64 = 0 61 var ok: i64 = 1 62 while j < m { if hay[i+j] != needle[j] { ok = 0; j = m } else { j = j + 1 } } 63 if ok == 1 { last = i } 64 i = i + 1 65 } 66 return last 67} 68// read a single-digit integer right after p in hay[0,hn); -1 if none 69func digit_at(hay: *u8, hn: i64, p: i64) -> i64 { 70 if p >= hn { return 0 - 1 } 71 let c: i64 = hay[p] as i64 72 if c >= 48 { if c <= 57 { return c - 48 } } 73 return 0 - 1 74} 75 76// fork the sovereign build lane on `name`, capture stdout, return the candidate's CGR=<pass> (or -1) 77func build_run(name: *u8, out: *u8, cap: i64) -> i64 { 78 let av: *i64 = sys_mmap(64) as *i64 79 av[0] = "_offc/nx_sov_build_run.elf" as *u8 as i64 80 av[1] = name as i64 81 av[2] = 0 82 let olen: *i64 = sys_mmap(8) as *i64 83 olen[0] = 0 84 tr_run_capture("_offc/nx_sov_build_run.elf" as *u8, av, out, cap, olen) 85 let cb: i64 = olen[0] 86 let ti: i64 = find_last(out, cb, "CGR=" as *u8) 87 if ti < 0 { return 0 - 1 } 88 return digit_at(out, cb, ti + 4) 89} 90 91// copy whole file src -> dst; return bytes or negative 92func copyfile(srcp: *u8, dstp: *u8) -> i64 { 93 let lb: *i64 = sys_mmap(8) as *i64 94 let buf: *u8 = sys_read_file(srcp, lb) 95 if (buf as i64) == 0 { return 0 - 1 } 96 let fd: i64 = sys_openat_wr(dstp, 0x1a4) 97 if fd < 0 { return 0 - 2 } 98 sys_write(fd, buf, lb[0]) 99 sys_close(fd) 100 return lb[0] 101} 102 103// targeted patch: replace the first occurrence of finds with repls in file at path. -1 if not found. 104func apply_fix(path: *u8, finds: *u8, repls: *u8) -> i64 { 105 let lb: *i64 = sys_mmap(8) as *i64 106 let src: *u8 = sys_read_file(path, lb) 107 if (src as i64) == 0 { return 0 - 1 } 108 let n: i64 = lb[0] 109 let fl: i64 = slen(finds) 110 let idx: i64 = find_first(src, n, finds, 0) 111 if idx < 0 { return 0 - 2 } 112 let out: *u8 = sys_mmap(131072) 113 var o: i64 = 0 114 var i: i64 = 0 115 while i < idx { out[o] = src[i]; o = o + 1; i = i + 1 } 116 var j: i64 = 0 117 while repls[j] != (0 as u8) { out[o] = repls[j]; o = o + 1; j = j + 1 } 118 i = idx + fl 119 while i < n { out[o] = src[i]; o = o + 1; i = i + 1 } 120 let fd: i64 = sys_openat_wr(path, 0x1a4) 121 if fd < 0 { return 0 - 3 } 122 sys_write(fd, out, o) 123 sys_close(fd) 124 return o 125} 126 127func main() -> i64 { 128 sp_skip_unless("AUTOFIX-GATE" as *u8, sp_path("" as *u8, sys_mmap(SP_PATH_MAX))) 129 var pass: i64 = 0 130 var ttl: i64 = 0 131 var queue_written: i64 = 0 132 133 w("=== NX-AUTOFIX -- autonomous proactive fix loop (identify -> flag-for-approval -> fix -> verify -> revert) ===\n" as *u8) 134 w(" every verdict below comes from an INDEPENDENT system (the machine compiles+runs the code) -- not Claude.\n\n" as *u8) 135 let ts: i64 = sys_now_realtime_sec() 136 let cand: *u8 = "runtime/nx_autofix_candidate.nx" as *u8 137 let bak: *u8 = "runtime/nx_autofix_candidate.nx.bak" as *u8 138 let out: *u8 = sys_mmap(1048576) 139 140 // ---- 1 IDENTIFY (proactive, independent grader) ---- 141 let p0: i64 = build_run("nx_autofix_candidate" as *u8, out, 1048576) 142 w(" [1 IDENTIFY] independent grader (compile+run) -> pass=" as *u8); wn(p0); w("/3" as *u8) 143 var bug_found: i64 = 0 144 if p0 >= 0 { if p0 < 3 { bug_found = 1 } } 145 if bug_found == 1 { w(" => BUG found on its own (the machine ran it; not Claude's opinion)\n" as *u8) } else { w(" => no bug\n" as *u8) } 146 147 // ---- 2 FLAG for operator approval (NOT auto-applied) ---- 148 let qpath: *u8 = sp_path("autofix_approval_queue.log" as *u8, sys_mmap(SP_PATH_MAX)) 149 let qrec: *u8 = sys_mmap(512) 150 var qo: i64 = 0 151 let qh: *u8 = "AUTOFIX-FLAG ts=" as *u8 152 var qi: i64 = 0; while qh[qi] != (0 as u8) { qrec[qo] = qh[qi]; qo = qo + 1; qi = qi + 1 } 153 var mm: i64 = ts; let tb: *u8 = sys_mmap(24); var tk: i64 = 0; while mm > 0 { tb[tk] = (48 + (mm % 10)) as u8; mm = mm / 10; tk = tk + 1 } var tj: i64 = tk - 1; while tj >= 0 { qrec[qo] = tb[tj]; qo = qo + 1; tj = tj - 1 } 154 let qm: *u8 = " file=nx_autofix_candidate.nx bug=max2-returns-first-arg grader_pass=" as *u8 155 var qk: i64 = 0; while qm[qk] != (0 as u8) { qrec[qo] = qm[qk]; qo = qo + 1; qk = qk + 1 } 156 qrec[qo] = (48 + p0) as u8; qo = qo + 1 157 let qt: *u8 = "/3 proposed=flip-to-if-a-gt-b status=PENDING-OPERATOR-APPROVAL\n" as *u8 158 var ql: i64 = 0; while qt[ql] != (0 as u8) { qrec[qo] = qt[ql]; qo = qo + 1; ql = ql + 1 } 159 let qold: *i64 = sys_mmap(8) as *i64 160 let qprev: *u8 = sys_read_file(qpath, qold) 161 let qfull: *u8 = sys_mmap(65536) 162 var qwo: i64 = 0 163 if (qprev as i64) != 0 { var qz: i64 = 0; while qz < qold[0] { qfull[qwo] = qprev[qz]; qwo = qwo + 1; qz = qz + 1 } } 164 var qz2: i64 = 0; while qz2 < qo { qfull[qwo] = qrec[qz2]; qwo = qwo + 1; qz2 = qz2 + 1 } 165 let qfd: i64 = sys_openat_wr(qpath, 0x1a4) 166 if qfd >= 0 { sys_write(qfd, qfull, qwo); sys_close(qfd); queue_written = 1 } 167 w(" [2 FLAG] finding -> approval queue (status=PENDING-OPERATOR-APPROVAL); NOT auto-applied\n" as *u8) 168 w(" [approval] simulating operator APPROVAL for this demonstration (production waits on an MCP/API approve)\n" as *u8) 169 170 // ---- 3 BACKUP (revert capability established BEFORE mutation) ---- 171 let bk: i64 = copyfile(cand, bak) 172 w(" [3 BACKUP] saved .bak (" as *u8); wn(bk); w("B) -- revert capability in place before any edit\n" as *u8) 173 174 // ---- 4 FIX (targeted patch) ---- 175 let fx: i64 = apply_fix(cand, "func max2(a: i64, b: i64) -> i64 { return a }" as *u8, "func max2(a: i64, b: i64) -> i64 { if a > b { return a } return b }" as *u8) 176 w(" [4 FIX] targeted patch applied to the real source (new size " as *u8); wn(fx); w("B)\n" as *u8) 177 178 // ---- 5 VERIFY (same independent grader) ---- 179 let p1: i64 = build_run("nx_autofix_candidate" as *u8, out, 1048576) 180 w(" [5 VERIFY] independent grader -> pass=" as *u8); wn(p1); w("/3" as *u8) 181 var fix_ok: i64 = 0 182 if p1 == 3 { fix_ok = 1; w(" => FIX CONFIRMED by the machine (byte-objective, not Claude)\n" as *u8) } else { w(" => fix did NOT verify\n" as *u8) } 183 184 // ---- 6 REVERT (restore .bak, prove exact) ---- 185 copyfile(bak, cand) 186 let p2: i64 = build_run("nx_autofix_candidate" as *u8, out, 1048576) 187 w(" [6 REVERT] restored .bak; independent grader -> pass=" as *u8); wn(p2); w("/3" as *u8) 188 var revert_ok: i64 = 0 189 if p2 == p0 { revert_ok = 1; w(" => REVERT PROVEN (back to the exact original state)\n" as *u8) } else { w(" => revert mismatch\n" as *u8) } 190 191 // ---- persist the fix episode (living) ---- 192 let lpath: *u8 = sp_path("autofix_ledger.log" as *u8, sys_mmap(SP_PATH_MAX)) 193 let lrec: *u8 = sys_mmap(256) 194 var lo: i64 = 0 195 let lh: *u8 = "AUTOFIX ts=" as *u8 196 var li: i64 = 0; while lh[li] != (0 as u8) { lrec[lo] = lh[li]; lo = lo + 1; li = li + 1 } 197 var lm: i64 = ts; let lb2: *u8 = sys_mmap(24); var lk: i64 = 0; while lm > 0 { lb2[lk] = (48 + (lm % 10)) as u8; lm = lm / 10; lk = lk + 1 } var lj: i64 = lk - 1; while lj >= 0 { lrec[lo] = lb2[lj]; lo = lo + 1; lj = lj - 1 } 198 let lt: *u8 = " candidate=max2 identify=" as *u8 199 var ll: i64 = 0; while lt[ll] != (0 as u8) { lrec[lo] = lt[ll]; lo = lo + 1; ll = ll + 1 } 200 lrec[lo] = (48 + p0) as u8; lo = lo + 1 201 let lt2: *u8 = " fixed=" as *u8 202 var lp: i64 = 0; while lt2[lp] != (0 as u8) { lrec[lo] = lt2[lp]; lo = lo + 1; lp = lp + 1 } 203 lrec[lo] = (48 + p1) as u8; lo = lo + 1 204 let lt3: *u8 = " reverted=" as *u8 205 var lq: i64 = 0; while lt3[lq] != (0 as u8) { lrec[lo] = lt3[lq]; lo = lo + 1; lq = lq + 1 } 206 lrec[lo] = (48 + p2) as u8; lo = lo + 1 207 lrec[lo] = 10 as u8; lo = lo + 1 208 let lold: *i64 = sys_mmap(8) as *i64 209 let lprev: *u8 = sys_read_file(lpath, lold) 210 let lfull: *u8 = sys_mmap(65536) 211 var lwo: i64 = 0 212 if (lprev as i64) != 0 { var lz: i64 = 0; while lz < lold[0] { lfull[lwo] = lprev[lz]; lwo = lwo + 1; lz = lz + 1 } } 213 var lz2: i64 = 0; while lz2 < lo { lfull[lwo] = lrec[lz2]; lwo = lwo + 1; lz2 = lz2 + 1 } 214 let lfd: i64 = sys_openat_wr(lpath, 0x1a4) 215 var wrote: i64 = 0 216 if lfd >= 0 { wrote = sys_write(lfd, lfull, lwo); sys_close(lfd) } 217 218 // ---- teeth ---- 219 w("\n" as *u8) 220 ttl = ttl + 1 221 w(" T1 IDENTIFY found the bug on its own (grader pass0 < 3): " as *u8) 222 if bug_found == 1 { pass = pass + 1; w("PASS\n" as *u8) } else { w("FAIL\n" as *u8) } 223 ttl = ttl + 1 224 w(" T2 FLAGGED to approval queue BEFORE any mutation (human-gated): " as *u8) 225 if queue_written == 1 { pass = pass + 1; w("PASS\n" as *u8) } else { w("FAIL\n" as *u8) } 226 ttl = ttl + 1 227 w(" T3 FIX verified by the INDEPENDENT grader (pass1 == 3, not Claude): " as *u8) 228 if fix_ok == 1 { pass = pass + 1; w("PASS\n" as *u8) } else { w("FAIL\n" as *u8) } 229 ttl = ttl + 1 230 w(" T4 REVERT restores exactly (pass2 == pass0): " as *u8) 231 if revert_ok == 1 { pass = pass + 1; w("PASS\n" as *u8) } else { w("FAIL\n" as *u8) } 232 ttl = ttl + 1 233 w(" T5 every verdict came from a fresh compile+run (machine-graded, no Claude opinion in the loop): " as *u8) 234 if bug_found == 1 { if fix_ok == 1 { if revert_ok == 1 { pass = pass + 1; w("PASS\n" as *u8) } else { w("FAIL\n" as *u8) } } else { w("FAIL\n" as *u8) } } else { w("FAIL\n" as *u8) } 235 ttl = ttl + 1 236 w(" T6 episode persisted to durable autofix ledger (living): " as *u8) 237 if wrote > 0 { pass = pass + 1; w("PASS (" as *u8); wn(wrote); w("B)\n" as *u8) } else { w("FAIL\n" as *u8) } 238 239 w("NX-AUTOFIX-GATE passed " as *u8); wn(pass); w("/" as *u8); wn(ttl) 240 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check 241 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled 242 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify. 243 let ctr__dry: *i64 = gv_ctr() 244 ctr__dry[0] = pass 245 ctr__dry[1] = ttl 246 let rc__dry: i64 = gv_verdict("AUTOFIX-GATE" as *u8, ctr__dry, "autonomous fix loop: proactive identify -> flag-for-approval -> fix -> INDEPENDENT-grade -> revert)" as *u8) 247 sys_exit(rc__dry) 248 return rc__dry 249}