"""System B passes only when electric/thermal ledgers stay separate and scenarios cover the shortfall honestly.""" from __future__ import annotations import math import sys from pathlib import Path import pytest ROOT = Path(__file__).resolve().parents[1] sys.path.insert(0, str(ROOT)) from system_b_ledger import ( # noqa: E402 RETIRED_COMPOSITE_MW, SystemBLedger, build_ledger, ) @pytest.fixture def ledger() -> SystemBLedger: return build_ledger() def test_retired_composite_is_not_firm_electric(ledger: SystemBLedger) -> None: """The old 895 MW figure mixed 145 MWth into MW — it must not be the firm headline.""" assert RETIRED_COMPOSITE_MW == 895 assert ledger.firm_headline_mw != RETIRED_COMPOSITE_MW assert RETIRED_COMPOSITE_MW not in ledger.accreditation_mw.values() def test_thermal_mwth_never_enters_electric_sum(ledger: SystemBLedger) -> None: """Electric firm = BESS + DSM + intertie + hub_net_electric — never hub_thermal_mwth.""" full = ledger.accreditation_mw["full"] parts = ( ledger.bess_mw + ledger.dsm_mw + ledger.intertie_mw + ledger.hub_net_electric_mw ) assert full == parts assert ledger.hub_thermal_mwth not in ( ledger.bess_mw, ledger.dsm_mw, ledger.intertie_mw, ledger.hub_net_electric_mw, ) # Explicit anti-pattern: adding the full thermal build (effluent + contingent # compute reject) would recreate the retired 895 composite from regulator_paper_assumptions import v as _v hub_all_th = ledger.hub_thermal_mwth + _v("hub_contingent_thermal_mwth") mixed = ledger.bess_mw + hub_all_th + ledger.dsm_mw + ledger.intertie_mw assert mixed == RETIRED_COMPOSITE_MW assert full != mixed def test_reference_and_full_cover_shortfall(ledger: SystemBLedger) -> None: assert ledger.covers_shortfall("conservative") is False assert ledger.covers_shortfall("reference") is True assert ledger.covers_shortfall("full") is True assert ledger.margin_mw("reference") == ledger.accreditation_mw["reference"] - ledger.shortfall_mw assert ledger.margin_mw("full") == ledger.accreditation_mw["full"] - ledger.shortfall_mw def test_cost_per_kw_uses_electric_denominator(ledger: SystemBLedger) -> None: ref_net = ledger.cost_per_kw_hybrid_net("reference") full_net = ledger.cost_per_kw_hybrid_net("full") gas = ledger.cost_per_kw_gas_derate() assert ref_net < gas assert full_net < gas # Must not match the invalid $1,676/kW that used 895 as denominator invalid = ledger.hybrid_capex_net_b * 1e9 / (RETIRED_COMPOSITE_MW * 1000) assert not math.isclose(ref_net, invalid, rel_tol=1e-6) assert not math.isclose(full_net, invalid, rel_tol=1e-6) def test_twenty_year_bands_do_not_overlap(ledger: SystemBLedger) -> None: assert ledger.hybrid_20yr_high_b < ledger.gas_20yr_low_b lo, hi = ledger.savings_band_b assert lo == pytest.approx(ledger.gas_20yr_low_b - ledger.hybrid_20yr_high_b) assert hi == pytest.approx(ledger.gas_20yr_high_b - ledger.hybrid_20yr_low_b) assert lo > 0 and hi > lo def test_dual_ledgers_expose_thermal_and_electric(ledger: SystemBLedger) -> None: assert ledger.thermal_ledger_mwth["hub_total"] == ledger.hub_thermal_mwth assert ledger.electric_ledger_mw["hub_net"] == ledger.hub_net_electric_mw assert ledger.electric_ledger_mw["hub_net"] < ledger.thermal_ledger_mwth["hub_total"] def test_system_b_pass_report_is_all_green(ledger: SystemBLedger) -> None: report = ledger.pass_report() assert report["passed"] is True assert all(report["gates"].values()) assert "895" not in report["headline"] assert "413" in report["headline"] or "688" in report["headline"] or "788" in report["headline"] def test_peak_shave_profile_uses_net_electric_hub(ledger: SystemBLedger) -> None: """Hourly electric peak shave credits hub as net electric MW, not MWth.""" profile = ledger.peak_shave_mw_by_hour() assert len(profile) == 24 # Off-peak hours: hub net electric only assert profile[3] == ledger.hub_net_electric_mw # Morning peak window: hub + BESS + DSM assert profile[8] == ledger.hub_net_electric_mw + ledger.bess_mw + ledger.dsm_mw