code wiki / _hdl_build / nx_undopath_gate.nx
nx_undopath_gate.nx
buildroot/runtime/_hdl_build/nx_undopath_gate.nx
about
nx_undopath_gate.nx -- proves nx_undopath_lib, and CENSUSES every deploy row's reverse gear.
THE THIRD QUESTION IN THE DEPLOY FAMILY. nx_deploycover_gate asks "is there a row at all";
nx_deploy_listen_gate asks "did the post-deploy check verify the INCOMING listener". This asks:
WHEN THE ROW'S REVERSE GEAR FIRES, DOES IT REVERSE THIS TARGET -- OR SOMEBODY ELSE'S?
It exists because on 2026-09-03 the answer was "somebody else's" for 16 of 31 rows: they declared
`rollback`, and cmd_rollback() takes no target argument -- it renames sites.elf.prev over sites.elf and
kills sites.elf. /api/deploy's health watchdog invokes that field, so a failed deploy of any of those
daemons would AUTOMATICALLY have reverted the public front door and left the bad daemon live.
ADVISORY ON THE CENSUS, HARD ON THE RULER. The pure classifier and the ratchet are teeth: they fail the
gate. The live census RATCHETS -- wrong-subject may only fall -- because a permanently-red detector is
one everybody learns to ignore, and because the honest remedy for a wrong row is a source change in the
control plane, not a blocked build. A RISE is RED and the baseline is NOT rewritten.
WHY IT COMPOSES md_resolve_target INSTEAD OF PARSING THE CONF ITSELF: that function IS the resolution
/api/deploy performs -- primary knowledge/hosting path, cwd fallback, and the compiled-in builtin rows.
A hand-rolled parser would measure a DIFFERENT SUBJECT than the deploy plane actually reads, which is
the exact wrong-subject error this gate exists to catch. The row NAMES are enumerated from the conf
(that is a list, not a resolution); every rb verb comes from the shipping resolver.
license_tier: ORIGINAL Read-only. No hw writes (Rule 26). expect_exit: 0
dependencies 5 imports · 0 importers
imports: nx_syscalls.nxnx_gate_verdict.nxnx_gatekit_lib.nxnx_undopath_lib.nxnx_mgmt_data.nx
imported by: nobody (leaf or entry point)
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| 29 | const UG_FX: *u8 = "/tmp/nx_undopath_gate" |
| 30 | const UG_FX_SRC: *u8 = "/tmp/nx_undopath_gate/fixture_hostctl.nx" |
| 31 | const UG_FX_ABSENT: *u8 = "/tmp/nx_undopath_gate/does-not-exist.nx" |
| 32 | const UG_FX_CONSTSRC: *u8 = "/tmp/nx_undopath_gate/fixture_consts.nx" |
| 35 | const UG_FX_CONSTBODY: *u8 = "const HC_GAMMA_LIVE: *u8 = \"/srv/nx_gamma.elf\"\nconst HC_GAMMA_PREV: *u8 = \"/srv/nx_gamma.elf.prev\"\nfunc cmd_gammarollback() -> i64 {\n let r: i64 = sys_renameat(HC_GAMMA_PREV, HC_GAMMA_LIVE)\n return r\n}\nfunc cmd_other() -> i64 { return 0 }\n" |
| 36 | const UG_FX_TRAILSRC: *u8 = "/tmp/nx_undopath_gate/fixture_trailing_comment.nx" |
| 41 | const UG_FX_TRAILBODY: *u8 = "const HC_KAPPA_LIVE: *u8 = \"/srv/nx_kappa.elf\"\nconst HC_KAPPA_PREV: *u8 = \"/srv/nx_kappa.elf.prev\"\nconst HC_LAMBDA_LIVE: *u8 = \"/srv/nx_lambda.elf\"\nfunc cmd_kapparollback() -> i64 {\n return sys_renameat(HC_KAPPA_PREV, HC_KAPPA_LIVE)\n}\n\n// LAMBDA deploy prep: the supervisor's HC_LAMBDA_LIVE guard then auto-launches it.\n// Idempotent and never-brick.\nfunc cmd_lambdadeploy() -> i64 {\n return 0\n}\n" |
| 42 | const UG_FX_PAIRSRC: *u8 = "/tmp/nx_undopath_gate/fixture_pair.nx" |
| 46 | const UG_FX_PAIRBODY: *u8 = "const HC_T_SOVNEW: *u8 = \"/nishihost/nx_theta.sov.elf.new\"\nconst HC_T_NEW: *u8 = \"/srv/app/nx_theta.elf.new\"\nconst HC_T_LIVE: *u8 = \"/srv/app/nx_theta.elf\"\nconst HC_T_PREV: *u8 = \"/srv/app/nx_theta.elf.prev\"\nconst HC_I_LIVE: *u8 = \"/srv/app/nx_iota.elf\"\nconst HC_I_PREV: *u8 = \"/srv/app/nx_iota.elf.prev\"\nfunc cmd_thetadeploy() -> i64 {\n hc_copyfile(HC_T_SOVNEW, HC_T_NEW)\n return hc_publish(HC_T_NEW, HC_T_LIVE)\n}\nfunc cmd_thetarollback() -> i64 {\n return sys_renameat(HC_T_PREV, HC_T_LIVE)\n}\nfunc cmd_iotarollback() -> i64 {\n return sys_renameat(HC_I_PREV, HC_I_LIVE)\n}\n" |
| 47 | const UG_HOSTCTL: *u8 = "buildroot/runtime/_hdl_build/nx_hostctl.nx" |
| 48 | const UG_HOSTCTL_B: *u8 = "runtime/_hdl_build/nx_hostctl.nx" |
| 49 | const UG_CONF: *u8 = "deploy_targets.conf" |
| 50 | const UG_CONF_B: *u8 = "knowledge/hosting/deploy_targets.conf" |
| 51 | const UG_RATCHET: *u8 = "knowledge/status/undopath.ratchet" |
| 52 | const UG_RATCHET_B: *u8 = "../knowledge/status/undopath.ratchet" |
| 53 | const UG_MODE: i64 = 420 |
| 57 | const UG_FX_BODY: *u8 = "func cmd_alpharollback() -> i64 {\n let r: i64 = sys_renameat(\"nx_alpha.elf.prev\" as *u8, \"nx_alpha.elf\" as *u8)\n return r\n}\nfunc cmd_betarollback() -> i64 {\n let r: i64 = sys_renameat(\"nx_beta.elf.prev\" as *u8, \"nx_beta.elf\" as *u8)\n return r\n}\n" |
| 59 | const UG_ROWCAP: i64 = 64 |
| 60 | const UG_NAMEW: i64 = 64 |
| 61 | const UG_PATHCAP: i64 = 512 |
| 62 | const UG_SMALL: i64 = 256 |
| 63 | const UG_CONFCAP: i64 = 65536 |
| 64 | const UG_SRCCAP: i64 = 1048576 |
| 65 | const UG_NL: i64 = 10 |
| 66 | const UG_HASH: i64 = 35 |
| 67 | const UG_SP: i64 = 32 |
functions
| 69 | func ug_slot(names: *u8, i: i64) -> *u8 { return ((names as i64) + i * UG_NAMEW) as *u8 } |
| 73 | func ug_row_names(path: *u8, names: *u8) -> i64 |
| 105 | func ug_read_src(a: *u8, b: *u8, box: *i64) -> *u8 |
| 111 | func ug_ratchet_read(a: *u8, b: *u8) -> i64 |
| 128 | func main(argc: i64, argv: *i64) -> i64 |