From 530f2a33564ad683a23aa7f04226556470447582 Mon Sep 17 00:00:00 2001 From: Ziming Date: Fri, 23 Oct 2026 18:11:10 -0400 Subject: [PATCH 1/2] Add Minnesota EAP Primary Heat benefit Co-Authored-By: Claude Opus 5.5 --- changelog.d/mn-liheap-wave1d.added.md | 1 + .../eap/eligibility/fpg_year_lag.yaml | 20 ++ .../mn/commerce/eap/eligibility/smi_rate.yaml | 16 + .../mn/commerce/eap/income/gift_minimum.yaml | 12 + .../eap/income/investment_minimum.yaml | 12 + .../income/qualified_eligibility_sources.yaml | 18 ++ .../commerce/eap/income/retirement_age.yaml | 12 + .../commerce/eap/income/sources/earned.yaml | 23 ++ .../eap/income/sources/investment.yaml | 15 + .../commerce/eap/income/sources/unearned.yaml | 30 ++ .../eap/income/student_age_limit.yaml | 12 + .../payment/backup_cost/district_heating.yaml | 41 +++ .../eap/payment/backup_cost/electricity.yaml | 40 +++ .../payment/backup_cost/metered_propane.yaml | 41 +++ .../eap/payment/backup_cost/natural_gas.yaml | 40 +++ .../commerce/eap/payment/backup_cost/oil.yaml | 41 +++ .../eap/payment/backup_cost/propane.yaml | 40 +++ .../eap/payment/backup_cost/steam.yaml | 41 +++ .../eap/payment/energy_cost_sources.yaml | 22 ++ .../mn/commerce/eap/payment/maximum.yaml | 18 ++ .../mn/commerce/eap/payment/minimum.yaml | 18 ++ .../commerce/eap/payment/share/maximum.yaml | 17 ++ .../commerce/eap/payment/share/minimum.yaml | 17 ++ .../commerce/eap/payment/share/slope_end.yaml | 17 ++ .../eap/payment/share/slope_start.yaml | 17 ++ policyengine_us/programs.yaml | 10 +- .../eap/eligibility/mn_eap_eligible.yaml | 188 ++++++++++++ .../eap/eligibility/mn_eap_income_limit.yaml | 146 +++++++++ .../eap/income/mn_eap_countable_income.yaml | 286 ++++++++++++++++++ .../gov/states/mn/commerce/eap/mn_eap.yaml | 245 +++++++++++++++ .../commerce/eap/mn_eap_household_size.yaml | 27 ++ .../eap/payment/mn_eap_energy_cost.yaml | 176 +++++++++++ .../eap/payment/mn_eap_pay_share.yaml | 156 ++++++++++ .../eap/eligibility/mn_eap_eligible.py | 45 +++ .../eap/eligibility/mn_eap_income_limit.py | 42 +++ .../eap/income/mn_eap_countable_income.py | 77 +++++ .../gov/states/mn/commerce/eap/mn_eap.py | 39 +++ .../mn/commerce/eap/mn_eap_household_size.py | 21 ++ .../eap/payment/mn_eap_energy_cost.py | 59 ++++ .../eap/payment/mn_eap_housing_type.py | 34 +++ .../commerce/eap/payment/mn_eap_pay_share.py | 44 +++ .../income/person/general/pfml_benefits.py | 1 - 42 files changed, 2175 insertions(+), 2 deletions(-) create mode 100644 changelog.d/mn-liheap-wave1d.added.md create mode 100644 policyengine_us/parameters/gov/states/mn/commerce/eap/eligibility/fpg_year_lag.yaml create mode 100644 policyengine_us/parameters/gov/states/mn/commerce/eap/eligibility/smi_rate.yaml create mode 100644 policyengine_us/parameters/gov/states/mn/commerce/eap/income/gift_minimum.yaml create mode 100644 policyengine_us/parameters/gov/states/mn/commerce/eap/income/investment_minimum.yaml create mode 100644 policyengine_us/parameters/gov/states/mn/commerce/eap/income/qualified_eligibility_sources.yaml create mode 100644 policyengine_us/parameters/gov/states/mn/commerce/eap/income/retirement_age.yaml create mode 100644 policyengine_us/parameters/gov/states/mn/commerce/eap/income/sources/earned.yaml create mode 100644 policyengine_us/parameters/gov/states/mn/commerce/eap/income/sources/investment.yaml create mode 100644 policyengine_us/parameters/gov/states/mn/commerce/eap/income/sources/unearned.yaml create mode 100644 policyengine_us/parameters/gov/states/mn/commerce/eap/income/student_age_limit.yaml create mode 100644 policyengine_us/parameters/gov/states/mn/commerce/eap/payment/backup_cost/district_heating.yaml create mode 100644 policyengine_us/parameters/gov/states/mn/commerce/eap/payment/backup_cost/electricity.yaml create mode 100644 policyengine_us/parameters/gov/states/mn/commerce/eap/payment/backup_cost/metered_propane.yaml create mode 100644 policyengine_us/parameters/gov/states/mn/commerce/eap/payment/backup_cost/natural_gas.yaml create mode 100644 policyengine_us/parameters/gov/states/mn/commerce/eap/payment/backup_cost/oil.yaml create mode 100644 policyengine_us/parameters/gov/states/mn/commerce/eap/payment/backup_cost/propane.yaml create mode 100644 policyengine_us/parameters/gov/states/mn/commerce/eap/payment/backup_cost/steam.yaml create mode 100644 policyengine_us/parameters/gov/states/mn/commerce/eap/payment/energy_cost_sources.yaml create mode 100644 policyengine_us/parameters/gov/states/mn/commerce/eap/payment/maximum.yaml create mode 100644 policyengine_us/parameters/gov/states/mn/commerce/eap/payment/minimum.yaml create mode 100644 policyengine_us/parameters/gov/states/mn/commerce/eap/payment/share/maximum.yaml create mode 100644 policyengine_us/parameters/gov/states/mn/commerce/eap/payment/share/minimum.yaml create mode 100644 policyengine_us/parameters/gov/states/mn/commerce/eap/payment/share/slope_end.yaml create mode 100644 policyengine_us/parameters/gov/states/mn/commerce/eap/payment/share/slope_start.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/mn/commerce/eap/eligibility/mn_eap_eligible.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/mn/commerce/eap/eligibility/mn_eap_income_limit.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/mn/commerce/eap/income/mn_eap_countable_income.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/mn/commerce/eap/mn_eap.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/mn/commerce/eap/mn_eap_household_size.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/mn/commerce/eap/payment/mn_eap_energy_cost.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/mn/commerce/eap/payment/mn_eap_pay_share.yaml create mode 100644 policyengine_us/variables/gov/states/mn/commerce/eap/eligibility/mn_eap_eligible.py create mode 100644 policyengine_us/variables/gov/states/mn/commerce/eap/eligibility/mn_eap_income_limit.py create mode 100644 policyengine_us/variables/gov/states/mn/commerce/eap/income/mn_eap_countable_income.py create mode 100644 policyengine_us/variables/gov/states/mn/commerce/eap/mn_eap.py create mode 100644 policyengine_us/variables/gov/states/mn/commerce/eap/mn_eap_household_size.py create mode 100644 policyengine_us/variables/gov/states/mn/commerce/eap/payment/mn_eap_energy_cost.py create mode 100644 policyengine_us/variables/gov/states/mn/commerce/eap/payment/mn_eap_housing_type.py create mode 100644 policyengine_us/variables/gov/states/mn/commerce/eap/payment/mn_eap_pay_share.py diff --git a/changelog.d/mn-liheap-wave1d.added.md b/changelog.d/mn-liheap-wave1d.added.md new file mode 100644 index 00000000000..d383cbd41ff --- /dev/null +++ b/changelog.d/mn-liheap-wave1d.added.md @@ -0,0 +1 @@ +Add Minnesota Energy Assistance Program Primary Heat benefit. diff --git a/policyengine_us/parameters/gov/states/mn/commerce/eap/eligibility/fpg_year_lag.yaml b/policyengine_us/parameters/gov/states/mn/commerce/eap/eligibility/fpg_year_lag.yaml new file mode 100644 index 00000000000..d007b06d1cc --- /dev/null +++ b/policyengine_us/parameters/gov/states/mn/commerce/eap/eligibility/fpg_year_lag.yaml @@ -0,0 +1,20 @@ +description: Minnesota uses the poverty guidelines from this many years before the model year for the federal income floor under the Energy Assistance Program. +# HHS makes each January's guidelines mandatory for LIHEAP from the next +# October 1. The FFY2026 table prints 110% of the 2025 guidelines for sizes 19 +# and 20 ($10,509 and $11,013 a month), and the FFY2027 table prints 110% of +# the 2026 guidelines ($10,835 and $11,355). +values: + 2025-10-01: 1 +metadata: + unit: year + period: year + label: Minnesota EAP poverty guideline year lag + reference: + - title: "Minnesota EAP Policy Manual FFY26, Chapter 3, 2026 Maximum EAP Income Guidelines #page 88-89" + href: https://mn.gov/commerce-stat/pdfs/ffy26-eap-policy-manual.pdf#page=88 + - title: Minnesota EAP Policy Manual FFY27, Chapter 3, 2027 Maximum EAP Income Guidelines + href: https://mn.gov/commerce-stat/pdfs/ffy27-eap-policy-manual.pdf#page=90 + - title: LIHEAP IM 2025-02, Attachment 2, poverty guidelines for mandatory use in FY26 + href: https://acf.gov/sites/default/files/documents/ocs/COMM_LIHEAP_IM2025-02_FPGSte-Table_Att2.pdf#page=1 + - title: LIHEAP IM 2026-01, poverty guidelines for optional use in FY26 and mandatory use in FY27 + href: https://acf.gov/ocs/policy-guidance/liheap-im2026-01-federal-poverty-guidelines-fpg-and-state-median-income-smi diff --git a/policyengine_us/parameters/gov/states/mn/commerce/eap/eligibility/smi_rate.yaml b/policyengine_us/parameters/gov/states/mn/commerce/eap/eligibility/smi_rate.yaml new file mode 100644 index 00000000000..cd1ed06fa04 --- /dev/null +++ b/policyengine_us/parameters/gov/states/mn/commerce/eap/eligibility/smi_rate.yaml @@ -0,0 +1,16 @@ +description: Minnesota limits Energy Assistance Program income to this share of state median income. +# The published tables apply this rate for household sizes 1 to 18. Larger +# households use 110% of the poverty guideline (gov.hhs.liheap.fpg_floor). +values: + 2025-10-01: 0.5 +metadata: + unit: /1 + period: year + label: Minnesota EAP state median income rate + reference: + - title: "Minnesota EAP Policy Manual FFY26, Chapter 3, 2026 Maximum EAP Income Guidelines #page 88-89" + href: https://mn.gov/commerce-stat/pdfs/ffy26-eap-policy-manual.pdf#page=88 + - title: Minnesota EAP Policy Manual FFY27, Chapter 3, 2027 Maximum EAP Income Guidelines + href: https://mn.gov/commerce-stat/pdfs/ffy27-eap-policy-manual.pdf#page=90 + - title: Minnesota FY2026 LIHEAP State Plan, section 2.1 + href: https://liheapch.acf.gov/docs/2026/state-plans/MN_Plan_2026.pdf#page=8 diff --git a/policyengine_us/parameters/gov/states/mn/commerce/eap/income/gift_minimum.yaml b/policyengine_us/parameters/gov/states/mn/commerce/eap/income/gift_minimum.yaml new file mode 100644 index 00000000000..55f4a3a9317 --- /dev/null +++ b/policyengine_us/parameters/gov/states/mn/commerce/eap/income/gift_minimum.yaml @@ -0,0 +1,12 @@ +description: Minnesota counts cash gifts when their monthly total reaches this amount under the Energy Assistance Program. +values: + 2025-10-01: 100 +metadata: + unit: currency-USD + period: month + label: Minnesota EAP cash gift minimum + reference: + - title: Minnesota EAP Policy Manual FFY26, Chapter 3, Gifts (cash) + href: https://mn.gov/commerce-stat/pdfs/ffy26-eap-policy-manual.pdf#page=92 + - title: Minnesota EAP Policy Manual FFY27, Chapter 3, Gifts (cash) + href: https://mn.gov/commerce-stat/pdfs/ffy27-eap-policy-manual.pdf#page=94 diff --git a/policyengine_us/parameters/gov/states/mn/commerce/eap/income/investment_minimum.yaml b/policyengine_us/parameters/gov/states/mn/commerce/eap/income/investment_minimum.yaml new file mode 100644 index 00000000000..d894345c675 --- /dev/null +++ b/policyengine_us/parameters/gov/states/mn/commerce/eap/income/investment_minimum.yaml @@ -0,0 +1,12 @@ +description: Minnesota counts dividend, interest and royalty income when its monthly amount reaches this level under the Energy Assistance Program. +values: + 2025-10-01: 50 +metadata: + unit: currency-USD + period: month + label: Minnesota EAP dividend and interest income minimum + reference: + - title: Minnesota EAP Policy Manual FFY26, Chapter 3, Dividends, Interest and Royalties + href: https://mn.gov/commerce-stat/pdfs/ffy26-eap-policy-manual.pdf#page=90 + - title: Minnesota EAP Policy Manual FFY27, Chapter 3, Dividends, Interest and Royalties + href: https://mn.gov/commerce-stat/pdfs/ffy27-eap-policy-manual.pdf#page=92 diff --git a/policyengine_us/parameters/gov/states/mn/commerce/eap/income/qualified_eligibility_sources.yaml b/policyengine_us/parameters/gov/states/mn/commerce/eap/income/qualified_eligibility_sources.yaml new file mode 100644 index 00000000000..07b2894899c --- /dev/null +++ b/policyengine_us/parameters/gov/states/mn/commerce/eap/income/qualified_eligibility_sources.yaml @@ -0,0 +1,18 @@ +description: Minnesota places households whose only income comes from these sources at the lowest income level under the Energy Assistance Program. +values: + 2025-10-01: + # MFIP is part of tanf. The Diversionary Work Program has no input. The + # lowest income level is read as an income percentile of zero for the pay + # share; the income limit still applies. + - tanf + - general_assistance + - ssi +metadata: + unit: list + period: year + label: Minnesota EAP qualified eligibility income sources + reference: + - title: Minnesota EAP Policy Manual FFY26, Chapter 3, Qualified Eligibility + href: https://mn.gov/commerce-stat/pdfs/ffy26-eap-policy-manual.pdf#page=102 + - title: Minnesota EAP Policy Manual FFY27, Chapter 3, Qualified Eligibility + href: https://mn.gov/commerce-stat/pdfs/ffy27-eap-policy-manual.pdf#page=103 diff --git a/policyengine_us/parameters/gov/states/mn/commerce/eap/income/retirement_age.yaml b/policyengine_us/parameters/gov/states/mn/commerce/eap/income/retirement_age.yaml new file mode 100644 index 00000000000..8695ce57795 --- /dev/null +++ b/policyengine_us/parameters/gov/states/mn/commerce/eap/income/retirement_age.yaml @@ -0,0 +1,12 @@ +description: Minnesota counts retirement account withdrawals from this age under the Energy Assistance Program. +values: + 2025-10-01: 59.5 +metadata: + unit: year + period: year + label: Minnesota EAP retirement withdrawal age + reference: + - title: "Minnesota EAP Policy Manual FFY26, Chapter 3, Retirement Income and Pension Documentation #page 96,111" + href: https://mn.gov/commerce-stat/pdfs/ffy26-eap-policy-manual.pdf#page=96 + - title: "Minnesota EAP Policy Manual FFY27, Chapter 3, Retirement Income and Pension Documentation #page 98,113" + href: https://mn.gov/commerce-stat/pdfs/ffy27-eap-policy-manual.pdf#page=98 diff --git a/policyengine_us/parameters/gov/states/mn/commerce/eap/income/sources/earned.yaml b/policyengine_us/parameters/gov/states/mn/commerce/eap/income/sources/earned.yaml new file mode 100644 index 00000000000..f7d33a97259 --- /dev/null +++ b/policyengine_us/parameters/gov/states/mn/commerce/eap/income/sources/earned.yaml @@ -0,0 +1,23 @@ +description: Minnesota counts these sources as earned income under the Energy Assistance Program. +values: + 2025-10-01: + - employment_income + # Business, rental, partnership and S corporation, and farm income count as + # self-employment (Form 1040 Schedule 1 lines 3, 5 and 6). Each source is + # floored at zero per person, so a loss in one source does not offset + # another. The 50% gross-receipts method has no input. + - self_employment_income + - sstb_self_employment_income + - partnership_s_corp_income + - farm_operations_income + - farm_rent_income + - rental_income +metadata: + unit: list + period: year + label: Minnesota EAP earned income sources + reference: + - title: "Minnesota EAP Policy Manual FFY26, Chapter 3, Income Inclusions and Exclusions and Self-Employment Income #page 89,91,96,107-108" + href: https://mn.gov/commerce-stat/pdfs/ffy26-eap-policy-manual.pdf#page=89 + - title: "Minnesota EAP Policy Manual FFY27, Chapter 3, Income Inclusions and Exclusions and Self-Employment Income #page 91-92,98,109-110" + href: https://mn.gov/commerce-stat/pdfs/ffy27-eap-policy-manual.pdf#page=91 diff --git a/policyengine_us/parameters/gov/states/mn/commerce/eap/income/sources/investment.yaml b/policyengine_us/parameters/gov/states/mn/commerce/eap/income/sources/investment.yaml new file mode 100644 index 00000000000..9d4f15f978f --- /dev/null +++ b/policyengine_us/parameters/gov/states/mn/commerce/eap/income/sources/investment.yaml @@ -0,0 +1,15 @@ +description: Minnesota counts these sources as dividend and interest income under the Energy Assistance Program. +values: + 2025-10-01: + - interest_income + # Only ordinary dividends (Form 1040 line 3b) count. + - ordinary_dividend_income +metadata: + unit: list + period: year + label: Minnesota EAP dividend and interest income sources + reference: + - title: Minnesota EAP Policy Manual FFY26, Chapter 3, Dividends, Interest and Royalties + href: https://mn.gov/commerce-stat/pdfs/ffy26-eap-policy-manual.pdf#page=90 + - title: Minnesota EAP Policy Manual FFY27, Chapter 3, Dividends, Interest and Royalties + href: https://mn.gov/commerce-stat/pdfs/ffy27-eap-policy-manual.pdf#page=92 diff --git a/policyengine_us/parameters/gov/states/mn/commerce/eap/income/sources/unearned.yaml b/policyengine_us/parameters/gov/states/mn/commerce/eap/income/sources/unearned.yaml new file mode 100644 index 00000000000..3e8c229db90 --- /dev/null +++ b/policyengine_us/parameters/gov/states/mn/commerce/eap/income/sources/unearned.yaml @@ -0,0 +1,30 @@ +description: Minnesota counts these sources as unearned income under the Energy Assistance Program. +values: + 2025-10-01: + # The formula counts Social Security and pensions net of the Medicare Part B + # premium, unemployment compensation with the student exclusion, retirement + # account distributions from age 59 1/2, and MFIP and other TANF cash + # through the SPM unit tanf variable. + - ssi + - general_assistance + - military_retirement_income + - railroad_benefits + - veterans_benefits + - workers_compensation + - disability_benefits + # Minnesota Paid Leave, wage replacement cash paid from 2026-01-01. + - pfml_benefits + - alimony_income + - strike_benefits + # Trust disbursements. + - estate_income + - survivor_benefits +metadata: + unit: list + period: year + label: Minnesota EAP unearned income sources + reference: + - title: "Minnesota EAP Policy Manual FFY26, Chapter 3, Income Definition and Determination and Income Inclusions and Exclusions #page 88-89,91,96-99" + href: https://mn.gov/commerce-stat/pdfs/ffy26-eap-policy-manual.pdf#page=88 + - title: "Minnesota EAP Policy Manual FFY27, Policy Manual Changes and Chapter 3, Income Inclusions and Exclusions and Minnesota Paid Leave #page 11-12,91-92,96,98,100,116" + href: https://mn.gov/commerce-stat/pdfs/ffy27-eap-policy-manual.pdf#page=11 diff --git a/policyengine_us/parameters/gov/states/mn/commerce/eap/income/student_age_limit.yaml b/policyengine_us/parameters/gov/states/mn/commerce/eap/income/student_age_limit.yaml new file mode 100644 index 00000000000..66705d421ee --- /dev/null +++ b/policyengine_us/parameters/gov/states/mn/commerce/eap/income/student_age_limit.yaml @@ -0,0 +1,12 @@ +description: Minnesota excludes the earnings and unemployment insurance of kindergarten through grade 12 students up to this age under the Energy Assistance Program. +values: + 2025-10-01: 19 +metadata: + unit: year + period: year + label: Minnesota EAP student income exclusion age limit + reference: + - title: "Minnesota EAP Policy Manual FFY26, Chapter 3, Income Inclusions and Exclusions #page 91,99" + href: https://mn.gov/commerce-stat/pdfs/ffy26-eap-policy-manual.pdf#page=91 + - title: "Minnesota EAP Policy Manual FFY27, Chapter 3, Income Inclusions and Exclusions #page 93,100" + href: https://mn.gov/commerce-stat/pdfs/ffy27-eap-policy-manual.pdf#page=93 diff --git a/policyengine_us/parameters/gov/states/mn/commerce/eap/payment/backup_cost/district_heating.yaml b/policyengine_us/parameters/gov/states/mn/commerce/eap/payment/backup_cost/district_heating.yaml new file mode 100644 index 00000000000..68581bfb54a --- /dev/null +++ b/policyengine_us/parameters/gov/states/mn/commerce/eap/payment/backup_cost/district_heating.yaml @@ -0,0 +1,41 @@ +description: Minnesota uses this average annual energy cost for district heating by housing type under the Energy Assistance Program. +# No heating_type value selects this row. +APARTMENT: + 2025-10-01: 2_072 + 2026-10-01: 2_241 +DUPLEX: + 2025-10-01: 2_361 + 2026-10-01: 2_554 +TRIPLEX: + 2025-10-01: 2_228 + 2026-10-01: 2_409 +FOURPLEX: + 2025-10-01: 2_205 + 2026-10-01: 2_385 +TOWNHOUSE: + 2025-10-01: 2_228 + 2026-10-01: 2_409 +HOUSE: + 2025-10-01: 2_450 + 2026-10-01: 2_650 +MOBILE_HOME: + 2025-10-01: 2_450 + 2026-10-01: 2_650 +OTHER: + 2025-10-01: 2_228 + 2026-10-01: 2_409 +metadata: + unit: currency-USD + period: year + breakdown: + - mn_eap_housing_type + label: Minnesota EAP district heating backup matrix energy cost + reference: + - title: Minnesota EAP Policy Manual FFY26 Appendix 4A Primary Heat Benefit Calculator, Backup Matrix Values!A42:C49 + href: https://liheapch.acf.gov/docs/2026/benefits-matricies/MN_BenefitMatrix_2026.xlsx + - title: Minnesota EAP Policy Manual FFY27 Appendix 4A Primary Heat Benefit Calculator, Backup Matrix Values!A42:C49 + href: https://mn.gov/commerce-stat/xls/phb-calculator.xlsx + - title: "Minnesota EAP Policy Manual FFY26, Chapter 4, Backup Matrix and Knowing Which Method to Use #page 125-126" + href: https://mn.gov/commerce-stat/pdfs/ffy26-eap-policy-manual.pdf#page=125 + - title: "Minnesota EAP Policy Manual FFY27, Chapter 4, Backup Matrix and Knowing Which Method to Use #page 127-128" + href: https://mn.gov/commerce-stat/pdfs/ffy27-eap-policy-manual.pdf#page=127 diff --git a/policyengine_us/parameters/gov/states/mn/commerce/eap/payment/backup_cost/electricity.yaml b/policyengine_us/parameters/gov/states/mn/commerce/eap/payment/backup_cost/electricity.yaml new file mode 100644 index 00000000000..920b4c85e14 --- /dev/null +++ b/policyengine_us/parameters/gov/states/mn/commerce/eap/payment/backup_cost/electricity.yaml @@ -0,0 +1,40 @@ +description: Minnesota uses this average annual energy cost for electric heat by housing type under the Energy Assistance Program. +APARTMENT: + 2025-10-01: 873 + 2026-10-01: 891 +DUPLEX: + 2025-10-01: 1_747 + 2026-10-01: 1_782 +TRIPLEX: + 2025-10-01: 1_373 + 2026-10-01: 1_400 +FOURPLEX: + 2025-10-01: 1_223 + 2026-10-01: 1_248 +TOWNHOUSE: + 2025-10-01: 1_547 + 2026-10-01: 1_579 +HOUSE: + 2025-10-01: 2_496 + 2026-10-01: 2_546 +MOBILE_HOME: + 2025-10-01: 2_496 + 2026-10-01: 2_546 +OTHER: + 2025-10-01: 1_697 + 2026-10-01: 1_731 +metadata: + unit: currency-USD + period: year + breakdown: + - mn_eap_housing_type + label: Minnesota EAP electricity backup matrix energy cost + reference: + - title: Minnesota EAP Policy Manual FFY26 Appendix 4A Primary Heat Benefit Calculator, Backup Matrix Values!A34:C41 + href: https://liheapch.acf.gov/docs/2026/benefits-matricies/MN_BenefitMatrix_2026.xlsx + - title: Minnesota EAP Policy Manual FFY27 Appendix 4A Primary Heat Benefit Calculator, Backup Matrix Values!A34:C41 + href: https://mn.gov/commerce-stat/xls/phb-calculator.xlsx + - title: "Minnesota EAP Policy Manual FFY26, Chapter 4, Backup Matrix and Knowing Which Method to Use #page 125-126" + href: https://mn.gov/commerce-stat/pdfs/ffy26-eap-policy-manual.pdf#page=125 + - title: "Minnesota EAP Policy Manual FFY27, Chapter 4, Backup Matrix and Knowing Which Method to Use #page 127-128" + href: https://mn.gov/commerce-stat/pdfs/ffy27-eap-policy-manual.pdf#page=127 diff --git a/policyengine_us/parameters/gov/states/mn/commerce/eap/payment/backup_cost/metered_propane.yaml b/policyengine_us/parameters/gov/states/mn/commerce/eap/payment/backup_cost/metered_propane.yaml new file mode 100644 index 00000000000..65c3c8dc2c0 --- /dev/null +++ b/policyengine_us/parameters/gov/states/mn/commerce/eap/payment/backup_cost/metered_propane.yaml @@ -0,0 +1,41 @@ +description: Minnesota uses this average annual energy cost for metered propane heat by housing type under the Energy Assistance Program. +# No heating_type value selects this row; propane heat uses propane.yaml. +APARTMENT: + 2025-10-01: 2_272 + 2026-10-01: 2_306 +DUPLEX: + 2025-10-01: 2_502 + 2026-10-01: 2_540 +TRIPLEX: + 2025-10-01: 2_272 + 2026-10-01: 2_306 +FOURPLEX: + 2025-10-01: 2_140 + 2026-10-01: 2_172 +TOWNHOUSE: + 2025-10-01: 2_041 + 2026-10-01: 2_072 +HOUSE: + 2025-10-01: 3_293 + 2026-10-01: 3_342 +MOBILE_HOME: + 2025-10-01: 3_293 + 2026-10-01: 3_342 +OTHER: + 2025-10-01: 2_469 + 2026-10-01: 2_506 +metadata: + unit: currency-USD + period: year + breakdown: + - mn_eap_housing_type + label: Minnesota EAP metered propane backup matrix energy cost + reference: + - title: Minnesota EAP Policy Manual FFY26 Appendix 4A Primary Heat Benefit Calculator, Backup Matrix Values!A50:C57 + href: https://liheapch.acf.gov/docs/2026/benefits-matricies/MN_BenefitMatrix_2026.xlsx + - title: Minnesota EAP Policy Manual FFY27 Appendix 4A Primary Heat Benefit Calculator, Backup Matrix Values!A50:C57 + href: https://mn.gov/commerce-stat/xls/phb-calculator.xlsx + - title: "Minnesota EAP Policy Manual FFY26, Chapter 4, Backup Matrix and Knowing Which Method to Use #page 125-126" + href: https://mn.gov/commerce-stat/pdfs/ffy26-eap-policy-manual.pdf#page=125 + - title: "Minnesota EAP Policy Manual FFY27, Chapter 4, Backup Matrix and Knowing Which Method to Use #page 127-128" + href: https://mn.gov/commerce-stat/pdfs/ffy27-eap-policy-manual.pdf#page=127 diff --git a/policyengine_us/parameters/gov/states/mn/commerce/eap/payment/backup_cost/natural_gas.yaml b/policyengine_us/parameters/gov/states/mn/commerce/eap/payment/backup_cost/natural_gas.yaml new file mode 100644 index 00000000000..790a2978259 --- /dev/null +++ b/policyengine_us/parameters/gov/states/mn/commerce/eap/payment/backup_cost/natural_gas.yaml @@ -0,0 +1,40 @@ +description: Minnesota uses this average annual energy cost for natural gas heat by housing type under the Energy Assistance Program. +APARTMENT: + 2025-10-01: 1_458 + 2026-10-01: 1_554 +DUPLEX: + 2025-10-01: 2_423 + 2026-10-01: 2_581 +TRIPLEX: + 2025-10-01: 2_225 + 2026-10-01: 2_370 +FOURPLEX: + 2025-10-01: 1_854 + 2026-10-01: 1_975 +TOWNHOUSE: + 2025-10-01: 1_780 + 2026-10-01: 1_896 +HOUSE: + 2025-10-01: 2_472 + 2026-10-01: 2_634 +MOBILE_HOME: + 2025-10-01: 2_472 + 2026-10-01: 2_634 +OTHER: + 2025-10-01: 1_805 + 2026-10-01: 1_923 +metadata: + unit: currency-USD + period: year + breakdown: + - mn_eap_housing_type + label: Minnesota EAP natural gas backup matrix energy cost + reference: + - title: Minnesota EAP Policy Manual FFY26 Appendix 4A Primary Heat Benefit Calculator, Backup Matrix Values!A26:C33 + href: https://liheapch.acf.gov/docs/2026/benefits-matricies/MN_BenefitMatrix_2026.xlsx + - title: Minnesota EAP Policy Manual FFY27 Appendix 4A Primary Heat Benefit Calculator, Backup Matrix Values!A26:C33 + href: https://mn.gov/commerce-stat/xls/phb-calculator.xlsx + - title: "Minnesota EAP Policy Manual FFY26, Chapter 4, Backup Matrix and Knowing Which Method to Use #page 125-126" + href: https://mn.gov/commerce-stat/pdfs/ffy26-eap-policy-manual.pdf#page=125 + - title: "Minnesota EAP Policy Manual FFY27, Chapter 4, Backup Matrix and Knowing Which Method to Use #page 127-128" + href: https://mn.gov/commerce-stat/pdfs/ffy27-eap-policy-manual.pdf#page=127 diff --git a/policyengine_us/parameters/gov/states/mn/commerce/eap/payment/backup_cost/oil.yaml b/policyengine_us/parameters/gov/states/mn/commerce/eap/payment/backup_cost/oil.yaml new file mode 100644 index 00000000000..5ece349e0bf --- /dev/null +++ b/policyengine_us/parameters/gov/states/mn/commerce/eap/payment/backup_cost/oil.yaml @@ -0,0 +1,41 @@ +description: Minnesota uses this average annual energy cost for oil heat by housing type under the Energy Assistance Program. +# Applies to the FUEL_OIL and KEROSENE heating types. +APARTMENT: + 2025-10-01: 2_631 + 2026-10-01: 2_690 +DUPLEX: + 2025-10-01: 2_566 + 2026-10-01: 2_623 +TRIPLEX: + 2025-10-01: 2_533 + 2026-10-01: 2_590 +FOURPLEX: + 2025-10-01: 2_436 + 2026-10-01: 2_491 +TOWNHOUSE: + 2025-10-01: 2_631 + 2026-10-01: 2_690 +HOUSE: + 2025-10-01: 3_248 + 2026-10-01: 3_321 +MOBILE_HOME: + 2025-10-01: 3_248 + 2026-10-01: 3_321 +OTHER: + 2025-10-01: 2_631 + 2026-10-01: 2_690 +metadata: + unit: currency-USD + period: year + breakdown: + - mn_eap_housing_type + label: Minnesota EAP oil backup matrix energy cost + reference: + - title: Minnesota EAP Policy Manual FFY26 Appendix 4A Primary Heat Benefit Calculator, Backup Matrix Values!A2:C9 + href: https://liheapch.acf.gov/docs/2026/benefits-matricies/MN_BenefitMatrix_2026.xlsx + - title: Minnesota EAP Policy Manual FFY27 Appendix 4A Primary Heat Benefit Calculator, Backup Matrix Values!A2:C9 + href: https://mn.gov/commerce-stat/xls/phb-calculator.xlsx + - title: "Minnesota EAP Policy Manual FFY26, Chapter 4, Backup Matrix and Knowing Which Method to Use #page 125-126" + href: https://mn.gov/commerce-stat/pdfs/ffy26-eap-policy-manual.pdf#page=125 + - title: "Minnesota EAP Policy Manual FFY27, Chapter 4, Backup Matrix and Knowing Which Method to Use #page 127-128" + href: https://mn.gov/commerce-stat/pdfs/ffy27-eap-policy-manual.pdf#page=127 diff --git a/policyengine_us/parameters/gov/states/mn/commerce/eap/payment/backup_cost/propane.yaml b/policyengine_us/parameters/gov/states/mn/commerce/eap/payment/backup_cost/propane.yaml new file mode 100644 index 00000000000..44673f81106 --- /dev/null +++ b/policyengine_us/parameters/gov/states/mn/commerce/eap/payment/backup_cost/propane.yaml @@ -0,0 +1,40 @@ +description: Minnesota uses this average annual energy cost for propane heat by housing type under the Energy Assistance Program. +APARTMENT: + 2025-10-01: 2_272 + 2026-10-01: 2_306 +DUPLEX: + 2025-10-01: 2_502 + 2026-10-01: 2_540 +TRIPLEX: + 2025-10-01: 2_272 + 2026-10-01: 2_306 +FOURPLEX: + 2025-10-01: 2_140 + 2026-10-01: 2_172 +TOWNHOUSE: + 2025-10-01: 2_041 + 2026-10-01: 2_072 +HOUSE: + 2025-10-01: 3_293 + 2026-10-01: 3_342 +MOBILE_HOME: + 2025-10-01: 3_293 + 2026-10-01: 3_342 +OTHER: + 2025-10-01: 2_469 + 2026-10-01: 2_506 +metadata: + unit: currency-USD + period: year + breakdown: + - mn_eap_housing_type + label: Minnesota EAP propane backup matrix energy cost + reference: + - title: Minnesota EAP Policy Manual FFY26 Appendix 4A Primary Heat Benefit Calculator, Backup Matrix Values!A10:C17 + href: https://liheapch.acf.gov/docs/2026/benefits-matricies/MN_BenefitMatrix_2026.xlsx + - title: Minnesota EAP Policy Manual FFY27 Appendix 4A Primary Heat Benefit Calculator, Backup Matrix Values!A10:C17 + href: https://mn.gov/commerce-stat/xls/phb-calculator.xlsx + - title: "Minnesota EAP Policy Manual FFY26, Chapter 4, Backup Matrix and Knowing Which Method to Use #page 125-126" + href: https://mn.gov/commerce-stat/pdfs/ffy26-eap-policy-manual.pdf#page=125 + - title: "Minnesota EAP Policy Manual FFY27, Chapter 4, Backup Matrix and Knowing Which Method to Use #page 127-128" + href: https://mn.gov/commerce-stat/pdfs/ffy27-eap-policy-manual.pdf#page=127 diff --git a/policyengine_us/parameters/gov/states/mn/commerce/eap/payment/backup_cost/steam.yaml b/policyengine_us/parameters/gov/states/mn/commerce/eap/payment/backup_cost/steam.yaml new file mode 100644 index 00000000000..90bcf7ea46e --- /dev/null +++ b/policyengine_us/parameters/gov/states/mn/commerce/eap/payment/backup_cost/steam.yaml @@ -0,0 +1,41 @@ +description: Minnesota uses this average annual energy cost for steam heat by housing type under the Energy Assistance Program. +# No heating_type value selects this row. +APARTMENT: + 2025-10-01: 2_061 + 2026-10-01: 1_952 +DUPLEX: + 2025-10-01: 2_490 + 2026-10-01: 2_359 +TRIPLEX: + 2025-10-01: 2_375 + 2026-10-01: 2_250 +FOURPLEX: + 2025-10-01: 2_261 + 2026-10-01: 2_142 +TOWNHOUSE: + 2025-10-01: 2_061 + 2026-10-01: 1_952 +HOUSE: + 2025-10-01: 2_862 + 2026-10-01: 2_711 +MOBILE_HOME: + 2025-10-01: 2_862 + 2026-10-01: 2_711 +OTHER: + 2025-10-01: 1_660 + 2026-10-01: 1_572 +metadata: + unit: currency-USD + period: year + breakdown: + - mn_eap_housing_type + label: Minnesota EAP steam backup matrix energy cost + reference: + - title: Minnesota EAP Policy Manual FFY26 Appendix 4A Primary Heat Benefit Calculator, Backup Matrix Values!A18:C25 + href: https://liheapch.acf.gov/docs/2026/benefits-matricies/MN_BenefitMatrix_2026.xlsx + - title: Minnesota EAP Policy Manual FFY27 Appendix 4A Primary Heat Benefit Calculator, Backup Matrix Values!A18:C25 + href: https://mn.gov/commerce-stat/xls/phb-calculator.xlsx + - title: "Minnesota EAP Policy Manual FFY26, Chapter 4, Backup Matrix and Knowing Which Method to Use #page 125-126" + href: https://mn.gov/commerce-stat/pdfs/ffy26-eap-policy-manual.pdf#page=125 + - title: "Minnesota EAP Policy Manual FFY27, Chapter 4, Backup Matrix and Knowing Which Method to Use #page 127-128" + href: https://mn.gov/commerce-stat/pdfs/ffy27-eap-policy-manual.pdf#page=127 diff --git a/policyengine_us/parameters/gov/states/mn/commerce/eap/payment/energy_cost_sources.yaml b/policyengine_us/parameters/gov/states/mn/commerce/eap/payment/energy_cost_sources.yaml new file mode 100644 index 00000000000..7d61004713b --- /dev/null +++ b/policyengine_us/parameters/gov/states/mn/commerce/eap/payment/energy_cost_sources.yaml @@ -0,0 +1,22 @@ +description: Minnesota counts these home energy expenses as annual energy cost under the Energy Assistance Program. +values: + 2025-10-01: + # Primary Heat is based on all home energy costs, including non-heating + # electricity. Current-year expenses stand in for up to 12 months of + # prior-year consumption inside the 16-month window. + - pre_subsidy_electricity_expense + - gas_expense + - fuel_oil_expense + - bottled_gas_expense + - wood_expense + - coal_expense + - other_heating_fuel_expense +metadata: + unit: list + period: year + label: Minnesota EAP energy cost sources + reference: + - title: "Minnesota EAP Policy Manual FFY26, Chapter 4, What is Primary Heat and Measuring Energy Costs #page 117-119" + href: https://mn.gov/commerce-stat/pdfs/ffy26-eap-policy-manual.pdf#page=117 + - title: "Minnesota EAP Policy Manual FFY27, Chapter 4, What is Primary Heat and Measuring Energy Costs #page 119-121" + href: https://mn.gov/commerce-stat/pdfs/ffy27-eap-policy-manual.pdf#page=119 diff --git a/policyengine_us/parameters/gov/states/mn/commerce/eap/payment/maximum.yaml b/policyengine_us/parameters/gov/states/mn/commerce/eap/payment/maximum.yaml new file mode 100644 index 00000000000..74f595f9df0 --- /dev/null +++ b/policyengine_us/parameters/gov/states/mn/commerce/eap/payment/maximum.yaml @@ -0,0 +1,18 @@ +description: Minnesota provides at most this Primary Heat benefit under the Energy Assistance Program. +values: + 2025-10-01: 1_400 +metadata: + unit: currency-USD + period: year + label: Minnesota EAP maximum Primary Heat benefit + reference: + - title: Minnesota EAP Policy Manual FFY26, Chapter 4, Determining Primary Heat Benefits + href: https://mn.gov/commerce-stat/pdfs/ffy26-eap-policy-manual.pdf#page=124 + - title: Minnesota EAP Policy Manual FFY27, Chapter 4, Determining Primary Heat Benefits + href: https://mn.gov/commerce-stat/pdfs/ffy27-eap-policy-manual.pdf#page=126 + - title: Minnesota FY2026 LIHEAP State Plan, section 2.6 + href: https://liheapch.acf.gov/docs/2026/state-plans/MN_Plan_2026.pdf#page=9 + - title: Minnesota EAP Policy Manual FFY26 Appendix 4A Primary Heat Benefit Calculator, Formula Parameters!C3 + href: https://liheapch.acf.gov/docs/2026/benefits-matricies/MN_BenefitMatrix_2026.xlsx + - title: Minnesota EAP Policy Manual FFY27 Appendix 4A Primary Heat Benefit Calculator, Formula Parameters!C3 + href: https://mn.gov/commerce-stat/xls/phb-calculator.xlsx diff --git a/policyengine_us/parameters/gov/states/mn/commerce/eap/payment/minimum.yaml b/policyengine_us/parameters/gov/states/mn/commerce/eap/payment/minimum.yaml new file mode 100644 index 00000000000..6c8d9af2af4 --- /dev/null +++ b/policyengine_us/parameters/gov/states/mn/commerce/eap/payment/minimum.yaml @@ -0,0 +1,18 @@ +description: Minnesota provides at least this Primary Heat benefit under the Energy Assistance Program. +values: + 2025-10-01: 200 +metadata: + unit: currency-USD + period: year + label: Minnesota EAP minimum Primary Heat benefit + reference: + - title: Minnesota EAP Policy Manual FFY26, Chapter 4, Determining Primary Heat Benefits + href: https://mn.gov/commerce-stat/pdfs/ffy26-eap-policy-manual.pdf#page=124 + - title: Minnesota EAP Policy Manual FFY27, Chapter 4, Determining Primary Heat Benefits + href: https://mn.gov/commerce-stat/pdfs/ffy27-eap-policy-manual.pdf#page=126 + - title: Minnesota FY2026 LIHEAP State Plan, section 2.6 + href: https://liheapch.acf.gov/docs/2026/state-plans/MN_Plan_2026.pdf#page=9 + - title: Minnesota EAP Policy Manual FFY26 Appendix 4A Primary Heat Benefit Calculator, Formula Parameters!C2 + href: https://liheapch.acf.gov/docs/2026/benefits-matricies/MN_BenefitMatrix_2026.xlsx + - title: Minnesota EAP Policy Manual FFY27 Appendix 4A Primary Heat Benefit Calculator, Formula Parameters!C2 + href: https://mn.gov/commerce-stat/xls/phb-calculator.xlsx diff --git a/policyengine_us/parameters/gov/states/mn/commerce/eap/payment/share/maximum.yaml b/policyengine_us/parameters/gov/states/mn/commerce/eap/payment/share/maximum.yaml new file mode 100644 index 00000000000..322c224b9e4 --- /dev/null +++ b/policyengine_us/parameters/gov/states/mn/commerce/eap/payment/share/maximum.yaml @@ -0,0 +1,17 @@ +description: Minnesota pays this share of annual energy cost at the lowest income percentiles under the Energy Assistance Program. +values: + 2025-10-01: 0.439 + 2026-10-01: 0.452 +metadata: + unit: /1 + period: year + label: Minnesota EAP maximum pay share + reference: + - title: Minnesota EAP Policy Manual FFY26 Appendix 4A Primary Heat Benefit Calculator, Formula Parameters!C4 + href: https://liheapch.acf.gov/docs/2026/benefits-matricies/MN_BenefitMatrix_2026.xlsx + - title: Minnesota EAP Policy Manual FFY27 Appendix 4A Primary Heat Benefit Calculator, Formula Parameters!C4 + href: https://mn.gov/commerce-stat/xls/phb-calculator.xlsx + - title: Minnesota EAP Policy Manual FFY26, Chapter 4, Measuring Financial Need + href: https://mn.gov/commerce-stat/pdfs/ffy26-eap-policy-manual.pdf#page=124 + - title: Minnesota EAP Policy Manual FFY27, Chapter 4, Measuring Financial Need + href: https://mn.gov/commerce-stat/pdfs/ffy27-eap-policy-manual.pdf#page=126 diff --git a/policyengine_us/parameters/gov/states/mn/commerce/eap/payment/share/minimum.yaml b/policyengine_us/parameters/gov/states/mn/commerce/eap/payment/share/minimum.yaml new file mode 100644 index 00000000000..bec59d48726 --- /dev/null +++ b/policyengine_us/parameters/gov/states/mn/commerce/eap/payment/share/minimum.yaml @@ -0,0 +1,17 @@ +description: Minnesota pays this share of annual energy cost at the highest income percentiles under the Energy Assistance Program. +values: + 2025-10-01: 0.108 + 2026-10-01: 0.113 +metadata: + unit: /1 + period: year + label: Minnesota EAP minimum pay share + reference: + - title: Minnesota EAP Policy Manual FFY26 Appendix 4A Primary Heat Benefit Calculator, Formula Parameters!C5 + href: https://liheapch.acf.gov/docs/2026/benefits-matricies/MN_BenefitMatrix_2026.xlsx + - title: Minnesota EAP Policy Manual FFY27 Appendix 4A Primary Heat Benefit Calculator, Formula Parameters!C5 + href: https://mn.gov/commerce-stat/xls/phb-calculator.xlsx + - title: Minnesota EAP Policy Manual FFY26, Chapter 4, Measuring Financial Need + href: https://mn.gov/commerce-stat/pdfs/ffy26-eap-policy-manual.pdf#page=124 + - title: Minnesota EAP Policy Manual FFY27, Chapter 4, Measuring Financial Need + href: https://mn.gov/commerce-stat/pdfs/ffy27-eap-policy-manual.pdf#page=126 diff --git a/policyengine_us/parameters/gov/states/mn/commerce/eap/payment/share/slope_end.yaml b/policyengine_us/parameters/gov/states/mn/commerce/eap/payment/share/slope_end.yaml new file mode 100644 index 00000000000..e587dde16ad --- /dev/null +++ b/policyengine_us/parameters/gov/states/mn/commerce/eap/payment/share/slope_end.yaml @@ -0,0 +1,17 @@ +description: Minnesota stops reducing the pay share at this income percentile under the Energy Assistance Program. +values: + 2025-10-01: 0.896 + 2026-10-01: 0.891 +metadata: + unit: /1 + period: year + label: Minnesota EAP pay share slope end percentile + reference: + - title: Minnesota EAP Policy Manual FFY26 Appendix 4A Primary Heat Benefit Calculator, Formula Parameters!C7 + href: https://liheapch.acf.gov/docs/2026/benefits-matricies/MN_BenefitMatrix_2026.xlsx + - title: Minnesota EAP Policy Manual FFY27 Appendix 4A Primary Heat Benefit Calculator, Formula Parameters!C7 + href: https://mn.gov/commerce-stat/xls/phb-calculator.xlsx + - title: Minnesota EAP Policy Manual FFY26, Chapter 4, Measuring Financial Need + href: https://mn.gov/commerce-stat/pdfs/ffy26-eap-policy-manual.pdf#page=124 + - title: Minnesota EAP Policy Manual FFY27, Chapter 4, Measuring Financial Need + href: https://mn.gov/commerce-stat/pdfs/ffy27-eap-policy-manual.pdf#page=126 diff --git a/policyengine_us/parameters/gov/states/mn/commerce/eap/payment/share/slope_start.yaml b/policyengine_us/parameters/gov/states/mn/commerce/eap/payment/share/slope_start.yaml new file mode 100644 index 00000000000..b3b6b489005 --- /dev/null +++ b/policyengine_us/parameters/gov/states/mn/commerce/eap/payment/share/slope_start.yaml @@ -0,0 +1,17 @@ +description: Minnesota starts reducing the pay share above this income percentile under the Energy Assistance Program. +values: + 2025-10-01: 0 + 2026-10-01: 0 +metadata: + unit: /1 + period: year + label: Minnesota EAP pay share slope start percentile + reference: + - title: Minnesota EAP Policy Manual FFY26 Appendix 4A Primary Heat Benefit Calculator, Formula Parameters!C6 + href: https://liheapch.acf.gov/docs/2026/benefits-matricies/MN_BenefitMatrix_2026.xlsx + - title: Minnesota EAP Policy Manual FFY27 Appendix 4A Primary Heat Benefit Calculator, Formula Parameters!C6 + href: https://mn.gov/commerce-stat/xls/phb-calculator.xlsx + - title: Minnesota EAP Policy Manual FFY26, Chapter 4, Measuring Financial Need + href: https://mn.gov/commerce-stat/pdfs/ffy26-eap-policy-manual.pdf#page=124 + - title: Minnesota EAP Policy Manual FFY27, Chapter 4, Measuring Financial Need + href: https://mn.gov/commerce-stat/pdfs/ffy27-eap-policy-manual.pdf#page=126 diff --git a/policyengine_us/programs.yaml b/policyengine_us/programs.yaml index 43fdd714b80..92a259e5661 100644 --- a/policyengine_us/programs.yaml +++ b/policyengine_us/programs.yaml @@ -808,7 +808,7 @@ programs: category: Benefits agency: HHS status: partial - coverage: AL, DC, Riverside County, MA, FL, IL, IN, KS, KY, MD, MS, NC, NE, NJ, NY, OH, OK, OR, SD, RI, TX + coverage: AL, DC, Riverside County, MA, FL, IL, IN, KS, KY, MD, MN, MS, NC, NE, NJ, NY, OH, OK, OR, SD, RI, TX state_implementations: - state: AL status: partial @@ -898,6 +898,14 @@ programs: parameter_prefix: gov.states.md.dhs.meap verified_years: "2025-2027" notes: FY25-FY27 regular heating only, with the fuel tables, the Garrett County multiplier and the subsidized and nominal levels. The SNAP nominal payment, cooling, EUSP, arrearage, crisis and equipment benefits are out of scope. + - state: MN + status: partial + name: Minnesota EAP + full_name: Minnesota Energy Assistance Program + variable: mn_eap + parameter_prefix: gov.states.mn.commerce.eap + verified_years: "2026-2027" + notes: FFY2026-FFY2027 Primary Heat, Minnesota's single regular benefit, based on total household energy costs including electricity. Crisis, Energy Related Repair and weatherization are out of scope. - state: MS status: partial name: Mississippi LIHEAP diff --git a/policyengine_us/tests/policy/baseline/gov/states/mn/commerce/eap/eligibility/mn_eap_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/mn/commerce/eap/eligibility/mn_eap_eligible.yaml new file mode 100644 index 00000000000..9563fe3f838 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/mn/commerce/eap/eligibility/mn_eap_eligible.yaml @@ -0,0 +1,188 @@ +# Eligibility needs at least one eligible member, income at or below the +# limit (Appendix 4A Calculator!G2 is ineligible only when the income +# percentile exceeds 1), a known heating type, and vulnerability to energy +# costs: a household that pays an energy vendor, heat included in unsubsidized +# rent, or subsidized heat-in-rent with an electric bill (FFY26 EAP Policy +# Manual, Chapter 3 vulnerability rules and Chapter 4 "Knowing Which Method to +# Use"). + +# FFY26 size 1 limit $3,119 x 12 = $37,428. Wages of $37,428 are at the limit +# (eligible); $37,429 is one dollar above (ineligible). +- name: Case 1, income at the limit is eligible and one dollar above is not. + period: 2026 + input: + people: + person1: + age: 45 + employment_income: 37_428 + person2: + age: 45 + employment_income: 37_429 + spm_units: + spm_unit1: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 800 + pre_subsidy_electricity_expense: 700 + tanf: 0 + spm_unit2: + members: [person2] + heating_type: NATURAL_GAS + gas_expense: 800 + pre_subsidy_electricity_expense: 700 + tanf: 0 + households: + household1: + members: [person1] + state_code: MN + household2: + members: [person2] + state_code: MN + output: + mn_eap_eligible: [true, false] + +# Same income ($20,000, under the $37,428 limit) and bills; only the heating +# type differs. UNSPECIFIED and NONE are ineligible; natural gas is eligible. +- name: Case 2, unspecified and no heating types are ineligible. + period: 2026 + input: + people: + person1: + age: 38 + employment_income: 20_000 + person2: + age: 38 + employment_income: 20_000 + person3: + age: 38 + employment_income: 20_000 + spm_units: + spm_unit1: + members: [person1] + heating_type: UNSPECIFIED + gas_expense: 900 + pre_subsidy_electricity_expense: 800 + tanf: 0 + spm_unit2: + members: [person2] + heating_type: NONE + pre_subsidy_electricity_expense: 900 + tanf: 0 + spm_unit3: + members: [person3] + heating_type: NATURAL_GAS + gas_expense: 900 + pre_subsidy_electricity_expense: 800 + tanf: 0 + households: + household1: + members: [person1] + state_code: MN + household2: + members: [person2] + state_code: MN + household3: + members: [person3] + state_code: MN + output: + mn_eap_eligible: [false, false, true] + +# Subsidized housing with heat in rent: a household paying no electric bill is +# not vulnerable (ineligible); one paying $650 a year for electricity is +# eligible. +- name: Case 3, subsidized heat-in-rent needs an electric bill. + period: 2026 + input: + people: + person1: + age: 72 + social_security_retirement: 14_400 + medicare_part_b_premium: 2_434.8 + ssi: 0 + person2: + age: 72 + social_security_retirement: 14_400 + medicare_part_b_premium: 2_434.8 + ssi: 0 + spm_units: + spm_unit1: + members: [person1] + heating_type: NATURAL_GAS + heat_expense_included_in_rent: true + receives_housing_assistance: true + tanf: 0 + spm_unit2: + members: [person2] + heating_type: NATURAL_GAS + heat_expense_included_in_rent: true + receives_housing_assistance: true + pre_subsidy_electricity_expense: 650 + tanf: 0 + households: + household1: + members: [person1] + state_code: MN + household2: + members: [person2] + state_code: MN + output: + mn_eap_eligible: [false, true] + +# A household paying its own energy with $0 energy cost is ineligible; an +# unsubsidized renter with heat included in rent is eligible with no bills of +# its own (the backup matrix supplies the cost). +- name: Case 4, an own-paying household with no energy cost is ineligible and unsubsidized heat-in-rent is eligible. + period: 2026 + input: + people: + person1: + age: 30 + employment_income: 22_000 + person2: + age: 30 + employment_income: 22_000 + spm_units: + spm_unit1: + members: [person1] + heating_type: NATURAL_GAS + tanf: 0 + spm_unit2: + members: [person2] + heating_type: NATURAL_GAS + heat_expense_included_in_rent: true + mn_eap_housing_type: APARTMENT + tanf: 0 + households: + household1: + members: [person1] + state_code: MN + household2: + members: [person2] + state_code: MN + output: + mn_eap_eligible: [false, true] + +# No member is a citizen or eligible non-citizen, so the household size is 0 +# and the household is ineligible despite low income and energy bills. +- name: Case 5, a household with no eligible members is ineligible. + period: 2026 + input: + people: + person1: + age: 33 + immigration_status: UNDOCUMENTED + employment_income: 18_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 900 + pre_subsidy_electricity_expense: 800 + tanf: 0 + households: + household: + members: [person1] + state_code: MN + output: + mn_eap_household_size: 0 + mn_eap_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/mn/commerce/eap/eligibility/mn_eap_income_limit.yaml b/policyengine_us/tests/policy/baseline/gov/states/mn/commerce/eap/eligibility/mn_eap_income_limit.yaml new file mode 100644 index 00000000000..89b59a626d4 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/mn/commerce/eap/eligibility/mn_eap_income_limit.yaml @@ -0,0 +1,146 @@ +# The monthly limit is 50% of state median income for sizes 1-18 and 110% of +# the prior year's federal poverty guideline for sizes 19-20 (FFY26 EAP Policy +# Manual and FFY27 EAP Policy Manual, Chapter 3, "Maximum EAP Income +# Guidelines" tables; Appendix 4A 'Income Guidelines'!B2:B21). The model stores +# the annual equivalent, 12 x the one-month maximum. Above size 20 the larger of +# the two standards applies (42 U.S.C. 8624(b)(2)(B) floor). + +# FFY26 one-month maximums: size 1 $3,119 x 12 = $37,428; size 4 $5,999 x 12 = +# $71,988; size 18 $10,079 x 12 = $120,948 (50% SMI binds: 110% FPG would give +# $10,005); size 19 $10,509 x 12 = $126,108 (110% FPG binds). Size 21 by hand: +# 2025 FPG $15,650 + 20 x $5,500 = $125,650 x 1.1 = $138,215 / 12 = $11,517.92 +# -> $11,517 (50% SMI: $143,998 x 1.77 x 0.5 / 12 = $10,619.85 is lower); +# $11,517 x 12 = $138,204. Size 0 returns $0. +- name: Case 1, FFY2026 annual equivalent limits for sizes 0, 1, 4, 18, 19 and 21. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + person2: + age: 40 + person3: + age: 40 + person4: + age: 40 + person5: + age: 40 + person6: + age: 40 + spm_units: + spm_unit1: + members: [person1] + mn_eap_household_size: 0 + heating_type: NATURAL_GAS + spm_unit2: + members: [person2] + mn_eap_household_size: 1 + heating_type: NATURAL_GAS + spm_unit3: + members: [person3] + mn_eap_household_size: 4 + heating_type: NATURAL_GAS + spm_unit4: + members: [person4] + mn_eap_household_size: 18 + heating_type: NATURAL_GAS + spm_unit5: + members: [person5] + mn_eap_household_size: 19 + heating_type: NATURAL_GAS + spm_unit6: + members: [person6] + mn_eap_household_size: 21 + heating_type: NATURAL_GAS + households: + household1: + members: [person1] + state_code: MN + household2: + members: [person2] + state_code: MN + household3: + members: [person3] + state_code: MN + household4: + members: [person4] + state_code: MN + household5: + members: [person5] + state_code: MN + household6: + members: [person6] + state_code: MN + output: + mn_eap_income_limit: [0, 37_428, 71_988, 120_948, 126_108, 138_204] + +# FFY27 one-month maximums: size 1 $3,205 x 12 = $38,460; size 4 $6,164 x 12 = +# $73,968; size 18 $10,355 x 12 = $124,260 (50% SMI binds: 110% FPG would give +# $10,314); size 19 $10,835 x 12 = $130,020 (110% FPG binds). Size 21 by hand: +# 2026 FPG $15,960 + 20 x $5,680 = $129,560 x 1.1 = $142,516 / 12 = $11,876.33 +# -> $11,876 (50% SMI: $147,939 x 1.77 x 0.5 / 12 = $10,910.50 is lower); +# $11,876 x 12 = $142,512. +- name: Case 2, FFY2027 annual equivalent limits for sizes 0, 1, 4, 18, 19 and 21. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + person2: + age: 40 + person3: + age: 40 + person4: + age: 40 + person5: + age: 40 + person6: + age: 40 + spm_units: + spm_unit1: + members: [person1] + mn_eap_household_size: 0 + heating_type: NATURAL_GAS + spm_unit2: + members: [person2] + mn_eap_household_size: 1 + heating_type: NATURAL_GAS + spm_unit3: + members: [person3] + mn_eap_household_size: 4 + heating_type: NATURAL_GAS + spm_unit4: + members: [person4] + mn_eap_household_size: 18 + heating_type: NATURAL_GAS + spm_unit5: + members: [person5] + mn_eap_household_size: 19 + heating_type: NATURAL_GAS + spm_unit6: + members: [person6] + mn_eap_household_size: 21 + heating_type: NATURAL_GAS + households: + household1: + members: [person1] + state_code: MN + household2: + members: [person2] + state_code: MN + household3: + members: [person3] + state_code: MN + household4: + members: [person4] + state_code: MN + household5: + members: [person5] + state_code: MN + household6: + members: [person6] + state_code: MN + output: + mn_eap_income_limit: [0, 38_460, 73_968, 124_260, 130_020, 142_512] diff --git a/policyengine_us/tests/policy/baseline/gov/states/mn/commerce/eap/income/mn_eap_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/mn/commerce/eap/income/mn_eap_countable_income.yaml new file mode 100644 index 00000000000..edabc5705fc --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/mn/commerce/eap/income/mn_eap_countable_income.yaml @@ -0,0 +1,286 @@ +# Countable income is gross cash receipts under the FFY26 EAP Policy Manual, +# Chapter 3 Income Inclusions and Exclusions table. Annual inputs stand for +# twelve times the one-month eligibility amount. + +# Wages $23,733 ($11.41 x 2,080 hours) + self-employment loss floored at $0 +# (a loss on one source is not subtracted from another) + undocumented spouse's +# wages $18,000 (not in the household size, but income counts in full) +# = $41,733. +- name: Case 1, a self-employment loss does not offset wages and an ineligible non-citizen's wages count. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + immigration_status: CITIZEN + employment_income: 23_733 + self_employment_income: -4_000 + person2: + age: 34 + immigration_status: UNDOCUMENTED + employment_income: 18_000 + spm_units: + spm_unit: + members: [person1, person2] + heating_type: NATURAL_GAS + tanf: 0 + households: + household: + members: [person1, person2] + state_code: MN + output: + mn_eap_household_size: 1 + mn_eap_countable_income: 41_733 + +# Parent's wages $31,200 count. The 19-year-old high school student's $6,000 +# wages and $1,200 unemployment insurance are excluded (age 19 and below in +# K-12). The 20-year-old in a GED program is over the age limit, so the +# $6,000 + $1,200 count: $31,200 + $7,200 = $38,400. +- name: Case 2, a student aged 19 has earnings and unemployment excluded and a student aged 20 does not. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 42 + employment_income: 31_200 + person2: + age: 19 + is_in_k12_school: true + employment_income: 6_000 + unemployment_compensation: 1_200 + person3: + age: 20 + is_in_k12_school: true + employment_income: 6_000 + unemployment_compensation: 1_200 + spm_units: + spm_unit: + members: [person1, person2, person3] + heating_type: NATURAL_GAS + tanf: 0 + households: + household: + members: [person1, person2, person3] + state_code: MN + output: + mn_eap_countable_income: 38_400 + +# Social Security counts net of the Medicare premium deducted from it, and the +# pension is netted in the same term once: $21,600 + $6,000 - $2,434.80 (2026 +# Part B premium $202.90 x 12) = $25,165.20. The working spouse aged 66 pays +# the premium but has no Social Security or pension, so the premium does not +# reduce the $18,000 wages. Total $43,165.20. +- name: Case 3, Social Security and pension count net of the Medicare premium without reducing wages. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + social_security_retirement: 21_600 + pension_income: 6_000 + medicare_part_b_premium: 2_434.8 + ssi: 0 + person2: + age: 66 + employment_income: 18_000 + medicare_part_b_premium: 2_434.8 + ssi: 0 + spm_units: + spm_unit: + members: [person1, person2] + heating_type: NATURAL_GAS + tanf: 0 + households: + household: + members: [person1, person2] + state_code: MN + output: + mn_eap_countable_income: 43_165.2 + +# Retirement payments count at age 59 1/2 or older; early withdrawals do not. +# The $6,000 IRA withdrawal at age 59 is excluded and the $6,000 at exactly +# age 59 1/2 counts: $6,000. +- name: Case 4, an IRA withdrawal counts at exactly age 59 1/2 and not at age 59. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 59 + taxable_ira_distributions: 6_000 + person2: + age: 59.5 + taxable_ira_distributions: 6_000 + spm_units: + spm_unit: + members: [person1, person2] + heating_type: NATURAL_GAS + tanf: 0 + households: + household: + members: [person1, person2] + state_code: MN + output: + mn_eap_countable_income: 6_000 + +# Dividends and interest count when the one-month equivalent is $50 or more. +# Unit 1: $400 interest + $200 ordinary dividends = $600 a year ($50 a month) +# counts: $20,000 + $600 = $20,600. Unit 2: $399 + $200 = $599 ($49.92 a +# month) does not: $20,000. +- name: Case 5, household interest and dividends count at exactly 50 dollars a month and not below. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 64 + employment_income: 20_000 + interest_income: 400 + person2: + age: 63 + ordinary_dividend_income: 200 + person3: + age: 64 + employment_income: 20_000 + interest_income: 399 + person4: + age: 63 + ordinary_dividend_income: 200 + spm_units: + spm_unit1: + members: [person1, person2] + heating_type: NATURAL_GAS + tanf: 0 + spm_unit2: + members: [person3, person4] + heating_type: NATURAL_GAS + tanf: 0 + households: + household1: + members: [person1, person2] + state_code: MN + household2: + members: [person3, person4] + state_code: MN + output: + mn_eap_countable_income: [20_600, 20_000] + +# Cash gifts count when they total $100 or more in the eligibility period +# ($99 or less does not). Unit 1: $1,200 a year ($100 a month) counts: +# $20,000 + $1,200 = $21,200. Unit 2: $1,199 ($99.92 a month) does not: +# $20,000. +- name: Case 6, cash gifts count at exactly 100 dollars a month and not below. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 29 + employment_income: 20_000 + financial_assistance: 1_200 + person2: + age: 29 + employment_income: 20_000 + financial_assistance: 1_199 + spm_units: + spm_unit1: + members: [person1] + heating_type: NATURAL_GAS + tanf: 0 + spm_unit2: + members: [person2] + heating_type: NATURAL_GAS + tanf: 0 + households: + household1: + members: [person1] + state_code: MN + household2: + members: [person2] + state_code: MN + output: + mn_eap_countable_income: [21_200, 20_000] + +# Veteran's benefits and SSI count: $14,400 ($1,200 a month) + $11,928 (2026 +# federal SSI rate $994 x 12) = $26,328. +- name: Case 7, veterans benefits and SSI count. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 55 + veterans_benefits: 14_400 + person2: + age: 50 + is_disabled: true + ssi: 11_928 + spm_units: + spm_unit: + members: [person1, person2] + heating_type: NATURAL_GAS + tanf: 0 + households: + household: + members: [person1, person2] + state_code: MN + output: + mn_eap_countable_income: 26_328 + +# MFIP cash assistance counts (Assistance Payments); child support received +# does not: $7,800. +- name: Case 8, MFIP cash assistance counts and child support does not. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 27 + child_support_received: 3_600 + person2: + age: 4 + spm_units: + spm_unit: + members: [person1, person2] + heating_type: NATURAL_GAS + tanf: 7_800 + households: + household: + members: [person1, person2] + state_code: MN + output: + mn_eap_countable_income: 7_800 + +# Minnesota Paid Leave, paid from 2026-01-01, is wage replacement cash and +# counts in FFY2026 under the FFY26 definition of income as gross cash +# receipts (the FFY27 Income Inclusions and Exclusions table states "MPL +# payments are countable income"). $30,000 wages + $9,000 paid leave = +# $39,000, above the FFY26 size 1 limit of $3,119 x 12 = $37,428, so the +# household is ineligible although it has a known heating type and $2,000 of +# energy bills ($30,000 of wages alone would be under the limit). +- name: Case 9, Minnesota Paid Leave benefits count in FFY2026. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 39 + employment_income: 30_000 + pfml_benefits: 9_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + pre_subsidy_electricity_expense: 1_000 + tanf: 0 + households: + household: + members: [person1] + state_code: MN + output: + mn_eap_countable_income: 39_000 + mn_eap_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/mn/commerce/eap/mn_eap.yaml b/policyengine_us/tests/policy/baseline/gov/states/mn/commerce/eap/mn_eap.yaml new file mode 100644 index 00000000000..6d249b75361 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/mn/commerce/eap/mn_eap.yaml @@ -0,0 +1,245 @@ +# Primary Heat benefit = pay share x annual energy cost, rounded to the +# nearest dollar and held between the $200 minimum and $1,400 maximum (FFY26 +# EAP Policy Manual and FFY27 EAP Policy Manual, Chapter 4 "Determining +# Primary Heat Benefits"; Appendix 4A Calculator!H2 = ROUND(G2*C2, 0) and +# Calculator!I2; 'Formula Parameters'!C2:C3). + +# Appendix 4A FFY26 Calculator row 2: size 1, $1,000 a month ($12,000 a year) +# against $3,119 ($37,428): E2 = 0.3206156; F2 = 0.439 - 0.331 x 0.3206156 / +# 0.896 = 0.3205583. $2,000 annual energy cost: 0.3205583 x $2,000 = $641.12 +# -> H2 = I2 = $641. +- name: Case 1, a mid benefit reproduces FFY2026 Appendix 4A Calculator row 2. + period: 2026 + absolute_error_margin: 0.0001 + input: + people: + person1: + age: 36 + employment_income: 12_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + pre_subsidy_electricity_expense: 1_000 + tanf: 0 + households: + household: + members: [person1] + state_code: MN + output: + mn_eap_pay_share: 0.3205583 + mn_eap: 641 + +# Appendix 4A FFY27 Calculator row 2: size 1, $12,000 a year against $3,205 x +# 12 = $38,460: E2 = 0.3120125; F2 = 0.452 - 0.339 x 0.3120125 / 0.891 = +# 0.3332882. 0.3332882 x $2,000 = $666.58, rounded up to H2 = I2 = $667. +- name: Case 2, a mid benefit rounds up and reproduces FFY2027 Appendix 4A Calculator row 2. + period: 2027 + absolute_error_margin: 0.0001 + input: + people: + person1: + age: 36 + employment_income: 12_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + pre_subsidy_electricity_expense: 1_000 + tanf: 0 + households: + household: + members: [person1] + state_code: MN + output: + mn_eap_pay_share: 0.3332882 + mn_eap: 667 + +# $35,000 / $37,428 = 0.935 -> pay min 0.108; $450 gas + $650 electricity = +# $1,100; 0.108 x $1,100 = $118.80 -> $119, raised to the $200 minimum. +- name: Case 3, the 200 dollar minimum binds. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 29 + employment_income: 35_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 450 + pre_subsidy_electricity_expense: 650 + tanf: 0 + households: + household: + members: [person1] + state_code: MN + output: + mn_eap: 200 + +# Size 3 FFY26 limit $5,039 x 12 = $60,468; $14,000 / $60,468 = 0.2315275; +# share 0.439 - 0.331 x 0.2315275 / 0.896 = 0.3534692; $2,700 propane + $1,500 +# electricity = $4,200; 0.3534692 x $4,200 = $1,484.57 -> $1,485, capped at the +# $1,400 maximum. +- name: Case 4, the 1,400 dollar maximum binds. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 34 + employment_income: 14_000 + person2: + age: 7 + person3: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3] + heating_type: PROPANE + bottled_gas_expense: 2_700 + pre_subsidy_electricity_expense: 1_500 + mn_eap_housing_type: HOUSE + tanf: 0 + households: + household: + members: [person1, person2, person3] + state_code: MN + output: + mn_eap: 1_400 + +# Heat included in unsubsidized rent with wood heat: eligible, but the backup +# matrix has no wood row, so the energy cost and the benefit are $0. +- name: Case 5, heat-in-rent with no backup matrix row pays nothing. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 47 + employment_income: 20_000 + spm_units: + spm_unit: + members: [person1] + heating_type: WOOD + heat_expense_included_in_rent: true + mn_eap_housing_type: HOUSE + tanf: 0 + households: + household: + members: [person1] + state_code: MN + output: + mn_eap_eligible: true + mn_eap_energy_cost: 0 + mn_eap: 0 + +# $40,000 is above the FFY26 size 1 limit of $37,428, so no benefit. +- name: Case 6, an over-income household gets no benefit. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 44 + employment_income: 40_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + pre_subsidy_electricity_expense: 900 + tanf: 0 + households: + household: + members: [person1] + state_code: MN + output: + mn_eap_eligible: false + mn_eap: 0 + +# Minneapolis renter family of four paying its own gas and electricity, FFY26. +# Size 4 (all citizens). Countable income: $37,440 ($18 x 2,080 hours) + +# $14,040 ($13.50 x 1,040 hours) = $51,480; the 16-year-old high school +# student's $4,000 summer wages are excluded. Limit $5,999 x 12 = $71,988. +# Energy cost $1,050 gas + $1,000 electricity = $2,050. Percentile $51,480 / +# $71,988 = 0.7151192; share 0.439 - 0.331 x 0.7151192 / 0.896 = 0.1748209. +# Benefit 0.1748209 x $2,050 = $358.38 -> $358. +- name: Case 7, Minneapolis renter family paying gas and electricity in FFY2026. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 38 + employment_income: 37_440 + person2: + age: 36 + employment_income: 14_040 + person3: + age: 16 + is_in_k12_school: true + employment_income: 4_000 + person4: + age: 9 + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + heating_type: NATURAL_GAS + gas_expense: 1_050 + pre_subsidy_electricity_expense: 1_000 + mn_eap_housing_type: DUPLEX + tanf: 0 + households: + household: + members: [person1, person2, person3, person4] + state_code: MN + output: + mn_eap_household_size: 4 + mn_eap_countable_income: 51_480 + mn_eap_income_limit: 71_988 + mn_eap_energy_cost: 2_050 + mn_eap_eligible: true + mn_eap_pay_share: 0.1748209 + mn_eap: 358 + +# Single parent and child renting a mobile home with propane heat included in +# the rent, FFY27. Size 2. Countable income: $27,000 wages; the $3,000 of +# child support is not counted. Limit $4,191 x 12 = $50,292. Energy cost from +# the FFY27 backup matrix, Propane, Mobile Home, C14 = $3,342. Percentile +# $27,000 / $50,292 = 0.5368647; share 0.452 - 0.339 x 0.5368647 / 0.891 = +# 0.2477383. Benefit 0.2477383 x $3,342 = $827.94 -> $828. +- name: Case 8, mobile home renter with propane heat included in rent in FFY2027. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 31 + employment_income: 27_000 + child_support_received: 3_000 + person2: + age: 6 + spm_units: + spm_unit: + members: [person1, person2] + heating_type: PROPANE + heat_expense_included_in_rent: true + mn_eap_housing_type: MOBILE_HOME + tanf: 0 + households: + household: + members: [person1, person2] + state_code: MN + output: + mn_eap_household_size: 2 + mn_eap_countable_income: 27_000 + mn_eap_income_limit: 50_292 + mn_eap_energy_cost: 3_342 + mn_eap_eligible: true + mn_eap_pay_share: 0.2477383 + mn_eap: 828 diff --git a/policyengine_us/tests/policy/baseline/gov/states/mn/commerce/eap/mn_eap_household_size.yaml b/policyengine_us/tests/policy/baseline/gov/states/mn/commerce/eap/mn_eap_household_size.yaml new file mode 100644 index 00000000000..62dc8e272e8 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/mn/commerce/eap/mn_eap_household_size.yaml @@ -0,0 +1,27 @@ +# EAP counts household members who are citizens or eligible non-citizens; an +# ineligible non-citizen is left out of the size (FFY26 EAP Policy Manual, +# Chapter 3, household composition). +- name: Case 1, a citizen and a permanent resident count and an undocumented member does not. + period: 2026 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + person2: + age: 38 + immigration_status: LEGAL_PERMANENT_RESIDENT + person3: + age: 36 + immigration_status: UNDOCUMENTED + spm_units: + spm_unit: + members: [person1, person2, person3] + heating_type: NATURAL_GAS + households: + household: + members: [person1, person2, person3] + state_code: MN + output: + # 1 citizen + 1 legal permanent resident = 2. + mn_eap_household_size: 2 diff --git a/policyengine_us/tests/policy/baseline/gov/states/mn/commerce/eap/payment/mn_eap_energy_cost.yaml b/policyengine_us/tests/policy/baseline/gov/states/mn/commerce/eap/payment/mn_eap_energy_cost.yaml new file mode 100644 index 00000000000..5d2e91b0b63 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/mn/commerce/eap/payment/mn_eap_energy_cost.yaml @@ -0,0 +1,176 @@ +# Energy cost is the household's total home energy bills, heating fuels plus +# all electricity (FFY26 EAP Policy Manual, Chapter 4 "What is Primary Heat?"). +# With heat included in unsubsidized rent, the backup matrix average annual +# energy cost for the primary fuel and housing type applies; with heat +# included in subsidized rent, the electric cost applies (Chapter 4 "Knowing +# Which Method to Use"). Backup matrix values: Appendix 4A 'Backup Matrix +# Values'!A2:C57, FFY26 and FFY27 editions. + +# Own bills: $1,100 gas + $1,000 electricity + $200 firewood for a wood stove +# = $2,300. +- name: Case 1, own bills are summed across fuels including electricity. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 41 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_100 + pre_subsidy_electricity_expense: 1_000 + wood_expense: 200 + households: + household: + members: [person1] + state_code: MN + output: + mn_eap_energy_cost: 2_300 + +# Heat included in unsubsidized rent: the FFY26 backup matrix replaces bills. +# Unit 1: natural gas, apartment, C26 = $1,458 (its $600 electric bill is not +# added). Unit 2: propane, mobile home, C14 = $3,293. +- name: Case 2, unsubsidized heat-in-rent uses the FFY2026 backup matrix for two housing types. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 41 + person2: + age: 63 + spm_units: + spm_unit1: + members: [person1] + heating_type: NATURAL_GAS + heat_expense_included_in_rent: true + mn_eap_housing_type: APARTMENT + pre_subsidy_electricity_expense: 600 + spm_unit2: + members: [person2] + heating_type: PROPANE + heat_expense_included_in_rent: true + mn_eap_housing_type: MOBILE_HOME + households: + household1: + members: [person1] + state_code: MN + household2: + members: [person2] + state_code: MN + output: + mn_eap_energy_cost: [1_458, 3_293] + +# Fuel oil and kerosene both use the Oil row: FFY26 Oil, Duplex, C3 = $2,566 +# (propane duplex is $2,502, natural gas $2,423, electricity $1,747). Electric +# heat in a townhouse uses the Electricity row, C40 = $1,547. +- name: Case 3, fuel oil and kerosene both use the oil row and electric heat uses the electricity row. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 52 + person2: + age: 52 + person3: + age: 52 + spm_units: + spm_unit1: + members: [person1] + heating_type: FUEL_OIL + heat_expense_included_in_rent: true + mn_eap_housing_type: DUPLEX + spm_unit2: + members: [person2] + heating_type: KEROSENE + heat_expense_included_in_rent: true + mn_eap_housing_type: DUPLEX + spm_unit3: + members: [person3] + heating_type: ELECTRICITY + heat_expense_included_in_rent: true + mn_eap_housing_type: TOWNHOUSE + households: + household1: + members: [person1] + state_code: MN + household2: + members: [person2] + state_code: MN + household3: + members: [person3] + state_code: MN + output: + mn_eap_energy_cost: [2_566, 2_566, 1_547] + +# Heat included in subsidized rent: only the electric bill counts. Unit 1 +# (Section 8 voucher) pays $720 for electricity; unit 2 (public housing) pays +# $650. The backup matrix is not used. +- name: Case 4, subsidized heat-in-rent uses the electric bill only. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 68 + person2: + age: 68 + spm_units: + spm_unit1: + members: [person1] + heating_type: NATURAL_GAS + heat_expense_included_in_rent: true + receives_housing_assistance: true + mn_eap_housing_type: APARTMENT + pre_subsidy_electricity_expense: 720 + spm_unit2: + members: [person2] + heating_type: NATURAL_GAS + heat_expense_included_in_rent: true + mn_eap_housing_type: APARTMENT + pre_subsidy_electricity_expense: 650 + households: + household1: + members: [person1] + state_code: MN + household2: + members: [person2] + state_code: MN + is_in_public_housing: true + output: + mn_eap_energy_cost: [720, 650] + +# FFY27 backup matrix: natural gas, apartment, C26 = $1,554 (FFY26 was +# $1,458). With no housing type supplied, the House row applies: C29 = +# $2,634. +- name: Case 5, FFY2027 backup matrix values and the house default. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 41 + person2: + age: 41 + spm_units: + spm_unit1: + members: [person1] + heating_type: NATURAL_GAS + heat_expense_included_in_rent: true + mn_eap_housing_type: APARTMENT + spm_unit2: + members: [person2] + heating_type: NATURAL_GAS + heat_expense_included_in_rent: true + households: + household1: + members: [person1] + state_code: MN + household2: + members: [person2] + state_code: MN + output: + mn_eap_energy_cost: [1_554, 2_634] diff --git a/policyengine_us/tests/policy/baseline/gov/states/mn/commerce/eap/payment/mn_eap_pay_share.yaml b/policyengine_us/tests/policy/baseline/gov/states/mn/commerce/eap/payment/mn_eap_pay_share.yaml new file mode 100644 index 00000000000..d17072daf59 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/mn/commerce/eap/payment/mn_eap_pay_share.yaml @@ -0,0 +1,156 @@ +# Pay share = pay max - (pay max - pay min) x clip((percentile - slope start) / +# (slope end - slope start), 0, 1), with percentile = income / income limit +# (Appendix 4A Calculator!E2:G2). 'Formula Parameters'!C4:C7: FFY26 pay max +# 0.439, pay min 0.108, slope 0 to 0.896; FFY27 pay max 0.452, pay min 0.113, +# slope 0 to 0.891. Households whose only income is DWP, General Assistance, +# MFIP or SSI are placed at the lowest income level (FFY26 EAP Policy Manual, +# Chapter 3 "Qualified Eligibility"). + +# Zero income: percentile 0, pay max 0.439. +- name: Case 1, zero income gets the FFY2026 pay maximum. + period: 2026 + absolute_error_margin: 0.0001 + input: + people: + person1: + age: 36 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + pre_subsidy_electricity_expense: 900 + tanf: 0 + households: + household: + members: [person1] + state_code: MN + output: + mn_eap_pay_share: 0.439 + +# Zero income: percentile 0, pay max 0.452. +- name: Case 2, zero income gets the FFY2027 pay maximum. + period: 2027 + absolute_error_margin: 0.0001 + input: + people: + person1: + age: 36 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + pre_subsidy_electricity_expense: 900 + tanf: 0 + households: + household: + members: [person1] + state_code: MN + output: + mn_eap_pay_share: 0.452 + +# FFY26: $35,000 / $37,428 = 0.935, at or above the 0.896 slope end, so the +# pay minimum 0.108 applies. +- name: Case 3, a percentile above the FFY2026 slope end gets the pay minimum. + period: 2026 + absolute_error_margin: 0.0001 + input: + people: + person1: + age: 36 + employment_income: 35_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + pre_subsidy_electricity_expense: 900 + tanf: 0 + households: + household: + members: [person1] + state_code: MN + output: + mn_eap_pay_share: 0.108 + +# FFY27: $36,000 / $38,460 = 0.936, above the 0.891 slope end, so the pay +# minimum 0.113 applies. +- name: Case 4, a percentile above the FFY2027 slope end gets the pay minimum. + period: 2027 + absolute_error_margin: 0.0001 + input: + people: + person1: + age: 36 + employment_income: 36_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + pre_subsidy_electricity_expense: 900 + tanf: 0 + households: + household: + members: [person1] + state_code: MN + output: + mn_eap_pay_share: 0.113 + +# Qualified Eligibility: SSI of $11,928 ($994 x 12) is the only income, so the +# household is placed at the lowest income level and gets the pay max 0.439 +# (without it, $11,928 / $37,428 would give 0.321). +- name: Case 5, an SSI-only household gets the pay maximum under Qualified Eligibility. + period: 2026 + absolute_error_margin: 0.0001 + input: + people: + person1: + age: 67 + ssi: 11_928 + medicare_part_b_premium: 0 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 900 + pre_subsidy_electricity_expense: 800 + tanf: 0 + households: + household: + members: [person1] + state_code: MN + output: + mn_eap_countable_income: 11_928 + mn_eap_pay_share: 0.439 + +# Social Security of $6,000 ($500 a month) plus SSI of $6,168 ($994 - ($500 - +# $20) = $514 a month), with the Part B premium paid by the Medicare Savings +# Program: income $12,168 is not SSI-only, so the ordinary percentile applies: +# $12,168 / $37,428 = 0.3251042; 0.439 - 0.331 x 0.3251042 / 0.896 = +# 0.3189001. +- name: Case 6, an SSI and Social Security household uses the ordinary percentile. + period: 2026 + absolute_error_margin: 0.0001 + input: + people: + person1: + age: 70 + social_security_retirement: 6_000 + ssi: 6_168 + medicare_part_b_premium: 0 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 900 + pre_subsidy_electricity_expense: 800 + tanf: 0 + households: + household: + members: [person1] + state_code: MN + output: + mn_eap_countable_income: 12_168 + mn_eap_pay_share: 0.3189001 diff --git a/policyengine_us/variables/gov/states/mn/commerce/eap/eligibility/mn_eap_eligible.py b/policyengine_us/variables/gov/states/mn/commerce/eap/eligibility/mn_eap_eligible.py new file mode 100644 index 00000000000..78626204765 --- /dev/null +++ b/policyengine_us/variables/gov/states/mn/commerce/eap/eligibility/mn_eap_eligible.py @@ -0,0 +1,45 @@ +from policyengine_us.model_api import * + + +class mn_eap_eligible(Variable): + value_type = bool + entity = SPMUnit + definition_period = YEAR + label = "Minnesota EAP Primary Heat eligibility" + defined_for = StateCode.MN + reference = ( + # PDF pages 72, 80-81, 84, 88, 126 + "https://mn.gov/commerce-stat/pdfs/ffy26-eap-policy-manual.pdf#page=72", + # PDF pages 74, 82-83, 86, 90, 128 + "https://mn.gov/commerce-stat/pdfs/ffy27-eap-policy-manual.pdf#page=74", + # PDF pages 8-9 + "https://liheapch.acf.gov/docs/2026/state-plans/MN_Plan_2026.pdf#page=8", + ) + + def formula(spm_unit, period, parameters): + size = spm_unit("mn_eap_household_size", period) + income = spm_unit("mn_eap_countable_income", period) + limit = spm_unit("mn_eap_income_limit", period) + heating_type = spm_unit("heating_type", period) + types = heating_type.possible_values + heating_reported = (heating_type != types.UNSPECIFIED) & ( + heating_type != types.NONE + ) + # A household must be vulnerable to rising energy costs: it pays an + # energy vendor, or pays for heat through unsubsidized rent. Subsidized + # housing with heat in rent qualifies only when the household pays + # electricity, and is ineligible with heat and electricity included. + # Paying electricity is read from a positive electricity expense, so + # the $200 minimum for such a household with no electric usage is not + # modeled. + heat_in_rent = spm_unit("heat_expense_included_in_rent", period) + subsidized = spm_unit( + "receives_housing_assistance", period + ) | spm_unit.household("is_in_public_housing", period) + vulnerable = (heat_in_rent & ~subsidized) | ( + spm_unit("mn_eap_energy_cost", period) > 0 + ) + # No categorical eligibility or asset test applies. Residency duration, + # SSNs, dwelling eligibility, institutions, the application deadline + # and the one-grant-per-year rule are not modeled. + return (size > 0) & (income <= limit) & heating_reported & vulnerable diff --git a/policyengine_us/variables/gov/states/mn/commerce/eap/eligibility/mn_eap_income_limit.py b/policyengine_us/variables/gov/states/mn/commerce/eap/eligibility/mn_eap_income_limit.py new file mode 100644 index 00000000000..14f2b42f1fb --- /dev/null +++ b/policyengine_us/variables/gov/states/mn/commerce/eap/eligibility/mn_eap_income_limit.py @@ -0,0 +1,42 @@ +from policyengine_us.model_api import * +from policyengine_us.variables.gov.hhs.hhs_smi import smi +from policyengine_us.variables.gov.hhs.tax_unit_fpg import fpg + + +class mn_eap_income_limit(Variable): + value_type = float + entity = SPMUnit + definition_period = YEAR + unit = USD + label = "Minnesota EAP annual income limit" + defined_for = StateCode.MN + reference = ( + # PDF pages 88-89 + "https://mn.gov/commerce-stat/pdfs/ffy26-eap-policy-manual.pdf#page=88", + "https://mn.gov/commerce-stat/pdfs/ffy27-eap-policy-manual.pdf#page=90", + "https://liheapch.acf.gov/docs/2026/state-plans/MN_Plan_2026.pdf#page=8", + "https://www.law.cornell.edu/uscode/text/42/8624#b_2_B", + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.mn.commerce.eap.eligibility + p_hhs = parameters(period).gov.hhs.liheap + size = spm_unit("mn_eap_household_size", period) + state = spm_unit.household("state_code_str", period) + state_group = spm_unit.household("state_group_str", period) + # The tables use 50% of state median income for sizes 1 to 18 and 110% + # of the prior year's poverty guideline for sizes 19 and 20. The larger + # of the two reproduces all 40 FFY2026 and FFY2027 monthly cells, and + # 42 U.S.C. 8624(b)(2)(B) keeps the 110% floor above size 20, where + # the tables stop. Each monthly cell truncates the annual amount / 12. + smi_limit = np.floor( + np.round(smi(size, state, period, parameters) * p.smi_rate, 2) + / MONTHS_IN_YEAR + ) + guideline = fpg(size, state_group, period, parameters, year_lag=p.fpg_year_lag) + fpg_limit = np.floor(np.round(guideline * p_hhs.fpg_floor, 2) / MONTHS_IN_YEAR) + monthly_limit = max_(smi_limit, fpg_limit) + # Eligibility compares one month of income with the one-month limit, + # so the annual equivalent is twelve times that limit, not the + # published annual column. + return where(size > 0, monthly_limit * MONTHS_IN_YEAR, 0) diff --git a/policyengine_us/variables/gov/states/mn/commerce/eap/income/mn_eap_countable_income.py b/policyengine_us/variables/gov/states/mn/commerce/eap/income/mn_eap_countable_income.py new file mode 100644 index 00000000000..a01bfcd8cee --- /dev/null +++ b/policyengine_us/variables/gov/states/mn/commerce/eap/income/mn_eap_countable_income.py @@ -0,0 +1,77 @@ +from policyengine_us.model_api import * + + +class mn_eap_countable_income(Variable): + value_type = float + entity = SPMUnit + definition_period = YEAR + unit = USD + label = "Minnesota EAP annual countable income" + defined_for = StateCode.MN + reference = ( + # PDF pages 88-102, 107-108, 111 + "https://mn.gov/commerce-stat/pdfs/ffy26-eap-policy-manual.pdf#page=88", + # PDF pages 90-103, 109-110, 113, 116 + "https://mn.gov/commerce-stat/pdfs/ffy27-eap-policy-manual.pdf#page=90", + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.mn.commerce.eap.income + person = spm_unit.members + age = person("age", period) + # Gross income for one calendar month (prior-year self-employment + # profit / 12) is approximated by annual inputs; the eligibility test + # compares the annual total with 12 times the monthly limit. + earned = 0 + for source in p.sources.earned: + earned = earned + max_(person(source, period), 0) + unemployment = max_(person("total_unemployment_compensation", period), 0) + # Earnings and unemployment insurance of a person aged 19 or below in + # K-12, a diploma-granting or an equivalency program are not counted. + # is_in_k12_school does not identify equivalency programs. + student = (age <= p.student_age_limit) & person("is_in_k12_school", period) + earned_and_unemployment = where(student, 0, earned + unemployment) + unearned = 0 + for source in p.sources.unearned: + # ADD sums monthly sources such as ssi over the year. + unearned = unearned + max_(person(source, period, options=[ADD]), 0) + # Retirement payments count from age 59 1/2. Early benefits before that + # age count only when not penalized; no input shows whether a withdrawal + # was penalized, so the age cut-off approximates the penalty test. + distributions = where( + age >= p.retirement_age, + max_(person("retirement_distributions", period), 0), + 0, + ) + # Social Security counts net of the Medicare premium deducted from the + # check, and a pension (PERA) net of Medicare paid out of it. The Part B + # premium is subtracted once from the combined amount. No Part D + # premium input exists. + social_security = max_(person("social_security", period), 0) + pension = max_(person("pension_income", period), 0) + premium = person("medicare_part_b_premium", period) + net_social_security_and_pension = max_(social_security + pension - premium, 0) + person_income = spm_unit.sum( + earned_and_unemployment + + unearned + + distributions + + net_social_security_and_pension + ) + # Dividends, interest and royalties count only when the one-month + # equivalent is at least $50; cash gifts only when they total at least + # $100 in the eligibility month. Royalties have no separate input. + investment = 0 + for source in p.sources.investment: + investment = investment + spm_unit.sum(max_(person(source, period), 0)) + counted_investment = where( + investment / MONTHS_IN_YEAR >= p.investment_minimum, investment, 0 + ) + gifts = spm_unit.sum(max_(person("financial_assistance", period), 0)) + counted_gifts = where(gifts / MONTHS_IN_YEAR >= p.gift_minimum, gifts, 0) + # MFIP cash is part of tanf. The Diversionary Work Program, MFIP + # housing assistance grants, Housing Support, tribal per capita payments, + # irregular income, jury pay, inheritances and lump sums have no input. + # Child support, capital gains, student aid, Minnesota Supplemental Aid, + # foster care, tax refunds and SNAP are not counted. + tanf = max_(spm_unit("tanf", period), 0) + return person_income + counted_investment + counted_gifts + tanf diff --git a/policyengine_us/variables/gov/states/mn/commerce/eap/mn_eap.py b/policyengine_us/variables/gov/states/mn/commerce/eap/mn_eap.py new file mode 100644 index 00000000000..6df0bfda814 --- /dev/null +++ b/policyengine_us/variables/gov/states/mn/commerce/eap/mn_eap.py @@ -0,0 +1,39 @@ +from policyengine_us.model_api import * + + +class mn_eap(Variable): + value_type = float + entity = SPMUnit + definition_period = YEAR + unit = USD + label = "Minnesota EAP Primary Heat benefit" + documentation = ( + "Primary Heat is the single regular benefit of Minnesota's Energy " + "Assistance Program. It pays a share of the household's total home " + "energy cost, including non-heating electricity, between the minimum " + "and maximum benefit. Verified for FFY2026 and FFY2027; earlier years " + "use model parameter backfilling and are unverified historical " + "estimates. Crisis, Energy Related Repair and weatherization are out " + "of scope." + ) + defined_for = "mn_eap_eligible" + reference = ( + # PDF pages 117, 124-126 + "https://mn.gov/commerce-stat/pdfs/ffy26-eap-policy-manual.pdf#page=117", + # PDF pages 119, 126-128 + "https://mn.gov/commerce-stat/pdfs/ffy27-eap-policy-manual.pdf#page=119", + "https://liheapch.acf.gov/docs/2026/state-plans/MN_Plan_2026.pdf#page=9", + "https://liheapch.acf.gov/docs/2026/benefits-matricies/MN_BenefitMatrix_2026.xlsx", + "https://mn.gov/commerce-stat/xls/phb-calculator.xlsx", + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.mn.commerce.eap.payment + cost = spm_unit("mn_eap_energy_cost", period) + share = spm_unit("mn_eap_pay_share", period) + # Appendix 4A rounds the share times cost to whole dollars with Excel + # ROUND (halves away from zero), then applies the floor and ceiling. + # The floor applies at any positive cost; households without a cost + # basis (no backup matrix row) receive nothing. + amount = np.floor(share * cost + 0.5) + return where(cost > 0, clip(amount, p.minimum, p.maximum), 0) diff --git a/policyengine_us/variables/gov/states/mn/commerce/eap/mn_eap_household_size.py b/policyengine_us/variables/gov/states/mn/commerce/eap/mn_eap_household_size.py new file mode 100644 index 00000000000..bbcb0e3935f --- /dev/null +++ b/policyengine_us/variables/gov/states/mn/commerce/eap/mn_eap_household_size.py @@ -0,0 +1,21 @@ +from policyengine_us.model_api import * + + +class mn_eap_household_size(Variable): + value_type = int + entity = SPMUnit + definition_period = YEAR + label = "Minnesota EAP household size" + defined_for = StateCode.MN + reference = ( + # PDF pages 80-81 + "https://mn.gov/commerce-stat/pdfs/ffy26-eap-policy-manual.pdf#page=80", + # PDF pages 82-83 + "https://mn.gov/commerce-stat/pdfs/ffy27-eap-policy-manual.pdf#page=82", + "https://liheapch.acf.gov/docs/2026/state-plans/MN_Plan_2026.pdf#page=9", + ) + # SPM units approximate the economic unit that buys energy in common. + # Ineligible non-citizens are not counted, but their income counts in + # mn_eap_countable_income. Citizenship is approximated by the existing + # qualified-status flag; SSN and document checks are not modeled. + adds = ["is_citizen_or_legal_immigrant"] diff --git a/policyengine_us/variables/gov/states/mn/commerce/eap/payment/mn_eap_energy_cost.py b/policyengine_us/variables/gov/states/mn/commerce/eap/payment/mn_eap_energy_cost.py new file mode 100644 index 00000000000..ce3985c569b --- /dev/null +++ b/policyengine_us/variables/gov/states/mn/commerce/eap/payment/mn_eap_energy_cost.py @@ -0,0 +1,59 @@ +from policyengine_us.model_api import * + + +class mn_eap_energy_cost(Variable): + value_type = float + entity = SPMUnit + definition_period = YEAR + unit = USD + label = "Minnesota EAP annual energy cost" + defined_for = StateCode.MN + reference = ( + # PDF pages 117-119, 125-126 + "https://mn.gov/commerce-stat/pdfs/ffy26-eap-policy-manual.pdf#page=117", + # PDF pages 119-121, 127-128 + "https://mn.gov/commerce-stat/pdfs/ffy27-eap-policy-manual.pdf#page=119", + "https://liheapch.acf.gov/docs/2026/benefits-matricies/MN_BenefitMatrix_2026.xlsx", + "https://mn.gov/commerce-stat/xls/phb-calculator.xlsx", + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.mn.commerce.eap.payment + # Households paying their own energy use the total of all home energy + # bills, heating fuels and all electricity. Current-year expenses stand + # in for prior-year consumption; the eHEAT larger-of rule for partial + # data and lower-of rule for business use or shared meters are not + # modeled. Zero expense inputs mean no cost, so the backup-matrix + # fallback for an own-payer without consumption data is not modeled. + own_cost = add(spm_unit, period, p.energy_cost_sources) + electricity = spm_unit("pre_subsidy_electricity_expense", period) + heating_type = spm_unit("heating_type", period) + types = heating_type.possible_values + housing = spm_unit("mn_eap_housing_type", period) + # Heat included in rent uses the backup matrix for the primary fuel and + # housing type. No heating_type value identifies steam, district + # heating or metered propane, so those rows are not selected; wood, + # coal, solar and other fuels have no row. + backup_cost = select( + [ + (heating_type == types.FUEL_OIL) | (heating_type == types.KEROSENE), + heating_type == types.PROPANE, + heating_type == types.NATURAL_GAS, + heating_type == types.ELECTRICITY, + ], + [ + p.backup_cost.oil[housing], + p.backup_cost.propane[housing], + p.backup_cost.natural_gas[housing], + p.backup_cost.electricity[housing], + ], + default=0, + ) + heat_in_rent = spm_unit("heat_expense_included_in_rent", period) + # Section 8, public or tribal subsidized housing with heat in rent bases + # the benefit on electric costs. + subsidized = spm_unit( + "receives_housing_assistance", period + ) | spm_unit.household("is_in_public_housing", period) + rent_cost = where(subsidized, electricity, backup_cost) + return where(heat_in_rent, rent_cost, own_cost) diff --git a/policyengine_us/variables/gov/states/mn/commerce/eap/payment/mn_eap_housing_type.py b/policyengine_us/variables/gov/states/mn/commerce/eap/payment/mn_eap_housing_type.py new file mode 100644 index 00000000000..b16baa77c20 --- /dev/null +++ b/policyengine_us/variables/gov/states/mn/commerce/eap/payment/mn_eap_housing_type.py @@ -0,0 +1,34 @@ +from policyengine_us.model_api import * + + +class MNEAPHousingType(Enum): + APARTMENT = "Apartment" + DUPLEX = "Duplex" + TRIPLEX = "Triplex" + FOURPLEX = "Fourplex" + TOWNHOUSE = "Townhouse" + HOUSE = "House" + MOBILE_HOME = "Mobile home" + OTHER = "Other" + + +class mn_eap_housing_type(Variable): + value_type = Enum + entity = SPMUnit + possible_values = MNEAPHousingType + default_value = MNEAPHousingType.HOUSE + definition_period = YEAR + label = "Minnesota EAP housing type" + documentation = ( + "Housing type column of the Minnesota EAP backup matrix, used for " + "households with heat included in rent. If omitted, the model assumes " + "a house; report the type to apply the matching average energy cost." + ) + defined_for = StateCode.MN + reference = ( + # PDF pages 125-126 + "https://mn.gov/commerce-stat/pdfs/ffy26-eap-policy-manual.pdf#page=125", + # PDF pages 127-128 + "https://mn.gov/commerce-stat/pdfs/ffy27-eap-policy-manual.pdf#page=127", + "https://mn.gov/commerce-stat/xls/phb-calculator.xlsx", + ) diff --git a/policyengine_us/variables/gov/states/mn/commerce/eap/payment/mn_eap_pay_share.py b/policyengine_us/variables/gov/states/mn/commerce/eap/payment/mn_eap_pay_share.py new file mode 100644 index 00000000000..2adbc28ecb3 --- /dev/null +++ b/policyengine_us/variables/gov/states/mn/commerce/eap/payment/mn_eap_pay_share.py @@ -0,0 +1,44 @@ +from policyengine_us.model_api import * + + +class mn_eap_pay_share(Variable): + value_type = float + entity = SPMUnit + definition_period = YEAR + unit = "/1" + label = "Minnesota EAP share of energy cost paid" + defined_for = StateCode.MN + reference = ( + # PDF pages 102, 124 + "https://mn.gov/commerce-stat/pdfs/ffy26-eap-policy-manual.pdf#page=102", + # PDF pages 103, 126 + "https://mn.gov/commerce-stat/pdfs/ffy27-eap-policy-manual.pdf#page=103", + "https://liheapch.acf.gov/docs/2026/benefits-matricies/MN_BenefitMatrix_2026.xlsx", + "https://mn.gov/commerce-stat/xls/phb-calculator.xlsx", + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.mn.commerce.eap + share = p.payment.share + income = spm_unit("mn_eap_countable_income", period) + limit = spm_unit("mn_eap_income_limit", period) + # Qualified Eligibility places households whose only income is DWP, + # General Assistance, MFIP or SSI at the lowest income level, read here + # as an income percentile of zero. Amounts are compared to the cent so + # that summation order does not decide the test. + qualified_income = add(spm_unit, period, p.income.qualified_eligibility_sources) + qualified_only = (qualified_income > 0) & ( + np.round(income, 2) <= np.round(qualified_income, 2) + ) + # The income percentile is income over the limit for the household + # size; annual equivalents give the same ratio as monthly amounts. + ratio = np.divide(income, limit, out=np.zeros_like(income), where=limit > 0) + percentile = where(qualified_only, 0, ratio) + # Appendix 4A pays the maximum share up to the slope start, falls + # linearly to the minimum share at the slope end, and stays there. + progress = clip( + (percentile - share.slope_start) / (share.slope_end - share.slope_start), + 0, + 1, + ) + return share.maximum - (share.maximum - share.minimum) * progress diff --git a/policyengine_us/variables/household/income/person/general/pfml_benefits.py b/policyengine_us/variables/household/income/person/general/pfml_benefits.py index 83cca0df964..df5ebc4de24 100644 --- a/policyengine_us/variables/household/income/person/general/pfml_benefits.py +++ b/policyengine_us/variables/household/income/person/general/pfml_benefits.py @@ -1,7 +1,6 @@ from policyengine_us.model_api import * -# Note that right now this variable is only used for MA CCFA. class pfml_benefits(Variable): value_type = float entity = Person From 4b335140adbf178f3b5fe7c41068f35b20419747 Mon Sep 17 00:00:00 2001 From: Ziming Date: Wed, 28 Oct 2026 20:10:30 -0400 Subject: [PATCH 2/2] Address review round 1 for Minnesota LIHEAP Apply DTrim99's round 1 review: tests that pin every income source, the rule and documentation fixes, and source-conflict candidates. Co-Authored-By: Claude Opus 5.5 --- .../mn/commerce/eap/eligibility/smi_rate.yaml | 2 +- .../commerce/eap/income/sources/unearned.yaml | 9 +- .../eap/eligibility/mn_eap_eligible.yaml | 27 ++++++ .../eap/income/mn_eap_countable_income.yaml | 93 +++++++++++++++++++ .../gov/states/mn/commerce/eap/mn_eap.yaml | 46 +++++++++ .../eap/payment/mn_eap_energy_cost.yaml | 23 +++++ .../eap/income/mn_eap_countable_income.py | 28 +++--- source_conflicts/candidates.yaml | 29 ++++++ 8 files changed, 239 insertions(+), 18 deletions(-) diff --git a/policyengine_us/parameters/gov/states/mn/commerce/eap/eligibility/smi_rate.yaml b/policyengine_us/parameters/gov/states/mn/commerce/eap/eligibility/smi_rate.yaml index cd1ed06fa04..506eed14743 100644 --- a/policyengine_us/parameters/gov/states/mn/commerce/eap/eligibility/smi_rate.yaml +++ b/policyengine_us/parameters/gov/states/mn/commerce/eap/eligibility/smi_rate.yaml @@ -1,4 +1,4 @@ -description: Minnesota limits Energy Assistance Program income to this share of state median income. +description: Minnesota limits income to this share of state median income under the Energy Assistance Program. # The published tables apply this rate for household sizes 1 to 18. Larger # households use 110% of the poverty guideline (gov.hhs.liheap.fpg_floor). values: diff --git a/policyengine_us/parameters/gov/states/mn/commerce/eap/income/sources/unearned.yaml b/policyengine_us/parameters/gov/states/mn/commerce/eap/income/sources/unearned.yaml index 3e8c229db90..f6af0ead915 100644 --- a/policyengine_us/parameters/gov/states/mn/commerce/eap/income/sources/unearned.yaml +++ b/policyengine_us/parameters/gov/states/mn/commerce/eap/income/sources/unearned.yaml @@ -1,14 +1,13 @@ description: Minnesota counts these sources as unearned income under the Energy Assistance Program. values: 2025-10-01: - # The formula counts Social Security and pensions net of the Medicare Part B - # premium, unemployment compensation with the student exclusion, retirement - # account distributions from age 59 1/2, and MFIP and other TANF cash - # through the SPM unit tanf variable. + # The formula counts Social Security, railroad retirement and pensions net + # of the Medicare Part A and Part B premiums, unemployment compensation with + # the student exclusion, retirement account distributions from age 59 1/2, + # and MFIP and other TANF cash through the SPM unit tanf variable. - ssi - general_assistance - military_retirement_income - - railroad_benefits - veterans_benefits - workers_compensation - disability_benefits diff --git a/policyengine_us/tests/policy/baseline/gov/states/mn/commerce/eap/eligibility/mn_eap_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/mn/commerce/eap/eligibility/mn_eap_eligible.yaml index 9563fe3f838..79095685a76 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mn/commerce/eap/eligibility/mn_eap_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mn/commerce/eap/eligibility/mn_eap_eligible.yaml @@ -186,3 +186,30 @@ output: mn_eap_household_size: 0 mn_eap_eligible: false + +# Public housing with heat included in rent and no electric bill: wages of +# $18,000 are under the $37,428 size 1 limit and natural gas is reported, but +# the rent is subsidized, so heat in rent does not make the household +# vulnerable and its energy cost is the $0 electric bill: ineligible. Read as +# unsubsidized, the same household would be eligible on the backup matrix. +- name: Case 6, public housing with heat in rent and no electric bill is ineligible. + period: 2026 + input: + people: + person1: + age: 40 + employment_income_before_lsr: 18_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + heat_expense_included_in_rent: true + tanf: 0 + households: + household: + members: [person1] + state_code: MN + is_in_public_housing: true + output: + mn_eap_energy_cost: 0 + mn_eap_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/mn/commerce/eap/income/mn_eap_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/mn/commerce/eap/income/mn_eap_countable_income.yaml index edabc5705fc..55486e920ce 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mn/commerce/eap/income/mn_eap_countable_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mn/commerce/eap/income/mn_eap_countable_income.yaml @@ -284,3 +284,96 @@ output: mn_eap_countable_income: 39_000 mn_eap_eligible: false + +# Railroad retirement and a PERA pension count net of the Medicare premiums, +# subtracted once from the combined Social Security, railroad and pension +# amount. Unit 1: $38,000 railroad annuity - $2,434.80 Part B ($202.90 x 12; +# Part A is premium-free with the default 40 quarters) = $35,565.20, under the +# FFY26 size 1 limit of $37,428 (the gross $38,000 would be over it). +# Percentile 35,565.20 / 37,428 = 0.9502, past the 0.896 slope end, so the +# share is 0.108: 0.108 x ($1,000 gas + $1,000 electricity) = $216. Unit 2: +# $30,000 PERA pension - $2,434.80 Part B - $3,732 Part A (2026 reduced +# premium $311 x 12) = $23,833.20; 23,833.20 / 37,428 = 0.6367746; share +# 0.439 - 0.331 x 0.6367746 / 0.896 = 0.2037630; 0.2037630 x $2,000 = +# $407.53 -> $408. +- name: Case 10, railroad retirement and a pension count net of Medicare Part A and Part B premiums. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + railroad_benefits: 38_000 + medicare_part_b_premium: 2_434.8 + ssi: 0 + person2: + age: 70 + taxable_public_pension_income: 30_000 + medicare_part_b_premium: 2_434.8 + medicare_part_a_premium: 3_732 + ssi: 0 + spm_units: + spm_unit1: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + pre_subsidy_electricity_expense: 1_000 + tanf: 0 + spm_unit2: + members: [person2] + heating_type: NATURAL_GAS + gas_expense: 1_000 + pre_subsidy_electricity_expense: 1_000 + tanf: 0 + households: + household1: + members: [person1] + state_code: MN + household2: + members: [person2] + state_code: MN + output: + mn_eap_countable_income: [35_565.2, 23_833.2] + mn_eap_eligible: [true, true] + mn_eap: [216, 408] + +# Each earned and unearned list source gets a distinct amount, so dropping any +# entry lowers the total. Earned: $1,000 self-employment + $2,000 SSTB +# self-employment + $3,000 partnership + $4,000 farm operations + $5,000 farm +# rent + $6,000 rental = $21,000. Unearned: $7,000 military retirement + +# $8,000 workers' compensation + $9,000 employment disability + $10,000 +# alimony + $11,000 strike benefits + $12,000 trust income + $13,000 survivor +# benefits = $70,000. Total $21,000 + $70,000 = $91,000. +- name: Case 11, every earned and unearned list source counts. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 45 + self_employment_income_before_lsr: 1_000 + sstb_self_employment_income_before_lsr: 2_000 + partnership_income: 3_000 + farm_operations_income: 4_000 + farm_rent_income: 5_000 + rental_income: 6_000 + person2: + age: 44 + military_retirement_pay: 7_000 + workers_compensation: 8_000 + disability_benefits: 9_000 + alimony_income: 10_000 + strike_benefits: 11_000 + estate_income: 12_000 + survivor_benefits: 13_000 + spm_units: + spm_unit: + members: [person1, person2] + heating_type: NATURAL_GAS + tanf: 0 + households: + household: + members: [person1, person2] + state_code: MN + output: + mn_eap_countable_income: 91_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/mn/commerce/eap/mn_eap.yaml b/policyengine_us/tests/policy/baseline/gov/states/mn/commerce/eap/mn_eap.yaml index 6d249b75361..50a298fba17 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mn/commerce/eap/mn_eap.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mn/commerce/eap/mn_eap.yaml @@ -243,3 +243,49 @@ mn_eap_eligible: true mn_eap_pay_share: 0.2477383 mn_eap: 828 + +# Qualified Eligibility places households whose only income is General +# Assistance or MFIP at an income percentile of 0, so the FFY26 pay maximum +# 0.439 applies. Unit 1: General Assistance $4,200 ($350 a month); $800 gas + +# $700 electricity = $1,500; 0.439 x $1,500 = $658.50, which rounds half up to +# $659 (half to even would give $658). Unit 2: parent and child with MFIP cash +# of $7,800 ($650 a month); $900 gas + $800 electricity = $1,700; 0.439 x +# $1,700 = $746.30 -> $746. Under the ordinary percentile the shares would be +# 4,200 / 37,428 -> 0.3975 ($596) and 7,800 / 48,948 (size 2 limit $4,079 x +# 12) -> 0.3801 ($646). +- name: Case 9, General Assistance-only and MFIP-only households get the pay maximum and a half-dollar benefit rounds up. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 45 + general_assistance: 4_200 + person2: + age: 27 + person3: + age: 4 + spm_units: + spm_unit1: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 800 + pre_subsidy_electricity_expense: 700 + tanf: 0 + spm_unit2: + members: [person2, person3] + heating_type: NATURAL_GAS + gas_expense: 900 + pre_subsidy_electricity_expense: 800 + tanf: 7_800 + households: + household1: + members: [person1] + state_code: MN + household2: + members: [person2, person3] + state_code: MN + output: + mn_eap_countable_income: [4_200, 7_800] + mn_eap_pay_share: [0.439, 0.439] + mn_eap: [659, 746] diff --git a/policyengine_us/tests/policy/baseline/gov/states/mn/commerce/eap/payment/mn_eap_energy_cost.yaml b/policyengine_us/tests/policy/baseline/gov/states/mn/commerce/eap/payment/mn_eap_energy_cost.yaml index 5d2e91b0b63..daa3d7ba6a3 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mn/commerce/eap/payment/mn_eap_energy_cost.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mn/commerce/eap/payment/mn_eap_energy_cost.yaml @@ -174,3 +174,26 @@ state_code: MN output: mn_eap_energy_cost: [1_554, 2_634] + +# Own bills for an oil-heated home with a coal stove and another fuel: +# $1,600 fuel oil + $400 coal + $200 other heating fuel = $2,200. +- name: Case 6, fuel oil, coal and other fuel bills are summed. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 58 + spm_units: + spm_unit: + members: [person1] + heating_type: FUEL_OIL + fuel_oil_expense: 1_600 + coal_expense: 400 + other_heating_fuel_expense: 200 + households: + household: + members: [person1] + state_code: MN + output: + mn_eap_energy_cost: 2_200 diff --git a/policyengine_us/variables/gov/states/mn/commerce/eap/income/mn_eap_countable_income.py b/policyengine_us/variables/gov/states/mn/commerce/eap/income/mn_eap_countable_income.py index a01bfcd8cee..db60d91817f 100644 --- a/policyengine_us/variables/gov/states/mn/commerce/eap/income/mn_eap_countable_income.py +++ b/policyengine_us/variables/gov/states/mn/commerce/eap/income/mn_eap_countable_income.py @@ -9,10 +9,11 @@ class mn_eap_countable_income(Variable): label = "Minnesota EAP annual countable income" defined_for = StateCode.MN reference = ( - # PDF pages 88-102, 107-108, 111 + # PDF pages 88-102, 107-108, 110-111 "https://mn.gov/commerce-stat/pdfs/ffy26-eap-policy-manual.pdf#page=88", - # PDF pages 90-103, 109-110, 113, 116 + # PDF pages 90-103, 109-110, 112-113, 116 "https://mn.gov/commerce-stat/pdfs/ffy27-eap-policy-manual.pdf#page=90", + "https://www.rrb.gov/RB30/DeductionsforOtherFederalPrograms/MedicareCoverage", ) def formula(spm_unit, period, parameters): @@ -43,19 +44,22 @@ def formula(spm_unit, period, parameters): max_(person("retirement_distributions", period), 0), 0, ) - # Social Security counts net of the Medicare premium deducted from the - # check, and a pension (PERA) net of Medicare paid out of it. The Part B - # premium is subtracted once from the combined amount. No Part D - # premium input exists. + # Social Security and railroad retirement count net of the Medicare + # premiums withheld from the check, and a pension (PERA) net of Medicare + # paid out of it. Part A and Part B premiums are subtracted once from the + # combined amount; Social Security and railroad annuitants have + # premium-free Part A. No Part D premium input exists. social_security = max_(person("social_security", period), 0) pension = max_(person("pension_income", period), 0) - premium = person("medicare_part_b_premium", period) - net_social_security_and_pension = max_(social_security + pension - premium, 0) + railroad = max_(person("railroad_benefits", period), 0) + premiums = add( + person, period, ["medicare_part_a_premium", "medicare_part_b_premium"] + ) + net_retirement_benefits = max_( + social_security + pension + railroad - premiums, 0 + ) person_income = spm_unit.sum( - earned_and_unemployment - + unearned - + distributions - + net_social_security_and_pension + earned_and_unemployment + unearned + distributions + net_retirement_benefits ) # Dividends, interest and royalties count only when the one-month # equivalent is at least $50; cash gifts only when they total at least diff --git a/source_conflicts/candidates.yaml b/source_conflicts/candidates.yaml index 843ddcbe21c..34b2f3332a1 100644 --- a/source_conflicts/candidates.yaml +++ b/source_conflicts/candidates.yaml @@ -3336,6 +3336,35 @@ candidates: state: unreviewed note: PE-US follows the manual and surrounding report editions; obtain contemporaneous BEM 556 for October 2022-September 2023. +- id: us-mn:liheap-plan-income-checklist + program: liheap + years: + from: 2026 + to: 2026 + type: federal-fiscal + question: Do foster care payments, minors' earnings and insurance wage replacement count for Minnesota EAP as the + manual provides or as the FY2026 plan checklist marks them? + sources: + - kind: manual + citation: Minnesota EAP Policy Manual FFY26, Chapter 3, Income Inclusions and Exclusions, PDF pages 91-92 and 99 + url: https://mn.gov/commerce-stat/pdfs/ffy26-eap-policy-manual.pdf#page=91 + - kind: plan + citation: Minnesota FY2026 LIHEAP State Plan, section 1.9, PDF pages 6-7 + url: https://liheapch.acf.gov/docs/2026/state-plans/MN_Plan_2026.pdf#page=6 + readings: + statute: No statute is supplied; the manual excludes foster care payments, counts minors' earnings unless they are + K-12 students aged 19 or under, and counts workers' compensation and wage-replacement disability pay. + other: The plan checks funds for the care of a foster child and leaves earned income of a child under 18 and + insurance payments made directly to the insured unchecked. + example: $6,000 of wages of a 17-year-old not in school counts $6,000 under the manual and $0 under the plan. + pe_us: + follows: gap-fill + code: [] + prs: + - https://github.com/PolicyEngine/policyengine-us/pull/10433 + state: ruled + note: 'Ruled 2026-10-06: follow the manual over the plan. Code not yet on main: mn_eap_countable_income, + gov.states.mn.commerce.eap.income.sources.' - id: us-mn:msa-guardian-fee-cap program: minnesota-supplemental-aid years: