code wiki / _hdl_build / nx_build_admit.nx

nx_build_admit.nx

buildroot/runtime/_hdl_build/nx_build_admit.nx

16307 B298 linesdepth 2pulls 2 transitivereach 0 importersview sourcekind tooltopic build
docsdependenciesstructsconstsfunctions

about

nx_build_admit.nx -- BUILD ADMISSION CONTROL (the missing gate that let the fleet wedge the host). INCIDENT 2026-07-20: ~10 concurrent sessions were compiling at once (registry grew 198->236 GREEN tools in ONE session). Every /api/build forks nx_cc_sovereign (549KB) on a memory-limited Synology and NOTHING serialized or admitted them -> the NAS went userspace-wedged (sshd could not complete a banner, DSM could not serve a page, every sovereign daemon refused TCP) and then off the network entirely. Measured, not guessed. nx_swarm_admit ALREADY documents itself as the gate "BEFORE any heavy launch (model decode, codec, image-gen, BIG BUILD)" -- but /api/build never called it. A compile IS a heavy launch. This organ is the build-shaped admission verdict, with ZERO deps beyond nx_syscalls so it can never itself be the thing that fails under load. LIAR-KILLED: every number is read live from /proc on the host being protected -- no estimate, no cache. MemAvailable from /proc/meminfo (the honest figure: reclaimable included, unlike MemFree) 1-minute load from /proc/loadavg, carried as CENTI-load (integer; no floats, sovereign law) nx_build_admit check [floor_mb] [max_centiload] exit 0 GRANT -- headroom exists, compile now exit 3 DENY-LOAD -- below the memory floor; compiling now risks wedging the HOST, not just the build exit 4 QUEUE -- load above the ceiling; hand to nx_orchestrate wait-for-opening and come back exit 2 usage | 5 unreadable /proc (fail-CLOSED: cannot measure => cannot admit) COMPOSES (does not duplicate): the QUEUE verdict is designed to be absorbed by nx_orchestrate's wait-for-opening deploy queue -- the same anti-collision primitive shipped this session, pointed at COMPUTE instead of deploys. The structural half is mgmt-owned: ma_do_build must consult this BEFORE forking the compiler (filed rung) -- until then this is the session-callable discipline half, same two-tier pattern as nx_route_diff/nx_tooldiff (detector live, enforcement filed). FAIL-CLOSED BY CONSTRUCTION: an unreadable /proc returns exit 5, never GRANT. A guard that cannot measure must refuse, never wave through -- the same law as an instrument that must not score bytes it did not fetch. ENVELOPE (declared in output): 64KB per /proc read; thresholds are NAMED CONSTS (rule-11) and argv-overridable. license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0

dependencies 1 imports · 0 importers

nx_syscalls.nx nx_build_admit.nx

imports: nx_syscalls.nx

imported by: nobody (leaf or entry point)

call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown

main ba_werr sys_write ba_slen sys_exit ba_uint_at ba_slen ↻ sys_mmap ba_read sys_openat_rd sys_read sys_close ba_find ba_slen ↻ ba_ncpu ba_centi_head ba_puts ba_puti sys_mmap ↻ ba_verdict sys_write ↻

structs

none

consts

32const BA_MEMINFO: *u8 = "/proc/meminfo" as *u8
33const BA_LOADAVG: *u8 = "/proc/loadavg" as *u8
34const BA_READCAP: i64 = 65536
35const BA_OUTCAP: i64 = 4096
39const BA_FLOOR_MB: i64 = 512
40const BA_MAX_CENTILOAD: i64 = 400
61const BA_STAT: *u8 = "/proc/stat" as *u8
64const BA_PROCSRUN_OFF: i64 = 13
65const BA_CENTI_PER_CPU: i64 = 100 // 1.00 x ncpu, in centi-load
66const BA_NCPU_FALLBACK: i64 = 4 // only if /proc/stat is unreadable; conservative, never unbounded
92const BA_KB_PER_MB: i64 = 1024
93const BA_CENTI: i64 = 100
94const BA_STDOUT: i64 = 1
95const BA_STDERR: i64 = 2
96const BA_ZERO: i64 = 48
97const BA_NINE: i64 = 57
98const BA_DOT: i64 = 46
99const BA_NL: i64 = 10
100const BA_SP: i64 = 32
101const BA_EXIT_USAGE: i64 = 2
102const BA_EXIT_DENY: i64 = 3
103const BA_EXIT_QUEUE: i64 = 4
104const BA_EXIT_UNREADABLE: i64 = 5

functions

69func ba_ncpu(buf: *u8, n: i64) -> i64
called by 1: main
116func ba_verdict(avail_mb: i64, floor_mb: i64, load1: i64, max_load: i64, procs_run: i64, ncpu: i64) -> i64
called by 1: main
123func ba_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
called by 3: ba_werrba_findmain
124func ba_werr(s: *u8) -> i64 { sys_write(BA_STDERR, s, ba_slen(s)); return 0 }
called by 1: main calls 2: sys_writeba_slen
125func ba_puts(b: *u8, off: i64, s: *u8) -> i64 { var o: i64 = off; var j: i64 = 0; while s[j] != (0 as u8) { b[o] = s[j]; o = o + 1; j = j + 1 } return o }
called by 1: main
126func ba_puti(b: *u8, off: i64, v: i64) -> i64
called by 1: main calls 1: sys_mmap
138func ba_read(path: *u8, buf: *u8, cap: i64) -> i64
called by 1: main calls 3: sys_openat_rdsys_readsys_close
148func ba_find(buf: *u8, n: i64, needle: *u8) -> i64
called by 1: main calls 1: ba_slen
162func ba_uint_at(buf: *u8, p: i64, n: i64) -> i64
called by 1: main
180func ba_centi_head(buf: *u8, n: i64) -> i64
called by 1: main
204func main(argc: i64, argv: *i64) -> i64