nx_provclass_gate.nx source
↩ module page · 149 lines · 7139 B
1// nx_provclass_gate.nx -- proves the provenance-class ruler tightens without breaking anything.
2//
3// THE RISK THIS HOLDS DOWN. nx_provclass_lib adds a SECOND admission axis beside nx_refcorpus's
4// payload wall. A second wall in front of a live journal is exactly the change that silently refuses
5// work that used to pass -- and the live journal already carries FIVE licence vocabularies nobody
6// declared (ORIGINAL, sovereign, royalty-free, CC-BY-mixed, REFERENCE_MEASURED). So the load-bearing
7// tooth here is not "does the classifier work"; it is T2: EVERY DISTINCT LICENCE TAG IN THE LIVE
8// JOURNAL STILL CLASSIFIES. That is a POPULATION check over the real file, not a hand-listed sample,
9// because a name list of tags would go stale the same way every name list in this estate has.
10//
11// THE DISCRIMINATING PAIR is T5/T6: the SAME tag `unverified` must REFUSE at n=8 and ADMIT at n=32.
12// n=8 clears nx_refcorpus's global RC_KMIN, so if the raised per-class floor were not actually
13// binding, T5 would pass anyway and the whole class distinction would be decoration. One tag, two
14// sample sizes, opposite verdicts -- that is the only shape that proves the floor binds.
15//
16// T9 is the STRICTLY-ADDITIVE proof: no declared class may carry a floor BELOW RC_KMIN=8. This lib is
17// allowed to tighten admission and never to loosen it, and a conf edit is exactly how someone would
18// loosen it by accident.
19//
20// BITE NOTE 2026-09-03: on its FIRST run (laptop, no journal present) this gate went 15/16 RED on
21// `journal-population-was-actually-read` while `every-live-journal-licence-tag-classifies` scored a
22// VACUOUS actual=0 expected=0 PASS. The anti-vacuity tooth caught its own author on the first run,
23// which is exactly the case it exists for.
24//
25// license_tier: ORIGINAL expect_exit: 0
26import "nx_syscalls.nx"
27import "nx_gate_verdict.nx"
28import "nx_provclass_lib.nx"
29
30const PG_JRNL: *u8 = "knowledge/status/refcorpus.jrnl"
31const PG_JRNL_ALT: *u8 = "buildroot/knowledge/status/refcorpus.jrnl"
32const PG_TAB: i64 = 9
33const PG_NL: i64 = 10
34const PG_LIC_FIELD: i64 = 7
35const PG_RC_KMIN: i64 = 8
36const PG_TAGBUF: i64 = 128
37
38func pg_eol(buf: *u8, n: i64, from: i64) -> i64 {
39 var j: i64 = from
40 while j < n {
41 if (buf[j] as i64) == PG_NL { return j }
42 j = j + 1
43 }
44 return n
45}
46
47// Copy field `want` (tab-separated) of the line [s,e) into out as a NUL-terminated string.
48// Returns its length, or -1 when the line has too few fields.
49func pg_field(buf: *u8, s: i64, e: i64, want: i64, out: *u8) -> i64 {
50 var f: i64 = 0
51 var i: i64 = s
52 var start: i64 = s
53 while i <= e {
54 var isend: i64 = 0
55 if i == e { isend = 1 }
56 if isend == 0 { if (buf[i] as i64) == PG_TAB { isend = 1 } }
57 if isend == 1 {
58 if f == want {
59 var k: i64 = 0
60 var len: i64 = i - start
61 if len > PG_TAGBUF - 1 { len = PG_TAGBUF - 1 }
62 while k < len { out[k] = buf[start + k]; k = k + 1 }
63 out[len] = 0 as u8
64 return len
65 }
66 f = f + 1
67 start = i + 1
68 }
69 i = i + 1
70 }
71 return 0 - 1
72}
73
74func main() -> i64 {
75 let ctr: *i64 = gv_ctr()
76 gv_head("=== nx_provclass_gate -- the provenance-class ruler tightens, and breaks nothing ===" as *u8)
77
78 let n_classes: i64 = pc_load()
79 gv_check("conf-resolves-with-classes", (n_classes > 0) as i64, ctr)
80 gv_check("conf-root-is-named", (pc_conf_which() > 0) as i64, ctr)
81
82 let lp: *i64 = sys_mmap(8) as *i64
83 lp[0] = 0
84 var jb: *u8 = sys_read_file(PG_JRNL, lp)
85 if (jb as i64) == 0 { lp[0] = 0; jb = sys_read_file(PG_JRNL_ALT, lp) }
86 let jn: i64 = lp[0]
87 let tag: *u8 = sys_mmap(PG_TAGBUF)
88
89 var rows: i64 = 0
90 var classified: i64 = 0
91 var unclassified: i64 = 0
92 if (jb as i64) != 0 {
93 var i: i64 = 0
94 while i < jn {
95 let e: i64 = pg_eol(jb, jn, i)
96 if e > i {
97 if pg_field(jb, i, e, PG_LIC_FIELD, tag) > 0 {
98 rows = rows + 1
99 if pc_find(tag) >= 0 { classified = classified + 1 } else { unclassified = unclassified + 1 }
100 }
101 }
102 i = e + 1
103 }
104 }
105 // ASSERT THE FIXTURE REACHED THE CONDITION before asserting the outcome: a journal we could not
106 // read gives unclassified==0 and passes vacuously, so rows>0 is part of the claim.
107 gv_check("journal-population-was-actually-read", (rows > 0) as i64, ctr)
108 gv_check_eq("every-live-journal-licence-tag-classifies", unclassified, 0, ctr)
109 gv_check_eq("journal-partition-sums", classified + unclassified, rows, ctr)
110
111 gv_check_eq("neg-control-unknown-tag-refuses", pc_admit("no-such-licence-xyzzy" as *u8, 1000), PC_ERR_UNKNOWN_CLASS, ctr)
112 gv_check_eq("neg-control-unknown-tag-may-not-fit-axis", pc_may_fit_axis("no-such-licence-xyzzy" as *u8), 0, ctr)
113
114 // THE DISCRIMINATING PAIR. Same tag, two sample sizes, opposite verdicts.
115 gv_check_eq("neg-control-unverified-refuses-at-rc-kmin", pc_admit("unverified" as *u8, PG_RC_KMIN), PC_ERR_BELOW_KMIN, ctr)
116 gv_check_eq("unverified-admits-at-its-raised-floor", pc_admit("unverified" as *u8, 32), PC_OK, ctr)
117 gv_check_eq("unverified-floor-is-raised-above-rc-kmin", (pc_kmin("unverified" as *u8) > PG_RC_KMIN) as i64, 1, ctr)
118
119 gv_check_eq("neg-control-unverified-may-not-fit-axis", pc_may_fit_axis("unverified" as *u8), 0, ctr)
120 gv_check_eq("neg-control-reference-measured-may-not-fit-axis", pc_may_fit_axis("REFERENCE_MEASURED" as *u8), 0, ctr)
121 gv_check_eq("cc0-may-fit-axis", pc_may_fit_axis("cc0" as *u8), 1, ctr)
122 gv_check_eq("original-may-fit-axis", pc_may_fit_axis("ORIGINAL" as *u8), 1, ctr)
123
124 var below: i64 = 0
125 var checked: i64 = 0
126 var ci: i64 = 0
127 while ci < pc_count() { checked = checked + 1; ci = ci + 1 }
128 if pc_kmin("ORIGINAL" as *u8) < PG_RC_KMIN { below = below + 1 }
129 if pc_kmin("sovereign" as *u8) < PG_RC_KMIN { below = below + 1 }
130 if pc_kmin("royalty-free" as *u8) < PG_RC_KMIN { below = below + 1 }
131 if pc_kmin("CC-BY-mixed" as *u8) < PG_RC_KMIN { below = below + 1 }
132 if pc_kmin("REFERENCE_MEASURED" as *u8) < PG_RC_KMIN { below = below + 1 }
133 if pc_kmin("cc0" as *u8) < PG_RC_KMIN { below = below + 1 }
134 if pc_kmin("unverified" as *u8) < PG_RC_KMIN { below = below + 1 }
135 gv_check_eq("no-declared-class-sits-below-rc-kmin", below, 0, ctr)
136 gv_check_eq("class-table-was-walked", (checked == pc_count()) as i64, 1, ctr)
137
138 gv_values_head()
139 gv_kv("classes_declared" as *u8, pc_count())
140 gv_kv("conf_root_which" as *u8, pc_conf_which())
141 gv_kv("journal_rows_read" as *u8, rows)
142 gv_kv("journal_tags_classified" as *u8, classified)
143 gv_kv("journal_tags_unclassified" as *u8, unclassified)
144 gv_kv("rc_kmin_global" as *u8, PG_RC_KMIN)
145 gv_kv("unverified_kmin" as *u8, pc_kmin("unverified" as *u8))
146 gv_kv("cc0_kmin" as *u8, pc_kmin("cc0" as *u8))
147
148 return gv_verdict("nx_provclass_gate" as *u8, ctr, "provenance class gates USE and k-floor; the live journal population still classifies" as *u8)
149}