nx_coach.nx source
↩ module page · 238 lines · 9521 B
1// nx_coach.nx -- balanced pro/anti-pattern coach.
2//
3// Cardinal: feedback-pro-anti-pattern-coach-balanced-no-corruption.
4//
5// Advisory, not authoritative. Never deletes / auto-edits / auto-
6// rejects code. Emits a verdict + confidence + cited evidence.
7// Caller decides what to do.
8//
9// Five-verdict sealed enum (binary pro/anti is FORBIDDEN):
10// PRO -- known pro-pattern, evidence-cited, confidence >= 870
11// ANTI -- known anti-pattern, evidence-cited, confidence >= 870
12// NOVEL -- doesn't match either catalog; might be cutting-edge
13// S-class innovation OR new anti-pattern; ESCALATE
14// AMBIGUOUS -- matches multiple patterns with conflicting verdicts;
15// ESCALATE
16// PROTECTED -- matches a cardinal-class fix / innovation safe-harbor;
17// coach CANNOT advise against (refusal-of-refusal)
18//
19// Confidence Q10 (0..1024); PRO/ANTI require >= 870.
20
21import "syscalls.nx"
22const NX_MAGIC_1024: i64 = 1024
23const NX_MAGIC_2048: i64 = 2048
24
25// Verdict enum.
26const NX_COACH_PRO: i64 = 1
27const NX_COACH_ANTI: i64 = 2
28const NX_COACH_NOVEL: i64 = 3
29const NX_COACH_AMBIGUOUS: i64 = 4
30const NX_COACH_PROTECTED: i64 = 5
31
32// Confidence threshold for PRO/ANTI.
33const NX_COACH_MIN_CONF: i64 = 870
34
35// Protected cardinal-class tags (refusal-of-refusal list).
36const NX_COACH_PROTECT_BITS_UP: i64 = 0x10000001
37const NX_COACH_PROTECT_NO_C_EXTENSION: i64 = 0x10000002
38const NX_COACH_PROTECT_NO_SKIP: i64 = 0x10000003
39const NX_COACH_PROTECT_SILICON_TO_DEATH: i64 = 0x10000004
40const NX_COACH_PROTECT_HARDWARE_AGNOSTIC: i64 = 0x10000005
41const NX_COACH_PROTECT_USER_OWNS_BITS: i64 = 0x10000006
42const NX_COACH_PROTECT_HONEST_VERDICT: i64 = 0x10000007
43const NX_COACH_PROTECT_FOUR_PILLAR_FIX: i64 = 0x10000008
44
45// Pattern catalogs. Each row: (pattern_tag, verdict, evidence_hash).
46// Pro and anti share a table; verdict field disambiguates.
47// [0] pattern_tag (caller computes via FNV-1a over pattern signature)
48// [1] verdict (PRO / ANTI / PROTECTED)
49// [2] evidence_hash (content-addressed cardinal / smoke / bench)
50// [3] base_confidence_q10 (catalog baseline; gets adjusted)
51static NX_COACH_ACTIVE: i64
52static NX_COACH_CAT_PTR: i64
53static NX_COACH_CAT_N: i64
54static NX_COACH_CAT_CAP: i64
55
56const NX_COACH_REC_SIZE: i64 = 32 // 4 i64
57const NX_COACH_CAT_BYTES: i64 = 16384
58
59func nx_coach_init() -> i64 {
60 if NX_COACH_CAT_PTR != 0 { return 0 }
61 let raw: *u8 = sys_mmap(NX_COACH_CAT_BYTES)
62 if (raw as i64) == 0 { return 1 }
63 if (raw as i64) == 0 - 1 { return 2 }
64 NX_COACH_CAT_PTR = raw as i64
65 NX_COACH_CAT_N = 0
66 NX_COACH_CAT_CAP = NX_COACH_CAT_BYTES / NX_COACH_REC_SIZE
67 NX_COACH_ACTIVE = 1
68 return 0
69}
70
71// Register one catalog entry. Caller-side authoring: substrate's
72// pattern-catalog-writer seeds this at startup from sealed source.
73func nx_coach_register(pattern_tag: i64, verdict: i64,
74 evidence_hash: i64, base_confidence_q10: i64) -> i64 {
75 if NX_COACH_ACTIVE == 0 { return 0 }
76 nx_coach_init()
77 if NX_COACH_CAT_N >= NX_COACH_CAT_CAP { return 3 }
78 if verdict < 1 { return 4 }
79 if verdict > 5 { return 4 }
80 if base_confidence_q10 < 0 { return 5 }
81 if base_confidence_q10 > NX_MAGIC_1024 { return 5 }
82 let base: i64 = NX_COACH_CAT_PTR + (NX_COACH_CAT_N * NX_COACH_REC_SIZE)
83 let rec: *i64 = base as *i64
84 rec[0] = pattern_tag
85 rec[1] = verdict
86 rec[2] = evidence_hash
87 rec[3] = base_confidence_q10
88 NX_COACH_CAT_N = NX_COACH_CAT_N + 1
89 return 0
90}
91
92// Lookup classify: scan the catalog for matching pattern_tag.
93// Returns:
94// - PROTECTED if any matching row has verdict=PROTECTED
95// - AMBIGUOUS if matching rows disagree (one PRO and one ANTI)
96// - PRO/ANTI if single match AND base_confidence >= MIN_CONF
97// - NOVEL otherwise (no match OR below confidence threshold)
98//
99// Out-of-band: caller-supplied confidence_modifier (e.g. recent
100// smoke failures lower confidence) is added to the catalog base
101// before threshold check. Negative modifier penalises.
102func nx_coach_classify(pattern_tag: i64,
103 confidence_modifier_q10: i64) -> i64 {
104 nx_coach_init()
105 var n_pro: i64 = 0
106 var n_anti: i64 = 0
107 var n_protected: i64 = 0
108 var best_conf: i64 = 0
109 var best_verdict: i64 = NX_COACH_NOVEL
110 var i: i64 = 0
111 while i < NX_COACH_CAT_N {
112 let base: i64 = NX_COACH_CAT_PTR + (i * NX_COACH_REC_SIZE)
113 let rec: *i64 = base as *i64
114 if rec[0] == pattern_tag {
115 let v: i64 = rec[1]
116 if v == NX_COACH_PROTECTED { n_protected = n_protected + 1 }
117 if v == NX_COACH_PRO { n_pro = n_pro + 1 }
118 if v == NX_COACH_ANTI { n_anti = n_anti + 1 }
119 let raw_conf: i64 = rec[3] + confidence_modifier_q10
120 if raw_conf > best_conf {
121 best_conf = raw_conf
122 best_verdict = v
123 }
124 }
125 i = i + 1
126 }
127 // PROTECTED takes precedence (refusal-of-refusal).
128 if n_protected > 0 { return NX_COACH_PROTECTED }
129 // Conflicting verdicts -> AMBIGUOUS escalate.
130 if n_pro > 0 {
131 if n_anti > 0 { return NX_COACH_AMBIGUOUS }
132 }
133 // Confidence threshold check for PRO / ANTI.
134 if best_verdict == NX_COACH_PRO {
135 if best_conf >= NX_COACH_MIN_CONF { return NX_COACH_PRO }
136 return NX_COACH_NOVEL
137 }
138 if best_verdict == NX_COACH_ANTI {
139 if best_conf >= NX_COACH_MIN_CONF { return NX_COACH_ANTI }
140 return NX_COACH_NOVEL
141 }
142 // No match in catalog -> NOVEL (caller decides to escalate).
143 return NX_COACH_NOVEL
144}
145
146// Convenience: report the cited evidence hash for a single-match
147// pattern. Returns 0 if no match.
148func nx_coach_evidence(pattern_tag: i64) -> i64 {
149 nx_coach_init()
150 var i: i64 = 0
151 while i < NX_COACH_CAT_N {
152 let base: i64 = NX_COACH_CAT_PTR + (i * NX_COACH_REC_SIZE)
153 let rec: *i64 = base as *i64
154 if rec[0] == pattern_tag { return rec[2] }
155 i = i + 1
156 }
157 return 0
158}
159
160func nx_coach_n_catalog() -> i64 {
161 nx_coach_init()
162 return NX_COACH_CAT_N
163}
164
165// Anti-corruption guard: caller asserts "this is PRO" via this entry
166// point. The coach IGNORES it. It only logs the attempt for the
167// audit grader to spot suspicious bypasses.
168func nx_coach_caller_asserts_pro(pattern_tag: i64, caller_tag: i64) -> i64 {
169 // V0: pure no-op for the verdict; future versions log to a
170 // bypass-attempt ring buffer. Returns the REAL classify result
171 // so the caller can see we don't trust them.
172 return nx_coach_classify(pattern_tag, 0)
173}
174
175// ---- self-test ---------------------------------------------------
176// expect_exit: 0
177
178func main() -> i64 {
179 if nx_coach_init() != 0 { return 1 }
180
181 // Seed the catalog.
182 // PRO: bits-up sealed-enum verdict pattern.
183 if nx_coach_register(0xABCD0001, NX_COACH_PRO, 0xE1DE0001, 950) != 0 { return 10 }
184 // ANTI: silent SKIP verdict as error code.
185 if nx_coach_register(0xABCD0002, NX_COACH_ANTI, 0xE1DE0002, 920) != 0 { return 11 }
186 // PROTECTED: bits-up fix pattern (cannot be advised against).
187 if nx_coach_register(NX_COACH_PROTECT_BITS_UP, NX_COACH_PROTECTED,
188 0xE1DE0003, NX_MAGIC_1024) != 0 { return 12 }
189 // Low-confidence PRO: should DOWNGRADE to NOVEL.
190 if nx_coach_register(0xABCD0003, NX_COACH_PRO, 0xE1DE0004, 700) != 0 { return 13 }
191 // Conflicting registrations: same pattern with PRO + ANTI -> AMBIGUOUS.
192 if nx_coach_register(0xABCD0004, NX_COACH_PRO, 0xE1DE0005, 950) != 0 { return 14 }
193 if nx_coach_register(0xABCD0004, NX_COACH_ANTI, 0xE1DE0006, 940) != 0 { return 15 }
194
195 if nx_coach_n_catalog() != 6 { return 20 }
196
197 // PRO with high confidence -> PRO verdict.
198 if nx_coach_classify(0xABCD0001, 0) != NX_COACH_PRO { return 30 }
199
200 // ANTI with high confidence -> ANTI verdict.
201 if nx_coach_classify(0xABCD0002, 0) != NX_COACH_ANTI { return 31 }
202
203 // PROTECTED takes precedence.
204 if nx_coach_classify(NX_COACH_PROTECT_BITS_UP, 0) != NX_COACH_PROTECTED { return 32 }
205
206 // Low-confidence PRO downgrades to NOVEL.
207 if nx_coach_classify(0xABCD0003, 0) != NX_COACH_NOVEL { return 33 }
208
209 // Conflicting registrations -> AMBIGUOUS.
210 if nx_coach_classify(0xABCD0004, 0) != NX_COACH_AMBIGUOUS { return 34 }
211
212 // Confidence modifier raises a low-conf pattern above threshold.
213 if nx_coach_classify(0xABCD0003, 200) != NX_COACH_PRO { return 35 }
214
215 // Confidence modifier pushes a high-conf pattern below threshold.
216 if nx_coach_classify(0xABCD0001, 0 - 200) != NX_COACH_NOVEL { return 36 }
217
218 // Unknown pattern -> NOVEL (cutting-edge innovation safe-harbor).
219 if nx_coach_classify(0xDEADBEEF, 0) != NX_COACH_NOVEL { return 37 }
220
221 // Anti-corruption: caller claims PRO; coach ignores + returns real
222 // classify result.
223 if nx_coach_caller_asserts_pro(0xABCD0002, 0xCA110001) != NX_COACH_ANTI {
224 return 40
225 }
226
227 // Evidence lookup.
228 if nx_coach_evidence(0xABCD0001) != 0xE1DE0001 { return 50 }
229 if nx_coach_evidence(0xABCD0002) != 0xE1DE0002 { return 51 }
230 if nx_coach_evidence(0xDEADBEEF) != 0 { return 52 } // not in catalog
231
232 // Invalid registrations rejected.
233 if nx_coach_register(0xCAFE, 99, 0, 500) == 0 { return 60 }
234 if nx_coach_register(0xCAFE, NX_COACH_PRO, 0, NX_MAGIC_2048) == 0 { return 61 }
235 if nx_coach_register(0xCAFE, NX_COACH_PRO, 0, 0 - 1) == 0 { return 62 }
236
237 return 0
238}