nx_ux_triangulate.nx source
↩ module page · 126 lines · 4301 B
1// nx_ux_triangulate.nx -- ≥3-independent-sources-agree gate.
2//
3// T3 of NISHI_UX_TRIANGULATION_ROADMAP. Given an array of
4// (clause_id, score) pairs, decide whether the UX pattern is
5// validated-S-class. Rules:
6//
7// 1. Count clauses scoring ≥8 from DISTINCT sources.
8// 2. Count clauses scoring ≤4 from ANY source.
9// 3. Verdict:
10// VALIDATED_S_CLASS if (distinct_sources_>=8) >= 3
11// AND no source scored ≤4
12// CONFLICTED if (>=8) >= 1 AND (<=4) >= 1
13// UNVERIFIED otherwise (insufficient agreement)
14//
15// This is the substrate-side enforcement of "no solo design, no
16// one-vendor-validates-its-own-pattern." Innovation gated behind
17// VALIDATED_S_CLASS verdicts on the relevant clauses.
18//
19// license_tier: ORIGINAL
20// lineage_id: nishi_ux_triangulate_q10
21
22import "nx_syscalls.nx"
23import "nx_ux_standard.nx"
24
25const NX_UX_VERDICT_UNVERIFIED: i64 = 1
26const NX_UX_VERDICT_VALIDATED_S_CLASS: i64 = 2
27const NX_UX_VERDICT_CONFLICTED: i64 = 3
28
29struct UxScore {
30 clause_id: i64,
31 score: i64
32}
33
34const NX_UX_SCORE_BYTES: i64 = 16
35
36func _ux_at(scores: *UxScore, idx: i64) -> *UxScore {
37 return ((scores as i64) + idx * NX_UX_SCORE_BYTES) as *UxScore
38}
39
40// Given a list of scores, return the verdict + (optionally) write a
41// brief note via out_note. Caller passes scores[] + n_scores.
42func nx_ux_triangulate(scores: *UxScore, n_scores: i64) -> i64 {
43 // Track which source-ids hit ≥8, and whether any hit ≤4.
44 let seen_high: *u8 = sys_mmap(NX_UX_SRC_N + 4)
45 var i: i64 = 0
46 while i < NX_UX_SRC_N { seen_high[i] = 0; i = i + 1 }
47 var any_low: i64 = 0
48 var any_high: i64 = 0
49
50 var idx: i64 = 0
51 while idx < n_scores {
52 let s: *UxScore = _ux_at(scores, idx)
53 let src: i64 = nx_ux_clause_source(s.clause_id)
54 if s.score >= 8 {
55 any_high = 1
56 if src > 0 { seen_high[src] = 1 }
57 }
58 if s.score <= 4 { any_low = 1 }
59 idx = idx + 1
60 }
61
62 var distinct_high_sources: i64 = 0
63 i = 0
64 while i < NX_UX_SRC_N {
65 if seen_high[i] == 1 { distinct_high_sources = distinct_high_sources + 1 }
66 i = i + 1
67 }
68
69 if any_high == 1 { if any_low == 1 { return NX_UX_VERDICT_CONFLICTED } }
70 if distinct_high_sources >= 3 { return NX_UX_VERDICT_VALIDATED_S_CLASS }
71 return NX_UX_VERDICT_UNVERIFIED
72}
73
74func nx_ux_verdict_label(v: i64) -> *u8 {
75 if v == NX_UX_VERDICT_VALIDATED_S_CLASS { return "VALIDATED_S_CLASS" as *u8 }
76 if v == NX_UX_VERDICT_CONFLICTED { return "CONFLICTED" as *u8 }
77 return "UNVERIFIED" as *u8
78}
79
80// T4: Per-cluster triangulation. Returns a verdict for ONE cluster
81// based on scores whose clause-cluster matches `cluster_id`. Same
82// rules as nx_ux_triangulate but scoped to a pattern category --
83// weak feedback signals do not contaminate the accessibility verdict.
84func nx_ux_triangulate_cluster(scores: *UxScore, n_scores: i64,
85 cluster_id: i64) -> i64 {
86 let seen_high: *u8 = sys_mmap(NX_UX_SRC_N + 4)
87 var i: i64 = 0
88 while i < NX_UX_SRC_N { seen_high[i] = 0; i = i + 1 }
89 var any_low: i64 = 0
90 var any_high: i64 = 0
91 var any_in_cluster: i64 = 0
92
93 var idx: i64 = 0
94 while idx < n_scores {
95 let s: *UxScore = _ux_at(scores, idx)
96 let c: i64 = nx_ux_clause_cluster(s.clause_id)
97 if c == cluster_id {
98 any_in_cluster = 1
99 let src: i64 = nx_ux_clause_source(s.clause_id)
100 if s.score >= 8 {
101 any_high = 1
102 if src > 0 { seen_high[src] = 1 }
103 }
104 if s.score <= 4 { any_low = 1 }
105 }
106 idx = idx + 1
107 }
108
109 if any_in_cluster == 0 { return NX_UX_VERDICT_UNVERIFIED }
110
111 var distinct_high_sources: i64 = 0
112 i = 0
113 while i < NX_UX_SRC_N {
114 if seen_high[i] == 1 { distinct_high_sources = distinct_high_sources + 1 }
115 i = i + 1
116 }
117
118 if any_high == 1 { if any_low == 1 { return NX_UX_VERDICT_CONFLICTED } }
119 if distinct_high_sources >= 3 { return NX_UX_VERDICT_VALIDATED_S_CLASS }
120 if distinct_high_sources >= 2 { if any_low == 0 { return NX_UX_VERDICT_VALIDATED_S_CLASS } }
121 return NX_UX_VERDICT_UNVERIFIED
122}
123
124func main() -> i64 {
125 return 0
126}