code wiki / _hdl_build / nx_tsv_migrate.nx
nx_tsv_migrate.nx source
↩ module page · 112 lines · 5703 B
1// nx_tsv_migrate.nx -- retire a flat .tsv/.conf/.list registry file into the NATIVE sovereign seg-store plane
2// (operator 2026-07-20: "get rid of all these tsvs and migrate to native nishi information management"; this is
3// the standing 07-18 law "no tsv -- nishi formats" made MECHANICAL). The ecosystem already owns the primitive
4// (sts_seed = flat buffer -> ONE plane commit) but every caller inlines it, so there was no way to migrate an
5// EXISTING file without writing a bespoke organ each time. This is that missing reusable tool -- one call per
6// file, so the ~150-file legacy population can be retired lane by lane instead of hand-ported.
7// nx_tsv_migrate <srcfile> <plane-prefix> e.g. knowledge/registry/x.tsv knowledge/store/x-
8// DATA-LOSSLESS + EXPLICIT ABOUT THE REST: every data row is carried verbatim. `#` comment lines are NOT carried,
9// because the native store's own seeder (sts_seed) drops them BY DESIGN -- a plane holds rows, and provenance
10// belongs in the emitting organ's envelope. That drop is COUNTED and REPORTED (comments_dropped), never silent,
11// so an owner migrating a heavily-commented file knows to re-home the prose before retiring the source.
12// VERIFIED BY ROUND-TRIP: after the commit it reads the plane back through the real sts_load and compares the
13// data-row count; a mismatch is a LOUD nonzero exit, never a silent partial migration. Non-destructive: the
14// source is NEVER touched -- retiring it stays a separate reversible decision (.superseded-by-sovereign-store).
15// license_tier: ORIGINAL expect_exit: 0
16import "nx_store_seed_lib.nx"
17import "nx_seg_store.nx"
18import "nx_syscalls.nx"
19const TM_MAGIC_4096: i64 = 4096
20
21const TM_CAP: i64 = 4194304
22
23func tm_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
24func tm_pn(v: i64) -> i64 { let b: *u8=sys_mmap(32) as *u8; var x: i64=v; var ng: i64=0; if x<0{ng=1;x=0-x} var i: i64=31; if x==0{b[i]=48 as u8;i=i-1} while x>0{b[i]=(48+x%10) as u8;x=x/10;i=i-1} if ng==1{b[i]=45 as u8;i=i-1} sys_write(1,(b as i64+i+1) as *u8,31-i); return 0 }
25// count non-empty lines in buf[0..n)
26func tm_lines(b: *u8, n: i64) -> i64 {
27 var c: i64=0
28 var i: i64=0
29 while i<n {
30 let ls: i64=i
31 var le: i64=ls
32 var go: i64=1
33 while go==1 { if le>=n { go=0 } else { if b[le]==(10 as u8) { go=0 } else { le=le+1 } } }
34 if le>ls { c=c+1 }
35 i=le+1
36 }
37 return c
38}
39
40func main(argc: i64, argv: *i64) -> i64 {
41 if argc < 3 {
42 tm_puts("usage: nx_tsv_migrate <srcfile> <plane-prefix> (e.g. knowledge/registry/x.tsv knowledge/store/x-)\n" as *u8)
43 sys_exit(2)
44 return 2
45 }
46 let src: *u8 = argv[1] as *u8
47 let pfx: *u8 = argv[2] as *u8
48 let szp: *i64 = sys_mmap(16) as *i64
49 let raw: *u8 = sys_read_file(src, szp)
50 if (raw as i64)==0 {
51 tm_puts("TSV-MIGRATE RED -- source unreadable (fail-closed, nothing committed): " as *u8); tm_puts(src); tm_puts("\n" as *u8)
52 sys_exit(1)
53 return 1
54 }
55 let n: i64 = szp[0]
56 // carry every DATA line verbatim; count (never silently swallow) the comment lines the store drops by design
57 let buf: *u8 = sys_mmap(TM_CAP)
58 var o: i64 = 0
59 var i: i64 = 0
60 var src_lines: i64 = 0
61 var comments: i64 = 0
62 while i<n {
63 let ls: i64=i
64 var le: i64=ls
65 var go: i64=1
66 while go==1 { if le>=n { go=0 } else { if raw[le]==(10 as u8) { go=0 } else { le=le+1 } } }
67 if le>ls {
68 if raw[ls]==(35 as u8) { comments=comments+1 } else {
69 if o + (le-ls) + 2 < TM_CAP {
70 var k: i64=ls
71 while k<le { buf[o]=raw[k]; o=o+1; k=k+1 }
72 buf[o]=10 as u8; o=o+1
73 src_lines=src_lines+1
74 }
75 }
76 }
77 i=le+1
78 }
79 if src_lines==0 {
80 tm_puts("TSV-MIGRATE RED -- source has no data lines (fail-closed; comment-only files carry no plane): " as *u8); tm_puts(src); tm_puts("\n" as *u8)
81 sys_exit(1)
82 return 1
83 }
84 let seeded: i64 = sts_seed(pfx, buf, o)
85 if seeded < 0 {
86 tm_puts("TSV-MIGRATE RED -- plane commit FAILED: " as *u8); tm_puts(pfx); tm_puts("\n" as *u8)
87 sys_exit(3)
88 return 3
89 }
90 // ROUND-TRIP VERIFY through the real reader -- no migration is trusted on the write alone
91 let back: *u8 = sys_mmap(TM_CAP)
92 let bn: i64 = sts_load(pfx, back, TM_CAP - TM_MAGIC_4096)
93 let back_lines: i64 = tm_lines(back, bn)
94 tm_puts("{\x22src\x22:\x22" as *u8); tm_puts(src)
95 tm_puts("\x22,\x22plane\x22:\x22" as *u8); tm_puts(pfx)
96 tm_puts("\x22,\x22src_data_lines\x22:" as *u8); tm_pn(src_lines)
97 tm_puts(",\x22comments_dropped\x22:" as *u8); tm_pn(comments)
98 tm_puts(",\x22seeded_rows\x22:" as *u8); tm_pn(seeded)
99 tm_puts(",\x22readback_lines\x22:" as *u8); tm_pn(back_lines)
100 tm_puts(",\x22src_bytes\x22:" as *u8); tm_pn(n)
101 tm_puts(",\x22plane_bytes\x22:" as *u8); tm_pn(bn)
102 if back_lines != src_lines {
103 tm_puts(",\x22verified\x22:0}\n" as *u8)
104 tm_puts("TSV-MIGRATE RED -- ROUND-TRIP MISMATCH (plane does NOT reproduce the source; do NOT retire the file)\n" as *u8)
105 sys_exit(4)
106 return 4
107 }
108 tm_puts(",\x22verified\x22:1,\x22source_untouched\x22:1" as *u8)
109 tm_puts(",\x22note\x22:\x22comment lines are dropped by the native seeder BY DESIGN (a plane holds rows) -- re-home any provenance prose into the emitting organ's envelope BEFORE retiring the source\x22}\n" as *u8)
110 tm_puts("TSV-MIGRATE GREEN -- plane reproduces every data row; source left in place (retire it separately, reversibly)\n" as *u8)
111 return 0
112}