code wiki / _hdl_build / nx_unwired.nx

nx_unwired.nx source

↩ module page · 540 lines · 28000 B

1// nx_unwired.nx -- FIND EVERY FUNCTION THAT IS DEFINED AND NEVER CALLED, ACROSS THE WHOLE TREE. 2// 3// WHY THIS IS AN ORGAN AND NOT A NOTE 4// ----------------------------------- 5// On 2026-08-07 I fixed a measurement leak in nx_memroot, wrote the fix, built it, deployed it, 6// measured the "result", and recorded it in memory. `mr_body` was DEFINED AND NEVER CALLED. Two 7// string-replacements had matched nothing and reported success. The gate was green because the gate 8// had gone green before the tooth existed. 9// 10// ★★★★★★ A FUNCTION DEFINED AND NEVER CALLED IS A COMMENT. 11// ★★★★★ A STRING REPLACE THAT MATCHES NOTHING IS A NO-OP THAT REPORTS SUCCESS -- VERIFY THE CALL 12// SITE, NOT THE DEFINITION. 13// 14// The estate already had vocabulary for this failure -- BUILT+UNWIRED, "comments not code", the 15// adoption gap -- written down in several memory files. It was written down and it still happened, 16// three times in one session, because a law in a file is consulted at the rate advice is consulted. 17// ★★★★★★ A LAW THAT IS ONLY WRITTEN DOWN IS ENFORCED AT THE RATE PEOPLE REMEMBER TO READ IT; THE SAME 18// LAW COMPILED INTO A GATE IS ENFORCED EVERY TIME. 19// 20// FULL ECOSYSTEM SCOPE, NOT A SAMPLE: every `.nx` in the tree is both a definition source and a call 21// source, so a helper used only by a sibling organ is correctly seen as WIRED. Reporting on one file 22// would manufacture false positives for every library function. 23// ★★★★★ A REACHABILITY QUESTION ASKED OF ONE FILE IS ANSWERED WRONG BY CONSTRUCTION. 24// 25// usage: nx_unwired [--dir D] [--quiet] 26// exit: 0 = nothing unwired; 1 = unwired definitions exist 27// license_tier: ORIGINAL 28import "nx_memplane_lib.nx" 29import "nx_gatekit_lib.nx" 30const UW_MAGIC_2166136261: i64 = 2166136261 31const UW_MAGIC_16777619: i64 = 16777619 32const UW_MAGIC_1073741823: i64 = 1073741823 33const UW_MAGIC_8192: i64 = 8192 34const UW_MAGIC_4096: i64 = 4096 35const UW_MAGIC_262144: i64 = 262144 36const UW_MAGIC_262000: i64 = 262000 37 38// ⚠ UW_DIR IS NO LONGER THE CORPUS. It scanned _hdl_build ONLY -- 7,159 of 18,559 files, 38.6% -- 39// while the header above claimed "every .nx in the tree". Because the unscanned files are BOTH 40// definition sources AND call sources, that truncation was wrong in both directions at once: 41// 30 names were reported UNWIRED that ARE called in files it never opened, and 3,379 definitions 42// in those files were never examined. The corpus now comes from gk_corpus_scan, the estate's one 43// definition of "the tree" (see nx_gatekit_lib), so this organ and gk_srcpath cannot disagree. 44// ★★★★★★ A CENSUS IS ONLY AS HONEST AS ITS DENOMINATOR, AND THE DENOMINATOR BELONGS IN ONE PLACE. 45const UW_DIR: *u8 = "/mnt/c/Users/elder/nishi-core/nxc2/runtime/_hdl_build/" 46const UW_MAXF: i64 = 32768 // corpus is 18,560 today; 16,384 would REFUSE, which is why it rose 47const UW_HASH: i64 = 262144 // identifier -> slot (power of two) 48const UW_FBUF: i64 = 4194304 49const UW_NAMEB: i64 = 1048576 // packed definition names 50 51import "nx_headmark_lib.nx" 52func uw_h(s: *u8, n: i64) -> i64 { 53 var h: i64 = UW_MAGIC_2166136261 54 var i: i64 = 0 55 while i < n { 56 h = h ^ (s[i] as i64) 57 h = (h * UW_MAGIC_16777619) & UW_MAGIC_1073741823 58 i = i + 1 59 } 60 if h == 0 { h = 1 } 61 return h 62} 63 64func uw_slot(keys: *i64, h: i64) -> i64 { 65 var p: i64 = h & (UW_HASH - 1) 66 var tries: i64 = 0 67 var res: i64 = 0 - 1 68 var go: i64 = 1 69 while go == 1 { 70 if tries >= 64 { go = 0 } 71 if go == 1 { 72 if keys[p] == 0 { keys[p] = h; res = p; go = 0 } 73 if go == 1 { 74 if keys[p] == h { res = p; go = 0 } 75 if go == 1 { p = (p + 1) & (UW_HASH - 1); tries = tries + 1 } 76 } 77 } 78 } 79 return res 80} 81 82// Does the file DECLARE ITSELF a generated artifact? Checked in the head only, where such banners 83// live, so the word appearing later in ordinary prose cannot misclassify a hand-written organ. 84// 85// WHY THIS IS ITS OWN BUCKET: nx_shapeprobe_cand.nx is a codegen-shape reproducer holding 1,002 86// machine-emitted `sp2_N` functions, 265 of which the census counted as UNWIRED -- 17% of the entire 87// backlog. They are not an adoption gap: the file exists precisely to compile shapes nothing calls. 88// Counting them inflates the worklist; silently dropping them would hide real defects in generated 89// code. ★★★★★★ TWO CAUSES WITH OPPOSITE REMEDIES MUST NEVER SHARE A COUNTER -- REPORT BOTH, RATCHET 90// ONLY THE ONE A HUMAN CAN ACT ON. 91// The artifact declares itself, which is the estate's own rule for generated output. 92 93 94// A DEFINITION-COMPLETE library is one whose uncalled state is CORRECT: an ISA encoder with one 95// function per instruction, an opcode/codec table, a protocol constant set. `nxasm_arm64_enc.nx` 96// holds 45 A64 encoders of which 24 are uncalled because the aarch64 backend is still being built -- 97// deleting them would strip the capability under construction (rule 25). 98// ★★★★★★ AN ISA ENCODER OR TABLE LIBRARY IS DEFINITION-COMPLETE BY DESIGN, NOT CALL-COMPLETE, AND A 99// REACHABILITY RATCHET READS ITS CORRECT STEADY STATE AS DEBT. 100// 101// THIS IS A DECLARATION, NOT A DETECTOR, AND THAT IS THE WHOLE POINT. A heuristic that guessed at 102// "looks like a table" would gate a DESTRUCTIVE remedy, and a heuristic gating deletion must be wrong 103// in the direction of doing nothing -- so there is no heuristic. The file says so itself, exactly as 104// generated artifacts do. ★★★★★ THE ARTEFACT MUST DECLARE ITSELF; A CENTRAL LIST ALWAYS LAGS THE TREE. 105func uw_defcomplete(buf: *u8, n: i64) -> i64 { 106 return uw_headmark(buf, n, "DEFINITION-COMPLETE" as *u8, 19) 107} 108 109// An EXPORTED-ENTRYPOINTS file's functions are called from OUTSIDE the .nx corpus -- wasm exports 110// invoked by the browser, handlers dispatched by name, ABI shims called by the loader. The census 111// only ever sees .nx call sites, so their caller is structurally invisible to it and "uncalled" is 112// their correct steady state. 113// ★★★★★★ A REACHABILITY CENSUS CAN ONLY SEE THE CALLERS INSIDE ITS OWN CORPUS; A FUNCTION CALLED FROM 114// OUTSIDE IT IS INVISIBLY WIRED, AND COUNTING IT AS DEBT INVITES DELETING A LIVE ENTRY POINT. 115// A separate marker from DEFINITION-COMPLETE on purpose: those are "not called YET" (a backend under 116// construction), these are "called, but not from here". Same symptom, different truth, different 117// remedy. ★★★★★ A BUCKET NAMED FOR HOW THE READER FAILED MERGES A REAL FAILURE WITH A HEALTHY PASS. 118func uw_exported(buf: *u8, n: i64) -> i64 { 119 return uw_headmark(buf, n, "EXPORTED-ENTRYPOINTS" as *u8, 20) 120} 121 122func uw_isid(c: i64) -> i64 { 123 if c >= 97 { if c <= 122 { return 1 } } 124 if c >= 65 { if c <= 90 { return 1 } } 125 if c >= 48 { if c <= 57 { return 1 } } 126 if c == 95 { return 1 } 127 return 0 128} 129 130// is the file a .nx source? 131func uw_isnx(name: *u8) -> i64 { 132 let l: i64 = mp_len(name) 133 if l < 4 { return 0 } 134 if name[l - 3] != (46 as u8) { return 0 } 135 if name[l - 2] != (110 as u8) { return 0 } 136 if name[l - 1] != (120 as u8) { return 0 } 137 return 1 138} 139 140// mp_scan hard-filters to .md (it is the memory-plane scanner), so a source tree needs its own walk. 141// ★ A SCANNER NAMED FOR A GENERAL ACTION MAY CARRY A SPECIFIC FILTER -- READ IT BEFORE REUSING IT. 142 143 144func main(argc: i64, argv: *i64) -> i64 { 145 var dir: *u8 = UW_DIR 146 var dirset: i64 = 0 147 var trace: i64 = 0 148 var quiet: i64 = 0 149 var accept: i64 = 0 150 var a: i64 = 1 151 while a < argc { 152 let s: *u8 = argv[a] as *u8 153 if mp_streq(s, "--dir" as *u8) == 1 { if a + 1 < argc { dir = argv[a + 1] as *u8; dirset = 1; a = a + 1 } } 154 if mp_streq(s, "--quiet" as *u8) == 1 { quiet = 1 } 155 if mp_streq(s, "--trace" as *u8) == 1 { trace = 1 } 156 if mp_streq(s, "--accept" as *u8) == 1 { accept = 1 } 157 a = a + 1 158 } 159 160 let msg: *u8 = sys_mmap(UW_MAGIC_8192) 161 let names: *u8 = sys_mmap(UW_MAXF * 128) 162 let ntbl: *i64 = sys_mmap(8 * UW_MAGIC_8192) as *i64 163 let fbuf: *u8 = sys_mmap(UW_FBUF) 164 let path: *u8 = sys_mmap(UW_MAGIC_4096) 165 166 let keys: *i64 = sys_mmap(8 * UW_HASH) as *i64 167 let uses: *i64 = sys_mmap(8 * UW_HASH) as *i64 168 let defat: *i64 = sys_mmap(8 * UW_HASH) as *i64 // slot -> offset into nameb, +1 (0 = not a def) 169 let deffl: *i64 = sys_mmap(8 * UW_HASH) as *i64 // slot -> file index 170 let genf: *i64 = sys_mmap(8 * UW_MAXF) as *i64 // file index -> 1 if self-declared generated 171 let dcf: *i64 = sys_mmap(8 * UW_MAXF) as *i64 // file index -> 1 if self-declared DEFINITION-COMPLETE 172 let expf: *i64 = sys_mmap(8 * UW_MAXF) as *i64 // file index -> 1 if self-declared EXPORTED-ENTRYPOINTS 173 let nameb: *u8 = sys_mmap(UW_NAMEB) 174 var nbo: i64 = 1 175 176 // THE CORPUS. Default is the whole compile corpus (both source directories, _hdl_build 177 // overlaying runtime, exactly as gk_srcpath resolves a target). --dir narrows it deliberately; 178 // the narrowing is then VISIBLE in the output rather than baked into a constant nobody reads. 179 var cnt: i64 = 0 180 if dirset == 0 { cnt = gk_corpus_scan(names, MP_SLOT, UW_MAXF) } 181 if dirset == 1 { cnt = gk_dirscan(dir, 0 as *u8, names, MP_SLOT, UW_MAXF, 0) } 182 183 if cnt == (0 - 2) { 184 var m2: i64 = mp_cat(msg, 0, "*** nx_unwired: REFUSED -- the corpus exceeds UW_MAXF (" as *u8) 185 m2 = mp_catn(msg, m2, UW_MAXF) 186 m2 = mp_cat(msg, m2, "). Raise it. A truncated census under-reports unwired functions AND invents them. ***\n" as *u8) 187 mp_say(msg, m2) 188 return 1 189 } 190 if cnt == (0 - 3) { 191 var m3: i64 = mp_cat(msg, 0, "*** nx_unwired: REFUSED -- a source path is longer than the name slot. ***\n" as *u8) 192 mp_say(msg, m3) 193 return 1 194 } 195 if cnt <= 0 { 196 var me: i64 = mp_cat(msg, 0, "*** nx_unwired: REFUSED -- could not scan the source tree. ***\n" as *u8) 197 mp_say(msg, me) 198 return 1 199 } 200 // A CENSUS THAT HIT ITS CAP IS NOT A CENSUS. The first run reported "4096 sources" against a tree 201 // of 7,113 -- 58% coverage presented as a complete answer, with no indication anything was 202 // dropped. A partial count is more dangerous than no count, because it reads as authoritative. 203 // ★★★★★★ A CAP REACHED IN SILENCE BECOMES A MEASUREMENT NOBODY KNOWS IS PARTIAL -- REFUSE, OR SAY 204 // WHAT YOU DROPPED, BUT NEVER RETURN A TRUNCATED TOTAL WEARING A COMPLETE ONE'S CLOTHES. 205 // (The cap check that used to live here now lives INSIDE gk_corpus_scan and returns -2, handled 206 // above. It moved because the refusal must belong to the enumerator, not to each of its callers: 207 // ★★★★★ A SAFETY CHECK RE-IMPLEMENTED BY EVERY CALLER IS A SAFETY CHECK SOME CALLER WILL OMIT.) 208 var mcorp: i64 = mp_cat(msg, 0, " corpus=" as *u8) 209 mcorp = mp_catn(msg, mcorp, cnt) 210 if dirset == 0 { mcorp = mp_cat(msg, mcorp, " files (WHOLE compile corpus: runtime/_hdl_build + runtime)\n" as *u8) } 211 if dirset == 1 { mcorp = mp_cat(msg, mcorp, " files (NARROWED by --dir; this is NOT the whole tree)\n" as *u8) } 212 mp_say(msg, mcorp) 213 214 var nfiles: i64 = 0 215 var ndefs: i64 = 0 216 217 // ---- one pass: record every `func NAME(` definition AND count every identifier occurrence ---- 218 var fi: i64 = 0 219 while fi < cnt { 220 // The corpus scanner returns ABSOLUTE paths, so there is no dir to re-join here. That join 221 // was the seam where a second directory could not be represented at all. 222 let nm: *u8 = mp_nameptr(names, fi) 223 if trace == 1 { 224 var mt: i64 = mp_cat(msg, 0, "TRACE " as *u8) 225 mt = mp_catn(msg, mt, fi) 226 mt = mp_cat(msg, mt, " " as *u8) 227 mt = mp_cat(msg, mt, nm) 228 mt = mp_cat(msg, mt, "\n" as *u8) 229 mp_say(msg, mt) 230 } 231 if uw_isnx(nm) == 1 { 232 let n: i64 = mp_readf(nm, fbuf, UW_FBUF) 233 if n > 0 { 234 nfiles = nfiles + 1 235 genf[fi] = uw_generated(fbuf, n) 236 dcf[fi] = uw_defcomplete(fbuf, n) 237 expf[fi] = uw_exported(fbuf, n) 238 var i: i64 = 0 239 while i < n { 240 if uw_isid(fbuf[i] as i64) == 1 { 241 // FLAG-TERMINATED. The sentinel form (`e = n + 9`) writes the exit marker into 242 // the cursor and the restore lands on `n`, so every identifier "extends to end 243 // of file" -- one token per file, zero definitions found. This is the FOURTH 244 // time that idiom has cost a defect in one session, and it happened here while 245 // writing the organ whose whole purpose is catching unverified changes. 246 // ★★★★★★ THE IDIOM YOU KEEP FIXING BY HAND IS THE ONE THAT WILL BITE YOU INSIDE 247 // THE TOOL YOU BUILT TO CATCH IT. 248 var e: i64 = i 249 var fin: i64 = 0 250 while fin == 0 { 251 if e >= n { fin = 1 } 252 if fin == 0 { 253 if uw_isid(fbuf[e] as i64) == 1 { e = e + 1 } 254 if uw_isid(fbuf[e] as i64) == 0 { fin = 1 } 255 } 256 } 257 let idl: i64 = e - i 258 // must start with a letter or underscore, not a digit 259 var okstart: i64 = 0 260 let c0: i64 = fbuf[i] as i64 261 if c0 == 95 { okstart = 1 } 262 if c0 >= 97 { if c0 <= 122 { okstart = 1 } } 263 if c0 >= 65 { if c0 <= 90 { okstart = 1 } } 264 if okstart == 1 { 265 if idl > 1 { 266 let h: i64 = uw_h(((fbuf as i64) + i) as *u8, idl) 267 let sl: i64 = uw_slot(keys, h) 268 if sl >= 0 { 269 uses[sl] = uses[sl] + 1 270 // a DEFINITION is `func` + space + this identifier 271 var isdef: i64 = 0 272 if i >= 5 { 273 if fbuf[i - 1] == (32 as u8) { 274 if fbuf[i - 2] == (99 as u8) { 275 if fbuf[i - 3] == (110 as u8) { 276 if fbuf[i - 4] == (117 as u8) { 277 if fbuf[i - 5] == (102 as u8) { isdef = 1 } 278 } 279 } 280 } 281 } 282 } 283 if isdef == 1 { 284 if defat[sl] == 0 { 285 if nbo + idl + 2 < UW_NAMEB { 286 var q: i64 = 0 287 while q < idl { nameb[nbo + q] = fbuf[i + q]; q = q + 1 } 288 nameb[nbo + idl] = 0 as u8 289 defat[sl] = nbo 290 deffl[sl] = fi 291 nbo = nbo + idl + 1 292 ndefs = ndefs + 1 293 } 294 } 295 } 296 } 297 } 298 } 299 i = e 300 } 301 if uw_isid(fbuf[i] as i64) == 0 { i = i + 1 } 302 } 303 } 304 } 305 fi = fi + 1 306 } 307 308 // ---- report: a definition whose identifier occurs exactly once is never called ---- 309 var nunwired: i64 = 0 310 var ngen: i64 = 0 311 var ndc: i64 = 0 // unwired inside SELF-DECLARED DEFINITION-COMPLETE libraries 312 var nexp: i64 = 0 // unwired inside SELF-DECLARED EXPORTED-ENTRYPOINTS files // unwired inside SELF-DECLARED GENERATED files -- reported, never ratcheted 313 var m: i64 = 0 314 var sl2: i64 = 0 315 while sl2 < UW_HASH { 316 if defat[sl2] != 0 { 317 // `main` is called by the runtime, not by source 318 let dn: *u8 = ((nameb as i64) + defat[sl2]) as *u8 319 var skip: i64 = 0 320 if mp_streq(dn, "main" as *u8) == 1 { skip = 1 } 321 if skip == 0 { if uses[sl2] <= 1 { if genf[deffl[sl2]] == 1 { ngen = ngen + 1; skip = 1 } } } 322 if skip == 0 { if uses[sl2] <= 1 { if dcf[deffl[sl2]] == 1 { ndc = ndc + 1; skip = 1 } } } 323 if skip == 0 { if uses[sl2] <= 1 { if expf[deffl[sl2]] == 1 { nexp = nexp + 1; skip = 1 } } } 324 if skip == 0 { 325 if uses[sl2] <= 1 { 326 nunwired = nunwired + 1 327 if quiet == 0 { 328 m = mp_cat(msg, 0, " UNWIRED " as *u8) 329 m = mp_cat(msg, m, dn) 330 m = mp_cat(msg, m, " defined in " as *u8) 331 m = mp_cat(msg, m, mp_nameptr(names, deffl[sl2])) 332 m = mp_cat(msg, m, " -- never called anywhere in the tree\n" as *u8) 333 mp_say(msg, m) 334 } 335 } 336 } 337 } 338 sl2 = sl2 + 1 339 } 340 341 m = mp_cat(msg, 0, "nx_unwired: " as *u8) 342 m = mp_catn(msg, m, nfiles) 343 m = mp_cat(msg, m, " sources, " as *u8) 344 m = mp_catn(msg, m, ndefs) 345 m = mp_cat(msg, m, " functions, " as *u8) 346 m = mp_catn(msg, m, nunwired) 347 m = mp_cat(msg, m, " UNWIRED (authored)" as *u8) 348 m = mp_cat(msg, m, ", " as *u8) 349 m = mp_catn(msg, m, ngen) 350 m = mp_cat(msg, m, " more in self-declared GENERATED files (reported, not ratcheted -- a codegen reproducer is meant to hold uncalled shapes)" as *u8) 351 m = mp_cat(msg, m, ", " as *u8) 352 m = mp_catn(msg, m, ndc) 353 m = mp_cat(msg, m, " in self-declared DEFINITION-COMPLETE libraries (an ISA/table library is correct while uncalled)" as *u8) 354 m = mp_cat(msg, m, ", " as *u8) 355 m = mp_catn(msg, m, nexp) 356 m = mp_cat(msg, m, " in self-declared EXPORTED-ENTRYPOINTS files (called from outside the .nx corpus, so invisibly wired)" as *u8) 357 358 // ---- RATCHET, not a threshold ---- 359 // 396 pre-existing unwired functions cannot be a pass/fail gate: it would sit RED forever and be 360 // ignored within a day. What IS enforceable is the DIRECTION -- the count may never rise, and when 361 // it falls the ceiling follows it down so the gain can never be given back. 362 // ★★★★★ A DETECTOR THAT IS PERMANENTLY RED IS A DETECTOR EVERYONE LEARNS TO IGNORE; RATCHET THE 363 // DIRECTION INSTEAD OF DEMANDING PERFECTION ON DAY ONE. 364 // ★★★★★ A RATCHET THAT DOES NOT TIGHTEN WHEN YOU IMPROVE IS JUST A THRESHOLD -- IT MUST FOLLOW THE 365 // BEST RESULT DOWN, AUTOMATICALLY, OR THE NEXT REGRESSION HIDES INSIDE THE SLACK YOU EARNED. 366 // THE BASELINE IS A SET OF NAMES, NOT A COUNT. This tree is shared and written concurrently: 367 // mid-measurement, 9 organs from another seat appeared at once and the count rose by 2 through no 368 // action of mine. A count-only ratchet would have reported MY run as the regression. 369 // ★★★★★★ A COUNT-ONLY RATCHET ON A SHARED TREE REPORTS A REGRESSION WITHOUT SAYING WHOSE -- AND AN 370 // ALARM YOU CANNOT ATTRIBUTE IS AN ALARM YOU WILL LEARN TO CLEAR WITHOUT READING. 371 // Flush the summary before the diff so the per-line emitter below cannot interleave with a 372 // half-built buffer, and so a crash after this point still leaves the totals on the record. 373 mp_say(msg, m) 374 m = 0 375 let nbuf: *u8 = sys_mmap(UW_MAGIC_4096) 376 // HOST-RESOLVED, not hardcoded: the baseline must live beside the tree it describes, or an 377 // organ shipped to a second host silently ratchets against another machine's record. 378 let bl: *u8 = sys_mmap(UW_MAGIC_4096) 379 if gk_ops_path(bl, "unwired.baseline" as *u8) == 0 { 380 var mb: i64 = mp_cat(msg, 0, "*** nx_unwired: REFUSED -- cannot resolve the baseline dir on this host. ***\n" as *u8) 381 mp_say(msg, mb) 382 return 1 383 } 384 let bb: *u8 = sys_mmap(UW_MAGIC_262144) 385 let bn: i64 = mp_readf(bl, bb, UW_MAGIC_262000) 386 387 // THE BASELINE RECORDS ITS OWN POPULATION, as a "# corpus=N" first line. 388 // A ratchet compared across two different corpora is not a ratchet: it reports the RULER 389 // changing as though the TREE had regressed. That is exactly how the single-directory census 390 // stayed hidden for so long -- nothing anywhere declared what had actually been counted, so 391 // 403-of-7,159 and 1,559-of-18,561 were silently comparable numbers. 392 // ★★★★★★ A BASELINE THAT DOES NOT RECORD ITS DENOMINATOR CANNOT TELL A REGRESSION FROM A 393 // RE-MEASUREMENT, AND WILL CONFIDENTLY REPORT THE SECOND AS THE FIRST. 394 var bcorp: i64 = 0 395 if bn > 9 { 396 if bb[0] == (35 as u8) { 397 var ci: i64 = 9 398 var cgo: i64 = 1 399 while cgo == 1 { 400 let d: i64 = bb[ci] as i64 401 if d < 48 { cgo = 0 } 402 if d > 57 { cgo = 0 } 403 if cgo == 1 { bcorp = bcorp * 10 + (d - 48); ci = ci + 1 } 404 if ci >= bn { cgo = 0 } 405 } 406 } 407 } 408 var popchanged: i64 = 0 409 if bcorp > 0 { if bcorp != cnt { popchanged = 1 } } 410 411 var rc: i64 = 0 412 var nadd: i64 = 0 413 var ngone: i64 = 0 414 415 // mark every baseline name in a lookup so the diff is O(n) 416 let bkeys: *i64 = sys_mmap(8 * UW_HASH) as *i64 417 if bn > 0 { 418 var p: i64 = 0 419 while p < bn { 420 var e2: i64 = p 421 var f2: i64 = 0 422 while f2 == 0 { 423 if e2 >= bn { f2 = 1 } 424 if f2 == 0 { 425 if bb[e2] == (10 as u8) { f2 = 1 } 426 if f2 == 0 { e2 = e2 + 1 } 427 } 428 } 429 if e2 > p { 430 let hh: i64 = uw_h(((bb as i64) + p) as *u8, e2 - p) 431 let ss: i64 = uw_slot(bkeys, hh) 432 if ss >= 0 { bkeys[ss] = hh } 433 } 434 p = e2 + 1 435 } 436 } 437 438 // ADDED = unwired now, absent from the baseline. Those are the actionable ones. 439 let outb: *u8 = sys_mmap(UW_MAGIC_262144) 440 var oo: i64 = mp_cat(outb, 0, "# corpus=" as *u8) 441 oo = mp_catn(outb, oo, cnt) 442 oo = mp_cat(outb, oo, "\n" as *u8) 443 var s3: i64 = 0 444 while s3 < UW_HASH { 445 if defat[s3] != 0 { 446 let dn2: *u8 = ((nameb as i64) + defat[s3]) as *u8 447 var sk: i64 = 0 448 if mp_streq(dn2, "main" as *u8) == 1 { sk = 1 } 449 // Generated files are reported but NEVER ratcheted: their contents churn wholesale every 450 // time the generator runs, so a baseline over them is noise that buries real regressions. 451 if sk == 0 { if genf[deffl[s3]] == 1 { sk = 1 } } 452 if sk == 0 { if dcf[deffl[s3]] == 1 { sk = 1 } } 453 if sk == 0 { if expf[deffl[s3]] == 1 { sk = 1 } } 454 if sk == 0 { 455 if uses[s3] <= 1 { 456 oo = mp_cat(outb, oo, dn2) 457 outb[oo] = 10 as u8 458 oo = oo + 1 459 if bn > 0 { 460 let h3: i64 = uw_h(dn2, mp_len(dn2)) 461 var found: i64 = 0 462 var pp: i64 = h3 & (UW_HASH - 1) 463 var tr: i64 = 0 464 var go3: i64 = 1 465 while go3 == 1 { 466 if tr >= 64 { go3 = 0 } 467 if go3 == 1 { 468 if bkeys[pp] == 0 { go3 = 0 } 469 if go3 == 1 { 470 if bkeys[pp] == h3 { found = 1; go3 = 0 } 471 if go3 == 1 { pp = (pp + 1) & (UW_HASH - 1); tr = tr + 1 } 472 } 473 } 474 } 475 if found == 0 { 476 nadd = nadd + 1 477 // EMIT PER LINE, NEVER ACCUMULATE. This previously appended every entry 478 // into the 8 KB `msg` and flushed once at the end: ~150 B per entry, so 479 // it overflowed and SIGSEGV'd past ~54 additions. The organ therefore 480 // crashed precisely when a large regression appeared -- the one occasion 481 // its output mattered -- and looked perfectly healthy on small diffs. 482 // ★★★★★★ AN UNBOUNDED ACCUMULATOR SIZED BY THE HAPPY PATH FAILS ONLY ON 483 // THE BAD NEWS IT EXISTS TO DELIVER. 484 var mn: i64 = mp_cat(nbuf, 0, " *** NEWLY UNWIRED: " as *u8) 485 mn = mp_cat(nbuf, mn, dn2) 486 mn = mp_cat(nbuf, mn, " in " as *u8) 487 mn = mp_cat(nbuf, mn, mp_nameptr(names, deffl[s3])) 488 mn = mp_cat(nbuf, mn, " ***\n" as *u8) 489 mp_say(nbuf, mn) 490 } 491 } 492 } 493 } 494 } 495 s3 = s3 + 1 496 } 497 498 if bn <= 0 { m = mp_cat(msg, m, " (no baseline yet -- recording the current set)\n" as *u8) } 499 if bn > 0 { 500 if popchanged == 1 { 501 m = mp_cat(msg, m, "\n *** POPULATION CHANGED: baseline was taken over " as *u8) 502 m = mp_catn(msg, m, bcorp) 503 m = mp_cat(msg, m, " files, this run measured " as *u8) 504 m = mp_catn(msg, m, cnt) 505 m = mp_cat(msg, m, ". The names above are NOT attributable regressions -- they are what a different corpus makes visible. Re-baseline deliberately with --accept. ***\n" as *u8) 506 } 507 if nadd > 0 { if popchanged == 0 { 508 m = mp_cat(msg, m, "\n *** RED: " as *u8) 509 m = mp_catn(msg, m, nadd) 510 m = mp_cat(msg, m, " function(s) newly defined and never called -- named above, so the regression can be attributed. ***\n" as *u8) 511 rc = 1 512 } } 513 if nadd == 0 { m = mp_cat(msg, m, " GREEN: no NEW unwired function since the baseline.\n" as *u8) } 514 } 515 mp_say(msg, m) 516 517 // The baseline only ever tightens on its own: it is rewritten when nothing new appeared, so a fixed 518 // function can never be re-broken for free. 519 // 520 // --accept is the DELIBERATE act for adopting a regression you are not going to fix -- in a shared 521 // tree most reds belong to another seat, and there has to be a way to acknowledge one without 522 // either editing their code or leaving the roster permanently red. 523 // ★★★★★ AN ALARM WITH NO ACKNOWLEDGE PATH IS CLEARED BY IGNORING IT, WHICH CLEARS EVERY OTHER ALARM 524 // TOO. Make acknowledgement explicit, deliberate, and recorded -- never automatic. 525 var writeit: i64 = 0 526 if nadd == 0 { writeit = 1 } 527 if accept == 1 { writeit = 1 } 528 if writeit == 1 { 529 let wf: i64 = sys_openat_wr(bl, 420) 530 if wf >= 0 { mp_write_all(wf, outb, oo); sys_close(wf) } 531 if accept == 1 { if nadd > 0 { 532 var ma: i64 = mp_cat(msg, 0, " ACCEPTED " as *u8) 533 ma = mp_catn(msg, ma, nadd) 534 ma = mp_cat(msg, ma, " into the baseline by explicit --accept (named above, so the record says what was adopted and by whom).\n" as *u8) 535 mp_say(msg, ma) 536 rc = 0 537 } } 538 } 539 return rc 540}