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}