code wiki / _hdl_build / nx_gramdec_gate.nx

nx_gramdec_gate.nx source

↩ module page · 238 lines · 10262 B

1// nx_gramdec_gate.nx -- NB10 gate: grammar-constrained decode (nx_gramdec_lib) teeth. 2// T1-T8 = automaton ruler teeth (no model). T9 = LIVE no-op equivalence: on an already-grammatical 3// greedy generation the constrained decode must be BIT-EXACT (prefix) with nsv_generate, zero 4// rejections, accept-stop. T10 = LIVE mask-fires (anti-vacuity + escape): an else-if-baited prompt 5// must (a) make the UNCONSTRAINED model emit `else if` (proves the bait bites -- the vacuity guard), 6// (b) under the mask produce grammar-VALID output with >=1 rejection and NO `else if`. 7// MUTATION PROOF (rung 5): flip GD_NEG_ALLOW_ELSEIF=1 in nx_gramdec_lib.nx, rebuild, run -> T3 8// accepts the else-if text and T10 sees the escape -> verdict=RED exit 1. Restore -> GREEN. 9// argv: [model.gguf] [probe] (default model /home/elderwesto/nx_stage/nx_15b_model.gguf; 10// "probe" prints raw outputs for tooth calibration instead of judging). 11// license_tier: ORIGINAL No hw writes (Rule 26). 12import "nx_gramdec_lib.nx" 13import "nx_gate_verdict.nx" 14 15const GG_MAXNEW: i64 = 120 16const GG_OCAP: i64 = 4000 17 18func gg_w(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 19func gg_wn(v: i64) -> i64 { 20 var m: i64 = v 21 if m < 0 { gg_w("-" as *u8); m = 0 - m } 22 let t: *u8 = sys_mmap(24) 23 var k: i64 = 0 24 if m == 0 { t[0] = 48 as u8; k = 1 } 25 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 26 let o: *u8 = sys_mmap(24) 27 var i: i64 = 0 28 while i < k { o[i] = t[k - 1 - i]; i = i + 1 } 29 sys_write(1, o, k) 30 return 0 31} 32func gg_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 33func gg_cat(b: *u8, off: i64, s: *u8) -> i64 { 34 var i: i64 = 0 35 var o: i64 = off 36 while s[i] != (0 as u8) { b[o] = s[i]; o = o + 1; i = i + 1 } 37 return o 38} 39func gg_find(hay: *u8, hn: i64, needle: *u8, from: i64) -> i64 { 40 let m: i64 = gg_slen(needle) 41 if m == 0 { return 0 - 1 } 42 var i: i64 = from 43 while i + m <= hn { 44 var j: i64 = 0 45 var ok: i64 = 1 46 while j < m { if hay[i + j] != needle[j] { ok = 0; j = m } else { j = j + 1 } } 47 if ok == 1 { return i } 48 i = i + 1 49 } 50 return 0 - 1 51} 52 53static gg_pass: i64 54static gg_total: i64 55 56func gg_tooth(name: *u8, got: i64) -> i64 { 57 gg_total = gg_total + 1 58 gg_w(" T" as *u8) 59 gg_wn(gg_total) 60 gg_w(" " as *u8) 61 gg_w(name) 62 if got == 1 { gg_w(": PASS\n" as *u8); gg_pass = gg_pass + 1 } else { gg_w(": FAIL\n" as *u8) } 63 return 0 64} 65// validate a NUL-terminated literal through the whole-text ruler 66func gg_val(s: *u8) -> i64 { let n: i64 = gg_slen(s); return gd_validate(s, n) } 67 68// build the CLEAN round-1 sgn prompt (exact episode shape, cand2, no FNCASE rows) 69func gg_prompt_clean(pb: *u8) -> i64 { 70 var o: i64 = 0 71 o = gg_cat(pb, o, "Fix each buggy NishiLang function. Output only the corrected function on one line.\n" as *u8) 72 o = gg_cat(pb, o, "Buggy: func min2(a: i64, b: i64) -> i64 { return b }\n" as *u8) 73 o = gg_cat(pb, o, "Fixed: func min2(a: i64, b: i64) -> i64 { if a < b { return a } return b }\n" as *u8) 74 o = gg_cat(pb, o, "Buggy: func abs1(x: i64) -> i64 { return x }\n" as *u8) 75 o = gg_cat(pb, o, "Fixed: func abs1(x: i64) -> i64 { if x < 0 { return 0 - x } return x }\n" as *u8) 76 o = gg_cat(pb, o, "Buggy: func sgn(x: i64) -> i64 { return 0 }\n" as *u8) 77 o = gg_cat(pb, o, "Fixed: " as *u8) 78 return o 79} 80// build the ELSE-IF BAIT prompt (few-shots in else-if style -> greedy model copies the style) 81func gg_prompt_bait(pb: *u8) -> i64 { 82 var o: i64 = 0 83 o = gg_cat(pb, o, "Fix each buggy NishiLang function. Output only the corrected function on one line.\n" as *u8) 84 o = gg_cat(pb, o, "Buggy: func min2(a: i64, b: i64) -> i64 { return b }\n" as *u8) 85 o = gg_cat(pb, o, "Fixed: func min2(a: i64, b: i64) -> i64 { if a < b { return a } else { return b } }\n" as *u8) 86 o = gg_cat(pb, o, "Buggy: func clamp1(x: i64) -> i64 { return x }\n" as *u8) 87 o = gg_cat(pb, o, "Fixed: func clamp1(x: i64) -> i64 { if x < 0 { return 0 } else if x > 1 { return 1 } else { return x } }\n" as *u8) 88 o = gg_cat(pb, o, "Buggy: func sgn(x: i64) -> i64 { return 0 }\n" as *u8) 89 o = gg_cat(pb, o, "Fixed: " as *u8) 90 return o 91} 92// run one generation. which=0 -> nsv_generate (raw), 1 -> gdx_generate (masked). Greedy. 93// pb/plen prompt; tx out buffer; mt meta. returns text length. 94static gg_pb: *u8 95static gg_plen: i64 96func gg_gen(which: i64, tx: *u8, mt: *i64) -> i64 { 97 let gp: *i64 = sys_mmap(16 * 8) as *i64 98 gp[0] = gg_pb as i64 99 gp[1] = gg_plen 100 gp[2] = GG_MAXNEW 101 gp[3] = 1 102 gp[4] = tx as i64 103 gp[5] = GG_OCAP 104 gp[6] = mt as i64 105 gp[7] = 0 - 1 106 gp[8] = 0 107 gp[9] = 0 108 gp[10] = 0 109 gp[11] = 0 110 gp[12] = 0 111 if which == 1 { return gdx_generate(gp) } 112 return nsv_generate(gp) 113} 114 115func main(argc: i64, argv: *i64) -> i64 { 116 gg_w("nx_gramdec gate -- NB10 grammar-constrained decode: automaton ruler + live mask teeth\n\n" as *u8) 117 gg_pass = 0 118 gg_total = 0 119 // --- automaton teeth (no model) --- 120 gg_tooth("accepts correct early-return fn" as *u8, gg_val("func sgn(x: i64) -> i64 { if x > 0 { return 1 } if x < 0 { return 0 - 1 } return 0 }" as *u8)) 121 gg_tooth("accepts legal } else { form" as *u8, gg_val("func f(x: i64) -> i64 { if x > 0 { return 1 } else { return 0 } }" as *u8)) 122 var r3: i64 = 0 123 if gg_val("func f(x: i64) -> i64 { if x > 0 { return 1 } else if x < 0 { return 2 } return 0 }" as *u8) == 0 { r3 = 1 } 124 gg_tooth("rejects else-if chain" as *u8, r3) 125 var r4: i64 = 0 126 if gg_val("func f(x: i64) -> i64 { return abs(x) }" as *u8) == 0 { r4 = 1 } 127 gg_tooth("rejects helper call abs()" as *u8, r4) 128 var r5: i64 = 0 129 if gg_val("func f(x: i64) -> i64 { return -x }" as *u8) == 0 { r5 = 1 } 130 gg_tooth("rejects unary minus on identifier" as *u8, r5) 131 gg_tooth("accepts negative literal return -1" as *u8, gg_val("func f(x: i64) -> i64 { if x < 0 { return -1 } return 1 }" as *u8)) 132 var r7: i64 = 0 133 if gg_val("func f(x: i64) -> i64 { if x > 0 { return 1 }" as *u8) == 0 { r7 = 1 } 134 gg_tooth("rejects truncated fn (open brace)" as *u8, r7) 135 // string literal body: poke the quote byte (34) -- never a bare "" in source 136 let sb: *u8 = sys_mmap(256) 137 var so: i64 = 0 138 so = gg_cat(sb, so, "func f(x: i64) -> i64 { return " as *u8) 139 sb[so] = 34 as u8 140 so = so + 1 141 so = gg_cat(sb, so, "x" as *u8) 142 sb[so] = 34 as u8 143 so = so + 1 144 so = gg_cat(sb, so, " }" as *u8) 145 sb[so] = 0 as u8 146 var r8: i64 = 0 147 if gd_validate(sb, so) == 0 { r8 = 1 } 148 gg_tooth("rejects string literal in body" as *u8, r8) 149 // --- live model teeth --- 150 var mpath: *u8 = "/home/elderwesto/nx_stage/nx_15b_model.gguf" as *u8 151 if argc >= 2 { mpath = argv[1] as *u8 } 152 var probe: i64 = 0 153 if argc >= 3 { let pv: *u8 = argv[2] as *u8; if pv[0] == (112 as u8) { probe = 1 } } 154 let irc: i64 = nsv_init_i8(mpath) 155 if irc != 0 { 156 gg_w("model init FAILED -> live teeth cannot run\n" as *u8) 157 gg_tooth("live no-op equivalence" as *u8, 0) 158 gg_tooth("live mask-fires on bait" as *u8, 0) 159 gg_w("\nNX-GRAMDEC-GATE passed " as *u8) 160 gg_wn(gg_pass) 161 gg_w("/" as *u8) 162 gg_wn(gg_total) 163 gg_w(" verdict=RED\n" as *u8) 164 return 1 165 } 166 gg_pb = sys_mmap(4096) 167 let tx1: *u8 = sys_mmap(4096) 168 let tx2: *u8 = sys_mmap(4096) 169 let mt1: *i64 = sys_mmap(64) as *i64 170 let mt2: *i64 = sys_mmap(64) as *i64 171 // T9: no-op equivalence on the clean sgn prompt 172 gg_plen = gg_prompt_clean(gg_pb) 173 let l1: i64 = gg_gen(0, tx1, mt1) 174 let l2: i64 = gg_gen(1, tx2, mt2) 175 if probe == 1 { 176 gg_w("PROBE clean raw (" as *u8) 177 gg_wn(l1) 178 gg_w("B):\n" as *u8) 179 if l1 > 0 { sys_write(1, tx1, l1) } 180 gg_w("\nPROBE clean gdx (" as *u8) 181 gg_wn(l2) 182 gg_w("B, rej=" as *u8) 183 gg_wn(mt2[6]) 184 gg_w(", fin=" as *u8) 185 gg_wn(mt2[7]) 186 gg_w("):\n" as *u8) 187 if l2 > 0 { sys_write(1, tx2, l2) } 188 gg_w("\n" as *u8) 189 } 190 var eq: i64 = 0 191 if l2 > 0 { if l2 <= l1 { 192 var zi: i64 = 0 193 eq = 1 194 while zi < l2 { if tx2[zi] != tx1[zi] { eq = 0; zi = l2 } else { zi = zi + 1 } } 195 } } 196 var t9: i64 = 0 197 if eq == 1 { if mt2[6] == 0 { if mt2[7] == 1 { if gd_validate(tx2, l2) == 1 { t9 = 1 } } } } 198 gg_tooth("live no-op equivalence (prefix bit-exact, 0 rej, accept-stop)" as *u8, t9) 199 // T10: bait -- raw must emit else-if (vacuity guard); masked must not, with >=1 rejection 200 gg_plen = gg_prompt_bait(gg_pb) 201 let b1: i64 = gg_gen(0, tx1, mt1) 202 let b2: i64 = gg_gen(1, tx2, mt2) 203 if probe == 1 { 204 gg_w("PROBE bait raw (" as *u8) 205 gg_wn(b1) 206 gg_w("B):\n" as *u8) 207 if b1 > 0 { sys_write(1, tx1, b1) } 208 gg_w("\nPROBE bait gdx (" as *u8) 209 gg_wn(b2) 210 gg_w("B, rej=" as *u8) 211 gg_wn(mt2[6]) 212 gg_w(", fin=" as *u8) 213 gg_wn(mt2[7]) 214 gg_w("):\n" as *u8) 215 if b2 > 0 { sys_write(1, tx2, b2) } 216 gg_w("\n" as *u8) 217 } 218 var baited: i64 = 0 219 if gg_find(tx1, b1, "else if" as *u8, 0) >= 0 { baited = 1 } 220 var noesc: i64 = 0 221 if gg_find(tx2, b2, "else if" as *u8, 0) < 0 { noesc = 1 } 222 var t10: i64 = 0 223 if baited == 1 { if noesc == 1 { if mt2[6] >= 1 { if b2 > 0 { if gd_validate(tx2, b2) == 1 { t10 = 1 } } } } } 224 gg_tooth("live mask-fires on bait (raw baited, masked clean+valid, >=1 rej)" as *u8, t10) 225 gg_w("\nNX-GRAMDEC-GATE passed " as *u8) 226 gg_wn(gg_pass) 227 gg_w("/" as *u8) 228 gg_wn(gg_total) 229 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check 230 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled 231 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify. 232 let ctr__dry: *i64 = gv_ctr() 233 ctr__dry[0] = gg_pass 234 ctr__dry[1] = gg_total 235 let rc__dry: i64 = gv_verdict("GRAMDEC-GATE" as *u8, ctr__dry, "grammar-constrained decode: ruler sound, live mask load-bearing, no-op path bit-exact)" as *u8) 236 sys_exit_group(rc__dry) 237 return rc__dry 238}