nx_conductor_live.nx source
↩ module page · 280 lines · 16601 B
1// nx_conductor_live.nx -- the Nishi CONDUCTOR, v3: the LIVE, WARDEN-GATED tick
2// that ticks the INVENTION ORGANS via the SOVEREIGN code path (NO .sh).
3//
4// v1 (nx_conductor.nx) was OBSERVE-ONLY (measure canaries + journal, no Warden,
5// no action). v2 was LIVE+Warden-gated but dispatched each gate by fork+exec'ing
6// a .sh WRAPPER via /bin/bash -- the LAST non-sovereign part. v3 REMOVES that:
7// the beat now runs the invention organs (AUTHOR + VERIFY-BY-PROOF) directly via
8// the gr_gate shape ported INTO the Conductor (cl_run/cl_gate): fork+exec the
9// PINNED known-good compiler -> as -> ld -> nx_run_timeout, exit-code = verdict.
10// No /bin/bash, no .sh anywhere on the dispatch path -- argv[0] is the known-good
11// ELF / as / ld, never a shell. (Operator cardinal: sovereign NishiLang only.)
12//
13// Each BEAT it (1) asks the WARDEN to authorize the additive verify/author-to-
14// memory action, then (2) ticks the two invention organs hang-safe (each stage,
15// including cc/as/ld, runs under a self-SIGALRM deadline so a looping build-
16// oracle or organ kills itself -- it cannot wedge the beat), and (3) journals the
17// verdict to the event bus -- on cadence, UNATTENDED. This flips the build->
18// verify->invent loop from "a human runs it" to "the crew ticks itself."
19//
20// The Warden GATES, it does not rubber-stamp: each beat we show it ALLOW the
21// safe (additive, read-only) verify/author-to-MEMORY tick AND DENY a forbidden
22// source overwrite -- proving the cardinal gate is live in the loop (#13
23// additive-only). The author organ EMITs to MEMORY only; an EMIT-to-SOURCE would
24// be a W_OVERWRITE_SRC -> DENIED. The exit code itself proves the deny fired on
25// every beat (warden_denies must == CL_BEATS).
26//
27// Composes nx_run_timeout (hang-safety + nx_rt_alarm) + nx_warden_lib (the
28// cardinal gate). Sovereign: raw syscalls, zero deps, ZERO shell. Bounded beats
29// (testable); the unbounded daemon is a config flip once this is trusted.
30// license_tier: ORIGINAL
31
32import "nx_run_timeout.nx"
33import "nx_warden_lib.nx"
34import "nx_win_ledger.nx" // ADDITIVE: post-verify win-ledger journaling (self-learning capture)
35import "nx_framed_append.nx" // WMS LIVE-1/LIVE-3: locked single-write framing (heartbeat + event-log torn-write kill)
36
37const CL_EVENTLOG: *u8 = "/mnt/c/Users/elder/nishi-core/nxc2/_offc/nx_crew_events.log"
38const CL_GATE_TIMEOUT_MS: i64 = 12000 // per-organ RUN hang bound
39const CL_BUILD_TIMEOUT_MS: i64 = 60000 // per cc/as/ld stage hang bound (compiler can loop)
40const CL_CADENCE_MS: i64 = 500 // sleep between beats (short for the demo)
41const CL_BEATS: i64 = 3 // bounded; unbounded daemon = config flip
42const CL_MODE_FILE: i64 = 420
43const CL_NGATES: i64 = 2 // the two invention organs (author + verify-by-proof)
44
45// SOVEREIGN dispatch oracles -- the PINNED known-good compiler + tolerated build
46// oracles (as/ld). argv[0] of every spawn below is one of THESE, never /bin/bash.
47const CL_CC: *u8 = "/mnt/c/Users/elder/nishi-core/nxc2/_offc/nx_cc_known_good.elf"
48const CL_AS: *u8 = "/usr/bin/as"
49const CL_LD: *u8 = "/usr/bin/ld"
50// UNIQUE /tmp tag (distinct from gr_gate's /tmp/nx_gr.* -> no race vs gate-runner)
51const CL_S: *u8 = "/tmp/nx_cl.s"
52const CL_O: *u8 = "/tmp/nx_cl.o"
53const CL_ELF: *u8 = "/tmp/nx_cl.elf"
54// WMS LIVE-1/LIVE-3 additive wiring
55const CL_REC_CAP: i64 = 256 // bounded event/heartbeat record (matches WMS-R0 RECCAP)
56const CL_HB_CHANNEL: *u8 = "/mnt/c/Users/elder/nishi-core/nxc2/knowledge/status/wms_heartbeat.log"
57const CL_CONDUCTOR_WS: i64 = 1 // the conductor's own workstream id in the heartbeat channel
58
59func cl_wstr(fd: i64, s: *u8) -> i64 {
60 var n: i64 = 0
61 while s[n] != 0 as u8 { n = n + 1 }
62 sys_write(fd, s, n)
63 return 0
64}
65func cl_wnum(fd: i64, n: i64) -> i64 {
66 if n == 0 { sys_write(fd, "0" as *u8, 1); return 0 }
67 var m: i64 = n
68 let d: *u8 = sys_mmap(24)
69 var k: i64 = 0
70 while m > 0 { d[k] = (0x30 + (m % 10)) as u8; m = m / 10; k = k + 1 }
71 var i: i64 = k - 1
72 while i >= 0 { let o: *u8 = sys_mmap(1); o[0] = d[i]; sys_write(fd, o, 1); i = i - 1 }
73 return 0
74}
75
76// WMS LIVE-1: beat the conductor's own liveness as ONE locked framed write. Mirrors
77// nx_heartbeat_monitor's hbm_build "HBX ws=<id> epoch=<e> seq=<n> actor=<pid> END" contract so M1's
78// hbm_scan reads it -- inlined (single fa_appendz) so the live daemon needs no main-bearing import.
79// Additive + fire-and-forget: the beat NEVER affects the verdict/Warden/exit accounting below.
80func cl_hb_beat(seq: i64) -> i64 {
81 let epoch: i64 = sys_now_realtime_sec()
82 let pid: i64 = __syscall(172, 0, 0, 0, 0, 0, 0) // getpid (actor). rv64 getpid=172; raw x86 39 is an RV64 KEY translated to ioctl(16) -> -ENOTTY (debt idx 2277)
83 let buf: *u8 = sys_mmap(CL_REC_CAP + 16)
84 var o: i64 = 0
85 o = fa_cat(buf, o, "HBX ws=" as *u8); o = fa_catn(buf, o, CL_CONDUCTOR_WS)
86 o = fa_cat(buf, o, " epoch=" as *u8); o = fa_catn(buf, o, epoch)
87 o = fa_cat(buf, o, " seq=" as *u8); o = fa_catn(buf, o, seq)
88 o = fa_cat(buf, o, " actor=" as *u8); o = fa_catn(buf, o, pid)
89 o = fa_cat(buf, o, " END" as *u8)
90 buf[o] = 0 as u8
91 return fa_appendz(CL_HB_CHANNEL, buf, CL_REC_CAP)
92}
93
94// SOVEREIGN spawn: fork+exec `path` with argv/envp, child stdout -> out_path if
95// non-null else /dev/null, stderr -> /dev/null. Ported from gr_run BUT made
96// hang-safe -- the child arms a self-SIGALRM deadline (nx_rt_alarm, reused from
97// nx_run_timeout) before execve, so a looping build-oracle (the known-good
98// compiler CAN loop on bad source; see the print-codegen-triage ledger) kills
99// ITSELF at the deadline instead of wedging the beat. Guards pid<0 BEFORE wait4
100// so a fork failure is never silently decoded as exit 0 (a false PROVEN). On
101// success returns the child exit code; on a deadline hit returns NX_RT_TIMEOUT;
102// on fork failure returns NX_RT_FORK_FAIL.
103func cl_run(path: *u8, argv: *i64, envp: *i64, out_path: *u8, timeout_ms: i64) -> i64 {
104 var tsec: i64 = (timeout_ms + 999) / 1000 // ceil to whole seconds
105 if tsec < 1 { tsec = 1 }
106 let pid: i64 = sys_fork()
107 if pid == 0 {
108 let dn: i64 = sys_openat_wr("/dev/null" as *u8, 0)
109 if (out_path as i64) != 0 {
110 let ofd: i64 = sys_openat_wr(out_path, CL_MODE_FILE)
111 if ofd >= 0 { sys_dup3(ofd, 1, 0) }
112 }
113 if (out_path as i64) == 0 { if dn >= 0 { sys_dup3(dn, 1, 0) } }
114 if dn >= 0 { sys_dup3(dn, 2, 0) }
115 nx_rt_alarm(tsec) // self-deadline: SIGALRM terminates a hung stage
116 sys_execve(path, argv, envp)
117 sys_exit(127)
118 }
119 if pid < 0 { return NX_RT_FORK_FAIL }
120 let st: *i64 = sys_mmap(16) as *i64
121 let r: i64 = sys_wait4(pid, st, 0)
122 if r < 0 { return NX_RT_FORK_FAIL }
123 let status: i64 = st[0]
124 let termsig: i64 = status & 0x7f
125 if termsig == NX_RT_SIGALRM { return NX_RT_TIMEOUT } // deadline hit = HANG/loop
126 if termsig != 0 { return 1000 + termsig } // other signal = crashed
127 return wait_exit_code(status)
128}
129
130// SOVEREIGN gate: compile + assemble + link an invention organ .nx, then run it
131// hang-safe; the organ's exit code IS the verdict (0 = PROVEN), or a negative
132// stage code on a build-oracle failure, or NX_RT_TIMEOUT on any hang. This is the
133// gr_gate shape ported into the Conductor -- argv[0] is the known-good ELF / as /
134// ld, NEVER /bin/bash. EVERY stage (cc/as/ld AND the run) is deadline-bounded.
135func cl_gate(testnx: *u8, elapsed_out: *i64) -> i64 {
136 let envp: *i64 = sys_mmap(8) as *i64
137 envp[0] = 0
138 // 1. compile: cc testnx > CL_S
139 let a1: *i64 = sys_mmap(32) as *i64
140 a1[0] = CL_CC as i64; a1[1] = testnx as i64; a1[2] = 0
141 if cl_run(CL_CC, a1, envp, CL_S, CL_BUILD_TIMEOUT_MS) != 0 { return 0 - 1 }
142 // 2. assemble: as CL_S -o CL_O
143 let a2: *i64 = sys_mmap(40) as *i64
144 a2[0] = CL_AS as i64; a2[1] = CL_S as i64; a2[2] = ("-o" as *u8) as i64; a2[3] = CL_O as i64; a2[4] = 0
145 if cl_run(CL_AS, a2, envp, 0 as *u8, CL_BUILD_TIMEOUT_MS) != 0 { return 0 - 2 }
146 // 3. link: ld -o CL_ELF CL_O
147 let a3: *i64 = sys_mmap(40) as *i64
148 a3[0] = CL_LD as i64; a3[1] = ("-o" as *u8) as i64; a3[2] = CL_ELF as i64; a3[3] = CL_O as i64; a3[4] = 0
149 if cl_run(CL_LD, a3, envp, 0 as *u8, CL_BUILD_TIMEOUT_MS) != 0 { return 0 - 3 }
150 // 4. run the organ hang-safe; its exit code IS the verdict
151 let a4: *i64 = sys_mmap(16) as *i64
152 a4[0] = CL_ELF as i64; a4[1] = 0
153 return nx_run_timeout(CL_ELF, a4, envp, CL_GATE_TIMEOUT_MS, elapsed_out)
154}
155
156// WMS LIVE-3: the event record was 8 sequential sys_write calls to one O_APPEND fd -- a torn-write
157// channel under concurrent beats (the exact "NOTES epoch=NOTES epoch=" bug class). Now assembled
158// into ONE buffer and emitted with a SINGLE locked fa_appendz. Output is byte-identical
159// ("beat=<b> tick=<label> verdict=<v> ms=<ms>\n"); fa_appendz supplies the framing newline.
160func cl_event(beat: i64, label: *u8, verdict: *u8, ms: i64) -> i64 {
161 let buf: *u8 = sys_mmap(CL_REC_CAP + 16)
162 var o: i64 = 0
163 o = fa_cat(buf, o, "beat=" as *u8); o = fa_catn(buf, o, beat)
164 o = fa_cat(buf, o, " tick=" as *u8); o = fa_cat(buf, o, label)
165 o = fa_cat(buf, o, " verdict=" as *u8); o = fa_cat(buf, o, verdict)
166 o = fa_cat(buf, o, " ms=" as *u8); o = fa_catn(buf, o, ms)
167 buf[o] = 0 as u8
168 return fa_appendz(CL_EVENTLOG, buf, CL_REC_CAP)
169}
170
171// ADDITIVE win-ledger journaling for ONE verify-by-proof verdict. Strictly a
172// SIDE EFFECT: it records the verified organ as an NxWinRecord (claim=the organ,
173// repro=the SAME gate just ticked, expected=the gate's real known answer) and
174// re-verifies it on the PINNED compiler, appending HOLDS/REFUTED to the ledger's
175// own in-memory hash-chained journal. It is FIRE-AND-FORGET: every failure path
176// (null ledger, invalid record, journal append fault) is swallowed and returns
177// without touching the beat -- so journaling can never flip the beat verdict, the
178// Warden ALLOW/DENY asserts, or the exit gate. Returns the ledger entry count
179// AFTER this attempt (unchanged on any failure), purely for the proof line.
180func cl_journal_win(L: *NxWinLedger, repro_gate: *u8) -> i64 {
181 if (L as i64) == 0 { return -1 } // non-fatal: no ledger -> skip
182 if nx_win_ledger_is_valid(L) != 1 { return -1 } // non-fatal: bad ledger -> skip
183 let r: *NxWinRecord = nx_win_record_new(
184 "verify-by-proof: mul x8 == shl x3 (membership-as-PROOF)" as *u8, // claim = the organ verified
185 "meet" as *u8, // exceed axis
186 "e-graph membership re-derives the strength-reduction equiv; sound per rule_soundness gate" as *u8,
187 repro_gate, // repro = the SAME gate just ticked
188 "3584" as *u8) // expected known answer (mul 448 x8 == shl 448 x3)
189 if (r as i64) == 0 { return nx_win_ledger_count(L) } // non-fatal: alloc fault -> skip, count unchanged
190 nx_win_record_add_assumption(r, "pinned nx_cc_known_good.elf re-gates (not the active poisoned compiler)" as *u8)
191 nx_win_record_add_assumption(r, "membership proof is total over the tested operand domain" as *u8)
192 // record_and_verify is itself defensive (returns negative on bad input, never
193 // crashes); its return is ADVISORY only -- we do not branch the beat on it.
194 nx_win_ledger_record_and_verify(L, r)
195 return nx_win_ledger_count(L)
196}
197
198func main() -> i64 {
199 cl_wstr(1, "NISHI CONDUCTOR v3 -- LIVE, WARDEN-GATED tick: ticks the INVENTION ORGANS sovereign (no .sh), UNATTENDED\n")
200 cl_wstr(1, "===================================================================================================\n")
201
202 // the verification grid = the two INVENTION ORGANS (proven gate-runner 16+18),
203 // ticked via the sovereign cl_gate path -- NO .sh, argv[0] = known-good ELF.
204 let names: *i64 = sys_mmap(CL_NGATES * 8) as *i64
205 let gates: *i64 = sys_mmap(CL_NGATES * 8) as *i64
206 names[0] = ("author : superopt PROPOSE/SCORE/VERIFY/EMIT(mem) " as *u8) as i64
207 gates[0] = ("/mnt/c/Users/elder/nishi-core/nxc2/runtime/_hdl_build/nx_superopt_test.nx" as *u8) as i64
208 names[1] = ("verify : membership-as-PROOF (mul x8 == shl x3) " as *u8) as i64
209 gates[1] = ("/mnt/c/Users/elder/nishi-core/nxc2/runtime/_hdl_build/nx_eqsat_membership_proof_test.nx" as *u8) as i64
210
211 // ADDITIVE: a process-local win-ledger (in-memory, hash-chained) capturing
212 // each verify-by-proof verdict as a falsifiable win record. Constructed OUTSIDE
213 // the beat-verdict / Warden / exit accounting -- pure self-learning capture.
214 let win_ledger: *NxWinLedger = nx_win_ledger_new()
215
216 var beat: i64 = 0
217 var allgreen_beats: i64 = 0
218 var warden_denies: i64 = 0
219 while beat < CL_BEATS {
220 cl_wstr(1, "beat "); cl_wnum(1, beat); cl_wstr(1, ":\n")
221 cl_hb_beat(beat) // WMS LIVE-1: durable liveness beat -> M1 sees a real crash as STALLED
222
223 // THE WARDEN GATES THE TICK. allow the safe verify action...
224 let auth: i64 = warden_authorize(W_ADDITIVE, CL_EVENTLOG, 0)
225 // ...and prove it DENIES a forbidden one (overwriting source).
226 let deny: i64 = warden_authorize(W_OVERWRITE_SRC, "/mnt/c/Users/elder/nishi-core/nxc2/runtime/nx_eqsat.nx" as *u8, 1)
227 if deny == W_DENY { warden_denies = warden_denies + 1 }
228 cl_wstr(1, " warden: verify-tick=")
229 if auth == W_ALLOW { cl_wstr(1, "ALLOW") } else { cl_wstr(1, "DENY") }
230 cl_wstr(1, " overwrite-src=")
231 if deny == W_ALLOW { cl_wstr(1, "ALLOW") } else { cl_wstr(1, "DENY") }
232 cl_wstr(1, "\n")
233
234 if auth == W_ALLOW {
235 var i: i64 = 0
236 var proven: i64 = 0
237 while i < CL_NGATES {
238 let el: *i64 = sys_mmap(8) as *i64
239 el[0] = 0
240 let rc: i64 = cl_gate(gates[i] as *u8, el)
241 var verdict: *u8 = "PROVEN " as *u8
242 if rc != 0 {
243 if rc == NX_RT_TIMEOUT { verdict = "TIMEOUT" as *u8 } else { verdict = "FAIL " as *u8 }
244 }
245 if rc == 0 { proven = proven + 1 }
246 cl_wstr(1, " "); cl_wstr(1, names[i] as *u8); cl_wstr(1, " "); cl_wstr(1, verdict)
247 cl_wstr(1, " "); cl_wnum(1, el[0]); cl_wstr(1, "ms\n")
248 cl_event(beat, names[i] as *u8, verdict, el[0])
249 // ADDITIVE win-ledger journaling for the verify-by-proof organ
250 // (i == 1). Strictly AFTER the proven tally + cl_event above, and
251 // OUTSIDE allgreen_beats/warden_denies/exit accounting. Fire-and-
252 // forget: cl_journal_win swallows every failure -> NON-FATAL, the
253 // beat still passes on a real all-green tick. (We only journal when
254 // the organ actually PROVEN this beat, so the win record is honest.)
255 if i == 1 {
256 if rc == 0 {
257 let wc: i64 = cl_journal_win(win_ledger, gates[1] as *u8)
258 cl_wstr(1, " win-ledger: recorded verify-by-proof; entries="); cl_wnum(1, wc); cl_wstr(1, "\n")
259 }
260 }
261 i = i + 1
262 }
263 cl_wstr(1, " beat verdict: "); cl_wnum(1, proven); cl_wstr(1, "/"); cl_wnum(1, CL_NGATES); cl_wstr(1, " PROVEN\n")
264 if proven == CL_NGATES { allgreen_beats = allgreen_beats + 1 }
265 }
266 sys_sleep_ms(CL_CADENCE_MS)
267 beat = beat + 1
268 }
269
270 cl_wstr(1, "HEARTBEAT: "); cl_wnum(1, CL_BEATS); cl_wstr(1, " beats, Warden-gated, engine verification journaled -- the loop ticked WITHOUT a human.\n")
271 cl_wstr(1, " all-green beats="); cl_wnum(1, allgreen_beats); cl_wstr(1, " warden-denies="); cl_wnum(1, warden_denies); cl_wstr(1, "\n")
272 // ADDITIVE proof line: the win-ledger gained entries (2 per verified beat:
273 // a RECORD entry + a HOLDS/REFUTED entry). Reported AFTER the verdict, OUTSIDE
274 // the exit gate -- a journaling shortfall here can never change the exit code.
275 cl_wstr(1, " win-ledger entries="); cl_wnum(1, nx_win_ledger_count(win_ledger)); cl_wstr(1, " (additive self-learning capture; journaling is non-fatal)\n")
276 // exit 0 only if every beat verified the engine AND the Warden denied every forbidden action
277 if allgreen_beats != CL_BEATS { sys_exit(1); return 1 }
278 if warden_denies != CL_BEATS { sys_exit(2); return 2 }
279 sys_exit(0); return 0
280}