nx_refdrift.nx source
↩ module page · 600 lines · 33275 B
1// nx_refdrift.nx -- DOES THE URL STILL SERVE THE BYTES WE PINNED? The refs referee proves the mirror matches
2// its pin, which is a claim about OUR disk. It says so about itself in its own verdict note: "fetch-time
3// provenance proves the mirror is OF the url. It does NOT prove the url still serves those bytes." This
4// organ closes that residual, and it exists because the gap was measured the hard way on 2026-09-04: two
5// pinned standards had MOVED upstream since they were fetched, and a seat only discovered it by re-fetching
6// them for an unrelated reason. A CITATION THAT DRIFTS SILENTLY IS A CLAIM WITH AN EXPIRY DATE NOBODY
7// RECORDED -- the pin still matches the mirror, the mirror still matches the pin, and the source has changed.
8//
9// IT COMPARES BYTES, NOT HASHES, AND THAT IS DELIBERATE. The refs referee already proves pin == filehash of
10// the mirror, so the mirror IS the pinned bytes. Re-fetching and byte-comparing against the mirror therefore
11// answers the drift question exactly, with no second hash implementation to drift from the first. One ruler.
12//
13// IT IS BOUNDED BY CONSTRUCTION AND SAYS SO. The operator's standing law is that hammering the estate is a
14// defect in its own right, so this organ takes ONE refs file and a MAXIMUM number of rows per run, both from
15// argv, and it PRINTS the bound beside the result. A run that stops at its cap declares checked and total, so
16// a partial pass can never read as a clean sweep -- the self-ceiling defect this estate names as law L011.
17//
18// nx_refdrift check <refsfile> [max] -> per-row MATCH / DRIFTED / UNREACHABLE, plus a summing partition
19// nx_refdrift selftest -> teeth, exit 0 GREEN / 1 RED
20// Exit: 0 no drift found | 1 DRIFTED rows exist | 2 usage | 3 UNREADABLE refs file. verdict= is LAST.
21// license_tier: ORIGINAL. Forks the sovereign fetcher, writes one reused temp mirror. No hw writes (Rule 26).
22import "nx_syscalls.nx"
23import "nx_tool_run.nx"
24import "nx_rowparse_lib.nx"
25import "nx_mirrorintegrity_lib.nx"
26
27const RD_EXIT_OK: i64 = 0
28const RD_EXIT_DRIFT: i64 = 1
29const RD_EXIT_USAGE: i64 = 2
30const RD_EXIT_UNREAD: i64 = 3
31const RD_SPAN: i64 = 8
32const RD_OUT: i64 = 262144
33const RD_REFS_CAP: i64 = 1048576
34const RD_BODY_CAP: i64 = 8388608
35const RD_FETCH_OUT: i64 = 65536
36const RD_PATH: i64 = 4096
37const RD_SEEK_END: i64 = 2
38// DEFAULT ROWS PER RUN. Derived, not picked: a refs file averages a dozen rows and each check is one network
39// fetch, so a full small file fits in one pass while a large one is covered across runs. Override with argv.
40const RD_MAX_DEFAULT: i64 = 12
41const RD_COL_KEY: i64 = 1
42const RD_COL_URL: i64 = 3
43const RD_COL_MIRROR: i64 = 4
44const RD_ARGV_SLOTS: i64 = 4
45const RD_PROBE: *u8 = "knowledge/fetched/refdrift_probe.tmp"
46const RD_FETCHER: *u8 = "nx_research_fetch.elf"
47const RD_PROBE_NAME: *u8 = "refdrift_probe.tmp"
48const RD_PROBE_B: *u8 = "knowledge/fetched/refdrift_probe_b.tmp"
49const RD_PROBE_B_NAME: *u8 = "refdrift_probe_b.tmp"
50
51// whole-file read, sized from the file so there is no cap to guess and no short read to miss
52func rd_slurp(path: *u8, buf: *u8, cap: i64) -> i64 {
53 let fd: i64 = sys_openat_rd(path)
54 if fd < 0 { return 0 - 1 }
55 let sz: i64 = sys_lseek(fd, 0, RD_SEEK_END)
56 if sz < 0 { sys_close(fd); return 0 - 1 }
57 if sz > cap { sys_close(fd); return 0 - 2 }
58 sys_lseek(fd, 0, 0)
59 let n: i64 = sys_read(fd, buf, sz)
60 sys_close(fd)
61 return n
62}
63// 1 if the two byte ranges are identical
64
65// ---- RECITE (2026-09-05): consume the refs gate's MOVED worklist ----
66// `MOVED <dom>.refs <key> <mirror> <canonical>` rows (space-separated, written by nx_compare_refs_gate). For each one:
67// fetch the CANONICAL url into the probe and classify it; refuse a body the completeness classifier calls truncated or
68// suspect (the mirror is untouched); dry-run prints WOULD-RECITE; apply fetches again under the mirror's OWN name so the
69// fetcher journals fresh provenance for that mirror, hashes it with the ONE hasher, and rewrites the row's url, pin and
70// accessed columns in place (temp + rename). Every row prints its own verdict and the run is bounded like check.
71const RD_SPACE: i64 = 32
72const RD_WL_COL_DOM: i64 = 1
73const RD_WL_COL_KEY: i64 = 2
74const RD_WL_COL_MIRROR: i64 = 3
75const RD_WL_COL_CANON: i64 = 4
76const RD_COL_PIN: i64 = 5
77const RD_COL_ACCESSED: i64 = 6
78const RD_REFS_DIR: *u8 = "buildroot/knowledge/compare/"
79const RD_HASHER: *u8 = "nx_filehash.elf"
80const RD_SHA_TAG: *u8 = "sha256"
81const RD_JSON_QCQ: i64 = 3
82const RD_HEXLEN: i64 = 64
83const RD_TMP_SUFFIX: *u8 = ".recite.tmp"
84const RD_WL_TAG: *u8 = "MOVED"
85// optional argv `key=<k>`: only that worklist row is tried (the others are counted as skipped_by_filter), so an apply
86// can be selective -- a canonical that lands on a HOMEPAGE re-cites a specific claim to a landing page and needs a read first
87const RD_KEYARG: *u8 = "key="
88// civil date from epoch seconds (Hinnant's civil_from_days) for the accessed column; every constant is the algorithm's own
89const RD_SECS_PER_DAY: i64 = 86400
90const RD_DAYS_EPOCH_TO_ERA0: i64 = 719468
91const RD_DAYS_PER_ERA: i64 = 146097
92const RD_ERA_YEARS: i64 = 400
93const RD_DOE_4Y: i64 = 1460
94const RD_DOE_100Y: i64 = 36524
95const RD_DOE_ERA_LAST: i64 = 146096
96const RD_DAYS_PER_YEAR: i64 = 365
97const RD_LEAP_4: i64 = 4
98const RD_LEAP_100: i64 = 100
99const RD_MP_SCALE: i64 = 5
100const RD_MP_OFF: i64 = 2
101const RD_MP_DIV: i64 = 153
102const RD_MP_MARCH: i64 = 3
103const RD_MP_WRAP: i64 = 9
104const RD_MP_JAN: i64 = 10
105const RD_TWO_DIGIT: i64 = 10
106func rd_put2(out: *u8, o: i64, v: i64) -> i64 {
107 var p: i64 = o
108 if v < RD_TWO_DIGIT { out[p] = 48 as u8; p = p + 1 }
109 return rp_putn(out, p, v)
110}
111func rd_ymd(epoch: i64, out: *u8) -> i64 {
112 let z: i64 = epoch / RD_SECS_PER_DAY + RD_DAYS_EPOCH_TO_ERA0
113 let era: i64 = z / RD_DAYS_PER_ERA
114 let doe: i64 = z - era * RD_DAYS_PER_ERA
115 let yoe: i64 = (doe - doe / RD_DOE_4Y + doe / RD_DOE_100Y - doe / RD_DOE_ERA_LAST) / RD_DAYS_PER_YEAR
116 var y: i64 = yoe + era * RD_ERA_YEARS
117 let doy: i64 = doe - (RD_DAYS_PER_YEAR * yoe + yoe / RD_LEAP_4 - yoe / RD_LEAP_100)
118 let mp: i64 = (RD_MP_SCALE * doy + RD_MP_OFF) / RD_MP_DIV
119 let d: i64 = doy - (RD_MP_DIV * mp + RD_MP_OFF) / RD_MP_SCALE + 1
120 var m: i64 = mp + RD_MP_MARCH
121 if mp >= RD_MP_JAN { m = mp - RD_MP_WRAP }
122 if m <= RD_MP_OFF { y = y + 1 }
123 var o: i64 = rp_putn(out, 0, y)
124 out[o] = 45 as u8
125 o = rd_put2(out, o + 1, m)
126 out[o] = 45 as u8
127 o = rd_put2(out, o + 1, d)
128 out[o] = 0 as u8
129 return o
130}
131func rd_basename(p: *u8) -> *u8 {
132 var i: i64 = 0
133 var last: i64 = 0
134 while p[i] != (0 as u8) { if p[i] == (47 as u8) { last = i + 1 } i = i + 1 }
135 return ((p as i64) + last) as *u8
136}
137// sha256 hex of a file via the ONE hasher, forked: 1 ok (out = 64 hex + NUL), 0 when it failed or printed no digest
138func rd_sha(path: *u8, out: *u8, fo: *u8, folen: *i64, av: *i64) -> i64 {
139 av[0] = RD_HASHER as i64
140 av[1] = path as i64
141 av[2] = 0
142 let rc: i64 = tr_run_capture(RD_HASHER, av, fo, RD_FETCH_OUT, folen)
143 if rc != 0 { return 0 }
144 let n: i64 = folen[0]
145 let tl: i64 = rp_slen(RD_SHA_TAG)
146 var i: i64 = 0
147 while i + tl + RD_JSON_QCQ + RD_HEXLEN <= n {
148 if rp_lit_eq(fo, i, tl, RD_SHA_TAG) == 1 {
149 let hs: i64 = i + tl + RD_JSON_QCQ
150 var k: i64 = 0
151 while k < RD_HEXLEN { out[k] = fo[hs + k]; k = k + 1 }
152 out[RD_HEXLEN] = 0 as u8
153 return 1
154 }
155 i = i + 1
156 }
157 return 0
158}
159// rewrite ONE refs row (col 1 == key): url -> newurl, pin -> h<sha>, accessed -> ymd, every other column verbatim by
160// walking the pipes (no dependence on a column parser's last-field rule). returns rows rewritten (0 = key absent), -1 io.
161// temp + rename, so a crash mid-write leaves the register whole.
162func rd_recite_row(refs: *u8, key: *u8, newurl: *u8, sha: *u8, ymd: *u8, rb: *u8, ob: *u8, c: *i64) -> i64 {
163 let rn: i64 = rd_slurp(refs, rb, RD_REFS_CAP)
164 if rn <= 0 { return 0 - 1 }
165 var o: i64 = 0
166 var hit: i64 = 0
167 var i: i64 = 0
168 while i < rn {
169 let e: i64 = rp_le(rb, i, rn)
170 var copied: i64 = 0
171 if e > i { if rb[i] == (114 as u8) {
172 if rp_col_pipe(rb, i, e, RD_COL_KEY, c) == 1 {
173 if rp_lit_eq(rb, c[0], c[1], key) == 1 {
174 var f: i64 = 0
175 var p: i64 = i
176 var fs: i64 = i
177 while p <= e {
178 var atend: i64 = 0
179 if p == e { atend = 1 } else { if rb[p] == (124 as u8) { atend = 1 } }
180 if atend == 1 {
181 if f > 0 { ob[o] = 124 as u8; o = o + 1 }
182 if f == RD_COL_URL { o = rp_put(ob, o, newurl) } else {
183 if f == RD_COL_PIN { ob[o] = 104 as u8; o = o + 1; o = rp_put(ob, o, sha) } else {
184 if f == RD_COL_ACCESSED { o = rp_put(ob, o, ymd) } else { o = rp_putspan(ob, o, rb, fs, p - fs) }
185 }
186 }
187 f = f + 1
188 fs = p + 1
189 }
190 p = p + 1
191 }
192 ob[o] = 10 as u8
193 o = o + 1
194 hit = hit + 1
195 copied = 1
196 }
197 }
198 } }
199 if copied == 0 { o = rp_putspan(ob, o, rb, i, e - i); ob[o] = 10 as u8; o = o + 1 }
200 i = e + 1
201 }
202 if hit == 0 { return 0 }
203 let tp: *u8 = sys_mmap(RD_PATH)
204 var tpo: i64 = rp_put(tp, 0, refs)
205 tpo = rp_put(tp, tpo, RD_TMP_SUFFIX)
206 tp[tpo] = 0 as u8
207 let fd: i64 = sys_openat_wr(tp, MODE_0644)
208 if fd < 0 { return 0 - 1 }
209 let w: i64 = sys_write(fd, ob, o)
210 sys_close(fd)
211 if w != o { return 0 - 1 }
212 if sys_renameat(tp, refs) < 0 { return 0 - 1 }
213 return hit
214}
215// RD_SAME -- THE FOUR-STATE DRIFT CLASSIFIER, given its contracted name 2026-09-06.
216// WHY THIS EXISTS AS A FUNCTION AT ALL: /compare/deepresearch published a row claiming exceed=1 on symbol rd_same in
217// THIS organ, and nx_domain_admit reported it UNGROUNDED. The capability was real and correct -- it simply ran inline
218// in main and its contracted entry point had never been written. A grep for the symbol name found `func rd_same` in
219// exactly one file estate-wide and it was nx_rebuild_drain.nx, an unrelated organ sharing the rd_ prefix, so a
220// name-only verification would have CONFIRMED the false claim. VERIFY A SYMBOL IN THE ORGAN THAT NAMES IT.
221//
222// IT DOES NOT RE-IMPLEMENT THE BYTE COMPARE. rp_same (nx_rowparse_lib) is and remains the ONE byte comparator; a
223// second one here would be the duplicate-ruler defect. What was missing was a NAME for the four-state decision that
224// wraps it, which is the thing the board actually contracted.
225// MATCH the mirror equals what the url serves now
226// DRIFTED the mirror and the url disagree, and the url agrees with ITSELF across two fetches
227// DYNAMIC the two fetches disagree with EACH OTHER, so the page varies per request and NO byte compare can
228// judge it -- never clean and never drifted. Folding this into DRIFTED would ship a false-positive
229// generator, which this estate ranks as worse than no detector at all.
230// UNREACHABLE nothing readable came back, which is not a statement about drift in either direction
231// PURE AND EXTRACTED WITHOUT WIDENING: the caller still performs both fetches and both slurps under exactly the
232// guards it used before, so this is a behaviour-preserving extraction and not a change of contract.
233const RD_V_MATCH: i64 = 0
234const RD_V_DRIFTED: i64 = 1
235const RD_V_UNREACHABLE: i64 = 2
236const RD_V_DYNAMIC: i64 = 3
237
238func rd_same(mb: *u8, mn: i64, pb: *u8, pn: i64, qb: *u8, qn: i64) -> i64 {
239 if pn <= 0 { return RD_V_UNREACHABLE }
240 if qn <= 0 { return RD_V_UNREACHABLE }
241 if rp_same(pb, pn, qb, qn) == 0 { return RD_V_DYNAMIC }
242 if rp_same(mb, mn, pb, pn) == 1 { return RD_V_MATCH }
243 return RD_V_DRIFTED
244}
245
246func main(argc: i64, argv: **u8) -> i64 {
247 var mode: i64 = 0 - 1
248 if argc > 1 {
249 let v: *u8 = argv[1] as *u8
250 if rp_slen(v) == 5 { if v[0] == (99 as u8) { mode = 0 } }
251 if rp_slen(v) == 8 { if v[0] == (115 as u8) { mode = 1 } }
252 if rp_slen(v) == 6 { if v[0] == (114 as u8) { mode = 2 } }
253 }
254 if mode < 0 {
255 sys_write(2, "usage: nx_refdrift {check <refsfile> [max] | selftest}\n" as *u8, 54)
256 sys_exit(RD_EXIT_USAGE)
257 return RD_EXIT_USAGE
258 }
259 let out: *u8 = sys_mmap(RD_OUT)
260 var o: i64 = 0
261 if mode == 1 {
262 var pass: i64 = 0
263 var tot: i64 = 0
264 let fx: *u8 = sys_mmap(4096)
265 var fn: i64 = 0
266 fn = rp_put(fx, fn, "ref|kk|Some citation prose|https://example.invalid/x|knowledge/fetched/m.html|habc|2026-09-04|vendor-doc|A row label\n" as *u8)
267 let c: *i64 = sys_mmap(RD_SPAN * 2) as *i64
268 let e: i64 = rp_le(fx, 0, fn)
269 // the 9-field pipe schema must yield key, url and mirror at their declared columns, or every later
270 // verdict would be about the wrong string
271 tot = tot + 1
272 if rp_col_pipe(fx, 0, e, RD_COL_KEY, c) == 1 { if c[1] == 2 { pass = pass + 1 } }
273 tot = tot + 1
274 if rp_col_pipe(fx, 0, e, RD_COL_URL, c) == 1 { if fx[c[0]] == (104 as u8) { pass = pass + 1 } }
275 tot = tot + 1
276 if rp_col_pipe(fx, 0, e, RD_COL_MIRROR, c) == 1 { if fx[c[0]] == (107 as u8) { pass = pass + 1 } }
277 // THE COMPARATOR, both directions. A byte compare that answered "same" for everything would report a
278 // permanently clean fleet, which is the guard-that-refuses-nothing failure.
279 let a1: *u8 = sys_mmap(64)
280 let b1: *u8 = sys_mmap(64)
281 a1[0] = 65 as u8
282 a1[1] = 66 as u8
283 b1[0] = 65 as u8
284 b1[1] = 66 as u8
285 tot = tot + 1
286 if rp_same(a1, 2, b1, 2) == 1 { pass = pass + 1 }
287 b1[1] = 67 as u8
288 tot = tot + 1
289 if rp_same(a1, 2, b1, 2) == 0 { pass = pass + 1 }
290 // neg-control: a LENGTH difference alone must read as drift. A comparator that only checked the
291 // overlapping prefix would call a truncated re-fetch identical, which is the exact silent case.
292 tot = tot + 1
293 if rp_same(a1, 2, b1, 1) == 0 { pass = pass + 1 }
294 // fixture-reached-the-condition: the row really parsed, so the schema teeth are not passing on empties
295 tot = tot + 1
296 if e > 40 { pass = pass + 1 }
297 o = rp_put(out, o, "NX-REFDRIFT-SELFTEST passed " as *u8)
298 o = rp_putn(out, o, pass)
299 o = rp_put(out, o, "/" as *u8)
300 o = rp_putn(out, o, tot)
301 if pass == tot { o = rp_put(out, o, " verdict=GREEN\n" as *u8) } else { o = rp_put(out, o, " verdict=RED\n" as *u8) }
302 sys_write(1, out, o)
303 if pass == tot { sys_exit(RD_EXIT_OK); return RD_EXIT_OK }
304 sys_exit(RD_EXIT_DRIFT)
305 return RD_EXIT_DRIFT
306 }
307 if mode == 2 {
308 if argc < 3 {
309 let u2: *u8 = "usage: nx_refdrift recite <moved-worklist> [max] [apply]\n" as *u8
310 sys_write(2, u2, rp_slen(u2))
311 sys_exit(RD_EXIT_USAGE)
312 return RD_EXIT_USAGE
313 }
314 let wl: *u8 = argv[2] as *u8
315 var rmax: i64 = RD_MAX_DEFAULT
316 var apply: i64 = 0
317 var keyf: *u8 = 0 as *u8
318 var skipped: i64 = 0
319 let kal: i64 = rp_slen(RD_KEYARG)
320 var ai: i64 = 3
321 while ai < argc {
322 let s2: *u8 = argv[ai] as *u8
323 if s2[0] == (97 as u8) { apply = 1 } else {
324 var iskey: i64 = 0
325 if rp_slen(s2) > kal { if rp_lit_eq(s2, 0, kal, RD_KEYARG) == 1 { keyf = ((s2 as i64) + kal) as *u8; iskey = 1 } }
326 if iskey == 0 {
327 let m2: i64 = rp_num(s2, 0, rp_slen(s2))
328 if m2 > 0 { rmax = m2 }
329 }
330 }
331 ai = ai + 1
332 }
333 let wb: *u8 = sys_mmap(RD_REFS_CAP)
334 let wn: i64 = rd_slurp(wl, wb, RD_REFS_CAP)
335 if wn <= 0 {
336 let u3: *u8 = "NX-REFDRIFT-RECITE UNREADABLE: the worklist did not read -- nothing is recited from nothing\n" as *u8
337 sys_write(2, u3, rp_slen(u3))
338 sys_exit(RD_EXIT_UNREAD)
339 return RD_EXIT_UNREAD
340 }
341 let c: *i64 = sys_mmap(RD_SPAN * 2) as *i64
342 let dom: *u8 = sys_mmap(RD_PATH)
343 let key: *u8 = sys_mmap(RD_PATH)
344 let mir: *u8 = sys_mmap(RD_PATH)
345 let canon: *u8 = sys_mmap(RD_PATH)
346 let refs: *u8 = sys_mmap(RD_PATH)
347 let sha: *u8 = sys_mmap(RD_PATH)
348 let ymd: *u8 = sys_mmap(RD_PATH)
349 let fo: *u8 = sys_mmap(RD_FETCH_OUT)
350 let folen: *i64 = sys_mmap(RD_SPAN) as *i64
351 let av: *i64 = sys_mmap(RD_SPAN * RD_ARGV_SLOTS) as *i64
352 let rb: *u8 = sys_mmap(RD_REFS_CAP)
353 let ob: *u8 = sys_mmap(RD_REFS_CAP)
354 let hb: *u8 = sys_mmap(MI_HEAD)
355 let tb: *u8 = sys_mmap(MI_TAIL)
356 let rcode: *i64 = sys_mmap(RD_SPAN) as *i64
357 let szo: *i64 = sys_mmap(RD_SPAN) as *i64
358 let decl: *i64 = sys_mmap(RD_SPAN) as *i64
359 let ts: *i64 = sys_mmap(RD_SPAN * 2) as *i64
360 sys_clock_gettime_real(ts)
361 rd_ymd(ts[0], ymd)
362 var total: i64 = 0
363 var tried: i64 = 0
364 var recited: i64 = 0
365 var would: i64 = 0
366 var refused: i64 = 0
367 var ffail: i64 = 0
368 var absent: i64 = 0
369 var ioerr: i64 = 0
370 let tagl: i64 = rp_slen(RD_WL_TAG)
371 var i: i64 = 0
372 while i < wn {
373 let e: i64 = rp_le(wb, i, wn)
374 if e > i + tagl { if rp_lit_eq(wb, i, tagl, RD_WL_TAG) == 1 {
375 total = total + 1
376 if tried < rmax {
377 var ok: i64 = 1
378 if rp_col(wb, i, e, RD_WL_COL_DOM, RD_SPACE, c) == 1 { rp_cstr(dom, wb, c[0], c[1]) } else { ok = 0 }
379 if rp_col(wb, i, e, RD_WL_COL_KEY, RD_SPACE, c) == 1 { rp_cstr(key, wb, c[0], c[1]) } else { ok = 0 }
380 if rp_col(wb, i, e, RD_WL_COL_MIRROR, RD_SPACE, c) == 1 { rp_cstr(mir, wb, c[0], c[1]) } else { ok = 0 }
381 if rp_col(wb, i, e, RD_WL_COL_CANON, RD_SPACE, c) == 1 { rp_cstr(canon, wb, c[0], c[1]) } else { ok = 0 }
382 if ok == 1 { if (keyf as i64) != 0 { if rp_lit_eq(key, 0, rp_slen(key), keyf) == 0 { ok = 0; skipped = skipped + 1 } } }
383 if ok == 1 {
384 tried = tried + 1
385 var ro: i64 = rp_put(refs, 0, RD_REFS_DIR)
386 ro = rp_put(refs, ro, dom)
387 refs[ro] = 0 as u8
388 av[0] = RD_FETCHER as i64
389 av[1] = canon as i64
390 av[2] = RD_PROBE_NAME as i64
391 av[3] = 0
392 let rc: i64 = tr_run_capture(RD_FETCHER, av, fo, RD_FETCH_OUT, folen)
393 if rc != 0 {
394 ffail = ffail + 1
395 o = rp_put(out, o, "FETCH-FAILED key=" as *u8); o = rp_put(out, o, key); o = rp_put(out, o, " canonical=" as *u8); o = rp_put(out, o, canon); o = rp_put(out, o, " rc=" as *u8); o = rp_putn(out, o, rc); o = rp_put(out, o, "\n" as *u8)
396 } else {
397 let cls: i64 = mi_classify(RD_PROBE, hb, tb, rcode, szo, decl)
398 var bad: i64 = 0
399 if cls == MI_PROVEN { bad = 1 }
400 if cls == MI_SUSPECT { bad = 1 }
401 if bad == 1 {
402 refused = refused + 1
403 o = rp_put(out, o, "REFUSED-BODY key=" as *u8); o = rp_put(out, o, key); o = rp_put(out, o, " class=" as *u8); o = rp_putn(out, o, cls); o = rp_put(out, o, " bytes=" as *u8); o = rp_putn(out, o, szo[0]); o = rp_put(out, o, " canonical=" as *u8); o = rp_put(out, o, canon); o = rp_put(out, o, " <== the canonical fetched short or suspect; the row is NOT re-cited and the mirror is untouched\n" as *u8)
404 } else {
405 if apply == 0 {
406 would = would + 1
407 o = rp_put(out, o, "WOULD-RECITE key=" as *u8); o = rp_put(out, o, key); o = rp_put(out, o, " refs=" as *u8); o = rp_put(out, o, refs); o = rp_put(out, o, " canonical=" as *u8); o = rp_put(out, o, canon); o = rp_put(out, o, " bytes=" as *u8); o = rp_putn(out, o, szo[0]); o = rp_put(out, o, " class=" as *u8); o = rp_putn(out, o, cls); o = rp_put(out, o, "\n" as *u8)
408 } else {
409 av[0] = RD_FETCHER as i64
410 av[1] = canon as i64
411 av[2] = rd_basename(mir) as i64
412 av[3] = 0
413 let rc2: i64 = tr_run_capture(RD_FETCHER, av, fo, RD_FETCH_OUT, folen)
414 if rc2 != 0 {
415 ffail = ffail + 1
416 o = rp_put(out, o, "FETCH-FAILED key=" as *u8); o = rp_put(out, o, key); o = rp_put(out, o, " canonical=" as *u8); o = rp_put(out, o, canon); o = rp_put(out, o, " rc=" as *u8); o = rp_putn(out, o, rc2); o = rp_put(out, o, " <== on the APPLY fetch under the mirror name\n" as *u8)
417 } else {
418 if rd_sha(mir, sha, fo, folen, av) == 0 {
419 ioerr = ioerr + 1
420 o = rp_put(out, o, "HASH-FAILED key=" as *u8); o = rp_put(out, o, key); o = rp_put(out, o, " mirror=" as *u8); o = rp_put(out, o, mir); o = rp_put(out, o, "\n" as *u8)
421 } else {
422 let rw: i64 = rd_recite_row(refs, key, canon, sha, ymd, rb, ob, c)
423 if rw > 0 {
424 recited = recited + 1
425 o = rp_put(out, o, "RECITED key=" as *u8); o = rp_put(out, o, key); o = rp_put(out, o, " refs=" as *u8); o = rp_put(out, o, refs); o = rp_put(out, o, " url=" as *u8); o = rp_put(out, o, canon); o = rp_put(out, o, " pin=h" as *u8); o = rp_put(out, o, sha); o = rp_put(out, o, " accessed=" as *u8); o = rp_put(out, o, ymd); o = rp_put(out, o, "\n" as *u8)
426 }
427 if rw == 0 {
428 absent = absent + 1
429 o = rp_put(out, o, "ROW-ABSENT key=" as *u8); o = rp_put(out, o, key); o = rp_put(out, o, " refs=" as *u8); o = rp_put(out, o, refs); o = rp_put(out, o, " <== the worklist names a key this register no longer carries; the mirror WAS re-fetched under the canonical url\n" as *u8)
430 }
431 if rw < 0 {
432 ioerr = ioerr + 1
433 o = rp_put(out, o, "IO-ERROR key=" as *u8); o = rp_put(out, o, key); o = rp_put(out, o, " refs=" as *u8); o = rp_put(out, o, refs); o = rp_put(out, o, "\n" as *u8)
434 }
435 }
436 }
437 }
438 }
439 }
440 }
441 }
442 } }
443 // append each row's verdict as it is decided: a run interrupted at row 20 keeps 20 rows, not none
444 if o > 0 { sys_write(1, out, o); o = 0 }
445 i = e + 1
446 }
447 o = rp_put(out, o, "ENVELOPE moved_total=" as *u8); o = rp_putn(out, o, total)
448 o = rp_put(out, o, " tried=" as *u8); o = rp_putn(out, o, tried)
449 o = rp_put(out, o, " skipped_by_filter=" as *u8); o = rp_putn(out, o, skipped)
450 o = rp_put(out, o, " recited=" as *u8); o = rp_putn(out, o, recited)
451 o = rp_put(out, o, " would_recite=" as *u8); o = rp_putn(out, o, would)
452 o = rp_put(out, o, " refused_body=" as *u8); o = rp_putn(out, o, refused)
453 o = rp_put(out, o, " fetch_failed=" as *u8); o = rp_putn(out, o, ffail)
454 o = rp_put(out, o, " row_absent=" as *u8); o = rp_putn(out, o, absent)
455 o = rp_put(out, o, " io_err=" as *u8); o = rp_putn(out, o, ioerr)
456 o = rp_put(out, o, " sum=" as *u8); o = rp_putn(out, o, recited + would + refused + ffail + absent + ioerr)
457 o = rp_put(out, o, " max_per_run=" as *u8); o = rp_putn(out, o, rmax)
458 o = rp_put(out, o, " apply=" as *u8); o = rp_putn(out, o, apply)
459 o = rp_put(out, o, " accessed=" as *u8); o = rp_put(out, o, ymd)
460 if tried + skipped < total { o = rp_put(out, o, " PARTIAL=1 <== A PREFIX OF THE WORKLIST, NOT A SWEEP: raise max or run again" as *u8) } else { o = rp_put(out, o, " PARTIAL=0" as *u8) }
461 o = rp_put(out, o, "\n" as *u8)
462 // the verdict names what HAPPENED, never the mode: an apply that recited nothing is not RECITED (measured on the
463 // first live batch -- a refused body with recited=0 printed RECITED and read as success)
464 var bad2: i64 = ffail + ioerr
465 if bad2 > 0 { o = rp_put(out, o, "NX-REFDRIFT-RECITE verdict=FAILURES\n" as *u8) } else {
466 if apply == 0 { o = rp_put(out, o, "NX-REFDRIFT-RECITE verdict=DRY\n" as *u8) } else {
467 if recited == 0 { bad2 = 1; o = rp_put(out, o, "NX-REFDRIFT-RECITE verdict=NOTHING-RECITED\n" as *u8) } else {
468 if refused > 0 { o = rp_put(out, o, "NX-REFDRIFT-RECITE verdict=RECITED-WITH-REFUSALS\n" as *u8) } else { o = rp_put(out, o, "NX-REFDRIFT-RECITE verdict=RECITED\n" as *u8) }
469 }
470 }
471 }
472 sys_write(1, out, o)
473 if bad2 > 0 { sys_exit(RD_EXIT_DRIFT); return RD_EXIT_DRIFT }
474 sys_exit(RD_EXIT_OK)
475 return RD_EXIT_OK
476 }
477 if argc < 3 {
478 sys_write(2, "usage: nx_refdrift check <refsfile> [max]\n" as *u8, 41)
479 sys_exit(RD_EXIT_USAGE)
480 return RD_EXIT_USAGE
481 }
482 let refs: *u8 = argv[2] as *u8
483 var maxrows: i64 = RD_MAX_DEFAULT
484 if argc > 3 {
485 var m: i64 = 0
486 let s: *u8 = argv[3] as *u8
487 var i0: i64 = 0
488 let l0: i64 = rp_slen(s)
489 while i0 < l0 {
490 let ch: i64 = s[i0] as i64
491 if ch < 48 { i0 = l0 } else { if ch > 57 { i0 = l0 } else { m = m * 10 + (ch - 48); i0 = i0 + 1 } }
492 }
493 if m > 0 { maxrows = m }
494 }
495 let rb: *u8 = sys_mmap(RD_REFS_CAP)
496 let rn: i64 = rd_slurp(refs, rb, RD_REFS_CAP)
497 if rn <= 0 {
498 sys_write(2, "NX-REFDRIFT UNREADABLE: the refs file did not read -- no drift verdict is published from nothing\n" as *u8, 95)
499 sys_exit(RD_EXIT_UNREAD)
500 return RD_EXIT_UNREAD
501 }
502 let c: *i64 = sys_mmap(RD_SPAN * 2) as *i64
503 let url: *u8 = sys_mmap(RD_PATH)
504 let mir: *u8 = sys_mmap(RD_PATH)
505 let key: *u8 = sys_mmap(RD_PATH)
506 let mb: *u8 = sys_mmap(RD_BODY_CAP)
507 let pb: *u8 = sys_mmap(RD_BODY_CAP)
508 let qb: *u8 = sys_mmap(RD_BODY_CAP)
509 let fo: *u8 = sys_mmap(RD_FETCH_OUT)
510 let folen: *i64 = sys_mmap(RD_SPAN) as *i64
511 let av: *i64 = sys_mmap(RD_SPAN * RD_ARGV_SLOTS) as *i64
512 var total: i64 = 0
513 var checked: i64 = 0
514 var match_n: i64 = 0
515 var drift: i64 = 0
516 var unreach: i64 = 0
517 var dynamic: i64 = 0
518 var i: i64 = 0
519 while i < rn {
520 let e: i64 = rp_le(rb, i, rn)
521 if e > i { if rb[i] == (114 as u8) {
522 if rp_col_pipe(rb, i, e, 0, c) == 1 { if c[1] == 3 {
523 total = total + 1
524 if checked < maxrows {
525 var ok: i64 = 0
526 if rp_col_pipe(rb, i, e, RD_COL_KEY, c) == 1 { rp_cstr(key, rb, c[0], c[1]); ok = 1 }
527 if ok == 1 { if rp_col_pipe(rb, i, e, RD_COL_URL, c) == 1 { rp_cstr(url, rb, c[0], c[1]) } else { ok = 0 } }
528 if ok == 1 { if rp_col_pipe(rb, i, e, RD_COL_MIRROR, c) == 1 { rp_cstr(mir, rb, c[0], c[1]) } else { ok = 0 } }
529 if ok == 1 {
530 let mn: i64 = rd_slurp(mir, mb, RD_BODY_CAP)
531 if mn <= 0 { ok = 0 }
532 if ok == 1 {
533 checked = checked + 1
534 av[0] = RD_FETCHER as i64
535 av[1] = url as i64
536 av[2] = RD_PROBE_NAME as i64
537 av[3] = 0
538 let rc: i64 = tr_run_capture(RD_FETCHER, av, fo, RD_FETCH_OUT, folen)
539 // FETCH TWICE. A page that varies against ITSELF cannot be judged by a byte
540 // compare at all, and calling that DRIFTED would be a false-positive generator
541 // -- worse than no detector, because the fleet would learn to ignore it.
542 // MEASURED 2026-09-04 on the very first live run: one url returned THREE
543 // DIFFERENT HASHES ACROSS THREE FETCHES AT AN IDENTICAL 106703 BYTES, so a size
544 // check calls it stable and a hash check calls it drifted and BOTH ARE WRONG.
545 // The second fetch is the discriminator and it costs one request.
546 av[2] = RD_PROBE_B_NAME as i64
547 let rc2: i64 = tr_run_capture(RD_FETCHER, av, fo, RD_FETCH_OUT, folen)
548 av[2] = RD_PROBE_NAME as i64
549 var verdict: i64 = RD_V_UNREACHABLE
550 if rc == 0 { if rc2 == 0 {
551 let pn: i64 = rd_slurp(RD_PROBE, pb, RD_BODY_CAP)
552 let qn: i64 = rd_slurp(RD_PROBE_B, qb, RD_BODY_CAP)
553 verdict = rd_same(mb, mn, pb, pn, qb, qn)
554 } }
555 if verdict == 0 { match_n = match_n + 1; o = rp_put(out, o, "MATCH key=" as *u8) }
556 if verdict == 1 { drift = drift + 1; o = rp_put(out, o, "DRIFTED key=" as *u8) }
557 if verdict == 2 { unreach = unreach + 1; o = rp_put(out, o, "UNREACHABLE key=" as *u8) }
558 if verdict == 3 { dynamic = dynamic + 1; o = rp_put(out, o, "DYNAMIC key=" as *u8) }
559 o = rp_put(out, o, key)
560 o = rp_put(out, o, " mirror_bytes=" as *u8)
561 o = rp_putn(out, o, mn)
562 o = rp_put(out, o, " url=" as *u8)
563 o = rp_put(out, o, url)
564 if verdict == 1 { o = rp_put(out, o, " <== THE SOURCE HAS MOVED SINCE IT WAS PINNED: the mirror and its pin still agree, so every pin check stays green while the citation now points at different bytes. Re-fetch, re-pin, and re-read the claim it grounds" as *u8) }
565 if verdict == 2 { o = rp_put(out, o, " <== NOT A DRIFT VERDICT: the fetch did not complete, so this row is UNJUDGED rather than clean" as *u8) }
566 if verdict == 3 { o = rp_put(out, o, " <== NOT A DRIFT VERDICT EITHER: two consecutive fetches of this url disagree with EACH OTHER, so the page varies per request and a byte compare cannot judge it. This is UNJUDGEABLE, never clean and never drifted; pin a stable artifact or cite a versioned URL if this reference must be checkable" as *u8) }
567 o = rp_put(out, o, "\n" as *u8)
568 }
569 }
570 }
571 } }
572 } }
573 i = e + 1
574 }
575 o = rp_put(out, o, "ENVELOPE refs_total=" as *u8)
576 o = rp_putn(out, o, total)
577 o = rp_put(out, o, " checked=" as *u8)
578 o = rp_putn(out, o, checked)
579 o = rp_put(out, o, " match=" as *u8)
580 o = rp_putn(out, o, match_n)
581 o = rp_put(out, o, " drifted=" as *u8)
582 o = rp_putn(out, o, drift)
583 o = rp_put(out, o, " unreachable=" as *u8)
584 o = rp_putn(out, o, unreach)
585 o = rp_put(out, o, " dynamic=" as *u8)
586 o = rp_putn(out, o, dynamic)
587 o = rp_put(out, o, " sum=" as *u8)
588 o = rp_putn(out, o, match_n + drift + unreach + dynamic)
589 o = rp_put(out, o, " max_per_run=" as *u8)
590 o = rp_putn(out, o, maxrows)
591 if checked < total {
592 o = rp_put(out, o, " PARTIAL=1 <== THIS RUN IS A PREFIX OF THE FILE, NOT A SWEEP: raise max or run again to cover the rest, and do NOT read this as a clean bill for the unchecked rows" as *u8)
593 } else { o = rp_put(out, o, " PARTIAL=0" as *u8) }
594 o = rp_put(out, o, "\n" as *u8)
595 if drift > 0 { o = rp_put(out, o, "NX-REFDRIFT verdict=DRIFTED\n" as *u8) } else { o = rp_put(out, o, "NX-REFDRIFT verdict=GREEN\n" as *u8) }
596 sys_write(1, out, o)
597 if drift > 0 { sys_exit(RD_EXIT_DRIFT); return RD_EXIT_DRIFT }
598 sys_exit(RD_EXIT_OK)
599 return RD_EXIT_OK
600}