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}