code wiki / _hdl_build / nx_research_cycle.nx
nx_research_cycle.nx source
↩ module page · 85 lines · 4871 B
1// nx_research_cycle.nx -- THE AUTONOMOUS SELF-IMPROVING CYCLE. One invocation runs the whole researcher loop in
2// order, each step a separate process via the sovereign runner: (1) nx_research_grow (index the next delta,
3// content-dedup, cross-topic flag), (2) nx_search_register (refresh the search-sources manifest = integration),
4// (3) nx_research_miner (re-rank rich veins), (4) nx_research_freshness (moving/static/constant review). This is
5// the schedulable unit: cron/pulse it on a cadence (e.g. monthly for freshness, or per-fetch for growth) and the
6// researcher compounds + integrates + prioritizes + self-refreshes with no human in the loop. Steps stay loosely
7// coupled (each is its own organ/process talking only through durable artifacts); this orchestrator just sequences
8// them. Records a cycle ledger. expect_exit: 0 license_tier: ORIGINAL
9import "nx_search_inverted_persist.nx" // brings syscalls (fork/execve/wait4/openat/dup3/write)
10import "nx_itoa_lib.nx" // shared MSB-first emitter (zero-alloc)
11
12func rc_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
13// MIGRATED to the shared emitter (debt 1785563586). The old body mmapped a scratch buffer
14// per call and never freed it. At PAGE granularity that is 4096B leaked PER CALL -- the
15// defect that took 28.5GB of a 36GB host in nx_ts_lumadiff (2MB input, ~3.66M calls).
16// nxi_* is MSB-first, allocates NOTHING, and emits identical bytes including the sign.
17func rc_num(v: i64) -> i64 { nxi_out(v); return 0 }
18func rc_cat(dst: *u8, off: i64, s: *u8) -> i64 { var i: i64=0; while s[i]!=(0 as u8){dst[off+i]=s[i];i=i+1} return off+i }
19
20// run one organ via the sovereign runner as a child process; child stdout -> /dev/null (each organ writes its
21// own durable artifacts). Returns the organ's exit code (signal death mapped non-zero per the sigfix law).
22func rc_run(organ: *u8) -> i64 {
23 let pid: i64 = sys_fork()
24 if pid == 0 {
25 let devnull: i64 = sys_openat_wr("/dev/null" as *u8, 0x1a4)
26 if devnull >= 0 { sys_dup3(devnull, 1, 0) }
27 let argv: *i64 = sys_mmap(32) as *i64
28 argv[0] = "_offc/nx_sov_build_run.elf" as *u8 as i64
29 argv[1] = organ as i64
30 argv[2] = 0
31 let envp: *i64 = sys_mmap(16) as *i64
32 envp[0] = "PATH=/usr/bin:/bin" as *u8 as i64
33 envp[1] = 0
34 sys_execve("_offc/nx_sov_build_run.elf" as *u8, argv, envp)
35 sys_exit(127)
36 }
37 let st: *i64 = sys_mmap(16) as *i64
38 sys_wait4(pid, st, 0)
39 if (st[0] & 0x7f) != 0 { return 128 + (st[0] & 0x7f) }
40 return (st[0] >> 8) & 0xff
41}
42
43func rc_step(name: *u8) -> i64 {
44 rc_puts(" step "); rc_puts(name); rc_puts(" ... " as *u8)
45 let e: i64 = rc_run(name)
46 rc_puts("exit="); rc_num(e)
47 if e == 0 { rc_puts(" OK\n" as *u8) } else { rc_puts(" FAIL\n" as *u8) }
48 return e
49}
50
51func main() -> i64 {
52 rc_puts("=== nx_research_cycle: autonomous self-improving researcher loop (one cadence run) ===\n" as *u8)
53 var fails: i64 = 0
54 // 1. GROW: index the next delta (dedup + cross-topic) -> new shard
55 if rc_step("nx_research_grow" as *u8) != 0 { fails = fails + 1 }
56 // 2. REGISTER: refresh the search-sources manifest (loose-coupled integration with the search engine)
57 if rc_step("nx_search_register" as *u8) != 0 { fails = fails + 1 }
58 // 3. MINE: re-rank rich veins to mine deeper
59 if rc_step("nx_research_miner" as *u8) != 0 { fails = fails + 1 }
60 // 4. SERVE: drain the builder's request queue; serve adequate topics, flag inadequate ones (feedback)
61 if rc_step("nx_research_serve" as *u8) != 0 { fails = fails + 1 }
62 // 5. GAPS: clean open-gaps digest = the actionable feedback signal to operator + Claude
63 if rc_step("nx_research_gaps" as *u8) != 0 { fails = fails + 1 }
64 // 6. FRESHNESS: moving/static/constant review (movers -> re-mine, constants -> back off)
65 if rc_step("nx_research_freshness" as *u8) != 0 { fails = fails + 1 }
66 // 7. GATE: re-verify every index invariant (self-checking cycle -- catches any regression this run introduced)
67 if rc_step("nx_research_gate" as *u8) != 0 { fails = fails + 1 }
68
69 // cycle ledger
70 let lfd: i64 = sys_openat_append("knowledge/index/research_cycle.log" as *u8, 0x1a4)
71 if lfd >= 0 {
72 let line: *u8 = sys_mmap(128); var lp: i64 = 0
73 lp = rc_cat(line, lp, "cycle steps=7 fails=" as *u8);
74 if fails == 0 { line[lp]=48 as u8; lp=lp+1 } else { line[lp]=(48+fails) as u8; lp=lp+1 }
75 line[lp]=10 as u8; lp=lp+1
76 sys_write(lfd, line, lp); sys_close(lfd)
77 }
78
79 rc_puts("=== cycle done: steps=7 fails="); rc_num(fails); rc_puts(" ===\n" as *u8)
80 if fails == 0 {
81 rc_puts(" CYCLE-OK (grew + integrated + mined + freshness-reviewed; schedule this on a cadence)\n" as *u8)
82 sys_exit(0); return 0
83 }
84 sys_exit(1); return 1
85}