code wiki / (root) / nx_mf_hold.nx

nx_mf_hold.nx

buildroot/runtime/nx_mf_hold.nx

26830 B640 linesdepth 2pulls 2 transitivereach 0 importersview sourcekind tool
docsdependenciesstructsconstsfunctions

about

nx_mf_hold.nx -- ADVANCE A SYNC WATERMARK EXCEPT WHERE IT WAS NEVER EARNED. WHY IT EXISTS (measured 2026-08-16, treecanon flow-back lane): sync_nas_ahead.ps1 ended with `if ($Apply) { Copy-Item $cur $base -Force }` -- it advanced the baseline manifest to the CURRENT NAS manifest WHOLESALE. For a REFUSE that is correct: the file was examined, declined, and durably queued in conflicts.log for conflicts.ps1 to rank. But a FETCH FAILURE `continue`d BEFORE that ledger append, so it was recorded NOWHERE -- and the watermark then advanced past a file the lane had never even looked at, marking it synced permanently and silently. => A TRANSIENT FAILURE THAT IS NEITHER RETRIED NOR RECORDED IS A PERMANENT ONE. SCOPE CORRECTION WORTH KEEPING, because the first version of this header got it wrong: the watermark answers "what changed on the NAS", NOT "what is still unreconciled". Those are different questions with different readers, and conflicts.log/conflicts.ps1 already answer the second (837 distinct files / 1185 events, measured the same day). Holding every refusal here would re-fetch all 837 on every hourly run to rebuild a worklist that already exists -- a duplicate ruler that also hammers the NAS. BEFORE BUILDING A QUEUE, CHECK WHETHER THE REFUSAL LEDGER IS ALREADY ONE. WHAT IT DOES out = current, EXCEPT that any path named in holdlist keeps its BASELINE row -- or is OMITTED entirely when the baseline has no row for it, so it re-surfaces next run as B-ONLY rather than being silently blessed. PER-PATH, deliberately. Holding the WHOLE watermark whenever anything was held would let one stuck file pin it forever and turn every later run into a full re-fetch: one silence traded for one flood. SELF-TESTS ON EVERY RUN AND REFUSES TO WRITE IF ANY TOOTH FAILS. Precedent in this same lane: nx_normdiff withholds its verdict when its supersede predicate regresses, so the failure mode is "no adopt", never "wrong adopt". Emitting a CORRUPT baseline is strictly worse than emitting none, because a corrupt watermark is indistinguishable from a converged one. ROW FORMAT: "<64hex> <bytes> <relpath>\n" -- what nx_treehash writes and nx_hashdiverge parses. IMPRECISION ACCEPTED AND NAMED: relpath is the bytes between the second space and the newline, so a relpath CONTAINING A SPACE parses short. nx_treehash never emits one. The parse is deliberately the SAME SHAPE as nx_hashdiverge's rather than a cleverer one, because two parsers that disagree under the same input is the duplicate-ruler defect wearing a bugfix. sys_openat_wr has NO O_TRUNC, so a shorter rewrite over a longer file leaves a live tail -- on a BASELINE manifest that is corrupt trailing rows that read as real. There is no sys_openat_trunc (proven absent over buildroot/runtime, corpus_complete=1), so: UNLINK FIRST.

dependencies 1 imports · 0 importers

nx_syscalls.nx nx_mf_hold.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 sys_mmap nxa_die sys_write sys_exit nxa_lock_take nxa_lock_addr sys_write ↻ nxa_lock_give nxa_lock_addr ↻ nxa_report_overrun sys_write ↻ nxa_dump_printable sys_write ↻ nxa_dump_sizes sys_write ↻ mh_puts sys_write ↻ sys_exit ↻ mh_selftest sys_mmap ↻ mh_row mh_fill mh_cat mh_holdline_crlf mh_cat ↻ mh_holdline mh_cat ↻ mh_alloc mh_pow2ge sys_mmap ↻ mh_scan_hold mh_hput mh_hash mh_streq mh_scan_mf mh_bput mh_hash ↻ mh_streq ↻ mh_hfind

structs

none

consts

58const MH_SHA_CHARS: i64 = 64
59const MH_NUMBUF: i64 = 64
60const MH_FNV_OFF: i64 = 1469598103934665603
61const MH_FNV_PRIME: i64 = 1099511628211
63const MH_MIN_MF_ROW: i64 = MH_SHA_CHARS + 4
65const MH_MIN_HOLD_ROW: i64 = 2
67const MH_LOAD_NUM: i64 = 4
68const MH_MIN_SLOTS: i64 = 16
69const MH_FIXTURE_BYTES: i64 = 4096
70const MH_OK: i64 = 0
71const MH_PARTITION_FAIL: i64 = 1
72const MH_USAGE: i64 = 2
73const MH_UNREADABLE: i64 = 3
74const MH_SELFTEST_FAIL: i64 = 4

functions

92func mh_puts(s: *u8) -> i64
98func mh_putn(v: i64) -> i64
called by 2: mh_selftestmain calls 2: sys_writemh_puts
109func mh_slen(s: *u8) -> i64
114func mh_streq(a: *u8, b: *u8) -> i64
125func mh_hash(s: *u8) -> i64
137func mh_pow2ge(v: i64) -> i64
called by 1: mh_alloc
144func mh_bput(rel: *u8, sha: *u8, sz: *u8) -> i64
called by 1: mh_scan_mf calls 2: mh_hashmh_streq
163func mh_bfind(rel: *u8) -> i64
called by 1: mh_scan_mf calls 2: mh_hashmh_streq
177func mh_hput(rel: *u8) -> i64
called by 1: mh_scan_hold calls 2: mh_hashmh_streq
195func mh_hfind(rel: *u8) -> i64
called by 1: mh_scan_mf calls 2: mh_hashmh_streq
208func mh_emit_row(sha: *u8, sz: *u8, rel: *u8) -> i64
called by 1: mh_scan_mf calls 1: mh_slen
227func mh_scan_mf(buf: *u8, n: i64, side: i64) -> i64
283func mh_scan_hold(buf: *u8, n: i64) -> i64
called by 2: mh_selftestmain calls 1: mh_hput
318func mh_sweep_hold() -> i64
called by 2: mh_selftestmain
331func mh_slurp(path: *u8, lenout: *i64) -> *u8
called by 1: main calls 2: sys_mmapsys_read_file
347func mh_alloc(brows: i64, hrows: i64) -> i64
called by 2: mh_selftestmain calls 2: mh_pow2gesys_mmap
361func mh_cat(dst: *u8, off: i64, s: *u8) -> i64
367func mh_fill(dst: *u8, off: i64, ch: i64, cnt: i64) -> i64
called by 1: mh_row
375func mh_row(dst: *u8, off: i64, shachar: i64, sz: *u8, path: *u8) -> i64
called by 1: mh_selftest calls 2: mh_fillmh_cat
384func mh_holdline(dst: *u8, off: i64, path: *u8) -> i64
called by 1: mh_selftest calls 1: mh_cat
391func mh_holdline_crlf(dst: *u8, off: i64, path: *u8) -> i64
called by 1: mh_selftest calls 1: mh_cat
397func mh_find_sub(hay: *u8, hn: i64, needle: *u8) -> i64
called by 1: mh_selftest calls 1: mh_slen
415func mh_check(name: *u8, cond: i64) -> i64
called by 1: mh_selftest calls 1: mh_puts
427func mh_selftest() -> i64
512func main(argc: i64, argv: *i64) -> i64