code wiki / (root) / nx_teacher_trainer.nx

nx_teacher_trainer.nx source

↩ module page · 178 lines · 8599 B

1// nx_teacher_trainer.nx -- the TRAINER half of the Nishi Teacher (Teacher arc, rung R3 = spaced review). 2// 3// Operator: "consume all our information from the nishi teacher AND TRAINER so we get insights to 4// improve the team's capabilities." The teacher SYNTHESIZES insights into the unified native capability 5// store (nx_teacher_merge); the trainer SCHEDULES spaced retrieval practice over them and MEASURES 6// coverage. Grounding = the cited learning science already in knowledge/registry/teaching_evidence.tsv 7// (Bjork desirable difficulties: retrieval practice + spacing beat re-reading). 8// 9// Append-only review state in the native seg_store (tag "rev", row = {id, reps, interval, due}); current 10// state of an id = its LAST appended row (additive, history-sacred #13). Spacing: first practice -> 1-day 11// interval, each subsequent success DOUBLES it; an insight is DUE if never practiced OR now >= its due 12// epoch. Coverage = (insights practiced >=1) *1000 / total -- a MEASURED readiness number. 13// 14// trn_practice(state, id, now) -- record a retrieval-practice event (advances spacing) 15// trn_due_count(cap, state, now) -- how many unified insights are due for practice 16// trn_coverage(cap, state) -- how many are under active practice (the meter) 17// 18// HONEST SCOPE (no-overclaim, [[feedback-no-wave-measured-exceed]]): this SCHEDULES practice and MEASURES 19// coverage; it does NOT by itself prove the team got "smarter" -- a real capability LIFT needs the team to 20// actually practice + a before/after task-performance measure (a further rung). license_tier: ORIGINAL 21import "nx_teacher_merge.nx" 22import "nx_syscalls.nx" 23 24const TRN_DAY: i64 = 86400 25 26func trn_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != 0 as u8 { n = n + 1 } sys_write(1, s, n); return 0 } 27func trn_putn(v: i64) -> i64 { 28 if v == 0 { sys_write(1, "0" as *u8, 1); return 0 } 29 var m: i64 = v; if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m } 30 let d: *u8 = sys_mmap(24); var k: i64 = 0 31 while m > 0 { d[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 32 var j: i64 = k - 1 33 while j >= 0 { sys_write(1, ((d as i64)+j) as *u8, 1); j = j - 1 } 34 return 0 35} 36func trn_itoa(v: i64, out: *u8) -> i64 { 37 if v == 0 { out[0] = 48 as u8; out[1] = 0 as u8; return 1 } 38 var m: i64 = v; var neg: i64 = 0 39 if m < 0 { neg = 1; m = 0 - m } 40 let t: *u8 = sys_mmap(28); var k: i64 = 0 41 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 42 var o: i64 = 0 43 if neg == 1 { out[0] = 45 as u8; o = 1 } 44 var i: i64 = 0 45 while i < k { out[o + i] = t[k - 1 - i]; i = i + 1 } 46 out[o + k] = 0 as u8 47 return o + k 48} 49func trn_atoi(s: *u8) -> i64 { 50 if (s as i64) == 0 { return 0 } 51 var v: i64 = 0; var i: i64 = 0 52 while s[i] != (0 as u8) { let c: i64 = s[i] as i64; if c >= 48 { if c <= 57 { v = v * 10 + (c - 48) } } i = i + 1 } 53 return v 54} 55// current review state of `id` (LAST appended row): out3[0]=reps out3[1]=interval out3[2]=due. 1=found. 56func trn_state(state_store: *u8, id: *u8, out3: *i64) -> i64 { 57 out3[0] = 0; out3[1] = 0; out3[2] = 0 58 let h: *i64 = ncfg_open(state_store) 59 if (h as i64) == 0 { return 0 } 60 let cnt: i64 = ncfg_count(h, "rev\x00" as *u8) 61 let rk: *i64 = sys_mmap(8 * 16) as *i64 62 let rv: *i64 = sys_mmap(8 * 16) as *i64 63 var found: i64 = 0 64 var i: i64 = 0 65 while i < cnt { 66 let rf: i64 = ncfg_row(h, "rev\x00" as *u8, i, rk, rv, 16) 67 if rf > 0 { 68 let idb: *u8 = ncfg_field(rk, rv, rf, "id\x00" as *u8) 69 if (idb as i64) != 0 { if tsyn_streq(idb, id) == 1 { 70 out3[0] = trn_atoi(ncfg_field(rk, rv, rf, "reps\x00" as *u8)) 71 out3[1] = trn_atoi(ncfg_field(rk, rv, rf, "interval\x00" as *u8)) 72 out3[2] = trn_atoi(ncfg_field(rk, rv, rf, "due\x00" as *u8)) 73 found = 1 74 } } 75 } 76 i = i + 1 77 } 78 return found 79} 80func trn_append_state(state_store: *u8, id: *u8, reps: i64, interval: i64, due: i64) -> i64 { 81 let h0: *i64 = ncfg_open(state_store) 82 var base: i64 = 0 83 if (h0 as i64) != 0 { base = ncfg_count(h0, "rev\x00" as *u8) } 84 let w: *i64 = ncfg_begin() 85 let kb: *i64 = sys_mmap(8 * 8) as *i64 86 let vb: *i64 = sys_mmap(8 * 8) as *i64 87 let rs: *u8 = sys_mmap(28); trn_itoa(reps, rs) 88 let is: *u8 = sys_mmap(28); trn_itoa(interval, is) 89 let ds: *u8 = sys_mmap(28); trn_itoa(due, ds) 90 kb[0] = ("id\x00") as i64; vb[0] = (id as i64) 91 kb[1] = ("reps\x00") as i64; vb[1] = (rs as i64) 92 kb[2] = ("interval\x00") as i64; vb[2] = (is as i64) 93 kb[3] = ("due\x00") as i64; vb[3] = (ds as i64) 94 ncfg_add_row(w, "rev\x00" as *u8, base, kb, vb, 4) 95 ncfg_set_count(w, "rev\x00" as *u8, base + 1) 96 return ncfg_commit(state_store, w) 97} 98// record a retrieval-practice event for `id`: reps+1, interval 1 then doubling, due = now + interval days. 99func trn_practice(state_store: *u8, id: *u8, now: i64) -> i64 { 100 let st: *i64 = sys_mmap(8 * 4) as *i64 101 let had: i64 = trn_state(state_store, id, st) 102 var ninterval: i64 = 1 103 if had == 1 { if st[0] >= 1 { ninterval = st[1] * 2 } } 104 let nreps: i64 = st[0] + 1 105 let due: i64 = now + ninterval * TRN_DAY 106 return trn_append_state(state_store, id, nreps, ninterval, due) 107} 108// how many unified insights are DUE (never practiced OR now >= due epoch). 109func trn_due_count(cap_store: *u8, state_store: *u8, now: i64) -> i64 { 110 let h: *i64 = ncfg_open(cap_store) 111 if (h as i64) == 0 { return 0 } 112 let cnt: i64 = ncfg_count(h, "insight\x00" as *u8) 113 let rk: *i64 = sys_mmap(8 * 16) as *i64 114 let rv: *i64 = sys_mmap(8 * 16) as *i64 115 let st: *i64 = sys_mmap(8 * 4) as *i64 116 var due: i64 = 0 117 var i: i64 = 0 118 while i < cnt { 119 let rf: i64 = ncfg_row(h, "insight\x00" as *u8, i, rk, rv, 16) 120 if rf > 0 { 121 let idb: *u8 = ncfg_field(rk, rv, rf, "id\x00" as *u8) 122 if (idb as i64) != 0 { 123 let had: i64 = trn_state(state_store, idb, st) 124 var isdue: i64 = 0 125 if had == 0 { isdue = 1 } else { if now >= st[2] { isdue = 1 } } 126 if isdue == 1 { due = due + 1 } 127 } 128 } 129 i = i + 1 130 } 131 return due 132} 133// how many unified insights are under active practice (reps >= 1) -- the coverage meter. 134func trn_coverage(cap_store: *u8, state_store: *u8) -> i64 { 135 let h: *i64 = ncfg_open(cap_store) 136 if (h as i64) == 0 { return 0 } 137 let cnt: i64 = ncfg_count(h, "insight\x00" as *u8) 138 let rk: *i64 = sys_mmap(8 * 16) as *i64 139 let rv: *i64 = sys_mmap(8 * 16) as *i64 140 let st: *i64 = sys_mmap(8 * 4) as *i64 141 var cov: i64 = 0 142 var i: i64 = 0 143 while i < cnt { 144 let rf: i64 = ncfg_row(h, "insight\x00" as *u8, i, rk, rv, 16) 145 if rf > 0 { 146 let idb: *u8 = ncfg_field(rk, rv, rf, "id\x00" as *u8) 147 if (idb as i64) != 0 { 148 let had: i64 = trn_state(state_store, idb, st) 149 if had == 1 { if st[0] >= 1 { cov = cov + 1 } } 150 } 151 } 152 i = i + 1 153 } 154 return cov 155} 156 157func main() -> i64 { 158 trn_puts("=== Nishi Teacher TRAINER: spaced-retrieval scheduler + coverage meter over the unified store ===\n") 159 let cap: *u8 = "knowledge/store/teacher-capability-\x00" as *u8 160 let state: *u8 = "knowledge/store/teacher-review-\x00" as *u8 161 let now: i64 = sys_now_realtime_sec() 162 let h: *i64 = ncfg_open(cap) 163 var total: i64 = 0 164 if (h as i64) != 0 { total = ncfg_count(h, "insight\x00" as *u8) } 165 trn_puts(" unified insights: "); trn_putn(total); trn_puts("\n") 166 trn_puts(" before: due="); trn_putn(trn_due_count(cap, state, now)); trn_puts(" covered="); trn_putn(trn_coverage(cap, state)); trn_puts("\n") 167 // demonstrate the loop: practice three unique-id insights (process lesson + technical trap + lesson) 168 trn_practice(state, "BL-001\x00" as *u8, now) 169 trn_practice(state, "LM-001\x00" as *u8, now) 170 trn_practice(state, "BL-002\x00" as *u8, now) 171 let cov1: i64 = trn_coverage(cap, state) 172 trn_puts(" after practicing BL-001,LM-001,BL-002: due="); trn_putn(trn_due_count(cap, state, now)); trn_puts(" covered="); trn_putn(cov1) 173 var permil: i64 = 0 174 if total > 0 { permil = cov1 * 1000 / total } 175 trn_puts(" coverage_permil="); trn_putn(permil); trn_puts("\n") 176 trn_puts(" HONEST: coverage = fraction under active spaced retrieval; capability LIFT needs the team to practice + a before/after performance measure (further rung)\n") 177 sys_exit(0); return 0 178}