code wiki / _hdl_build / nx_conductor_tick.nx
nx_conductor_tick.nx source
↩ module page · 68 lines · 3786 B
1// nx_conductor_tick.nx -- the conductor's CADENCE TICK for the self-improving researcher loop. One tick: read the
2// last-fire time (knowledge/registry/conductor_tick, a sovereign epoch), and if the cadence is DUE (now - last >=
3// CADENCE_SEC, or never fired) fire nx_research_cycle THROUGH the conductor's governed path (cr_conductor_fire:
4// registered + RACI-owned + gate-green + never-brick), then record the fire time. If not due, it reports the time
5// remaining and does nothing. This is the cadence ENGINE; a durable supervisor (or the operator) invokes the tick
6// periodically -> the loop runs monthly, autonomously, governed. Nishi-native, no shell. expect_exit: 0 license_tier: ORIGINAL
7import "nx_conductor_registry.nx" // cr_conductor_fire + syscalls + sys_now_realtime_sec
8
9const TICK_STATE: *u8 = "knowledge/registry/conductor_tick"
10const CADENCE_SEC: i64 = 2592000 // ~30 days (monthly); data-driven -- tune for "or other cadence"
11
12func tk_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
13func tk_num(v: i64) -> i64 { let bb: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m;sys_write(1,"-" as *u8,1)} let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=48;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} var i: i64=0; while i<k{bb[i]=t[k-1-i];i=i+1} sys_write(1,bb,k); return 0 }
14
15// read the last-fire epoch from the state file (leading decimal); -1 if absent/empty
16func tk_read_last() -> i64 {
17 let box: *i64 = sys_mmap(16) as *i64
18 let buf: *u8 = sys_read_file(TICK_STATE, box)
19 if buf == 0 as *u8 { return 0 - 1 }
20 let n: i64 = box[0]
21 if n <= 0 { return 0 - 1 }
22 var v: i64 = 0; var any: i64 = 0; var i: i64 = 0; var stop: i64 = 0
23 while stop == 0 {
24 if i >= n { stop = 1 }
25 else { let c: i64 = buf[i] as i64; if c < 48 { stop = 1 } else { if c > 57 { stop = 1 } else { v = v*10 + (c-48); any = 1; i = i+1 } } }
26 }
27 if any == 0 { return 0 - 1 }
28 return v
29}
30
31func tk_write_last(epoch: i64) -> i64 {
32 let fd: i64 = sys_openat_wr(TICK_STATE, 0x1a4)
33 if fd < 0 { return 0 - 1 }
34 let bb: *u8 = sys_mmap(32); var m: i64 = epoch; var k: i64 = 0
35 if m == 0 { bb[0]=48 as u8; k=1 }
36 let t: *u8 = sys_mmap(32)
37 while m > 0 { t[k]=(48+(m%10)) as u8; m=m/10; k=k+1 }
38 let out: *u8 = sys_mmap(40); var o: i64 = 0
39 var z: i64 = k
40 while z > 0 { z = z - 1; out[o] = t[z]; o = o + 1 }
41 out[o] = 10 as u8; o = o + 1
42 sys_write(fd, out, o); sys_close(fd)
43 return 0
44}
45
46func main() -> i64 {
47 tk_puts("=== nx_conductor_tick: cadence tick for nx_research_cycle (monthly, governed) ===\n" as *u8)
48 let now: i64 = sys_now_realtime_sec()
49 let last: i64 = tk_read_last()
50 tk_puts(" now="); tk_num(now); tk_puts(" last_fire="); tk_num(last); tk_puts(" cadence_sec="); tk_num(CADENCE_SEC); tk_puts("\n" as *u8)
51
52 var due: i64 = 0
53 if last < 0 { due = 1 } else { if now - last >= CADENCE_SEC { due = 1 } }
54
55 if due == 1 {
56 tk_puts(" DUE -> firing nx_research_cycle through the conductor (cr_conductor_fire)\n" as *u8)
57 let r: i64 = cr_conductor_fire("nx_research_cycle" as *u8, "researcher" as *u8, 0, 0)
58 tk_puts(" conductor fire result=" as *u8); tk_num(r); tk_puts(" (>=0 fired exit code; -1 admission failed; -2 not registered)\n" as *u8)
59 tk_write_last(now)
60 tk_puts(" recorded fire time; next fire in ~" as *u8); tk_num(CADENCE_SEC); tk_puts(" sec\n" as *u8)
61 tk_puts(" TICK-FIRED\n" as *u8)
62 sys_exit(0); return 0
63 }
64 let remain: i64 = (last + CADENCE_SEC) - now
65 tk_puts(" NOT DUE -- next fire in "); tk_num(remain); tk_puts(" sec (cadence gate holds; the supervisor calls this tick again later)\n" as *u8)
66 tk_puts(" TICK-IDLE\n" as *u8)
67 sys_exit(0); return 0
68}