code wiki / _hdl_build / nx_contentdiff_lib.nx
nx_contentdiff_lib.nx
buildroot/runtime/_hdl_build/nx_contentdiff_lib.nx
about
nx_contentdiff_lib.nx -- ONE CONTENT RULER, TWO BUDGETS.
THE RULER (lifted verbatim in semantics from nx_contentdiff.nx, whose reasoning stands): every
printable run of >= minlen bytes in the LIVE binary must still be findable somewhere in the
CANDIDATE's RAW BYTES. A missing run is a content difference requiring review, not proof of
destroyed behavior. Conversely, retained strings do not establish behavioral equivalence.
Structured ELF comparison below respects validated DWARF string boundaries; the raw API retains its contract.
WHY SIZE CANNOT DO THIS JOB, measured twice by the organ this lib is extracted from: SHRINK is not
regression (16 live organs had LARGER .prev files yet the smaller live binaries were string
SUPERSETS), and GROWTH is not improvement (nx_law_warden GREW 161951 -> 186696 bytes while losing
three whole detectors). A gate keyed on bytes is wrong about half the time and cannot tell you which
half. Re-measured on the live deploy root 2026-08-06: 22 of 89 staged artifacts with a live
counterpart would drop live runs, and several of those are LARGER than what they replace.
WHY IT IS A LIB (2026-08-06): the ruler existed only inside nx_contentdiff's main() -- a CLI oracle
with no deployed binary, no registry row, and therefore no consumer. The debt that named it
(1785531571) asked for it to be wired into /api/promote; nothing could, because there was nothing
importable to wire. A ruler that only a main() can reach is not a capability the fleet has.
TWO BUDGETS, ONE IMPLEMENTATION (Rule 15). The CLI oracle runs to completion and can afford to check
EVERY run; the promote guard runs inside a live deploy call and must bound its work. Those are
different BUDGETS, not different rulers -- so the budget is a PARAMETER and the semantics are shared.
Two rulers that can disagree about the same question is the defect this file exists to prevent.
DIALECT: reachable from nx_mgmt_data -> nx_mgmt_api, so plain-if (NO else), no empty string literals,
<=6 params.
license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0
dependencies 2 imports · 11 importers
diagram shows first 10 each side; +0 more imports, +1 more importers in the complete lists below.
imports: nx_syscalls.nxnx_elf_read.nx
imported by: nx_contentdiff.nxnx_contentdiff_display_20260907.nxnx_contentdiff_export.nxnx_contentdiff_gate.nxnx_contentdiff_iterator_gate_t295.nxnx_contentdiff_sectionless_candidate_t314.nxnx_contentdiff_sectionless_gate_t314.nxnx_contentdiff_structured_candidate_t294.nxnx_contentdiff_typed_candidate_t309.nxnx_staging_guard.nxnx_staging_guard_candidate_t296.nx
structs
| 318 | struct NxCdStructured {buf:*u8,bytes:i64,marks:*u8,at:i64,end:i64,error:i64,files:i64,sections:i64} |
| 477 | struct NxCdResult {state:i64,runs:i64,checked:i64,lost:i64,source_removed:i64,source_added:i64} |
| 479 | struct NxCdSpan {offset:i64,length:i64,kind:i64} |
consts
| 32 | const CDL_PRINT_LO: i64 = 32 |
| 33 | const CDL_PRINT_HI: i64 = 126 |
| 36 | const CDL_P_MINLEN: i64 = 0 // shortest printable run that counts as capability |
| 37 | const CDL_P_MAXSAMPLES: i64 = 1 // 0 = check every run (oracle); N = sample evenly across the file |
| 38 | const CDL_P_MAXTOKLEN: i64 = 2 // 0 = search the whole run; N = cap the searched prefix |
| 39 | const CDL_P_SLOTS: i64 = 4 |
| 42 | const CDL_O_RUNS: i64 = 0 // qualifying runs found in live |
| 43 | const CDL_O_CHECKED: i64 = 1 // runs actually searched for |
| 44 | const CDL_O_LOST: i64 = 2 // runs absent from the candidate |
| 48 | const CDL_O_SLOTS: i64 = 6 |
| 180 | const CDL_O_SRCPATH: i64 = 3 // of the LOST runs, how many look like a compiler-embedded source path |
| 181 | const CDL_O_IDENT: i64 = 4 // ... and how many look like a compiler-embedded SYMBOL name |
| 182 | const CDL_O_SECT: i64 = 5 // ... and how many are ELF/DWARF SECTION names (.debug_info, .shstrtab) |
| 183 | const CDL_SRC_SFX: *u8 = ".nx" |
| 184 | const CDL_IDENT_MIN: i64 = 6 // == the ruler's own minimum run length; not an independent knob |
| 293 | const CDL_SYM_IDENTICAL: i64 = 0 // neither side has a run the other lacks |
| 294 | const CDL_SYM_LOSS: i64 = 1 // only the candidate is missing runs -> a genuine one-way LOSS |
| 295 | const CDL_SYM_GAIN: i64 = 2 // only live is missing runs -> the candidate is a strict SUPERSET |
| 296 | const CDL_SYM_BOTH: i64 = 3 // both directions lose -> rename / re-encode / build-flavour change |
| 312 | const CDS_INVALID:i64=-201 |
| 313 | const CDS_UNKNOWN:i64=-202 |
| 314 | const CDS_RESOURCE:i64=-203 |
| 315 | const CDS_FILE:i64=1 |
| 316 | const CDS_DIR:i64=2 |
| 317 | const CDS_END:i64=3 |
| 496 | const CDS_CLASS_SOURCE:i64=1 |
| 497 | const CDS_CLASS_IDENT:i64=2 |
| 498 | const CDS_CLASS_SECTION:i64=3 |
| 499 | const CDS_CLASS_OTHER:i64=4 |
functions
| 50 | func cdl_is_print(c: i64) -> i64 |
| 57 | func cdl_runlen(b: *u8, n: i64, start: i64) -> i64 |
| 71 | func cdl_contains(hay: *u8, hn: i64, ndl: *u8, ns: i64, nl: i64) -> i64 |
| 96 | func cdl_bytes_eq(a: *u8, an: i64, b: *u8, bn: i64) -> i64 |
| 107 | func cdl_count_runs(b: *u8, n: i64, minlen: i64) -> i64 |
| 122 | func cdl_lost(live: *u8, ln: i64, cand: *u8, cn: i64, prm: *i64, out: *i64) -> i64 |
| 189 | func cdl_is_srcpath(b: *u8, off: i64, len: i64) -> i64 |
| 209 | func cdl_is_ident(b: *u8, off: i64, len: i64) -> i64 |
| 234 | func cdl_is_sectname(b: *u8, off: i64, len: i64) -> i64 |
| 255 | func cdl_lost_srcpath(live: *u8, ln: i64, cand: *u8, cn: i64, minlen: i64, out: *i64) -> i64 |
| 298 | func cdl_symclass(lost_fwd: i64, lost_rev: i64) -> i64 |
| 304 | func cdl_symname(s: i64) -> *u8 |
| 319 | func cds_init(c:*NxCdStructured,b:*u8,n:i64)->i64 |
| 324 | func cds_close(c:*NxCdStructured)->i64{if (c.marks as i64)>0{sys_munmap_direct(c.marks,c.bytes)};c.marks=0 as *u8;return 0} |
| 325 | func cds_span(n:i64,o:i64,z:i64)->i64{if o<0||z<0||o>n{return 0};if z>n-o{return 0};return 1} |
| 326 | func cds_byte(c:*NxCdStructured)->i64 |
| 331 | func cds_uleb(c:*NxCdStructured)->i64 |
| 342 | func cds_string(c:*NxCdStructured,kind:i64)->i64 |
| 351 | func cds_line(c:*NxCdStructured,off:i64,size:i64)->i64 |
| 394 | func cds_sectionless(c:*NxCdStructured)->i64 |
| 417 | func cds_elf(c:*NxCdStructured)->i64 |
| 462 | func cds_run(c:*NxCdStructured,start:i64)->i64 |
| 468 | func cds_file_present(a:*NxCdStructured,at:i64,n:i64,b:*NxCdStructured)->i64 |
| 482 | func cds_next_span(c:*NxCdStructured,cursor:*i64,s:*NxCdSpan)->i64 |
| 489 | func cds_span_missing(a:*NxCdStructured,b:*NxCdStructured,s:*NxCdSpan,maxlen:i64)->i64 |
| 493 | func cds_source_missing(a:*NxCdStructured,b:*NxCdStructured,s:*NxCdSpan)->i64 |
| 500 | func cds_span_class(a:*NxCdStructured,s:*NxCdSpan)->i64 called by 2: cd_structured_namescd_structured_names calls 3: cdl_is_srcpathcdl_is_identcdl_is_sectname |
| 508 | func cds_permil(lost:i64,checked:i64)->i64 |
| 516 | func cds_measure(a:*NxCdStructured,b:*NxCdStructured,prm:*i64,out:*NxCdResult)->i64 |