diff --git a/changelog.d/va-liheap-cooling.added.md b/changelog.d/va-liheap-cooling.added.md new file mode 100644 index 00000000000..a645ed568de --- /dev/null +++ b/changelog.d/va-liheap-cooling.added.md @@ -0,0 +1 @@ +Add Virginia Energy Assistance Program cooling assistance electric bill payment. diff --git a/policyengine_us/parameters/gov/hhs/liheap/regular_payments.yaml b/policyengine_us/parameters/gov/hhs/liheap/regular_payments.yaml index e811bea6fbd..619e6d83221 100644 --- a/policyengine_us/parameters/gov/hhs/liheap/regular_payments.yaml +++ b/policyengine_us/parameters/gov/hhs/liheap/regular_payments.yaml @@ -49,6 +49,7 @@ values: - tx_ceap # Texas CEAP - ut_heat # Utah HEAT - va_eap # Virginia EAP + - va_eap_cooling # Virginia EAP cooling - vt_liheap # Vermont Seasonal Fuel Assistance - wa_liheap # Washington LIHEAP - wi_wheap # Wisconsin WHEAP diff --git a/policyengine_us/parameters/gov/states/va/dss/eap/cooling/electric_bill_maximum.yaml b/policyengine_us/parameters/gov/states/va/dss/eap/cooling/electric_bill_maximum.yaml new file mode 100644 index 00000000000..5c2245b1cfb --- /dev/null +++ b/policyengine_us/parameters/gov/states/va/dss/eap/cooling/electric_bill_maximum.yaml @@ -0,0 +1,26 @@ +description: Virginia limits cooling assistance electric bill payments to this amount per program year under the Energy Assistance Program. +# The VDSS Home Office sets this maximum each year. Each value is dated to the +# start of the federal fiscal year whose summer it covers. VDSS announced $600 +# for 2023; no amount was found for 2024, so 2024 carries the $600 forward. The +# $365 for 2025 comes from press reports attributed to VDSS; no VDSS notice was +# found for 2025, 2026 or 2027, so 2026 and 2027 carry the $365 forward. The +# first value also backfills years before 2023, which are unverified. +values: + 2022-10-01: 600 + 2024-10-01: 365 + +metadata: + unit: currency-USD + period: year + label: Virginia EAP cooling assistance electric bill payment maximum + reference: + - title: "Virginia Energy Assistance Manual, Volume IX, Chapter J.6 Authorizations, J.7.g Payment of Electric Bill and J.8 Cooling Assistance Benefits #page 123,127-129" + href: https://www.dss.virginia.gov/media/vdss/benefit-programs/documents/eap/Complete_Manual.pdf#page=123 + - title: 22VAC40-680-63(C) Eligibility criteria; benefits + href: https://law.lis.virginia.gov/admincode/title22/agency40/chapter680/section63/ + - title: VDSS news release, Cooling Assistance Application Period Underway (July 5, 2023), one-time $600 benefit for electric bills (Wayback Machine copy) + href: https://web.archive.org/web/20260413134008/https://dss.virginia.gov/files/division/pa/news_releases/2023/Cooling_Assistance_2023_ENG.pdf#page=1 + - title: Press report, WYDaily, Cooling assistance available, application period underway (July 20, 2025), VDSS one-time $365 benefit for electric bills + href: https://wydaily.com/latest/regional-national/2025/07/20/cooling-assistance-available-application-period-underway/ + - title: Press report, WRIC on WAVY (July 17, 2025), VDSS one-time $365 benefit for electric bills + href: https://digital-release.wavy.com/?p=2780089 diff --git a/policyengine_us/parameters/gov/states/va/dss/eap/cooling/fpg_year_lag.yaml b/policyengine_us/parameters/gov/states/va/dss/eap/cooling/fpg_year_lag.yaml new file mode 100644 index 00000000000..052d0a8a6e2 --- /dev/null +++ b/policyengine_us/parameters/gov/states/va/dss/eap/cooling/fpg_year_lag.yaml @@ -0,0 +1,19 @@ +description: Virginia uses federal poverty guidelines from this many years before the cooling season for the cooling assistance income limit under the Energy Assistance Program. +# Virginia adopts each year's new 150% limits in June. They apply first to that +# June's cooling assistance and then to heating in the next federal fiscal +# year, so cooling in the summer of year Y uses the year Y guideline while +# heating in federal fiscal year Y uses the year Y - 1 guideline. The value is +# dated at the start of FFY2025, whose June 2025 cooling the matrix note +# describes. +values: + 2024-10-01: 0 + +metadata: + unit: year + period: year + label: Virginia EAP cooling assistance federal poverty guideline year lag + reference: + - title: LIHEAP Clearinghouse Virginia FY2026 benefit matrix, income limits note (the 150% limits "were used for Cooling Assistance in June of 2025") + href: https://liheapch.acf.gov/docs/2026/benefits-matricies/VA_BenefitMatrix_2026.pdf#page=1 + - title: Press report, WYDaily, State cooling assistance program helps residents with summer energy costs (June 15, 2026), 2026 limits of $1,995 a month for one person and $4,125 for four + href: https://wydaily.com/latest/2026/06/15/state-cooling-assistance-program-helps-residents-with-summer-energy-costs/ diff --git a/policyengine_us/programs.yaml b/policyengine_us/programs.yaml index 6f704d520fb..c92344013cf 100644 --- a/policyengine_us/programs.yaml +++ b/policyengine_us/programs.yaml @@ -1395,7 +1395,15 @@ programs: variable: va_eap parameter_prefix: gov.states.va.dss.eap verified_years: "2026" - notes: FFY2026 Fuel Assistance only, using the latest published (FFY2025) value per point and placeholder fuel-type and energy-burden points until VDSS publishes its survey. Crisis, cooling and weatherization assistance are out of scope. + notes: FFY2026 Fuel Assistance only, using the latest published (FFY2025) value per point and placeholder fuel-type and energy-burden points until VDSS publishes its survey. Cooling assistance is the separate Virginia EAP cooling entry; crisis and weatherization assistance are out of scope. + - state: VA + status: partial + name: Virginia EAP cooling + full_name: Virginia Energy Assistance Program Cooling Assistance electric bill payment + variable: va_eap_cooling + parameter_prefix: gov.states.va.dss.eap.cooling + verified_years: "2025" + notes: Cooling Assistance electric bill payment up to the statewide maximum, $365 for 2025 from press reports and carried forward to 2026 and 2027. Cooling equipment, security deposits, crisis and weatherization assistance are out of scope. - state: VT status: partial name: Vermont Seasonal Fuel Assistance diff --git a/policyengine_us/tests/policy/baseline/gov/states/va/dss/eap/cooling/va_eap_cooling.yaml b/policyengine_us/tests/policy/baseline/gov/states/va/dss/eap/cooling/va_eap_cooling.yaml new file mode 100644 index 00000000000..a1047704116 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/va/dss/eap/cooling/va_eap_cooling.yaml @@ -0,0 +1,200 @@ +# Virginia EAP cooling assistance electric bill payment: the electric bill up +# to the year's statewide maximum (Complete EAP Manual J.6, J.7.g, J.8). The +# maximum is $600 for 2023 (VDSS release) and $365 for 2025 (press reports), +# carried forward to 2026 and 2027. Unless noted, the household is one +# retiree aged 62 with $18,000 of Social Security, countable income +# 18,000 - 600 = 17,400, under every year's one-person cooling limit, and a +# $150 a month ($1,800 a year) electric bill, about the EIA 2024 Virginia +# average residential bill of $148.77 a month (Electric Sales, Revenue, and +# Average Price, Table 5A). + +- name: Case 1, an eligible retiree receives the 2025 maximum carried into 2026. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 62 + social_security_retirement: 18_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 900 + has_cooling_expense: true + pre_subsidy_electricity_expense: 1_800 + households: + household: + members: [person1] + state_code: VA + output: + # min(1,800, 365) = 365. + va_eap_cooling_eligible: true + va_eap_cooling: 365 + +- name: Case 2, an eligible retiree receives the 2025 maximum. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 62 + social_security_retirement: 18_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 900 + has_cooling_expense: true + pre_subsidy_electricity_expense: 1_800 + households: + household: + members: [person1] + state_code: VA + output: + # 17,400 <= 23,472 (2025 guideline); min(1,800, 365) = 365. + va_eap_cooling: 365 + +- name: Case 3, the 2025 maximum carries forward to 2027. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 62 + social_security_retirement: 18_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 900 + has_cooling_expense: true + pre_subsidy_electricity_expense: 1_800 + households: + household: + members: [person1] + state_code: VA + output: + va_eap_cooling: 365 + +- name: Case 4, the 2023 maximum applies in 2023. + period: 2023 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 62 + social_security_retirement: 18_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 900 + has_cooling_expense: true + pre_subsidy_electricity_expense: 1_800 + households: + household: + members: [person1] + state_code: VA + output: + # 17,400 <= 21,864 (floor(14,580 x 1.5 / 12) = 1,822 x 12); + # min(1,800, 600) = 600. + va_eap_cooling: 600 + +- name: Case 5, a bill below the maximum is paid in full. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 62 + social_security_retirement: 18_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 900 + has_cooling_expense: true + pre_subsidy_electricity_expense: 240 + households: + household: + members: [person1] + state_code: VA + output: + # min(240, 365) = 240. + va_eap_cooling: 240 + +- name: Case 6, income over the cooling limit receives nothing. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 62 + social_security_retirement: 30_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 900 + has_cooling_expense: true + pre_subsidy_electricity_expense: 1_800 + households: + household: + members: [person1] + state_code: VA + output: + # 30,000 - 600 = 29,400 > 23,940. + va_eap_cooling: 0 + +- name: Case 7, a household without a separate cooling cost receives nothing. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 62 + social_security_retirement: 18_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 900 + has_cooling_expense: false + pre_subsidy_electricity_expense: 1_800 + households: + household: + members: [person1] + state_code: VA + output: + va_eap_cooling: 0 + +# The Fairfax County retiree of the heating integration tests (Social Security +# 11,736, countable 11,736 - 600 = 11,136, gas heat, 103 points x 4.531665 = +# 466.76) also has a cooling cost and the $1,800 electric bill. Cooling pays +# min(1,800, 365) = 365. The national LIHEAP total is 466.76 + 365 = 831.76. +- name: Case 8, a retiree receives both the heating and the cooling payment. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + head: + age: 65 + social_security_retirement: 11_736 + ssi: 0 + spm_units: + spm_unit: + members: [head] + heating_type: NATURAL_GAS + gas_expense: 1_200 + has_cooling_expense: true + pre_subsidy_electricity_expense: 1_800 + households: + household: + members: [head] + state_code: VA + county: FAIRFAX_COUNTY_VA + output: + va_eap: 466.76 + va_eap_cooling: 365 + liheap: 831.76 diff --git a/policyengine_us/tests/policy/baseline/gov/states/va/dss/eap/cooling/va_eap_cooling_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/va/dss/eap/cooling/va_eap_cooling_eligible.yaml new file mode 100644 index 00000000000..3a36b6962f9 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/va/dss/eap/cooling/va_eap_cooling_eligible.yaml @@ -0,0 +1,377 @@ +# Virginia EAP cooling assistance electric bill payment eligibility (Complete +# EAP Manual J.3, J.7.g; FY2026 plan section 3; 22VAC40-680-63): the Fuel +# Assistance income and citizenship tests against the current-year guideline, +# at least one member aged 60 or older, under 6 or disabled, a cooling cost +# paid separately from rent, a positive electric bill, and not homeless. No +# heating fuel is required. A member aged 60 or older has $50 a month ($600 a +# year) deducted from income. 2026 one-person cooling limit 23,940 (2026 +# guideline); 2026 one-person heating limit 23,472 (2025 guideline). The $150 +# a month ($1,800 a year) electric bill is about the EIA 2024 Virginia average +# residential bill of $148.77 a month (Electric Sales, Revenue, and Average +# Price, Table 5A). + +- name: Case 1, a retiree at the 2026 one-person cooling limit is eligible though over the heating limit. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 62 + social_security_retirement: 24_540 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 900 + has_cooling_expense: true + pre_subsidy_electricity_expense: 1_800 + households: + household: + members: [person1] + state_code: VA + output: + # 24,540 - 600 = 23,940 <= 23,940 cooling limit; > 23,472 heating limit. + va_eap_countable_income: 23_940 + va_eap_cooling_income_limit: 23_940 + va_eap_income_eligible: false + va_eap_cooling_eligible: true + +- name: Case 2, a retiree one dollar over the 2026 one-person cooling limit is ineligible. + period: 2026 + input: + people: + person1: + age: 62 + social_security_retirement: 24_541 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 900 + has_cooling_expense: true + pre_subsidy_electricity_expense: 1_800 + households: + household: + members: [person1] + state_code: VA + output: + # 24,541 - 600 = 23,941 > 23,940. + va_eap_cooling_eligible: false + +- name: Case 3, a working adult with no vulnerable member is ineligible. + period: 2026 + input: + people: + person1: + age: 45 + employment_income_before_lsr: 20_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 900 + has_cooling_expense: true + pre_subsidy_electricity_expense: 1_800 + households: + household: + members: [person1] + state_code: VA + output: + # 20,000 <= 23,940, but no member is 60 or older, under 6 or disabled. + va_eap_vulnerability_points: 0 + va_eap_cooling_eligible: false + +- name: Case 4, a parent with a five-year-old child is eligible. + period: 2026 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 30_000 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + heating_type: ELECTRICITY + pre_subsidy_electricity_expense: 1_800 + has_cooling_expense: true + households: + household: + members: [person1, person2] + state_code: VA + output: + # 30,000 <= 32,460 two-person cooling limit (2,705 x 12); child under 6. + va_eap_cooling_eligible: true + +- name: Case 5, the same parent once the child is six is ineligible. + period: 2026 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 30_000 + person2: + age: 6 + spm_units: + spm_unit: + members: [person1, person2] + heating_type: ELECTRICITY + pre_subsidy_electricity_expense: 1_800 + has_cooling_expense: true + households: + household: + members: [person1, person2] + state_code: VA + output: + va_eap_cooling_eligible: false + +- name: Case 6, an adult receiving Social Security disability is eligible. + period: 2026 + input: + people: + person1: + age: 45 + social_security_disability: 18_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 900 + has_cooling_expense: true + pre_subsidy_electricity_expense: 1_800 + households: + household: + members: [person1] + state_code: VA + output: + # Disabled under 22VAC40-680-10; 18,000 - 600 = 17,400 <= 23,940. + va_eap_disabled: true + va_eap_cooling_eligible: true + +- name: Case 7, a working disabled couple who both receive SSI is eligible above the two-person cooling limit. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 45 + employment_income_before_lsr: 17_000 + ssi: 701 + is_ssi_disabled: true + person2: + age: 42 + employment_income_before_lsr: 17_000 + ssi: 701 + is_ssi_disabled: true + spm_units: + spm_unit: + members: [person1, person2] + heating_type: NATURAL_GAS + gas_expense: 900 + has_cooling_expense: true + pre_subsidy_electricity_expense: 1_800 + households: + household: + members: [person1, person2] + state_code: VA + output: + # 34,000 + 1,402 - 2 x 600 = 34,202 > 32,460, but every member receives + # SSI (Manual B.6.a, applied to cooling by J.3.a). + va_eap_countable_income: 34_202 + va_eap_cooling_eligible: true + +- name: Case 8, a household without a separate cooling cost is ineligible. + period: 2026 + input: + people: + person1: + age: 62 + social_security_retirement: 18_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 900 + has_cooling_expense: false + pre_subsidy_electricity_expense: 1_800 + households: + household: + members: [person1] + state_code: VA + output: + va_eap_cooling_eligible: false + +- name: Case 9, a household with no electric bill is ineligible. + period: 2026 + input: + people: + person1: + age: 62 + social_security_retirement: 18_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 900 + has_cooling_expense: true + pre_subsidy_electricity_expense: 0 + households: + household: + members: [person1] + state_code: VA + output: + va_eap_cooling_eligible: false + +- name: Case 10, a homeless household is ineligible. + period: 2026 + input: + people: + person1: + age: 62 + social_security_retirement: 18_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NONE + has_cooling_expense: true + pre_subsidy_electricity_expense: 1_800 + households: + household: + members: [person1] + state_code: VA + is_homeless: true + output: + va_eap_cooling_eligible: false + +- name: Case 11, a household with no heating fuel is eligible for cooling only. + period: 2026 + input: + people: + person1: + age: 62 + social_security_retirement: 18_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NONE + has_cooling_expense: true + pre_subsidy_electricity_expense: 1_800 + households: + household: + members: [person1] + state_code: VA + output: + va_eap_eligible: false + va_eap_cooling_eligible: true + +- name: Case 12, an unspecified heating type is eligible for cooling only. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 62 + social_security_retirement: 18_000 + spm_units: + spm_unit: + members: [person1] + heating_type: UNSPECIFIED + has_cooling_expense: true + pre_subsidy_electricity_expense: 1_800 + households: + household: + members: [person1] + state_code: VA + output: + # Regular heating pays no unspecified fuel; cooling sets no heating-fuel + # condition (manual J.3.a). + va_eap_eligible: false + # Was false, now true: cooling sets no heating-fuel condition. + va_eap_cooling_eligible: true + # Was 0, now 365: the household is eligible; min(1,800, 365) = 365. + va_eap_cooling: 365 + +- name: Case 13, a public housing tenant who pays the electric bill is eligible. + period: 2026 + input: + people: + person1: + age: 62 + social_security_retirement: 18_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 900 + has_cooling_expense: true + pre_subsidy_electricity_expense: 1_800 + households: + household: + members: [person1] + state_code: VA + is_in_public_housing: true + output: + # Living arrangement G on the cooling application. + va_eap_cooling_eligible: true + +- name: Case 14, a public housing tenant whose heat is in the rent and who pays a separate cooling cost is eligible. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 62 + social_security_retirement: 18_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + heat_expense_included_in_rent: true + has_cooling_expense: true + pre_subsidy_electricity_expense: 1_800 + households: + household: + members: [person1] + state_code: VA + is_in_public_housing: true + output: + # Regular heating excludes a subsidized household whose heat is in the + # rent. Cooling follows manual J.3.a (Chapter B sections 6-8) and plan + # 3.3, which excludes such a household only when its cooling is in the + # rent: 18,000 - 600 = 17,400 <= 23,940; min(1,800, 365) = 365. + # Candidate us-va:eap-cooling-subsidized-heat-in-rent. + va_eap_eligible: false + va_eap_cooling_eligible: true + va_eap_cooling: 365 + +- name: Case 15, a household with no citizen or qualified alien member is ineligible. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 62 + immigration_status: UNDOCUMENTED + employment_income_before_lsr: 17_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 900 + has_cooling_expense: true + pre_subsidy_electricity_expense: 1_800 + households: + household: + members: [person1] + state_code: VA + output: + # Manual B.7 (applied by J.3.a): the member is not counted in household + # size. The income limit uses a size of at least one: 17,000 - 600 = + # 16,400 <= 23,940, and the member is 60 or older, so only the household + # size term denies. + va_eap_household_size: 0 + va_eap_countable_income: 16_400 + va_eap_cooling_income_limit: 23_940 + va_eap_cooling_eligible: false + va_eap_cooling: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/va/dss/eap/cooling/va_eap_cooling_income_limit.yaml b/policyengine_us/tests/policy/baseline/gov/states/va/dss/eap/cooling/va_eap_cooling_income_limit.yaml new file mode 100644 index 00000000000..b88a80a386a --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/va/dss/eap/cooling/va_eap_cooling_income_limit.yaml @@ -0,0 +1,32 @@ +# Virginia EAP cooling assistance income limit: the Fuel Assistance formula, +# floor(150% of the guideline / 12) for sizes 1-20 plus a floored increment per +# member over 20, annualized x 12, but with the guideline of the cooling +# season's own year (VA FY2026 benefit matrix note: the 2025 limits "were used +# for Cooling Assistance in June of 2025"). WYDaily (June 15, 2026) reports +# 2026 cooling limits of $1,995 a month for one person and $4,125 for four. + +- name: Case 1, 2026 limits use the 2026 guideline, and zero outside Virginia. + period: 2026 + absolute_error_margin: 0.01 + input: + state_code: [VA, VA, VA, VA, MD] + va_eap_household_size: [1, 2, 4, 21, 1] + output: + # 2026 guideline 15,960 + 5,680 per added person, x 1.5 / 12: + # size 1 = 1,995; size 2 = 21,640 x 1.5 / 12 = 2,705; + # size 4 = 33,000 x 1.5 / 12 = 4,125; + # size 20 = 123,880 x 1.5 / 12 = 15,485, plus floor(5,680 x 1.5 / 12) = + # 710 for the 21st member = 16,195. Annual = monthly x 12. + va_eap_cooling_income_limit: [23_940, 32_460, 49_500, 194_340, 0] + +- name: Case 2, 2025 limits use the 2025 guideline. + period: 2025 + absolute_error_margin: 0.01 + input: + state_code: [VA, VA] + va_eap_household_size: [1, 4] + output: + # The published monthly limits used in June 2025: size 1 + # floor(15,650 x 1.5 / 12) = floor(1,956.25) = 1,956; size 4 + # floor(32,150 x 1.5 / 12) = floor(4,018.75) = 4,018. Annual = x 12. + va_eap_cooling_income_limit: [23_472, 48_216] diff --git a/policyengine_us/variables/gov/states/va/dss/eap/cooling/va_eap_cooling.py b/policyengine_us/variables/gov/states/va/dss/eap/cooling/va_eap_cooling.py new file mode 100644 index 00000000000..61c1701c462 --- /dev/null +++ b/policyengine_us/variables/gov/states/va/dss/eap/cooling/va_eap_cooling.py @@ -0,0 +1,30 @@ +from policyengine_us.model_api import * + + +class va_eap_cooling(Variable): + value_type = float + entity = SPMUnit + definition_period = YEAR + unit = USD + label = "Virginia EAP cooling assistance electric bill payment" + documentation = ( + "The electric bill up to the statewide maximum for the year. The annual " + "electricity expense stands in for the balance owed on the electric " + "account during the June to August application window. The first-come " + "funding pool and the application window are not modeled." + ) + reference = ( + # PDF pages 123, 127-129 + "https://www.dss.virginia.gov/media/vdss/benefit-programs/documents/eap/Complete_Manual.pdf#page=123", + "https://liheapch.acf.gov/docs/2026/state-plans/VA_Plan_2026.pdf#page=12", + "https://law.lis.virginia.gov/admincode/title22/agency40/chapter680/section63/", + ) + defined_for = "va_eap_cooling_eligible" + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.va.dss.eap.cooling + # Manual J.6: "The amount of assistance provided is the exact amount + # of the bill not to exceed the appropriate maximum benefit." The + # annual electricity bill stands in for the balance owed. + bill = spm_unit("pre_subsidy_electricity_expense", period) + return min_(bill, p.electric_bill_maximum) diff --git a/policyengine_us/variables/gov/states/va/dss/eap/cooling/va_eap_cooling_eligible.py b/policyengine_us/variables/gov/states/va/dss/eap/cooling/va_eap_cooling_eligible.py new file mode 100644 index 00000000000..ccd910f361c --- /dev/null +++ b/policyengine_us/variables/gov/states/va/dss/eap/cooling/va_eap_cooling_eligible.py @@ -0,0 +1,55 @@ +from policyengine_us.model_api import * +from policyengine_us.variables.gov.states.va.dss.eap.va_eap_income_eligible import ( + va_eap_income_test, +) + + +class va_eap_cooling_eligible(Variable): + value_type = bool + entity = SPMUnit + definition_period = YEAR + label = "Eligible for Virginia EAP cooling assistance electric bill payment" + reference = ( + # PDF pages 120-122, 127-128 + "https://www.dss.virginia.gov/media/vdss/benefit-programs/documents/eap/Complete_Manual.pdf#page=120", + # PDF pages 11-12 + "https://liheapch.acf.gov/docs/2026/state-plans/VA_Plan_2026.pdf#page=11", + "https://law.lis.virginia.gov/admincode/title22/agency40/chapter680/section63/", + "https://law.lis.virginia.gov/admincode/title22/agency40/chapter680/section10/", + ) + defined_for = StateCode.VA + + def formula(spm_unit, period, parameters): + # Manual J.3.a applies the Chapter B.6-8 income and citizenship + # criteria; no heating fuel is required. + has_eligible_member = spm_unit("va_eap_household_size", period) > 0 + limit = spm_unit("va_eap_cooling_income_limit", period) + income_eligible = va_eap_income_test(spm_unit, period, limit) + # Manual J.3.c: "at least one vulnerable person (a person who is age + # 60 or older, under age 6 or disabled)". Each of these conditions + # scores positive vulnerability points. + vulnerable = spm_unit("va_eap_vulnerability_points", period) > 0 + # Manual J.3.f.1: households without a regular cooling expense + # (living arrangements B and F) receive equipment only. Plan 3.3: + # subsidized households whose cooling is in rent are not eligible. + # Renters whose cooling is in an unsubsidized rent (living + # arrangement E) have no separate cooling expense here and are not + # modeled. A subsidized household whose heat is in its rent but which + # pays a separate cooling cost is eligible, following manual J.3.a + # (Chapter B sections 6-8 only) and plan 3.3; candidate + # us-va:eap-cooling-subsidized-heat-in-rent. + has_cooling_expense = spm_unit("has_cooling_expense", period) + # Manual J.7.g: the application is denied "If the current balance is + # zero". The annual electricity bill stands in for the balance owed. + has_electric_bill = spm_unit("pre_subsidy_electricity_expense", period) > 0 + # Manual J.3.f.2: shelter residents and homeless households receive + # only a security deposit. + homeless = spm_unit.household("is_homeless", period) + return ( + has_eligible_member + & income_eligible + & vulnerable + & has_cooling_expense + & has_electric_bill + & ~homeless + ) diff --git a/policyengine_us/variables/gov/states/va/dss/eap/cooling/va_eap_cooling_income_limit.py b/policyengine_us/variables/gov/states/va/dss/eap/cooling/va_eap_cooling_income_limit.py new file mode 100644 index 00000000000..486ccdfaea9 --- /dev/null +++ b/policyengine_us/variables/gov/states/va/dss/eap/cooling/va_eap_cooling_income_limit.py @@ -0,0 +1,28 @@ +from policyengine_us.model_api import * +from policyengine_us.variables.gov.states.va.dss.eap.va_eap_income_limit import ( + va_eap_annual_income_limit, +) + + +class va_eap_cooling_income_limit(Variable): + value_type = float + entity = SPMUnit + definition_period = YEAR + unit = USD + label = "Virginia EAP cooling assistance annual income limit" + reference = ( + # PDF pages 28, 120 + "https://www.dss.virginia.gov/media/vdss/benefit-programs/documents/eap/Complete_Manual.pdf#page=28", + # PDF pages 11-12 + "https://liheapch.acf.gov/docs/2026/state-plans/VA_Plan_2026.pdf#page=11", + "https://liheapch.acf.gov/docs/2026/benefits-matricies/VA_BenefitMatrix_2026.pdf#page=1", + "https://law.lis.virginia.gov/admincode/title22/agency40/chapter680/section63/", + ) + defined_for = StateCode.VA + + def formula(spm_unit, period, parameters): + # Plan 3.5: cooling recipients "must meet the same income criteria as + # established for the Heating Assistance component", with the + # guideline year adopted each June. + p = parameters(period).gov.states.va.dss.eap.cooling + return va_eap_annual_income_limit(spm_unit, period, parameters, p.fpg_year_lag) diff --git a/policyengine_us/variables/gov/states/va/dss/eap/va_eap_income_eligible.py b/policyengine_us/variables/gov/states/va/dss/eap/va_eap_income_eligible.py index 0c752da6e76..56754f03ade 100644 --- a/policyengine_us/variables/gov/states/va/dss/eap/va_eap_income_eligible.py +++ b/policyengine_us/variables/gov/states/va/dss/eap/va_eap_income_eligible.py @@ -1,6 +1,19 @@ from policyengine_us.model_api import * +def va_eap_income_test(spm_unit, period, limit): + """Countable income at or below limit, or every member receives SSI.""" + income = spm_unit("va_eap_countable_income", period) + # Manual B.6.a: "No eligible household shall exceed the income maximums + # set by the VDSS, except households in which all members are SSI + # recipients." 22VAC40-680-20(B)(1): income "must be at or below" the + # limit. + person = spm_unit.members + receives_ssi = (person("ssi", period) > 0) | person("receives_ssi", period) + all_ssi = spm_unit.all(receives_ssi) + return (income <= limit) | all_ssi + + class va_eap_income_eligible(Variable): value_type = bool entity = SPMUnit @@ -15,13 +28,5 @@ class va_eap_income_eligible(Variable): defined_for = StateCode.VA def formula(spm_unit, period, parameters): - income = spm_unit("va_eap_countable_income", period) limit = spm_unit("va_eap_income_limit", period) - # Manual B.6.a: "No eligible household shall exceed the income maximums - # set by the VDSS, except households in which all members are SSI - # recipients." 22VAC40-680-20(B)(1): income "must be at or below" the - # limit. - person = spm_unit.members - receives_ssi = (person("ssi", period) > 0) | person("receives_ssi", period) - all_ssi = spm_unit.all(receives_ssi) - return (income <= limit) | all_ssi + return va_eap_income_test(spm_unit, period, limit) diff --git a/policyengine_us/variables/gov/states/va/dss/eap/va_eap_income_limit.py b/policyengine_us/variables/gov/states/va/dss/eap/va_eap_income_limit.py index 9dc156996fb..79c0ef5a9d9 100644 --- a/policyengine_us/variables/gov/states/va/dss/eap/va_eap_income_limit.py +++ b/policyengine_us/variables/gov/states/va/dss/eap/va_eap_income_limit.py @@ -2,6 +2,34 @@ from policyengine_us.variables.gov.hhs.tax_unit_fpg import fpg +def va_eap_annual_income_limit(spm_unit, period, parameters, year_lag): + """Annual EAP income limit from the guideline year_lag years back.""" + p = parameters(period).gov.states.va.dss.eap.eligibility + size = spm_unit("va_eap_household_size", period) + state_group = spm_unit.household("state_group_str", period) + capped_size = clip(size, 1, p.max_table_size) + guideline = fpg(capped_size, state_group, period, parameters, year_lag=year_lag) + additional_guideline = ( + fpg( + capped_size + 1, + state_group, + period, + parameters, + year_lag=year_lag, + ) + - guideline + ) + # Manual B.6.a prints monthly limits for sizes 1 to 20 and "for each + # extra member over 20, add $687". Flooring 150% of the 2025 guideline + # over twelve months reproduces every printed amount and the $687 + # increment; this is a reconciled numerical pattern, not an express + # rounding rule. + monthly_limit = np.floor(p.fpg_rate * guideline / MONTHS_IN_YEAR) + monthly_increment = np.floor(p.fpg_rate * additional_guideline / MONTHS_IN_YEAR) + additional_people = max_(size - p.max_table_size, 0) + return (monthly_limit + additional_people * monthly_increment) * MONTHS_IN_YEAR + + class va_eap_income_limit(Variable): value_type = float entity = SPMUnit @@ -19,28 +47,4 @@ class va_eap_income_limit(Variable): def formula(spm_unit, period, parameters): p = parameters(period).gov.states.va.dss.eap.eligibility - size = spm_unit("va_eap_household_size", period) - state_group = spm_unit.household("state_group_str", period) - capped_size = clip(size, 1, p.max_table_size) - guideline = fpg( - capped_size, state_group, period, parameters, year_lag=p.fpg_year_lag - ) - additional_guideline = ( - fpg( - capped_size + 1, - state_group, - period, - parameters, - year_lag=p.fpg_year_lag, - ) - - guideline - ) - # Manual B.6.a prints monthly limits for sizes 1 to 20 and "for each - # extra member over 20, add $687". Flooring 150% of the 2025 guideline - # over twelve months reproduces every printed amount and the $687 - # increment; this is a reconciled numerical pattern, not an express - # rounding rule. - monthly_limit = np.floor(p.fpg_rate * guideline / MONTHS_IN_YEAR) - monthly_increment = np.floor(p.fpg_rate * additional_guideline / MONTHS_IN_YEAR) - additional_people = max_(size - p.max_table_size, 0) - return (monthly_limit + additional_people * monthly_increment) * MONTHS_IN_YEAR + return va_eap_annual_income_limit(spm_unit, period, parameters, p.fpg_year_lag) diff --git a/source_conflicts/candidates.yaml b/source_conflicts/candidates.yaml index 352bbc3a578..35ed4d348b9 100644 --- a/source_conflicts/candidates.yaml +++ b/source_conflicts/candidates.yaml @@ -12097,6 +12097,50 @@ candidates: a filer can be claimed, not whether one is, and either claimable spouse bars a joint return (va_refundable_eitc_if_claimed.py, va_non_refundable_eitc_if_claimed.py, va_low_income_tax_credit_eligible.py). Ruled in October 2026 to use claimability; verify the guidance and distinguish this wording conflict from mixed-spouse allocation.' +- id: us-va:eap-cooling-subsidized-heat-in-rent + program: liheap + years: + from: 2023 + to: 2027 + type: federal-fiscal + question: Can a Virginia subsidized household whose heat is included in its rent, and which pays a separate cooling + cost, receive the Cooling Assistance electric bill payment, although 22VAC40-680-63(B)(1) applies all of the fuel + assistance criteria of 22VAC40-680-20, whose 20(B)(3)(a) makes such households ineligible? + sources: + - kind: regulation + citation: 22VAC40-680-63(B)(1) + url: https://law.lis.virginia.gov/admincode/title22/agency40/chapter680/section63/ + - kind: regulation + citation: 22VAC40-680-20(B)(3)(a) + url: https://law.lis.virginia.gov/admincode/title22/agency40/chapter680/section20/ + - kind: manual + citation: Virginia Energy Assistance Manual, Volume IX, Chapter J.3.a and J.3.f, PDF pages 120-121 + url: https://www.dss.virginia.gov/media/vdss/benefit-programs/documents/eap/Complete_Manual.pdf#page=120 + - kind: plan + citation: Virginia FY2026 LIHEAP State Plan, item 3.3, PDF page 11 + url: https://liheapch.acf.gov/docs/2026/state-plans/VA_Plan_2026.pdf#page=11 + readings: + statute: No statute is supplied; 63(B)(1) requires a cooling household to "Meet all of the fuel assistance criteria + as set forth in 22VAC40-680-20", and 20(B)(3)(a) makes "Subsidized households whose total heating costs are + included in their rent" ineligible. + other: Manual J.3.a applies "All the criteria in Chapter B sections 6-8", which leave out the B.5.c.2 household-type + exclusions, and J.3.f says a household "may or may not be eligible for Cooling Assistance depending on their + living arrangement", limiting codes B and F to equipment and homeless households to a security deposit. Plan 3.3 + restates the exclusion in cooling terms, "Subsidized households whose total cooling costs are included in their + rent are not eligible for cooling assistance." + example: One person aged 62 in public housing with $18,000 of Social Security, natural gas heat included in the rent, + a separate cooling cost and a $1,800 electric bill receives $365 in 2026 under the manual and plan, and $0 under + 63(B)(1) and 20(B)(3)(a). + pe_us: + follows: conflicting-source + code: + - policyengine_us/variables/gov/states/va/dss/eap/cooling/va_eap_cooling_eligible.py + prs: + - https://github.com/PolicyEngine/policyengine-us/pull/10760 + state: ruled + note: 'Ruled 2026-11-13 by the project lead; the ruling record is https://github.com/PolicyEngine/policyengine-us/pull/10760#issuecomment-6863979262. Follow manual J.3.a and plan 3.3, + the current filing (22VAC40-680-63 dates from 2003): PE-US excludes a subsidized household only when its cooling is + in the rent, and va_eap_cooling_eligible.yaml Case 14 pins the reading.' - id: us-va:snap-child-support-exclusion program: snap years: