code wiki / _hdl_build / _t4b_closed_loop_authored.nx

_t4b_closed_loop_authored.nx source

↩ module page · 465 lines · 20156 B

1// _t4b_closed_loop_authored.nx -- T4b: the CLOSED-LOOP FIRST TURN. The first model trained 2// EXCLUSIVELY on team-generated, gate-verified data: the synthesis corpus 3// (knowledge/library/synth_corpus.log SYNTH rows). Task: expr -> spec (which spec does this 4// team-synthesized expression solve), an exact 7-class mapping (verified conflict-free). 5// Uses the NEW verified-gradient CE loss (tg_celoss op 6, gradcheck-gated) -- the one-hot-MSE 6// workaround is retired on its first outing. The T4 lesson set is APPLIED, not rediscovered: 7// centered features, inverse-frequency class weights, full-batch accumulation + gated AdamW, 8// deterministic early stop. Emits a machine-readable training report 9// (knowledge/status/train_report_t4b.log TRIAGE-* rows) for the nx_train_triage organ. 10// GATES: P parse+dict+consistency (identical features MUST agree on the label -- the 11// under-determined-data check) | Q trained to 100% (per-class pred counts == data counts, 12// loss decreased) | R BIT-EXACT two-run. Tamper hook: argv[1] corpus path override. 13// LAWS: struct-free, flat ifs, no &&/||, no unary-minus literals. license_tier: ORIGINAL 14import "nx_tgrad_core.nx" 15 16const B4_EPOCHS: i64 = 2000 17const B4_LOGEVERY: i64 = 100 18const B4_INB: i64 = 24 19const B4_HID: i64 = 16 20const B4_MAXCLS: i64 = 16 21const B4_MAXROWS: i64 = 256 22 23func b4_fp(fd: i64, s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(fd,s,n); return 0 } 24func b4_fn(fd: i64, v: i64) -> i64 { let bb: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m;sys_write(fd,"-" as *u8,1)}; let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=48;k=1}; while m>0{t[k]=48+(m%10);m=m/10;k=k+1}; var i: i64=0; while i<k{bb[i]=t[k-1-i];i=i+1}; sys_write(fd,bb,k); return 0 } 25func b4_bp(fd: i64, s: *u8) -> i64 { _tg_puts(s); b4_fp(fd, s); return 0 } 26func b4_bn(fd: i64, v: i64) -> i64 { _tg_num(v); b4_fn(fd, v); return 0 } 27 28func b4_match(b: *u8, i: i64, n: i64, lit: *u8) -> i64 { 29 var k: i64 = 0 30 while lit[k] != (0 as u8) { 31 if i + k >= n { return 0 } 32 if b[i+k] != lit[k] { return 0 } 33 k = k + 1 34 } 35 return 1 36} 37func b4_nameq(a: *u8, b: *u8) -> i64 { 38 var i: i64 = 0 39 while a[i] != (0 as u8) { 40 if a[i] != b[i] { return 0 } 41 i = i + 1 42 } 43 if b[i] == (0 as u8) { return 1 } 44 return 0 45} 46 47// parse SYNTH rows: spec dict (names 16x24) + per-row label + per-row expr window (rows x 28). 48// returns row count; nspecp[0] = dict size 49func b4_parse(cpath: *u8, dict: *u8, nspecp: *i64, labels: *i64, exprs: *u8) -> i64 { 50 let lenp: *i64 = sys_mmap(16) as *i64 51 let b: *u8 = sys_read_file(cpath, lenp) 52 let n: i64 = lenp[0] 53 if n <= 0 { return 0 - 1 } 54 var cnt: i64 = 0 55 var ls: i64 = 0 56 while ls < n { 57 var le: i64 = ls 58 var stop: i64 = 0 59 while stop == 0 { 60 if le >= n { stop = 1 } else { if b[le] == (10 as u8) { stop = 1 } else { le = le + 1 } } 61 } 62 if b4_match(b, ls, le, "SYNTH " as *u8) == 1 { 63 // spec= token 64 let tmp: *u8 = sys_mmap(32) 65 var got_spec: i64 = 0 66 var j: i64 = ls 67 while j < le { 68 if b4_match(b, j, le, "spec=" as *u8) == 1 { 69 var p: i64 = j + 5 70 var k: i64 = 0 71 var stop2: i64 = 0 72 while stop2 == 0 { 73 if p >= le { stop2 = 1 } else { if b[p] == (32 as u8) { stop2 = 1 } else { 74 if k < 23 { tmp[k] = b[p]; k = k + 1 } 75 p = p + 1 76 } } 77 } 78 tmp[k] = 0 as u8 79 if k > 0 { got_spec = 1 } 80 j = le 81 } else { j = j + 1 } 82 } 83 // expression field = expr= (search engines) OR step= (loop-synth fold rows), to EOL 84 var got_expr: i64 = 0 85 var ei: i64 = 0 - 1 86 j = ls 87 while j < le { 88 if b4_match(b, j, le, "expr=" as *u8) == 1 { ei = j + 5; got_expr = 1; j = le } else { j = j + 1 } 89 } 90 if got_expr == 0 { 91 j = ls 92 while j < le { 93 if b4_match(b, j, le, "step=" as *u8) == 1 { ei = j + 5; got_expr = 1; j = le } else { j = j + 1 } 94 } 95 } 96 if got_spec == 1 { if got_expr == 1 { if cnt < B4_MAXROWS { 97 // dict lookup/insert 98 var id: i64 = 0 - 1 99 var d: i64 = 0 100 while d < nspecp[0] { 101 let dp: *u8 = (dict as i64 + d*24) as *u8 102 if b4_nameq(tmp, dp) == 1 { id = d; d = nspecp[0] } else { d = d + 1 } 103 } 104 if id < 0 { 105 if nspecp[0] < B4_MAXCLS { 106 let dst: *u8 = (dict as i64 + nspecp[0]*24) as *u8 107 var k2: i64 = 0 108 var stop3: i64 = 0 109 while stop3 == 0 { 110 dst[k2] = tmp[k2] 111 if tmp[k2] == (0 as u8) { stop3 = 1 } else { k2 = k2 + 1 } 112 } 113 id = nspecp[0] 114 nspecp[0] = nspecp[0] + 1 115 } 116 } 117 if id >= 0 { 118 labels[cnt] = id 119 let xp: *u8 = (exprs as i64 + cnt*28) as *u8 120 var k3: i64 = 0 121 while k3 < B4_INB { 122 var bv: i64 = 0 123 if ei + k3 < le { bv = b[ei+k3] as i64 } 124 xp[k3] = bv 125 k3 = k3 + 1 126 } 127 xp[B4_INB] = 0 as u8 128 cnt = cnt + 1 129 } 130 } } } 131 } 132 ls = le + 1 133 } 134 return cnt 135} 136 137// plain forward, returns argmax over nspec logits 138func b4_fwd(w: *i64, x: *i64, nspec: i64, outv: *i64) -> i64 { 139 let b1o: i64 = B4_HID * B4_INB 140 let w2o: i64 = b1o + B4_HID 141 let b2o: i64 = w2o + nspec * B4_HID 142 let h: *i64 = sys_mmap(256) as *i64 143 var i: i64 = 0 144 while i < B4_HID { 145 var s: i64 = w[b1o + i] 146 var j: i64 = 0 147 while j < B4_INB { s = nx_f32_add(s, nx_f32_mul(w[i*B4_INB + j], x[j])); j = j + 1 } 148 if nx_f32_lt(s, 0) == 1 { s = 0 } 149 h[i] = s 150 i = i + 1 151 } 152 var c: i64 = 0 153 var best: i64 = 0 154 while c < nspec { 155 var o: i64 = w[b2o + c] 156 i = 0 157 while i < B4_HID { o = nx_f32_add(o, nx_f32_mul(w[w2o + c*B4_HID + i], h[i])); i = i + 1 } 158 outv[c] = o 159 if c > 0 { if nx_f32_gt(o, outv[best]) == 1 { best = c } } 160 c = c + 1 161 } 162 return best 163} 164 165func t4b_zero(w: *i64, b1o: i64, w2o: i64) -> i64 { 166 var z: i64 = b1o 167 while z < w2o { w[z] = 0; z = z + 1 } 168 return 0 169} 170// deterministic symmetry-breaking init (the gate-proven T4 pattern) 171func t4_initb(p: *i64, n: i64, salt: i64, den: i64) -> i64 { 172 var i: i64 = 0 173 while i < n { 174 let m: i64 = ((salt + i*7) % 13) - 6 175 if m < 0 { p[i] = nx_f32_neg(tg_q(0 - m, den)) } else { p[i] = tg_q(m, den) } 176 i = i + 1 177 } 178 return 0 179} 180 181// CE training: full-batch accumulation + gated ad_step, early stop; curve sampled into 182// curve buf (pairs ep,micro), curven[0] = entries, curven[1] = converged ep (or -1) 183func b4_train(tape: *i64, nb: *i64, arena: *i64, ab: *i64, xs: *i64, ts: *i64, wts: *i64, cnt: i64, nspec: i64, w: *i64, curve: *i64, curven: *i64, out2: *i64) -> i64 { 184 let w1n: i64 = B4_HID * B4_INB 185 let b1o: i64 = w1n 186 let w2o: i64 = b1o + B4_HID 187 let w2n: i64 = nspec * B4_HID 188 let b2o: i64 = w2o + w2n 189 t4b_zero(w, b1o, w2o) 190 t4_initb(w, w1n, 5, 16) 191 t4_initb((w as i64 + w2o*8) as *i64, w2n, 6, 16) 192 var z: i64 = b2o 193 while z < b2o + nspec { w[z] = 0; z = z + 1 } 194 let lr: i64 = tg_q(1, 20) 195 let b1c: i64 = tg_q(9, 10) 196 let b2c: i64 = tg_q(999, 1000) 197 let eps: i64 = tg_q(1, 100000) 198 let mw1: *i64 = sys_mmap(8192) as *i64 199 let vw1: *i64 = sys_mmap(8192) as *i64 200 let mb1: *i64 = sys_mmap(1024) as *i64 201 let vb1: *i64 = sys_mmap(1024) as *i64 202 let mw2: *i64 = sys_mmap(8192) as *i64 203 let vw2: *i64 = sys_mmap(8192) as *i64 204 let mb2: *i64 = sys_mmap(1024) as *i64 205 let vb2: *i64 = sys_mmap(1024) as *i64 206 let gaw1: *i64 = sys_mmap(8192) as *i64 207 let gab1: *i64 = sys_mmap(1024) as *i64 208 let gaw2: *i64 = sys_mmap(8192) as *i64 209 let gab2: *i64 = sys_mmap(1024) as *i64 210 let invn: i64 = nx_f32_div(nx_i32_to_f32(1), nx_i32_to_f32(cnt)) 211 curven[0] = 0 212 curven[1] = 0 - 1 213 var ep: i64 = 0 214 while ep < B4_EPOCHS { 215 var epsum: i64 = 0 216 var z2: i64 = 0 217 while z2 < w1n { gaw1[z2] = 0; z2 = z2 + 1 } 218 z2 = 0 219 while z2 < B4_HID { gab1[z2] = 0; z2 = z2 + 1 } 220 z2 = 0 221 while z2 < w2n { gaw2[z2] = 0; z2 = z2 + 1 } 222 z2 = 0 223 while z2 < nspec { gab2[z2] = 0; z2 = z2 + 1 } 224 var s: i64 = 0 225 while s < cnt { 226 nb[0] = 0 227 ab[0] = 0 228 let lw1: i64 = tg_leaf(tape, nb, arena, ab, w, B4_HID, B4_INB) 229 let lb1: i64 = tg_leaf(tape, nb, arena, ab, (w as i64 + b1o*8) as *i64, B4_HID, 1) 230 let lw2: i64 = tg_leaf(tape, nb, arena, ab, (w as i64 + w2o*8) as *i64, nspec, B4_HID) 231 let lb2: i64 = tg_leaf(tape, nb, arena, ab, (w as i64 + b2o*8) as *i64, nspec, 1) 232 let lx: i64 = tg_leaf(tape, nb, arena, ab, (xs as i64 + s*B4_INB*8) as *i64, B4_INB, 1) 233 let lt: i64 = tg_leaf(tape, nb, arena, ab, (ts as i64 + s*B4_MAXCLS*8) as *i64, nspec, 1) 234 let hh: i64 = tg_reluvec(tape, nb, arena, ab, tg_addvec(tape, nb, arena, ab, tg_matvec(tape, nb, arena, ab, lw1, lx), lb1)) 235 let oo: i64 = tg_addvec(tape, nb, arena, ab, tg_matvec(tape, nb, arena, ab, lw2, hh), lb2) 236 let lwt: i64 = tg_leaf(tape, nb, arena, ab, (wts as i64 + s*8) as *i64, 1, 1) 237 let loss: i64 = tg_smul(tape, nb, arena, ab, tg_celoss(tape, nb, arena, ab, oo, lt), lwt) 238 tg_backward(tape, nb[0], loss) 239 let lv: *i64 = tg_valp(tape, loss) 240 epsum = nx_f32_add(epsum, lv[0]) 241 let pg1: *i64 = tg_gradp(tape, lw1) 242 var q: i64 = 0 243 while q < w1n { gaw1[q] = nx_f32_add(gaw1[q], pg1[q]); q = q + 1 } 244 let pb1: *i64 = tg_gradp(tape, lb1) 245 q = 0 246 while q < B4_HID { gab1[q] = nx_f32_add(gab1[q], pb1[q]); q = q + 1 } 247 let pg2: *i64 = tg_gradp(tape, lw2) 248 q = 0 249 while q < w2n { gaw2[q] = nx_f32_add(gaw2[q], pg2[q]); q = q + 1 } 250 let pb2: *i64 = tg_gradp(tape, lb2) 251 q = 0 252 while q < nspec { gab2[q] = nx_f32_add(gab2[q], pb2[q]); q = q + 1 } 253 s = s + 1 254 } 255 ad_step(w, gaw1, mw1, vw1, w1n, lr, b1c, b2c, eps, 0, ep + 1) 256 ad_step((w as i64 + b1o*8) as *i64, gab1, mb1, vb1, B4_HID, lr, b1c, b2c, eps, 0, ep + 1) 257 ad_step((w as i64 + w2o*8) as *i64, gaw2, mw2, vw2, w2n, lr, b1c, b2c, eps, 0, ep + 1) 258 ad_step((w as i64 + b2o*8) as *i64, gab2, mb2, vb2, nspec, lr, b1c, b2c, eps, 0, ep + 1) 259 let avg: i64 = nx_f32_mul(epsum, invn) 260 if ep == 0 { out2[0] = avg } 261 out2[1] = avg 262 let micro: i64 = tg_milli(nx_f32_mul(avg, nx_i32_to_f32(1000))) 263 if ep % B4_LOGEVERY == 0 { 264 if curven[0] < 120 { 265 curve[curven[0]*2+0] = ep 266 curve[curven[0]*2+1] = micro 267 curven[0] = curven[0] + 1 268 } 269 } 270 // deterministic early stop at convergence (the T4 lesson: post-convergence constant-lr 271 // Adam blows up; stop epoch = pure function of the losses, preserves bit-exactness) 272 if nx_f32_lt(avg, tg_q(1, 100000)) == 1 { 273 if curven[0] < 120 { 274 curve[curven[0]*2+0] = ep 275 curve[curven[0]*2+1] = micro 276 curven[0] = curven[0] + 1 277 } 278 curven[1] = ep 279 ep = B4_EPOCHS 280 } else { ep = ep + 1 } 281 } 282 return 0 283} 284 285func main(argc: i64, argv: *i64) -> i64 { 286 _tg_puts("=== T4b CLOSED-LOOP FIRST TURN (model trained ONLY on team-synthesized gate-verified data; CE loss) ===\n" as *u8) 287 var cpath: *u8 = "knowledge/library/synth_corpus.log" as *u8 288 if argc >= 2 { cpath = argv[1] as *u8 } 289 let lfd: i64 = sys_openat_append("knowledge/status/modelwright.log" as *u8, 0x1a4) 290 if lfd < 0 { _tg_puts(" modelwright log open FAILED\n" as *u8); sys_exit(1); return 1 } 291 b4_fp(lfd, "MODELWRIGHT T4B RUN epoch_unix=" as *u8); b4_fn(lfd, sys_now_realtime_sec()); b4_fp(lfd, "\n" as *u8) 292 293 let tape: *i64 = sys_mmap(32768) as *i64 294 let nb: *i64 = sys_mmap(16) as *i64 295 let arena: *i64 = sys_mmap(131072) as *i64 296 let ab: *i64 = sys_mmap(16) as *i64 297 298 // ---- GATE P: parse + dict + consistency ---- 299 let dict: *u8 = sys_mmap(1024) 300 let nspecp: *i64 = sys_mmap(16) as *i64 301 let labels: *i64 = sys_mmap(4096) as *i64 302 let exprs: *u8 = sys_mmap(16384) 303 let cnt: i64 = b4_parse(cpath, dict, nspecp, labels, exprs) 304 let nspec: i64 = nspecp[0] 305 var pp: i64 = 1 306 if cnt < 20 { pp = 0 } 307 if nspec < 5 { pp = 0 } 308 if nspec > B4_MAXCLS { pp = 0 } 309 // consistency: identical feature windows MUST agree on the label (under-determined-data check) 310 var ii: i64 = 0 311 while ii < cnt { 312 var jj: i64 = ii + 1 313 while jj < cnt { 314 let xa: *u8 = (exprs as i64 + ii*28) as *u8 315 let xb: *u8 = (exprs as i64 + jj*28) as *u8 316 var same: i64 = 1 317 var k: i64 = 0 318 while k < B4_INB { if xa[k] != xb[k] { same = 0 } k = k + 1 } 319 if same == 1 { if labels[ii] != labels[jj] { 320 pp = 0 321 _tg_puts(" CONSISTENCY FAIL rows " as *u8); _tg_num(ii); _tg_puts(" vs " as *u8); _tg_num(jj); _tg_puts("\n" as *u8) 322 } } 323 jj = jj + 1 324 } 325 ii = ii + 1 326 } 327 let hist: *i64 = sys_mmap(256) as *i64 328 var s2: i64 = 0 329 while s2 < cnt { hist[labels[s2]] = hist[labels[s2]] + 1; s2 = s2 + 1 } 330 b4_bp(lfd, "MODELWRIGHT T4B DATA rows=" as *u8); b4_bn(lfd, cnt) 331 b4_bp(lfd, " specs=" as *u8); b4_bn(lfd, nspec) 332 var c2: i64 = 0 333 while c2 < nspec { 334 b4_bp(lfd, " " as *u8); b4_bp(lfd, (dict as i64 + c2*24) as *u8) 335 b4_bp(lfd, "=" as *u8); b4_bn(lfd, hist[c2]) 336 c2 = c2 + 1 337 } 338 b4_bp(lfd, "\n" as *u8) 339 if pp == 1 { _tg_puts(" GATE P corpus parse + spec dict + consistency: PASS\n" as *u8) } else { _tg_puts(" GATE P: FAIL\n" as *u8) } 340 341 // ---- features (centered bytes, the T4 lesson) + one-hot + inverse-frequency weights ---- 342 let xs: *i64 = sys_mmap(65536) as *i64 343 let ts: *i64 = sys_mmap(65536) as *i64 344 s2 = 0 345 while s2 < cnt { 346 let xp: *u8 = (exprs as i64 + s2*28) as *u8 347 var j: i64 = 0 348 while j < B4_INB { 349 let bv: i64 = xp[j] as i64 350 let m: i64 = bv - 84 351 if m < 0 { xs[s2*B4_INB + j] = nx_f32_neg(tg_q(0 - m, 32)) } else { xs[s2*B4_INB + j] = tg_q(m, 32) } 352 j = j + 1 353 } 354 var c3: i64 = 0 355 while c3 < B4_MAXCLS { 356 if c3 == labels[s2] { ts[s2*B4_MAXCLS + c3] = nx_i32_to_f32(1) } else { ts[s2*B4_MAXCLS + c3] = 0 } 357 c3 = c3 + 1 358 } 359 s2 = s2 + 1 360 } 361 let wts: *i64 = sys_mmap(4096) as *i64 362 s2 = 0 363 while s2 < cnt { wts[s2] = nx_f32_div(nx_f32_div(nx_i32_to_f32(1), nx_i32_to_f32(nspec)), nx_i32_to_f32(hist[labels[s2]])); s2 = s2 + 1 } 364 365 // ---- GATE Q: train to 100% with CE ---- 366 let w1: *i64 = sys_mmap(8192) as *i64 367 let curve: *i64 = sys_mmap(4096) as *i64 368 let curven: *i64 = sys_mmap(32) as *i64 369 let o1: *i64 = sys_mmap(64) as *i64 370 b4_train(tape, nb, arena, ab, xs, ts, wts, cnt, nspec, w1, curve, curven, o1) 371 var ci: i64 = 0 372 while ci < curven[0] { 373 b4_bp(lfd, "MODELWRIGHT T4B LOSSCURVE ep=" as *u8); b4_bn(lfd, curve[ci*2+0]) 374 b4_bp(lfd, " loss_micro=" as *u8); b4_bn(lfd, curve[ci*2+1]); b4_bp(lfd, "\n" as *u8) 375 ci = ci + 1 376 } 377 if curven[1] >= 0 { b4_bp(lfd, "MODELWRIGHT T4B CONVERGED ep=" as *u8); b4_bn(lfd, curven[1]); b4_bp(lfd, "\n" as *u8) } 378 let outv: *i64 = sys_mmap(256) as *i64 379 let pcount: *i64 = sys_mmap(256) as *i64 380 var acc: i64 = 0 381 s2 = 0 382 while s2 < cnt { 383 let pred: i64 = b4_fwd(w1, (xs as i64 + s2*B4_INB*8) as *i64, nspec, outv) 384 pcount[pred] = pcount[pred] + 1 385 if pred == labels[s2] { acc = acc + 1 } else { 386 _tg_puts(" MISS row=" as *u8); _tg_num(s2) 387 _tg_puts(" label=" as *u8); _tg_num(labels[s2]) 388 _tg_puts(" pred=" as *u8); _tg_num(pred); _tg_puts("\n" as *u8) 389 } 390 s2 = s2 + 1 391 } 392 var pq: i64 = 1 393 if acc != cnt { pq = 0 } 394 c2 = 0 395 while c2 < nspec { 396 if pcount[c2] != hist[c2] { pq = 0 } 397 c2 = c2 + 1 398 } 399 if nx_f32_lt(o1[1], o1[0]) == 0 { pq = 0 } 400 b4_bp(lfd, "MODELWRIGHT T4B ACC right=" as *u8); b4_bn(lfd, acc) 401 b4_bp(lfd, " total=" as *u8); b4_bn(lfd, cnt); b4_bp(lfd, "\n" as *u8) 402 if pq == 1 { _tg_puts(" GATE Q 100% on the synthesis corpus (per-class counts == data, CE loss decreased): PASS\n" as *u8) } else { _tg_puts(" GATE Q: FAIL\n" as *u8) } 403 404 // ---- GATE R: bit-exact two-run ---- 405 let w2b: *i64 = sys_mmap(8192) as *i64 406 let curve2: *i64 = sys_mmap(4096) as *i64 407 let curven2: *i64 = sys_mmap(32) as *i64 408 let o2: *i64 = sys_mmap(64) as *i64 409 b4_train(tape, nb, arena, ab, xs, ts, wts, cnt, nspec, w2b, curve2, curven2, o2) 410 let tot: i64 = B4_HID*B4_INB + B4_HID + nspec*B4_HID + nspec 411 var pr: i64 = 1 412 var k4: i64 = 0 413 while k4 < tot { if w1[k4] != w2b[k4] { pr = 0 } k4 = k4 + 1 } 414 b4_bp(lfd, "MODELWRIGHT T4B BITEXACT cells=" as *u8); b4_bn(lfd, tot) 415 b4_bp(lfd, " identical=" as *u8); b4_bn(lfd, pr); b4_bp(lfd, "\n" as *u8) 416 if pr == 1 { _tg_puts(" GATE R bit-exact two-run CE training: PASS\n" as *u8) } else { _tg_puts(" GATE R: FAIL\n" as *u8) } 417 418 // ---- machine-readable training report for nx_train_triage ---- 419 // tamper/override runs (argc>=2) must NEVER clobber the durable report -- the live 420 // triage row reads it (lesson: the first tamper run overwrote it and turned the gate red) 421 var rpath: *u8 = "knowledge/status/train_report_t4b.log" as *u8 422 if argc >= 2 { rpath = "/tmp/_t4b_report_override.log" as *u8 } 423 let rfd: i64 = sys_openat_wr(rpath, 0x1a4) 424 if rfd >= 0 { 425 c2 = 0 426 while c2 < nspec { 427 b4_fp(rfd, "TRIAGE-CLASS id=" as *u8); b4_fn(rfd, c2) 428 b4_fp(rfd, " count=" as *u8); b4_fn(rfd, hist[c2]); b4_fp(rfd, "\n" as *u8) 429 c2 = c2 + 1 430 } 431 c2 = 0 432 while c2 < nspec { 433 b4_fp(rfd, "TRIAGE-PRED id=" as *u8); b4_fn(rfd, c2) 434 b4_fp(rfd, " count=" as *u8); b4_fn(rfd, pcount[c2]); b4_fp(rfd, "\n" as *u8) 435 c2 = c2 + 1 436 } 437 b4_fp(rfd, "TRIAGE-ACC right=" as *u8); b4_fn(rfd, acc) 438 b4_fp(rfd, " total=" as *u8); b4_fn(rfd, cnt); b4_fp(rfd, "\n" as *u8) 439 ci = 0 440 while ci < curven[0] { 441 b4_fp(rfd, "TRIAGE-LOSS ep=" as *u8); b4_fn(rfd, curve[ci*2+0]) 442 b4_fp(rfd, " micro=" as *u8); b4_fn(rfd, curve[ci*2+1]); b4_fp(rfd, "\n" as *u8) 443 ci = ci + 1 444 } 445 sys_close(rfd) 446 _tg_puts(" training report written: " as *u8); _tg_puts(rpath); _tg_puts("\n" as *u8) 447 } 448 449 var gates: i64 = 0 450 if pp == 1 { gates = gates + 1 } 451 if pq == 1 { gates = gates + 1 } 452 if pr == 1 { gates = gates + 1 } 453 b4_bp(lfd, "MODELWRIGHT T4B VERDICT gates=" as *u8); b4_bn(lfd, gates) 454 b4_bp(lfd, "/3" as *u8) 455 if gates == 3 { b4_bp(lfd, " pass=1\n" as *u8) } else { b4_bp(lfd, " pass=0\n" as *u8) } 456 sys_close(lfd) 457 if gates == 3 { 458 _tg_puts(" T4B CLOSED-LOOP GATE: PASS (first model trained exclusively on team-generated gate-verified data)\n" as *u8) 459 sys_exit(0) 460 return 0 461 } 462 _tg_puts(" T4B CLOSED-LOOP GATE: FAIL\n" as *u8) 463 sys_exit(1) 464 return 1 465}