code wiki / _hdl_build / nx_ale_flywheel.nx
nx_ale_flywheel.nx source
↩ module page · 207 lines · 10279 B
1// nx_ale_flywheel.nx -- ALE-R5: the sovereign ALE SCORE-FLYWHEEL (the RSI loop driver). Runs a
2// task manifest through the ALE-R1 measure (_offc/nx_ale_harness.elf) and CLASSIFIES each task:
3// SOLVED = harness exit 0 AND milli-score == 1000 (the agent fully produced the graded artifact)
4// GAP = otherwise (refused/unscored [exit!=0] OR partial [score<1000]) -- a CAPABILITY GAP
5// It reports each GAP (task + exit + score) so the loop can GAP-ANALYZE -> build the missing
6// transform/skill -> re-attempt. That is the RSI loop toward the exam: measure -> gap -> build ->
7// re-measure -> close. Reuses the harness (DRY); the measure owns scoring, the flywheel owns triage.
8// args mode: nx_ale_flywheel <manifest> -> classify that manifest, print FLYWHEEL + per-gap.
9// no-arg: SELF-GATE -- a CONTROL manifest [a known-SOLVED task + a PERMANENT-GAP task
10// (ctl_never_supported, an executor token never built)] must classify exactly 1 solved + 1 gap
11// (separation bites), AND an all-solved manifest must yield 0 gaps (no false gap) ->
12// FLYWHEELGATE verdict=GREEN to knowledge/status/ale_flywheel.log + stdout.
13// Landmines: nested ifs (no &&/||), flat exprs, <=6 args/func, no empty-string literal, strings via
14// Write. license_tier: ORIGINAL
15//
16// module: nishi-core.ale.flywheel
17// depends: nishi-core.sys.syscalls
18// capability: ALE_SCORE_FLYWHEEL_RSI
19import "nx_syscalls.nx"
20const K_MAGIC_65536: i64 = 65536
21const K_MAGIC_2048: i64 = 2048
22const K_MAGIC_2047: i64 = 2047
23
24func fl_p(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
25func fl_fp(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 }
26func fl_fn(fd: i64, v: i64) -> i64 { let bb: *u8 = sys_mmap(28); var m: i64 = v; if m < 0 { m = 0 - m; sys_write(fd, "-" 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(fd, bb, k); return 0 }
27func fl_len(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
28func fl_unlink(path: *u8) -> i64 { return __syscall(263, AT_FDCWD, path, 0, 0, 0, 0) }
29
30func fl_read(path: *u8, buf: *u8, cap: i64) -> i64 {
31 let fd: i64 = sys_openat_rd(path)
32 if fd < 0 { return 0 }
33 var n: i64 = 0
34 var go: i64 = 1
35 while go == 1 {
36 let r: i64 = sys_read(fd, (buf as i64 + n) as *u8, cap - 1 - n)
37 if r <= 0 { go = 0 } else { n = n + r }
38 if n >= cap - 1 { go = 0 }
39 }
40 sys_close(fd)
41 return n
42}
43
44func fl_score_of(path: *u8) -> i64 {
45 let sb: *u8 = sys_mmap(64)
46 let n: i64 = fl_read(path, sb, 64)
47 if n <= 0 { return 0 - 1 }
48 var v: i64 = 0
49 var i: i64 = 0
50 while i < n { if sb[i] >= (48 as u8) { if sb[i] <= (57 as u8) { v = v * 10 + (sb[i] - 48) } } i = i + 1 }
51 return v
52}
53
54func fl_write_file(path: *u8, s: *u8) -> i64 {
55 fl_unlink(path)
56 let fd: i64 = sys_openat_wr(path, 0x1a4)
57 if fd < 0 { return 0 }
58 sys_write(fd, s, fl_len(s))
59 sys_close(fd)
60 return 1
61}
62
63func fl_idx_path(dst: *u8, prefix: *u8, idx: i64) -> i64 {
64 var o: i64 = 0
65 var i: i64 = 0
66 while prefix[i] != (0 as u8) { dst[o] = prefix[i]; o = o + 1; i = i + 1 }
67 var m: i64 = idx
68 let t: *u8 = sys_mmap(28)
69 var k: i64 = 0
70 if m == 0 { t[0] = 48 as u8; k = 1 }
71 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
72 var p: i64 = 0
73 while p < k { dst[o] = t[k - 1 - p]; o = o + 1; p = p + 1 }
74 dst[o] = 0 as u8
75 return o
76}
77
78func fl_run_harness(task: *u8, sb: *u8, out: *u8, score: *u8) -> i64 {
79 let pid: i64 = sys_fork()
80 if pid == 0 {
81 let dn: i64 = sys_openat_wr("/dev/null" as *u8, 0x1a4)
82 if dn >= 0 { sys_dup3(dn, 1, 0); sys_dup3(dn, 2, 0) }
83 let argv: *i64 = sys_mmap(48) as *i64
84 argv[0] = "_offc/nx_ale_harness.elf" as *u8 as i64
85 argv[1] = task as i64
86 argv[2] = sb as i64
87 argv[3] = out as i64
88 argv[4] = score as i64
89 argv[5] = 0
90 let envp: *i64 = sys_mmap(16) as *i64
91 envp[0] = 0
92 sys_execve("_offc/nx_ale_harness.elf" as *u8, argv, envp)
93 sys_exit(127)
94 }
95 let st: *i64 = sys_mmap(16) as *i64
96 sys_wait4(pid, st, 0)
97 return (st[0] >> 8) & 0xff
98}
99
100// classify each manifest task: res[0]=n_tasks res[1]=n_solved res[2]=n_gaps. verbose -> per-gap line.
101// ledger_fd >= 0 -> append each detected gap as a durable ALEGAP row (the auto-file surface the
102// gap-filer turns into queue rungs). Self-gate runs pass -1 (never pollute the real ledger).
103func fl_run(manifestpath: *u8, res: *i64, verbose: i64, ledger_fd: i64) -> i64 {
104 let buf: *u8 = sys_mmap(K_MAGIC_65536)
105 let n: i64 = fl_read(manifestpath, buf, K_MAGIC_65536)
106 var n_tasks: i64 = 0
107 var n_solved: i64 = 0
108 var n_gaps: i64 = 0
109 var idx: i64 = 0
110 var ls: i64 = 0
111 var i: i64 = 0
112 while i <= n {
113 var eol: i64 = 0
114 if i == n { eol = 1 } else { if buf[i] == (10 as u8) { eol = 1 } }
115 if eol == 1 {
116 if i > ls { if buf[ls] != (35 as u8) {
117 let tpath: *u8 = sys_mmap(K_MAGIC_2048)
118 var k: i64 = 0
119 var p: i64 = ls
120 while p < i { if k < K_MAGIC_2047 { tpath[k] = buf[p]; k = k + 1 } p = p + 1 }
121 tpath[k] = 0 as u8
122 if k > 0 {
123 n_tasks = n_tasks + 1
124 let sb: *u8 = sys_mmap(256); fl_idx_path(sb, "/tmp/_fly_sb_" as *u8, idx)
125 let out: *u8 = sys_mmap(256); fl_idx_path(out, "/tmp/_fly_out_" as *u8, idx)
126 let sc: *u8 = sys_mmap(256); fl_idx_path(sc, "/tmp/_fly_sc_" as *u8, idx)
127 sys_mkdir(sb, 0x1ed); sys_mkdir(out, 0x1ed)
128 fl_unlink(sc)
129 let rc: i64 = fl_run_harness(tpath, sb, out, sc)
130 var score: i64 = 0 - 1
131 if rc == 0 { score = fl_score_of(sc) }
132 var solved: i64 = 0
133 if rc == 0 { if score == 1000 { solved = 1 } }
134 if solved == 1 { n_solved = n_solved + 1 } else {
135 n_gaps = n_gaps + 1
136 if verbose == 1 { fl_p(" GAPFOUND task=" as *u8); fl_p(tpath); fl_p(" exit=" as *u8); fl_fn(1, rc); fl_p(" score=" as *u8); fl_fn(1, score); fl_p(" (missing capability)\n" as *u8) }
137 if ledger_fd >= 0 { fl_fp(ledger_fd, "ALEGAP\ttask=" as *u8); fl_fp(ledger_fd, tpath); fl_fp(ledger_fd, "\texit=" as *u8); fl_fn(ledger_fd, rc); fl_fp(ledger_fd, "\tscore=" as *u8); fl_fn(ledger_fd, score); fl_fp(ledger_fd, "\n" as *u8) }
138 }
139 idx = idx + 1
140 }
141 } }
142 ls = i + 1
143 }
144 i = i + 1
145 }
146 res[0] = n_tasks; res[1] = n_solved; res[2] = n_gaps
147 return 0
148}
149
150func main(argc: i64, argv: *i64) -> i64 {
151 if argc >= 2 {
152 let res: *i64 = sys_mmap(64) as *i64
153 // args/live mode AUTO-FILES gaps to the durable ledger (the gap-filer's input surface).
154 let glfd: i64 = sys_openat_append("knowledge/status/ale_gaps.tsv" as *u8, 0x1a4)
155 fl_p("=== ALE flywheel (run manifest) ===\n" as *u8)
156 fl_run(argv[1] as *u8, res, 1, glfd)
157 if glfd >= 0 { sys_close(glfd) }
158 fl_p("FLYWHEEL n_tasks=" as *u8); fl_fn(1, res[0]); fl_p(" solved=" as *u8); fl_fn(1, res[1]); fl_p(" gaps=" as *u8); fl_fn(1, res[2]); fl_p(" mode=RUN\n" as *u8)
159 sys_exit(0); return 0
160 }
161
162 fl_p("=== ALE-flywheel gate (ALE-R5: measure -> classify SOLVED/GAP -> the RSI loop) ===\n" as *u8)
163 // CONTROL: [solved task + PERMANENT-gap task] -> must separate exactly 1 solved + 1 gap.
164 fl_write_file("/tmp/_fly_ctl.manifest" as *u8, "knowledge/specs/ale_examples/task_count.txt\nknowledge/specs/ale_examples/task_gapctl.txt\n" as *u8)
165 let res: *i64 = sys_mmap(64) as *i64
166 fl_run("/tmp/_fly_ctl.manifest" as *u8, res, 1, 0 - 1)
167 let nt: i64 = res[0]
168 let nsv: i64 = res[1]
169 let ng: i64 = res[2]
170 var c_tasks: i64 = 0
171 if nt == 2 { c_tasks = 1 }
172 var c_solved: i64 = 0
173 if nsv == 1 { c_solved = 1 }
174 var c_gap: i64 = 0
175 if ng == 1 { c_gap = 1 }
176 // NO-FALSE-GAP: an all-solved manifest must classify 0 gaps.
177 fl_write_file("/tmp/_fly_pos.manifest" as *u8, "knowledge/specs/ale_examples/task_count.txt\nknowledge/specs/ale_examples/task_doc.txt\n" as *u8)
178 let resp: *i64 = sys_mmap(64) as *i64
179 fl_run("/tmp/_fly_pos.manifest" as *u8, resp, 0, 0 - 1)
180 var c_nofalse: i64 = 0
181 if resp[2] == 0 { if resp[1] == 2 { c_nofalse = 1 } }
182
183 fl_p(" ctl: n_tasks=" as *u8); fl_fn(1, nt); fl_p(" solved=" as *u8); fl_fn(1, nsv); fl_p(" gaps=" as *u8); fl_fn(1, ng)
184 fl_p(" | pos: solved=" as *u8); fl_fn(1, resp[1]); fl_p(" gaps=" as *u8); fl_fn(1, resp[2])
185 fl_p("\n c_tasks=" as *u8); fl_fn(1, c_tasks); fl_p(" c_solved=" as *u8); fl_fn(1, c_solved); fl_p(" c_gap_detected=" as *u8); fl_fn(1, c_gap); fl_p(" c_no_false_gap=" as *u8); fl_fn(1, c_nofalse); fl_p("\n" as *u8)
186
187 var allok: i64 = 1
188 if c_tasks == 0 { allok = 0 }
189 if c_solved == 0 { allok = 0 }
190 if c_gap == 0 { allok = 0 }
191 if c_nofalse == 0 { allok = 0 }
192
193 let lfd: i64 = sys_openat_append("knowledge/status/ale_flywheel.log" as *u8, 0x1a4)
194 if allok == 1 {
195 fl_p("FLYWHEELGATE verdict=GREEN separates_solved_gap=1 no_false_gap=1 rung=ALE-R5\n" as *u8)
196 if lfd >= 0 {
197 fl_fp(lfd, "FLYWHEELGATE verdict=GREEN ctl_solved=" as *u8); fl_fn(lfd, nsv)
198 fl_fp(lfd, " ctl_gaps=" as *u8); fl_fn(lfd, ng)
199 fl_fp(lfd, " no_false_gap=1 rung=ALE-R5 epoch=" as *u8); fl_fn(lfd, sys_now_realtime_sec())
200 fl_fp(lfd, "\n" as *u8); sys_close(lfd)
201 }
202 sys_exit(0); return 0
203 }
204 fl_p("FLYWHEELGATE verdict=RED\n" as *u8)
205 if lfd >= 0 { fl_fp(lfd, "FLYWHEELGATE verdict=RED ct=" as *u8); fl_fn(lfd, c_tasks); fl_fp(lfd, " cs=" as *u8); fl_fn(lfd, c_solved); fl_fp(lfd, " cg=" as *u8); fl_fn(lfd, c_gap); fl_fp(lfd, " cnf=" as *u8); fl_fn(lfd, c_nofalse); fl_fp(lfd, "\n" as *u8); sys_close(lfd) }
206 sys_exit(1); return 1
207}