code wiki / _hdl_build / nx_novel_close.nx
nx_novel_close.nx source
↩ module page · 748 lines · 35495 B
1// nx_novel_close.nx -- the INDEPENDENT REFEREE that CLOSES genuinely-built NOVEL
2// queue rows that nx_reconcile refuses to touch (NOVEL is never auto-flipped by
3// design: novel work is judged after the visit). A NOVEL row whose deliverable is
4// really built+gated cannot otherwise close, so its dependents stay FLOATING in
5// nx_capability_ladder.
6//
7// This organ adjudicates each candidate MECHANICALLY -- it does NOT trust the row's
8// stored ||MARK. Referee check per candidate (an auto_builder-emitted deliverable):
9// DELETE the deliverable .nx + _test.nx -> re-run nx_auto_builder from its
10// build-spec -> assert ALL of: (a) BOTH files RE-EMITTED, (b) builder exit==0
11// AND stdout carries the candidate's green marker "AUTO-BUILD GREEN: <name>
12// shape=<N> KAT green", (c) line 1 of the re-emitted primary .nx carries
13// "AUTHORED BY THE NISHI BUILDER" (proves author=organ, not a hand-written
14// false-green). Only ALL-PASS closes the row. A stale/hand-written deliverable
15// cannot survive deletion -> strongest no-false-green probe. The organ is NOT the
16// builder, so there is NO self-grade: it re-runs the team's own auto_builder and
17// reads the verdict.
18//
19// NOVEL is 5 bytes, DONE is 4 -> closing SHRINKS the line by 1 byte, so this is a
20// LENGTH-CHANGING line REWRITE (reconcile only does same-length 4-byte in-place
21// patches). We read the whole file, and for a referee-PASSED candidate row scoped
22// by (field1==id AND field6=="NOVEL") emit the prefix, write "DONE", then the rest
23// from after "NOVEL" (skip 5 src bytes, write 4). NEVER global-replace "NOVEL"
24// (other rows' descriptions contain it); field6 is located by tab position.
25//
26// BAKED SELF-TEST runs FIRST on a SCRATCH scenario (control_pos via the proven erf
27// pipeline MUST close; control_neg via a non-existent spec MUST NOT close); any
28// mismatch -> print RED + nonzero exit, real queue UNTOUCHED. Proves it cannot
29// false-close (sibling of nx_capability_ladder / nx_epic_rollup baked controls).
30//
31// argv[1] = queue-path override (scratch queue for dry-run; no side effects
32// beyond that named file -- like reconcile's is_live guard). No-arg =>
33// LIVE: operates on knowledge/registry/assignment_queue.tsv (the only
34// run that writes the real queue) and writes a .bak first.
35//
36// SOVEREIGN ONLY (nx_cc->nxasm, no gcc/python/qemu). Additive/history-sacred: the
37// log is append-only; referee deletions are repaired by the re-emit (verified) or
38// restored from backup on FAIL. The referee execs /tmp/nx_auto_builder.sov.elf, so
39// the wrapper must build nx_auto_builder into /tmp in the SAME shell session.
40// license_tier: ORIGINAL
41//
42// module: nishi-core.autonomy.novel_close
43// depends: nishi-core.sys.syscalls
44// capability: NO_FLOAT_NOVEL_CLOSE_REFEREE
45import "nx_registry_lock.nx" // lib-only (pulls nx_syscalls transitively); gives rt_lock/rt_unlock + the SHARED queue lock
46import "nx_itoa_lib.nx" // shared MSB-first emitter (zero-alloc)
47const Q_MAGIC_262144: i64 = 262144
48const Q_MAGIC_65536: i64 = 65536
49const Q_MAGIC_4096: i64 = 4096
50
51const Q_CAP: i64 = 1048576
52const MAXCAND: i64 = 64
53
54func nc_w(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 }
55// MIGRATED to the shared emitter (debt 1785563586). The old body mmapped a scratch buffer
56// per call and never freed it. At PAGE granularity that is 4096B leaked PER CALL -- the
57// defect that took 28.5GB of a 36GB host in nx_ts_lumadiff (2MB input, ~3.66M calls).
58// nxi_* is MSB-first, allocates NOTHING, and emits identical bytes including the sign.
59func nc_wn(fd: i64, v: i64) -> i64 { nxi_fd(fd, v); return 0 }
60func nc_len(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
61
62// unlinkat(AT_FDCWD, path, 0) -- x86_64 raw 263 passes through (fsync/74 precedent).
63func nc_unlink(path: *u8) -> i64 { return __syscall(263, AT_FDCWD, path, 0, 0, 0, 0) }
64
65func nc_read(path: *u8, buf: *u8, cap: i64) -> i64 {
66 let fd: i64 = sys_openat_rd(path)
67 if fd < 0 { return 0 }
68 var n: i64 = 0
69 var r: i64 = sys_read(fd, buf, cap - 1)
70 while r > 0 { n = n + r; if n >= cap - 1 { r = 0 } else { r = sys_read(fd, buf + n, cap - 1 - n) } }
71 sys_close(fd)
72 return n
73}
74
75func nc_exists(path: *u8) -> i64 {
76 let fd: i64 = sys_openat_rd(path)
77 if fd < 0 { return 0 }
78 sys_close(fd)
79 return 1
80}
81
82func nc_write_all(fd: i64, buf: *u8, len: i64) -> i64 {
83 var off: i64 = 0
84 while off < len { let w: i64 = sys_write(fd, buf + off, len - off); if w <= 0 { off = len } else { off = off + w } }
85 return 0
86}
87
88// copy src -> dst (whole file). 1 ok / 0 fail.
89func nc_copy(src: *u8, dst: *u8) -> i64 {
90 let buf: *u8 = sys_mmap(Q_CAP)
91 let rf: i64 = sys_openat_rd(src)
92 if rf < 0 { return 0 }
93 var n: i64 = 0
94 var r: i64 = sys_read(rf, buf, Q_CAP - 1)
95 while r > 0 { n = n + r; if n >= Q_CAP - 1 { r = 0 } else { r = sys_read(rf, buf + n, Q_CAP - 1 - n) } }
96 sys_close(rf)
97 let wf: i64 = sys_openat_wr(dst, 0x1a4)
98 if wf < 0 { return 0 }
99 nc_write_all(wf, buf, n)
100 sys_close(wf)
101 return 1
102}
103
104// substring search in buf[0,n)
105func nc_contains(buf: *u8, n: i64, needle: *u8) -> i64 {
106 let nl: i64 = nc_len(needle)
107 if nl == 0 { return 1 }
108 var i: i64 = 0
109 while i + nl <= n {
110 var k: i64 = 0
111 var ok: i64 = 1
112 while k < nl { if buf[i+k] != needle[k] { ok = 0; k = nl } else { k = k + 1 } }
113 if ok == 1 { return 1 }
114 i = i + 1
115 }
116 return 0
117}
118
119// exact byte-match of pat (len pl) at buf+i
120func nc_at(buf: *u8, n: i64, i: i64, pat: *u8, pl: i64) -> i64 {
121 if i + pl > n { return 0 }
122 var k: i64 = 0
123 while k < pl { if buf[i+k] != pat[k] { return 0 } k = k + 1 }
124 return 1
125}
126
127// concat s into dst at off (null-terminates); returns new off
128func nc_cat(dst: *u8, off: i64, s: *u8) -> i64 {
129 var o: i64 = off; var i: i64 = 0
130 while s[i] != (0 as u8) { dst[o] = s[i]; o = o + 1; i = i + 1 }
131 dst[o] = 0 as u8
132 return o
133}
134func nc_path_d(dst: *u8, name: *u8) -> i64 {
135 var o: i64 = nc_cat(dst, 0, "runtime/_hdl_build/" as *u8); o = nc_cat(dst, o, name); o = nc_cat(dst, o, ".nx" as *u8); return o
136}
137func nc_path_t(dst: *u8, name: *u8) -> i64 {
138 var o: i64 = nc_cat(dst, 0, "runtime/_hdl_build/" as *u8); o = nc_cat(dst, o, name); o = nc_cat(dst, o, "_test.nx" as *u8); return o
139}
140
141// REFEREE RE-VERIFY: delete D+T -> exec /tmp/nx_auto_builder.sov.elf <spec>
142// (stdout -> /tmp/_nc_ab_out.log, stderr silenced) -> assert (a) BOTH re-emitted,
143// (b) exit==0 AND green marker in stdout, (c) AUTHORED-BY header on D line1.
144// Returns 1 PASS / 0 FAIL. On FAIL restores D+T from backup so a transient builder
145// failure never leaves a real capability deleted (additive / history-sacred).
146func nc_referee(name: *u8, spec: *u8, green: *u8) -> i64 {
147 let dpath: *u8 = sys_mmap(512); nc_path_d(dpath, name)
148 let tpath: *u8 = sys_mmap(512); nc_path_t(tpath, name)
149 let dbak: *u8 = "/tmp/_nc_d.bak" as *u8
150 let tbak: *u8 = "/tmp/_nc_t.bak" as *u8
151 let had_d: i64 = nc_exists(dpath); if had_d == 1 { nc_copy(dpath, dbak) }
152 let had_t: i64 = nc_exists(tpath); if had_t == 1 { nc_copy(tpath, tbak) }
153 // no-false-green probe: DELETE both deliverables
154 nc_unlink(dpath)
155 nc_unlink(tpath)
156 // re-run the team's auto_builder, stdout -> outlog, stderr -> /dev/null
157 let outlog: *u8 = "/tmp/_nc_ab_out.log" as *u8
158 let pid: i64 = sys_fork()
159 if pid == 0 {
160 let of: i64 = sys_openat_wr(outlog, 0x1a4)
161 if of >= 0 { sys_dup3(of, 1, 0) }
162 let dn: i64 = sys_openat_wr("/dev/null" as *u8, 0x1a4)
163 if dn >= 0 { sys_dup3(dn, 2, 0) }
164 let lane: *u8 = "/tmp/nx_auto_builder.sov.elf" as *u8
165 let argv: *i64 = sys_mmap(32) as *i64
166 argv[0] = lane as i64
167 argv[1] = spec as i64
168 argv[2] = 0
169 let envp: *i64 = sys_mmap(16) as *i64
170 envp[0] = 0
171 sys_execve(lane, argv, envp)
172 sys_exit(127)
173 }
174 let st: *i64 = sys_mmap(16) as *i64
175 sys_wait4(pid, st, 0)
176 let ec: i64 = wait_exit_code(st[0])
177 // (a) BOTH re-emitted
178 let re_d: i64 = nc_exists(dpath)
179 let re_t: i64 = nc_exists(tpath)
180 // (b) green marker in builder stdout
181 let outbuf: *u8 = sys_mmap(Q_MAGIC_262144)
182 let on: i64 = nc_read(outlog, outbuf, Q_MAGIC_262144)
183 let has_green: i64 = nc_contains(outbuf, on, green)
184 // (c) AUTHORED-BY header on line 1 of re-emitted D
185 var has_hdr: i64 = 0
186 if re_d == 1 {
187 let dbuf: *u8 = sys_mmap(Q_MAGIC_262144)
188 let dn2: i64 = nc_read(dpath, dbuf, Q_MAGIC_262144)
189 // line-1 length = bytes up to the first '\n' (the header must be on line 1).
190 var l1: i64 = 0
191 var nl: i64 = dn2
192 var s: i64 = 0
193 while s < dn2 { if dbuf[s] == (10 as u8) { nl = s; s = dn2 } else { s = s + 1 } }
194 l1 = nl
195 has_hdr = nc_contains(dbuf, l1, "AUTHORED BY THE NISHI BUILDER" as *u8)
196 }
197 var pass: i64 = 0
198 if re_d == 1 { if re_t == 1 { if ec == 0 { if has_green == 1 { if has_hdr == 1 { pass = 1 } } } } }
199 if pass == 0 {
200 if had_d == 1 { nc_copy(dbak, dpath) }
201 if had_t == 1 { nc_copy(tbak, tpath) }
202 }
203 return pass
204}
205
206// RUN-referee (for a NOVEL row whose deliverable is NOT auto_builder-emitted -- e.g. a
207// re-instrumented measurement organ like nx_cms_wp_scorecard). REBUILD+RUN the organ via
208// ./_offc/nx_sov_build_run.elf (independent: the closer is not the organ's author, and it
209// rebuilds from source + runs fresh -- no trust of stored state), capture stdout, and assert
210// BOTH the candidate's green substring AND "run-exit=0" appear. Returns 1 PASS / 0 FAIL.
211// No deletion/restore needed (it does not mutate the deliverable; it rebuilds it).
212func nc_referee_run(organ: *u8, green: *u8) -> i64 {
213 let outlog: *u8 = "/tmp/_nc_run_out.log" as *u8
214 let pid: i64 = sys_fork()
215 if pid == 0 {
216 let of: i64 = sys_openat_wr(outlog, 0x1a4)
217 if of >= 0 { sys_dup3(of, 1, 0) }
218 let dn: i64 = sys_openat_wr("/dev/null" as *u8, 0x1a4)
219 if dn >= 0 { sys_dup3(dn, 2, 0) }
220 let lane: *u8 = "./_offc/nx_sov_build_run.elf" as *u8
221 let argv: *i64 = sys_mmap(32) as *i64
222 argv[0] = lane as i64
223 argv[1] = organ as i64
224 argv[2] = 0
225 let envp: *i64 = sys_mmap(16) as *i64
226 envp[0] = 0
227 sys_execve(lane, argv, envp)
228 sys_exit(127)
229 }
230 let st: *i64 = sys_mmap(16) as *i64
231 sys_wait4(pid, st, 0)
232 let outbuf: *u8 = sys_mmap(Q_MAGIC_262144)
233 let on: i64 = nc_read(outlog, outbuf, Q_MAGIC_262144)
234 var pass: i64 = 0
235 if nc_contains(outbuf, on, green) == 1 {
236 if nc_contains(outbuf, on, "run-exit=0" as *u8) == 1 { pass = 1 }
237 }
238 return pass
239}
240
241// ---- helpers for the DEPS-DONE referee ----
242// exact equality of the field starting at fstart (bounded by next tab or line_end) to s[0,sl).
243func nc_field_eq(buf: *u8, fstart: i64, line_end: i64, s: *u8, sl: i64) -> i64 {
244 var fend: i64 = fstart
245 var d: i64 = 0
246 while d == 0 {
247 if fend >= line_end { d = 1 } else { if buf[fend] == (9 as u8) { d = 1 } else { fend = fend + 1 } }
248 }
249 if fend - fstart != sl { return 0 }
250 var k: i64 = 0
251 while k < sl { if buf[fstart+k] != s[k] { return 0 } k = k + 1 }
252 return 1
253}
254
255// does the dep field [dep_off, next-tab-or-line_end) contain id as a whole SPACE-separated
256// token? Handles single-dep (token == whole field) AND multi-dep ("A B C"); token-bounded so
257// "R4-H2-001" never substring-matches "R4-H2-0011" (the no-false-close guard for this referee).
258func nc_dep_has_token(buf: *u8, dep_off: i64, line_end: i64, id: *u8, idl: i64) -> i64 {
259 var dep_end: i64 = dep_off
260 var d: i64 = 0
261 while d == 0 {
262 if dep_end >= line_end { d = 1 } else { if buf[dep_end] == (9 as u8) { d = 1 } else { dep_end = dep_end + 1 } }
263 }
264 var ts: i64 = dep_off
265 var p: i64 = dep_off
266 var found: i64 = 0
267 while p <= dep_end {
268 var sep: i64 = 0
269 if p == dep_end { sep = 1 } else { if buf[p] == (32 as u8) { sep = 1 } }
270 if sep == 1 {
271 if p - ts == idl {
272 var k: i64 = 0
273 var eq: i64 = 1
274 while k < idl { if buf[ts+k] != id[k] { eq = 0; k = idl } else { k = k + 1 } }
275 if eq == 1 { found = 1 }
276 }
277 ts = p + 1
278 }
279 p = p + 1
280 }
281 return found
282}
283
284// DEPS-DONE referee: for a SPEC/umbrella NOVEL row with NO code deliverable (e.g. the HTTP/2
285// ladder spec R4-H2-001). The spec is "realized" exactly when EVERY queue row that names it
286// as a dep (field7) is DONE (field6). Mechanical: the closer SCANS the live queue and runs
287// NOTHING -- no organ, no self-grade. Requires >=1 child (never vacuously closes a childless
288// row). Returns 1 PASS (>=1 child, ALL DONE) / 0 FAIL. Reusable rule-11 for any umbrella/spec
289// row -> serves the no-float + anti-Frankenstein (X-GEN-005) law.
290func nc_referee_deps(id: *u8, qpath: *u8) -> i64 {
291 let buf: *u8 = sys_mmap(Q_CAP)
292 let n: i64 = nc_read(qpath, buf, Q_CAP)
293 if n <= 0 { return 0 }
294 let idl: i64 = nc_len(id)
295 var children: i64 = 0
296 var not_done: i64 = 0
297 var ls: i64 = 0
298 var i: i64 = 0
299 while i <= n {
300 var eol: i64 = 0
301 if i == n { eol = 1 } else { if buf[i] == (10 as u8) { eol = 1 } }
302 if eol == 1 {
303 if i > ls {
304 var tabs: i64 = 0
305 var p: i64 = ls
306 var st_off: i64 = 0 - 1
307 var dep_off: i64 = 0 - 1
308 while p < i {
309 if buf[p] == (9 as u8) {
310 tabs = tabs + 1
311 if tabs == 5 { st_off = p + 1 }
312 if tabs == 6 { dep_off = p + 1 }
313 }
314 p = p + 1
315 }
316 if dep_off >= 0 { if st_off >= 0 {
317 if nc_dep_has_token(buf, dep_off, i, id, idl) == 1 {
318 children = children + 1
319 if nc_field_eq(buf, st_off, i, "DONE" as *u8, 4) != 1 { not_done = not_done + 1 }
320 }
321 } }
322 }
323 ls = i + 1
324 }
325 i = i + 1
326 }
327 if children >= 1 { if not_done == 0 { return 1 } }
328 return 0
329}
330
331// FILECHECK referee (for a NOVEL row whose deliverable is a FETCHED/GENERATED FILE carrying a
332// content marker -- e.g. a research-substrate doc fetched by _dlr_fetch_one). Reads the file at
333// <path> (field3) and asserts it contains <anchor> (field4) -- the NOVEL-row twin of reconcile's
334// ||MARK file-content check (reconcile refuses NOVEL). A failed/blocked fetch writes no anchor
335// (error/empty page lacks the distinctive anchor) -> cannot false-close. Returns 1 PASS / 0 FAIL.
336func nc_referee_file(path: *u8, anchor: *u8) -> i64 {
337 let buf: *u8 = sys_mmap(Q_CAP)
338 let n: i64 = nc_read(path, buf, Q_CAP)
339 if n <= 0 { return 0 }
340 if nc_contains(buf, n, anchor) == 1 { return 1 }
341 return 0
342}
343
344// In queue buf, locate a line where field1==id AND field6=="NOVEL". On hit sets
345// *line_start to that line offset and returns 1; else 0. Exact full-field equality
346// (bounded by tabs), never prefix; field6 = char after the 5th tab.
347func nc_find_novel(buf: *u8, n: i64, id: *u8, line_start: *i64) -> i64 {
348 let idl: i64 = nc_len(id)
349 var ls: i64 = 0
350 var i: i64 = 0
351 while i <= n {
352 var eol: i64 = 0
353 if i == n { eol = 1 } else { if buf[i] == (10 as u8) { eol = 1 } }
354 if eol == 1 {
355 var f1ok: i64 = 0
356 if ls + idl < i {
357 if nc_at(buf, n, ls, id, idl) == 1 { if buf[ls+idl] == (9 as u8) { f1ok = 1 } }
358 }
359 if f1ok == 1 {
360 var tabs: i64 = 0
361 var p: i64 = ls
362 var fs: i64 = 0 - 1
363 while p < i {
364 if buf[p] == (9 as u8) { tabs = tabs + 1; if tabs == 5 { fs = p + 1; p = i } }
365 p = p + 1
366 }
367 if fs >= 0 {
368 if nc_at(buf, n, fs, "NOVEL\t" as *u8, 6) == 1 { *line_start = ls; return 1 }
369 }
370 }
371 ls = i + 1
372 }
373 i = i + 1
374 }
375 return 0
376}
377
378// Locate the field6 status start offset for the line at line_start (5th tab + 1).
379func nc_status_off(buf: *u8, n: i64, line_start: i64) -> i64 {
380 var p: i64 = line_start
381 var tabs: i64 = 0
382 while p < n {
383 if buf[p] == (10 as u8) { return 0 - 1 }
384 if buf[p] == (9 as u8) { tabs = tabs + 1; if tabs == 5 { return p + 1 } }
385 p = p + 1
386 }
387 return 0 - 1
388}
389
390// Close the candidate id in queue file qpath IFF currently NOVEL. Assumes referee
391// already PASSED. Whole-file rewrite: [0,sstart) + "DONE" + [sstart+5, n).
392// Returns 1 if a line was rewritten, else 0.
393func nc_write_close(qpath: *u8, id: *u8) -> i64 {
394 let buf: *u8 = sys_mmap(Q_CAP)
395 let n: i64 = nc_read(qpath, buf, Q_CAP)
396 if n <= 0 { return 0 }
397 let lsp: *i64 = sys_mmap(16) as *i64
398 lsp[0] = 0 - 1
399 if nc_find_novel(buf, n, id, lsp) != 1 { return 0 }
400 let sstart: i64 = nc_status_off(buf, n, lsp[0])
401 if sstart < 0 { return 0 }
402 if nc_at(buf, n, sstart, "NOVEL" as *u8, 5) != 1 { return 0 }
403 let wf: i64 = sys_openat_wr(qpath, 0x1a4)
404 if wf < 0 { return 0 }
405 nc_write_all(wf, buf, sstart)
406 nc_write_all(wf, "DONE" as *u8, 4)
407 nc_write_all(wf, buf + sstart + 5, n - sstart - 5)
408 sys_close(wf)
409 return 1
410}
411
412// Process the queue against a candidate set. For each candidate found NOVEL, run
413// the referee; on PASS, rewrite NOVEL->DONE and log. Re-reads the file fresh per
414// candidate (lengths shift after a close). Returns flips, or -1 if queue missing.
415func nc_process(qpath: *u8, ids: *i64, specs: *i64, names: *i64, greens: *i64,
416 ncand: i64, do_log: i64, lfd: i64) -> i64 {
417 let buf: *u8 = sys_mmap(Q_CAP)
418 let n0: i64 = nc_read(qpath, buf, Q_CAP)
419 if n0 <= 0 { return 0 - 1 }
420 var flips: i64 = 0
421 var c: i64 = 0
422 while c < ncand {
423 let id: *u8 = ids[c] as *u8
424 // fresh read each candidate
425 let qn: i64 = nc_read(qpath, buf, Q_CAP)
426 let lsp: *i64 = sys_mmap(16) as *i64
427 lsp[0] = 0 - 1
428 if nc_find_novel(buf, qn, id, lsp) == 1 {
429 let name: *u8 = names[c] as *u8
430 let spec: *u8 = specs[c] as *u8
431 let green: *u8 = greens[c] as *u8
432 // referee type (DATA-driven by spec field): "RUN" -> RUN-referee (rebuild+run
433 // organ=name); "DEPSDONE" -> DEPS-DONE referee (spec row closes when every row that
434 // deps on it is DONE); else REEMIT-referee (delete+re-emit auto_builder deliverable).
435 var is_run: i64 = 0
436 if nc_len(spec) == 3 { if spec[0] == (82 as u8) { if spec[1] == (85 as u8) { if spec[2] == (78 as u8) { is_run = 1 } } } }
437 var is_deps: i64 = 0
438 if nc_len(spec) == 8 { if spec[0] == (68 as u8) { if spec[1] == (69 as u8) { if spec[2] == (80 as u8) { if spec[3] == (83 as u8) { if spec[4] == (68 as u8) { if spec[5] == (79 as u8) { if spec[6] == (78 as u8) { if spec[7] == (69 as u8) { is_deps = 1 } } } } } } } } }
439 var is_file: i64 = 0
440 if nc_len(spec) == 9 { if spec[0] == (70 as u8) { if spec[1] == (73 as u8) { if spec[2] == (76 as u8) { if spec[3] == (69 as u8) { if spec[4] == (67 as u8) { if spec[5] == (72 as u8) { if spec[6] == (69 as u8) { if spec[7] == (67 as u8) { if spec[8] == (75 as u8) { is_file = 1 } } } } } } } } } }
441 var passr: i64 = 0
442 if is_run == 1 { passr = nc_referee_run(name, green) } else { if is_deps == 1 { passr = nc_referee_deps(id, qpath) } else { if is_file == 1 { passr = nc_referee_file(name, green) } else { passr = nc_referee(name, spec, green) } } }
443 if passr == 1 {
444 // serialize the live-queue RMW against the beat + other side-organs via the SHARED
445 // queue lock (qpath + ".lock"); degrade-gracefully on giveup (-1) so the close never
446 // wedges (O_EXCL stale-steal bounds a crashed holder to 30s). [nx_registry_lock]
447 let nclkp: *u8 = sys_mmap(512)
448 nc_cat(nclkp, nc_cat(nclkp, 0, qpath), ".lock" as *u8)
449 let nclkfd: i64 = rt_lock(nclkp)
450 if nc_write_close(qpath, id) == 1 {
451 flips = flips + 1
452 nc_w(1, "NOVELCLOSE-FLIP row=" as *u8); nc_w(1, id)
453 if is_run == 1 { nc_w(1, " referee=RUN-GREEN verdict=CLOSED\n" as *u8) } else { if is_deps == 1 { nc_w(1, " referee=DEPSDONE-GREEN verdict=CLOSED\n" as *u8) } else { if is_file == 1 { nc_w(1, " referee=FILECHECK-GREEN verdict=CLOSED\n" as *u8) } else { nc_w(1, " referee=REEMIT-GREEN verdict=CLOSED\n" as *u8) } } }
454 if do_log == 1 { if lfd >= 0 {
455 nc_w(lfd, "NOVELCLOSE row=" as *u8); nc_w(lfd, id)
456 if is_run == 1 { nc_w(lfd, " referee=RUN-GREEN verdict=CLOSED\n" as *u8) } else { if is_deps == 1 { nc_w(lfd, " referee=DEPSDONE-GREEN verdict=CLOSED\n" as *u8) } else { if is_file == 1 { nc_w(lfd, " referee=FILECHECK-GREEN verdict=CLOSED\n" as *u8) } else { nc_w(lfd, " referee=REEMIT-GREEN verdict=CLOSED\n" as *u8) } } }
457 } }
458 }
459 if nclkfd >= 0 { rt_unlock(nclkp, nclkfd) }
460 } else {
461 nc_w(1, "NOVELCLOSE-SKIP row=" as *u8); nc_w(1, id)
462 nc_w(1, " referee=FAIL (not closed, deliverable intact)\n" as *u8)
463 }
464 }
465 c = c + 1
466 }
467 return flips
468}
469
470// Load knowledge/registry/novel_close.tsv: lines "id<TAB>spec<TAB>name<TAB>green";
471// '#'-prefixed lines skipped. Fills parallel id/spec/name/green pools; returns count.
472func nc_load_candidates(ids: *i64, specs: *i64, names: *i64, greens: *i64) -> i64 {
473 let buf: *u8 = sys_mmap(Q_MAGIC_65536)
474 let n: i64 = nc_read("knowledge/registry/novel_close.tsv" as *u8, buf, Q_MAGIC_65536)
475 if n <= 0 { return 0 }
476 var cnt: i64 = 0
477 var ls: i64 = 0
478 var i: i64 = 0
479 while i <= n {
480 var eol: i64 = 0
481 if i == n { eol = 1 } else { if buf[i] == (10 as u8) { eol = 1 } }
482 if eol == 1 {
483 if i > ls { if buf[ls] != (35 as u8) {
484 if cnt < MAXCAND {
485 let fid: *u8 = sys_mmap(256)
486 let fsp: *u8 = sys_mmap(512)
487 let fnm: *u8 = sys_mmap(256)
488 let fgr: *u8 = sys_mmap(512)
489 var field: i64 = 0
490 var k: i64 = 0
491 var p: i64 = ls
492 while p < i {
493 if buf[p] == (9 as u8) { field = field + 1; k = 0 } else {
494 if field == 0 { fid[k] = buf[p]; fid[k+1] = 0 as u8 }
495 if field == 1 { fsp[k] = buf[p]; fsp[k+1] = 0 as u8 }
496 if field == 2 { fnm[k] = buf[p]; fnm[k+1] = 0 as u8 }
497 if field == 3 { fgr[k] = buf[p]; fgr[k+1] = 0 as u8 }
498 k = k + 1
499 }
500 p = p + 1
501 }
502 if field >= 3 {
503 ids[cnt] = fid as i64; specs[cnt] = fsp as i64
504 names[cnt] = fnm as i64; greens[cnt] = fgr as i64
505 cnt = cnt + 1
506 }
507 }
508 } }
509 ls = i + 1
510 }
511 i = i + 1
512 }
513 return cnt
514}
515
516// ===================== BAKED SELF-TEST =====================
517// control_pos: scratch queue NOVEL row SELFTEST-POS mapped to the PROVEN erf
518// pipeline (real spec/deliverable) -> referee GREEN -> MUST close (closed==1).
519// control_neg: scratch NOVEL row SELFTEST-NEG mapped to a NON-EXISTENT spec ->
520// auto_builder REFUSED (exit!=0, no green) -> MUST NOT close (closed==0).
521// Runs on /tmp scratch queues; the real erf deliverable is backed up + restored.
522func nc_write_scratch_queue(path: *u8, status_line: *u8) -> i64 {
523 let fd: i64 = sys_openat_wr(path, 0x1a4)
524 if fd < 0 { return 0 }
525 nc_w(fd, status_line)
526 sys_close(fd)
527 return 1
528}
529
530// self-sufficiency: the REEMIT referee/control execs the PREBUILT /tmp/nx_auto_builder.sov.elf
531// (the now-gone autorun daemon used to keep it fresh). Build it if absent (the tp_run "heal"
532// pattern) so nx_novel_close never refuses-live just because that artifact is missing. 1 if present.
533func nc_ensure_auto_builder() -> i64 {
534 if nc_exists("/tmp/nx_auto_builder.sov.elf" as *u8) == 1 { return 1 }
535 let pid: i64 = sys_fork()
536 if pid == 0 {
537 let dn: i64 = sys_openat_wr("/dev/null" as *u8, 0x1a4)
538 if dn >= 0 { sys_dup3(dn, 1, 0); sys_dup3(dn, 2, 0) }
539 let lane: *u8 = "./_offc/nx_sov_build_run.elf" as *u8
540 let argv: *i64 = sys_mmap(32) as *i64
541 argv[0] = lane as i64; argv[1] = "nx_auto_builder" as *u8 as i64; argv[2] = 0
542 let envp: *i64 = sys_mmap(16) as *i64; envp[0] = 0
543 sys_execve(lane, argv, envp)
544 sys_exit(127)
545 }
546 let st: *i64 = sys_mmap(16) as *i64
547 sys_wait4(pid, st, 0)
548 return nc_exists("/tmp/nx_auto_builder.sov.elf" as *u8)
549}
550
551func nc_selftest() -> i64 {
552 nc_ensure_auto_builder() // ensure the REEMIT control's prebuilt elf exists -> self-sufficient
553 let erf_d: *u8 = "runtime/_hdl_build/_ab_mk_erf.nx" as *u8
554 let erf_t: *u8 = "runtime/_hdl_build/_ab_mk_erf_test.nx" as *u8
555 let erf_d_bak: *u8 = "/tmp/_nc_st_erf_d.bak" as *u8
556 let erf_t_bak: *u8 = "/tmp/_nc_st_erf_t.bak" as *u8
557 let had_d: i64 = nc_exists(erf_d); if had_d == 1 { nc_copy(erf_d, erf_d_bak) }
558 let had_t: i64 = nc_exists(erf_t); if had_t == 1 { nc_copy(erf_t, erf_t_bak) }
559
560 let ids: *i64 = sys_mmap(8 * 4) as *i64
561 let specs: *i64 = sys_mmap(8 * 4) as *i64
562 let names: *i64 = sys_mmap(8 * 4) as *i64
563 let greens: *i64 = sys_mmap(8 * 4) as *i64
564
565 // ---- control_pos ----
566 let qp: *u8 = "/tmp/_nc_st_pos.tsv" as *u8
567 nc_write_scratch_queue(qp, "SELFTEST-POS\tX\t9\tM\tBuilder\tNOVEL\tnone\tgate\tselftest pos row\n" as *u8)
568 ids[0] = "SELFTEST-POS" as *u8 as i64
569 specs[0] = "runtime/_hdl_build/_ab_mk_erf.spec" as *u8 as i64
570 names[0] = "_ab_mk_erf" as *u8 as i64
571 greens[0] = "AUTO-BUILD GREEN: _ab_mk_erf shape=11 KAT green" as *u8 as i64
572 nc_process(qp, ids, specs, names, greens, 1, 0, 0 - 1)
573 let pbuf: *u8 = sys_mmap(Q_MAGIC_4096)
574 let pn: i64 = nc_read(qp, pbuf, Q_MAGIC_4096)
575 var pos_closed: i64 = 0
576 if nc_contains(pbuf, pn, "\tDONE\t" as *u8) == 1 { pos_closed = 1 }
577
578 // ---- control_neg ---- (non-existent spec -> referee FAIL -> no close)
579 let qn: *u8 = "/tmp/_nc_st_neg.tsv" as *u8
580 nc_write_scratch_queue(qn, "SELFTEST-NEG\tX\t9\tM\tBuilder\tNOVEL\tnone\tgate\tselftest neg row\n" as *u8)
581 ids[0] = "SELFTEST-NEG" as *u8 as i64
582 specs[0] = "knowledge/specs/_NO_SUCH_SPEC_selftest.spec" as *u8 as i64
583 names[0] = "_nc_selftest_neg" as *u8 as i64
584 greens[0] = "AUTO-BUILD GREEN: _nc_selftest_neg" as *u8 as i64
585 nc_process(qn, ids, specs, names, greens, 1, 0, 0 - 1)
586 let nbuf: *u8 = sys_mmap(Q_MAGIC_4096)
587 let nn: i64 = nc_read(qn, nbuf, Q_MAGIC_4096)
588 var neg_closed: i64 = 1
589 if nc_contains(nbuf, nn, "\tNOVEL\t" as *u8) == 1 { neg_closed = 0 }
590 if nc_contains(nbuf, nn, "\tDONE\t" as *u8) == 1 { neg_closed = 1 }
591
592 // ---- control_run_pos ---- (RUN-referee: organ emits the green -> MUST close)
593 let qrp: *u8 = "/tmp/_nc_st_runpos.tsv" as *u8
594 nc_write_scratch_queue(qrp, "SELFTEST-RUNPOS\tX\t9\tM\tBuilder\tNOVEL\tnone\tgate\tselftest run pos\n" as *u8)
595 ids[0] = "SELFTEST-RUNPOS" as *u8 as i64
596 specs[0] = "RUN" as *u8 as i64
597 names[0] = "nx_cms_wp_scorecard" as *u8 as i64
598 greens[0] = "verdict=MEASURED" as *u8 as i64
599 nc_process(qrp, ids, specs, names, greens, 1, 0, 0 - 1)
600 let rpbuf: *u8 = sys_mmap(Q_MAGIC_4096)
601 let rpn: i64 = nc_read(qrp, rpbuf, Q_MAGIC_4096)
602 var runpos_closed: i64 = 0
603 if nc_contains(rpbuf, rpn, "\tDONE\t" as *u8) == 1 { runpos_closed = 1 }
604
605 // ---- control_run_neg ---- (RUN-referee: green absent -> MUST NOT close)
606 let qrn: *u8 = "/tmp/_nc_st_runneg.tsv" as *u8
607 nc_write_scratch_queue(qrn, "SELFTEST-RUNNEG\tX\t9\tM\tBuilder\tNOVEL\tnone\tgate\tselftest run neg\n" as *u8)
608 ids[0] = "SELFTEST-RUNNEG" as *u8 as i64
609 specs[0] = "RUN" as *u8 as i64
610 names[0] = "nx_cms_wp_scorecard" as *u8 as i64
611 greens[0] = "ZZ_NEVER_APPEARS_RUNNEG" as *u8 as i64
612 nc_process(qrn, ids, specs, names, greens, 1, 0, 0 - 1)
613 let rnbuf: *u8 = sys_mmap(Q_MAGIC_4096)
614 let rnn: i64 = nc_read(qrn, rnbuf, Q_MAGIC_4096)
615 var runneg_closed: i64 = 1
616 if nc_contains(rnbuf, rnn, "\tNOVEL\t" as *u8) == 1 { runneg_closed = 0 }
617 if nc_contains(rnbuf, rnn, "\tDONE\t" as *u8) == 1 { runneg_closed = 1 }
618
619 // ---- control_deps_pos ---- (DEPS-DONE: spec row whose only child is DONE -> MUST close)
620 let qdp: *u8 = "/tmp/_nc_st_depspos.tsv" as *u8
621 nc_write_scratch_queue(qdp, "SPECPOS\tX\t9\tM\tPM\tNOVEL\t-\tspec\tumbrella spec row\nCHILDPOS\tX\t9\tM\tBuilder\tDONE\tSPECPOS\tgate\tchild built\n" as *u8)
622 ids[0] = "SPECPOS" as *u8 as i64
623 specs[0] = "DEPSDONE" as *u8 as i64
624 names[0] = "-" as *u8 as i64
625 greens[0] = "-" as *u8 as i64
626 nc_process(qdp, ids, specs, names, greens, 1, 0, 0 - 1)
627 let dpbuf: *u8 = sys_mmap(Q_MAGIC_4096)
628 let dpn: i64 = nc_read(qdp, dpbuf, Q_MAGIC_4096)
629 let dplsp: *i64 = sys_mmap(16) as *i64
630 dplsp[0] = 0 - 1
631 var deps_pos_closed: i64 = 0
632 if nc_find_novel(dpbuf, dpn, "SPECPOS" as *u8, dplsp) == 0 { deps_pos_closed = 1 }
633
634 // ---- control_deps_neg ---- (DEPS-DONE: spec row whose child is still NOVEL -> MUST NOT close)
635 let qdn2: *u8 = "/tmp/_nc_st_depsneg.tsv" as *u8
636 nc_write_scratch_queue(qdn2, "SPECNEG\tX\t9\tM\tPM\tNOVEL\t-\tspec\tumbrella spec row\nCHILDNEG\tX\t9\tM\tBuilder\tNOVEL\tSPECNEG\tgate\tchild not built\n" as *u8)
637 ids[0] = "SPECNEG" as *u8 as i64
638 specs[0] = "DEPSDONE" as *u8 as i64
639 names[0] = "-" as *u8 as i64
640 greens[0] = "-" as *u8 as i64
641 nc_process(qdn2, ids, specs, names, greens, 1, 0, 0 - 1)
642 let dnbuf: *u8 = sys_mmap(Q_MAGIC_4096)
643 let dnn2: i64 = nc_read(qdn2, dnbuf, Q_MAGIC_4096)
644 let dnlsp: *i64 = sys_mmap(16) as *i64
645 dnlsp[0] = 0 - 1
646 var deps_neg_closed: i64 = 0
647 if nc_find_novel(dnbuf, dnn2, "SPECNEG" as *u8, dnlsp) == 0 { deps_neg_closed = 1 }
648
649 // ---- control_file_pos ---- (FILECHECK: deliverable file carries anchor -> MUST close)
650 let qfp: *u8 = "/tmp/_nc_st_filepos.tsv" as *u8
651 nc_write_scratch_queue(qfp, "FILEPOS\tX\t9\tM\tResearcher\tNOVEL\t-\tgate\tfile pos row\n" as *u8)
652 nc_write_scratch_queue("/tmp/_nc_st_file_pos.txt" as *u8, "header line\nWhen MARKER appears here exactly\nfooter line\n" as *u8)
653 ids[0] = "FILEPOS" as *u8 as i64
654 specs[0] = "FILECHECK" as *u8 as i64
655 names[0] = "/tmp/_nc_st_file_pos.txt" as *u8 as i64
656 greens[0] = "When MARKER appears here exactly" as *u8 as i64
657 nc_process(qfp, ids, specs, names, greens, 1, 0, 0 - 1)
658 let fpbuf: *u8 = sys_mmap(Q_MAGIC_4096)
659 let fpn: i64 = nc_read(qfp, fpbuf, Q_MAGIC_4096)
660 var file_pos_closed: i64 = 0
661 if nc_contains(fpbuf, fpn, "\tDONE\t" as *u8) == 1 { file_pos_closed = 1 }
662
663 // ---- control_file_neg ---- (FILECHECK: anchor absent in file -> MUST NOT close)
664 let qfn2: *u8 = "/tmp/_nc_st_fileneg.tsv" as *u8
665 nc_write_scratch_queue(qfn2, "FILENEG\tX\t9\tM\tResearcher\tNOVEL\t-\tgate\tfile neg row\n" as *u8)
666 nc_write_scratch_queue("/tmp/_nc_st_file_neg.txt" as *u8, "header line\nno marker present at all here\nfooter line\n" as *u8)
667 ids[0] = "FILENEG" as *u8 as i64
668 specs[0] = "FILECHECK" as *u8 as i64
669 names[0] = "/tmp/_nc_st_file_neg.txt" as *u8 as i64
670 greens[0] = "ZZ_NEVER_IN_FILE_NEG" as *u8 as i64
671 nc_process(qfn2, ids, specs, names, greens, 1, 0, 0 - 1)
672 let fnbuf: *u8 = sys_mmap(Q_MAGIC_4096)
673 let fnn2: i64 = nc_read(qfn2, fnbuf, Q_MAGIC_4096)
674 var file_neg_closed: i64 = 1
675 if nc_contains(fnbuf, fnn2, "\tNOVEL\t" as *u8) == 1 { file_neg_closed = 0 }
676 if nc_contains(fnbuf, fnn2, "\tDONE\t" as *u8) == 1 { file_neg_closed = 1 }
677
678 // restore the real erf deliverable regardless (history sacred)
679 if had_d == 1 { nc_copy(erf_d_bak, erf_d) }
680 if had_t == 1 { nc_copy(erf_t_bak, erf_t) }
681
682 nc_w(1, "SELFTEST control_pos=" as *u8); nc_wn(1, pos_closed)
683 nc_w(1, " control_neg=" as *u8); nc_wn(1, neg_closed)
684 nc_w(1, " control_run_pos=" as *u8); nc_wn(1, runpos_closed)
685 nc_w(1, " control_run_neg=" as *u8); nc_wn(1, runneg_closed)
686 nc_w(1, " control_deps_pos=" as *u8); nc_wn(1, deps_pos_closed)
687 nc_w(1, " control_deps_neg=" as *u8); nc_wn(1, deps_neg_closed)
688 nc_w(1, " control_file_pos=" as *u8); nc_wn(1, file_pos_closed)
689 nc_w(1, " control_file_neg=" as *u8); nc_wn(1, file_neg_closed)
690 var allok: i64 = 0
691 if pos_closed == 1 { if neg_closed == 0 { if runpos_closed == 1 { if runneg_closed == 0 { if deps_pos_closed == 1 { if deps_neg_closed == 0 { if file_pos_closed == 1 { if file_neg_closed == 0 { allok = 1 } } } } } } } }
692 if allok == 1 { nc_w(1, " verdict=GREEN\n" as *u8); return 1 }
693 nc_w(1, " verdict=RED\n" as *u8)
694 return 0
695}
696
697func main(argc: i64, argv: *i64) -> i64 {
698 // 1) BAKED SELF-TEST FIRST -- abort (no real-queue write) on any control mismatch.
699 if nc_selftest() == 0 {
700 nc_w(1, "NOVELCLOSE verdict=RED reason=selftest-failed (real queue UNTOUCHED)\n" as *u8)
701 sys_exit(7); return 7
702 }
703
704 // 2) target queue + live-ness
705 var qp: *u8 = "knowledge/registry/assignment_queue.tsv" as *u8
706 var is_live: i64 = 1
707 if argc >= 2 { qp = argv[1] as *u8; is_live = 0 }
708
709 // 3) LIVE run: write .bak of the real queue BEFORE any mutation
710 if is_live == 1 {
711 nc_copy("knowledge/registry/assignment_queue.tsv" as *u8,
712 "knowledge/registry/assignment_queue.tsv.bak" as *u8)
713 }
714
715 // 4) load DATA candidate table
716 let ids: *i64 = sys_mmap(8 * MAXCAND) as *i64
717 let specs: *i64 = sys_mmap(8 * MAXCAND) as *i64
718 let names: *i64 = sys_mmap(8 * MAXCAND) as *i64
719 let greens: *i64 = sys_mmap(8 * MAXCAND) as *i64
720 let ncand: i64 = nc_load_candidates(ids, specs, names, greens)
721 nc_w(1, "NOVELCLOSE candidates=" as *u8); nc_wn(1, ncand)
722 nc_w(1, " queue=" as *u8); nc_w(1, qp)
723 if is_live == 1 { nc_w(1, " mode=LIVE\n" as *u8) } else { nc_w(1, " mode=DRYRUN\n" as *u8) }
724
725 // 5) durable log (append-only) -- only LIVE runs append durable history
726 var lfd: i64 = 0 - 1
727 var do_log: i64 = 0
728 if is_live == 1 {
729 lfd = sys_openat_append("knowledge/status/novel_close.log" as *u8, 0x1a4)
730 do_log = 1
731 }
732
733 let flips: i64 = nc_process(qp, ids, specs, names, greens, ncand, do_log, lfd)
734 if flips < 0 {
735 nc_w(1, "NOVELCLOSE verdict=RED reason=queue-missing\n" as *u8)
736 sys_exit(101); return 101
737 }
738
739 nc_w(1, "NOVELCLOSE closed=" as *u8); nc_wn(1, flips)
740 nc_w(1, " verdict=GREEN epoch=" as *u8); nc_wn(1, sys_now_realtime_sec()); nc_w(1, "\n" as *u8)
741 if do_log == 1 { if lfd >= 0 {
742 nc_w(lfd, "NOVELCLOSE closed=" as *u8); nc_wn(lfd, flips)
743 nc_w(lfd, " verdict=GREEN epoch=" as *u8); nc_wn(lfd, sys_now_realtime_sec()); nc_w(lfd, "\n" as *u8)
744 sys_close(lfd)
745 } }
746 sys_exit(0)
747 return 0
748}