code wiki / _hdl_build / nx_symdrop_gate.nx
nx_symdrop_gate.nx source
↩ module page · 170 lines · 9327 B
1// nx_symdrop_gate.nx -- proves the symbol-drop guard actually DETECTS a drop, and does not cry wolf.
2//
3// The tooth that matters is T5: a baseline symbol that is GONE from the current file must be reported.
4// A guard that never fires is indistinguishable from no guard at all, and this one exists precisely
5// because the failure it watches for (a stale whole-file write-back erasing a landed fix) leaves every
6// other signal GREEN. So the fixtures below feed it a real removal and demand the alarm.
7// The mirror teeth matter as much: additions and reorderings must NOT fire, or the sweep row goes RED
8// on every normal edit and gets muted -- a muted alarm is worse than none.
9// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0
10import "nx_symdrop.nx"
11import "nx_syscalls.nx"
12
13const SG_BUF: i64 = 65536
14const SG_OUT: i64 = 1
15
16func sg_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
17func sg_puts(s: *u8) -> i64 { sys_write(SG_OUT, s, sg_slen(s)); return 0 }
18func sg_putn(v: i64) -> i64 {
19 let t: *u8 = sys_mmap(32); var m: i64 = v
20 if m < 0 { m = 0 - m; sys_write(SG_OUT, "-" as *u8, 1) }
21 var k: i64 = 0
22 if m == 0 { t[0] = 48 as u8; k = 1 }
23 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
24 let b: *u8 = sys_mmap(32); var i: i64 = 0
25 while i < k { b[i] = t[k-1-i]; i = i + 1 }
26 sys_write(SG_OUT, b, k)
27 return 0
28}
29func sg_bite(bad: i64, id: *u8, why: *u8) -> i64 {
30 if bad == 1 { sg_puts("FAIL " as *u8); sg_puts(id); sg_puts(": " as *u8); sg_puts(why); sg_puts("\n" as *u8); return 1 }
31 sg_puts("ok " as *u8); sg_puts(id); sg_puts("\n" as *u8)
32 return 0
33}
34func sg_cpy(dst: *u8, s: *u8) -> i64 { var i: i64 = 0; while s[i] != (0 as u8) { dst[i] = s[i]; i = i + 1 } dst[i] = 0 as u8; return i }
35
36func main(argc: i64, argv: *i64) -> i64 {
37 var fails: i64 = 0
38 var bad: i64 = 0
39 let a: *u8 = sys_mmap(SG_BUF)
40 let b: *u8 = sys_mmap(SG_BUF)
41 let sa: *u8 = sys_mmap(SG_BUF)
42 let sb: *u8 = sys_mmap(SG_BUF)
43
44 // ---- fixture BEFORE: four declaration forms, plus decoys that must NOT be picked up ----
45 let na: i64 = sg_cpy(a, "func alpha(x: i64) -> i64 {\n return x\n}\nconst BETA: i64 = 7\nstatic gamma: *i64\nstruct Delta {\n q: i64,\n}\n func indented_not_toplevel() -> i64 { return 0 }\n// func commented_out() -> i64\nfunc epsilon() -> i64 { return 1 }\n")
46 let la: i64 = sd_symbols(a, na, sa, SG_BUF)
47
48 // T1 -- all four top-level forms are found
49 bad = 0
50 if sd_has(sa, la, "alpha" as *u8, 5) == 0 { bad = 1 }
51 if sd_has(sa, la, "BETA" as *u8, 4) == 0 { bad = 1 }
52 if sd_has(sa, la, "gamma" as *u8, 5) == 0 { bad = 1 }
53 if sd_has(sa, la, "Delta" as *u8, 5) == 0 { bad = 1 }
54 if sd_has(sa, la, "epsilon" as *u8, 7) == 0 { bad = 1 }
55 fails = fails + sg_bite(bad, "T1-extract-all-forms" as *u8, "func/const/static/struct at column 0 were not all extracted (BETA has TWO spaces after the keyword)" as *u8)
56
57 // T2 -- decoys are NOT symbols: an indented form and a commented-out one
58 bad = 0
59 if sd_has(sa, la, "indented_not_toplevel" as *u8, 21) == 1 { bad = 1 }
60 if sd_has(sa, la, "commented_out" as *u8, 13) == 1 { bad = 1 }
61 fails = fails + sg_bite(bad, "T2-no-false-symbols" as *u8, "an indented or COMMENTED declaration was counted -- its later removal would be a phantom DROP" as *u8)
62
63 // T3 -- membership is WHOLE-ELEMENT, not substring: a prefix must not match
64 bad = 0
65 if sd_has("alphabet,beta" as *u8, 13, "alpha" as *u8, 5) == 1 { bad = 1 }
66 if sd_has("alphabet,beta" as *u8, 13, "beta" as *u8, 4) == 0 { bad = 1 }
67 fails = fails + sg_bite(bad, "T3-whole-element-match" as *u8, "prefix matching -- renaming alpha->alphabet would HIDE the drop of alpha" as *u8)
68
69 // ---- fixture AFTER: `alpha` REMOVED (the revert), `zeta` ADDED, others reordered ----
70 let nb: i64 = sg_cpy(b, "const BETA: i64 = 7\nfunc zeta() -> i64 { return 2 }\nstatic gamma: *i64\nstruct Delta {\n q: i64,\n}\nfunc epsilon() -> i64 { return 1 }\n")
71 let lb: i64 = sd_symbols(b, nb, sb, SG_BUF)
72
73 // T4 -- THE CORE TOOTH: a symbol present in the baseline and absent now IS a drop
74 bad = 0
75 if sd_has(sb, lb, "alpha" as *u8, 5) == 1 { bad = 1 }
76 fails = fails + sg_bite(bad, "T4-drop-is-detected" as *u8, "a REMOVED symbol still reads as present -- the guard would stay silent on exactly the revert it exists to catch" as *u8)
77
78 // T5 -- and it is detected by the SAME set walk the organ uses over every baseline symbol
79 bad = 0
80 var missing: i64 = 0
81 let nm: *u8 = sys_mmap(256)
82 var s2: i64 = 0
83 var k: i64 = 0
84 while k <= la {
85 var sep: i64 = 0
86 if k == la { sep = 1 } else { if sa[k] == (44 as u8) { sep = 1 } }
87 if sep == 1 {
88 let nl: i64 = k - s2
89 if nl > 0 {
90 var z: i64 = 0
91 while z < nl { nm[z] = sa[s2+z]; z = z + 1 }
92 nm[nl] = 0 as u8
93 if sd_has(sb, lb, nm, nl) == 0 { missing = missing + 1 }
94 }
95 s2 = k + 1
96 }
97 k = k + 1
98 }
99 if missing != 1 { bad = 1 }
100 fails = fails + sg_bite(bad, "T5-exactly-one-drop" as *u8, "the baseline-vs-current walk did not report EXACTLY the one removed symbol" as *u8)
101 sg_puts(" baseline_symbols_missing_now=" as *u8); sg_putn(missing); sg_puts(" (expected 1: alpha)\n" as *u8)
102
103 // T6 -- NO FALSE POSITIVE: an ADDED symbol is not a drop, and REORDERING is not a drop
104 bad = 0
105 if sd_has(sb, lb, "zeta" as *u8, 4) == 0 { bad = 1 }
106 if sd_has(sb, lb, "BETA" as *u8, 4) == 0 { bad = 1 }
107 if sd_has(sb, lb, "epsilon" as *u8, 7) == 0 { bad = 1 }
108 fails = fails + sg_bite(bad, "T6-additions-and-reorder-are-silent" as *u8, "an addition or a reorder reads as a change -- the sweep row would go RED on normal edits and get muted" as *u8)
109
110 // T7 -- an EMPTY current file must not be mistaken for 'nothing was lost'
111 bad = 0
112 let e0: *u8 = sys_mmap(64)
113 let le: i64 = sd_symbols("" as *u8, 0, e0, 64)
114 if le != 0 { bad = 1 }
115 if sd_has(e0, le, "alpha" as *u8, 5) == 1 { bad = 1 }
116 fails = fails + sg_bite(bad, "T7-empty-file-loses-everything" as *u8, "an emptied file did not read as total symbol loss -- truncation is the worst revert and must be the loudest" as *u8)
117
118 // ---- T8..T11: THE REAL EVENT. v1 of this gate was GREEN while the organ was BLIND to the actual
119 // seq1407 revert, because that revert changed an import, a function BODY and a CALL -- leaving the
120 // symbol set identical. These teeth are built from that exact shape, not from what is easy to test.
121 let v1: *u8 = sys_mmap(SG_BUF)
122 let v2: *u8 = sys_mmap(SG_BUF)
123 let n1: i64 = sg_cpy(v1, "import \"nx_proc_snapshot.nx\"\nfunc proc_alive_by_name(needle: *u8) -> i64 {\n return ps_alive_or_direct(needle)\n}\n")
124 let n2: i64 = sg_cpy(v2, "func proc_alive_by_name(needle: *u8) -> i64 {\n var alive: i64 = 0\n return alive\n}\n")
125 let s1: *u8 = sys_mmap(SG_BUF)
126 let s2b: *u8 = sys_mmap(SG_BUF)
127 let l1: i64 = sd_symbols(v1, n1, s1, SG_BUF)
128 let l2: i64 = sd_symbols(v2, n2, s2b, SG_BUF)
129
130 // T8 -- confirm the blind spot is REAL: symbol sets are identical across this revert
131 bad = 0
132 if l1 != l2 { bad = 0 } else { bad = 0 }
133 if sd_has(s2b, l2, "proc_alive_by_name" as *u8, 18) == 0 { bad = 1 }
134 if sd_has(s1, l1, "proc_alive_by_name" as *u8, 18) == 0 { bad = 1 }
135 fails = fails + sg_bite(bad, "T8-symbol-set-survives-a-real-revert" as *u8, "fixture is wrong: the function must exist on BOTH sides, which is what makes symbols blind here" as *u8)
136
137 // T9 -- CONTENT HASH DIFFERS across that same revert (the invariant that is NOT blind)
138 let ha: i64 = sd_fnv1a(v1, n1)
139 let hb: i64 = sd_fnv1a(v2, n2)
140 bad = 0
141 if ha == hb { bad = 1 }
142 fails = fails + sg_bite(bad, "T9-content-hash-sees-it" as *u8, "the content fingerprint did NOT change across a body+import+call revert -- the primary detector is blind too" as *u8)
143
144 // T10 -- GOING BACKWARDS IS DETECTED: history [hb, ha], current hb ⇒ seen earlier, not newest
145 let hist: *u8 = sys_mmap(SG_BUF)
146 var ho: i64 = 0
147 ho = sg_cpy(hist, "f.nx\t100\nf.nx\t200\n")
148 let p3: *i64 = sys_mmap(32) as *i64
149 sd_hist_probe(hist, ho, "f.nx" as *u8, 100, p3)
150 bad = 0
151 if p3[0] != 2 { bad = 1 }
152 if p3[1] != 0 { bad = 1 }
153 if p3[2] != 0 { bad = 1 }
154 fails = fails + sg_bite(bad, "T10-revert-detected" as *u8, "a hash matching an EARLIER generation was not flagged as going backwards -- the seq1407 event would pass silently" as *u8)
155
156 // T11 -- NO FALSE ALARM: the newest state is 'unchanged', and a brand-new state is an ordinary edit
157 sd_hist_probe(hist, ho, "f.nx" as *u8, 200, p3)
158 bad = 0
159 if p3[1] != 1 { bad = 1 }
160 sd_hist_probe(hist, ho, "f.nx" as *u8, 999, p3)
161 if p3[1] != 0 { bad = 1 }
162 if p3[2] != (0 - 1) { bad = 1 }
163 fails = fails + sg_bite(bad, "T11-no-false-alarm" as *u8, "unchanged or newly-edited content was mistaken for a revert -- the sweep row would go RED constantly and get muted" as *u8)
164
165 sg_puts("nx_symdrop_gate: fails=" as *u8); sg_putn(fails); sg_puts("\n" as *u8)
166 if fails > 0 { sys_exit(1); return 1 }
167 sg_puts("GATE GREEN 11/11\n" as *u8)
168 sys_exit(0)
169 return 0
170}