code wiki / _hdl_build / nx_treediverge.nx

nx_treediverge.nx

buildroot/runtime/_hdl_build/nx_treediverge.nx

11410 B252 linesdepth 2pulls 2 transitivereach 0 importersview sourcekind tool
docsdependenciesstructsconstsfunctions

about

nx_treediverge.nx -- THE MISSING CROSS-TREE DIVERGENCE DETECTOR (debt 1785438829, sev-8). THE GAP IT CLOSES, in that debt's own words: "nx_dup_source_check finds dups WITHIN buildroot but there is NO laptop-vs-NAS divergence detector -- I did it BY HAND four times today. BUILD THAT: a cross-tree census emitting per-file laptop_bytes / nas_bytes / delta / direction, so divergence is a REPORT rather than an archaeology exercise; size alone would have caught all four of today's instances." WHY IT MATTERS (not tidiness): /api/build compiles from buildroot, so a fix living only in the laptop SSOT NEVER REACHES A RUNNING BINARY, and a fix living only in buildroot is DESTROYED by the next sync from the SSOT. The divergence is BIDIRECTIONAL -- neither tree is a superset -- so a one-way sync in EITHER direction silently loses work. You cannot merge safely without first knowing the direction per file. That is exactly what this emits. COMPOSES, DOES NOT DUPLICATE: nx_treediff already emits one tree's manifest as "<bytes> <relpath>" per .nx file and says in its own usage that it is "for cross-tree comparison" -- it just never performed the comparison. This is the missing half. Run nx_treediff on each tree, then: nx_treediverge <manifestA> <manifestB> [labelA] [labelB] VERDICTS, per file: A-ONLY / B-ONLY / A-AHEAD / B-AHEAD / SAME. "AHEAD" is BY BYTES, which is the signal that caught all four historical instances; it is a FLOOR, not proof of content (equal size can still differ -- see the same-size-rewrite caveat on expect=<size> CAS). Declared, never implied. NON-VACUITY: an empty or unreadable manifest REFUSES (exit 3) instead of reporting "0 divergent", because a comparator that reads nothing and prints GREEN is the self-ceiling defect this ecosystem has banned repeatedly. A zero-divergence verdict is only emitted when BOTH sides actually had rows.

dependencies 1 imports · 0 importers

nx_syscalls.nx nx_treediverge.nx

imports: nx_syscalls.nx

imported by: nobody (leaf or entry point)

call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown

main tv_puts sys_write sys_exit sys_mmap tv_readall sys_openat_rd sys_mmap ↻ sys_read sys_close tv_index sys_mmap ↻ tv_parse tv_hash tv_parse ↻ tv_find tv_hash ↻ tv_streq tv_emit tv_puts ↻ tv_putn sys_mmap ↻ sys_write ↻ tv_puts ↻ tv_putn ↻

structs

none

consts

27const TV_MAGIC_5381: i64 = 5381
29const TV_HBUCKETS: i64 = 65536 // hash buckets; power of two so the mask is an AND
30const TV_MAXENT: i64 = 200000 // per-tree entry ceiling (corpus is ~17.7k .nx today, 11x headroom)
31const TV_BUFCAP: i64 = 16777216 // 16 MiB per manifest (17.7k rows x ~80B ~= 1.4 MiB, 11x headroom)

functions

40func tv_puts(s: *u8) -> i64
called by 3: tv_putntv_emitmain calls 1: sys_write
46func tv_putn(v: i64) -> i64
61func tv_readall(path: *u8, outn: *i64) -> *u8
78func tv_hash(s: *u8) -> i64
called by 2: tv_indextv_find
84func tv_streq(a: *u8, b: *u8) -> i64
called by 1: tv_find
95func tv_parse(buf: *u8, start: i64, end: i64, szout: *i64) -> *u8
called by 2: tv_indexmain
117func tv_index(buf: *u8, n: i64) -> i64
called by 1: main calls 3: sys_mmaptv_parsetv_hash
144func tv_find(rel: *u8) -> i64
called by 1: main calls 2: tv_hashtv_streq
154func tv_emit(tag: *u8, rel: *u8, a: i64, b: i64) -> i64
called by 1: main calls 2: tv_putstv_putn
163func main(argc: i64, argv: *i64) -> i64