nx_clock_driver_subject_ar.nx source
↩ module page · 248 lines · 22668 B
1// nx_clock_tickless.nx -- the TICKLESS driver (the sched_tickless.raw lesson: don't burn a constant tick when
2// idle). From ONE spark it runs a BOUNDED number of beats, but between beats it SLEEPS exactly until the next due
3// job (the minimum next_due) instead of waking every tick -- so a registry with sparse jobs costs only as many
4// wakeups as there are due events, not one-per-tick. Bounded (TLN_MAXBEATS) so a single spark can never run away.
5// Reduces the external trigger from per-beat to per-WINDOW. Reuses the gated nx_clock library (load/dispatch/save).
6// nx_clock_tickless [registry] [tickfile] (run the elf directly to pass args; defaults = the live registry)
7// license_tier: ORIGINAL expect_exit: 0
8import "nx_clock_driver_sched_ar.nx"
9import "nx_syscalls.nx"
10const TLN_MAGIC_1000000: i64 = 1000000
11
12const TLN_MAXBEATS: i64 = 30 // beats per window; the NAS supervisor respawns after each window (respawns stay well under the crash-loop guard)
13const TLN_WINDOW_SECS: i64 = 1800 // 2026-08-04: a window is now bounded by REAL seconds, not by a beat
14 // count whose duration depended on how long the children took. ~30min
15 // keeps the old window cadence (30 beats x ~60s) and the life budget.
16const TLN_MAXDISPATCH: i64 = 240 // hard per-window dispatch ceiling: a saturated registry can never turn
17 // one window into an unbounded run (the EDF loop exits on whichever of
18 // budget/ceiling comes first, and the supervisor respawns fresh).
19const TLN_TICK_MS: i64 = 1000 // 1s per logical tick (server cadence; a sitecheck at interval 30 = a probe every ~30s)
20const TLN_MAXWINDOWS: i64 = 120 // windows per LIFE (2026-07-05 leak arc): the GC-free substrate leaks address
21 // space per window forever (measured 1.81TB VmSize on a 21-day life = the
22 // Committed_AS flood); a clean exit after ~120 windows (>=1h life) lets the
23 // supervisor respawn fresh = supervisor-as-GC. Safe BY DESIGN for this daemon:
24 // hc_guard_one passes rwin=0 (tickless respawn is expected, never crash-loop),
25 // and each life is HOURS (the 2026-06 flap was 0ms hot-exits on an empty
26 // registry -- that idle-sleep fix below is kept; state persists via clk_save).
27
28func w(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
29func wn(v: i64) -> i64 { var m: i64=v; if m<0{w("-" as *u8);m=0-m} let t:*u8=sys_mmap(24); 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} var i:i64=0; let o:*u8=sys_mmap(24); while i<k{o[i]=t[k-1-i];i=i+1} sys_write(1,o,k); return 0 }
30func cat(dst: *u8, o: i64, s: *u8) -> i64 { var x: i64=o; var i: i64=0; while s[i]!=(0 as u8){dst[x]=s[i];x=x+1;i=i+1} return x }
31func catn(dst: *u8, o: i64, v: i64) -> i64 { var x: i64=o; var m: i64=v; if m<0{dst[x]=45 as u8;x=x+1;m=0-m} if m==0{dst[x]=48 as u8;return x+1} let t:*u8=sys_mmap(24); var k:i64=0; while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} var j:i64=0; while j<k{dst[x]=t[k-1-j];x=x+1;j=j+1} return x }
32// SELF-heartbeat to the docroot (the clock's OWN write -- NO dispatched child). Decisive diagnostic vs clock_health.txt
33// (the dispatched sitecheck's write): heartbeat present + health absent => the clock writes fine, the NESTED DISPATCH fails.
34// THE DISPATCH COUNT WAS UNOBSERVABLE BY CONSTRUCTION (fixed 2026-08-01). hb() writes ONE line and
35// OVERWRITES, and in the main loop hb("window-end") is followed immediately by clk_save/clk_load/merge and
36// then hb("window-start") -- so the window-end beat, the ONLY place the honest dispatch count b is
37// published, survived for well under a second and could never be sampled. Measured: two 20s-interval
38// watches spanning ~30 minutes caught window-start twice and window-end ZERO times, while the tick
39// advanced normally (+870/+900 per window), proving windows were completing the whole time.
40// THE FIX: route the terminal beat to its OWN path so a later beat cannot clobber it. b is now readable
41// at any time. b==0 isolates a nested-execve failure (every child failing); b>0 with stale job outputs
42// isolates individual organs. Without this, "did the scheduler actually RUN anything" was unanswerable.
43func hbp(tag: *u8, a: i64, b: i64, c: i64, p: *u8) -> i64 { let now: i64=sys_now_realtime_sec(); let st:*u8=sys_mmap(256); var o:i64=0; o=cat(st,o,"CLOCKBEAT " as *u8); o=cat(st,o,tag); o=cat(st,o," a=" as *u8); o=catn(st,o,a); o=cat(st,o," b=" as *u8); o=catn(st,o,b); o=cat(st,o," c=" as *u8); o=catn(st,o,c); o=cat(st,o," t=" as *u8); o=catn(st,o,now); st[o]=10 as u8; o=o+1; st[o]=0 as u8; let fd:i64=sys_openat_wr(p,0x1a4); if fd>=0 { sys_write(fd,st,o); sys_close(fd) } return 0 }
44// EXTENDED WINDOW REPORT (2026-08-06). clk_run_edf ALREADY COMPUTES out[4]=max_lateness and
45// out[5]=exec_secs -- its own comment calls exec_secs "the number the old design silently threw away" --
46// and then hbp published only 3 of the 6 outputs, so the two numbers that diagnose CAPACITY were thrown
47// away AGAIN at the publishing boundary. The window report could say a beat was starved but never say WHY,
48// which is exactly why netobs read as a dead job for days while its row and its elf were both fine.
49// ★A METRIC COMPUTED AND NOT PUBLISHED IS THE SAME BLIND SPOT AS A METRIC NEVER COMPUTED.
50// ADDITIVE (rule 19): a= b= c= keep their exact meanings, so every existing reader of this line still works.
51func hbx(tag: *u8, a: i64, b: i64, c: i64, d: i64, e: i64, f: i64, g: i64, h: i64, nm: *u8, p: *u8) -> i64 {
52 let now: i64 = sys_now_realtime_sec(); let st: *u8 = sys_mmap(CLK_NAMEW + 256); var o: i64 = 0 // the slowest= field carries an ORGAN slot (+ <=243 fixed bytes); DERIVED from the slot
53 o=cat(st,o,"CLOCKBEAT " as *u8); o=cat(st,o,tag)
54 o=cat(st,o," a=" as *u8); o=catn(st,o,a)
55 o=cat(st,o," b=" as *u8); o=catn(st,o,b)
56 o=cat(st,o," c=" as *u8); o=catn(st,o,c)
57 o=cat(st,o," max_late=" as *u8); o=catn(st,o,d)
58 o=cat(st,o," exec=" as *u8); o=catn(st,o,e)
59 o=cat(st,o," jobs=" as *u8); o=catn(st,o,f)
60 o=cat(st,o," demand=" as *u8); o=catn(st,o,g)
61 o=cat(st,o," max_exec=" as *u8); o=catn(st,o,h)
62 o=cat(st,o," slowest=" as *u8); o=cat(st,o,nm)
63 o=cat(st,o," t=" as *u8); o=catn(st,o,now)
64 st[o]=10 as u8; o=o+1; st[o]=0 as u8
65 let fd: i64 = sys_openat_wr(p,0x1a4); if fd>=0 { sys_write(fd,st,o); sys_close(fd) }
66 return 0
67}
68func hb(tag: *u8, a: i64, b: i64, c: i64) -> i64 { return hbp(tag, a, b, c, "sites/nishifamily/clock_heartbeat.txt" as *u8) }
69func readnum(p: *u8) -> i64 { let lp: *i64 = sys_mmap(8) as *i64; let d: *u8 = sys_read_file(p, lp); if (d as i64)==0 { return 0 } var c: i64=0; var i: i64=0; while i<lp[0] { if d[i]>=(48 as u8) { if d[i]<=(57 as u8) { c=c*10+(d[i]-(48 as u8)) as i64 } } i=i+1 } return c }
70func savenum(p: *u8, v: i64) -> i64 { let buf: *u8 = sys_mmap(24); var o: i64=0; var m: i64=v; if m==0 { buf[0]=48 as u8; o=1 } else { let t: *u8=sys_mmap(24); var k: i64=0; while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} while o<k { buf[o]=t[k-1-o]; o=o+1 } } let fd: i64 = sys_openat_wr(p, 0x1a4); if fd>=0 { sys_write(fd, buf, o); sys_close(fd) } return 0 }
71
72// sleep exactly ms milliseconds (the same nanosleep idiom clk_run_tickless uses between beats; self-contained,
73// no dependency on a sys_sleep_ms wrapper) -- used to idle a full window when the registry is (transiently) empty.
74// FIRST-LINE-ONLY integer read. readnum() above parses EVERY digit anywhere in the file, which is
75// fine for a bare stamp but is a footgun for a CONFIG: a comment containing any number would silently
76// concatenate into the value, and this particular value controls how much work the scheduler does per
77// window. Stopping at the first newline lets the file carry its own documentation without changing
78// behaviour -- the same shape as nx_seat's st_reap_ttl, for the same reason.
79func readnum1(p: *u8) -> i64 {
80 let lp: *i64 = sys_mmap(8) as *i64
81 let d: *u8 = sys_read_file(p, lp)
82 if (d as i64)==0 { return 0 }
83 var c: i64=0
84 var i: i64=0
85 var go: i64=1
86 while i<lp[0] {
87 if go==1 {
88 if d[i]==(10 as u8) { go=0 } else { if d[i]>=(48 as u8) { if d[i]<=(57 as u8) { c=c*10+(d[i]-(48 as u8)) as i64 } } }
89 }
90 i=i+1
91 }
92 return c
93}
94func sleep_ms(ms: i64) -> i64 {
95 dfi_mark("witness.driver-sleep-enter" as *u8)
96 let ts: *i64 = sys_mmap(16) as *i64
97 ts[0] = ms / 1000
98 ts[1] = (ms - (ms/1000)*1000) * TLN_MAGIC_1000000
99 __syscall(35, ts as i64, 0, 0, 0, 0, 0)
100 dfi_mark("witness.driver-sleep-exit" as *u8)
101 return 0
102}
103
104// PERSISTENT DAEMON (was: one-shot-per-window that leaned on the supervisor's dead->respawn to fake continuity --
105// which collapsed to a 0ms hot-exit + respawn STORM whenever the registry loaded zero jobs = the live flap the
106// operator caught). Now main() is a real long-running process the supervisor's PID guard expects: each iteration
107// RELOADS the registry (so a job registered later is picked up with no restart), then either runs a tickless window
108// (jobs present) or idles ONE full window (empty/at-deploy). It NEVER exits on an empty registry -> the flap is gone
109// by construction, and the tickless loop still sleeps between beats so CPU stays ~0.
110func main(argc: i64, argv: *i64) -> i64 {
111 if dfi_preflight(argc,argv)!=1 { return DFI_REFUSED }
112 // STATE SSOT IS A SEG-STORE PLANE (2026-08-03, debts 1784828927+1784868625: planes, never tsv).
113 // `reg` is now ONLY the one-time legacy migration source: clk_load_state reads the plane first
114 // and falls back to the tsv exactly once (the very next save lands in the plane and the tsv is
115 // never written again -- its mtime freezing is the cutover proof).
116 var reg: *u8 = "clock_jobs.tsv" as *u8 // LEGACY (cwd-relative): migration source only
117 var tickf: *u8 = "clock_tick.txt" as *u8
118 let stpl: *u8 = "knowledge/store/clocksched-" as *u8 // the mutable schedule-state plane (clock-exclusive)
119 if argc >= 2 { reg = argv[1] as *u8 }
120 if argc >= 3 { tickf = argv[2] as *u8 }
121
122 let names: *u8 = sys_mmap(CLK_MAXJOBS*CLK_NAMEW); let orgs: *u8 = sys_mmap(CLK_MAXJOBS*CLK_NAMEW)
123 let iv: *i64 = sys_mmap(CLK_MAXJOBS*8) as *i64; let nd: *i64 = sys_mmap(CLK_MAXJOBS*8) as *i64
124 let np: *i64 = sys_mmap(8) as *i64
125 // 128 BYTES = 16 SLOTS (widened from 64 = 8 on 2026-08-14). clk_run_edf now also publishes out[8]
126 // (worst-starver job index) and out[9] (periods it missed); at 64 bytes those two writes would have
127 // run off the end of the mapping. Sized with headroom so the next axis added to the window report
128 // does not silently overrun this allocation the way out[8] would have.
129 let out: *i64 = sys_mmap(CLKRS_OUT_N*8) as *i64
130
131 var run: i64 = 1
132 var windows: i64 = 0
133 while run == 1 {
134 np[0] = 0
135 let lsrc: i64 = clk_load_state(stpl, reg, names, orgs, iv, nd, np)
136 if lsrc == 1 {
137 // persist IMMEDIATELY so the cutover completes in seconds -- otherwise the plane only
138 // materializes at first window-end (~28 min) and a crash in that window re-migrates
139 clk_save_plane(stpl, names, orgs, iv, nd, np[0])
140 w("nx_clock_tickless: MIGRATED legacy " as *u8); w(reg); w(" -> clocksched- plane (one-time; the tsv is never written again)\n" as *u8)
141 }
142 // WALL-CLOCK BASE (2026-08-04): new jobs must arm at now+interval in EPOCH seconds. Passing the
143 // legacy logical tick here would arm them in the past and fire a thundering herd on first sight.
144 let merged: i64 = clk_merge_store("knowledge/store/clockjobs-" as *u8, names, orgs, iv, nd, np, sys_now_realtime_sec())
145 // PERSIST A RECONCILE IMMEDIATELY (2026-08-06). clk_save_plane otherwise runs ONLY at window end,
146 // so a re-period declared in clockjobs- stayed invisible in clocksched- for up to a full 1800s window.
147 // MEASURED: I re-periodded worldgen-gate 120s -> 86400s with the new nx_clockjob writer, restarted to
148 // force the merge, read the plane, saw 120 -- and nearly concluded my own writer was broken. It was
149 // not: the change was live in memory and merely unsaved. An operator without source access has NO WAY
150 // to tell those apart. Adopt the returned count (a merge the caller does not adopt repeats itself).
151 // (STAR)A CHANGE APPLIED IN MEMORY BUT NOT PERSISTED IS INDISTINGUISHABLE FROM A CHANGE THAT WAS
152 // REJECTED -- AND THE READER WILL BLAME THE TOOL, NOT THE OBSERVATION.
153 if merged > 0 { np[0] = clk_save_plane(stpl, names, orgs, iv, nd, np[0]) } // off-tsv additive job-adds (CLOBBER-PROOF: clock is READ-ONLY on the plane; adds via nx_store_put)
154 // ONE-TIME, SELF-HEALING MIGRATION: any deadline still carrying a legacy logical tick is converted
155 // to a real instant (exact -- a tick can never be a valid epoch). Runs every window and is a no-op
156 // once converted, so a row restored from an old backup repairs itself instead of firing forever.
157 let mig: i64 = clk_edf_migrate(nd, iv, np[0], sys_now_realtime_sec())
158 if mig > 0 { w("nx_clock_tickless: MIGRATED " as *u8); wn(mig); w(" logical-tick deadlines -> wall-clock instants\n" as *u8) }
159 if np[0] == 0 {
160 hb("idle-no-jobs" as *u8, 0, 0, 0) // observable self-beat: clock alive, registry empty (heartbeat present + zero dispatch)
161 w("nx_clock_tickless: no jobs in " as *u8); w(reg); w(" -- idling one window (not exiting)\n" as *u8)
162 sleep_ms(TLN_MAXBEATS * TLN_TICK_MS) // idle a FULL window, then RELOAD -- never the 0ms hot-exit that caused the flap
163 } else {
164 let T0: i64 = sys_now_realtime_sec()
165 hb("window-start" as *u8, T0, np[0], 0) // a=start-epoch b=jobs -> proves the clock ITSELF runs + writes the docroot
166 // WALL-CLOCK EDF WINDOW (2026-08-04, debt 1785872141). REPLACES clk_run_tickless, whose logical
167 // tick advanced by SLEEP ONLY and therefore drifted behind real time by exactly the dispatch
168 // cost -- stretching every period (measured: a 6h job fired ONCE in 21h). Deadlines are now real
169 // instants and the clock is re-read after every child, so job runtime can no longer be lost.
170 // DISPATCH CEILING IS DATA-DRIVEN (2026-08-06, rule 11). MEASURED that day: a window ran
171 // a=240 b=9 exec=252s of 1800s -- 240 is EXACTLY TLN_MAXDISPATCH, so the binding constraint
172 // was a COMPILED CONSTANT while 86pct of the time budget went unused, against demand=268.
173 // The window's TIME budget is the real resource and already bounds a runaway (clk_run_edf
174 // exits on whichever of budget/ceiling comes first); the count ceiling was belt-and-braces
175 // that quietly became the limiter as the registry grew to 45 jobs.
176 // FAIL-SAFE: an absent/zero/unreadable conf keeps the compiled 240 EXACTLY as before, so a
177 // missing file can never silently change how much work the scheduler does.
178 var maxd: i64 = TLN_MAXDISPATCH
179 let mdcfg: i64 = readnum1("knowledge/status/clock_maxdispatch.conf" as *u8)
180 if mdcfg > 0 { maxd = mdcfg }
181 let window_rc: i64 = clk_run_edf_reserved(orgs, names, iv, nd, np[0], maxd, TLN_WINDOW_SECS, TLN_TICK_MS, out)
182 if out[CLKRS_OUT_ERRORS] > 0 {
183 w("nx_clock_tickless: RESERVED-ERRORS " as *u8); wn(out[CLKRS_OUT_ERRORS]); w("; inspect dispatcher diagnostics\n" as *u8)
184 }
185 if clk_reserved_halt_required(out) == 1 {
186 w("nx_clock_tickless: FATAL ownership uncertain job=" as *u8)
187 if out[CLKRS_OUT_LOST_INDEX] >= 0 { w(clk_slot(names,out[CLKRS_OUT_LOST_INDEX])) }
188 w(" pid=" as *u8); wn(out[CLKRS_OUT_LOST_PID]); w(" wait_result=" as *u8); wn(out[CLKRS_OUT_LOST_WAIT])
189 w(" known_owned_remaining=" as *u8); wn(out[CLKRS_OUT_KNOWN_OWNED]); w(" window_rc=" as *u8); wn(window_rc)
190 w("; parked without another window, state save, or automatic exit; reconciliation required before external restart\n" as *u8)
191 hb("fatal-ownership-uncertain" as *u8,out[CLKRS_OUT_LOST_PID],out[CLKRS_OUT_LOST_WAIT],sys_now_realtime_sec())
192 while run == 1 { sleep_ms(TLN_TICK_MS) }
193 return CLKRS_FATAL_RC
194 }
195 // NAME THE BINDING CONSTRAINT. Hitting the ceiling and running out of time look identical
196 // in every other number this organ prints, and telling them apart is the whole difference
197 // between "raise a constant" and "the box is too slow" -- it cost a full session to spot.
198 if out[0]-out[11] >= maxd { w("nx_clock_tickless: DISPATCH-CEILING BOUND -- foreground completed " as *u8); wn(out[0]-out[11]); w(" = the ceiling (" as *u8); wn(maxd); w("), exec " as *u8); wn(out[5]); w("s of " as *u8); wn(TLN_WINDOW_SECS); w("s. The COUNT limit bound this window, not time; raise knowledge/status/clock_maxdispatch.conf\n" as *u8) }
199 if out[11] > 0 { w("nx_clock_tickless: RESERVED-SERVICE " as *u8); wn(out[11]); w(" dispatch(es) beside foreground; counts include assisted jobs, exec_secs remains occupied dispatcher wall time\n" as *u8) }
200 let demand: i64 = clk_demand_per_window(iv, np[0], TLN_WINDOW_SECS)
201 // NAME THE HOG, DO NOT MAKE THE READER INFER IT. out[7] is the job index that owned the worst
202 // single dispatch; -1 means nothing was dispatched at all (which is itself the answer).
203 var slow: *u8 = "none" as *u8
204 if out[7] >= 0 { slow = clk_slot(orgs, out[7]) }
205 hbx("window-end" as *u8, out[0], out[3], out[2], out[4], out[5], np[0], demand, out[6], slow, "sites/nishifamily/clock_dispatch.txt" as *u8) // a=DISPATCHES b=STARVED c=epoch (unchanged) + max_late/exec/jobs/demand
206 // OVERSUBSCRIPTION IS A CAPACITY FACT, NOT A SCHEDULING BUG. When the window cannot complete what
207 // the registry demands, NO ordering saves anyone -- EDF just picks who loses. Say it LOUDLY and name
208 // the ratio, because the alternative is precisely what happened for days: a healthy registry row, a
209 // healthy promoted elf, a beat silently running ~5x slow, and a remediation that sent every reader
210 // off to re-verify the row and the elf -- the two things that were never wrong.
211 if demand > out[0] { w("nx_clock_tickless: OVERSUBSCRIBED demand=" as *u8); wn(demand); w(" dispatches/window vs completed=" as *u8); wn(out[0]); w(" (exec " as *u8); wn(out[5]); w("s of " as *u8); wn(TLN_WINDOW_SECS); w("s) -- EDF is choosing WHO starves, not WHETHER. Lengthen periods or raise capacity.\n" as *u8) }
212 // ADOPT THE MERGED COUNT (2026-07-31). clk_save now reload-merges externally-added rows and returns
213 // the NEW job count. Discarding that return re-appends the same row on every save: the row lands in
214 // the arrays but np[0] never learns of it, so the next save's clk_find misses it and appends a
215 // DUPLICATE. Measured immediately after shipping the merge -- srcguard appeared twice while all 30
216 // other jobs stayed unique, which is what named the cause. u2605A MERGE THAT THE CALLER DOES NOT ADOPT
217 // IS A MERGE THAT REPEATS ITSELF.
218 np[0] = clk_save_plane(stpl, names, orgs, iv, nd, np[0]); savenum(tickf, out[2]) // persist advanced deadlines + final EPOCH to the plane (resume across windows; the tsv stays frozen)
219 // HONEST WINDOW REPORT: starvation and lateness are PUBLISHED, not inferred. exec_secs is the
220 // number the old design threw away -- it is precisely the drift the logical tick used to absorb.
221 w("nx_clock_tickless: " as *u8); wn(out[0]); w(" dispatches, slept " as *u8); wn(out[1]); w("s, exec " as *u8); wn(out[5]); w("s, STARVED " as *u8); wn(out[3]); w(", max_late " as *u8); wn(out[4]); w("s, epoch=" as *u8); wn(out[2]); w("\n" as *u8)
222 // NAME THE STARVED JOB (2026-08-14). The line above has printed a bare STARVED count since it
223 // was written; a reader seeing "STARVED 3" had no way to learn WHICH jobs missed their period,
224 // which is the only fact that decides the remedy (lengthen THAT period vs raise capacity).
225 // Printed as a SEPARATE line on purpose: clock_dispatch.txt's CLOCKBEAT format is parsed by
226 // other readers, and widening a published record to answer a new question is how a format
227 // silently breaks its consumers. Only emitted when something actually starved, so a healthy
228 // window stays exactly as quiet as before.
229 if out[3] > 0 { w("nx_clock_tickless: WORST-STARVER " as *u8); w(clk_slot(orgs, out[8])); w(" missed " as *u8); wn(out[9]); w(" period(s) -- its declared interval is unschedulable against this registry; lengthen THAT period or raise capacity\n" as *u8) }
230 // STORM-DEFERRED (2026-09-02): out[10] = heavy beats clk_run_edf declined to fork because the shared
231 // I/O-storm ruler (nx_ioadmit_lib, the build gate's own witness) reported zero spawn budget. Each one
232 // was re-armed a fraction of its period ahead, so a quiet window prints nothing new -- the line only
233 // appears when the clock actually stood aside, which is the whole point of announcing it.
234 if out[10] > 0 { w("nx_clock_tickless: STORM-DEFERRED " as *u8); wn(out[10]); w(" heavy dispatch(es) re-armed (knowledge/status/clock_heavy.conf; the box was at its D-state storm line, the same conjunct /api/build refuses on)\n" as *u8) }
235 }
236 // LIFE BUDGET (2026-07-05 leak arc): bounded windows per life -> clean exit -> the supervisor
237 // respawns fresh (rwin=0 = by-design respawn, never counted as crash-loop). Address-space leak
238 // per life is now BOUNDED instead of 1.81TB-per-21-days; state already persisted every window.
239 windows = windows + 1
240 if windows >= dfi_windows() {
241 hb("life-recycle" as *u8, windows, 0, 0)
242 w("nx_clock_tickless: window budget reached -- clean exit (supervisor respawns fresh)\n" as *u8)
243 run = 0
244 }
245 }
246 return 0
247}
248