code wiki / _hdl_build / nx_janitor_sprawl.nx

nx_janitor_sprawl.nx

buildroot/runtime/_hdl_build/nx_janitor_sprawl.nx

15695 B303 linesdepth 2pulls 2 transitivereach 1 importersview sourcekind tooltopic janitor
docsdependenciesstructsconstsfunctions

about

nx_janitor_sprawl.nx -- the JANITOR's SPRAWL/JUNK-CLEANUP half (X-JAN-002, the getdents-walk TODO noted in nx_janitor.nx). Finds ORPHANED registry .tsv files -- ones referenced by ZERO .nx organs anywhere under the scan root -- and QUARANTINES them (reversible MOVE, never delete). NO-FALSE-POSITIVE LAW (cardinal): a registry .tsv is "orphaned" ONLY IF its basename appears in ZERO .nx files under the scan root. ANY mention counts as PROTECTED -- a real read, a path const, or even a bare mention inside a // comment. When in doubt, protect. The detector therefore uses SUBSTRING matching of the literal basename "<name>.tsv" (so it catches bare names, full paths, and "\x00"-terminated path literals alike), gated by a LEFT word-boundary so that "census.tsv" is not spuriously matched as a substring of "math_census.tsv" -- the boundary only ever REJECTS a match that is genuinely part of a LONGER different filename, so it can never cause a false orphan. REVERSIBLE: the action is QUARANTINE = sys_renameat (atomic move) into the quarantine dir, preserving the filename. We NEVER unlink/delete registry data (CLAUDE.md #13: additive / soft-delete; history is sacred). Re-running is idempotent: a file already moved out of the registry is simply gone from the registry scan, so it is neither re-detected nor re-moved. PARAMETERIZED for testability (the gate points it at /tmp fixtures, never the real tree): nx_janitor_sprawl [scan_root] [registry_dir] [quarantine_dir] [logpath] Defaults (no argv) operate on the REAL tree: scan_root = runtime registry_dir = knowledge/registry quarantine_dir = knowledge/_quarantine/registry logpath = knowledge/status/janitor_sprawl.log Durable: a JANITOR-SPRAWL row -> the logpath. Exit 0. Slow forward is fine. license_tier: ORIGINAL

dependencies 1 imports · 1 importers

nx_syscalls.nx nx_janitor_sprawl.nx nx_janitor_sprawl_gate.nx

imports: nx_syscalls.nx

imported by: nx_janitor_sprawl_gate.nx

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

main sys_mmap js_run sys_mmap ↻ sys_openat_rd js_getdents js_slen js_ends js_slen ↻ js_dup js_slen ↻ sys_mmap ↻ sys_close sys_munmap js_build_protected sys_mmap ↻ sys_openat_rd ↻ js_getdents ↻ js_eq js_join js_isdir js_slen ↻ js_ends ↻ js_read sys_openat_rd ↻ sys_read sys_close ↻ js_referenced js_slen ↻ js_is_ident sys_close ↻ sys_munmap ↻ sys_openat_append sys_now_realtime_sec sys_mmap ↻ sys_clock_gettime_real js_puts sys_write js_num sys_mmap ↻

structs

none

consts

30const JS_PATH_SLOT: i64 = 768 // bytes per queued directory path
31const JS_QUEUE_CAP: i64 = 16384 // max directories in the BFS queue
32const JS_DENT_BUF: i64 = 65536 // getdents64 read buffer
33const JS_FILE_CAP: i64 = 4194304 // per-.nx read buffer (reused)
34const JS_NAME_CAP: i64 = 256 // max registry-basename length
35const JS_REG_MAX: i64 = 4096 // max registry .tsv files tracked
36const JS_DIR_MODE: i64 = 0x1ed // 0755 for the quarantine dir
37const JS_LOG_MODE: i64 = 0x1a4 // 0644 for the log
38const JS_DT_OFF: i64 = 16 // d_reclen offset in linux_dirent64
39const JS_NAME_OFF: i64 = 19 // d_name offset in linux_dirent64

functions

41func js_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
called by 2: js_runmain calls 1: sys_write
42func js_fputs(fd: i64, s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(fd,s,n); return 0 }
called by 1: js_run calls 1: sys_write
43func js_num(v: i64) -> i64 { let bb: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m;sys_write(1,"-" as *u8,1)}; let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=(48 as u8);k=1}; while m>0{t[k]=((48+(m%10)) as u8);m=m/10;k=k+1}; var i: i64=0; while i<k{bb[i]=t[k-1-i];i=i+1}; sys_write(1,bb,k); return 0 }
called by 2: js_runmain calls 2: sys_mmapsys_write
44func js_fnum(fd: i64, v: i64) -> i64 { let bb: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m;sys_write(fd,"-" as *u8,1)}; let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=(48 as u8);k=1}; while m>0{t[k]=((48+(m%10)) as u8);m=m/10;k=k+1}; var i: i64=0; while i<k{bb[i]=t[k-1-i];i=i+1}; sys_write(fd,bb,k); return 0 }
called by 1: js_run calls 2: sys_mmapsys_write
45func js_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
46func js_eq(a: *u8, b: *u8) -> i64 { var i: i64=0; while a[i]!=(0 as u8){ if a[i]!=b[i]{return 0} i=i+1 } if b[i]!=(0 as u8){return 0} return 1 }
called by 1: js_build_protected
49func js_ends(path: *u8, pl: i64, ext: *u8) -> i64
called by 2: js_build_protectedjs_run calls 1: js_slen
55func js_is_ident(c: i64) -> i64
called by 1: js_referenced
68func js_referenced(buf: *u8, n: i64, pat: *u8) -> i64
86func js_join(dst: *u8, dir: *u8, name: *u8) -> i64
94func js_getdents(fd: i64, buf: *u8, count: i64) -> i64 { return __syscall(SYS_GETDENTS64, fd, buf, count, 0, 0, 0) }
97func js_isdir(path: *u8, st: *u8) -> i64
called by 1: js_build_protected
106func js_read(path: *u8, buf: *u8, cap: i64) -> i64
114func js_dup(src: *u8) -> *u8
called by 1: js_run calls 2: js_slensys_mmap
124func js_build_protected(scan_root: *u8, names: *i64, prot: *i64, ncount: i64) -> i64
192func js_run(scan_root: *u8, registry_dir: *u8, quarantine_dir: *u8, logpath: *u8, outs: *i64) -> i64
284func main(argc: i64, argv: *i64) -> i64