code wiki / _hdl_build / nx_job_run.nx

nx_job_run.nx

buildroot/runtime/_hdl_build/nx_job_run.nx

14266 B261 linesdepth 4pulls 5 transitivereach 0 importersview sourcekind tooltopic job
docsdependenciesstructsconstsfunctions

about

nx_job_run.nx v3 -- GUARDED ASYNC JOB RUNNER. Eats the async-fetch >15s edge-timeout debt the good-form way: not a cron workaround, not an arbitrary executor. SAFE BY CONSTRUCTION (rule 26 never-brick / rule 12 boundary-defense) -- FOUR fail-closed gates: (1) CLASS: deny-by-class via nx_job_launch_bound -- WIDENED 2026-07-31, and this is exactly the "filed rung" the previous line named for itself. The old rule launched ONLY organs whose name contained *research_fetch*, which meant the ecosystem had NO route to run a general organ and every generator fell back to shell. Now: generators, rollups, censuses and page emitters are launchable; DAEMONS and SERVERS are refused (they never exit, so an async launch wedges the slot forever) and so is the CONTROL PLANE (deploy/promote/restart/kill/ mgmt/hostctl/supervisor). Fail-closed on an empty name. Deny-by-class, not allow-by-one- substring: a new generator is launchable the day it is allowlisted with no edit here, while a new daemon is refused by default -- a rule nothing must remember beats a list somebody must maintain. Proven by nx_job_launch_bound_gate 15/15 GREEN, including back-compat teeth for every organ the old *research_fetch* rule allowed. (2) VETTED: the name must resolve to a GREEN elf in tool_allowlist.conf -- the SAME trust boundary nx_plan_run uses; NEVER an arbitrary caller-supplied path. (3) NO-PIN-BYPASS: refuses pinned rows -- can never run a pinned elf with non-pinned args. (4) SCRATCH-ONLY: out-file confined to /tmp/ with no '..' -- writes land only on disposable scratch. Mechanism (mirrors nx_hostctl cmd_buildrun): fork -> child redirects stdout+stderr to out-file via sys_dup3 + execve the resolved elf with the caller's [args...]; PARENT returns IMMEDIATELY with a job handle (does NOT wait4) -> child is orphaned + reaped by init, runs to completion async while /mcp already answered -> a slow research-fetch no longer times out the edge. nx_job_run <tool-name(*research_fetch*)> <out-file:/tmp/...> [args...] -> JOB-STARTED pid=.. elf=.. out=.. license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0

dependencies 4 imports · 0 importers

nx_syscalls.nx nx_itoa_lib.nx nx_job_launch_bound.nx nx_jobcancel_lib.nx nx_job_run.nx

imports: nx_syscalls.nxnx_itoa_lib.nxnx_job_launch_bound.nxnx_jobcancel_lib.nx

imported by: nobody (leaf or entry point)

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

main jr_werr sys_write jr_slen sys_exit jr_slice_eq jr_slen ↻ jr_is_tmp jr_has_dotdot jc_conf_grace sys_mmap nxa_die sys_write ↻ sys_exit ↻ nxa_lock_take nxa_lock_addr sys_write ↻ nxa_lock_give nxa_lock_addr ↻ nxa_report_overrun sys_write ↻ nxa_dump_printable sys_write ↻ nxa_dump_sizes sys_write ↻ sys_read_file sys_openat_rd sys_lseek sys_mmap ↻ sys_read sys_munmap sys_close jc_slen jc_eq_n jc_slen ↻ jc_atoi_n sys_mmap ↻ jc_cancel sys_mmap ↻ jc_find

structs

none

consts

29const JR_MAGIC_1024: i64 = 1024
30const JR_VERB_CANCEL: *u8 = "cancel"
32const JR_OMODE: i64 = 0x1a4
33const JR_STDOUT: i64 = 1
34const JR_STDERR: i64 = 2
35const JR_MAXARGV: i64 = 32
36const JR_NL: i64 = 10
37const JR_TAB: i64 = 9
38const JR_HASH: i64 = 35

functions

40func jr_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
called by 3: jr_putsjr_werrmain
41func jr_puts(s: *u8) -> i64 { sys_write(JR_STDOUT, s, jr_slen(s)); return 0 }
called by 1: main calls 2: sys_writejr_slen
42func jr_werr(s: *u8) -> i64 { sys_write(JR_STDERR, s, jr_slen(s)); return 0 }
called by 1: main calls 2: sys_writejr_slen
45func jr_cat(d: *u8, off: i64, s: *u8) -> i64
called by 1: main
55func jr_putn(v: i64) -> i64 { nxi_out(v); return 0 }
called by 1: main calls 1: nxi_out
56func jr_slice_eq(buf: *u8, start: i64, end: i64, s: *u8) -> i64
called by 1: main
68func jr_contains(hay: *u8, needle: *u8) -> i64
82func jr_is_tmp(p: *u8) -> i64
called by 1: main
90func jr_has_dotdot(p: *u8) -> i64
called by 1: main
99func main(argc: i64, argv: *i64) -> i64