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}