code wiki / _hdl_build / nx_role_store_migrate.nx
nx_role_store_migrate.nx source
↩ module page · 122 lines · 5824 B
1// nx_role_store_migrate.nx -- MIGRATE the knowledge/roles/*.tsv files into the SOVEREIGN seg-store
2// (knowledge/store/roles-*, via nx_role_store). Operator 2026-06-22: "migrate and get rid of these tsvs just
3// nishi ecosystem." Reads each legacy .tsv, seeds its rows into the matching channel in ONE batched commit
4// (1 segment), then reads EVERY row back and byte-compares to the source line -> GREEN only if every source
5// row is present byte-exact. IDEMPOTENT (rule#10): a channel is seeded only when EMPTY (count==0); once seeded
6// (and possibly evolved by live appends) a re-run writes nothing and still verifies. ADDITIVE (rule#13): the
7// .tsv files are not touched here -- retirement to knowledge/_retired_tsv/ is a separate, post-verify step.
8// pm_coord.tsv -> pmcoord engineer_queue.tsv -> engineerq doctor_queue.tsv -> doctorq engineer_ledger.tsv -> engineerl
9// expect_exit: 0 license_tier: ORIGINAL
10import "nx_role_store.nx"
11import "nx_seg_store.nx"
12import "nx_syscalls.nx"
13const K_MAGIC_4096: i64 = 4096
14
15func mw(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
16func mn(v: i64) -> i64 { let b: *u8=sys_mmap(28); let e: i64=rs_itoa(b,v); sys_write(1,b,e); return 0 }
17
18// migrate ONE legacy tsv into a channel. counts source rows into tot[0], byte-verified rows into ver[0],
19// and channels freshly-seeded this run into wro[0]. Returns 0.
20func mig_one(ch: *u8, tsvpath: *u8, tot: *i64, ver: *i64, wro: *i64) -> i64 {
21 let szp: *i64 = sys_mmap(16) as *i64
22 let buf: *u8 = ss_readall(tsvpath, szp)
23 let sz: i64 = szp[0]
24 mw(" channel " as *u8); mw(ch); mw(" <- " as *u8); mw(tsvpath); mw(" ")
25
26 // SOURCE RETIRED: once the legacy .tsv has been moved to _retired_tsv/, the store is the SSOT. Verify the
27 // channel is self-consistent (every row reads back) so this migration stays idempotent-GREEN post-retirement.
28 if sz <= 0 {
29 let cntr: i64 = rs_count(ch)
30 mw("(source retired/absent; channel rows=" as *u8); mn(cntr); mw(") " as *u8)
31 let pqr: *i64 = sys_mmap(16) as *i64; let lqr: *i64 = sys_mmap(16) as *i64
32 var ir: i64 = 0
33 while ir < cntr { tot[0] = tot[0] + 1; if rs_get_seq(ch, ir, pqr, lqr) == 1 { ver[0] = ver[0] + 1 } ir = ir + 1 }
34 mw("verified=" as *u8); mn(cntr); mw("\n" as *u8)
35 return 0
36 }
37
38 // collect non-empty line (ptr,len) pairs -- the value is the line MINUS its trailing newline
39 let lp: *i64 = sys_mmap(8 * K_MAGIC_4096) as *i64
40 let ll: *i64 = sys_mmap(8 * K_MAGIC_4096) as *i64
41 var k: i64 = 0
42 if sz > 0 {
43 var i: i64 = 0
44 var ls: i64 = 0
45 while i <= sz {
46 var nl: i64 = 0
47 if i >= sz { nl = 1 } else { if buf[i] == (10 as u8) { nl = 1 } }
48 if nl == 1 {
49 let len: i64 = i - ls
50 if len > 0 { if k < K_MAGIC_4096 { lp[k] = (buf as i64) + ls; ll[k] = len; k = k + 1 } }
51 ls = i + 1
52 }
53 i = i + 1
54 }
55 }
56 mw("rows=" as *u8); mn(k)
57
58 let existing: i64 = rs_count(ch)
59 // SEED only when empty -- protects any live-evolved rows from being clobbered on re-run
60 if existing == 0 { if k > 0 {
61 let lk: i64 = rs_lock()
62 let w: *i64 = ss_begin()
63 var j: i64 = 0
64 while j < k {
65 let rk: *u8 = sys_mmap(128); rs_key(ch, j, rk)
66 ss_add(w, 1, rk, lp[j] as *u8, ll[j])
67 j = j + 1
68 }
69 let nk: *u8 = sys_mmap(128); rs_nkey(ch, nk)
70 let cb: *u8 = sys_mmap(32); let cl: i64 = rs_itoa(cb, k)
71 ss_add(w, 1, nk, cb, cl)
72 ss_commit(RS_PREFIX, w, rs_seg_next())
73 rs_unlock(lk)
74 wro[0] = wro[0] + 1
75 mw(" SEEDED" as *u8)
76 } } else { mw(" (already-present count=" as *u8); mn(existing); mw(")" as *u8) }
77
78 // VERIFY: each source row reads back byte-exact from the store
79 let pq: *i64 = sys_mmap(16) as *i64
80 let lq: *i64 = sys_mmap(16) as *i64
81 var vok: i64 = 0
82 var j2: i64 = 0
83 while j2 < k {
84 tot[0] = tot[0] + 1
85 if rs_get_seq(ch, j2, pq, lq) == 1 {
86 if lq[0] == ll[j2] {
87 let a: *u8 = pq[0] as *u8
88 let b2: *u8 = lp[j2] as *u8
89 var eq: i64 = 1
90 var x: i64 = 0
91 while x < lq[0] { if a[x] != b2[x] { eq = 0 } x = x + 1 }
92 if eq == 1 { vok = vok + 1; ver[0] = ver[0] + 1 }
93 }
94 }
95 j2 = j2 + 1
96 }
97 mw(" verified=" as *u8); mn(vok); mw("/" as *u8); mn(k); mw("\n" as *u8)
98 return 0
99}
100
101func main() -> i64 {
102 mw("=== nx_role_store_migrate: knowledge/roles/*.tsv -> sovereign seg-store (knowledge/store/roles-*) ===\n" as *u8)
103 let tot: *i64 = sys_mmap(16) as *i64; tot[0] = 0
104 let ver: *i64 = sys_mmap(16) as *i64; ver[0] = 0
105 let wro: *i64 = sys_mmap(16) as *i64; wro[0] = 0
106
107 mig_one("pmcoord" as *u8, "knowledge/roles/pm_coord.tsv" as *u8, tot, ver, wro)
108 mig_one("engineerq" as *u8, "knowledge/roles/engineer_queue.tsv" as *u8, tot, ver, wro)
109 mig_one("doctorq" as *u8, "knowledge/roles/doctor_queue.tsv" as *u8, tot, ver, wro)
110 mig_one("engineerl" as *u8, "knowledge/roles/engineer_ledger.tsv" as *u8, tot, ver, wro)
111
112 mw("\n source_rows=" as *u8); mn(tot[0]); mw(" verified_in_store=" as *u8); mn(ver[0])
113 mw(" channels_seeded_this_run=" as *u8); mn(wro[0]); mw(" segcount=" as *u8); mn(rs_segcount())
114 mw("\n store=knowledge/store/roles- (NO TSV)\n" as *u8)
115
116 if ver[0] == tot[0] { if tot[0] > 0 {
117 mw("ROLE-STORE-MIGRATE verdict=GREEN (every legacy roles/*.tsv row is byte-exact in the seg-store)\n" as *u8)
118 sys_exit(0); return 0
119 } }
120 mw("ROLE-STORE-MIGRATE verdict=RED (source rows not fully verified in the store)\n" as *u8)
121 sys_exit(1); return 1
122}