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