code wiki / _hdl_build / nx_builddeploy_lib.nx

nx_builddeploy_lib.nx

buildroot/runtime/_hdl_build/nx_builddeploy_lib.nx

9146 B159 linesdepth 0pulls 0 transitivereach 32 importersview sourcekind librarytopic builddeploy
docsdependenciesstructsconstsfunctions

about

nx_builddeploy_lib.nx -- THE ONE RULER FOR "MAY THIS BUILD WRITE A CONSUMER-VISIBLE BINARY?" WHY THIS EXISTS. nx_sov_build_run decides, inline and in three scattered places, whether a successful build ALSO replaces the binary consumers fork. Those guards were written on three different days for three different incidents -- toolchain (rule 26), the daemon supervisor-respawn class, and now the queued-build class -- and each only ever covered the case that motivated it. A LAW APPLIED IN ONE VERB AND NOT ITS SIBLING IS HALF A LAW: the flag literally named --build-only was never part of the decision at all, so it built AND deployed, and nothing in the estate could test that it did. MEASURED 2026-08-26 from the queue's OWN artifact (knowledge/store/planrun-build-nx_gate_roster_run-): [nx_sov_build_run] nx_gate_roster_run: DEPLOYED to serving root (twin refresh, live for the next fork) -> ../nx_gate_roster_run.elf That row was seeded by /api/build's own load-refusal path: nx_mgmt_api ma_build_refusal_body forks nx_job_run nx_buildq add, and nx_buildq seeds the plan step "nx_sov_build_run <target> --build-only". The refusal receipt tells the caller the result "lands in knowledge/store/planrun-build-<target>-; promote deliberately afterwards". By the time the caller reads that row the binary is ALREADY LIVE: no nx_contentdiff, no nx_behaveprobe, no capability-loss check, no .prev bank. A CALLER TOLD ITS WORK WAS MERELY DEFERRED HAD ITS SERVING BINARY REPLACED, WITH NO SEAT IN THE LOOP. THE HIDDEN VARIABLE IS THE CALLER'S WORKING DIRECTORY, AND IT IS WHY THIS SURVIVED SO LONG. The same binary, the same flag and the same target deploy or do not deploy depending only on where the caller stood. /api/build (nx_hostctl cmd_buildrun) chdir's INTO buildroot before exec, so the builder's CWD anchor never fires, root_pfx stays empty, the twin probe asks for buildroot/<name>.elf -- which does not exist -- and nothing is installed, which is why the build/promote split has held there and why hundreds of BEHIND rows exist on the drift board. The queue's runner starts in the SERVING ROOT, the anchor fires, root_pfx becomes "../", and the identical command deploys. The "../" in the receipt above is the PROOF the anchor fired: no other branch can emit that prefix. A FLAG WHOSE MEANING DEPENDS ON THE CALLER'S CWD CANNOT BE REASONED ABOUT FROM ITS NAME. WHAT THIS LIB IS. A pure integer decision -- no I/O, no paths, no forks -- so a gate holds every combination of its inputs with a fixture instead of reproducing a host state. The CALLER keeps its probes (does a twin exist, is this a toolchain, is this a declared daemon); this owns the JUDGEMENT. Because there is only ONE of it, the queued lane and the seat lane cannot disagree. SCOPE STATED HONESTLY -- WHAT THIS DELIBERATELY DOES NOT CHANGE: (1) dkind < 0 (organ_kind.conf unreadable, so daemon-ness UNPROVEN) still permits a serving-root write on the DEFAULT path, exactly as the incumbent does, and the caller still warns. That is an abstention-that-acquits and it is a real residual, but it is a DIFFERENT lane from this one and narrowing it would change the default build path for every caller. It is encoded faithfully here and pinned by its own tooth so the next reader adjudicates it instead of inheriting it silently.

dependencies 0 imports · 10 importers

nx_builddeploy_lib.nx nx_builddeploy_gate.nx nx_builddeploy_gate_t146.nx nx_mgmt_api.nx nx_mgmt_api_search_candidate_t330. nx_mgmt_api_toolchain_session_2026 nx_mgmt_cap_candidate_t186.nx nx_mgmt_deploy_candidate_t185.nx nx_sbr_admission_candidate.nx nx_sbr_key_candidate.nx nx_sov_build_run.nx

imports: none

imported by: nx_builddeploy_gate.nxnx_builddeploy_gate_t146.nxnx_mgmt_api.nxnx_mgmt_api_search_candidate_t330.nxnx_mgmt_api_toolchain_session_20260910.nxnx_mgmt_cap_candidate_t186.nxnx_mgmt_deploy_candidate_t185.nxnx_sbr_admission_candidate.nxnx_sbr_key_candidate.nxnx_sov_build_run.nx

structs

none

consts

46const BD_LOC_NONE: i64 = 0
47const BD_LOC_OFFC: i64 = 1
48const BD_LOC_ROOT: i64 = 2
51const BD_WHY_TOOLCHAIN: i64 = 1 // rule 26: only /api/promote_toolchain may move the toolchain
52const BD_WHY_BUILD_ONLY: i64 = 2 // the caller said build only, so this build installs nothing
53const BD_WHY_FORCE: i64 = 3 // --install: explicit, deliberate intent to make it permanent
54const BD_WHY_REFRESH: i64 = 4 // refresh-IF-PRESENT (LM-026): a twin exists and is being kept fresh
55const BD_WHY_NO_TWIN: i64 = 5 // nothing consumes this name yet; nothing to refresh

functions

61func bd_intent_permits_install(build_only: i64, force_install: i64) -> i64
68func bd_locations(has_offc: i64, has_root: i64, force_install: i64, build_only: i64, toolchain: i64, dkind: i64) -> i64
86func bd_writes_offc(loc: i64) -> i64 { if (loc & BD_LOC_OFFC) != 0 { return 1 } return 0 }
87func bd_writes_root(loc: i64) -> i64 { if (loc & BD_LOC_ROOT) != 0 { return 1 } return 0 }
90func bd_why(has_offc: i64, has_root: i64, force_install: i64, build_only: i64, toolchain: i64, dkind: i64) -> i64
102func bd_root_held(has_root: i64, force_install: i64, build_only: i64, toolchain: i64, dkind: i64) -> i64
112func bd_qualification_mode(qualify:i64, build_only:i64, force_install:i64)->i64
called by 3: mainmainmain
118func bd_qualification_flag(flag:*u8)->i64
126func bd_flag_equal(flag:*u8,wanted:*u8)->i64
called by 1: bd_lane_flag_known
132func bd_lane_flag_known(flag:*u8)->i64
143func bd_run_timeout_flag(flag:*u8)->i64
called by 1: main
150func bd_positive_ms(s:*u8)->i64
called by 3: mainmainmain