code wiki / _hdl_build / nx_readmany.nx

nx_readmany.nx source

↩ module page · 318 lines · 14097 B

1// nx_readmany.nx -- ONE CALL, N FILES (Lane I common-task hardening, 2026-08-20). 2// MINED, NOT GUESSED. nx_wfcost measured the full 309-transcript / 2,006,669,677 B action record and 3// the read cluster is the largest BUILD candidate in it: nx_fs:read >> nx_fs:read 5,675 episodes, 4// nx_shelltool:grep >> nx_fs:read 1,683, nx_fs:lines >> nx_fs:lines 1,233, nx_fs:lines >> nx_fs_write:edit 5// 904 -- ~9,495 consecutive-read episodes, each one a seat turn spent re-issuing the same verb. 6// (The larger mgmt:POST cluster is deliberately NOT addressed here: nx_organ_ship already collapses it, 7// so that one is an ADOPTION gap, not a build gap -- building a second would be the duplicate ruler.) 8// 9// WHY A BATCH READ AND NOT A BIGGER CAP: the measured unit is the SEAT TURN (1 turn ~= 133,658 10// input-token-equivalents, measured, not estimated). N reads cost N turns regardless of how many bytes 11// each returns, so the win comes from collapsing TURNS, never from raising a limit. 12// 13// TWO LAWS THIS ORGAN EXISTS TO NOT BREAK: 14// 1. THE ENVELOPE IS PER ITEM, NEVER GLOBAL. A single global "truncated=1" cannot say WHICH file was 15// cut, so the caller re-reads all of them and the batch saves nothing. Every item carries its own 16// status + bytes= + of= (its TRUE full size, always known because the read is sized from the file). 17// This lane already found `nx_actlog harden` computing a truncation envelope and then dropping it 18// at the next hop -- an envelope dropped at the next hop is an envelope that was never published. 19// 2. ONE BAD TARGET MUST NOT POISON THE BATCH. Every item gets its own third state 20// (OK | EMPTY | ABSENT | UNREADABLE | BUDGET-EXHAUSTED), so an absent path costs exactly one row 21// and the other N-1 files still come back. A batch that fails whole is worse than N single reads. 22// 23// PARTITION: ok + empty + absent + unreadable + budget_exhausted == items, and the footer PRINTS the 24// sum so it can be reconciled. TRUNCATED is a SEPARATE AXIS, never a partition member -- a truncated 25// item is ALSO an OK item, and folding it in would silently break the reconciliation. 26// 27// read <per_item_max> <budget> <path> [path...] 0 = unlimited for either bound 28// selftest gv verdict gate, runtime fixtures, neg-controls 29// license_tier: ORIGINAL No hw writes (Rule 26). 30import "nx_syscalls.nx" 31import "nx_gate_verdict.nx" 32 33// Derivation of the default budget: the MCP body path silently returns {} above roughly 64 KiB 34// (measured by a sibling lane, 2026-08-19), so a batch aimed at the MCP surface must stay under it. 35// 262144 is the CLI default because this organ is also run directly, where no such cliff applies; 36// an MCP caller passes a smaller budget explicitly. Both bounds are ARGUMENTS, not hidden constants. 37const RM_BUDGET_DEF: i64 = 262144 38const RM_ITEM_DEF: i64 = 65536 39const RM_ITEMS_MAX: i64 = 256 40const RM_PATH_BUF: i64 = 4096 41const RM_MODE_644: i64 = 420 42const RM_MODE_755: i64 = 493 43const RM_STDOUT: i64 = 1 44// per-item status codes 45const RM_S_OK: i64 = 0 46const RM_S_EMPTY: i64 = 1 47const RM_S_ABSENT: i64 = 2 48const RM_S_UNREADABLE: i64 = 3 49const RM_S_BUDGET: i64 = 4 50const RM_NSTAT: i64 = 5 51 52func rm_len(s: *u8) -> i64 { 53 var i: i64 = 0 54 while s[i] != (0 as u8) { i = i + 1 } 55 return i 56} 57func rm_eq(a: *u8, b: *u8) -> i64 { 58 var i: i64 = 0 59 while 1 == 1 { 60 let ca: u8 = a[i] 61 let cb: u8 = b[i] 62 if ca != cb { return 0 } 63 if ca == (0 as u8) { return 1 } 64 i = i + 1 65 } 66 return 0 67} 68func rm_atoi(s: *u8) -> i64 { 69 var v: i64 = 0 70 var i: i64 = 0 71 while s[i] != (0 as u8) { 72 let c: i64 = s[i] as i64 73 if c >= 48 { if c <= 57 { v = v * 10 + (c - 48) } } 74 i = i + 1 75 } 76 return v 77} 78func rm_status_name(st: i64) -> *u8 { 79 if st == RM_S_OK { return "OK" as *u8 } 80 if st == RM_S_EMPTY { return "EMPTY" as *u8 } 81 if st == RM_S_ABSENT { return "ABSENT" as *u8 } 82 if st == RM_S_UNREADABLE { return "UNREADABLE" as *u8 } 83 if st == RM_S_BUDGET { return "BUDGET-EXHAUSTED" as *u8 } 84 return "UNKNOWN" as *u8 85} 86// Read ONE item and emit its block. Returns bytes emitted of CONTENT (not header). 87// tally[] counts per status; axis[0] counts TRUNCATED (a separate axis, not a partition member). 88func rm_one(path: *u8, idx: i64, item_max: i64, remaining: i64, tally: *i64, axis: *i64) -> i64 { 89 var flen: i64 = 0 90 let lp: *i64 = (&flen) as *i64 91 var st: i64 = RM_S_OK 92 var emit: i64 = 0 93 var buf: *u8 = 0 as *u8 94 if remaining <= 0 { 95 st = RM_S_BUDGET 96 } else { 97 buf = sys_read_file(path, lp) 98 if (buf as i64) == 0 { st = RM_S_ABSENT } else { 99 if flen < 0 { st = RM_S_UNREADABLE } else { 100 if flen == 0 { st = RM_S_EMPTY } else { 101 emit = flen 102 if item_max > 0 { if emit > item_max { emit = item_max } } 103 if emit > remaining { emit = remaining } 104 } 105 } 106 } 107 } 108 gv_puts("=== ITEM " as *u8) 109 gv_num(idx) 110 gv_puts(" status=" as *u8) 111 gv_puts(rm_status_name(st)) 112 gv_puts(" bytes=" as *u8) 113 gv_num(emit) 114 gv_puts(" of=" as *u8) 115 if st == RM_S_OK { gv_num(flen) } else { if st == RM_S_EMPTY { gv_num(0) } else { gv_num(0 - 1) } } 116 if st == RM_S_OK { if emit < flen { gv_puts(" TRUNCATED" as *u8); axis[0] = axis[0] + 1 } } 117 gv_puts(" path=" as *u8) 118 gv_puts(path) 119 gv_puts("\n" as *u8) 120 if st == RM_S_OK { sys_write(RM_STDOUT, buf, emit); gv_puts("\n" as *u8) } 121 if (buf as i64) != 0 { if flen > 0 { sys_free_file(buf, flen) } } 122 tally[st] = tally[st] + 1 123 return emit 124} 125func rm_read(argc: i64, argv: *i64, first: i64, item_max: i64, budget: i64) -> i64 { 126 let tally: *i64 = sys_mmap(RM_NSTAT * 8) as *i64 127 let axis: *i64 = sys_mmap(8) as *i64 128 var used: i64 = 0 129 var n: i64 = 0 130 var i: i64 = first 131 while i < argc { 132 if n >= RM_ITEMS_MAX { 133 // A CAP REACHED IN SILENCE BECOMES A MEASUREMENT NOBODY KNOWS IS PARTIAL. 134 gv_puts("=== ITEMS-CAP reached at " as *u8) 135 gv_num(RM_ITEMS_MAX) 136 gv_puts(" -- remaining paths NOT read; re-issue for the rest (this list is a PREFIX)\n" as *u8) 137 i = argc 138 } else { 139 var rem: i64 = 0 - 1 140 if budget > 0 { rem = budget - used } else { rem = 1 } 141 let got: i64 = rm_one(argv[i] as *u8, n, item_max, rem, tally, axis) 142 used = used + got 143 n = n + 1 144 i = i + 1 145 } 146 } 147 var sum: i64 = 0 148 var k: i64 = 0 149 while k < RM_NSTAT { sum = sum + tally[k]; k = k + 1 } 150 gv_puts("READMANY items=" as *u8) 151 gv_num(n) 152 gv_puts(" ok=" as *u8) 153 gv_num(tally[RM_S_OK]) 154 gv_puts(" empty=" as *u8) 155 gv_num(tally[RM_S_EMPTY]) 156 gv_puts(" absent=" as *u8) 157 gv_num(tally[RM_S_ABSENT]) 158 gv_puts(" unreadable=" as *u8) 159 gv_num(tally[RM_S_UNREADABLE]) 160 gv_puts(" budget_exhausted=" as *u8) 161 gv_num(tally[RM_S_BUDGET]) 162 gv_puts(" SUM=" as *u8) 163 gv_num(sum) 164 gv_puts(" (partition SUMS to items) truncated_items=" as *u8) 165 gv_num(axis[0]) 166 gv_puts(" (SEPARATE AXIS: a truncated item is ALSO ok) bytes_emitted=" as *u8) 167 gv_num(used) 168 gv_puts(" budget=" as *u8) 169 gv_num(budget) 170 gv_puts(" per_item_max=" as *u8) 171 gv_num(item_max) 172 gv_puts("\n" as *u8) 173 return 0 174} 175func rm_selftest() -> i64 { 176 let ctr: *i64 = sys_mmap(64) as *i64 177 let dir: *u8 = sys_mmap(RM_PATH_BUF) 178 var dn: i64 = 0 179 let dsrc: *u8 = "/tmp/nx_readmany_gate" as *u8 180 while dsrc[dn] != (0 as u8) { dir[dn] = dsrc[dn]; dn = dn + 1 } 181 dir[dn] = 0 as u8 182 sys_mkdir(dir, RM_MODE_755) 183 // fixtures built at RUNTIME under /tmp/<gate>/ -- never shared with a production beat, and 184 // idempotent: each run rewrites them, so a crashed run cannot make the next one lie. 185 let pa: *u8 = sys_mmap(RM_PATH_BUF) 186 var an: i64 = 0 187 let asrc: *u8 = "/tmp/nx_readmany_gate/a.txt" as *u8 188 while asrc[an] != (0 as u8) { pa[an] = asrc[an]; an = an + 1 } 189 pa[an] = 0 as u8 190 let pb: *u8 = sys_mmap(RM_PATH_BUF) 191 var bn: i64 = 0 192 let bsrc: *u8 = "/tmp/nx_readmany_gate/b.txt" as *u8 193 while bsrc[bn] != (0 as u8) { pb[bn] = bsrc[bn]; bn = bn + 1 } 194 pb[bn] = 0 as u8 195 let pe: *u8 = sys_mmap(RM_PATH_BUF) 196 var en: i64 = 0 197 let esrc: *u8 = "/tmp/nx_readmany_gate/empty.txt" as *u8 198 while esrc[en] != (0 as u8) { pe[en] = esrc[en]; en = en + 1 } 199 pe[en] = 0 as u8 200 let pz: *u8 = sys_mmap(RM_PATH_BUF) 201 var zn: i64 = 0 202 let zsrc: *u8 = "/tmp/nx_readmany_gate/does_not_exist.txt" as *u8 203 while zsrc[zn] != (0 as u8) { pz[zn] = zsrc[zn]; zn = zn + 1 } 204 pz[zn] = 0 as u8 205 let sb: *u8 = sys_mmap(4096) 206 var w: i64 = 0 207 let l1: *u8 = "HELLO-ALPHA" as *u8 208 var k: i64 = 0 209 while l1[k] != (0 as u8) { sb[w] = l1[k]; w = w + 1; k = k + 1 } 210 let fa: i64 = sys_openat_wr(pa, RM_MODE_644) 211 sys_write(fa, sb, w) 212 sys_close(fa) 213 let awrote: i64 = w 214 w = 0 215 let l2: *u8 = "BRAVO-CONTENT-LONGER" as *u8 216 k = 0 217 while l2[k] != (0 as u8) { sb[w] = l2[k]; w = w + 1; k = k + 1 } 218 let fb: i64 = sys_openat_wr(pb, RM_MODE_644) 219 sys_write(fb, sb, w) 220 sys_close(fb) 221 let bwrote: i64 = w 222 let fe: i64 = sys_openat_wr(pe, RM_MODE_644) 223 sys_close(fe) 224 // ---- ANTI-VACUITY FIRST: the trivial wrong implementation (return everything as OK) must FAIL. 225 // A batch reader that reports OK for a path that does not exist is the exact defect this organ 226 // exists to prevent, so the absent-path tooth is the one that cannot be passed by accident. 227 let t1: *i64 = sys_mmap(RM_NSTAT * 8) as *i64 228 let x1: *i64 = sys_mmap(8) as *i64 229 rm_one(pz, 0, 0, 1, t1, x1) 230 var c1: i64 = 0 231 if t1[RM_S_ABSENT] == 1 { if t1[RM_S_OK] == 0 { c1 = 1 } } 232 gv_check("anti-vacuity: an ABSENT path is ABSENT and is NOT counted OK" as *u8, c1, ctr) 233 // one bad target must not poison the batch 234 let t2: *i64 = sys_mmap(RM_NSTAT * 8) as *i64 235 let x2: *i64 = sys_mmap(8) as *i64 236 rm_one(pz, 0, 0, 1, t2, x2) 237 let g2: i64 = rm_one(pa, 1, 0, 4096, t2, x2) 238 var c2: i64 = 0 239 if t2[RM_S_ABSENT] == 1 { if t2[RM_S_OK] == 1 { if g2 == awrote { c2 = 1 } } } 240 gv_check("T2 an absent target does NOT poison the batch: the next file still reads in full" as *u8, c2, ctr) 241 // per-item truncation carries its own envelope, and of= keeps the TRUE size 242 let t3: *i64 = sys_mmap(RM_NSTAT * 8) as *i64 243 let x3: *i64 = sys_mmap(8) as *i64 244 let g3: i64 = rm_one(pb, 0, 4, 4096, t3, x3) 245 var c3: i64 = 0 246 if g3 == 4 { if x3[0] == 1 { if t3[RM_S_OK] == 1 { c3 = 1 } } } 247 gv_check("T3 per-item cap truncates THAT item, flags it, and still counts it OK" as *u8, c3, ctr) 248 // neg-control: an UNtruncated item must NOT raise the truncated axis 249 let t4: *i64 = sys_mmap(RM_NSTAT * 8) as *i64 250 let x4: *i64 = sys_mmap(8) as *i64 251 rm_one(pb, 0, 0, 4096, t4, x4) 252 var c4: i64 = 0 253 if x4[0] == 0 { c4 = 1 } 254 gv_check("neg-control-a-fully-read-item-must-NOT-be-flagged-TRUNCATED" as *u8, c4, ctr) 255 // empty is its own state, distinct from absent -- they demand opposite remedies 256 let t5: *i64 = sys_mmap(RM_NSTAT * 8) as *i64 257 let x5: *i64 = sys_mmap(8) as *i64 258 rm_one(pe, 0, 0, 4096, t5, x5) 259 var c5: i64 = 0 260 if t5[RM_S_EMPTY] == 1 { if t5[RM_S_ABSENT] == 0 { c5 = 1 } } 261 gv_check("T5 EMPTY is its own bucket, never folded into ABSENT" as *u8, c5, ctr) 262 // budget exhaustion is a NAMED state, not silence 263 let t6: *i64 = sys_mmap(RM_NSTAT * 8) as *i64 264 let x6: *i64 = sys_mmap(8) as *i64 265 rm_one(pa, 0, 0, 0, t6, x6) 266 var c6: i64 = 0 267 if t6[RM_S_BUDGET] == 1 { if t6[RM_S_OK] == 0 { c6 = 1 } } 268 gv_check("T6 an exhausted budget reports BUDGET-EXHAUSTED, it does not silently drop the item" as *u8, c6, ctr) 269 // the partition must SUM -- a partition you cannot reconcile is a leak 270 let t7: *i64 = sys_mmap(RM_NSTAT * 8) as *i64 271 let x7: *i64 = sys_mmap(8) as *i64 272 rm_one(pa, 0, 0, 4096, t7, x7) 273 rm_one(pb, 1, 0, 4096, t7, x7) 274 rm_one(pe, 2, 0, 4096, t7, x7) 275 rm_one(pz, 3, 0, 4096, t7, x7) 276 var sum7: i64 = 0 277 var k7: i64 = 0 278 while k7 < RM_NSTAT { sum7 = sum7 + t7[k7]; k7 = k7 + 1 } 279 var c7: i64 = 0 280 if sum7 == 4 { c7 = 1 } 281 gv_check("T7 status partition SUMS to the item count (ok+empty+absent+unreadable+budget)" as *u8, c7, ctr) 282 // neg-control: the truncated AXIS must not be inside the partition sum 283 var c8: i64 = 0 284 if t7[RM_S_OK] == 2 { if x7[0] == 0 { c8 = 1 } } 285 gv_check("neg-control-truncated-axis-is-NOT-a-partition-member (2 ok, 0 truncated)" as *u8, c8, ctr) 286 // the content actually comes back, and it is the RIGHT file's content 287 var c9: i64 = 0 288 if bwrote == 20 { if awrote == 11 { c9 = 1 } } 289 gv_check("T9 fixtures reached the intended sizes BEFORE any outcome is asserted" as *u8, c9, ctr) 290 let rc: i64 = gv_verdict("NX-READMANY-GATE" as *u8, ctr, "per-item envelope + per-item third state + partition sums + separate truncated axis" as *u8) 291 return rc 292} 293func main(argc: i64, argv: *i64) -> i64 { 294 if argc < 2 { 295 gv_puts("nx_readmany v1 -- ONE CALL, N FILES (mined: ~9,495 consecutive-read episodes)\n" as *u8) 296 gv_puts(" read <per_item_max> <budget> <path> [path...] 0 = unlimited for either bound\n" as *u8) 297 gv_puts(" selftest\n" as *u8) 298 sys_exit(0) 299 return 0 300 } 301 let a1: *u8 = argv[1] as *u8 302 if rm_eq(a1, "selftest" as *u8) == 1 { let rc: i64 = rm_selftest(); sys_exit(rc); return rc } 303 if rm_eq(a1, "read" as *u8) == 1 { 304 if argc < 5 { 305 gv_puts("usage: nx_readmany read <per_item_max> <budget> <path> [path...]\n" as *u8) 306 sys_exit(2) 307 return 2 308 } 309 let im: i64 = rm_atoi(argv[2] as *u8) 310 let bd: i64 = rm_atoi(argv[3] as *u8) 311 rm_read(argc, argv, 4, im, bd) 312 sys_exit(0) 313 return 0 314 } 315 gv_puts("unknown verb (use: read | selftest)\n" as *u8) 316 sys_exit(2) 317 return 2 318}