code wiki / (root) / nx_sweepgate.nx

nx_sweepgate.nx source

↩ module page · 431 lines · 23063 B

1// nx_sweepgate.nx -- ASK A POPULATION QUESTION BY ITS INVARIANT, AND SEE EVERY SPELLING OF IT. 2// 3// WHY THIS EXISTS, from a measured failure on 2026-08-14. An out-of-bounds allocation bug was swept for 4// with the pattern `sys_mmap(128) as *NxEGraph`. That returned 9 sites in 5 files, and the number was 5// published as the population. It was the population OF ONE SPELLING: the same struct was also being 6// allocated at 256 and at 96, and the 96-byte sites overran a 280-byte struct by 184 bytes -- the WORST 7// sites in the estate, left live by a sweep that reported a clean, confident, complete-looking answer. 8// The true population was 27 sites in 16 files. What eventually surfaced the miss was not another grep; 9// it was the arena's ring detector printing ARENA-OVERRUN while the gate reported 15/15 GREEN. 10// 11// -- A SWEEP THAT MATCHES THE WRONG VALUE REPORTS A CLEAN POPULATION AND LEAVES THE WORST SITES LIVE. 12// 13// THE RULE THIS MAKES MECHANICAL: query by the INVARIANT (`as *NxEGraph`), never by an INSTANCE 14// (`sys_mmap(128) as *NxEGraph`). An instance pattern cannot answer a question about its own siblings, 15// and it fails in the direction of looking finished. So this organ takes the invariant, finds every 16// line, and reports the DISTINCT NUMERIC LITERALS across those lines with their counts. On the real 17// case its first line of output would have been: 18// shapes=3 128 x9 256 x11 96 x6 19// and the 17 hidden sites are visible before anyone acts on the 9. 20// 21// IT ALSO REFUSES TO CENSUS THROUGH A PARTIAL SCAN. nx_shelltool already prints coverage_complete and 22// corpus_complete; on 2026-08-14 a `matches=0` was read as absence while corpus_complete was 0, and the 23// wrong conclusion was published. Those flags are fields a reader may ignore, so this organ reads them 24// FOR the reader and returns UNPROVEN rather than a number it cannot stand behind. 25// -- A NUMBER THAT MIGHT BE PARTIAL IS MORE DANGEROUS THAN NO NUMBER. 26// 27// COMPOSES nx_shelltool; adds no second scanner. exit 0 SINGLE-SHAPE - 1 SPLIT (the finding) - 28// 3 UNPROVEN (partial coverage, or the tool could not be reached) - 2 usage. 29// license_tier: ORIGINAL expect_exit: 0 30 31import "nx_tool_run.nx" 32 33const SG_MAX_SHAPES: i64 = 64 34const SG_CAP: i64 = 1048576 35const SG_COLON: i64 = 58 36const SG_NL: i64 = 10 37const SG_D0: i64 = 48 38const SG_D9: i64 = 57 39 40func sg_w(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 41func sg_n(v: i64) -> i64 { 42 var m: i64 = v; if m < 0 { sg_w("-" as *u8); m = 0 - m } 43 let t: *u8 = sys_mmap(24); var k: i64 = 0; if m == 0 { t[0] = 48 as u8; k = 1 } 44 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 45 let o: *u8 = sys_mmap(24); var i: i64 = 0; while i < k { o[i] = t[k-1-i]; i = i + 1 } sys_write(1, o, k); return 0 46} 47// Is `needle` present in buf[0..n)? Composes the incumbent rather than adding a matcher. 48func sg_has(buf: *u8, n: i64, needle: *u8) -> i64 { return tr_contains(buf, n, needle) } 49 50// THE LOAD-BEARING LOGIC, EXTRACTED SO IT CAN BE PROVEN. Tally distinct integer literals across the 51// CONTENT of each `path:lineno:content` row. The prefix is skipped deliberately -- a path can carry 52// digits (nx_p256) and a line number always does, and counting either would drown the signal in noise. 53// Returns the number of distinct shapes, or 0-1 if the shape table overflowed. 54func sg_tally(buf: *u8, n: i64, vals: *i64, cnts: *i64, lines_out: *i64) -> i64 { 55 var nshapes: i64 = 0 56 var lines: i64 = 0 57 var p: i64 = 0 58 while p < n { 59 var e: i64 = p 60 while e < n { if buf[e] == (SG_NL as u8) { break } e = e + 1 } 61 var colons: i64 = 0 62 var c: i64 = p 63 var content: i64 = 0 - 1 64 while c < e { 65 if buf[c] == (SG_COLON as u8) { 66 colons = colons + 1 67 if colons == 2 { content = c + 1; c = e } 68 } 69 c = c + 1 70 } 71 if content > 0 { 72 lines = lines + 1 73 // COMMENT PROSE IS NOT CODE. Truncate the content at `//`. Caught by running the real census: 74 // the first live run tallied 128 x3 entirely from a COMMENT that describes this very bug -- 75 // the prose-is-source-bytes trap, biting the detector built to find it. 76 var stop_at: i64 = e 77 var sc: i64 = content 78 while sc < e - 1 { 79 if buf[sc] == (47 as u8) { if buf[sc+1] == (47 as u8) { stop_at = sc; sc = e } } 80 sc = sc + 1 81 } 82 var i: i64 = content 83 while i < stop_at { 84 let ch: i64 = buf[i] as i64 85 if ch >= SG_D0 { if ch <= SG_D9 { 86 // A DIGIT RUN GLUED TO AN IDENTIFIER IS PART OF THE NAME, NOT A VALUE. Caught by the 87 // first live census, which reported 2 x4 / 3 x3 / 5 x3 -- every one of them the tail 88 // of a local called eg2, g3 or c8. Counting those drowns the real spellings in noise, 89 // and a detector with false positives is worse than none because everyone learns to 90 // ignore it. 91 var glued: i64 = 0 92 if i > content { 93 let pv: i64 = buf[i-1] as i64 94 if pv == 95 { glued = 1 } 95 if pv >= 65 { if pv <= 90 { glued = 1 } } 96 if pv >= 97 { if pv <= 122 { glued = 1 } } 97 } 98 var v: i64 = 0 99 var stop: i64 = 0 100 while stop == 0 { 101 if i >= stop_at { stop = 1 } else { 102 let d: i64 = buf[i] as i64 103 if d < SG_D0 { stop = 1 } else { if d > SG_D9 { stop = 1 } else { 104 v = v * 10 + (d - SG_D0); i = i + 1 105 } } 106 } 107 } 108 if glued == 0 { 109 var k: i64 = 0 110 var seen: i64 = 0 111 while k < nshapes { if vals[k] == v { cnts[k] = cnts[k] + 1; seen = 1; k = nshapes } else { k = k + 1 } } 112 if seen == 0 { 113 if nshapes < SG_MAX_SHAPES { vals[nshapes] = v; cnts[nshapes] = 1; nshapes = nshapes + 1 } 114 else { lines_out[0] = lines; return 0 - 1 } 115 } 116 } 117 } } 118 i = i + 1 119 } 120 } 121 p = e + 1 122 } 123 lines_out[0] = lines 124 return nshapes 125} 126 127// SELFTEST -- runs when invoked with NO arguments, which is how /api/gate_run invokes a verifier. 128// This is a self-test, NOT a silent default doing real work: it cannot emit a population claim about 129// the estate, so it carries none of the risk that made the stale-default challenger a false-verdict 130// generator. It proves the tally on a crafted buffer whose right answer is known by construction. 131func sg_selftest() -> i64 { 132 sg_w("nx_sweepgate selftest -- the shape tally, on a buffer whose answer is known by construction\n\n" as *u8) 133 let vals: *i64 = sys_mmap(SG_MAX_SHAPES * 8) as *i64 134 let cnts: *i64 = sys_mmap(SG_MAX_SHAPES * 8) as *i64 135 let lo: *i64 = sys_mmap(16) as *i64 136 // THE EXACT SHAPE OF THE REAL FAILURE: one invariant, three spellings, plus digits in the PATH 137 // (nx_p256) and in every line number -- all of which must be ignored or the signal drowns. 138 // FIXTURE WIDENED 2026-08-14 AFTER THE FIRST LIVE RUN EXPOSED IT AS TOO NARROW. The original held 139 // only clean `sys_mmap(N)` rows, so it could not fail on either defect the real census immediately 140 // hit: digits welded to an identifier (eg2, g3, c8) and digits inside COMMENT prose. It passed 6/6 141 // while the shipped organ produced 6 shapes on real data, 5 of them noise. 142 // -- A FIXTURE THE DEFECT CANNOT FAIL IS NOT A TEST. 143 let fix: *u8 = "a/nx_p256.nx:99:let g = sys_mmap(128) as *Foo\nb/x.nx:12:let g = sys_mmap(256) as *Foo\nc/y.nx:7:let g = sys_mmap(128) as *Foo\nd/z.nx:1:let g = sys_mmap(96) as *Foo\ne/w.nx:3:let eg2 = sys_mmap(128) as *Foo\nf/v.nx:8:// sys_mmap(999) as *Foo -- prose about the bug\n-- matches=6 coverage_complete=1 corpus_complete=1\n" as *u8 144 var fn: i64 = 0 145 while fix[fn] != (0 as u8) { fn = fn + 1 } 146 let ns: i64 = sg_tally(fix, fn, vals, cnts, lo) 147 148 var pass: i64 = 0 149 var total: i64 = 0 150 // three distinct spellings found 151 total = total + 1; if ns == 3 { pass = pass + 1; sg_w(" three distinct spellings detected: PASS\n" as *u8) } else { sg_w(" three distinct spellings detected: FAIL\n" as *u8) } 152 // the repeated one is counted twice, the others once 153 var c128: i64 = 0 154 var c256: i64 = 0 155 var c96: i64 = 0 156 var k: i64 = 0 157 while k < ns { 158 if vals[k] == 128 { c128 = cnts[k] } 159 if vals[k] == 256 { c256 = cnts[k] } 160 if vals[k] == 96 { c96 = cnts[k] } 161 k = k + 1 162 } 163 total = total + 1; if c128 == 3 { pass = pass + 1; sg_w(" the repeated spelling is counted three times: PASS\n" as *u8) } else { sg_w(" the repeated spelling is counted three times: FAIL\n" as *u8) } 164 total = total + 1; if c256 == 1 { pass = pass + 1; sg_w(" the second spelling is counted once: PASS\n" as *u8) } else { sg_w(" the second spelling is counted once: FAIL\n" as *u8) } 165 total = total + 1; if c96 == 1 { pass = pass + 1; sg_w(" the third and worst spelling is counted once: PASS\n" as *u8) } else { sg_w(" the third and worst spelling is counted once: FAIL\n" as *u8) } 166 // NEG-CONTROL: the digits in the PATH (256 in nx_p256) and the LINE NUMBERS (99, 12, 7, 1) must NOT 167 // become shapes. Without this the tally would look right while counting noise -- and 256 appears in 168 // BOTH a path and a real value here on purpose, so a prefix-skipping bug cannot hide behind it. 169 total = total + 1; if ns == 3 { pass = pass + 1; sg_w(" neg-control-path-and-line-number-digits-are-NOT-counted-as-shapes: PASS\n" as *u8) } else { sg_w(" neg-control-path-and-line-number-digits-are-NOT-counted-as-shapes: FAIL\n" as *u8) } 170 // NEG-CONTROL: the summary row has no second colon, so it must contribute no line and no shape. 171 total = total + 1; if lo[0] == 6 { pass = pass + 1; sg_w(" neg-control-the-scanner-summary-row-is-not-mistaken-for-a-match: PASS\n" as *u8) } else { sg_w(" neg-control-the-scanner-summary-row-is-not-mistaken-for-a-match: FAIL\n" as *u8) } 172 // THE TWO CONTROLS THE ORIGINAL FIXTURE LACKED, each one a defect the live census actually hit. 173 var saw2: i64 = 0 174 var saw999: i64 = 0 175 var kk: i64 = 0 176 while kk < ns { if vals[kk] == 2 { saw2 = 1 } if vals[kk] == 999 { saw999 = 1 } kk = kk + 1 } 177 total = total + 1; if saw2 == 0 { pass = pass + 1; sg_w(" neg-control-digits-welded-to-an-identifier-are-NOT-a-value: PASS\n" as *u8) } else { sg_w(" neg-control-digits-welded-to-an-identifier-are-NOT-a-value: FAIL\n" as *u8) } 178 total = total + 1; if saw999 == 0 { pass = pass + 1; sg_w(" neg-control-a-number-in-COMMENT-prose-is-NOT-a-value: PASS\n" as *u8) } else { sg_w(" neg-control-a-number-in-COMMENT-prose-is-NOT-a-value: FAIL\n" as *u8) } 179 180 sg_w("\nNX-nx_sweepgate passed " as *u8); sg_n(pass); sg_w("/" as *u8); sg_n(total) 181 if pass == total { sg_w(" verdict=GREEN (shape tally proven on the exact shape of the real failure)\n" as *u8); return 0 } 182 sg_w(" verdict=RED\n" as *u8) 183 return 1 184} 185 186// ONE CENSUS PATH, called by BOTH the argv route and the conf-driven watch route. Returns 187// 0 SINGLE-SHAPE - 1 SPLIT - 3 UNPROVEN. It never exits, so a watch sweep can run every row and report 188// them all rather than stopping at the first finding. 189func sg_census(inv: *u8, dir: *u8, ext: *u8) -> i64 { 190 let out: *u8 = sys_mmap(SG_CAP) 191 let ol: *i64 = sys_mmap(16) as *i64 192 let av: *i64 = sys_mmap(64) as *i64 193 194 // CWD PROBE, not an assumption: a gate may run from the nishihost root or from buildroot, and a 195 // tool path that resolves in one and not the other is the difference between a census and a lie. 196 var tool: *u8 = "nx_shelltool.elf" as *u8 197 var fd: i64 = sys_openat_rd(tool) 198 if fd < 0 { 199 tool = "../nx_shelltool.elf" as *u8 200 fd = sys_openat_rd(tool) 201 if fd < 0 { 202 sg_w("NX-SWEEPGATE verdict=UNPROVEN reason=scanner-unreachable\n" as *u8) 203 sg_w(" nx_shelltool.elf resolves from neither the serving root nor buildroot; I could not look.\n" as *u8) 204 return 3 205 } 206 } 207 sys_close(fd) 208 209 av[0] = tool as i64 210 av[1] = "grep" as i64 211 av[2] = inv as i64 212 av[3] = dir as i64 213 var an: i64 = 4 214 if (ext as i64) != 0 { av[an] = ext as i64; an = an + 1 } 215 av[an] = 0 216 let rc: i64 = tr_run_capture(tool, av, out, SG_CAP, ol) 217 let n: i64 = ol[0] 218 if rc != 0 { 219 sg_w("NX-SWEEPGATE verdict=UNPROVEN reason=scanner-failed rc=" as *u8); sg_n(rc); sg_w("\n" as *u8) 220 return 3 221 } 222 223 // THE ONE BOUND IN THIS ORGAN ANSWERS FOR ITSELF. SG_CAP exists because a subprocess's output 224 // length is genuinely unknowable before it runs -- that is the only kind of ceiling this estate 225 // permits, and the rule that permits it also requires the truncation to ANNOUNCE. 226 // The envelope check below would catch this today too, because the scanner prints its coverage 227 // line LAST and a truncated capture loses it. But that is an accident of ordering, not a 228 // guarantee: let the scanner ever print its envelope first and that protection disappears without 229 // one test failing anywhere. A guard that works only because of where somebody else puts a line is 230 // not a guard. So the cap refuses in its own name, and says how many bytes it took. 231 if n >= SG_CAP { 232 sg_w("NX-SWEEPGATE verdict=UNPROVEN reason=capture-cap-reached bytes=" as *u8); sg_n(n) 233 sg_w(" -- the scan may have been complete; THIS ORGAN's read of it was not, and those are different failures\n" as *u8) 234 return 3 235 } 236 237 // READ THE ENVELOPE BEFORE THE NUMBERS. A census through a partial scan is worse than none. 238 if sg_has(out, n, "coverage_complete=1" as *u8) != 1 { 239 sg_w("NX-SWEEPGATE verdict=UNPROVEN reason=coverage-incomplete\n" as *u8) 240 sg_w(" the scanner did not cover everything it was pointed at, so no population claim is available.\n" as *u8) 241 return 3 242 } 243 if sg_has(out, n, "corpus_complete=1" as *u8) != 1 { 244 sg_w("NX-SWEEPGATE verdict=UNPROVEN reason=corpus-incomplete\n" as *u8) 245 sg_w(" the scan hit a budget or a cap. matches=0 from here is NOT absence, in either direction.\n" as *u8) 246 return 3 247 } 248 249 // ONE TALLY, NOT TWO. The census and the selftest call the SAME function, so the thing the selftest 250 // proves is the thing the census runs -- a second copy here would be the duplicate-ruler defect and 251 // the proof would drift away from the shipped path without anyone noticing. 252 let vals: *i64 = sys_mmap(SG_MAX_SHAPES * 8) as *i64 253 let cnts: *i64 = sys_mmap(SG_MAX_SHAPES * 8) as *i64 254 let lo: *i64 = sys_mmap(16) as *i64 255 let nshapes: i64 = sg_tally(out, n, vals, cnts, lo) 256 let lines: i64 = lo[0] 257 var overflow: i64 = 0 258 if nshapes < 0 { overflow = 1 } 259 260 sg_w("NX-SWEEPGATE invariant=" as *u8); sg_w(inv) 261 sg_w(" dir=" as *u8); sg_w(dir) 262 sg_w(" lines=" as *u8); sg_n(lines) 263 sg_w(" shapes=" as *u8); sg_n(nshapes); sg_w("\n" as *u8) 264 var k2: i64 = 0 265 while k2 < nshapes { 266 sg_w(" " as *u8); sg_n(vals[k2]); sg_w(" x" as *u8); sg_n(cnts[k2]); sg_w("\n" as *u8) 267 k2 = k2 + 1 268 } 269 // A CAP REACHED IN SILENCE BECOMES A MEASUREMENT NOBODY KNOWS IS PARTIAL. 270 if overflow == 1 { 271 sg_w("NX-SWEEPGATE verdict=UNPROVEN reason=shape-table-full -- more distinct literals than this organ can hold\n" as *u8) 272 return 3 273 } 274 if lines == 0 { 275 sg_w("NX-SWEEPGATE verdict=UNPROVEN reason=no-matching-lines -- nothing to census (the scan WAS complete)\n" as *u8) 276 return 3 277 } 278 if nshapes > 1 { 279 sg_w("NX-SWEEPGATE verdict=SPLIT -- this population is written more than one way, so a sweep for any ONE of the values above would have reported a clean and incomplete answer\n" as *u8) 280 return 1 281 } 282 sg_w("NX-SWEEPGATE verdict=SINGLE-SHAPE -- one spelling across the whole matched population\n" as *u8) 283 return 0 284} 285 286// ---- THE DURABLE RECORD ---- 287// A beat whose output goes nowhere is a beat nobody can audit: the estate pays for the run and 288// collects nothing, which is the same failure as not running at all. One line per run, appended, so 289// "when did this population split?" has an answer with a date on it instead of whatever the last 290// person happened to still have on their terminal. 291// ONE WRITER, ONE FILE -- a log several organs append to measures a race, not a subject. 292// The canonical verdict field goes LAST on the line, because a positional reader takes the answer and 293// can never pick up a field name that happens to appear in the prose beside it. 294// UNPROVEN is emitted as itself, never folded into RED or GREEN: an axis that could not look must 295// abstain, and collapsing "I could not see" into either answer is a lie in one direction or the other. 296func sg_dig(b: *u8, o: i64, v: i64, tmp: *u8) -> i64 { 297 if v == 0 { b[o] = SG_D0 as u8; return o + 1 } 298 var k: i64 = 0 299 var x: i64 = v 300 while x > 0 { tmp[k] = (SG_D0 + (x % 10)) as u8; x = x / 10; k = k + 1 } 301 var oo: i64 = o 302 while k > 0 { k = k - 1; b[oo] = tmp[k]; oo = oo + 1 } 303 return oo 304} 305 306func sg_put(b: *u8, o: i64, s: *u8) -> i64 { 307 var i: i64 = 0 308 var oo: i64 = o 309 while s[i] != (0 as u8) { b[oo] = s[i]; i = i + 1; oo = oo + 1 } 310 return oo 311} 312 313func sg_log(rows: i64, splits: i64, unproven: i64, verdict: *u8) -> i64 { 314 let b: *u8 = sys_mmap(512) 315 let tmp: *u8 = sys_mmap(64) 316 var o: i64 = 0 317 o = sg_put(b, o, "NX-SWEEPGATE watch rows=" as *u8) 318 o = sg_dig(b, o, rows, tmp) 319 o = sg_put(b, o, " split=" as *u8) 320 o = sg_dig(b, o, splits, tmp) 321 o = sg_put(b, o, " unproven=" as *u8) 322 o = sg_dig(b, o, unproven, tmp) 323 o = sg_put(b, o, " verdict=" as *u8) 324 o = sg_put(b, o, verdict) 325 b[o] = SG_NL as u8 326 o = o + 1 327 let fd: i64 = sys_openat_append("knowledge/status/sweepgate.log" as *u8, MODE_0644) 328 if fd < 0 { 329 sg_w("NX-SWEEPGATE log=UNWRITTEN -- the durable record could not be opened, so this run leaves nothing behind it\n" as *u8) 330 return 1 331 } 332 let w: i64 = sys_write(fd, b, o) 333 sys_close(fd) 334 // ANNOUNCE. A feature that prints nothing when it works is indistinguishable from one that was 335 // never compiled in -- absent code has no failure mode, so the build stays clean and the run stays 336 // green while the record silently stops being written. Publishing the byte counts turns "did the 337 // log land?" into one number the reader already has, instead of a hunt through the filesystem. 338 sg_w("NX-SWEEPGATE log=knowledge/status/sweepgate.log wrote=" as *u8); sg_n(w) 339 sg_w(" of=" as *u8); sg_n(o); sg_w("\n" as *u8) 340 return 0 341} 342 343// THE STANDING CENSUS. Rows live in a conf, so the estate declares WHAT must stay single-spelled and 344// this organ checks it on every beat. That is the difference between a tool somebody could run and a 345// control that actually runs -- the gap this whole session was spent closing. 346// Running declared conf rows on no-argv is NOT the silent-default defect: the rows are explicit, they 347// are in the SSOT, and a missing conf is reported as UNOBSERVABLE rather than treated as clean. 348func sg_watch() -> i64 { 349 let cl: *i64 = sys_mmap(16) as *i64 350 var conf: *u8 = sys_read_file("knowledge/status/sweepgate_watch.conf" as *u8, cl) 351 if (conf as i64) == 0 { conf = sys_read_file("buildroot/knowledge/status/sweepgate_watch.conf" as *u8, cl) } 352 if (conf as i64) == 0 { 353 sg_w("\nNX-SWEEPGATE watch=UNOBSERVABLE -- sweepgate_watch.conf resolves from neither root; declared rows unknown\n" as *u8) 354 return 3 355 } 356 let n: i64 = cl[0] 357 sg_w("\nstanding census over the declared watch rows:\n" as *u8) 358 var rows: i64 = 0 359 var splits: i64 = 0 360 var unproven: i64 = 0 361 var p: i64 = 0 362 while p < n { 363 var e: i64 = p 364 while e < n { if conf[e] == (SG_NL as u8) { break } e = e + 1 } 365 if e > p { if conf[p] != (35 as u8) { 366 // split on '|' in place: invariant | dir | ext 367 var f1: i64 = 0 - 1 368 var f2: i64 = 0 - 1 369 var c: i64 = p 370 while c < e { 371 if conf[c] == (124 as u8) { if f1 < 0 { f1 = c } else { if f2 < 0 { f2 = c } } } 372 c = c + 1 373 } 374 if f1 > 0 { 375 conf[f1] = 0 as u8 376 var ext2: *u8 = 0 as *u8 377 if f2 > 0 { conf[f2] = 0 as u8; ext2 = (conf as i64 + f2 + 1) as *u8 } 378 conf[e] = 0 as u8 379 let inv2: *u8 = (conf as i64 + p) as *u8 380 let dir2: *u8 = (conf as i64 + f1 + 1) as *u8 381 rows = rows + 1 382 let rv: i64 = sg_census(inv2, dir2, ext2) 383 if rv == 1 { splits = splits + 1 } 384 if rv == 3 { unproven = unproven + 1 } 385 } 386 } } 387 p = e + 1 388 } 389 sg_w("\nwatch rows=" as *u8); sg_n(rows) 390 sg_w(" split=" as *u8); sg_n(splits) 391 sg_w(" unproven=" as *u8); sg_n(unproven); sg_w("\n" as *u8) 392 if rows == 0 { 393 sg_w("NX-SWEEPGATE watch=UNOBSERVABLE -- the conf declared no rows\n" as *u8) 394 sg_log(rows, splits, unproven, "UNPROVEN" as *u8) 395 return 3 396 } 397 if unproven > 0 { 398 sg_w("NX-SWEEPGATE watch=UNPROVEN -- at least one row could not be censused\n" as *u8) 399 sg_log(rows, splits, unproven, "UNPROVEN" as *u8) 400 return 3 401 } 402 if splits > 0 { 403 sg_w("NX-SWEEPGATE watch=SPLIT -- a declared population is written more than one way\n" as *u8) 404 sg_log(rows, splits, unproven, "RED" as *u8) 405 return 1 406 } 407 sg_w("NX-SWEEPGATE watch=CLEAN -- every declared population has exactly one spelling\n" as *u8) 408 sg_log(rows, splits, unproven, "GREEN" as *u8) 409 return 0 410} 411 412func main(argc: i64, argv: *i64) -> i64 { 413 if argc < 2 { 414 let rc0: i64 = sg_selftest() 415 let rc1: i64 = sg_watch() 416 var rc: i64 = rc0 417 if rc1 != 0 { rc = rc1 } 418 sys_exit(rc); return rc 419 } 420 if argc < 3 { 421 sg_w("usage: nx_sweepgate <invariant> <dir> [ext]\n" as *u8) 422 sg_w(" Query by the INVARIANT the sites share, never by one instance of it. Reports every\n" as *u8) 423 sg_w(" distinct numeric literal across the matching lines, so a second spelling cannot hide.\n" as *u8) 424 sg_w(" With NO arguments it runs its selftest AND the declared watch rows.\n" as *u8) 425 sys_exit(2); return 2 426 } 427 var ext3: *u8 = 0 as *u8 428 if argc >= 4 { ext3 = argv[3] as *u8 } 429 let rc2: i64 = sg_census(argv[1] as *u8, argv[2] as *u8, ext3) 430 sys_exit(rc2); return rc2 431}