code wiki / _hdl_build / nx_ac_monitor_census.nx
nx_ac_monitor_census.nx source
↩ module page · 344 lines · 16825 B
1// nx_ac_monitor_census.nx -- EVIDENCE-BACKED SOTA gap map for the sovereign
2// AC/HVAC monitoring product ("Flume for AC", data-center-grade, hubless,
3// browser-first). The "census" leg of the operator's research/census/critic/
4// adversary product.
5//
6// DISCIPLINE (per project-nishi-sensor-gap-census + feedback-census-evidence-
7// backed-not-symbol-presence): a capability is credited HAVE only with
8// EVIDENCE. This census goes beyond symbol-presence -- for the organs built in
9// this workstream it EXECUTES a live witness (runs the organ, checks a known
10// output); crediting a capability whose witness fails turns the census RED.
11// Existing-stack capabilities proven by a sibling gate are HAVE-CITED (named
12// gate, not re-run here). Unbuilt capabilities are GAP with their SOTA source.
13// It is ITSELF liar-killed: a negative-control witness (an asserted-false
14// output) MUST fail -- if the witness harness "passes" a false claim, RED.
15//
16// Prints the honest map + coverage permille + a verdict every run. GREEN =
17// the witness harness is trustworthy (all HAVE witnesses pass, neg-control
18// fails, coverage floor held) -- NOT "coverage is complete"; the GAP rows ARE
19// the remaining work.
20//
21// Sovereign nx_cc->nxasm (no gcc). CWD = nxc2 root. expect_exit: 0
22// license_tier: ORIGINAL
23// genealogy_id: project-hvac-efficiency-sclass-2026-06-23
24// + project-nishi-sensor-gap-census-2026-07-14 (census discipline)
25
26import "syscalls.nx"
27import "runtime.nx"
28import "nx_axioms.nx"
29import "nx_psychrometrics.nx"
30import "nx_ac_enthalpy_metrics.nx"
31import "nx_ac_sensor_verify.nx"
32import "nx_ac_fdd.nx"
33// ---- WITNESS FIXTURES, NAMED FOR WHAT THEY ARE ---------------------------------------------------
34// These were K_MAGIC_<value>: named for their own number, which is worse here than a bare literal, for a
35// reason this file demonstrates FOUR times over. WHEN THE NAME IS THE VALUE, TWO UNRELATED QUANTITIES THAT
36// HAPPEN TO SHARE A NUMBER COLLAPSE INTO ONE CONSTANT -- 1200 was serving as BOTH airflow (CFM) and air
37// density (g/m3); 25000 as both the 25 C psychrometric reference and the 45 F condenser-over-ambient
38// ceiling; 1500 as both an impossible relative humidity (per-mille) and a 1.5 C subcool; 12000 as both the
39// 12 C supply temperature and a 12 C subcool. Tuning either purpose silently moved the other.
40// ★★★A VALUE-NAMED CONSTANT DOES NOT MERELY FAIL TO EXPLAIN ITSELF -- IT MANUFACTURES COUPLING BETWEEN
41// QUANTITIES THAT WERE NEVER RELATED. Split below; the repeated numbers are deliberate and annotated.
42// Units ride in the names: mC = milli-Celsius, pm = per-mille, PA = pascal, W = watt.
43
44// psychrometric reference points -- NIST/ASHRAE PUBLISHED VALUES, not tuning knobs
45const K_PSY_T25_mC: i64 = 25000
46const K_PSY_PSAT_25C_PA: i64 = 3170
47const K_PSY_T20_mC: i64 = 20000
48const K_PSY_PSAT_20C_PA: i64 = 2339
49const K_PSY_ENTHALPY_25C_60RH: i64 = 55460
50const K_NEGCTL_WRONG_PSAT_PA: i64 = 9999 // deliberately NOT psat(25C): the neg-control must NOT match
51
52// COP / Carnot / EER witness
53const K_COP_HEAT_W: i64 = 10800
54const K_COP_ELEC_W: i64 = 3000
55const K_CARNOT_COLD_mC: i64 = 24000
56const K_CARNOT_HOT_mC: i64 = 35000
57const K_CARNOT_COP_X100: i64 = 2701
58const K_EER_AT_COP360_X100: i64 = 1228
59
60// reading fixture
61const K_RDG_SUPPLY_mC: i64 = 12000
62const K_RDG_RETURN_mC: i64 = 24000
63const K_RDG_RETURN_B_mC: i64 = 27000
64const K_RDG_AIRFLOW_CFM: i64 = 1200
65const K_RDG_RHO_G_M3: i64 = 1200 // same number as the airflow above, unrelated quantity
66const K_RDG_ELEC_W: i64 = 3000
67const K_RH_IMPOSSIBLE_pm: i64 = 1500 // above 1000 per-mille is impossible -> must read IMPLAUSIBLE
68
69// FDD thresholds (the round values are Fahrenheit: 15F 5F 10F 25F 45F)
70const K_FDD_TARGET_SUPERHEAT_mC: i64 = 8333
71const K_FDD_SUPERHEAT_BAND_mC: i64 = 2778
72const K_FDD_TARGET_SUBCOOL_mC: i64 = 5556
73const K_FDD_SPLIT_CEILING_mC: i64 = 13889
74const K_FDD_COND_CEILING_mC: i64 = 25000 // same number as the 25 C reference above, unrelated quantity
75
76// FDD fixture readings
77const K_FDD_SUPERHEAT_HIGH_mC: i64 = 17000
78const K_FDD_SUBCOOL_LOW_mC: i64 = 1500 // same number as the impossible RH above, unrelated quantity
79const K_FDD_SUCTION_SAT_mC: i64 = 5000
80const K_FDD_EVAP_SPLIT_mC: i64 = 11000
81const K_FDD_COND_OVER_AMBIENT_mC: i64 = 15000
82const K_FDD_SUPERHEAT_LOW_mC: i64 = 6000
83const K_FDD_SUBCOOL_HIGH_mC: i64 = 12000 // same number as the supply temp above, unrelated quantity
84const K_FDD_FREEZE_SUCTION_mC: i64 = 2000
85
86// ---- live witnesses (execute the organ, check a known output) ------
87
88// physics floor: saturation pressure + enthalpy match NIST/ASHRAE exactly
89func w_psychro() -> i64 {
90 if nx_psy_psat_pa(K_PSY_T25_mC) != K_PSY_PSAT_25C_PA { return 0 }
91 if nx_psy_psat_pa(K_PSY_T20_mC) != K_PSY_PSAT_20C_PA { return 0 }
92 if nx_psy_enthalpy_from_rh(K_PSY_T25_mC, 600, NX_PSY_P_ATM_PA) != K_PSY_ENTHALPY_25C_60RH { return 0 }
93 return 1
94}
95
96// performance crown: COP / Carnot ceiling
97func w_metrics() -> i64 {
98 if nx_ac_cop_x100(K_COP_HEAT_W, K_COP_ELEC_W) != 360 { return 0 }
99 if nx_ac_carnot_cop_x100(K_CARNOT_COLD_mC, K_CARNOT_HOT_mC) != K_CARNOT_COP_X100 { return 0 }
100 if nx_ac_eer_x100(360) != K_EER_AT_COP360_X100 { return 0 }
101 return 1
102}
103
104// efficiency drift vs baseline (the Flume bill-hook)
105func w_drift() -> i64 {
106 if nx_ac_efficiency_drift_permille(328, 400) != 180 { return 0 }
107 return 1
108}
109
110// reading-level liar-killer: healthy -> PLAUSIBLE, impossible -> IMPLAUSIBLE
111func w_liarkill() -> i64 {
112 let r: *AcReading = sys_mmap(256) as *AcReading
113 let o: *AcVerify = sys_mmap(128) as *AcVerify
114 r.mode = NX_HVAC_MODE_COOL
115 r.t_supply_mC = K_RDG_SUPPLY_mC
116 r.rh_supply_pm = 900
117 r.t_return_mC = K_RDG_RETURN_mC
118 r.rh_return_pm = 500
119 r.airflow_cfm = K_RDG_AIRFLOW_CFM
120 r.rho_gm3 = K_RDG_RHO_G_M3
121 r.t_suction_mC = NX_ACV_ABSENT
122 r.t_sat_evap_mC = NX_ACV_ABSENT
123 r.t_liquid_mC = NX_ACV_ABSENT
124 r.t_sat_cond_mC = NX_ACV_ABSENT
125 r.t_outdoor_mC = NX_ACV_ABSENT
126 r.p_elec_w = K_RDG_ELEC_W
127 r.t_return_b_mC = NX_ACV_ABSENT
128 r.return_a_src = 1
129 r.return_b_src = 0
130 r.return_tol_mC = 500
131 nx_acv_verify(r, o)
132 if o.verdict != NX_ACV_PLAUSIBLE { return 0 }
133 r.rh_return_pm = K_RH_IMPOSSIBLE_pm
134 nx_acv_verify(r, o)
135 if o.verdict != NX_ACV_IMPLAUSIBLE_PHYSICS { return 0 }
136 return 1
137}
138
139// cross-sensor independence: a disagreeing SAME-SOURCE echo is NOT a conflict
140func w_independence() -> i64 {
141 let r: *AcReading = sys_mmap(256) as *AcReading
142 let o: *AcVerify = sys_mmap(128) as *AcVerify
143 r.mode = NX_HVAC_MODE_COOL
144 r.t_supply_mC = K_RDG_SUPPLY_mC
145 r.rh_supply_pm = 900
146 r.t_return_mC = K_RDG_RETURN_mC
147 r.rh_return_pm = 500
148 r.airflow_cfm = K_RDG_AIRFLOW_CFM
149 r.rho_gm3 = K_RDG_RHO_G_M3
150 r.t_suction_mC = NX_ACV_ABSENT
151 r.t_sat_evap_mC = NX_ACV_ABSENT
152 r.t_liquid_mC = NX_ACV_ABSENT
153 r.t_sat_cond_mC = NX_ACV_ABSENT
154 r.t_outdoor_mC = NX_ACV_ABSENT
155 r.p_elec_w = K_RDG_ELEC_W
156 r.t_return_b_mC = K_RDG_RETURN_B_mC
157 r.return_a_src = 1
158 r.return_b_src = 1
159 r.return_tol_mC = 500
160 nx_acv_verify(r, o)
161 if o.verdict != NX_ACV_PLAUSIBLE { return 0 }
162 if o.corroborated != -2 { return 0 }
163 return 1
164}
165
166// FDD: charge / condenser / airflow / freeze faults classify correctly
167func w_fdd() -> i64 {
168 let rd: *FddInput = sys_mmap(128) as *FddInput
169 let th: *FddThresh = sys_mmap(128) as *FddThresh
170 let o: *FddOut = sys_mmap(64) as *FddOut
171 th.target_superheat_mC = K_FDD_TARGET_SUPERHEAT_mC
172 th.superheat_band_mC = K_FDD_SUPERHEAT_BAND_mC
173 th.target_subcool_mC = K_FDD_TARGET_SUBCOOL_mC
174 th.subcool_band_mC = K_FDD_SUPERHEAT_BAND_mC
175 th.split_ceiling_mC = K_FDD_SPLIT_CEILING_mC
176 th.cond_over_ambient_ceiling_mC = K_FDD_COND_CEILING_mC
177 th.cfm_per_ton_floor = 350
178 th.max_cph_x10 = 35
179 th.freeze_suction_sat_mC = 0
180
181 rd.superheat_mC = K_FDD_SUPERHEAT_HIGH_mC
182 rd.subcool_mC = K_FDD_SUBCOOL_LOW_mC
183 rd.suction_sat_mC = K_FDD_SUCTION_SAT_mC
184 rd.evap_split_mC = K_FDD_EVAP_SPLIT_mC
185 rd.cond_over_ambient_mC = K_FDD_COND_OVER_AMBIENT_mC
186 rd.cfm_per_ton = 400
187 rd.cph_x10 = 20
188 nx_ac_fdd_analyze(rd, th, o)
189 if o.verdict != NX_FDD_UNDERCHARGE { return 0 }
190
191 rd.superheat_mC = K_FDD_SUPERHEAT_LOW_mC
192 rd.subcool_mC = K_FDD_SUBCOOL_HIGH_mC
193 nx_ac_fdd_analyze(rd, th, o)
194 if o.verdict != NX_FDD_OVERCHARGE { return 0 }
195
196 rd.superheat_mC = K_FDD_TARGET_SUPERHEAT_mC
197 rd.subcool_mC = K_FDD_TARGET_SUBCOOL_mC
198 rd.suction_sat_mC = -K_FDD_FREEZE_SUCTION_mC
199 nx_ac_fdd_analyze(rd, th, o)
200 if o.verdict != NX_FDD_FROZEN_COIL { return 0 }
201 return 1
202}
203
204// negative control: an asserted-FALSE output must NOT pass (proves the
205// witness harness discriminates -- can't rubber-stamp a false HAVE).
206func w_negctl() -> i64 {
207 if nx_psy_psat_pa(K_PSY_T25_mC) == K_NEGCTL_WRONG_PSAT_PA { return 1 }
208 return 0
209}
210
211// ---- row emitter ---------------------------------------------------
212func row(status: *u8, cap: *u8, ev: *u8) -> i64 {
213 print(status)
214 print(" " as *u8)
215 print(cap)
216 print("\n " as *u8)
217 print(ev)
218 print("\n" as *u8)
219 return 0
220}
221
222func main() -> i64 {
223 let wpsy: i64 = w_psychro()
224 let wmet: i64 = w_metrics()
225 let wdri: i64 = w_drift()
226 let wliar: i64 = w_liarkill()
227 let wind: i64 = w_independence()
228 let wfdd: i64 = w_fdd()
229 let wneg: i64 = w_negctl()
230
231 print("=============================================================\n" as *u8)
232 print(" SOVEREIGN AC/HVAC MONITOR -- SOTA CAPABILITY CENSUS\n" as *u8)
233 print(" [HAVE]=executed-witness-here [CITE]=sibling-gate [PART]=partial [GAP]=named-SOTA-frontier\n" as *u8)
234 print("=============================================================\n" as *u8)
235
236 var have: i64 = 0
237 var cite: i64 = 0
238 var part: i64 = 0
239 var gap: i64 = 0
240
241 print("\n-- PHYSICS FLOOR ------------------------------------------\n" as *u8)
242 if wpsy == 1 { have = have + 1
243 row("[HAVE]" as *u8, "Psychrometrics (Psat/W/enthalpy/dewpoint), no-float" as *u8, "nx_psychrometrics: psat(25C)=3170Pa, h(25C/60%)=55460 J/kg == NIST/ASHRAE" as *u8)
244 } else { gap = gap + 1
245 row("[GAP ]" as *u8, "Psychrometrics" as *u8, "witness FAILED" as *u8) }
246 if wmet == 1 { have = have + 1
247 row("[HAVE]" as *u8, "Delivered capacity / COP / EER (air-side enthalpy method)" as *u8, "nx_ac_enthalpy_metrics: COP=3.60, EER=12.28, DC-grade dT*airflow*dh" as *u8)
248 } else { gap = gap + 1
249 row("[GAP ]" as *u8, "Delivered capacity / COP" as *u8, "witness FAILED" as *u8) }
250 if wmet == 1 { have = have + 1
251 row("[HAVE]" as *u8, "Carnot COP ceiling (hard physical bound)" as *u8, "nx_ac_carnot_cop_x100(24C,35C)=27.01 -- caps any claimed COP" as *u8)
252 } else { gap = gap + 1
253 row("[GAP ]" as *u8, "Carnot ceiling" as *u8, "witness FAILED" as *u8) }
254
255 print("\n-- TRUST / VERIFICATION (the differentiator) --------------\n" as *u8)
256 if wliar == 1 { have = have + 1
257 row("[HAVE]" as *u8, "Reading-level LIAR-KILLER (physics-invariant rejection)" as *u8, "nx_ac_sensor_verify: impossible reading -> IMPLAUSIBLE, never trusted" as *u8)
258 } else { gap = gap + 1
259 row("[GAP ]" as *u8, "Reading-level liar-killer" as *u8, "witness FAILED" as *u8) }
260 if wind == 1 { have = have + 1
261 row("[HAVE]" as *u8, "Cross-sensor independence (echo != corroboration)" as *u8, "nx_ac_sensor_verify: same-source echo -> not corroborated (crossval discipline)" as *u8)
262 } else { gap = gap + 1
263 row("[GAP ]" as *u8, "Cross-sensor independence" as *u8, "witness FAILED" as *u8) }
264 if wdri == 1 { have = have + 1
265 row("[HAVE]" as *u8, "Efficiency drift vs own baseline (the bill-hook)" as *u8, "nx_ac_enthalpy_metrics: drift(3.28 vs 4.00)=180 permille (18% degraded)" as *u8)
266 } else { gap = gap + 1
267 row("[GAP ]" as *u8, "Efficiency drift" as *u8, "witness FAILED" as *u8) }
268 part = part + 1
269 row("[PART]" as *u8, "External-comp: NIST/ASHRAE-grounded thresholds" as *u8, "KATs match NIST WebBook + Title 24; nx_research_verify evidence-ledger pending" as *u8)
270
271 print("\n-- FAULT DETECTION & DIAGNOSIS (NIST/APAR-grounded) -------\n" as *u8)
272 if wfdd == 1 { have = have + 1
273 row("[HAVE]" as *u8, "Refrigerant charge: undercharge / overcharge / liquid restriction" as *u8, "nx_ac_fdd: superheat+subcool rules (NISTIR 7350), Title 24 thresholds" as *u8)
274 } else { gap = gap + 1
275 row("[GAP ]" as *u8, "Refrigerant charge FDD" as *u8, "witness FAILED" as *u8) }
276 if wfdd == 1 { have = have + 1
277 row("[HAVE]" as *u8, "Fouled condenser / low airflow / frozen coil" as *u8, "nx_ac_fdd: condensing-over-ambient, evap split, suction-sat<0 (freeze)" as *u8)
278 } else { gap = gap + 1
279 row("[GAP ]" as *u8, "Coil/airflow FDD" as *u8, "witness FAILED" as *u8) }
280 cite = cite + 1
281 row("[CITE]" as *u8, "Short-cycling / degraded-capacity / poor-tracking" as *u8, "nx_hvac_efficiency (gate nx_hvac_efficiency_test GREEN)" as *u8)
282 gap = gap + 1
283 row("[GAP ]" as *u8, "Capacitor/compressor EOL from inrush-current trend" as *u8, "SOTA: #1 residential AC repair; needs start-current trend organ" as *u8)
284 gap = gap + 1
285 row("[GAP ]" as *u8, "Condensate drain clog detection" as *u8, "SOTA gap: today only a $15 float switch; needs pan-moisture/flow organ" as *u8)
286 gap = gap + 1
287 row("[GAP ]" as *u8, "Benchmark FDD vs labeled fault dataset" as *u8, "datasets identified (NIST HP/AC, LBNL 10.25984/1881324, RP-1043); harness TODO" as *u8)
288
289 print("\n-- SENSING / INGEST ---------------------------------------\n" as *u8)
290 cite = cite + 1
291 row("[CITE]" as *u8, "Device discovery / classify / anchor (multi-vendor)" as *u8, "nx_iot_discover (gate nx_iot_discover_test GREEN)" as *u8)
292 part = part + 1
293 row("[PART]" as *u8, "Electrical CT power/current ingest (Emporia/Sense-class)" as *u8, "architecture defined (HVAC R3); adapter model-specific, not built" as *u8)
294 gap = gap + 1
295 row("[GAP ]" as *u8, "Energy disaggregation (recognize AC in whole-home power)" as *u8, "SOTA-hard (Sense misses ACs); NILM organ TODO" as *u8)
296
297 print("\n-- ALERTING / UX / FLEET ----------------------------------\n" as *u8)
298 part = part + 1
299 row("[PART]" as *u8, "Hubless browser monitor UI (mobile + desktop)" as *u8, "building this session; zero/last-mile-JS, no mandatory hub" as *u8)
300 part = part + 1
301 row("[PART]" as *u8, "Plain-language alerts + bill impact" as *u8, "drift number present; phrasing + $ estimate UX pending" as *u8)
302 cite = cite + 1
303 row("[CITE]" as *u8, "Zero-JS control/monitor page (cross-browser)" as *u8, "nx_iot_control_page / nx_iot_dashboard (gates GREEN)" as *u8)
304 cite = cite + 1
305 row("[CITE]" as *u8, "Watchdog / self-heal reconnect (kills the blink)" as *u8, "nx_iot_watchdog (gate nx_iot_watchdog_test GREEN)" as *u8)
306 cite = cite + 1
307 row("[CITE]" as *u8, "Multi-tenant per-house (HR realms) + hubless LAN-resilient" as *u8, "nx_iot_hub_tenant (gate nx_iot_hub_tenant_gate GREEN); no cloud at runtime" as *u8)
308
309 // ---- coverage summary ----------------------------------------
310 let total: i64 = have + cite + part + gap
311 let covered: i64 = have + cite
312 print("\n=============================================================\n" as *u8)
313 print(" HAVE(executed) " as *u8); print_i64(have)
314 print(" CITE(gate) " as *u8); print_i64(cite)
315 print(" PART " as *u8); print_i64(part)
316 print(" GAP " as *u8); print_i64(gap)
317 print(" / " as *u8); print_i64(total)
318 print("\n coverage(have+cite) = " as *u8)
319 if total > 0 { print_i64((covered * 1000) / total) } else { print_i64(0) }
320 print(" permille\n" as *u8)
321
322 // ---- verdict: is the census's witness harness TRUSTWORTHY? ----
323 // GREEN iff all executed-HAVE witnesses passed, the neg-control FAILED,
324 // and coverage did not fall below the floor. RED means a claimed HAVE
325 // could not be reproduced here (never a fabricated green).
326 var trust: i64 = 1
327 if wpsy != 1 { trust = 0 }
328 if wmet != 1 { trust = 0 }
329 if wdri != 1 { trust = 0 }
330 if wliar != 1 { trust = 0 }
331 if wind != 1 { trust = 0 }
332 if wfdd != 1 { trust = 0 }
333 if wneg != 0 { trust = 0 } // neg-control MUST fail
334 if have < 8 { trust = 0 } // no-backslide floor on executed HAVEs
335
336 if trust == 1 {
337 print(" VERDICT: GREEN -- witness harness trustworthy; GAP rows = the work.\n" as *u8)
338 print("=============================================================\n" as *u8)
339 return 0
340 }
341 print(" VERDICT: RED -- a HAVE witness failed or neg-control passed.\n" as *u8)
342 print("=============================================================\n" as *u8)
343 return 1
344}