code wiki / _hdl_build / nx_evidence_beat.nx
nx_evidence_beat.nx source
↩ module page · 410 lines · 24499 B
1// nx_evidence_beat.nx -- THE CADENCE. Closes the seq1433 half that turns this workstream from a one-shot
2// into an actual loop.
3//
4// ★WHY THIS IS THE KEYSTONE, NOT A CHORE. Everything built this session expires on purpose: evstamps carry
5// an epoch and are refused past the TTL, bite records likewise. That expiry is the whole point -- a verdict
6// that outlives its evidence is the defect this workstream opened by fixing. But expiry without RENEWAL is
7// just a slower way to reach zero: within one TTL every domain silently falls back to UNPROVEN and the
8// board returns to exactly the state it started in. A measurement you never repeat is a measurement you
9// will eventually be lying about.
10//
11// WHAT IT DOES, per invocation:
12// for each domain declaring executable evidence (knowledge/compare/<d>.gates)
13// * if its evstamp is missing or older than the REFRESH threshold -> re-run nx_swcompare_evidence <d>
14// * if any of its declared gates lacks a fresh bite record -> re-run nx_bite_sweep <d>
15//
16// ★REFRESH AT HALF THE TTL, not at expiry. Renewing only once a record has already died guarantees a window
17// in which the board reads UNPROVEN for domains that are fine -- the instrument would manufacture its own
18// false negatives on a timer. Half-life renewal means a single missed beat is survivable.
19//
20// ★BOUNDED WORK BY CONSTRUCTION. Each refresh forks real gates and, for a sweep, rebuilds source repeatedly;
21// an unbounded beat would run for hours and get killed mid-flight, leaving a mutated tree behind. maxwork
22// caps the number of refreshes per invocation and the beat reports what it DEFERRED rather than silently
23// truncating -- a cadence that hides its own backlog is how "green" drifts away from "current".
24//
25// usage: nx_evidence_beat [maxwork] [--dry] (CWD = nxc2 root)
26// exit 0 = nothing overdue, or all attempted work succeeded · 1 = a refresh failed · 2 = usage
27// license_tier: ORIGINAL
28import "nx_syscalls.nx"
29import "nx_artifact_root.nx"
30const EB_MAGIC_4096: i64 = 4096
31const EB_MAGIC_4095: i64 = 4095
32const EB_MAGIC_604800: i64 = 604800
33const EB_MAGIC_1024: i64 = 1024
34
35const EB_DEF_MAXWORK: i64 = 3
36
37func w(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
38func wn(v: i64) -> i64 { let t: *u8=sys_mmap(28); var m: i64=v; var k: i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} let b: *u8=sys_mmap(28); var i: i64=0; while i<k{b[i]=t[k-1-i];i=i+1} sys_write(1,b,k); return 0 }
39func wf(fd: i64, s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(fd,s,n); return 0 }
40func wnf(fd: i64, v: i64) -> i64 { let t: *u8=sys_mmap(28); var m: i64=v; var k: i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} let b: *u8=sys_mmap(28); var i: i64=0; while i<k{b[i]=t[k-1-i];i=i+1} sys_write(fd,b,k); return 0 }
41
42func eb_read(path: *u8, buf: *u8, cap: i64) -> i64 {
43 let fd: i64 = sys_openat_rd(path)
44 if fd < 0 { return 0 - 1 }
45 var tot: i64 = 0
46 var go: i64 = 1
47 while go == 1 {
48 let n: i64 = sys_read(fd, ((buf as i64)+tot) as *u8, cap - tot)
49 if n <= 0 { go = 0 } else { tot = tot + n; if tot >= cap { go = 0 } }
50 }
51 sys_close(fd)
52 return tot
53}
54func eb_num_after(buf: *u8, n: i64, key: *u8, kl: i64) -> i64 {
55 var i: i64 = 0
56 while i <= n - kl {
57 var j: i64 = 0
58 var m: i64 = 1
59 while j < kl { if buf[i+j] != key[j] { m = 0; j = kl } else { j = j + 1 } }
60 if m == 1 {
61 var p: i64 = i + kl
62 var v: i64 = 0
63 var got: i64 = 0
64 while p < n { let c: i64 = buf[p] as i64; if c >= 48 { if c <= 57 { v = v*10 + (c-48); got = 1; p = p + 1 } else { p = n } } else { p = n } }
65 if got == 1 { return v }
66 return 0 - 1
67 }
68 i = i + 1
69 }
70 return 0 - 1
71}
72func eb_cat(dst: *u8, off: i64, s: *u8) -> i64 {
73 var o: i64 = off
74 var i: i64 = 0
75 while s[i] != (0 as u8) { dst[o] = s[i]; o = o + 1; i = i + 1 }
76 return o
77}
78func eb_catn(dst: *u8, off: i64, domain: *u8, dl: i64) -> i64 {
79 var o: i64 = off
80 var i: i64 = 0
81 while i < dl { dst[o] = domain[i]; o = o + 1; i = i + 1 }
82 return o
83}
84
85// A .gates file holds one line per declared gate. The read cap is DERIVED from the buffer size and
86// never authored a second time -- a cap written as its own literal beside the buffer it guards is
87// the same constant spelled twice, and the two drift.
88const EB_GATES_BYTES: i64 = 65536
89const EB_GATES_CAP: i64 = EB_GATES_BYTES - 1
90const EB_VERDICT_BYTES: i64 = 1024
91const EB_VERDICT_CAP: i64 = EB_VERDICT_BYTES - 1
92
93// ---- EVIDENCE-NEWER-THAN-STAMP: the general repair (2026-08-15) ----
94// A stamp FREEZES redseen at the moment it is written, but its INPUT -- the bite records under
95// knowledge/status/bite_<gate>.verdict -- is written by a DIFFERENT producer at a DIFFERENT time.
96// When a bite lands after the stamp, the stamp reports fewer proven gates than the evidence on disk
97// already supports, and nothing corrects it until the half-life refresh up to ttl/2 later.
98// MEASURED 2026-08-15 over all 42 domains (coverage_complete=1): 26 sat at redseen=0 while the
99// estate held 109 killed=1 records, and finance alone moved 0 -> 16 on a single re-stamp with no
100// gate re-run differently and no source changed.
101// This trigger is deliberately GENERAL: it fires for bite records written by ANY producer, not only
102// by the sweep this beat runs itself, so a hand-run nx_gate_bite is repaired on the next pass too.
103// It is SELF-LIMITING -- re-stamping makes the stamp epoch newer than every bite, so the condition
104// clears until new evidence actually arrives, and a domain with no bites never triggers it at all.
105// A STAMP THAT PREDATES ITS OWN EVIDENCE UNDERSTATES THE SYSTEM AND READS EXACTLY LIKE VACUITY.
106func eb_evidence_newer(dom: *u8, stamp_ep: i64) -> i64 {
107 var dl: i64 = 0
108 while dom[dl] != (0 as u8) { dl = dl + 1 }
109 let gp: *u8 = sys_mmap(512)
110 var o: i64 = eb_cat(gp, 0, "knowledge/compare/" as *u8)
111 o = eb_catn(gp, o, dom, dl)
112 o = eb_cat(gp, o, ".gates" as *u8)
113 gp[o] = 0 as u8
114 let gb: *u8 = sys_mmap(EB_GATES_BYTES)
115 let gn: i64 = eb_read(gp, gb, EB_GATES_CAP)
116 if gn <= 0 { return 0 }
117 let vp: *u8 = sys_mmap(512)
118 let vb: *u8 = sys_mmap(EB_VERDICT_BYTES)
119 var found: i64 = 0
120 var i: i64 = 0
121 while i < gn {
122 // The line end is found with a SEPARATE flag, never by writing a sentinel into the cursor --
123 // a loop that exits by clobbering its own index cannot then report where it stopped.
124 var e: i64 = i
125 var eol: i64 = 0
126 while eol == 0 {
127 if e >= gn { eol = 1 } else {
128 if gb[e] == (10 as u8) { eol = 1 } else { e = e + 1 }
129 }
130 }
131 if gb[i] != (35 as u8) {
132 var bar: i64 = 0 - 1
133 var scan: i64 = i
134 while scan < e {
135 if bar < 0 { if gb[scan] == (124 as u8) { bar = scan } }
136 scan = scan + 1
137 }
138 if bar > i {
139 var s: i64 = i
140 var k: i64 = i
141 while k < bar { if gb[k] == (47 as u8) { s = k + 1 } k = k + 1 }
142 var en: i64 = bar
143 if en - s > 4 { if gb[en-4] == (46 as u8) { en = en - 4 } }
144 if en > s {
145 var vo: i64 = eb_cat(vp, 0, "knowledge/status/bite_" as *u8)
146 var c: i64 = s
147 while c < en { vp[vo] = gb[c]; vo = vo + 1; c = c + 1 }
148 vo = eb_cat(vp, vo, ".verdict" as *u8)
149 vp[vo] = 0 as u8
150 let vn: i64 = eb_read(vp, vb, EB_VERDICT_CAP)
151 if vn > 0 {
152 let bep: i64 = eb_num_after(vb, vn, "epoch=" as *u8, 6)
153 if bep > stamp_ep { found = 1 }
154 }
155 }
156 }
157 }
158 i = e + 1
159 }
160 return found
161}
162
163// fork <elf> <arg1> [arg2]; return exit code
164func eb_run2(elf: *u8, a1: *u8, a2: *u8, outpath: *u8) -> i64 {
165 let pid: i64 = sys_fork()
166 if pid == 0 {
167 // MODE_0644, not 0x1a4. The 39-site consolidation swept the DECIMAL spelling (420) and this
168 // hex twin survived it -- the same constant in two bases is two constants to every scanner.
169 let ofd: i64 = sys_openat_wr(outpath, MODE_0644)
170 if ofd >= 0 { sys_dup3(ofd, 1, 0); sys_dup3(ofd, 2, 0) }
171 let argv: *i64 = sys_mmap(48) as *i64
172 argv[0] = elf as i64
173 argv[1] = a1 as i64
174 if (a2 as i64) == 0 { argv[2] = 0 } else { argv[2] = a2 as i64; argv[3] = 0 }
175 let envp: *i64 = sys_mmap(16) as *i64
176 envp[0] = 0
177 sys_execve(elf, argv, envp)
178 sys_exit(127)
179 }
180 let stp: *i64 = sys_mmap(16) as *i64
181 sys_wait4(pid, stp, 0)
182 let sig: i64 = stp[0] & 0x7f
183 if sig != 0 { return 128 + sig }
184 return (stp[0] >> 8) & 0xff
185}
186
187func main(argc: i64, argv: *i64) -> i64 {
188 // Resolution order is argv > conf > compiled default (rule 17). 0 means "nobody has said yet", so a
189 // conf value can still outrank the compiled floor -- initialising straight to the default would let
190 // the code silently beat the config file that exists to hold precisely this number.
191 var maxwork: i64 = 0
192 var argv_maxwork: i64 = 0
193 var dry: i64 = 0
194 if argc > 1 {
195 let a: *u8 = argv[1] as *u8
196 if a[0] == (45 as u8) { dry = 1 } else {
197 maxwork = 0
198 var i: i64 = 0
199 while a[i] != (0 as u8) { maxwork = maxwork*10 + ((a[i] as i64) - 48); i = i + 1 }
200 if maxwork <= 0 { maxwork = EB_DEF_MAXWORK }
201 argv_maxwork = 1
202 }
203 }
204 if argc > 2 { let b: *u8 = argv[2] as *u8; if b[0] == (45 as u8) { dry = 1 } }
205
206 let now: i64 = sys_now_realtime_sec()
207 // ONE policy, read from the same file every other consumer reads (rule 17).
208 let pb: *u8 = sys_mmap(EB_MAGIC_4096)
209 let pn: i64 = eb_read("knowledge/evidence_policy.conf" as *u8, pb, EB_MAGIC_4095)
210 var ttl: i64 = EB_MAGIC_604800
211 if pn > 0 { let v: i64 = eb_num_after(pb, pn, "ttl_sec=" as *u8, 8); if v > 0 { ttl = v } }
212 // THE BUDGET COMES FROM THE SAME POLICY FILE AS THE TTL IT IS DERIVED FROM. It was a compiled
213 // constant of 3 while refresh demand was 44 domains / 14 passes per half-life = 3.15 per pass, so
214 // the beat could not keep up with its own scan even before sweeps: MEASURED 2026-08-15 as
215 // refreshed=3 swept=0 deferred=23, nine domains aged 6.3 days, and smallos/nishios never stamped
216 // because they sort last and the budget was always gone before the scan reached them.
217 // A BUDGET SET BELOW ITS STEADY-STATE DEMAND DOES NOT SLOW A QUEUE DOWN, IT GUARANTEES IT GROWS --
218 // and it reports a tidy GREEN while doing so, because every pass really did complete its budget.
219 if argv_maxwork == 0 { if pn > 0 { let mw: i64 = eb_num_after(pb, pn, "beat_maxwork=" as *u8, 13); if mw > 0 { maxwork = mw } } }
220 if maxwork <= 0 { maxwork = EB_DEF_MAXWORK }
221 let refresh: i64 = ttl / 2
222
223 w("=== nx_evidence_beat -- renew what is about to expire (half-life refresh) ===\n")
224 w(" ttl="); wn(ttl); w("s refresh_at="); wn(refresh); w("s maxwork="); wn(maxwork)
225 if dry == 1 { w(" MODE=dry-run") }
226 w("\n")
227
228 let evelf: *u8 = sys_mmap(512)
229 let swelf: *u8 = sys_mmap(512)
230 let haveev: i64 = ar_resolve("_offc/nx_swcompare_evidence.elf" as *u8, evelf)
231 let havesw: i64 = ar_resolve("_offc/nx_bite_sweep.elf" as *u8, swelf)
232 if haveev == 0 { w(" CANNOT RESOLVE nx_swcompare_evidence.elf -- promote it first\n"); sys_exit(2); return 2 }
233
234 let dbuf: *u8 = sys_mmap(1 << 16)
235 let fd: i64 = sys_openat_rd("knowledge/compare\x00" as *u8)
236 if fd < 0 { w(" cannot open knowledge/compare\n"); sys_exit(2); return 2 }
237 let outp: *u8 = "knowledge/status/evidence_beat_run.out\x00" as *u8
238 let dom: *u8 = sys_mmap(256)
239 let path: *u8 = sys_mmap(512)
240 var scanned: i64 = 0
241 var refreshed: i64 = 0
242 var swept: i64 = 0
243 var restamped: i64 = 0
244 var deferred: i64 = 0
245 var failed: i64 = 0
246 var work: i64 = 0
247
248 var go: i64 = 1
249 while go == 1 {
250 let nr: i64 = sys_getdents64(fd, dbuf, 1 << 16)
251 if nr <= 0 { go = 0 } else {
252 var pos: i64 = 0
253 while pos < nr {
254 let rec: *u8 = ((dbuf as i64) + pos) as *u8
255 let reclen: i64 = dirent_reclen(rec)
256 let name: *u8 = ((rec as i64) + 19) as *u8
257 var ln: i64 = 0
258 while name[ln] != (0 as u8) { ln = ln + 1 }
259 // only domains that DECLARE executable evidence: <d>.gates
260 var isg: i64 = 0
261 if ln > 6 {
262 let g: *u8 = ".gates\x00" as *u8
263 var m: i64 = 1
264 var q: i64 = 0
265 while q < 6 { if name[ln-6+q] != g[q] { m = 0; q = 6 } else { q = q + 1 } }
266 isg = m
267 }
268 if isg == 1 {
269 let dl: i64 = ln - 6
270 var c: i64 = 0
271 while c < dl { dom[c] = name[c]; c = c + 1 }
272 dom[dl] = 0 as u8
273 scanned = scanned + 1
274 // age of this domain's evstamp
275 var o: i64 = eb_cat(path, 0, "knowledge/status/evstamp_" as *u8)
276 o = eb_catn(path, o, dom, dl)
277 o = eb_cat(path, o, ".verdict" as *u8)
278 path[o] = 0 as u8
279 let sb: *u8 = sys_mmap(EB_MAGIC_1024)
280 let sn: i64 = eb_read(path, sb, 1023)
281 var age: i64 = ttl + 1
282 var stamp_ep: i64 = 0
283 if sn > 0 { let ep: i64 = eb_num_after(sb, sn, "epoch=" as *u8, 6); if ep > 0 { stamp_ep = ep; if now >= ep { age = now - ep } } }
284 // TWO INDEPENDENT REASONS TO RENEW, AND THEY MUST NOT SHARE A MESSAGE: the stamp is
285 // near expiry (TIME), or the evidence underneath it has moved since it was written
286 // (CONTENT). Only the first existed before 2026-08-15, which is why 26 of 42 domains
287 // published a redseen lower than their own bite records already supported. The content
288 // test is asked ONLY when the time test did not fire, so an overdue domain costs no
289 // extra reads and a fresh one costs a handful of small reads and no gate runs.
290 var evnew: i64 = 0
291 if age <= refresh { if stamp_ep > 0 { evnew = eb_evidence_newer(dom, stamp_ep) } }
292 var due: i64 = 0
293 if age > refresh { due = 1 } else { if evnew == 1 { due = 1 } }
294 if due == 1 {
295 // ★THE DRY RUN MUST SPEND THE SAME BUDGET. The first cut incremented the work
296 // counter only on the real path, so --dry listed EVERY overdue domain as if it
297 // would all be done in one pass -- a preview that disagrees with the run it is
298 // previewing is worse than no preview, because it is trusted.
299 if work >= maxwork {
300 deferred = deferred + 1
301 w(" DEFER "); w(dom); w(" age="); wn(age); w("s (budget spent)\n")
302 } else {
303 work = work + 1
304 if evnew == 1 { w(" REFRESH "); w(dom); w(" EVIDENCE-NEWER-THAN-STAMP -> ") } else { w(" REFRESH "); w(dom); w(" age="); wn(age); w("s -> ") }
305 if dry == 1 { w("(dry)\n") } else {
306 let rc: i64 = eb_run2(evelf, dom, 0 as *u8, outp)
307 if rc == 0 { w("MEASURED-HONEST\n") } else { w("RED (exit "); wn(rc); w(")\n"); failed = failed + 1 }
308 refreshed = refreshed + 1
309 // NON-VACUITY RENEWAL: re-read the stamp we just wrote. If fewer gates have
310 // a live bite record than the domain declares, its non-vacuity has aged out
311 // and the sweep must run -- otherwise the beat renews the cheap half of the
312 // evidence and quietly lets the expensive half expire.
313 if havesw == 1 {
314 let s2: *u8 = sys_mmap(EB_MAGIC_1024)
315 let n2: i64 = eb_read(path, s2, 1023)
316 if n2 > 0 {
317 let rs: i64 = eb_num_after(s2, n2, "redseen=" as *u8, 8)
318 let dc: i64 = eb_num_after(s2, n2, "declared=" as *u8, 9)
319 if dc > 0 { if rs < dc {
320 // A SWEEP WHOSE RESULT IS NEVER STAMPED IS WORK PAID FOR AND
321 // THROWN AWAY. The re-stamp is not a separate task -- it is the
322 // second half of this one, so the budget reserves BOTH or the
323 // pass declines to start. Budget-checking the cheap half only
324 // AFTER spending the expensive half discards the sweep's result
325 // at exactly the moment the budget is tightest, which is the
326 // worst possible time to lose it.
327 if work + 2 <= maxwork {
328 work = work + 2
329 w(" SWEEP "); w(dom); w(" redseen="); wn(rs); w("/"); wn(dc); w(" -> ")
330 // 6 -> 16, MEASURED 2026-08-01, not guessed. nx_x25519_kat_gate
331 // returned INCONCLUSIVE at 4 sites and again at 6-equivalent
332 // depth; the KILL landed at site 4 of the NUMERIC-CONSTANT
333 // operator only once the cap allowed 14. Constant-time crypto
334 // exposes few mutable comparisons and its early numeric literals
335 // are structural (array sizes -> uncompilable), so the first
336 // handful of sites are systematically barren for exactly the
337 // KAT/ORACLE class this beat most needs to score.
338 // ★A SITE CAP IS A SAMPLING DECISION: TOO SMALL AND THE SWEEP
339 // MANUFACTURES "INCONCLUSIVE" AND CALLS IT A MEASUREMENT.
340 // Cost is bounded -- the sweep stops at the FIRST kill, so a
341 // gate that bites early still costs the same 1-2 rebuilds.
342 let rc2: i64 = eb_run2(swelf, dom, "16\x00" as *u8, outp)
343 if rc2 == 0 { w("all gates BITE\n") } else { w("not all proven (exit "); wn(rc2); w(")\n") }
344 swept = swept + 1
345 // THE STAMP IS WRITTEN BEFORE THE SWEEP THAT PRODUCES ITS OWN
346 // NON-VACUITY EVIDENCE. Without this re-stamp the sweep's
347 // result is invisible until the next half-life refresh 3.5
348 // days later, so the beat renews the CHEAP half of the
349 // evidence, generates the EXPENSIVE half, and then throws the
350 // expensive half away.
351 // MEASURED 2026-08-15 over all 42 domains: finance held 18
352 // killed=1 records and published redseen=0 because its stamp
353 // epoch was 100 SECONDS OLDER than the bites it should have
354 // counted; librarian (2s) and surveys (3s) show the identical
355 // ordering. A single re-stamp moved finance 0 -> 16 with no
356 // gate re-run differently and no source changed -- the proof
357 // was on disk the whole time and the stamp could not see it.
358 // A STAMP THAT PREDATES ITS OWN EVIDENCE UNDERSTATES THE
359 // SYSTEM'S HONESTY AND READS EXACTLY LIKE VACUOUS GATES.
360 let rc3: i64 = eb_run2(evelf, dom, 0 as *u8, outp)
361 if rc3 == 0 { w(" RESTAMP "); w(dom); w(" post-sweep -> MEASURED-HONEST\n") } else { w(" RESTAMP "); w(dom); w(" post-sweep RED (exit "); wn(rc3); w(")\n"); failed = failed + 1 }
362 restamped = restamped + 1
363 } else { deferred = deferred + 1; w(" DEFER "); w(dom); w(" sweep (budget spent)\n") }
364 } }
365 }
366 }
367 }
368 }
369 }
370 }
371 if reclen <= 0 { pos = nr } else { pos = pos + reclen }
372 }
373 }
374 }
375 sys_close(fd)
376
377 // swept WAS COUNTED AND NEVER PRINTED, so a pass that swept nothing and a pass that swept every
378 // overdue domain produced IDENTICAL summaries. The non-vacuity half of this beat's work was
379 // invisible in the beat's own log, which is why "scanned=43 refreshed=3 failed=0" read as the
380 // whole story when it was reporting only the cheap half. A COUNTER THAT IS TALLIED BUT NEVER
381 // EMITTED IS A MEASUREMENT THE ORGANISATION IS PAYING FOR AND NOT COLLECTING.
382 w(" scanned="); wn(scanned); w(" refreshed="); wn(refreshed); w(" swept="); wn(swept); w(" restamped="); wn(restamped); w(" deferred="); wn(deferred); w(" failed="); wn(failed); w("\n")
383 if havesw == 0 { w(" NOTE nx_bite_sweep.elf unresolved -- non-vacuity records will not be renewed by this beat\n") }
384
385 let lfd: i64 = sys_openat_wr("knowledge/status/evidence_beat.log\x00" as *u8, 0x1a4)
386 if lfd >= 0 {
387 wf(lfd, "NX-EVIDENCE-BEAT scanned=" as *u8); wnf(lfd, scanned)
388 wf(lfd, " refreshed=" as *u8); wnf(lfd, refreshed)
389 wf(lfd, " deferred=" as *u8); wnf(lfd, deferred)
390 wf(lfd, " failed=" as *u8); wnf(lfd, failed)
391 wf(lfd, " ttl=" as *u8); wnf(lfd, ttl)
392 // ts= is the DEAD-MAN'S-SWITCH marker knowledge/registry/cron_heartbeats.tsv looks for. Emitting
393 // only `epoch=` would leave the watch permanently stale even while the beat ran perfectly -- the
394 // heartbeat would report a dead cadence that is actually alive, which is the same false-negative
395 // class as every other reader/writer dialect mismatch this session. Both are written: ts= for the
396 // watch, epoch= for anything reading this log the way the stamps are read.
397 wf(lfd, " ts=" as *u8); wnf(lfd, now)
398 wf(lfd, " epoch=" as *u8); wnf(lfd, now)
399 wf(lfd, "\n" as *u8)
400 // DEFERRED WORK IS NOT A FAILURE, but it must be VISIBLE: a beat that silently drops its backlog
401 // lets the board age out one domain at a time while every log line still reads GREEN.
402 if failed == 0 { wf(lfd, "VERDICT=GREEN evidence renewed within its half-life\n" as *u8) } else { wf(lfd, "VERDICT=RED a refresh failed -- a domain's evidence could not be re-measured\n" as *u8) }
403 sys_close(lfd)
404 }
405
406 if failed == 0 { w("VERDICT: verdict=GREEN (nothing overdue, or all attempted refreshes succeeded)\n"); sys_exit(0); return 0 }
407 w("VERDICT: verdict=RED (a refresh failed)\n")
408 sys_exit(1)
409 return 1
410}