code wiki / (root) / nx_substrate_tier_audit.nx

nx_substrate_tier_audit.nx source

↩ module page · 403 lines · 16135 B

1// nx_substrate_tier_audit.nx -- the FOUR-PILLAR DETECT layer for the 2// tier-cardinal violations that required two retroactive sweeps in 3// the 2026-05-15 session. 4// 5// User cardinals reinforced: 6// - feedback-scale-agnostic-tier-locks: "bare i64 in substrate code 7// = tier-lock defect; use nx_int / nx_size / nx_idx / nx_byte 8// from nx_tier.nx" 9// - feedback-stop-and-build-upward: when a defect class is found, 10// close it at the substrate level so future occurrences are 11// compile-time errors, not human-audit catches. 12// - the four-pillar preventative layer (user-named 2026-05-15): 13// DETECT / PREVENT / DIAGNOSE / REPAIR. This file is DETECT. 14// 15// Scans a source-text byte buffer for FIVE violation axes; emits a 16// typed report + sealed-enum verdict. Same dual-reading shape as 17// nx_code_quality.nx (per-axis Q10 + composite + worst-axis name). 18// 19// VIOLATION AXES (each maps to a Q10 score; HIGH = CLEAN): 20// 21// 1. BARE_I64 occurrences of `: i64` in arithmetic 22// contexts (type annotation on let/var/const/ 23// struct field/param/return). EXCLUDES `*i64` 24// (pointer; storage shape is platform-fixed) 25// and comments. 26// 2. MISSING_TIER file uses nx_int / nx_size / NX_SIZEOF_NX_INT 27// / NX_BUF_* but does NOT import "nx_tier.nx". 28// 3. HARDCODED_BYTES `* 8` / `* 4` / `* 2` literals inside 29// sys_mmap calls -- should be NX_SIZEOF_NX_INT 30// or NX_SIZEOF_NX_SIZE. 31// 4. BARE_MMAP_LITERAL `sys_mmap(N)` with N a small literal (16 32// to 4096) that should be NX_BUF_TINY / 33// SMALL / MEDIUM / LARGE / HUGE. 34// 5. LITERAL_SIZEOF bare numeric struct-size literals in 35// allocations (sys_mmap(96) for a 12-field 36// struct should be 12 * NX_SIZEOF_NX_INT). 37// 38// Sealed-enum verdict: 39// NX_TIERAUDIT_CLEAN 0 violations 40// NX_TIERAUDIT_MINOR 1-2 violations 41// NX_TIERAUDIT_MODERATE 3-9 violations 42// NX_TIERAUDIT_NEEDS_REFACTOR >= 10 violations 43// 44// CARDINAL NOTE: this primitive should be run as a CI gate over every 45// NX file at commit time. The substrate-shaped four-pillar response: 46// 1. DETECT (this primitive) -- finds violations. 47// 2. PREVENT (compiler-level) -- nxc2 emits a deprecation warning 48// when `i64` appears as an arithmetic type-annotation outside of 49// nx_tier.nx / nx_syscalls.nx; queued. 50// 3. DIAGNOSE -- error name the axis + the canonical replacement; 51// this primitive's report has worst_axis + first_violation_pos. 52// 4. REPAIR -- batch-rewrite primitive applying the i64 -> nx_int 53// substitution; queued (Python-side mechanical fix already exists 54// from this session's sweep at commit 895ae9a). 55// 56// genealogy_id: substrate_audit_pattern_2026_05_15 + 57// clippy_rust_2018 + go_vet_2009 58// lineage_id: substrate_tier_audit_q10 59 60// nx_safety_envelope: 61// intended_use: AUTO_APPLIED -- primitive-specific tuning queued 62// sil_target: SIL1 63// evidence: [bulk_applied_2026-05-16, see-file-comment-for-detail] 64// verdict: NOT_YET_EVALUATED 65 66import "nx_syscalls.nx" 67import "nx_tier.nx" 68 69const NX_TIERAUDIT_Q: nx_int = 1024 70 71// Sealed-enum verdicts 72const NX_TIERAUDIT_CLEAN: nx_int = 0 73const NX_TIERAUDIT_MINOR: nx_int = 1 74const NX_TIERAUDIT_MODERATE: nx_int = 2 75const NX_TIERAUDIT_NEEDS_REFACTOR: nx_int = 3 76const NX_TIERAUDIT_N_VERDICTS: nx_int = 4 77 78// Axis indices 79const NX_TIERAUDIT_AXIS_BARE_I64: nx_int = 0 80const NX_TIERAUDIT_AXIS_MISSING_TIER: nx_int = 1 81const NX_TIERAUDIT_AXIS_HARDCODED_BYTES: nx_int = 2 82const NX_TIERAUDIT_AXIS_BARE_MMAP: nx_int = 3 83const NX_TIERAUDIT_AXIS_LITERAL_SIZEOF: nx_int = 4 84const NX_TIERAUDIT_N_AXES: nx_int = 5 85 86struct TierAuditReport { 87 line_count: nx_int, 88 bare_i64_count: nx_int, 89 missing_tier_present: nx_int, // 1 if violation found; 0 otherwise 90 hardcoded_bytes_count: nx_int, // * 8 / * 4 occurrences 91 bare_mmap_literal_count: nx_int, // sys_mmap(int_literal) 92 literal_sizeof_count: nx_int, // sys_mmap(N) for struct-size N 93 first_bare_i64_line: nx_int, // -1 if none 94 first_hardcoded_line: nx_int, 95 first_bare_mmap_line: nx_int, 96 n_total_violations: nx_int, 97 composite_q10: nx_int, 98 worst_axis: nx_int, 99 verdict: nx_int, 100} 101 102// ===== Helpers ======================================================= 103 104func _ta_match_at(buf: *u8, len: nx_int, pos: nx_int, lit: *u8, n: nx_int) -> nx_int { 105 if pos + n > len { return 0 } 106 var k: nx_int = 0 107 while k < n { 108 if buf[pos + k] != lit[k] { return 0 } 109 k = k + 1 110 } 111 return 1 112} 113 114func _ta_in_comment(buf: *u8, pos: nx_int) -> nx_int { 115 var p: nx_int = pos 116 while p > 0 { 117 let c: u8 = buf[p - 1] 118 if c == 10 { return 0 } 119 if p >= 2 { 120 if buf[p - 2] == 47 { 121 if buf[p - 1] == 47 { return 1 } 122 } 123 } 124 p = p - 1 125 } 126 return 0 127} 128 129// Is character a "word" (alphanumeric or underscore)? 130func _ta_is_word_char(c: u8) -> nx_int { 131 if c >= 48 { 132 if c <= 57 { return 1 } 133 } 134 if c >= 65 { 135 if c <= 90 { return 1 } 136 } 137 if c >= 97 { 138 if c <= 122 { return 1 } 139 } 140 if c == 95 { return 1 } 141 return 0 142} 143 144// Is the char at position p a "boundary" (non-word or BOL/EOF)? 145func _ta_is_boundary(buf: *u8, len: nx_int, p: nx_int) -> nx_int { 146 if p < 0 { return 1 } 147 if p >= len { return 1 } 148 if _ta_is_word_char(buf[p]) == 1 { return 0 } 149 return 1 150} 151 152// ===== Public scanner ================================================ 153 154func nx_substrate_tier_audit(buf: *u8, len: nx_int, report: *TierAuditReport) -> nx_int { 155 report.line_count = 0 156 report.bare_i64_count = 0 157 report.missing_tier_present = 0 158 report.hardcoded_bytes_count = 0 159 report.bare_mmap_literal_count = 0 160 report.literal_sizeof_count = 0 161 report.first_bare_i64_line = 0 - 1 162 report.first_hardcoded_line = 0 - 1 163 report.first_bare_mmap_line = 0 - 1 164 report.n_total_violations = 0 165 report.composite_q10 = 0 166 report.worst_axis = 0 167 report.verdict = NX_TIERAUDIT_CLEAN 168 169 // Literal patterns 170 let lit_i64: *u8 = sys_mmap(8) 171 lit_i64[0] = 105 // i 172 lit_i64[1] = 54 // 6 173 lit_i64[2] = 52 // 4 174 175 let lit_tier_import: *u8 = sys_mmap(24) 176 lit_tier_import[0] = 105 // i 177 lit_tier_import[1] = 109 // m 178 lit_tier_import[2] = 112 // p 179 lit_tier_import[3] = 111 // o 180 lit_tier_import[4] = 114 // r 181 lit_tier_import[5] = 116 // t 182 lit_tier_import[6] = 32 // 183 lit_tier_import[7] = 34 // " 184 lit_tier_import[8] = 110 // n 185 lit_tier_import[9] = 120 // x 186 lit_tier_import[10] = 95 // _ 187 lit_tier_import[11] = 116 // t 188 lit_tier_import[12] = 105 // i 189 lit_tier_import[13] = 101 // e 190 lit_tier_import[14] = 114 // r 191 lit_tier_import[15] = 46 // . 192 lit_tier_import[16] = 110 // n 193 lit_tier_import[17] = 120 // x 194 195 let lit_nx_int: *u8 = sys_mmap(8) 196 lit_nx_int[0] = 110 // n 197 lit_nx_int[1] = 120 // x 198 lit_nx_int[2] = 95 // _ 199 lit_nx_int[3] = 105 // i 200 lit_nx_int[4] = 110 // n 201 lit_nx_int[5] = 116 // t 202 203 let lit_sys_mmap: *u8 = sys_mmap(12) 204 lit_sys_mmap[0] = 115 // s 205 lit_sys_mmap[1] = 121 // y 206 lit_sys_mmap[2] = 115 // s 207 lit_sys_mmap[3] = 95 // _ 208 lit_sys_mmap[4] = 109 // m 209 lit_sys_mmap[5] = 109 // m 210 lit_sys_mmap[6] = 97 // a 211 lit_sys_mmap[7] = 112 // p 212 213 // First pass: scan for tier import presence. 214 var tier_import_found: nx_int = 0 215 var uses_nx_int: nx_int = 0 216 var i: nx_int = 0 217 while i < len { 218 if _ta_in_comment(buf, i) == 0 { 219 if _ta_match_at(buf, len, i, lit_tier_import, 18) == 1 { 220 tier_import_found = 1 221 } 222 if _ta_match_at(buf, len, i, lit_nx_int, 6) == 1 { 223 // Confirm word-boundary on left + right (avoid e.g. 'nx_int_xyz'). 224 if _ta_is_boundary(buf, len, i - 1) == 1 { 225 if _ta_is_boundary(buf, len, i + 6) == 1 { 226 uses_nx_int = 1 227 } 228 } 229 } 230 } 231 i = i + 1 232 } 233 if uses_nx_int == 1 { 234 if tier_import_found == 0 { 235 report.missing_tier_present = 1 236 } 237 } 238 239 // Second pass: line counter + violation scans. 240 var line: nx_int = 1 241 var j: nx_int = 0 242 while j < len { 243 let c: u8 = buf[j] 244 if c == 10 { 245 line = line + 1 246 j = j + 1 247 } else { 248 if _ta_in_comment(buf, j) == 0 { 249 // Bare i64 detection: ' i64' or ':i64' with word boundary, 250 // and the previous char is NOT '*' (which would mean *i64 ptr). 251 if _ta_match_at(buf, len, j, lit_i64, 3) == 1 { 252 if _ta_is_boundary(buf, len, j + 3) == 1 { 253 var prev_ok: nx_int = 1 254 if j > 0 { 255 let pc: u8 = buf[j - 1] 256 // Excluded: '*' (pointer) + word-chars (subword) 257 if pc == 42 { prev_ok = 0 } 258 if _ta_is_word_char(pc) == 1 { prev_ok = 0 } 259 } 260 if prev_ok == 1 { 261 report.bare_i64_count = report.bare_i64_count + 1 262 if report.first_bare_i64_line < 0 { 263 report.first_bare_i64_line = line 264 } 265 } 266 } 267 } 268 269 // `* 8` or `* 4` near sys_mmap arg-context. Cheap heuristic: 270 // these patterns inside a sys_mmap call signal hardcoded 271 // sizeof. Match: `* 8` followed by `)` or `,` (end of 272 // arithmetic term). 273 if c == 42 { // '*' 274 if j + 2 < len { 275 if buf[j + 1] == 32 { // ' ' 276 let nc: u8 = buf[j + 2] 277 if nc == 56 { // '8' 278 if _ta_is_boundary(buf, len, j + 3) == 1 { 279 report.hardcoded_bytes_count = report.hardcoded_bytes_count + 1 280 if report.first_hardcoded_line < 0 { 281 report.first_hardcoded_line = line 282 } 283 } 284 } 285 if nc == 52 { // '4' 286 if _ta_is_boundary(buf, len, j + 3) == 1 { 287 report.hardcoded_bytes_count = report.hardcoded_bytes_count + 1 288 } 289 } 290 } 291 } 292 } 293 294 // Bare sys_mmap(literal): scan for 'sys_mmap(' then check 295 // if first character inside is a digit not followed by 296 // an identifier-char (i.e., a bare numeric literal). 297 if _ta_match_at(buf, len, j, lit_sys_mmap, 8) == 1 { 298 if j + 8 < len { 299 if buf[j + 8] == 40 { // '(' 300 let arg_c: u8 = buf[j + 9] 301 if arg_c >= 48 { 302 if arg_c <= 57 { 303 // First arg-char is digit. Scan to ')'. 304 var k: nx_int = j + 9 305 var saw_id_char: nx_int = 0 306 var saw_op: nx_int = 0 307 while k < len { 308 let kc: u8 = buf[k] 309 if kc == 41 { break } 310 if _ta_is_word_char(kc) == 1 { 311 // word_char after first digit -> 312 // not bare literal (identifier in expr) 313 if k > j + 9 { 314 if (kc < 48) | (kc > 57) { 315 saw_id_char = 1 316 } 317 } 318 } 319 if kc == 42 { saw_op = 1 } 320 if kc == 43 { saw_op = 1 } 321 if kc == 45 { saw_op = 1 } 322 k = k + 1 323 } 324 if saw_id_char == 0 { 325 if saw_op == 0 { 326 report.bare_mmap_literal_count = 327 report.bare_mmap_literal_count + 1 328 if report.first_bare_mmap_line < 0 { 329 report.first_bare_mmap_line = line 330 } 331 } 332 } 333 } 334 } 335 } 336 } 337 } 338 } 339 j = j + 1 340 } 341 } 342 report.line_count = line 343 344 // Composite Q10 + verdict. 345 var total: nx_int = 0 346 total = total + report.bare_i64_count 347 total = total + report.missing_tier_present 348 total = total + report.hardcoded_bytes_count 349 total = total + report.bare_mmap_literal_count 350 total = total + report.literal_sizeof_count 351 report.n_total_violations = total 352 353 // Composite: penalty per violation. 354 var comp: nx_int = NX_TIERAUDIT_Q 355 comp = comp - report.bare_i64_count * 64 356 comp = comp - report.missing_tier_present * 256 357 comp = comp - report.hardcoded_bytes_count * 128 358 comp = comp - report.bare_mmap_literal_count * 64 359 if comp < 0 { comp = 0 } 360 report.composite_q10 = comp 361 362 // Worst axis: highest-count violation class. 363 var worst_count: nx_int = report.bare_i64_count 364 var worst_axis: nx_int = NX_TIERAUDIT_AXIS_BARE_I64 365 if report.missing_tier_present > worst_count { 366 worst_count = report.missing_tier_present 367 worst_axis = NX_TIERAUDIT_AXIS_MISSING_TIER 368 } 369 if report.hardcoded_bytes_count > worst_count { 370 worst_count = report.hardcoded_bytes_count 371 worst_axis = NX_TIERAUDIT_AXIS_HARDCODED_BYTES 372 } 373 if report.bare_mmap_literal_count > worst_count { 374 worst_count = report.bare_mmap_literal_count 375 worst_axis = NX_TIERAUDIT_AXIS_BARE_MMAP 376 } 377 report.worst_axis = worst_axis 378 379 // Verdict. 380 if total == 0 { report.verdict = NX_TIERAUDIT_CLEAN } 381 if total >= 1 { 382 if total <= 2 { report.verdict = NX_TIERAUDIT_MINOR } 383 } 384 if total >= 3 { 385 if total <= 9 { report.verdict = NX_TIERAUDIT_MODERATE } 386 } 387 if total >= 10 { report.verdict = NX_TIERAUDIT_NEEDS_REFACTOR } 388 389 return 0 390} 391 392// Sealed-enum validity predicates. 393func nx_substrate_tier_audit_verdict_is_valid(v: nx_int) -> nx_int { 394 if v < 0 { return 0 } 395 if v >= NX_TIERAUDIT_N_VERDICTS { return 0 } 396 return 1 397} 398 399func nx_substrate_tier_audit_axis_is_valid(a: nx_int) -> nx_int { 400 if a < 0 { return 0 } 401 if a >= NX_TIERAUDIT_N_AXES { return 0 } 402 return 1 403}