code wiki / _hdl_build / nx_gateverify.nx
nx_gateverify.nx source
↩ module page · 144 lines · 5274 B
1// nx_gateverify.nx -- BEHAVIOURAL gate-record verification: run a gate, then compare what it PRINTED
2// against what it RECORDED.
3//
4// WHY THIS AND NOT THE TEXTUAL CHECK: an earlier sibling organ tried to judge emit ORDER from source
5// position and was wrong on all seven gates it flagged -- helper definitions, test fixtures and /tmp
6// writes all match an append token, and it even flagged its own gate via test-data literals. That check
7// was DELETED. The one genuine defect in that arc was caught by READING THE LOG AGAINST THE OUTPUT:
8// the gate printed 41/41 while its log said 23/23. This organ mechanises exactly that comparison, so it
9// finds the real thing and cannot manufacture the false ones.
10//
11// ★A gate's stdout is watched by a human for ten seconds; its LOG is what every ruler reads forever.
12// When those two disagree, the log is the one that matters and the one that is wrong.
13//
14// nx_gateverify <gate-name> [logname]
15// e.g. nx_gateverify nx_capgraph_derive_gate
16// verdicts: AGREE · DISAGREE (the record is untrustworthy) · NO-LOG · UNPARSED
17// exit 0 agree/no-log · 1 DISAGREE · 4 run-fail
18// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0
19import "nx_gateorder_lib.nx"
20import "nx_tool_run.nx"
21
22const GV_CAP: i64 = 262144
23const GV_PATH: i64 = 512
24
25static gv_out: *u8
26static gv_log: *u8
27static gv_path: *u8
28
29func gv_cat(dst: *u8, at: i64, s: *u8) -> i64 {
30 var w: i64 = at
31 var i: i64 = 0
32 while s[i] != (0 as u8) {
33 if w < GV_PATH - 1 {
34 dst[w] = s[i]
35 w = w + 1
36 }
37 i = i + 1
38 }
39 dst[w] = 0 as u8
40 return w
41}
42
43// knowledge/status/<name-without-nx_>.log -- the convention every gate here follows.
44func gv_logpath(name: *u8) -> i64 {
45 var o: i64 = gv_cat(gv_path, 0, "knowledge/status/" as *u8)
46 var start: i64 = 0
47 if name[0] == (110 as u8) {
48 if name[1] == (120 as u8) {
49 if name[2] == (95 as u8) { start = 3 }
50 }
51 }
52 var i: i64 = start
53 while name[i] != (0 as u8) {
54 if o < GV_PATH - 5 {
55 gv_path[o] = name[i]
56 o = o + 1
57 }
58 i = i + 1
59 }
60 gv_path[o] = 46 as u8
61 gv_path[o + 1] = 108 as u8
62 gv_path[o + 2] = 111 as u8
63 gv_path[o + 3] = 103 as u8
64 gv_path[o + 4] = 0 as u8
65 return o + 4
66}
67
68func main(argc: i64, argv: *i64) -> i64 {
69 if argc < 2 {
70 go_puts("usage: nx_gateverify <gate-name> e.g. nx_capgraph_derive_gate\n" as *u8)
71 return 0
72 }
73 let name: *u8 = argv[1] as *u8
74 gv_out = sys_mmap(GV_CAP + 64) as *u8
75 gv_log = sys_mmap(GV_CAP + 64) as *u8
76 gv_path = sys_mmap(GV_PATH + 64) as *u8
77
78 go_puts("=== NX-GATEVERIFY: does the gate's RECORD match what it PRINTED? ===\n" as *u8)
79 go_puts("gate=" as *u8)
80 go_puts(name)
81 go_puts("\n\n" as *u8)
82
83 // ---- run the gate, capture stdout ----
84 var elf: *u8 = sys_mmap(GV_PATH + 64) as *u8
85 var eo: i64 = gv_cat(elf, 0, "/volume1/homes/elderwesto/nishihost/" as *u8)
86 eo = gv_cat(elf, eo, name)
87 gv_cat(elf, eo, ".elf" as *u8)
88 let olen: *i64 = sys_mmap(16) as *i64
89 let rc: i64 = tr_run1(elf, 0 as *u8, gv_out, GV_CAP, olen)
90 let on: i64 = olen[0]
91 if rc == 127 {
92 go_puts("verdict=RUN-FAIL exec-127 (is it promoted + is the path right?)\n" as *u8)
93 return 4
94 }
95 if on <= 0 {
96 go_puts("verdict=RUN-FAIL empty output\n" as *u8)
97 return 4
98 }
99
100 let pr: *i64 = sys_mmap(64) as *i64
101 let okout: i64 = go_last_ratio(gv_out, on, pr)
102 if okout == 0 {
103 go_puts("verdict=UNPARSED no N/M ratio in the gate's output -- cannot compare\n" as *u8)
104 return 0
105 }
106 go_kv("printed_passed" as *u8, pr[0])
107 go_kv("printed_total" as *u8, pr[1])
108 go_puts("\n" as *u8)
109
110 // ---- read the recorded verdict ----
111 gv_logpath(name)
112 let llen: *i64 = sys_mmap(16) as *i64
113 let lb: *u8 = sys_read_file(gv_path, llen)
114 let ln: i64 = llen[0]
115 go_puts("log=" as *u8)
116 go_puts(gv_path)
117 go_puts("\n" as *u8)
118 if ln <= 0 {
119 go_puts("\nverdict=NO-LOG the gate leaves NO durable record.\n" as *u8)
120 go_puts(" Its stdout is watched for ten seconds; the LOG is what every ruler reads forever.\n" as *u8)
121 return 0
122 }
123 let lp: i64 = go_kv_num(lb, ln, "passed=" as *u8)
124 let lt: i64 = go_kv_num(lb, ln, "total=" as *u8)
125 go_kv("recorded_passed" as *u8, lp)
126 go_kv("recorded_total" as *u8, lt)
127 go_puts("\n\n" as *u8)
128 if lp < 0 {
129 go_puts("verdict=UNPARSED the log carries no passed=/total= fields\n" as *u8)
130 return 0
131 }
132 if lp == pr[0] {
133 if lt == pr[1] {
134 go_puts("verdict=AGREE the record matches the run.\n" as *u8)
135 return 0
136 }
137 }
138 go_puts("verdict=DISAGREE ** THE RECORD IS UNTRUSTWORTHY **\n" as *u8)
139 go_puts(" The gate printed one result and recorded another. Every ruler reads the RECORD, so a\n" as *u8)
140 go_puts(" regression can be RED on screen and GREEN in the ledger. Usual cause: the verdict emit\n" as *u8)
141 go_puts(" is not the gate's LAST act, so teeth added later run AFTER the counters were read.\n" as *u8)
142 go_puts(" FIX: make the emit the final statement before the footer, then re-run this.\n" as *u8)
143 return 1
144}