nx_artifactdrift_gate.nx
buildroot/runtime/nx_artifactdrift_gate.nx
about
nx_artifactdrift_gate.nx -- THE BITE PROOF FOR THE FORK-ROOT AXIS (2026-08-31).
WHY THIS GATE EXISTS. On 2026-08-31 a compare regen returned `published=201 fails=0 verdict=GREEN`
and published NOTHING: every one of the 201 lines reported prev= EQUAL to its new byte count. The
cause was a THIRD TWIN nobody was censusing -- nx_compare_regen chdirs into buildroot and forks the
BARE path `_offc/nx_swcompare_*.elf`, so buildroot/_offc is the copy the publisher actually executes,
and /api/promote never writes it. FOUR INDEPENDENT AGENTS each verified their promote against the
serving root and/or nishihost/_offc and all four missed it, because nx_catalog enumerates
SOURCE/BUILT/STAGED/PROMOTED/_offc and NOT buildroot/_offc -- so every row read BUILT==PROMOTED.
nx_artifactdrift grew a FORK-ROOT axis for exactly this. That axis had never been proven to go
SILENT. A detector that has only ever fired on real data is HALF verified: firing proves it can
speak, never that its silence means anything. A GREEN THAT NEVER HAD A CORRESPONDING RED IS
UNVERIFIED -- AND SO IS A RED THAT NEVER HAD A CORRESPONDING GREEN.
THIS GATE NEVER TOUCHES buildroot/_offc. The subject fork root is argv[7], overridable precisely
so a gate can point the axis at a FIXTURE tree. A gate that must perturb the directory the compare
publisher forks in order to report on it is a gate that can take the estate down to test itself.
Every fixture lives under /tmp/nx_artifactdrift_gate/ and the subject trend log is redirected
there too, so this can never append to knowledge/status/artifactdrift.log -- a gate must not share
its fixture with a production beat.
THREE LEGS, because the axis has three honest answers and all three must be proven:
RED a planted twin that differs -> FIRES and NAMES it, carrying BOTH byte counts
GREEN a byte-identical twin -> SILENT (FORK-STALE=0 and no offender line at all)
ABSTAIN a fork root it cannot open -> UNPROVEN, and must NOT report agreement
The GREEN leg additionally asserts the twin was EXAMINED (FORK-IDENTICAL=1): a zero from an EMPTY
directory is the gate-passes-on-the-empty-set defect, and would look exactly like a real green.
Exit carries the verdict via gv_verdict (0 GREEN / 1 RED / 3 SKIP).
license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0
dependencies 3 imports · 0 importers
imports: nx_gate_verdict.nxnx_gatekit_lib.nxnx_tool_run.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
| 41 | const AG_SUBJECT: *u8 = "./nx_artifactdrift.elf" |
| 42 | const AG_DIR: *u8 = "/tmp/nx_artifactdrift_gate" |
| 43 | const AG_A: *u8 = "/tmp/nx_artifactdrift_gate/forkA/" |
| 44 | const AG_B: *u8 = "/tmp/nx_artifactdrift_gate/forkB/" |
| 45 | const AG_BLIND: *u8 = "/tmp/nx_artifactdrift_gate/no_such_forkroot/" |
| 46 | const AG_LOG: *u8 = "/tmp/nx_artifactdrift_gate/drift_fixture.log" |
| 47 | const AG_ADIR: *u8 = "/tmp/nx_artifactdrift_gate/forkA" |
| 48 | const AG_BDIR: *u8 = "/tmp/nx_artifactdrift_gate/forkB" |
| 52 | const AG_REG: *u8 = "tool_allowlist.conf" |
| 53 | const AG_BROOT: *u8 = "buildroot/_build/" |
| 54 | const AG_SRCA: *u8 = "buildroot/runtime/_hdl_build/" |
| 55 | const AG_SRCB: *u8 = "buildroot/runtime/" |
| 56 | const AG_DECL: *u8 = "knowledge/status/drift_owner_declare.conf" |
| 63 | const AG_DONOR: *u8 = "nx_magic.elf" |
| 64 | const AG_VICTIM: *u8 = "nx_debtmine.elf" |
| 65 | const AG_ORPHAN: *u8 = "nx_zzz_gatefixture.elf" |
| 66 | const AG_PLANT: *u8 = "NOT-THE-SERVED-BYTES-planted-by-nx_artifactdrift_gate\n" |
| 68 | const AG_CAP: i64 = 1048576 // > 12x the ~82 KB the live census emits; truncation is ASSERTED, not assumed |
| 69 | const AG_MODE644: i64 = 420 |
| 70 | const AG_PATHBUF: i64 = 256 |
| 71 | const AG_LINEBUF: i64 = 1024 |
| 72 | const AG_NL: i64 = 10 |
functions
| 74 | func ag_path(dir: *u8, name: *u8) -> *u8 |
| 86 | func ag_copy(src: *u8, dst: *u8, buf: *u8, cap: i64) -> i64 |
| 98 | func ag_same(a: *u8, b: *u8, ba: *u8, bb: *u8, cap: i64) -> i64 |
| 112 | func ag_line_at(buf: *u8, n: i64, key: *u8, dst: *u8, cap: i64) -> i64 |
| 129 | func ag_run(forkp: *u8, out: *u8, cap: i64, ol: *i64) -> i64 |
| 143 | func main(argc: i64, argv: *i64) -> i64 |