code wiki / _hdl_build / nx_teacher_coordinate_gate.nx
nx_teacher_coordinate_gate.nx source
↩ module page · 132 lines · 6973 B
1// nx_teacher_coordinate_gate.nx -- proves the TEACHER + TRAINER + PUBLISHER coordinate: the published
2// page is a JOINT artifact whose content depends on BOTH the teacher's store AND the trainer's live state.
3//
4// Hermetic /tmp. Seed 3 insights (teacher), practice one (trainer), emit the page (publisher), read it:
5// T1 emit produced bytes
6// T2 page carries the teacher's insight COUNT (INSIGHTS=3)
7// T3 page carries the trainer's COVERED meter (COVERED=1 after one practice)
8// T4 page renders the teacher's insight rules (rule one / two / three) -- data-driven, all of them
9// T5 page carries source+id (the unified record shape)
10// T6[neg] no-fabrication: a rule never seeded is ABSENT from the page
11// T7 COORDINATION: practice a 2nd insight -> re-emit -> the page now shows COVERED=2 (the publisher
12// reflects the trainer's UPDATED state -- proof the meter is live, not a constant)
13// GREEN iff all. Sovereign: imports nx_teacher_publish + nx_syscalls. license_tier: ORIGINAL
14import "nx_teacher_publish.nx"
15import "nx_syscalls.nx"
16import "nx_gate_verdict.nx"
17
18func cg_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != 0 as u8 { n = n + 1 } sys_write(1, s, n); return 0 }
19func cg_putn(v: i64) -> i64 {
20 if v == 0 { sys_write(1, "0" as *u8, 1); return 0 }
21 var m: i64 = v; if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m }
22 let d: *u8 = sys_mmap(24); var k: i64 = 0
23 while m > 0 { d[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
24 var j: i64 = k - 1
25 while j >= 0 { sys_write(1, ((d as i64)+j) as *u8, 1); j = j - 1 }
26 return 0
27}
28func cg_cat(dst: *u8, off: i64, s: *u8) -> i64 { var i: i64 = 0; while s[i] != 0 as u8 { dst[off + i] = s[i]; i = i + 1 } return off + i }
29func cg_catn(dst: *u8, off: i64, v: i64) -> i64 {
30 var m: i64 = v; var o: i64 = off
31 let t: *u8 = sys_mmap(28); var k: i64 = 0
32 if m == 0 { t[0] = 48 as u8; k = 1 }
33 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
34 var i: i64 = 0; while i < k { dst[o + i] = t[k - 1 - i]; i = i + 1 }
35 return o + k
36}
37func cg_join(out: *u8, a: *u8, b: *u8) -> i64 { var o: i64 = cg_cat(out, 0, a); o = cg_cat(out, o, b); out[o] = 0 as u8; return o }
38func cg_mkdir(path: *u8) -> i64 { return sys_mkdir(path, 0x1ed) }
39func cg_write(path: *u8, content: *u8) -> i64 {
40 let fd: i64 = sys_openat_wr(path, 0x1a4)
41 if fd < 0 { return 0 - 1 }
42 var n: i64 = 0; while content[n] != 0 as u8 { n = n + 1 }
43 sys_write(fd, content, n); sys_close(fd); return 0
44}
45func cg_read(path: *u8, buf: *u8, cap: i64) -> i64 {
46 let fd: i64 = sys_openat_rd(path); if fd < 0 { return 0 }
47 var n: i64 = 0; var go: i64 = 1
48 while go == 1 { let r: i64 = sys_read(fd, ((buf as i64) + n) as *u8, cap - n); if r <= 0 { go = 0 } else { n = n + r } if n >= cap { go = 0 } }
49 sys_close(fd); return n
50}
51func cg_contains(buf: *u8, n: i64, needle: *u8) -> i64 {
52 var pl: i64 = 0; while needle[pl] != (0 as u8) { pl = pl + 1 }
53 if pl == 0 { return 0 }
54 var i: i64 = 0
55 while i + pl <= n {
56 var j: i64 = 0; var ok: i64 = 1
57 while j < pl { if buf[i + j] != needle[j] { ok = 0; j = pl } else { j = j + 1 } }
58 if ok == 1 { return 1 }
59 i = i + 1
60 }
61 return 0
62}
63func cg_assert(label: *u8, cond: i64) -> i64 {
64 if cond != 0 { cg_puts(" [PASS] "); cg_puts(label); cg_puts("\n"); return 1 }
65 cg_puts(" [FAIL] "); cg_puts(label); cg_puts("\n"); return 0
66}
67
68func main() -> i64 {
69 cg_puts("=== nx_teacher_coordinate_gate: teacher+trainer+publisher joint artifact (neg-control) ===\n")
70 let epoch: i64 = sys_now_realtime_sec()
71 let root: *u8 = sys_mmap(512)
72 var ro: i64 = cg_cat(root, 0, "/tmp/tcg-" as *u8); ro = cg_catn(root, ro, epoch); root[ro] = 0 as u8
73 cg_mkdir(root)
74 let led: *u8 = sys_mmap(512); cg_join(led, root, "/cap.tsv\x00" as *u8)
75 let cap: *u8 = sys_mmap(512); cg_join(cap, root, "/cap-\x00" as *u8)
76 let state: *u8 = sys_mmap(512); cg_join(state, root, "/state-\x00" as *u8)
77 let page: *u8 = sys_mmap(512); cg_join(page, root, "/curriculum.html\x00" as *u8)
78 cg_write(led, "# cap\nI1\tC\trule one\tx\nI2\tC\trule two\tx\nI3\tC\trule three\tx\n\x00" as *u8)
79
80 let now: i64 = 1000000000
81 // TEACHER
82 tsyn_merge_cols(led, "fix\x00" as *u8, cap, 0, 2)
83 // TRAINER: practice I1
84 trn_practice(state, "I1\x00" as *u8, now)
85 // PUBLISHER: emit
86 let bytes: i64 = tpub_emit(cap, state, page, now)
87 let buf: *u8 = sys_mmap(65536)
88 let n: i64 = cg_read(page, buf, 65535)
89
90 var pass: i64 = 0
91 var total: i64 = 0
92 var c: i64 = 0
93
94 c = 0; if bytes > 0 { if n > 0 { c = 1 } }
95 total = total + 1; pass = pass + cg_assert("T1 publisher emitted a page", c)
96
97 c = 0; if cg_contains(buf, n, "INSIGHTS=3\x00" as *u8) == 1 { c = 1 }
98 total = total + 1; pass = pass + cg_assert("T2 page carries teacher insight count (INSIGHTS=3)", c)
99
100 c = 0; if cg_contains(buf, n, "COVERED=1\x00" as *u8) == 1 { c = 1 }
101 total = total + 1; pass = pass + cg_assert("T3 page carries trainer meter (COVERED=1)", c)
102
103 c = 0; if cg_contains(buf, n, "rule one\x00" as *u8) == 1 { c = 1 }
104 total = total + 1; pass = pass + cg_assert("T4a page renders insight rule one", c)
105
106 c = 0; if cg_contains(buf, n, "rule two\x00" as *u8) == 1 { if cg_contains(buf, n, "rule three\x00" as *u8) == 1 { c = 1 } }
107 total = total + 1; pass = pass + cg_assert("T4b page renders ALL insight rules (two + three)", c)
108
109 c = 0; if cg_contains(buf, n, "I1\x00" as *u8) == 1 { if cg_contains(buf, n, "fix\x00" as *u8) == 1 { c = 1 } }
110 total = total + 1; pass = pass + cg_assert("T5 page carries source + id", c)
111
112 c = 0; if cg_contains(buf, n, "PHANTOM rule never seeded\x00" as *u8) == 0 { c = 1 }
113 total = total + 1; pass = pass + cg_assert("T6[neg] no-fabrication: a rule never seeded is ABSENT from the page", c)
114
115 // COORDINATION: trainer state change must flow through to the published page.
116 trn_practice(state, "I2\x00" as *u8, now)
117 tpub_emit(cap, state, page, now)
118 let n2: i64 = cg_read(page, buf, 65535)
119 c = 0; if cg_contains(buf, n2, "COVERED=2\x00" as *u8) == 1 { c = 1 }
120 total = total + 1; pass = pass + cg_assert("T7 COORDINATION: practice 2nd -> re-emit -> page shows COVERED=2 (live trainer->publisher)", c)
121
122 cg_puts("\n---- nx_teacher_coordinate gate: passed "); cg_putn(pass); cg_puts(" / "); cg_putn(total); cg_puts(" ----\n")
123 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check
124 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled
125 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify.
126 let ctr__dry: *i64 = gv_ctr()
127 ctr__dry[0] = pass
128 ctr__dry[1] = total
129 let rc__dry: i64 = gv_verdict("TEACHER-COORDINATE-GATE" as *u8, ctr__dry, "teeth unchanged; verdict emission migrated onto the shared base class" as *u8)
130 sys_exit(rc__dry)
131 return rc__dry
132}