code wiki / (root) / nx_water_awg_test.nx

nx_water_awg_test.nx source

↩ module page · 56 lines · 3924 B

1// nx_water_awg_test.nx -- the atmospheric-water-generation GATE for nx_water_awg: the psychrometric 2// condensation yield and energy model, the technology-class envelopes, and the harvester recommender 3// (humid -> condensation, desert -> sorbent, moderate -> passive capillary, too dry -> none). 4// 5// MIGRATED OFF A HAND-ROLLED VERDICT 2026-08-14 -- see the note in nx_water_quality_test for the full 6// reasoning. Short version: the exit code used to be the failed assertion NUMBER, so nothing outside 7// could read the outcome (no verdict line, no harness.jrnl frame) and the run stopped at the first 8// failure, hiding every later one. It now inherits nx_gate_verdict, so every tooth runs and the exit 9// code carries the verdict. Migrated per-tooth by hand: the automated D001 candidate collapses N teeth 10// into one boolean and reports passed 1/1, which cannot see a dropped conjunct. 11// 12// THE ENVELOPE TEETH ARE THE POINT. A recommender that always answered CONDENSATION would satisfy the 13// humid case; the desert, moderate and too-dry teeth are what force it to actually discriminate, and 14// the WA_NONE tooth is the one that proves it will REFUSE rather than invent a harvester for a climate 15// that cannot feed one. 16// license_tier: ORIGINAL expect_exit: 0 17 18import "nx_syscalls.nx" 19import "nx_gate_verdict.nx" 20import "nx_water_awg.nx" 21 22func main() -> i64 { 23 gv_head("nx_water_awg gate -- psychrometrics, technology envelopes, climate-to-harvester choice" as *u8) 24 let ctr: *i64 = gv_ctr() 25 26 // --- saturation vapour density table --- 27 gv_check("sat-vapour-density-30C-is-304" as *u8, wa_sat_vapor_density_x10(30) == 304, ctr) 28 gv_check("sat-vapour-density-20C-is-173" as *u8, wa_sat_vapor_density_x10(20) == 173, ctr) 29 30 // --- psychrometric condensation yield --- 31 gv_check("absolute-humidity-30C-70pct-is-212" as *u8, wa_abs_humidity_x10(30, 70) == 212, ctr) 32 gv_check("extractable-30C-70pct-coil-5C-is-144" as *u8, wa_extractable_x10(30, 70, 5) == 144, ctr) 33 // COOL AND DRY MUST YIELD NOTHING. Without this the model could return a positive extraction for 34 // every input and still pass every other yield tooth. 35 gv_check("neg-control-cool-dry-air-condenses-nothing" as *u8, wa_extractable_x10(20, 30, 5) == 0, ctr) 36 gv_check("daily-yield-100m3h-is-34560ml" as *u8, wa_daily_yield_ml(100, 144) == 34560, ctr) 37 gv_check("specific-energy-humid-case-is-208-wh-per-litre" as *u8, wa_specific_energy_whl(144) == 208, ctr) 38 39 // --- technology-class envelopes --- 40 gv_check("sorbent-MOF-works-at-20pct-RH" as *u8, wa_class_works(WA_SORBENT, 20) == 1, ctr) 41 // The paired opposite: the SAME humidity must be outside refrigeration's envelope. One envelope 42 // tooth alone proves nothing about whether the classes are actually distinguished. 43 gv_check("neg-control-refrigeration-does-NOT-work-at-20pct-RH" as *u8, wa_class_works(WA_CONDENSATION, 20) == 0, ctr) 44 gv_check("passive-capillary-costs-zero-energy" as *u8, wa_class_energy_whl(WA_PASSIVE_CAP) == 0, ctr) 45 46 // --- the recommender picks the right harvester per climate --- 47 gv_check("humid-climate-recommends-condensation" as *u8, wa_recommend(30, 70) == WA_CONDENSATION, ctr) 48 gv_check("desert-climate-recommends-sorbent" as *u8, wa_recommend(25, 20) == WA_SORBENT, ctr) 49 gv_check("moderate-climate-recommends-passive-capillary" as *u8, wa_recommend(20, 35) == WA_PASSIVE_CAP, ctr) 50 // REFUSAL OVER FABRICATION: a climate too dry for every class must return NONE, not the least-bad 51 // guess. This is the tooth that separates an honest recommender from one that always answers. 52 gv_check("neg-control-too-dry-for-any-class-returns-NONE" as *u8, wa_recommend(20, 10) == WA_NONE, ctr) 53 54 return gv_verdict("nx_water_awg_test" as *u8, ctr, 55 "psychrometric yield and energy, paired technology envelopes, and a climate recommender that refuses rather than guesses" as *u8) 56}