nx_formatlaw_lib.nx source
↩ module page · 212 lines · 11830 B
1// nx_formatlaw_lib.nx -- THE SOURCE-LAW SCANNER (operator 2026-09-02: "these are estate wide things that need
2// autonomous management as you keep breaking them and putting 3rd parties in build lanes and using tsvs and
3// other old crappy formats and ignoring licenses and patents").
4//
5// ONE RULER, THREE LAWS, over the STRING LITERALS of a NishiLang source (comments are skipped: a law that cannot
6// tell code from the comment describing it flags every explanation of the defect it hunts):
7// F1 DURABLE-LEGACY-FORMAT a path literal ending .tsv .csv .sqlite .db .xml .yaml .yml .ini .toml .jsonl
8// anywhere, and .json under knowledge/ -- durable estate state belongs in the
9// sovereign store plane (knowledge/store/<prefix>-, nx_store_seed_lib), never a
10// third-party file format beside it. EXEMPT: knowledge/fetched/ (mirrored evidence
11// is whatever the publisher shipped), /tmp/ (fixtures), sites/ web_assets/ _jobs/
12// (wire formats a browser or a job runner reads), and specs/ (documents).
13// F2 THIRD-PARTY-EXEC a literal beginning /bin/ /usr/bin/ /usr/local/bin/ /sbin/ /usr/sbin/ /opt/ --
14// a NishiLang fork needs an absolute path, so every third-party tool in a build or
15// serving lane carries exactly this shape; the estate's own organs live under the
16// serving root, ./ or _offc/.
17// F3 NO-LICENSE-TIER the source carries no `license_tier:` declaration, so its shippability and its
18// IP posture are unknown to nx_licgate and to the review queue.
19// IT NEVER BLOCKS. Every hit is a NAMED, LOCATED finding (class, file, line, literal, remedy) for the REVIEW
20// QUEUE plane (knowledge/store/review-, 7-col debt grammar so the estate's board readers already read it), and
21// the same rows print to the seat at write time through the PreToolUse hook verb. A ratchet that refuses NEW
22// offenders in the build lane is a separate decision the operator takes after seeing the queue.
23// license_tier: ORIGINAL No hw writes (Rule 26).
24import "nx_syscalls.nx"
25
26const FL_F1: i64 = 1
27const FL_F1J: i64 = 2
28const FL_F2: i64 = 3
29const FL_F3: i64 = 4
30const FL_CLASSES: i64 = 5 // counts array size (index 0 unused)
31const FL_MAX_LIT: i64 = 512 // a path literal longer than this is not a path
32const FL_MAX_HITS: i64 = 256 // findings kept per file; the count keeps counting past it and the report SAYS so
33const FL_HIT_WORDS: i64 = 4 // per hit: class, line, lit_start, lit_end
34const FL_CH_QUOTE: i64 = 34
35const FL_CH_BSLASH: i64 = 92
36const FL_CH_SLASH: i64 = 47
37const FL_CH_NL: i64 = 10
38const FL_CH_DOT: i64 = 46
39const FL_LICENSE_TOKEN: *u8 = "license_tier:"
40// the review plane and its 7-col grammar (id title sev status owner scope note)
41const FL_REVIEW_PLANE: *u8 = "knowledge/store/review-"
42const FL_SEV_F1: i64 = 5
43const FL_SEV_F1J: i64 = 3
44const FL_SEV_F2: i64 = 6
45const FL_SEV_F3: i64 = 4
46const FL_FNV_OFFSET: i64 = 1469598103934665603
47const FL_FNV_PRIME: i64 = 1099511628211
48
49func fl_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
50func fl_lower(c: i64) -> i64 { if c >= 65 { if c <= 90 { return c + 32 } } return c }
51// does buf[a..e) end with lit (case-insensitive)?
52func fl_ends_ci(b: *u8, a: i64, e: i64, lit: *u8) -> i64 {
53 let l: i64 = fl_slen(lit)
54 if e - a < l { return 0 }
55 var i: i64 = 0
56 while i < l { if fl_lower(b[e - l + i] as i64) != fl_lower(lit[i] as i64) { return 0 } i = i + 1 }
57 return 1
58}
59func fl_starts(b: *u8, a: i64, e: i64, lit: *u8) -> i64 {
60 let l: i64 = fl_slen(lit)
61 if e - a < l { return 0 }
62 var i: i64 = 0
63 while i < l { if b[a + i] != lit[i] { return 0 } i = i + 1 }
64 return 1
65}
66func fl_contains(b: *u8, a: i64, e: i64, lit: *u8) -> i64 {
67 let l: i64 = fl_slen(lit)
68 if l == 0 { return 0 }
69 var i: i64 = a
70 while i + l <= e {
71 var m: i64 = 1
72 var k: i64 = 0
73 while k < l { if b[i + k] != lit[k] { m = 0; k = l } else { k = k + 1 } }
74 if m == 1 { return 1 }
75 i = i + 1
76 }
77 return 0
78}
79// FNV-1a over a slice: the identity of a finding (file + literal), so a re-scan files the same id and the queue dedupes
80func fl_fnv(b: *u8, a: i64, e: i64, seed: i64) -> i64 {
81 var h: i64 = seed
82 var i: i64 = a
83 while i < e { h = (h ^ (b[i] as i64)) * FL_FNV_PRIME; i = i + 1 }
84 return h
85}
86
87// F1: a durable legacy-format path literal? (exemptions applied). Returns FL_F1 / FL_F1J / 0.
88func fl_class_format(b: *u8, a: i64, e: i64) -> i64 {
89 if e - a > FL_MAX_LIT { return 0 }
90 if e - a < 5 { return 0 }
91 // A PATH, NOT A TOKEN: the scanner's own extension table (`".tsv"`) is not a file. A durable path names something
92 // before its extension -- at least one byte that is not the dot -- so a bare extension literal is not a finding.
93 // (Caught by dogfooding: the first census flagged this lib's own rule table 4 times.)
94 if fl_is_bare_ext(b, a, e) == 1 { return 0 }
95 // exemptions: evidence mirrors, fixtures, wire formats, documents
96 if fl_contains(b, a, e, "knowledge/fetched/" as *u8) == 1 { return 0 }
97 if fl_starts(b, a, e, "/tmp/" as *u8) == 1 { return 0 }
98 if fl_contains(b, a, e, "sites/" as *u8) == 1 { return 0 }
99 if fl_contains(b, a, e, "web_assets/" as *u8) == 1 { return 0 }
100 if fl_contains(b, a, e, "_jobs/" as *u8) == 1 { return 0 }
101 if fl_contains(b, a, e, "specs/" as *u8) == 1 { return 0 }
102 if fl_ends_ci(b, a, e, ".tsv" as *u8) == 1 { return FL_F1 }
103 if fl_ends_ci(b, a, e, ".csv" as *u8) == 1 { return FL_F1 }
104 if fl_ends_ci(b, a, e, ".sqlite" as *u8) == 1 { return FL_F1 }
105 if fl_ends_ci(b, a, e, ".db" as *u8) == 1 { return FL_F1 }
106 if fl_ends_ci(b, a, e, ".xml" as *u8) == 1 { return FL_F1 }
107 if fl_ends_ci(b, a, e, ".yaml" as *u8) == 1 { return FL_F1 }
108 if fl_ends_ci(b, a, e, ".yml" as *u8) == 1 { return FL_F1 }
109 if fl_ends_ci(b, a, e, ".ini" as *u8) == 1 { return FL_F1 }
110 if fl_ends_ci(b, a, e, ".toml" as *u8) == 1 { return FL_F1 }
111 if fl_ends_ci(b, a, e, ".jsonl" as *u8) == 1 { return FL_F1 }
112 if fl_ends_ci(b, a, e, ".json" as *u8) == 1 { if fl_contains(b, a, e, "knowledge/" as *u8) == 1 { return FL_F1J } }
113 return 0
114}
115// F2: a third-party executable path literal?
116func fl_class_exec(b: *u8, a: i64, e: i64) -> i64 {
117 if e - a > FL_MAX_LIT { return 0 }
118 // A BINARY, NOT A DIRECTORY: `/usr/bin/` alone names no tool. The literal must carry a basename after its last
119 // slash, or it is a prefix table entry (this lib's own) rather than an exec target.
120 if b[e - 1] == (FL_CH_SLASH as u8) { return 0 }
121 if fl_starts(b, a, e, "/bin/" as *u8) == 1 { return FL_F2 }
122 if fl_starts(b, a, e, "/usr/bin/" as *u8) == 1 { return FL_F2 }
123 if fl_starts(b, a, e, "/usr/local/bin/" as *u8) == 1 { return FL_F2 }
124 if fl_starts(b, a, e, "/sbin/" as *u8) == 1 { return FL_F2 }
125 if fl_starts(b, a, e, "/usr/sbin/" as *u8) == 1 { return FL_F2 }
126 if fl_starts(b, a, e, "/opt/" as *u8) == 1 { return FL_F2 }
127 return 0
128}
129// a literal that is ONLY an extension: `.tsv`, `.CSV`, `.jsonl` -- a dot then letters, nothing before the dot
130func fl_is_bare_ext(b: *u8, a: i64, e: i64) -> i64 {
131 if b[a] != (FL_CH_DOT as u8) { return 0 }
132 var i: i64 = a + 1
133 while i < e { if b[i] == (FL_CH_DOT as u8) { return 0 } if b[i] == (FL_CH_SLASH as u8) { return 0 } i = i + 1 }
134 return 1
135}
136func fl_class_name(c: i64) -> *u8 {
137 if c == FL_F1 { return "F1-DURABLE-LEGACY-FORMAT" as *u8 }
138 if c == FL_F1J { return "F1J-JSON-AS-DURABLE-STATE" as *u8 }
139 if c == FL_F2 { return "F2-THIRD-PARTY-EXEC" as *u8 }
140 if c == FL_F3 { return "F3-NO-LICENSE-TIER" as *u8 }
141 return "UNCLASSIFIED" as *u8
142}
143func fl_remedy(c: i64) -> *u8 {
144 if c == FL_F1 { return "write the rows to a sovereign plane (knowledge/store/<prefix>-, nx_store_seed_lib sts_append_fast_locked / nx_store_put put) and read them with sts_load_fit; a .tsv/.csv beside the plane is a second, unprovenanced copy" as *u8 }
145 if c == FL_F1J { return "durable state is plane rows, not a .json under knowledge/; JSON stays a WIRE format for browsers (sites/, api.json) and job receipts" as *u8 }
146 if c == FL_F2 { return "compose the sovereign organ that does this job (nx_capsearch <words>) or write it in NishiLang; a third-party binary in a build or serving lane is an outside dependency the estate measures as a defect" as *u8 }
147 if c == FL_F3 { return "add `license_tier: <ORIGINAL|...>` to the header so nx_licgate and the review queue know the source's IP posture" as *u8 }
148 return "-" as *u8
149}
150func fl_sev(c: i64) -> i64 {
151 if c == FL_F1 { return FL_SEV_F1 }
152 if c == FL_F1J { return FL_SEV_F1J }
153 if c == FL_F2 { return FL_SEV_F2 }
154 if c == FL_F3 { return FL_SEV_F3 }
155 return 1
156}
157
158// THE SCAN. Walks the source once: `//` comments (outside strings) are skipped to end of line, every string literal
159// is classified. hits[] receives FL_HIT_WORDS per finding (class, line, lit_start, lit_end) up to FL_MAX_HITS;
160// counts[class] counts EVERY finding, kept or not, so `kept < total` is visible. Returns the total finding count.
161// F3 is a file-level finding recorded once at line 0 when the token is absent.
162func fl_scan(b: *u8, n: i64, hits: *i64, counts: *i64) -> i64 {
163 var c: i64 = 0
164 while c < FL_CLASSES { counts[c] = 0; c = c + 1 }
165 var total: i64 = 0
166 var kept: i64 = 0
167 var line: i64 = 1
168 var i: i64 = 0
169 var has_license: i64 = 0
170 while i < n {
171 let ch: i64 = b[i] as i64
172 if ch == FL_CH_NL { line = line + 1; i = i + 1 }
173 else { if ch == FL_CH_SLASH { if i + 1 < n { if b[i + 1] == (FL_CH_SLASH as u8) {
174 // a comment: the license declaration lives here, everything else in it is prose
175 let cs: i64 = i
176 var ce: i64 = i
177 var go: i64 = 1
178 while go == 1 { if ce >= n { go = 0 } else { if b[ce] == (FL_CH_NL as u8) { go = 0 } else { ce = ce + 1 } } }
179 if fl_contains(b, cs, ce, FL_LICENSE_TOKEN) == 1 { has_license = 1 }
180 i = ce
181 } else { i = i + 1 } } else { i = i + 1 } }
182 else { if ch == FL_CH_QUOTE {
183 // a string literal: find its end, honouring backslash escapes; a literal may span lines in this dialect
184 let ls: i64 = i + 1
185 var le: i64 = ls
186 var go2: i64 = 1
187 while go2 == 1 {
188 if le >= n { go2 = 0 } else {
189 let cc: i64 = b[le] as i64
190 if cc == FL_CH_BSLASH { le = le + 2 }
191 else { if cc == FL_CH_QUOTE { go2 = 0 } else { if cc == FL_CH_NL { line = line + 1; le = le + 1 } else { le = le + 1 } } }
192 }
193 }
194 if le > n { le = n }
195 var cls: i64 = fl_class_format(b, ls, le)
196 if cls == 0 { cls = fl_class_exec(b, ls, le) }
197 if cls != 0 {
198 counts[cls] = counts[cls] + 1
199 total = total + 1
200 if kept < FL_MAX_HITS { hits[kept*FL_HIT_WORDS] = cls; hits[kept*FL_HIT_WORDS+1] = line; hits[kept*FL_HIT_WORDS+2] = ls; hits[kept*FL_HIT_WORDS+3] = le; kept = kept + 1 }
201 }
202 i = le + 1
203 } else { i = i + 1 } } }
204 }
205 if has_license == 0 {
206 counts[FL_F3] = counts[FL_F3] + 1
207 total = total + 1
208 if kept < FL_MAX_HITS { hits[kept*FL_HIT_WORDS] = FL_F3; hits[kept*FL_HIT_WORDS+1] = 0; hits[kept*FL_HIT_WORDS+2] = 0; hits[kept*FL_HIT_WORDS+3] = 0; kept = kept + 1 }
209 }
210 return total
211}
212func fl_kept(total: i64) -> i64 { if total > FL_MAX_HITS { return FL_MAX_HITS } return total }