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}