code wiki / _hdl_build / nx_buildq.nx
nx_buildq.nx source
↩ module page · 337 lines · 17927 B
1// nx_buildq.nx -- QUEUE A BUILD FOR THE NEXT OPENING instead of re-issuing it by hand.
2//
3// WHY. `/api/build` under load answers REFUSED-LOAD: "NOTHING IS QUEUED for you anywhere -- re-issue it
4// yourself once the load clears" -- and nx_build_admit's own header says its QUEUE verdict was DESIGNED to
5// be absorbed by nx_orchestrate's wait-for-opening queue. Nothing ever wired the two: the queue had no
6// predicate for headroom, and nothing seeded a build row. Measured 2026-08-18: five REFUSED-LOAD
7// re-issues by hand in one session while the toolchain rung shipped -- a human acting as the retry loop.
8//
9// WHAT (composition, no new mechanism): one call seeds
10// plan-build-<target>- : 1 <TAB> nx_sov_build_run <TAB> <target> <TAB> --build-only
11// deployq- : BQ-<target> | title | headroom:[floor:max] | queued | build-<target> | note
12// nx_orchestrate (the */5 poller) evaluates `headroom:` by forking nx_build_admit and FIRES the plan via
13// nx_plan_run when the box GRANTS -- so the compile lands in buildroot/_build/<target>.sov.elf on the
14// first pass after the opening, its rc + output snippet in planrun-build-<target>-, no human in the loop.
15// The build itself still runs through nx_sov_build_run, so admission, lease, cache, canon and every other
16// guard the build lane already has apply unchanged. Promotion is NOT queued here (a promote is a
17// deliberate act with a digest); read the planrun result, then promote.
18//
19// DL9 (deploy, 2026-09-02) bq_dedupe_target: the queue was MEASURED idempotent by id (231 rows, 231 distinct
20// ids, nx_store_put re-puts by id), so a second `add` of one target replaces the row rather than doubling it
21// -- and this organ now SAYS so (ALREADY-QUEUED) instead of printing a second QUEUED receipt that read like
22// a second row. The half of the rung that was genuinely open is CLOSE: a build that succeeds by another
23// door (a sync /api/build, a hand nx_sov_build_run) left the queued row alive, so the poller rebuilt the
24// same source on its next opening. `close <target> [rc]` marks the row closed with the reason, in place,
25// by id; the poller fires only `queued` rows, so a closed row can never fire. Nothing to close is a named
26// NO-ROW, never an error: a caller in a build lane must not fail because nobody had queued it.
27//
28// nx_buildq add <target> [floor_mb] [max_centiload] [--store <elf>] [--queue <prefix>] [--plan <prefix>]
29// nx_buildq close <target> [rc] [--store <elf>] [--queue <prefix>]
30//
31// Both writes go through nx_store_put (THE plane write verb, provenanced, revision-logged) -- forked,
32// never re-implemented. Fails CLOSED and LOUD: a refused seed prints the verb's own answer and exits 4.
33// The --store/--queue/--plan overrides exist for the gate (fixture planes under /tmp); production callers
34// never pass them.
35// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0
36import "nx_tool_run.nx"
37import "nx_syscalls.nx"
38
39const BQ_STORE_PUT_DEFAULT: *u8 = "/volume1/homes/elderwesto/nishihost/nx_store_put.elf"
40const BQ_PLAN_PREFIX_DEFAULT: *u8 = "knowledge/store/plan-build-"
41const BQ_QUEUE_PREFIX_DEFAULT: *u8 = "knowledge/store/deployq-"
42const BQ_ACTOR: *u8 = "nx_buildq"
43const BQ_STATUS_QUEUED: *u8 = "queued"
44const BQ_STATUS_CLOSED: *u8 = "closed"
45const BQ_CAP: i64 = 65536
46const BQ_LOAD_CAP: i64 = 1048576 // a whole-plane load: 231 rows measured at ~74 KB; 1 MiB holds 14x and the brim is announced
47const BQ_PATHCAP: i64 = 512
48const BQ_NOTECAP: i64 = 1024
49const BQ_ROW_FIELDS: i64 = 6 // id title precond status plan note
50const BQ_TAB: i64 = 9
51const BQ_NL: i64 = 10
52const BQ_EXIT_USAGE: i64 = 2
53const BQ_EXIT_REFUSED: i64 = 4
54// NO deadline on the store verb: nx_store_put serialises whole-store writers and under contention a
55// single put MEASURED ~90 s (2026-08-18). A 30 s box here killed a legitimate in-flight write and
56// reported REFUSED -- the verb owns its own locking and its own answer; this organ only relays it.
57
58func bq_w(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
59func bq_wn(v: i64) -> i64 {
60 let t: *u8 = sys_mmap(32); var m: i64 = v; var neg: i64 = 0
61 if m < 0 { neg = 1; m = 0 - m }
62 let d: *u8 = sys_mmap(32); var k: i64 = 0
63 if m == 0 { d[0] = 48 as u8; k = 1 }
64 while m > 0 { d[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
65 var o: i64 = 0
66 if neg == 1 { t[0] = 45 as u8; o = 1 }
67 var i: i64 = 0
68 while i < k { t[o] = d[k - 1 - i]; o = o + 1; i = i + 1 }
69 sys_write(1, t, o)
70 return 0
71}
72func bq_len(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
73func bq_streq(a: *u8, b: *u8) -> i64 {
74 var i: i64 = 0
75 while a[i] != (0 as u8) { if a[i] != b[i] { return 0 } i = i + 1 }
76 if b[i] != (0 as u8) { return 0 }
77 return 1
78}
79func bq_cat(dst: *u8, o: i64, s: *u8) -> i64 { var i: i64 = 0; var p: i64 = o; while s[i] != (0 as u8) { if p < BQ_PATHCAP - 1 { dst[p] = s[i]; p = p + 1 } i = i + 1 } dst[p] = 0 as u8; return p }
80func bq_catn(dst: *u8, o: i64, cap: i64, s: *u8) -> i64 { var i: i64 = 0; var p: i64 = o; while s[i] != (0 as u8) { if p < cap - 1 { dst[p] = s[i]; p = p + 1 } i = i + 1 } dst[p] = 0 as u8; return p }
81func bq_catnum(dst: *u8, o: i64, cap: i64, v: i64) -> i64 {
82 let d: *u8 = sys_mmap(32); var m: i64 = v; var k: i64 = 0
83 if m < 0 { m = 0 }
84 if m == 0 { d[0] = 48 as u8; k = 1 }
85 while m > 0 { d[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
86 var p: i64 = o
87 var i: i64 = 0
88 while i < k { if p < cap - 1 { dst[p] = d[k - 1 - i]; p = p + 1 } i = i + 1 }
89 dst[p] = 0 as u8
90 return p
91}
92// a target name is a bare organ basename: [A-Za-z0-9_] only, so it can never smuggle a path or a tab
93// into a plane row or a plan step (the same sanitizer shape /api/build applies).
94func bq_safe(s: *u8) -> i64 {
95 var i: i64 = 0
96 if s[0] == (0 as u8) { return 0 }
97 while s[i] != (0 as u8) {
98 let c: i64 = s[i] as i64
99 var ok: i64 = 0
100 if c >= 48 { if c <= 57 { ok = 1 } }
101 if c >= 65 { if c <= 90 { ok = 1 } }
102 if c >= 97 { if c <= 122 { ok = 1 } }
103 if c == 95 { ok = 1 }
104 if ok == 0 { return 0 }
105 i = i + 1
106 }
107 return 1
108}
109func bq_digits(s: *u8) -> i64 {
110 var i: i64 = 0
111 if s[0] == (0 as u8) { return 0 }
112 while s[i] != (0 as u8) { let c: i64 = s[i] as i64; if c < 48 { return 0 } if c > 57 { return 0 } i = i + 1 }
113 return 1
114}
115// fork nx_store_put with argv (null-terminated array), echo its answer, return its exit code
116func bq_put(store: *u8, av: *i64) -> i64 {
117 let out: *u8 = sys_mmap(BQ_CAP)
118 let olen: *i64 = sys_mmap(16) as *i64
119 let rc: i64 = tr_run_capture(store, av, out, BQ_CAP, olen)
120 if olen[0] > 0 { sys_write(1, out, olen[0]) }
121 return rc
122}
123// fork `nx_store_put <prefix> load`; the whole plane dump lands in buf (announces a brim, never trims silently)
124func bq_load(store: *u8, prefix: *u8, buf: *u8, cap: i64) -> i64 {
125 let av: *i64 = sys_mmap(8 * 4) as *i64
126 av[0] = store as i64
127 av[1] = prefix as i64
128 av[2] = "load" as *u8 as i64
129 av[3] = 0
130 let olen: *i64 = sys_mmap(16) as *i64
131 let rc: i64 = tr_run_capture(store, av, buf, cap, olen)
132 if rc != 0 { return 0 - 1 }
133 var n: i64 = olen[0]
134 if n < 0 { n = 0 }
135 if n >= cap - 1 { bq_w("BUILDQ BRIM: the plane load filled the capture; rows past the brim were NOT scanned\n" as *u8); n = cap - 1 }
136 buf[n] = 0 as u8
137 return n
138}
139// DL9 bq_dedupe_target: the row for <target> in a plane dump. Fills fields[0..5] (id title precond status plan
140// note, each NUL-terminated in its own BQ_NOTECAP cell) and returns 1 when a row with id BQ-<target> exists,
141// 0 when none does. A pure function of the dump text, so a tooth can drive it without a store.
142func bq_dedupe_target(dump: *u8, n: i64, target: *u8, fields: *u8) -> i64 {
143 let want: *u8 = sys_mmap(BQ_PATHCAP)
144 var wl: i64 = bq_cat(want, 0, "BQ-" as *u8)
145 wl = bq_cat(want, wl, target)
146 var i: i64 = 0
147 while i < n {
148 // one line [i, e)
149 var e: i64 = i
150 var scan: i64 = 1
151 while scan == 1 { if e >= n { scan = 0 } else { if (dump[e] as i64) == BQ_NL { scan = 0 } else { e = e + 1 } } }
152 // the id is the first tab-delimited field; it must equal want EXACTLY (BQ-x must not match BQ-xy)
153 var t: i64 = i
154 var s2: i64 = 1
155 while s2 == 1 { if t >= e { s2 = 0 } else { if (dump[t] as i64) == BQ_TAB { s2 = 0 } else { t = t + 1 } } }
156 var same: i64 = 0
157 if t - i == wl {
158 same = 1
159 var k: i64 = 0
160 while k < wl { if dump[i + k] != want[k] { same = 0 } k = k + 1 }
161 }
162 if same == 1 {
163 var f: i64 = 0
164 var s: i64 = i
165 var p: i64 = i
166 var go: i64 = 1
167 while go == 1 {
168 var cut: i64 = 0
169 if p >= e { cut = 1 } else { if (dump[p] as i64) == BQ_TAB { cut = 1 } }
170 if cut == 1 {
171 if f < BQ_ROW_FIELDS {
172 let cell: *u8 = ((fields as i64) + f * BQ_NOTECAP) as *u8
173 var c: i64 = 0
174 var q: i64 = s
175 while q < p { if c < BQ_NOTECAP - 1 { cell[c] = dump[q]; c = c + 1 } q = q + 1 }
176 cell[c] = 0 as u8
177 f = f + 1
178 }
179 s = p + 1
180 if p >= e { go = 0 }
181 }
182 p = p + 1
183 }
184 while f < BQ_ROW_FIELDS { let cz: *u8 = ((fields as i64) + f * BQ_NOTECAP) as *u8; cz[0] = 0 as u8; f = f + 1 }
185 return 1
186 }
187 i = e + 1
188 }
189 return 0
190}
191func bq_field(fields: *u8, k: i64) -> *u8 { return ((fields as i64) + k * BQ_NOTECAP) as *u8 }
192
193func bq_usage() -> i64 {
194 bq_w("usage: nx_buildq add <target> [floor_mb] [max_centiload] [--store <elf>] [--queue <prefix>] [--plan <prefix>] | close <target> [rc] [--store <elf>] [--queue <prefix>]\n" as *u8)
195 sys_exit(BQ_EXIT_USAGE)
196 return BQ_EXIT_USAGE
197}
198
199func main(argc: i64, argv: *i64) -> i64 {
200 if argc < 3 { return bq_usage() }
201 let verb: *u8 = argv[1] as *u8
202 var is_add: i64 = 0
203 var is_close: i64 = 0
204 if bq_streq(verb, "add" as *u8) == 1 { is_add = 1 }
205 if bq_streq(verb, "close" as *u8) == 1 { is_close = 1 }
206 if is_add + is_close == 0 { return bq_usage() }
207 let target: *u8 = argv[2] as *u8
208 if bq_safe(target) == 0 { bq_w("BUILDQ REFUSED: target must be a bare organ basename [A-Za-z0-9_]\n" as *u8); sys_exit(BQ_EXIT_REFUSED); return BQ_EXIT_REFUSED }
209 // positional numerics, then flags (the gate's fixture overrides; production never passes them)
210 var store: *u8 = BQ_STORE_PUT_DEFAULT
211 var qpfx: *u8 = BQ_QUEUE_PREFIX_DEFAULT
212 var ppfx0: *u8 = BQ_PLAN_PREFIX_DEFAULT
213 var floor: *u8 = "" as *u8
214 var maxl: *u8 = "" as *u8
215 var rcs: *u8 = "" as *u8
216 var npos: i64 = 0
217 var ai: i64 = 3
218 while ai < argc {
219 let a: *u8 = argv[ai] as *u8
220 var used: i64 = 0
221 if bq_streq(a, "--store" as *u8) == 1 { if ai + 1 < argc { store = argv[ai + 1] as *u8; ai = ai + 1 } used = 1 }
222 if bq_streq(a, "--queue" as *u8) == 1 { if ai + 1 < argc { qpfx = argv[ai + 1] as *u8; ai = ai + 1 } used = 1 }
223 if bq_streq(a, "--plan" as *u8) == 1 { if ai + 1 < argc { ppfx0 = argv[ai + 1] as *u8; ai = ai + 1 } used = 1 }
224 if used == 0 {
225 if bq_digits(a) == 0 { bq_w("BUILDQ REFUSED: numeric argument must be decimal digits: " as *u8); bq_w(a); bq_w("\n" as *u8); sys_exit(BQ_EXIT_REFUSED); return BQ_EXIT_REFUSED }
226 if is_add == 1 { if npos == 0 { floor = a } else { if npos == 1 { maxl = a } } }
227 if is_close == 1 { if npos == 0 { rcs = a } }
228 npos = npos + 1
229 }
230 ai = ai + 1
231 }
232 let rid: *u8 = sys_mmap(BQ_PATHCAP)
233 var r: i64 = bq_cat(rid, 0, "BQ-" as *u8)
234 r = bq_cat(rid, r, target)
235
236 if is_close == 1 {
237 // ---- close: mark the queued row closed, in place, by id -- never invent a row to close ----
238 let dump: *u8 = sys_mmap(BQ_LOAD_CAP)
239 let n: i64 = bq_load(store, qpfx, dump, BQ_LOAD_CAP)
240 if n < 0 { bq_w("BUILDQ REFUSED: the plane could not be loaded (see the verb's answer above)\n" as *u8); sys_exit(BQ_EXIT_REFUSED); return BQ_EXIT_REFUSED }
241 let fields: *u8 = sys_mmap(BQ_ROW_FIELDS * BQ_NOTECAP)
242 if bq_dedupe_target(dump, n, target, fields) == 0 {
243 bq_w("BUILDQ CLOSE NO-ROW id=" as *u8); bq_w(rid); bq_w(" -- nothing was queued for this target; nothing to close (not an error: a build lane must not fail because nobody queued it)\n" as *u8)
244 return 0
245 }
246 let st: *u8 = bq_field(fields, 3)
247 if bq_streq(st, BQ_STATUS_QUEUED) == 0 {
248 bq_w("BUILDQ CLOSE NOT-QUEUED id=" as *u8); bq_w(rid); bq_w(" status=" as *u8); bq_w(st); bq_w(" -- only a queued row is closed; a fired or closed row is left as its own record\n" as *u8)
249 return 0
250 }
251 let note: *u8 = sys_mmap(BQ_NOTECAP)
252 var no: i64 = bq_catn(note, 0, BQ_NOTECAP, "closed by nx_buildq close: a build of " as *u8)
253 no = bq_catn(note, no, BQ_NOTECAP, target)
254 no = bq_catn(note, no, BQ_NOTECAP, " succeeded by another door" as *u8)
255 if rcs[0] != (0 as u8) { no = bq_catn(note, no, BQ_NOTECAP, " rc=" as *u8); no = bq_catn(note, no, BQ_NOTECAP, rcs) }
256 no = bq_catn(note, no, BQ_NOTECAP, " at epoch " as *u8)
257 no = bq_catnum(note, no, BQ_NOTECAP, sys_now_realtime_sec())
258 no = bq_catn(note, no, BQ_NOTECAP, "; the queued row would have rebuilt the same source on the next opening (DL9 bq_dedupe_target)" as *u8)
259 let av: *i64 = sys_mmap(8 * 12) as *i64
260 av[0] = store as i64
261 av[1] = qpfx as i64
262 av[2] = "put" as *u8 as i64
263 av[3] = BQ_ACTOR as i64
264 av[4] = rid as i64
265 av[5] = bq_field(fields, 1) as i64
266 av[6] = bq_field(fields, 2) as i64
267 av[7] = BQ_STATUS_CLOSED as i64
268 av[8] = bq_field(fields, 4) as i64
269 av[9] = note as i64
270 av[10] = 0
271 bq_w("BUILDQ close " as *u8); bq_w(rid); bq_w(" queued -> closed\n" as *u8)
272 let rcc: i64 = bq_put(store, av)
273 if rcc != 0 { bq_w("BUILDQ REFUSED: close re-put failed (see the verb's answer above)\n" as *u8); sys_exit(BQ_EXIT_REFUSED); return BQ_EXIT_REFUSED }
274 bq_w("BUILDQ CLOSED id=" as *u8); bq_w(rid); bq_w(" -- the poller fires only queued rows, so this one can never fire\n" as *u8)
275 return 0
276 }
277
278 // ---- add ----
279 // DL9: say what the plane already holds before re-putting. A queued row for this target is REPLACED by id
280 // (the measured idempotence), and the receipt names it so a second QUEUED line never reads as a second row.
281 let dump0: *u8 = sys_mmap(BQ_LOAD_CAP)
282 let n0: i64 = bq_load(store, qpfx, dump0, BQ_LOAD_CAP)
283 if n0 >= 0 {
284 let f0: *u8 = sys_mmap(BQ_ROW_FIELDS * BQ_NOTECAP)
285 if bq_dedupe_target(dump0, n0, target, f0) == 1 {
286 bq_w("BUILDQ ALREADY-QUEUED id=" as *u8); bq_w(rid); bq_w(" status=" as *u8); bq_w(bq_field(f0, 3)); bq_w(" -- one row per target by id; this add REPLACES it, it does not add a second\n" as *u8)
287 }
288 }
289 // 1. the plan: one step, the sovereign build runner in build-only mode
290 let ppfx: *u8 = sys_mmap(BQ_PATHCAP)
291 var o: i64 = bq_cat(ppfx, 0, ppfx0)
292 o = bq_cat(ppfx, o, target)
293 o = bq_cat(ppfx, o, "-" as *u8)
294 let av1: *i64 = sys_mmap(8 * 10) as *i64
295 av1[0] = store as i64
296 av1[1] = ppfx as i64
297 av1[2] = "put" as *u8 as i64
298 av1[3] = BQ_ACTOR as i64
299 av1[4] = "1" as *u8 as i64
300 av1[5] = "nx_sov_build_run" as *u8 as i64
301 av1[6] = target as i64
302 av1[7] = "--build-only" as *u8 as i64
303 av1[8] = 0
304 bq_w("BUILDQ plan " as *u8); bq_w(ppfx); bq_w(" <- 1 nx_sov_build_run " as *u8); bq_w(target); bq_w(" --build-only\n" as *u8)
305 let rc1: i64 = bq_put(store, av1)
306 if rc1 != 0 { bq_w("BUILDQ REFUSED: plan seed failed (see the verb's answer above)\n" as *u8); sys_exit(BQ_EXIT_REFUSED); return BQ_EXIT_REFUSED }
307
308 // 2. the queue row: precondition headroom:[floor[:max]], plan build-<target>
309 let pre: *u8 = sys_mmap(BQ_PATHCAP)
310 var q: i64 = bq_cat(pre, 0, "headroom:" as *u8)
311 if floor[0] != (0 as u8) { q = bq_cat(pre, q, floor) }
312 if maxl[0] != (0 as u8) { q = bq_cat(pre, q, ":" as *u8); q = bq_cat(pre, q, maxl) }
313 let planid: *u8 = sys_mmap(BQ_PATHCAP)
314 var pl: i64 = bq_cat(planid, 0, "build-" as *u8)
315 pl = bq_cat(planid, pl, target)
316 let title: *u8 = sys_mmap(BQ_PATHCAP)
317 var t: i64 = bq_cat(title, 0, "queued build of " as *u8)
318 t = bq_cat(title, t, target)
319 t = bq_cat(title, t, " (fires on the first poller pass with build headroom)" as *u8)
320 let av2: *i64 = sys_mmap(8 * 12) as *i64
321 av2[0] = store as i64
322 av2[1] = qpfx as i64
323 av2[2] = "put" as *u8 as i64
324 av2[3] = BQ_ACTOR as i64
325 av2[4] = rid as i64
326 av2[5] = title as i64
327 av2[6] = pre as i64
328 av2[7] = BQ_STATUS_QUEUED as i64
329 av2[8] = planid as i64
330 av2[9] = "seeded by nx_buildq; result lands in knowledge/store/planrun-build-<target>-; promote deliberately afterwards; a build that succeeds by another door closes this row (nx_buildq close)" as *u8 as i64
331 av2[10] = 0
332 bq_w("BUILDQ queue " as *u8); bq_w(rid); bq_w(" precond=" as *u8); bq_w(pre); bq_w(" plan=" as *u8); bq_w(planid); bq_w("\n" as *u8)
333 let rc2: i64 = bq_put(store, av2)
334 if rc2 != 0 { bq_w("BUILDQ REFUSED: queue seed failed (see the verb's answer above)\n" as *u8); sys_exit(BQ_EXIT_REFUSED); return BQ_EXIT_REFUSED }
335 bq_w("BUILDQ QUEUED id=" as *u8); bq_w(rid); bq_w(" -- nx_orchestrate fires it on its next pass with headroom; read knowledge/store/planrun-build-" as *u8); bq_w(target); bq_w("- for the result\n" as *u8)
336 return 0
337}