diff --git a/changelog.d/de-liheap-cooling.added.md b/changelog.d/de-liheap-cooling.added.md new file mode 100644 index 00000000000..2c4bbf755c9 --- /dev/null +++ b/changelog.d/de-liheap-cooling.added.md @@ -0,0 +1 @@ +Add Delaware LIHEAP summer cooling electric benefit eligibility. diff --git a/policyengine_us/parameters/gov/states/de/dhss/liheap/cooling/child_age_limit.yaml b/policyengine_us/parameters/gov/states/de/dhss/liheap/cooling/child_age_limit.yaml new file mode 100644 index 00000000000..eb6982b3cc6 --- /dev/null +++ b/policyengine_us/parameters/gov/states/de/dhss/liheap/cooling/child_age_limit.yaml @@ -0,0 +1,13 @@ +description: Delaware treats children younger than this age as vulnerable household members for the summer cooling electric benefit under the Low Income Home Energy Assistance Program. +# The plans target "children five and under", that is, children younger than 6. +values: + 2025-10-01: 6 +metadata: + unit: year + period: year + label: Delaware LIHEAP cooling vulnerable child age limit + reference: + - title: Delaware FY2026 LIHEAP State Plan, section 3.3 ("children five and under") + href: https://liheapch.acf.gov/docs/2026/state-plans/DE_Plan_2026.pdf#page=12 + - title: Delaware FY2027 LIHEAP State Plan, section 3.3 ("children five and under") + href: https://liheapch.acf.gov/docs/2027/state-plans/DE_Plan_2027.pdf#page=11 diff --git a/policyengine_us/parameters/gov/states/de/dhss/liheap/cooling/elderly_age.yaml b/policyengine_us/parameters/gov/states/de/dhss/liheap/cooling/elderly_age.yaml new file mode 100644 index 00000000000..237f6c2149b --- /dev/null +++ b/policyengine_us/parameters/gov/states/de/dhss/liheap/cooling/elderly_age.yaml @@ -0,0 +1,12 @@ +description: Delaware treats household members at or above this age as vulnerable for the summer cooling electric benefit under the Low Income Home Energy Assistance Program. +values: + 2025-10-01: 60 +metadata: + unit: year + period: year + label: Delaware LIHEAP cooling elderly member age + reference: + - title: Delaware FY2026 LIHEAP State Plan, section 3.3 (members "sixty or older") + href: https://liheapch.acf.gov/docs/2026/state-plans/DE_Plan_2026.pdf#page=12 + - title: Delaware FY2027 LIHEAP State Plan, section 3.3 (members "sixty or older") + href: https://liheapch.acf.gov/docs/2027/state-plans/DE_Plan_2027.pdf#page=11 diff --git a/policyengine_us/programs.yaml b/policyengine_us/programs.yaml index 0f74596fd68..48f444c2401 100644 --- a/policyengine_us/programs.yaml +++ b/policyengine_us/programs.yaml @@ -1151,7 +1151,14 @@ programs: variable: de_liheap parameter_prefix: gov.states.de.dhss.liheap verified_years: "2026" - notes: FY2026 regular heating matrix and the subsidized-housing flat award. Crisis, cooling, weatherization and equipment assistance are out of scope. + notes: FY2026 regular heating matrix and the subsidized-housing flat award. Summer cooling eligibility is the separate Delaware LIHEAP cooling entry; crisis, weatherization and equipment assistance are out of scope. + - state: DE + status: partial + name: Delaware LIHEAP cooling + full_name: Delaware Summer Cooling Assistance Program electric benefit + variable: de_liheap_cooling_eligible + parameter_prefix: gov.states.de.dhss.liheap.cooling + notes: Eligibility only for the flat summer electric benefit, for LIHEAP households that buy their heating or pass the income test with a cooling cost, with a member 60 or older, under 6 or disabled; no amount is modeled because the state divides available funds equally. The State may extend it to every applicant (as HHS data show for FY2023-FY2024; FY2025 served 88 households) and no 2026 decision was found; the breathing-condition route, air conditioners, crisis and weatherization are out of scope. - state: MA status: complete name: Massachusetts LIHEAP diff --git a/policyengine_us/tests/policy/baseline/gov/states/de/dhss/liheap/cooling/de_liheap_cooling_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/de/dhss/liheap/cooling/de_liheap_cooling_eligible.yaml new file mode 100644 index 00000000000..a42142cf555 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/de/dhss/liheap/cooling/de_liheap_cooling_eligible.yaml @@ -0,0 +1,293 @@ +# Delaware Summer Cooling Assistance Program electric benefit eligibility +# (FY2026 plan sections 3.3-3.5; FY2027 plan sections 3.3-3.5; DHSS Utility +# Assistance page; historical manual 303 and the SCAP chart on page 100): a +# household that buys its heating (de_liheap_eligible), or one that meets the +# LIHEAP household and income test (de_liheap_income_eligible, without the +# heating responsibility test of regular heating) and has a cooling cost, with +# a member aged 60 or older, a child five or under, or a disabled member. +# heating_type must be reported: UNSPECIFIED does not qualify. No amount is +# modeled. +# FY2026 one-person LIHEAP limit 39,342 (60% of state median income). + +- name: Case 1, a retiree with gas heat and a cooling cost is eligible. + period: 2026 + input: + people: + person1: + age: 67 + social_security_retirement: 18_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 900 + has_cooling_expense: true + households: + household: + members: [person1] + state_code: DE + output: + # Countable income at most 18,000 <= 39,342; gas heating bill; aged 67. + de_liheap_eligible: true + de_liheap_cooling_eligible: true + +- name: Case 2, a worker aged 63 with income over the LIHEAP limit is ineligible. + period: 2026 + input: + people: + person1: + age: 63 + employment_income_before_lsr: 65_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 900 + has_cooling_expense: true + households: + household: + members: [person1] + state_code: DE + output: + # 65,000 less estimated withholding stays well above 39,342. + de_liheap_income_eligible: false + de_liheap_cooling_eligible: false + +- name: Case 3, a LIHEAP-eligible member aged 60 qualifies. + period: 2026 + input: + people: + person1: + age: 60 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + de_liheap_income_eligible: true + has_cooling_expense: true + households: + household: + members: [person1] + state_code: DE + output: + de_liheap_cooling_eligible: true + +- name: Case 4, a LIHEAP-eligible member aged 59 does not qualify. + period: 2026 + input: + people: + person1: + age: 59 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + de_liheap_income_eligible: true + has_cooling_expense: true + households: + household: + members: [person1] + state_code: DE + output: + de_liheap_cooling_eligible: false + +- name: Case 5, a LIHEAP-eligible parent with a five-year-old child qualifies. + period: 2026 + input: + people: + person1: + age: 32 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + heating_type: NATURAL_GAS + de_liheap_income_eligible: true + has_cooling_expense: true + households: + household: + members: [person1, person2] + state_code: DE + output: + de_liheap_cooling_eligible: true + +- name: Case 6, a LIHEAP-eligible parent with a six-year-old child does not qualify. + period: 2026 + input: + people: + person1: + age: 32 + person2: + age: 6 + spm_units: + spm_unit: + members: [person1, person2] + heating_type: NATURAL_GAS + de_liheap_income_eligible: true + has_cooling_expense: true + households: + household: + members: [person1, person2] + state_code: DE + output: + de_liheap_cooling_eligible: false + +- name: Case 7, a LIHEAP-eligible disabled adult qualifies. + period: 2026 + input: + people: + person1: + age: 40 + is_disabled: true + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + de_liheap_income_eligible: true + has_cooling_expense: true + households: + household: + members: [person1] + state_code: DE + output: + de_liheap_cooling_eligible: true + +- name: Case 8, a household without a separate cooling cost does not qualify. + period: 2026 + input: + people: + person1: + age: 67 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + de_liheap_income_eligible: true + has_cooling_expense: false + households: + household: + members: [person1] + state_code: DE + output: + # No gas bill, so the household does not buy its heating, and it reports no + # cooling cost. + de_liheap_cooling_eligible: false + +- name: Case 9, a retiree with no heating who pays for cooling qualifies. + period: 2026 + input: + people: + person1: + age: 67 + social_security_retirement: 18_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NONE + has_cooling_expense: true + households: + household: + members: [person1] + state_code: DE + output: + # No heating bill, so no regular heating assistance. + de_liheap_eligible: false + # Was false, now true: the SCAP chart's LIHEAP eligibility is "Purchase + # Source of Heating or Cooling", and this household pays for cooling. + de_liheap_cooling_eligible: true + +- name: Case 10, a retiree with heat in rent and an unspecified heating type does not qualify. + period: 2026 + input: + people: + person1: + age: 67 + social_security_retirement: 18_000 + spm_units: + spm_unit: + members: [person1] + heating_type: UNSPECIFIED + heat_expense_included_in_rent: true + has_cooling_expense: true + households: + household: + members: [person1] + state_code: DE + output: + # Unsubsidized heat in rent passes de_liheap_eligible with an unknown + # building fuel. heating_type is a required input in PolicyEngine (a + # convention, not a Delaware rule), so an unspecified type does not qualify. + de_liheap_eligible: true + de_liheap_cooling_eligible: false + +- name: Case 11, the FY2027 rules keep a retiree with gas heat eligible. + period: 2027 + input: + people: + person1: + age: 67 + social_security_retirement: 18_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 900 + has_cooling_expense: true + households: + household: + members: [person1] + state_code: DE + output: + de_liheap_cooling_eligible: true + +- name: Case 12, a public-housing tenant with heat in the rent who pays for cooling qualifies. + period: 2026 + input: + people: + person1: + age: 70 + social_security_retirement: 14_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_200 + households: + household: + members: [person1] + state_code: DE + is_in_public_housing: true + output: + # Subsidized heat in the rent is not regular heating responsibility. + de_liheap_eligible: false + # Plan 3.3 sets no cooling policy for subsidized renters, and the SCAP chart + # asks for a purchased source of heating or cooling. + de_liheap_cooling_eligible: true + +- name: Case 13, a retiree with gas heat and no reported cooling cost qualifies. + period: 2026 + input: + people: + person1: + age: 67 + social_security_retirement: 18_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 900 + has_cooling_expense: false + households: + household: + members: [person1] + state_code: DE + output: + # Countable income at most 18,000 <= 39,342 and a gas heating bill: the + # household buys its heating, which meets the SCAP chart's "Purchase Source + # of Heating or Cooling", and manual 303.2 A processes its SCAP application + # automatically. Aged 67. + de_liheap_eligible: true + de_liheap_cooling_eligible: true diff --git a/policyengine_us/variables/gov/states/de/dhss/liheap/cooling/de_liheap_cooling_eligible.py b/policyengine_us/variables/gov/states/de/dhss/liheap/cooling/de_liheap_cooling_eligible.py new file mode 100644 index 00000000000..29770140192 --- /dev/null +++ b/policyengine_us/variables/gov/states/de/dhss/liheap/cooling/de_liheap_cooling_eligible.py @@ -0,0 +1,68 @@ +from policyengine_us.model_api import * + + +class de_liheap_cooling_eligible(Variable): + value_type = bool + entity = SPMUnit + definition_period = YEAR + label = "Eligible for the Delaware LIHEAP summer cooling electric benefit" + defined_for = StateCode.DE + reference = ( + # PDF pages 12-13 + "https://liheapch.acf.gov/docs/2026/state-plans/DE_Plan_2026.pdf#page=12", + # PDF pages 11-12 + "https://liheapch.acf.gov/docs/2027/state-plans/DE_Plan_2027.pdf#page=11", + "https://dhss.delaware.gov/dss/division-of-social-services/utility-assistance/", + # Historical manual sections 303.1-303.2 and 415 and the SCAP eligibility + # chart. + # PDF pages 21-22, 32, 100 + "https://bidcondocs.delaware.gov/HSS/HSS_15027Liheap_MAN.pdf#page=21", + "https://liheappm.acf.gov/sites/default/files/private/congress/profiles/2023/FY2023DelawareProfile-508Compliant.pdf", + "https://liheappm.acf.gov/sites/default/files/private/congress/profiles/2024/FY2024_Delaware_Profile.pdf", + "https://liheappm.acf.gov/sites/default/files/private/congress/profiles/2025/FY%202025%20Delaware%20Profile.pdf", + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.de.dhss.liheap.cooling + # Plan 3.5: the benefit "is distributed only to the LIHEAP eligible + # households"; DHSS: "Eligibility requires prior application for + # LIHEAP during the program year". The SCAP chart (manual page 100) + # defines LIHEAP eligibility as "Purchase Source of Heating or Cooling", + # and plan 3.3 sets no cooling policy for subsidized renters or renters + # with utilities in the rent. Manual section 415 asks for a heating bill + # for "cooling electric"; the plan and the chart are followed. So a + # household that buys its heating qualifies, and so does one that meets + # the household and income test, without the heating responsibility + # test, and pays for cooling. + income_eligible = spm_unit("de_liheap_income_eligible", period) + # PolicyEngine convention, not a Delaware rule: heating_type is a + # required input, so an unspecified type is ineligible. + heating_type = spm_unit("heating_type", period) + heating_type_reported = heating_type != heating_type.possible_values.UNSPECIFIED + # Plan 3.3-3.4: targeted to members "sixty or older, disabled, + # children five and under", and members with chronic breathing + # conditions, which have no input. The plans let the State extend the + # benefit to every LIHEAP applicant when funds allow. HHS profiles count + # more cooling households than households with a targeted member in + # FY2023 and FY2024, and 88 cooling households in FY2025. No decision + # for 2026 was found, so the targeted rule applies. + person = spm_unit.members + age = person("age", period) + vulnerable = ( + (age >= p.elderly_age) + | (age < p.child_age_limit) + | person("is_disabled", period) + ) + has_vulnerable_member = spm_unit.any(vulnerable) + # Manual 303.2 A: "If applicant has a current FAP application, the SCAP + # application is automatically processed". + purchases_heating = spm_unit("de_liheap_eligible", period) + # Modeling reading, with no Delaware text: the cooling cost stands for + # the purchased source of cooling of a household that does not buy its + # heating. Every household is assumed to hold an active electric account. + has_cooling_expense = spm_unit("has_cooling_expense", period) + return ( + heating_type_reported + & has_vulnerable_member + & (purchases_heating | (income_eligible & has_cooling_expense)) + ) diff --git a/policyengine_us/variables/gov/states/de/dhss/liheap/eligibility/de_liheap_eligible.py b/policyengine_us/variables/gov/states/de/dhss/liheap/eligibility/de_liheap_eligible.py index 2f693554512..eb93c09c52b 100644 --- a/policyengine_us/variables/gov/states/de/dhss/liheap/eligibility/de_liheap_eligible.py +++ b/policyengine_us/variables/gov/states/de/dhss/liheap/eligibility/de_liheap_eligible.py @@ -1,5 +1,4 @@ from policyengine_us.model_api import * -from policyengine_us.variables.gov.hhs.tax_unit_fpg import fpg class de_liheap_eligible(Variable): @@ -16,18 +15,6 @@ class de_liheap_eligible(Variable): ) def formula(spm_unit, period, parameters): - p = parameters(period) - size = spm_unit("de_liheap_household_size", period) - income = spm_unit("de_liheap_countable_income", period) - limit = spm_unit("de_liheap_income_limit", period) - guideline = fpg( - max_(size, 1), - spm_unit.household("state_group_str", period), - period, - parameters, - year_lag=p.gov.states.de.dhss.liheap.eligibility.fpg_year_lag, - ) - federal_floor = np.round(guideline * p.gov.hhs.liheap.fpg_floor, 2) heat_in_rent = spm_unit("heat_expense_included_in_rent", period) subsidized = spm_unit( "receives_housing_assistance", period @@ -49,8 +36,4 @@ def formula(spm_unit, period, parameters): # SPMUnit approximates the energy-sharing household. Application, # funding, boarder/absence exceptions and duplicate claims are not # represented by existing inputs; they are not automatic exclusions. - return ( - (size > 0) - & ((income <= limit) | (income < federal_floor)) - & heating_responsibility - ) + return spm_unit("de_liheap_income_eligible", period) & heating_responsibility diff --git a/policyengine_us/variables/gov/states/de/dhss/liheap/eligibility/de_liheap_income_eligible.py b/policyengine_us/variables/gov/states/de/dhss/liheap/eligibility/de_liheap_income_eligible.py new file mode 100644 index 00000000000..eea1a24b476 --- /dev/null +++ b/policyengine_us/variables/gov/states/de/dhss/liheap/eligibility/de_liheap_income_eligible.py @@ -0,0 +1,29 @@ +from policyengine_us.model_api import * +from policyengine_us.variables.gov.hhs.tax_unit_fpg import fpg + + +class de_liheap_income_eligible(Variable): + value_type = bool + entity = SPMUnit + definition_period = YEAR + label = "Meets the Delaware LIHEAP household and income test" + defined_for = StateCode.DE + reference = ( + "https://www.law.cornell.edu/uscode/text/42/8624#b_2_B", + "https://liheapch.acf.gov/docs/2026/state-plans/DE_Plan_2026.pdf#page=9", + ) + + def formula(spm_unit, period, parameters): + p = parameters(period) + size = spm_unit("de_liheap_household_size", period) + income = spm_unit("de_liheap_countable_income", period) + limit = spm_unit("de_liheap_income_limit", period) + guideline = fpg( + max_(size, 1), + spm_unit.household("state_group_str", period), + period, + parameters, + year_lag=p.gov.states.de.dhss.liheap.eligibility.fpg_year_lag, + ) + federal_floor = np.round(guideline * p.gov.hhs.liheap.fpg_floor, 2) + return (size > 0) & ((income <= limit) | (income < federal_floor)) diff --git a/source_conflicts/candidates.yaml b/source_conflicts/candidates.yaml index 4e687a33ca4..fe69d6a712b 100644 --- a/source_conflicts/candidates.yaml +++ b/source_conflicts/candidates.yaml @@ -2387,6 +2387,45 @@ candidates: on joint returns (de_elderly_or_disabled_income_exclusion_joint.py) and on other returns (de_elderly_or_disabled_income_exclusion_eligible_person.py). The statute-first rule requires replacing age-60 eligibility if the literal boundary is confirmed; verify individual-return scope and intervening editions.' +- id: us-de:liheap-cooling-heating-bill + program: liheap + years: + from: 2026 + to: 2027 + type: federal-fiscal + question: Does the Delaware Summer Cooling Assistance electric benefit need a purchased source of heating or cooling, + as the manual's SCAP chart provides (plan item 3.3 sets no different cooling policy for renters), or responsibility + for a heating bill, as manual section 415 provides? + sources: + - kind: manual + citation: DEAP Policies and Procedures Manual, SCAP eligibility chart (final, 2/24/2015), PDF page 100 + url: https://bidcondocs.delaware.gov/HSS/HSS_15027Liheap_MAN.pdf#page=100 + - kind: plan + citation: Delaware FY2026 LIHEAP State Plan, item 3.3, PDF page 12 + url: https://liheapch.acf.gov/docs/2026/state-plans/DE_Plan_2026.pdf#page=12 + - kind: plan + citation: Delaware FY2027 LIHEAP State Plan, item 3.3, PDF page 11 + url: https://liheapch.acf.gov/docs/2027/state-plans/DE_Plan_2027.pdf#page=11 + - kind: manual + citation: DEAP Policies and Procedures Manual, section 415, PDF page 32 + url: https://bidcondocs.delaware.gov/HSS/HSS_15027Liheap_MAN.pdf#page=32 + readings: + statute: No statute is supplied; the SCAP chart's LIHEAP eligibility is "Purchase Source of Heating or Cooling", and + plan 3.3 sets no different cooling policy for subsidized renters or renters with utilities in the rent. + other: Section 415 says "applicants must be responsible for paying a heating bill in order to receive assistance for + heating, crisis and cooling electric". + example: One person aged 70 in public housing with $14,000 of Social Security, heat in the rent and a cooling cost is + eligible under the chart and the plan, and ineligible under section 415. + pe_us: + follows: gap-fill + code: + - policyengine_us/variables/gov/states/de/dhss/liheap/cooling/de_liheap_cooling_eligible.py + prs: + - https://github.com/PolicyEngine/policyengine-us/pull/10762 + state: ruled + note: 'Ruled 2026-11-12 by the project lead; the ruling record is https://github.com/PolicyEngine/policyengine-us/pull/10762#issuecomment-6837369871. Follow the plan and the SCAP chart. + us-de:liheap-plan-income-checklist follows the manual over the plan''s checklist; here the manual itself is split + between section 415 and its own chart, and the plan sides with the chart.' - id: us-de:liheap-income-floor-vs-smi-limit program: liheap years: @@ -2410,13 +2449,14 @@ candidates: pe_us: follows: statute code: - - policyengine_us/variables/gov/states/de/dhss/liheap/eligibility/de_liheap_eligible.py + - policyengine_us/variables/gov/states/de/dhss/liheap/eligibility/de_liheap_income_eligible.py - policyengine_us/parameters/gov/hhs/liheap/fpg_floor.yaml - policyengine_us/parameters/gov/states/de/dhss/liheap/eligibility/fpg_year_lag.yaml prs: - https://github.com/PolicyEngine/policyengine-us/pull/10612 + - https://github.com/PolicyEngine/policyengine-us/pull/10762 state: unreviewed - note: PE-US applies the floor, rounded to cents with the statute's strict "less than" (de_liheap_eligible.py). + note: PE-US applies the floor, rounded to cents with the statute's strict "less than" (de_liheap_income_eligible.py). - id: us-de:liheap-plan-income-checklist program: liheap years: