nx_genealogist_gapscan.nx
buildroot/runtime/nx_genealogist_gapscan.nx
about
nx_genealogist_gapscan.nx -- the Nishi GENEALOGIST's gap-scanner (FamilySearch-for-code:
"find the missing gaps"), sovereign NishiLang (raw syscalls, no shell/sed/awk).
(renamed from nx_genealogist to un-shadow the DISTINCT _hdl_build/nx_genealogist anti-DUPLICATION library
-- that one prevents rebuilding what exists; this one finds what is MISSING. Two facets, one old name.)
Mechanizes the Genealogist leg of the "what comes next" plan: it scans a
registry of modules for GAP MARKERS (TODO_SILICON = an unbuilt/stub silicon
path; SEED = a not-yet-matured module) and reports which modules carry which.
Each gap it finds is fused (in NISHI_WHAT_COMES_NEXT.md) with the RESEARCHER's
target for that capability (NISHI_RESEARCH_BASIS.md) to produce a ranked
next-step -- so the roadmap is DERIVED from code-state x research, not
hand-curated, and re-derives itself as we build (gaps shrink, plan updates).
DATA-DRIVEN (Cardinal 11, fixed 2026-06-16): the scan targets and the DRY
threshold are NO LONGER hardcoded. The old organ baked `let N=4` / `let M=6`
+ two arrays of absolute paths straight into code -- the exact magic-number /
data-in-code smell. Now the target list lives in DATA
(knowledge/registry/genealogist_targets.tsv: kind<TAB>name<TAB>path), the
counts are DERIVED from the row count, and the DRY threshold is one named
const. Add/remove a module = edit the data file, no code change (Cardinal 25);
the scan re-derives from current data every run (fresh, not a baked snapshot).
Bounded length-safe substring scan over the raw file bytes (sys_read_file),
so it never over-reads. license_tier: ORIGINAL
dependencies 1 imports · 0 importers
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
structs
| none |
consts
| 28 | const G_TGT_FILE: *u8 = "knowledge/registry/genealogist_targets.tsv" |
| 32 | const G_DUP_DRY_THRESHOLD: i64 = 3 |
functions
| 34 | func g_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != 0 as u8 { n = n + 1 } sys_write(1, s, n); return 0 } |
| 35 | func g_putn(n: i64) -> i64 |
| 45 | func g_strlen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != 0 as u8 { n = n + 1 } return n } called by 1: g_find |
| 47 | func g_streq(a: *u8, b: *u8) -> i64 called by 1: g_scan |
| 55 | func g_find(hay: *u8, hlen: i64, needle: *u8) -> i64 |
| 73 | func g_file_has(path: *u8, marker: *u8) -> i64 |
| 84 | func g_field(b: *u8, ls: i64, le: i64, f: i64, out: *u8) -> i64 called by 1: g_scan |
| 103 | func g_scan(tgtfile: *u8, outs: *i64) -> i64 |
| 158 | func main() -> i64 |