code wiki / _hdl_build / nx_plan_run.nx
nx_plan_run.nx source
↩ module page · 286 lines · 11564 B
1// nx_plan_run.nx -- WORKFLOWS-AS-DATA: the sovereign plan executor (operator 2026-07-18: "i still
2// see scratchpadding not via nishi... get what you are doing outside of it in mcp and api and
3// workflow"). Kills the session-side shell-script orchestration class: a PLAN is rows in a plane
4// (seeded via the MCP-live nx_store_put), and ONE cap-gated tools/call executes the whole sequence
5// SERVER-SIDE, recording per-step results to a results plane (provenance in the plane, as always).
6// nx_plan_run <planid> [allowlist] [planprefix] [resultsprefix]
7// plan rows : knowledge/store/plan-<id>- seq<TAB>tool<TAB>arg... (executed in seq order)
8// results rows: knowledge/store/planrun-<id>- seq<TAB>tool<TAB>rc<TAB>output-snippet
9// SECURITY = the tools-plane model, no escalation: each step's tool MUST be a GREEN row in
10// tool_allowlist.conf; a row's PINNED args override plan args (fixed-arg pinning, caller args
11// ignored); unknown tool -> REFUSED fail-closed; a failing step STOPS the plan (later steps never
12// run) with the failure recorded. nx_plan_run itself is cap-gated on the tools plane.
13// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0
14import "nx_store_seed_lib.nx"
15import "nx_seg_store.nx"
16import "nx_deploy_lib.nx"
17import "nx_syscalls.nx"
18
19const PR_CAP: i64 = 1048576
20const PR_NL: i64 = 10
21const PR_TAB: i64 = 9
22const PR_SP: i64 = 32
23const PR_MAXCOL: i64 = 16
24const PR_PAIR: i64 = 2
25const PR_SPB: i64 = 256
26const PR_MAXSTEP: i64 = 64
27const PR_MAXARG: i64 = 12
28const PR_ARENA: i64 = 65536
29const PR_PFXCAP: i64 = 256
30// ★200 -> 2000 (2026-07-30, ws=neuro). A 200-byte snippet is SMALLER THAN THE SUMMARY MANY ORGANS PRINT,
31// so the results plane silently reported only a tool's header and dropped its actual finding: nx_meshprofile
32// emits a DELIBERATE SHORTLIST (top-12 radius jumps, the whole point of the organ) and the plane carried only
33// the DIAG line, making the step unreadable while still recording rc=0. A results row that cannot hold the
34// result is a green light with the answer cut off. BOUNDED BY CONSTRUCTION, not by hope: res is mmap'd at
35// PR_CAP (1 MiB) and steps are capped at PR_MAXSTEP (64), so the worst case is 64*~2050 = ~131 KB, an eighth
36// of the arena. Raise PR_CAP first if PR_MAXSTEP ever grows.
37const PR_SNIP: i64 = 2000
38const PR_OUTCAP: i64 = 65536
39const PR_STDERR: i64 = 2
40const PR_EXIT_USAGE: i64 = 2
41const PR_EXIT_IO: i64 = 1
42const PR_EXIT_REFUSED: i64 = 4
43const PR_EXIT_STEPFAIL: i64 = 5
44const PR_ZERO: i64 = 48
45const PR_NINE: i64 = 57
46const PR_B10: i64 = 10
47
48func pr_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
49func pr_werr(s: *u8) -> i64 { sys_write(PR_STDERR, s, pr_slen(s)); return 0 }
50func pr_cols(q: *u8, ls: i64, le: i64, sp: *i64) -> i64 {
51 var c: i64 = 0
52 var p: i64 = ls
53 while c < PR_MAXCOL {
54 var e: i64 = p
55 var s: i64 = 1
56 while s == 1 { if e >= le { s = 0 } else { if q[e] == (PR_TAB as u8) { s = 0 } else { e = e + 1 } } }
57 sp[c*PR_PAIR] = p
58 sp[c*PR_PAIR+1] = e
59 c = c + 1
60 if e >= le { return c }
61 p = e + 1
62 }
63 return c
64}
65func pr_slice_int(q: *u8, a: i64, b: i64) -> i64 {
66 var v: i64 = 0
67 var i: i64 = a
68 while i < b { let c: i64 = q[i]; if c >= PR_ZERO { if c <= PR_NINE { v = v * PR_B10 + (c - PR_ZERO) } } i = i + 1 }
69 return v
70}
71func pr_slice_eq(q: *u8, a: i64, b: i64, r: *u8, c: i64, d: i64) -> i64 {
72 if b - a != d - c { return 0 }
73 var i: i64 = 0
74 while a + i < b { if q[a+i] != r[c+i] { return 0 } i = i + 1 }
75 return 1
76}
77// copy slice into arena as a NUL-terminated C-string; returns its address, bumps off
78func pr_cstr(arena: *u8, off: *i64, q: *u8, a: i64, b: i64) -> i64 {
79 let base: i64 = off[0]
80 var i: i64 = a
81 var o: i64 = base
82 while i < b { arena[o] = q[i]; o = o + 1; i = i + 1 }
83 arena[o] = 0 as u8
84 off[0] = o + 1
85 return (arena as i64) + base
86}
87// find tool (slice) in allowlist buf; fill elfp[0]=elf cstr addr; pinned args into av[0..], returns nargs (-1 not found)
88func pr_find_tool(al: *u8, n: i64, q: *u8, ta: i64, tb: i64, arena: *u8, off: *i64, elfp: *i64, av: *i64) -> i64 {
89 let sp: *i64 = sys_mmap(PR_SPB) as *i64
90 var i: i64 = 0
91 while i < n {
92 var le: i64 = i
93 var s: i64 = 1
94 while s == 1 { if le >= n { s = 0 } else { if al[le] == (PR_NL as u8) { s = 0 } else { le = le + 1 } } }
95 if le > i {
96 let nc: i64 = pr_cols(al, i, le, sp)
97 if nc >= 3 {
98 if pr_slice_eq(al, sp[0], sp[1], q, ta, tb) == 1 {
99 elfp[0] = pr_cstr(arena, off, al, sp[2], sp[3])
100 var na: i64 = 0
101 if nc >= 4 {
102 // pinned args col: split on spaces
103 var p: i64 = sp[6]
104 let pe: i64 = sp[7]
105 while p < pe {
106 var e2: i64 = p
107 var s2: i64 = 1
108 while s2 == 1 { if e2 >= pe { s2 = 0 } else { if al[e2] == (PR_SP as u8) { s2 = 0 } else { e2 = e2 + 1 } } }
109 if e2 > p { if na < PR_MAXARG { av[na] = pr_cstr(arena, off, al, p, e2); na = na + 1 } }
110 p = e2 + 1
111 }
112 }
113 return na
114 }
115 }
116 }
117 i = le + 1
118 }
119 return 0 - 1
120}
121// sanitize outfile content into a snippet: tabs/newlines -> spaces, cap PR_SNIP
122func pr_snip(dst: *u8, o: i64, src: *u8, n: i64) -> i64 {
123 var m: i64 = n
124 if m > PR_SNIP { m = PR_SNIP }
125 var oo: i64 = o
126 var i: i64 = 0
127 while i < m {
128 var c: i64 = src[i]
129 if c == PR_TAB { c = PR_SP }
130 if c == PR_NL { c = PR_SP }
131 if c < PR_SP { c = PR_SP }
132 dst[oo] = c as u8
133 oo = oo + 1
134 i = i + 1
135 }
136 return oo
137}
138
139func main(argc: i64, argv: *i64) -> i64 {
140 if argc < 2 { pr_werr("usage: nx_plan_run <planid> [allowlist] [planprefix] [resultsprefix]\n" as *u8); sys_exit(PR_EXIT_USAGE); return PR_EXIT_USAGE }
141 let planid: *u8 = argv[1] as *u8
142 var alpath: *u8 = "tool_allowlist.conf" as *u8
143 if argc > 2 { alpath = argv[2] as *u8 }
144 let ppfx: *u8 = sys_mmap(PR_PFXCAP)
145 let rpfx: *u8 = sys_mmap(PR_PFXCAP)
146 if argc > 3 {
147 let p3: *u8 = argv[3] as *u8
148 var i0: i64 = 0
149 while p3[i0] != (0 as u8) { ppfx[i0] = p3[i0]; i0 = i0 + 1 }
150 ppfx[i0] = 0 as u8
151 } else {
152 var o1: i64 = ss_cat(ppfx, 0, "knowledge/store/plan-" as *u8)
153 o1 = ss_cat(ppfx, o1, planid)
154 o1 = ss_cat(ppfx, o1, "-" as *u8)
155 ppfx[o1] = 0 as u8
156 }
157 if argc > 4 {
158 let p4: *u8 = argv[4] as *u8
159 var i1: i64 = 0
160 while p4[i1] != (0 as u8) { rpfx[i1] = p4[i1]; i1 = i1 + 1 }
161 rpfx[i1] = 0 as u8
162 } else {
163 var o2: i64 = ss_cat(rpfx, 0, "knowledge/store/planrun-" as *u8)
164 o2 = ss_cat(rpfx, o2, planid)
165 o2 = ss_cat(rpfx, o2, "-" as *u8)
166 rpfx[o2] = 0 as u8
167 }
168
169 let plan: *u8 = sys_mmap(PR_CAP)
170 let pn: i64 = sts_load(ppfx, plan, PR_CAP)
171 if pn <= 0 { pr_werr("plan plane EMPTY / unseeded (fail-closed)\n" as *u8); sys_exit(PR_EXIT_IO); return PR_EXIT_IO }
172 let al: *u8 = sys_mmap(PR_CAP)
173 let an: i64 = dp_read(alpath, al, PR_CAP - 4)
174 if an <= 0 { pr_werr("allowlist unreadable (fail-closed)\n" as *u8); sys_exit(PR_EXIT_IO); return PR_EXIT_IO }
175
176 // collect step line spans + seqs
177 let lss: *i64 = sys_mmap(PR_MAXSTEP*8) as *i64
178 let les: *i64 = sys_mmap(PR_MAXSTEP*8) as *i64
179 let sqs: *i64 = sys_mmap(PR_MAXSTEP*8) as *i64
180 let sp: *i64 = sys_mmap(PR_SPB) as *i64
181 var nstep: i64 = 0
182 var i: i64 = 0
183 while i < pn {
184 var le: i64 = i
185 var s: i64 = 1
186 while s == 1 { if le >= pn { s = 0 } else { if plan[le] == (PR_NL as u8) { s = 0 } else { le = le + 1 } } }
187 if le > i { if nstep < PR_MAXSTEP {
188 let nc: i64 = pr_cols(plan, i, le, sp)
189 if nc >= 2 {
190 lss[nstep] = i
191 les[nstep] = le
192 sqs[nstep] = pr_slice_int(plan, sp[0], sp[1])
193 nstep = nstep + 1
194 }
195 } }
196 i = le + 1
197 }
198 // insertion sort by seq
199 var a: i64 = 1
200 while a < nstep {
201 var b: i64 = a
202 while b > 0 {
203 if sqs[b-1] > sqs[b] {
204 let t0: i64 = sqs[b-1]
205 sqs[b-1] = sqs[b]
206 sqs[b] = t0
207 let t1: i64 = lss[b-1]
208 lss[b-1] = lss[b]
209 lss[b] = t1
210 let t2: i64 = les[b-1]
211 les[b-1] = les[b]
212 les[b] = t2
213 b = b - 1
214 } else { b = 0 }
215 }
216 a = a + 1
217 }
218
219 let arena: *u8 = sys_mmap(PR_ARENA)
220 let aoff: *i64 = sys_mmap(16) as *i64
221 let res: *u8 = sys_mmap(PR_CAP)
222 let outbuf: *u8 = sys_mmap(PR_OUTCAP)
223 let elfp: *i64 = sys_mmap(16) as *i64
224 let av: *i64 = sys_mmap((PR_MAXARG+2)*8) as *i64
225 let outfile: *u8 = "/tmp/nx_plan_step.out" as *u8
226 var ro: i64 = 0
227 var k: i64 = 0
228 var failed: i64 = 0
229 while k < nstep {
230 if failed == 0 {
231 aoff[0] = 0
232 let nc2: i64 = pr_cols(plan, lss[k], les[k], sp)
233 // resolve tool (col1) in allowlist
234 var na: i64 = pr_find_tool(al, an, plan, sp[2], sp[3], arena, aoff, elfp, av)
235 if na < 0 {
236 ro = ss_catn(res, ro, sqs[k])
237 res[ro] = PR_TAB as u8
238 ro = ro + 1
239 var rr: i64 = ro
240 rr = pr_snip(res, rr, "REFUSED-unknown-tool" as *u8, 20)
241 ro = rr
242 res[ro] = PR_NL as u8
243 ro = ro + 1
244 failed = PR_EXIT_REFUSED
245 } else {
246 if na == 0 {
247 // no pinned args -> plan cols 2.. are the argv
248 var c: i64 = 2
249 while c < nc2 {
250 if na < PR_MAXARG { av[na] = pr_cstr(arena, aoff, plan, sp[c*PR_PAIR], sp[c*PR_PAIR+1]); na = na + 1 }
251 c = c + 1
252 }
253 }
254 let rc: i64 = dep_run_capture(elfp[0] as *u8, av, na, outfile)
255 let on: i64 = dp_read(outfile, outbuf, PR_OUTCAP - 4)
256 ro = ss_catn(res, ro, sqs[k])
257 res[ro] = PR_TAB as u8
258 ro = ro + 1
259 ro = ss_cat(res, ro, "rc=" as *u8)
260 ro = ss_catn(res, ro, rc)
261 res[ro] = PR_TAB as u8
262 ro = ro + 1
263 var on2: i64 = on
264 if on2 < 0 { on2 = 0 }
265 ro = pr_snip(res, ro, outbuf, on2)
266 res[ro] = PR_NL as u8
267 ro = ro + 1
268 if rc != 0 { failed = PR_EXIT_STEPFAIL }
269 }
270 }
271 k = k + 1
272 }
273 if sts_seed(rpfx, res, ro) < 0 { pr_werr("results commit error\n" as *u8); sys_exit(PR_EXIT_IO); return PR_EXIT_IO }
274 let msg: *u8 = sys_mmap(PR_PFXCAP)
275 var mo: i64 = ss_cat(msg, 0, "PLAN " as *u8)
276 mo = ss_cat(msg, mo, planid)
277 mo = ss_cat(msg, mo, " steps=" as *u8)
278 mo = ss_catn(msg, mo, nstep)
279 if failed != 0 { mo = ss_cat(msg, mo, " FAILED (stopped fail-closed, results recorded)" as *u8) } else { mo = ss_cat(msg, mo, " ok" as *u8) }
280 msg[mo] = PR_NL as u8
281 mo = mo + 1
282 sys_write(1, msg, mo)
283 if failed != 0 { sys_exit(failed); return failed }
284 sys_exit(0)
285 return 0
286}