code wiki / _hdl_build / nx_janitor_sprawl.nx
nx_janitor_sprawl.nx
buildroot/runtime/_hdl_build/nx_janitor_sprawl.nx
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
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
structs
| none |
consts
| 30 | const JS_PATH_SLOT: i64 = 768 // bytes per queued directory path |
| 31 | const JS_QUEUE_CAP: i64 = 16384 // max directories in the BFS queue |
| 32 | const JS_DENT_BUF: i64 = 65536 // getdents64 read buffer |
| 33 | const JS_FILE_CAP: i64 = 4194304 // per-.nx read buffer (reused) |
| 34 | const JS_NAME_CAP: i64 = 256 // max registry-basename length |
| 35 | const JS_REG_MAX: i64 = 4096 // max registry .tsv files tracked |
| 36 | const JS_DIR_MODE: i64 = 0x1ed // 0755 for the quarantine dir |
| 37 | const JS_LOG_MODE: i64 = 0x1a4 // 0644 for the log |
| 38 | const JS_DT_OFF: i64 = 16 // d_reclen offset in linux_dirent64 |
| 39 | const JS_NAME_OFF: i64 = 19 // d_name offset in linux_dirent64 |
functions
| 41 | func 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 } |
| 42 | func 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 } |
| 43 | func 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 } |
| 44 | func 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 } |
| 45 | func js_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n } |
| 46 | func 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 |
| 49 | func js_ends(path: *u8, pl: i64, ext: *u8) -> i64 |
| 55 | func js_is_ident(c: i64) -> i64 called by 1: js_referenced |
| 68 | func js_referenced(buf: *u8, n: i64, pat: *u8) -> i64 |
| 86 | func js_join(dst: *u8, dir: *u8, name: *u8) -> i64 |
| 94 | func js_getdents(fd: i64, buf: *u8, count: i64) -> i64 { return __syscall(SYS_GETDENTS64, fd, buf, count, 0, 0, 0) } |
| 97 | func js_isdir(path: *u8, st: *u8) -> i64 called by 1: js_build_protected |
| 106 | func js_read(path: *u8, buf: *u8, cap: i64) -> i64 |
| 114 | func js_dup(src: *u8) -> *u8 |
| 124 | func js_build_protected(scan_root: *u8, names: *i64, prot: *i64, ncount: i64) -> i64 |
| 192 | func js_run(scan_root: *u8, registry_dir: *u8, quarantine_dir: *u8, logpath: *u8, outs: *i64) -> i64 |
| 284 | func main(argc: i64, argv: *i64) -> i64 |