nx_ac_sensor_verify_test.nx source
↩ module page · 147 lines · 5170 B
1// nx_ac_sensor_verify_test.nx -- gate for the reading-level liar-killer.
2//
3// Proves every trust verdict + every physics-invariant reason fires, and that
4// the cross-sensor independence discipline holds: an independent agreeing
5// sensor -> CORROBORATED; independent disagreement -> CONFLICTED; but a
6// DISAGREEING SAME-SOURCE echo -> PLAUSIBLE (corroborated=-2), NOT conflicted
7// (echo is not corroboration -- the crossval discipline).
8//
9// expect_exit: 0
10// license_tier: ORIGINAL
11
12import "nx_syscalls_x86_64.nx"
13import "nx_ac_sensor_verify.nx"
14
15// Fill a HEALTHY air-side-only reading (refrigerant + outdoor channels absent,
16// no independent corroborator). Each test then overrides one thing.
17func acv_reset(r: *AcReading) -> i64 {
18 r.mode = NX_HVAC_MODE_COOL
19 r.t_supply_mC = 12000
20 r.rh_supply_pm = 900
21 r.t_return_mC = 24000
22 r.rh_return_pm = 500
23 r.airflow_cfm = 1200
24 r.rho_gm3 = 1200
25 r.t_suction_mC = NX_ACV_ABSENT
26 r.t_sat_evap_mC = NX_ACV_ABSENT
27 r.t_liquid_mC = NX_ACV_ABSENT
28 r.t_sat_cond_mC = NX_ACV_ABSENT
29 r.t_outdoor_mC = NX_ACV_ABSENT
30 r.p_elec_w = 3000
31 r.t_return_b_mC = NX_ACV_ABSENT
32 r.return_a_src = 1
33 r.return_b_src = 0
34 r.return_tol_mC = 500
35 return 0
36}
37
38func main() -> i64 {
39 // ---- sealed-enum validity ------------------------------------
40 if nx_acv_verdict_is_valid(NX_ACV_PLAUSIBLE) != 1 { return 1 }
41 if nx_acv_verdict_is_valid(NX_ACV_N) != 0 { return 2 }
42 if nx_acv_verdict_is_valid(-1) != 0 { return 3 }
43
44 let r: *AcReading = sys_mmap(256) as *AcReading
45 let o: *AcVerify = sys_mmap(128) as *AcVerify
46
47 // ===== C1: healthy air-side-only -> PLAUSIBLE ==================
48 acv_reset(r)
49 nx_acv_verify(r, o)
50 if o.verdict != NX_ACV_PLAUSIBLE { return 10 }
51 if o.reason != NX_ACV_R_NONE { return 11 }
52 if o.corroborated != 0 { return 12 }
53 if o.q_cool_w < 9000 { return 13 } // real cooling delivered
54 if o.split_mC != 12000 { return 14 } // 24C - 12C
55
56 // ===== C2: independent agreeing sensor -> CORROBORATED =========
57 acv_reset(r)
58 r.t_return_b_mC = 24100
59 r.return_a_src = 1
60 r.return_b_src = 2
61 nx_acv_verify(r, o)
62 if o.verdict != NX_ACV_CORROBORATED { return 20 }
63 if o.corroborated != 1 { return 21 }
64
65 // ===== C3: independent disagreeing sensor -> CONFLICTED ========
66 acv_reset(r)
67 r.t_return_b_mC = 27000
68 r.return_a_src = 1
69 r.return_b_src = 2
70 nx_acv_verify(r, o)
71 if o.verdict != NX_ACV_CONFLICTED { return 30 }
72 if o.reason != NX_ACV_R_CONFLICT { return 31 }
73 if o.corroborated != -1 { return 32 }
74
75 // ===== C4: DISAGREEING SAME-SOURCE ECHO -> PLAUSIBLE, not conflict
76 // The independence liar-kill: identical source id cannot corroborate OR
77 // conflict (it is the same sensor echoing itself).
78 acv_reset(r)
79 r.t_return_b_mC = 27000
80 r.return_a_src = 1
81 r.return_b_src = 1
82 nx_acv_verify(r, o)
83 if o.verdict != NX_ACV_PLAUSIBLE { return 40 }
84 if o.corroborated != -2 { return 41 }
85
86 // ===== C5: impossible humidity (150% RH) -> IMPLAUSIBLE r1 =====
87 acv_reset(r)
88 r.rh_return_pm = 1500
89 nx_acv_verify(r, o)
90 if o.verdict != NX_ACV_IMPLAUSIBLE_PHYSICS { return 50 }
91 if o.reason != NX_ACV_R_RH_RANGE { return 51 }
92
93 // ===== C6: swapped supply/return under power -> IMPLAUSIBLE r2 =
94 // supply air warmer/moister than return while drawing power -> the
95 // evaporator cannot add enthalpy in cooling -> sensors swapped.
96 acv_reset(r)
97 r.t_supply_mC = 26000
98 r.rh_supply_pm = 400
99 r.t_return_mC = 14000
100 r.rh_return_pm = 600
101 nx_acv_verify(r, o)
102 if o.verdict != NX_ACV_IMPLAUSIBLE_PHYSICS { return 60 }
103 if o.reason != NX_ACV_R_REVERSED { return 61 }
104
105 // ===== C7: negative superheat -> IMPLAUSIBLE r3 ===============
106 acv_reset(r)
107 r.t_suction_mC = 2000
108 r.t_sat_evap_mC = 5000
109 nx_acv_verify(r, o)
110 if o.verdict != NX_ACV_IMPLAUSIBLE_PHYSICS { return 70 }
111 if o.reason != NX_ACV_R_SUPERHEAT { return 71 }
112
113 // ===== C8: COP above Carnot ceiling -> IMPLAUSIBLE r5 =========
114 // Big airflow + tiny power => impossibly high COP for the temperature lift.
115 acv_reset(r)
116 r.t_supply_mC = 10000
117 r.rh_supply_pm = 800
118 r.t_return_mC = 15000
119 r.rh_return_pm = 550
120 r.t_outdoor_mC = 45000
121 r.p_elec_w = 200
122 nx_acv_verify(r, o)
123 if o.verdict != NX_ACV_IMPLAUSIBLE_PHYSICS { return 80 }
124 if o.reason != NX_ACV_R_CARNOT { return 81 }
125
126 // ===== C9: liquid line colder than ambient -> IMPLAUSIBLE r7 ==
127 acv_reset(r)
128 r.t_liquid_mC = 20000
129 r.t_outdoor_mC = 35000
130 nx_acv_verify(r, o)
131 if o.verdict != NX_ACV_IMPLAUSIBLE_PHYSICS { return 90 }
132 if o.reason != NX_ACV_R_LIQUID_AMB { return 91 }
133
134 // ===== C10: non-cooling mode -> BAD_ARG =======================
135 acv_reset(r)
136 r.mode = NX_HVAC_MODE_HEAT
137 nx_acv_verify(r, o)
138 if o.verdict != NX_ACV_BAD_ARG { return 100 }
139
140 // ===== C11: missing core channel -> INSUFFICIENT_DATA =========
141 acv_reset(r)
142 r.t_supply_mC = NX_ACV_ABSENT
143 nx_acv_verify(r, o)
144 if o.verdict != NX_ACV_INSUFFICIENT_DATA { return 110 }
145
146 return 0
147}