code wiki / (root) / nx_sizeguard.nx

nx_sizeguard.nx source

↩ module page · 131 lines · 5861 B

1// nx_sizeguard.nx -- FAIL LOUD BEFORE A READER SILENTLY TRUNCATES (seq1469 root fix #1). 2// 3// THE CLASS: MEMORY.md is read by a loader that takes the first ~200 lines / ~25KB and DROPS THE REST 4// SILENTLY, TAIL-FIRST. No error, no marker, no count -- so the dropped lines are precisely the ones you 5// would need in order to learn they were dropped. That is the partial-as-complete defect this ecosystem 6// has banned repeatedly (L011 scancap, seq646, nx_debt truncation), sitting in the BOOT PATH. 7// 8// AND IT IS NOT ONE FILE. Append-only artefacts grow forever by design: knowledge/status/*.jrnl, 9// law_warden.jrnl, and -- MY OWN DEBT FROM THIS SESSION -- procchurn.jrnl and adopt_census.txt, both of 10// which I created with no size discipline while filing debt about exactly this. 11// LAW: AN APPEND-ONLY FILE WITH NO SIZE DISCIPLINE IS A FUTURE SILENT TRUNCATION. 12// 13// THE FIX IS A REFUSAL, NOT A REMINDER. Compaction is a workaround every session must repeat forever on 14// files that grow by design; a guard converts an invisible cliff into a loud verdict BEFORE it is crossed. 15// Lives in runtime/ (the PRIMITIVE layer) so any organ can reach it -- seq1450: build the primitive in the 16// layer its consumers can reach; imports nothing above its own layer. 17// argv: <path> <byte-cliff> <line-cliff> [amber-permil] 18// exit 0=GREEN 1=AMBER 2=RED(over cliff) 3=UNMEASURED. license_tier: ORIGINAL No hw writes (Rule 26). 19import "nx_syscalls.nx" 20 21const SG_READBUF: i64 = 65536 22const SG_PERMIL: i64 = 1000 23const SG_DEF_AMBER: i64 = 800 24const SG_NL: i64 = 10 25const SG_GREEN: i64 = 0 26const SG_AMBER: i64 = 1 27const SG_RED: i64 = 2 28const SG_UNMEASURED: i64 = 3 29 30// fill of a budget, in permil. -1 when the cliff is nonsense (never divide by it). 31func sg_fill_permil(cur: i64, cliff: i64) -> i64 { 32 if cliff <= 0 { return 0 - 1 } 33 if cur < 0 { return 0 - 1 } 34 return (cur * SG_PERMIL) / cliff 35} 36 37// Verdict over BOTH axes. A tail-first loader truncates on WHICHEVER limit is hit first, so a guard that 38// watches only bytes is blind to a line-count cliff and vice-versa -- the worst axis decides. 39// FAIL-CLOSED: an unmeasurable axis returns UNMEASURED rather than a comfortable GREEN. 40func sg_verdict(bytes: i64, lines: i64, byte_cliff: i64, line_cliff: i64, amber_permil: i64) -> i64 { 41 if amber_permil <= 0 { return SG_UNMEASURED } 42 let bf: i64 = sg_fill_permil(bytes, byte_cliff) 43 let lf: i64 = sg_fill_permil(lines, line_cliff) 44 if bf < 0 { return SG_UNMEASURED } 45 if lf < 0 { return SG_UNMEASURED } 46 var sev: i64 = SG_GREEN 47 if bf >= amber_permil { sev = SG_AMBER } 48 if lf >= amber_permil { sev = SG_AMBER } 49 if bf >= SG_PERMIL { sev = SG_RED } 50 if lf >= SG_PERMIL { sev = SG_RED } 51 return sev 52} 53 54// how many bytes may still be appended before the byte cliff; 0 once past it (never negative) 55func sg_headroom(cur: i64, cliff: i64) -> i64 { 56 if cliff <= 0 { return 0 - 1 } 57 if cur >= cliff { return 0 } 58 return cliff - cur 59} 60 61func sg_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 62func sg_num(v: i64) -> i64 { 63 let t: *u8 = sys_mmap(32) 64 let b: *u8 = sys_mmap(32) 65 var m: i64 = v 66 var p: i64 = 0 67 if m < 0 { b[p] = 45 as u8; p = p + 1; m = 0 - m } 68 var k: i64 = 0 69 if m == 0 { t[0] = 48 as u8; k = 1 } 70 while m > 0 { t[k] = (48 + (m - (m / 10) * 10)) as u8; m = m / 10; k = k + 1 } 71 var i: i64 = 0 72 while i < k { b[p + i] = t[k - 1 - i]; i = i + 1 } 73 sys_write(1, b, p + k) 74 sys_munmap(t, 32) 75 sys_munmap(b, 32) 76 return 0 77} 78func sg_atoi(s: *u8) -> i64 { 79 var v: i64 = 0 80 var i: i64 = 0 81 while s[i] != (0 as u8) { 82 let c: i64 = s[i] as i64 83 if c < 48 { return 0 - 1 } 84 if c > 57 { return 0 - 1 } 85 v = v * 10 + (c - 48) 86 i = i + 1 87 } 88 if i == 0 { return 0 - 1 } 89 return v 90} 91 92func main(argc: i64, argv: *i64) -> i64 { 93 if argc < 4 { sg_puts("usage: nx_sizeguard <path> <byte-cliff> <line-cliff> [amber-permil]\n" as *u8); return SG_UNMEASURED } 94 let path: *u8 = argv[1] as *u8 95 let bcliff: i64 = sg_atoi(argv[2] as *u8) 96 let lcliff: i64 = sg_atoi(argv[3] as *u8) 97 var amber: i64 = SG_DEF_AMBER 98 if argc >= 5 { let a: i64 = sg_atoi(argv[4] as *u8); if a > 0 { amber = a } } 99 100 let fd: i64 = sys_openat_rd(path) 101 if fd < 0 { sg_puts("NX-SIZEGUARD verdict=UNMEASURED why=unreadable path=" as *u8); sg_puts(path); sg_puts("\n" as *u8); return SG_UNMEASURED } 102 let buf: *u8 = sys_mmap(SG_READBUF) 103 var bytes: i64 = 0 104 var lines: i64 = 0 105 var r: i64 = sys_read(fd, buf, SG_READBUF) 106 while r > 0 { 107 bytes = bytes + r 108 var i: i64 = 0 109 while i < r { if buf[i] == (SG_NL as u8) { lines = lines + 1 } i = i + 1 } 110 r = sys_read(fd, buf, SG_READBUF) 111 } 112 sys_close(fd) 113 sys_munmap(buf, SG_READBUF) 114 115 let sev: i64 = sg_verdict(bytes, lines, bcliff, lcliff, amber) 116 sg_puts("NX-SIZEGUARD path=" as *u8); sg_puts(path) 117 sg_puts(" bytes=" as *u8); sg_num(bytes) 118 sg_puts("/" as *u8); sg_num(bcliff) 119 sg_puts(" (" as *u8); sg_num(sg_fill_permil(bytes, bcliff)); sg_puts("permil)" as *u8) 120 sg_puts(" lines=" as *u8); sg_num(lines) 121 sg_puts("/" as *u8); sg_num(lcliff) 122 sg_puts(" (" as *u8); sg_num(sg_fill_permil(lines, lcliff)); sg_puts("permil)" as *u8) 123 sg_puts(" headroom_bytes=" as *u8); sg_num(sg_headroom(bytes, bcliff)) 124 sg_puts(" verdict=" as *u8) 125 if sev == SG_GREEN { sg_puts("GREEN" as *u8) } 126 if sev == SG_AMBER { sg_puts("AMBER -- compact BEFORE the reader starts dropping the tail" as *u8) } 127 if sev == SG_RED { sg_puts("RED -- PAST THE CLIFF: a reader is ALREADY dropping content SILENTLY" as *u8) } 128 if sev == SG_UNMEASURED { sg_puts("UNMEASURED" as *u8) } 129 sg_puts(" sev=" as *u8); sg_num(sev); sg_puts("\n" as *u8) 130 return sev 131}