code wiki / _hdl_build / nx_job_run.nx

nx_job_run.nx

buildroot/runtime/_hdl_build/nx_job_run.nx

9918 B195 linesdepth 3pulls 4 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 3 imports · 0 importers

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

imports: nx_syscalls.nxnx_itoa_lib.nxnx_job_launch_bound.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 jlb_denied jlb_seg_prefix jlb_seg_starts jr_is_tmp jr_has_dotdot sys_mmap sys_read_file sys_openat_rd sys_lseek sys_mmap ↻ sys_read sys_close jr_slice_eq sys_openat_rd ↻ sys_close ↻ sys_fork sys_openat_wr sys_dup3 sys_execve jr_puts sys_write ↻ jr_slen ↻ jr_putn nxi_out nxi_fd sys_mmap ↻ ccz_cat_num sys_write ↻ sys_munmap

structs

none

consts

28const JR_MAGIC_1024: i64 = 1024
30const JR_OMODE: i64 = 0x1a4
31const JR_STDOUT: i64 = 1
32const JR_STDERR: i64 = 2
33const JR_MAXARGV: i64 = 32
34const JR_NL: i64 = 10
35const JR_TAB: i64 = 9
36const JR_HASH: i64 = 35

functions

38func jr_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
called by 2: jr_putsjr_werr
39func jr_puts(s: *u8) -> i64 { sys_write(JR_STDOUT, s, jr_slen(s)); return 0 }
called by 1: main calls 2: sys_writejr_slen
40func 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_putn(v: i64) -> i64 { nxi_out(v); return 0 }
called by 1: main calls 1: nxi_out
46func jr_slice_eq(buf: *u8, start: i64, end: i64, s: *u8) -> i64
called by 1: main
58func jr_contains(hay: *u8, needle: *u8) -> i64
72func jr_is_tmp(p: *u8) -> i64
called by 1: main
80func jr_has_dotdot(p: *u8) -> i64
called by 1: main
89func main(argc: i64, argv: *i64) -> i64