diff --git a/changelog.d/mo-liheap-wave1d.added.md b/changelog.d/mo-liheap-wave1d.added.md new file mode 100644 index 00000000000..5a78d2cf416 --- /dev/null +++ b/changelog.d/mo-liheap-wave1d.added.md @@ -0,0 +1 @@ +Add Missouri LIHEAP Energy Assistance for regular heating (FY2026-FY2027). diff --git a/policyengine_us/parameters/gov/states/mo/dss/liheap/amount.yaml b/policyengine_us/parameters/gov/states/mo/dss/liheap/amount.yaml new file mode 100644 index 00000000000..1d980453293 --- /dev/null +++ b/policyengine_us/parameters/gov/states/mo/dss/liheap/amount.yaml @@ -0,0 +1,55 @@ +description: Missouri provides this one-time Energy Assistance payment by primary heating fuel under the Low Income Home Energy Assistance Program. +# The same amounts appear in the October 2025 manual (its Appendix K), the +# FFY2026 Appendix K matrix and the FFY2027 application. 13 CSR 40-19.020(14) +# bases payments on household size, income range and fuel source, using +# metrics established by the division, and prints a 2017 table of payments +# that decline across income ranges from 0 to 135 percent of the poverty level. +# The FFY2026 plan, the Appendix K matrix, the October 2025 manual and the +# 8-2026 application set one amount per fuel for incomes up to 60 percent of +# state median income; the model applies those amounts. +NATURAL_GAS: + 2023-10-01: 326 +# Tank propane. The schedule also pays $177 for cylinder propane, which is not +# reachable because heating_type has a single propane value. +PROPANE: + 2023-10-01: 495 +ELECTRICITY: + 2023-10-01: 318 +FUEL_OIL: + 2023-10-01: 326 +WOOD: + 2023-10-01: 219 +KEROSENE: + 2023-10-01: 153 +# Solar-heated homes are paid on their electric account at the electric amount. +SOLAR: + 2023-10-01: 318 +# Households that heat with coal are denied (October 2025 manual Appendix E, +# denial code O); mo_liheap_eligible applies that denial. +COAL: + 2023-10-01: 0 +# The schedule has no row for other fuels. +OTHER: + 2023-10-01: 0 +NONE: + 2023-10-01: 0 +UNSPECIFIED: + 2023-10-01: 0 + +metadata: + unit: currency-USD + period: year + label: Missouri LIHEAP Energy Assistance amount by heating fuel + breakdown: + - heating_type + reference: + - title: "13 CSR 40-19.020(3)(A) and (4) #page 2-3" + href: https://www.sos.mo.gov/cmsimages/adrules/csr/current/13csr/13c40-19.pdf#page=2 + - title: Missouri LIHEAP FFY2026 State Plan, Sections 2.5 and 2.6 + href: https://liheapch.acf.gov/docs/2026/state-plans/MO_Plan_2026.pdf#page=9 + - title: Missouri LIHEAP FFY2026 Appendix K, Income Ranges and Benefit Amounts + href: https://liheapch.acf.gov/docs/2026/benefits-matricies/MO_BenefitMatrix_2026.docx + - title: Missouri LIHEAP application MO 886-4576 (8-2026), Program Description + href: https://dssmanuals.mo.gov/wp-content/uploads/2022/02/liheap-application.pdf#page=1 + - title: "Missouri LIHEAP Policy and Procedure Manual (October 2025), Appendix E and Appendix K #page 122,129" + href: https://dss.mo.gov/sites/mydss/files/media/pdf/2025/10/liheap-policy-procedure-manual.pdf#page=122 diff --git a/policyengine_us/parameters/gov/states/mo/dss/liheap/eligibility/fpg_year_lag.yaml b/policyengine_us/parameters/gov/states/mo/dss/liheap/eligibility/fpg_year_lag.yaml new file mode 100644 index 00000000000..e29cf5e154b --- /dev/null +++ b/policyengine_us/parameters/gov/states/mo/dss/liheap/eligibility/fpg_year_lag.yaml @@ -0,0 +1,17 @@ +description: Missouri uses the federal poverty guidelines from this many years before the model year for the federal income floor under the Low Income Home Energy Assistance Program. +# HHS made the 2025 guidelines mandatory for LIHEAP from October 1, 2025, so +# model period 2026 (FFY2026) uses the 2025 guidelines and 2027 (FFY2027) the +# 2026 guidelines. Backfilled years use their lagged guidelines and are +# unverified. +values: + 2025-10-01: 1 + +metadata: + unit: year + period: year + label: Missouri LIHEAP poverty guideline year lag + reference: + - 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/mo/dss/liheap/eligibility/resource_limit.yaml b/policyengine_us/parameters/gov/states/mo/dss/liheap/eligibility/resource_limit.yaml new file mode 100644 index 00000000000..2069a8d678d --- /dev/null +++ b/policyengine_us/parameters/gov/states/mo/dss/liheap/eligibility/resource_limit.yaml @@ -0,0 +1,21 @@ +description: Missouri limits household resources to this amount under the Low Income Home Energy Assistance Program. +# Applied to spm_unit_cash_assets. Individual retirement accounts, Keogh plans, +# deferred compensation plans and annuities (13 CSR 40-19.020(2)(N); the +# October 2025 manual's list omits annuities) count as resources but lack +# asset inputs. +values: + 2017-05-30: 3_000 + +metadata: + unit: currency-USD + period: year + label: Missouri LIHEAP resource limit + reference: + - title: "13 CSR 40-19.020(2)(N) and (6)(B) #page 2-3" + href: https://www.sos.mo.gov/cmsimages/adrules/csr/current/13csr/13c40-19.pdf#page=2 + - title: Missouri LIHEAP FFY2026 State Plan, Section 2.3 + href: https://liheapch.acf.gov/docs/2026/state-plans/MO_Plan_2026.pdf#page=8 + - title: Missouri LIHEAP Policy and Procedure Manual (October 2025), Resources + href: https://dss.mo.gov/sites/mydss/files/media/pdf/2025/10/liheap-policy-procedure-manual.pdf#page=40 + - title: Missouri DSS draft FFY2027 LIHEAP State Plan (report status Saved with Errors), Section 2.3 + href: https://dss.mo.gov/sites/mydss/files/media/pdf/2026/08/liheap-active-ffy2027.pdf#page=8 diff --git a/policyengine_us/parameters/gov/states/mo/dss/liheap/eligibility/smi_rate.yaml b/policyengine_us/parameters/gov/states/mo/dss/liheap/eligibility/smi_rate.yaml new file mode 100644 index 00000000000..017049e473e --- /dev/null +++ b/policyengine_us/parameters/gov/states/mo/dss/liheap/eligibility/smi_rate.yaml @@ -0,0 +1,25 @@ +description: Missouri limits household income to this share of the state median income under the Low Income Home Energy Assistance Program. +# The published monthly limits equal the HHS LIHEAP limit for the household +# size divided by twelve and rounded to the nearest dollar (FFY2026 sizes 1-20, +# FFY2027 sizes 1-10). 13 CSR 40-19.020(6)(D) refers to the income ranges of +# section (14), a 2017 table that runs from 0 to 135 percent of the poverty +# level; the FFY2026 plan, Appendix K, the October 2025 manual and the 8-2026 +# application set this share of state median income. +values: + 2023-10-01: 0.6 + +metadata: + unit: /1 + period: year + label: Missouri LIHEAP state median income rate + reference: + - title: Missouri LIHEAP FFY2026 State Plan, Section 2.1 + href: https://liheapch.acf.gov/docs/2026/state-plans/MO_Plan_2026.pdf#page=8 + - title: Missouri LIHEAP FFY2026 Appendix K, Income Ranges and Benefit Amounts + href: https://liheapch.acf.gov/docs/2026/benefits-matricies/MO_BenefitMatrix_2026.docx + - title: Missouri LIHEAP application MO 886-4576 (8-2026), Program Description + href: https://dssmanuals.mo.gov/wp-content/uploads/2022/02/liheap-application.pdf#page=1 + - title: Missouri LIHEAP Policy and Procedure Manual (October 2025), Appendix K + href: https://dss.mo.gov/sites/mydss/files/media/pdf/2025/10/liheap-policy-procedure-manual.pdf#page=129 + - title: Missouri DSS draft FFY2027 LIHEAP State Plan (report status Saved with Errors), Section 2.1 + href: https://dss.mo.gov/sites/mydss/files/media/pdf/2026/08/liheap-active-ffy2027.pdf#page=8 diff --git a/policyengine_us/parameters/gov/states/mo/dss/liheap/income/adult_age.yaml b/policyengine_us/parameters/gov/states/mo/dss/liheap/income/adult_age.yaml new file mode 100644 index 00000000000..1777fc462ce --- /dev/null +++ b/policyengine_us/parameters/gov/states/mo/dss/liheap/income/adult_age.yaml @@ -0,0 +1,22 @@ +description: Missouri excludes the earned income and the disability income of household members below this age under the Low Income Home Energy Assistance Program. +# The October 2025 manual leaves out the earned income and the disability +# income of a household member under 18 but counts the member's SSA income +# (adult_unearned_sources lists the disability payments). The FFY2026 plan does +# not count the earned income of a child under 18, and the 8-2026 application +# asks for job income only from members 18 or older. +values: + 2023-10-01: 18 + +metadata: + unit: year + period: year + label: Missouri LIHEAP adult age + reference: + - title: Missouri LIHEAP FFY2026 State Plan, Section 1.9 + href: https://liheapch.acf.gov/docs/2026/state-plans/MO_Plan_2026.pdf#page=6 + - title: Missouri LIHEAP application MO 886-4576 (8-2026), Part 5 Household Income + href: https://dssmanuals.mo.gov/wp-content/uploads/2022/02/liheap-application.pdf#page=4 + - title: Missouri LIHEAP Policy and Procedure Manual (October 2025), Earnings of Children + href: https://dss.mo.gov/sites/mydss/files/media/pdf/2025/10/liheap-policy-procedure-manual.pdf#page=38 + - title: Missouri DSS draft FFY2027 LIHEAP State Plan (report status Saved with Errors), Section 1.9 + href: https://dss.mo.gov/sites/mydss/files/media/pdf/2026/08/liheap-active-ffy2027.pdf#page=6 diff --git a/policyengine_us/parameters/gov/states/mo/dss/liheap/income/adult_unearned_sources.yaml b/policyengine_us/parameters/gov/states/mo/dss/liheap/income/adult_unearned_sources.yaml new file mode 100644 index 00000000000..8d64b06c09f --- /dev/null +++ b/policyengine_us/parameters/gov/states/mo/dss/liheap/income/adult_unearned_sources.yaml @@ -0,0 +1,19 @@ +description: Missouri counts these unearned income sources only for household members at or above the adult age under the Low Income Home Energy Assistance Program. +# The October 2025 manual does not count the unearned income from disability +# of a household member under 18 but counts the member's SSA income. Social +# Security and SSI are read as SSA income and count at any age. +# disability_benefits (employment-based disability payments other than Social +# Security and workers' compensation) stands in for the manual's short- and +# long-term disability payments; workers' compensation and veterans benefits +# count at any age (unearned_sources). +values: + 2025-10-01: + - disability_benefits + +metadata: + unit: list + period: year + label: Missouri LIHEAP adult-only unearned income sources + reference: + - title: "Missouri LIHEAP Policy and Procedure Manual (October 2025), Unearned Income and Earnings of Children #page 34,38" + href: https://dss.mo.gov/sites/mydss/files/media/pdf/2025/10/liheap-policy-procedure-manual.pdf#page=34 diff --git a/policyengine_us/parameters/gov/states/mo/dss/liheap/income/disability_benefit_sources.yaml b/policyengine_us/parameters/gov/states/mo/dss/liheap/income/disability_benefit_sources.yaml new file mode 100644 index 00000000000..aece6789354 --- /dev/null +++ b/policyengine_us/parameters/gov/states/mo/dss/liheap/income/disability_benefit_sources.yaml @@ -0,0 +1,35 @@ +description: Missouri treats a totally and permanently disabled or blind individual as disabled for the medical deduction when the individual receives one of these benefits under the Low Income Home Energy Assistance Program. +# The medical deduction also requires the member to be disabled or blind. With +# that requirement, the general veterans and railroad benefit inputs stand in +# for Veterans Administration and Railroad Retirement disability benefits, and +# the general Social Security dependents and survivors inputs stand in for +# disabled adult child and disabled widow(er) benefits. These four inputs also +# include benefits a disabled member receives for reasons other than +# disability, such as Social Security spousal, aged survivor or child-in-care +# benefits or a railroad age-and-service annuity, since no input separates +# them. Civil Service Disability and Black Lung benefits have no separate +# inputs. +values: + 2017-05-30: + - ssi + - social_security_disability + # General dependents and survivors benefits; see the note above. + - social_security_dependents + - social_security_survivors + - veterans_benefits + - railroad_benefits + # Medical Assistance (MO HealthNet). + - medicaid + # State Supplemental Payments, State Aid to the Blind and State Blind + # Pension. + - mo_ssp + +metadata: + unit: list + period: year + label: Missouri LIHEAP disability benefit sources + reference: + - title: 13 CSR 40-19.020(2)(C) + href: https://www.sos.mo.gov/cmsimages/adrules/csr/current/13csr/13c40-19.pdf#page=2 + - title: "Missouri LIHEAP Policy and Procedure Manual (October 2025), Medical Deduction for Elderly-Disabled and Disability #page 36,48" + href: https://dss.mo.gov/sites/mydss/files/media/pdf/2025/10/liheap-policy-procedure-manual.pdf#page=36 diff --git a/policyengine_us/parameters/gov/states/mo/dss/liheap/income/earned_income_deduction_rate.yaml b/policyengine_us/parameters/gov/states/mo/dss/liheap/income/earned_income_deduction_rate.yaml new file mode 100644 index 00000000000..1c1cf974dcd --- /dev/null +++ b/policyengine_us/parameters/gov/states/mo/dss/liheap/income/earned_income_deduction_rate.yaml @@ -0,0 +1,11 @@ +description: Missouri deducts this share of earned income in determining countable income under the Low Income Home Energy Assistance Program. +values: + 2023-10-01: 0.2 + +metadata: + unit: /1 + period: year + label: Missouri LIHEAP earned income deduction rate + reference: + - title: "Missouri LIHEAP Policy and Procedure Manual (October 2025), Self-Employment-Partnership Income and Income Deductions #page 32,36" + href: https://dss.mo.gov/sites/mydss/files/media/pdf/2025/10/liheap-policy-procedure-manual.pdf#page=32 diff --git a/policyengine_us/parameters/gov/states/mo/dss/liheap/income/earned_sources.yaml b/policyengine_us/parameters/gov/states/mo/dss/liheap/income/earned_sources.yaml new file mode 100644 index 00000000000..5ecfa754439 --- /dev/null +++ b/policyengine_us/parameters/gov/states/mo/dss/liheap/income/earned_sources.yaml @@ -0,0 +1,21 @@ +description: Missouri counts these earned income sources, after the earned income deduction, under the Low Income Home Energy Assistance Program. +# Each source is floored at zero: business and farm losses do not offset other +# income. Net business income inputs stand in for the Form 1040 business lines. +# Roomer and boarder income is also earned income but has no input. +values: + 2023-10-01: + - employment_income + - self_employment_income + - sstb_self_employment_income + - farm_operations_income + - partnership_s_corp_income + +metadata: + unit: list + period: year + label: Missouri LIHEAP earned income sources + reference: + - title: "Missouri LIHEAP FFY2026 State Plan, Sections 1.8 and 1.9 #page 5-7" + href: https://liheapch.acf.gov/docs/2026/state-plans/MO_Plan_2026.pdf#page=5 + - title: "Missouri LIHEAP Policy and Procedure Manual (October 2025), Self-Employment-Partnership Income and Income Deductions #page 32,36" + href: https://dss.mo.gov/sites/mydss/files/media/pdf/2025/10/liheap-policy-procedure-manual.pdf#page=32 diff --git a/policyengine_us/parameters/gov/states/mo/dss/liheap/income/elderly_age.yaml b/policyengine_us/parameters/gov/states/mo/dss/liheap/income/elderly_age.yaml new file mode 100644 index 00000000000..45b26a8f352 --- /dev/null +++ b/policyengine_us/parameters/gov/states/mo/dss/liheap/income/elderly_age.yaml @@ -0,0 +1,13 @@ +description: Missouri treats applicants and spouses at or above this age as elderly for the medical deduction under the Low Income Home Energy Assistance Program. +values: + 2017-05-30: 65 + +metadata: + unit: year + period: year + label: Missouri LIHEAP elderly age + reference: + - title: 13 CSR 40-19.020(2)(D) + href: https://www.sos.mo.gov/cmsimages/adrules/csr/current/13csr/13c40-19.pdf#page=2 + - title: Missouri LIHEAP Policy and Procedure Manual (October 2025), Medical Deduction for Elderly-Disabled + href: https://dss.mo.gov/sites/mydss/files/media/pdf/2025/10/liheap-policy-procedure-manual.pdf#page=36 diff --git a/policyengine_us/parameters/gov/states/mo/dss/liheap/income/medical_deduction.yaml b/policyengine_us/parameters/gov/states/mo/dss/liheap/income/medical_deduction.yaml new file mode 100644 index 00000000000..207908e8844 --- /dev/null +++ b/policyengine_us/parameters/gov/states/mo/dss/liheap/income/medical_deduction.yaml @@ -0,0 +1,13 @@ +description: Missouri deducts this amount for medical expenses, once per household, when the applicant or spouse is elderly or disabled under the Low Income Home Energy Assistance Program. +values: + 2017-05-30: 100 + +metadata: + unit: currency-USD + period: month + label: Missouri LIHEAP medical deduction + reference: + - title: "13 CSR 40-19.020(2)(C), (2)(D) and (6)(D)1 #page 2-3" + href: https://www.sos.mo.gov/cmsimages/adrules/csr/current/13csr/13c40-19.pdf#page=2 + - title: Missouri LIHEAP Policy and Procedure Manual (October 2025), Medical Deduction for Elderly-Disabled + href: https://dss.mo.gov/sites/mydss/files/media/pdf/2025/10/liheap-policy-procedure-manual.pdf#page=36 diff --git a/policyengine_us/parameters/gov/states/mo/dss/liheap/income/unearned_sources.yaml b/policyengine_us/parameters/gov/states/mo/dss/liheap/income/unearned_sources.yaml new file mode 100644 index 00000000000..351df33790e --- /dev/null +++ b/policyengine_us/parameters/gov/states/mo/dss/liheap/income/unearned_sources.yaml @@ -0,0 +1,53 @@ +description: Missouri counts these unearned income sources under the Low Income Home Energy Assistance Program. +# Social Security counts net of the Medicare Part B premium in +# mo_liheap_countable_income_person, and Missouri TANF is added at the +# household level in mo_liheap_countable_income. Short- and long-term +# disability payments count only for members 18 or older +# (adult_unearned_sources). +# Interest and dividends are excluded (October 2025 manual, page 38), as are +# capital gains, which page 38 treats as lump sums; page 32 lists the Form 1040 +# capital gains line among self-employment documents. Foster care payments, +# royalties, roomer and boarder payments, armed forces allotments and +# installment income have no inputs. +# Retirement-account (IRA, Keogh or 401(k)) withdrawals are not counted: the +# income lists name pensions but not account withdrawals, and IRA and Keogh +# balances count as resources (manual page 40; 13 CSR 40-19.020(2)(N)), so +# the model treats a withdrawal as a change in resources, not income. +values: + 2023-10-01: + - total_unemployment_compensation + # Union funds or strike benefits. + - strike_benefits + - ssi + # Supplemental Aid to the Blind, Blind Pension and Supplemental State + # Payments. + - mo_ssp + - pension_income + - military_retirement_income + - railroad_benefits + # Rent received from land or buildings, including farm rent and + # Conservation Reserve Program payments. + - rental_income + - farm_rent_income + - alimony_income + - child_support_received + - veterans_benefits + - workers_compensation + # Contributions: money received from friends, family or organizations. + - financial_assistance + +metadata: + unit: list + period: year + label: Missouri LIHEAP unearned income sources + reference: + - title: "Missouri LIHEAP FFY2026 State Plan, Section 1.9 #page 5-7" + href: https://liheapch.acf.gov/docs/2026/state-plans/MO_Plan_2026.pdf#page=5 + - title: Missouri LIHEAP application MO 886-4576 (8-2026), Part 7 Other Income + href: https://dssmanuals.mo.gov/wp-content/uploads/2022/02/liheap-application.pdf#page=5 + - title: "Missouri LIHEAP Policy and Procedure Manual (October 2025), Unearned Income, Income Exclusions and Resources #page 32-34,38,40" + href: https://dss.mo.gov/sites/mydss/files/media/pdf/2025/10/liheap-policy-procedure-manual.pdf#page=32 + - title: 13 CSR 40-19.020(2)(N), Low-Income Home Energy Assistance Program + href: https://www.sos.mo.gov/cmsimages/adrules/csr/current/13csr/13c40-19.pdf#page=2 + - title: "Missouri DSS draft FFY2027 LIHEAP State Plan (report status Saved with Errors), Section 1.9 #page 5-7" + href: https://dss.mo.gov/sites/mydss/files/media/pdf/2026/08/liheap-active-ffy2027.pdf#page=5 diff --git a/policyengine_us/parameters/gov/states/mo/dss/liheap/rent_share.yaml b/policyengine_us/parameters/gov/states/mo/dss/liheap/rent_share.yaml new file mode 100644 index 00000000000..ae4e181ec0d --- /dev/null +++ b/policyengine_us/parameters/gov/states/mo/dss/liheap/rent_share.yaml @@ -0,0 +1,30 @@ +description: Missouri pays a renter household whose heating costs are included in the rent this share of its annual rent, up to the Energy Assistance amount for its heating fuel, under the Low Income Home Energy Assistance Program. +# 13 CSR 40-19.020(13) sets a payment of no more than eight percent of annual +# rent, applied here. The October 2025 manual (page 63), the FFY2024-FFY2026 +# plans and the DSS draft FFY2027 plan (section 2.3) describe 16 percent; the +# manual caps the payment at the Energy Assistance amount for the household's +# energy source. RSMo 660.115.2 separately limits renter payments from the +# state Utilicare stabilization fund to the lesser of eight percent of annual +# rent or $100; Energy Assistance is paid from federal LIHEAP funds. +values: + 2017-05-30: 0.08 + +metadata: + unit: /1 + period: year + label: Missouri LIHEAP renter annual rent share + reference: + - title: 13 CSR 40-19.020(13) + href: https://www.sos.mo.gov/cmsimages/adrules/csr/current/13csr/13c40-19.pdf#page=4 + - title: Missouri LIHEAP Policy and Procedure Manual (October 2025), Renter Household Payment + href: https://dss.mo.gov/sites/mydss/files/media/pdf/2025/10/liheap-policy-procedure-manual.pdf#page=63 + - title: Missouri LIHEAP FFY2026 State Plan, Section 2.3 + href: https://liheapch.acf.gov/docs/2026/state-plans/MO_Plan_2026.pdf#page=8 + - title: Missouri DSS draft FFY2027 LIHEAP State Plan (report status Saved with Errors), Section 2.3 + href: https://dss.mo.gov/sites/mydss/files/media/pdf/2026/08/liheap-active-ffy2027.pdf#page=8 + - title: Missouri LIHEAP FFY2025 State Plan, Section 2.3 + href: https://liheapch.acf.gov/docs/2025/state-plans/MO_Plan_2025.pdf#page=8 + - title: Missouri LIHEAP FFY2024 State Plan, Section 2.3 + href: https://liheapch.acf.gov/docs/2024/state-plans/MO_Plan_2024.pdf#page=8 + - title: RSMo 660.115 + href: https://revisor.mo.gov/main/OneSection.aspx?section=660.115 diff --git a/policyengine_us/programs.yaml b/policyengine_us/programs.yaml index 86c8759b02d..089e73e0d47 100644 --- a/policyengine_us/programs.yaml +++ b/policyengine_us/programs.yaml @@ -987,7 +987,7 @@ programs: category: Benefits agency: HHS status: partial - coverage: AR, AL, DC, GA, Riverside County, MA, FL, IL, IN, KS, KY, MD, MS, NC, NE, NJ, NY, OH, OK, OR, SD, RI, TX + coverage: AR, AL, DC, GA, Riverside County, MA, FL, IL, IN, KS, KY, MD, MO, MS, NC, NE, NJ, NY, OH, OK, OR, SD, RI, TX state_implementations: - state: AL status: partial @@ -1092,6 +1092,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: MO + status: partial + name: Missouri LIHEAP + full_name: Missouri Low Income Home Energy Assistance Program + variable: mo_liheap + parameter_prefix: gov.states.mo.dss.liheap + verified_years: "2026-2027" + notes: FY2026-FY2027 regular Energy Assistance only, including the heat-in-rent payment. Crisis (ECIP), cooling and weatherization assistance are out of scope. - state: MS status: partial name: Mississippi LIHEAP diff --git a/policyengine_us/tests/policy/baseline/gov/states/mo/dss/liheap/eligibility/mo_liheap_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/mo/dss/liheap/eligibility/mo_liheap_eligible.yaml new file mode 100644 index 00000000000..50e87a60c05 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/mo/dss/liheap/eligibility/mo_liheap_eligible.yaml @@ -0,0 +1,263 @@ +# Missouri LIHEAP Energy Assistance eligibility: at least one qualifying +# member; countable income at or below the 60% SMI limit, or below the +# federal 110% poverty floor; cash resources of at most $3,000; heating costs +# paid through the household's own fuel bill or through unsubsidized rent +# that includes heat; and a heating fuel other than coal. + +- name: Case 1, countable income exactly at the size one limit is eligible. + period: 2026 + input: + people: + person1: + age: 40 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_100 + mo_liheap_countable_income: 34_080 + households: + household: + members: [person1] + state_code: MO + output: + # Boundary case: FFY2026 size 1 limit 2,840 x 12 = 34,080. + mo_liheap_eligible: true + +- name: Case 2, countable income one dollar above the size one limit is ineligible. + period: 2026 + input: + people: + person1: + age: 40 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_100 + mo_liheap_countable_income: 34_081 + households: + household: + members: [person1] + state_code: MO + output: + # Boundary case: 34,081 > 34,080, and the 110% poverty floor for one + # person, 1.1 x 15,650 = 17,215, is far below the limit. + mo_liheap_eligible: false + +- name: Case 3, FFY2026 federal poverty floor admits a sixteen-person household above the state limit. + period: 2026 + input: + state_code: [MO, MO] + heating_type: [NATURAL_GAS, NATURAL_GAS] + gas_expense: [1_800, 1_800] + mo_liheap_household_size: [16, 16] + mo_liheap_countable_income: [107_000, 107_965] + output: + # Size 16 limit: 8,847 x 12 = 106,164. Floor with the 2025 guidelines: + # 1.1 x (15,650 + 5,500 x 15) = 1.1 x 98,150 = 107,965. + # Unit 1: 107,000 is above the limit but below the floor -> eligible. + # Unit 2 (boundary case): income exactly at the floor is not below it + # -> ineligible. + mo_liheap_eligible: [true, false] + +- name: Case 4, FFY2027 federal poverty floor uses the 2026 guidelines at size sixteen. + period: 2027 + input: + state_code: MO + heating_type: ELECTRICITY + pre_subsidy_electricity_expense: 2_400 + mo_liheap_household_size: 16 + mo_liheap_countable_income: 110_500 + output: + # Size 16 limit: 9,164 x 12 = 109,968. Floor: 1.1 x (15,960 + 5,680 x 15) + # = 1.1 x 101,160 = 111,276. 110,500 is between them -> eligible. + mo_liheap_eligible: true + +- name: Case 5, cash assets exactly at the 3,000 resource limit are eligible. + period: 2026 + input: + people: + person1: + age: 58 + bank_account_assets: 3_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_100 + mo_liheap_countable_income: 24_000 + households: + household: + members: [person1] + state_code: MO + output: + # Boundary case: 3,000 <= 3,000. + mo_liheap_eligible: true + +- name: Case 6, cash assets of 3,001 exceed the resource limit. + period: 2026 + input: + people: + person1: + age: 58 + bank_account_assets: 3_001 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_100 + mo_liheap_countable_income: 24_000 + households: + household: + members: [person1] + state_code: MO + output: + # Boundary case: 3,001 > 3,000. + mo_liheap_eligible: false + +- name: Case 7, household with no citizen or qualified noncitizen is ineligible. + period: 2026 + input: + people: + person1: + age: 30 + immigration_status: UNDOCUMENTED + employment_income: 31_200 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + households: + household: + members: [person1] + state_code: MO + output: + # Household size 0, so the household fails the size test even though the + # member's countable income (31,200 x 0.8 = 24,960) is below the size one + # limit. + mo_liheap_eligible: false + +- name: Case 8, housing assistance recipient with heat included in the rent is ineligible. + period: 2026 + input: + people: + person1: + age: 33 + pre_subsidy_rent: 9_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + heat_expense_included_in_rent: true + receives_housing_assistance: true + mo_liheap_countable_income: 14_000 + households: + household: + members: [person1] + state_code: MO + output: + mo_liheap_eligible: false + +- name: Case 9, public housing tenant with heat included in the rent is ineligible. + period: 2026 + input: + people: + person1: + age: 33 + pre_subsidy_rent: 6_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + heat_expense_included_in_rent: true + mo_liheap_countable_income: 14_000 + households: + household: + members: [person1] + state_code: MO + is_in_public_housing: true + output: + mo_liheap_eligible: false + +- name: Case 10, housing assistance recipient paying its own electric heating bill is eligible. + period: 2026 + input: + people: + person1: + age: 33 + pre_subsidy_rent: 6_000 + spm_units: + spm_unit: + members: [person1] + heating_type: ELECTRICITY + pre_subsidy_electricity_expense: 1_400 + receives_housing_assistance: true + mo_liheap_countable_income: 14_000 + households: + household: + members: [person1] + state_code: MO + output: + mo_liheap_eligible: true + +- name: Case 11, home with no heating has no heating cost and is ineligible. + period: 2026 + input: + people: + person1: + age: 45 + spm_units: + spm_unit: + members: [person1] + heating_type: NONE + mo_liheap_countable_income: 18_000 + households: + household: + members: [person1] + state_code: MO + output: + mo_liheap_eligible: false + +- name: Case 12, household that heats with coal is denied. + period: 2026 + input: + people: + person1: + age: 61 + spm_units: + spm_unit: + members: [person1] + heating_type: COAL + coal_expense: 800 + mo_liheap_countable_income: 18_000 + households: + household: + members: [person1] + state_code: MO + output: + # The coal bill is a heating cost, but manual denial code O ("Heats with + # Coal") applies. + mo_liheap_eligible: false + +- name: Case 13, household heating with another fuel is eligible. + period: 2026 + input: + people: + person1: + age: 61 + spm_units: + spm_unit: + members: [person1] + heating_type: OTHER + other_heating_fuel_expense: 600 + mo_liheap_countable_income: 18_000 + households: + household: + members: [person1] + state_code: MO + output: + # Eligible; the payment schedule has no row for other fuels (see + # mo_liheap.yaml). + mo_liheap_eligible: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/mo/dss/liheap/eligibility/mo_liheap_income_limit.yaml b/policyengine_us/tests/policy/baseline/gov/states/mo/dss/liheap/eligibility/mo_liheap_income_limit.yaml new file mode 100644 index 00000000000..80492c73a60 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/mo/dss/liheap/eligibility/mo_liheap_income_limit.yaml @@ -0,0 +1,37 @@ +# Missouri LIHEAP annual income limit: 12 x the published monthly 60% state +# median income limit, which equals the HHS LIHEAP 60% SMI amount for the +# household size divided by 12 and rounded to the nearest dollar. +# FFY2026 (model year 2026) uses Missouri SMI 109,229: floor(109,229 x 0.6) = +# 65,537 for four people. FFY2027 (model year 2027) uses SMI 113,137: +# floor(113,137 x 0.6) = 67,882. + +- name: Case 1, FFY2026 published limits for household sizes 1, 4, 16 and 20. + period: 2026 + absolute_error_margin: 0.01 + input: + state_code: [MO, MO, MO, MO] + heating_type: [NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, NATURAL_GAS] + mo_liheap_household_size: [1, 4, 16, 20] + output: + # Size 1: floor(65,537 x 0.52) = 34,079; 34,079 / 12 = 2,839.92 -> 2,840 + # monthly (Appendix K) -> 34,080. + # Size 4: 65,537 / 12 = 5,461.42 -> 5,461 -> 65,532. + # Size 16: floor(65,537 x 1.62) = 106,169; / 12 = 8,847.42 -> 8,847 + # -> 106,164. + # Size 20: floor(65,537 x 1.74) = 114,034; / 12 = 9,502.83 -> 9,503 + # -> 114,036. + mo_liheap_income_limit: [34_080, 65_532, 106_164, 114_036] + +- name: Case 2, FFY2027 published limits for household sizes 1 and 10. + period: 2027 + absolute_error_margin: 0.01 + input: + state_code: [MO, MO] + heating_type: [ELECTRICITY, ELECTRICITY] + mo_liheap_household_size: [1, 10] + output: + # Size 1: floor(67,882 x 0.52) = 35,298; 35,298 / 12 = 2,941.50 -> 2,942 + # monthly (MO 886-4576) -> 35,304. + # Size 10: floor(67,882 x 1.44) = 97,750; / 12 = 8,145.83 -> 8,146 + # -> 97,752. + mo_liheap_income_limit: [35_304, 97_752] diff --git a/policyengine_us/tests/policy/baseline/gov/states/mo/dss/liheap/income/mo_liheap_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/mo/dss/liheap/income/mo_liheap_countable_income.yaml new file mode 100644 index 00000000000..5db7f57d810 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/mo/dss/liheap/income/mo_liheap_countable_income.yaml @@ -0,0 +1,124 @@ +# Missouri LIHEAP countable household income: all members' countable income +# plus Missouri TANF, less child support paid by any member and the medical +# deduction, floored at zero. + +- name: Case 1, Missouri TANF counts as income. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 27 + child_support_received: 2_400 + person2: + age: 6 + person3: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3] + heating_type: NATURAL_GAS + mo_tanf: 3_504 + households: + household: + members: [person1, person2, person3] + state_code: MO + output: + # TANF of 292 a month = 3,504 + child support received 2,400 = 5,904. + mo_liheap_countable_income: 5_904 + +- name: Case 2, child support paid outside the household is deducted. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + employment_income: 31_200 + child_support_expense: 4_800 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + households: + household: + members: [person1] + state_code: MO + output: + # 31,200 x 0.8 = 24,960 - child support paid of 400 a month (4,800) + # = 20,160. + mo_liheap_countable_income: 20_160 + +- name: Case 3, medical deduction for a retiree is subtracted. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 68 + social_security_retirement: 23_400 + medicare_part_b_premium: 2_434.80 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + households: + household: + members: [person1] + state_code: MO + output: + # 23,400 - 2,434.80 = 20,965.20 - medical deduction 1,200 = 19,765.20. + mo_liheap_countable_income: 19_765.20 + +- name: Case 4, child support paid above countable earnings floors income at zero. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 24 + employment_income: 6_240 + child_support_expense: 6_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + households: + household: + members: [person1] + state_code: MO + output: + # 8 hours a week at $15.00 = 6,240 x 0.8 = 4,992; + # max(4,992 - 6,000, 0) = 0. + mo_liheap_countable_income: 0 + +- name: Case 5, an undocumented member is left out of the household size but that member's earnings count and child support paid is deducted. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 34 + immigration_status: CITIZEN + employment_income: 31_200 + person2: + age: 32 + immigration_status: UNDOCUMENTED + employment_income: 31_200 + child_support_expense: 3_600 + spm_units: + spm_unit: + members: [person1, person2] + heating_type: NATURAL_GAS + households: + household: + members: [person1, person2] + state_code: MO + output: + # The undocumented member is left out of the household size (2 - 1 = 1) + # but the 2025 manual counts that member's income: 31,200 x 0.8 = 24,960 + # for each member = 49,920. The 300 a month (3,600) of child support that + # member pays to someone outside the household is deducted: + # 49,920 - 3,600 = 46,320. + mo_liheap_household_size: 1 + mo_liheap_countable_income: 46_320 diff --git a/policyengine_us/tests/policy/baseline/gov/states/mo/dss/liheap/income/mo_liheap_countable_income_person.yaml b/policyengine_us/tests/policy/baseline/gov/states/mo/dss/liheap/income/mo_liheap_countable_income_person.yaml new file mode 100644 index 00000000000..0e387add86b --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/mo/dss/liheap/income/mo_liheap_countable_income_person.yaml @@ -0,0 +1,268 @@ +# Missouri LIHEAP countable income per member: earned income less the 20% +# earned income deduction (each earned source floored at zero; none for +# members under 18), plus unearned income (without short- and long-term +# disability payments for members under 18), plus Social Security net of the +# Medicare Part B premium. Members left out of the household size as +# non-citizens have their income counted. + +- name: Case 1, full-time minimum wage earnings after the 20 percent deduction. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 31_200 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + households: + household: + members: [person1] + state_code: MO + output: + # $15.00 an hour x 2,080 hours = 31,200 x (1 - 0.2) = 24,960. + mo_liheap_countable_income_person: [24_960] + +- name: Case 2, a seventeen-year-old's wages are excluded but survivor benefits count. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 31_200 + person2: + age: 17 + employment_income: 6_000 + social_security_survivors: 9_600 + spm_units: + spm_unit: + members: [person1, person2] + heating_type: NATURAL_GAS + households: + household: + members: [person1, person2] + state_code: MO + output: + # Parent: 31,200 x 0.8 = 24,960. Teenager: wages excluded under age 18; + # survivor benefits of 800 a month = 9,600 count (no Part B premium). + mo_liheap_countable_income_person: [24_960, 9_600] + +- name: Case 3, an eighteen-year-old in high school has wages counted. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 46 + person2: + age: 18 + is_in_secondary_school: true + is_tax_unit_dependent: true + employment_income: 7_800 + spm_units: + spm_unit: + members: [person1, person2] + heating_type: ELECTRICITY + households: + household: + members: [person1, person2] + state_code: MO + output: + # A high school senior and tax dependent working 10 hours a week at + # $15.00: 7,800. The 2025 manual excludes earnings only under age 18 + # (boundary case: 18 is not under 18) and no longer excludes students: + # 7,800 x 0.8 = 6,240. + mo_liheap_countable_income_person: [0, 6_240] + +- name: Case 4, self-employment counts after the deduction and a farm loss is floored at zero. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 45 + self_employment_income: 24_000 + farm_operations_income: -3_000 + spm_units: + spm_unit: + members: [person1] + heating_type: PROPANE + households: + household: + members: [person1] + state_code: MO + output: + # Each earned source is floored: max(24,000, 0) + max(-3,000, 0) = 24,000; + # 24,000 x 0.8 = 19,200. Netting the loss would give 21,000 x 0.8 = 16,800. + mo_liheap_countable_income_person: [19_200] + +- name: Case 5, Social Security counts net of the Medicare Part B premium. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 72 + social_security_retirement: 23_400 + medicare_part_b_premium: 2_434.80 + person2: + age: 66 + social_security_retirement: 1_800 + medicare_part_b_premium: 2_434.80 + taxable_pension_income: 6_000 + spm_units: + spm_unit: + members: [person1, person2] + heating_type: NATURAL_GAS + households: + household: + members: [person1, person2] + state_code: MO + output: + # 2026 Part B premium 202.90 x 12 = 2,434.80. + # Person 1: 1,950 a month = 23,400 - 2,434.80 = 20,965.20. + # Person 2: max(1,800 - 2,434.80, 0) = 0, plus a 500 a month pension + # of 6,000 = 6,000. + mo_liheap_countable_income_person: [20_965.20, 6_000] + +- name: Case 6, unearned sources count in full and interest is excluded. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 38 + unemployment_compensation: 6_000 + child_support_received: 4_800 + financial_assistance: 1_200 + taxable_interest_income: 300 + person2: + age: 41 + military_retirement_pay: 24_000 + veterans_benefits: 6_000 + spm_units: + spm_unit: + members: [person1, person2] + heating_type: NATURAL_GAS + households: + household: + members: [person1, person2] + state_code: MO + output: + # Person 1: unemployment 6,000 + child support 4,800 + money from family + # 1,200 = 12,000; interest of 300 is not counted. + # Person 2: military retirement 24,000 + VA benefits 6,000 = 30,000. + mo_liheap_countable_income_person: [12_000, 30_000] + +- name: Case 7, monthly SSI payments count as their annual total. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 45 + is_disabled: true + ssi: 11_928 + spm_units: + spm_unit: + members: [person1] + heating_type: ELECTRICITY + households: + household: + members: [person1] + state_code: MO + output: + # 994 a month x 12 = 11,928. + mo_liheap_countable_income_person: [11_928] + +- name: Case 8, an undocumented member's earnings count. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 34 + immigration_status: CITIZEN + employment_income: 31_200 + person2: + age: 32 + immigration_status: UNDOCUMENTED + employment_income: 31_200 + spm_units: + spm_unit: + members: [person1, person2] + heating_type: NATURAL_GAS + households: + household: + members: [person1, person2] + state_code: MO + output: + # Both: 31,200 x 0.8 = 24,960. The 2025 manual counts the income of a + # member left out of the household as a non-citizen. + mo_liheap_countable_income_person: [24_960, 24_960] + +- name: Case 9, earnings of a parent attending GED classes count. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 25 + is_in_secondary_school: true + employment_income_before_lsr: 58_240 + person2: + age: 6 + spm_units: + spm_unit: + members: [person1, person2] + heating_type: NATURAL_GAS + gas_expense: 1_100 + households: + household: + members: [person1, person2] + state_code: MO + output: + # The parent is 25, so the earnings count whether or not the parent + # attends GED classes. + # $28.00 an hour x 2,080 hours = 58,240 x (1 - 0.2) = 46,592. + # Missouri TANF: 58,240 / 12 = 4,853.33 a month, above the gross limit + # of 678 x 1.85 = 1,254.30 for two, so TANF is 0. + # Size 2 limit (FFY2026): 3,714 x 12 = 44,568. 46,592 > 44,568, and the + # 110% poverty floor 1.1 x (15,650 + 5,500) = 23,265 does not bind. + mo_liheap_countable_income_person: [46_592, 0] + mo_tanf: 0 + mo_liheap_countable_income: 46_592 + mo_liheap_income_limit: 44_568 + mo_liheap_eligible: false + mo_liheap: 0 + +- name: Case 10, a minor's disability payments are excluded while the minor's Social Security counts. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 44 + disability_benefits: 18_000 + person2: + age: 17 + disability_benefits: 1_440 + social_security_survivors: 9_600 + spm_units: + spm_unit: + members: [person1, person2] + heating_type: NATURAL_GAS + households: + household: + members: [person1, person2] + state_code: MO + output: + # Parent: private long-term disability of 1,500 a month = 18,000 counts. + # Teenager: short-term disability from a part-time job (60% of 300 a week + # for 8 weeks = 1,440) is excluded under age 18; the Social Security + # child's survivor benefit of 800 a month = 9,600 counts as SSA income + # (no Part B premium). + mo_liheap_countable_income_person: [18_000, 9_600] diff --git a/policyengine_us/tests/policy/baseline/gov/states/mo/dss/liheap/income/mo_liheap_medical_deduction.yaml b/policyengine_us/tests/policy/baseline/gov/states/mo/dss/liheap/income/mo_liheap_medical_deduction.yaml new file mode 100644 index 00000000000..c5b2e1622a7 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/mo/dss/liheap/income/mo_liheap_medical_deduction.yaml @@ -0,0 +1,235 @@ +# Missouri LIHEAP medical deduction: $100 a month ($1,200 a year), once per +# household, when the applicant or spouse (modeled as a tax-unit head or +# spouse who is a citizen or qualified noncitizen) is 65 or older, or is +# disabled or blind and receives SSI, Social Security disability, dependent +# or survivor benefits, veterans or railroad benefits, Medicaid or a Missouri +# state supplementary payment. + +- name: Case 1, applicant who just turned 65 qualifies. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 65 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: MO + output: + # Boundary case: 65 >= 65 -> 100 x 12 = 1,200. + mo_liheap_medical_deduction: 1_200 + +- name: Case 2, applicant aged 64 without a disability does not qualify. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 64 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: MO + output: + mo_liheap_medical_deduction: 0 + +- name: Case 3, disabled spouse receiving SSI qualifies the household. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 52 + person2: + age: 48 + is_disabled: true + ssi: 11_928 + spm_units: + spm_unit: + members: [person1, person2] + heating_type: ELECTRICITY + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MO + output: + mo_liheap_medical_deduction: 1_200 + +- name: Case 4, disabled applicant with only private disability insurance does not qualify. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 50 + is_disabled: true + disability_benefits: 18_000 + ssi: 0 + social_security_disability: 0 + medicaid: 0 + mo_ssp: 0 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: MO + output: + # Private long-term disability is not a listed benefit, and no listed + # benefit is received. + mo_liheap_medical_deduction: 0 + +- name: Case 5, blind applicant receiving Social Security disability qualifies. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 52 + is_blind: true + social_security_disability: 18_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: MO + output: + mo_liheap_medical_deduction: 1_200 + +- name: Case 6, elderly grandparent who is a dependent does not qualify the household. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 45 + person2: + age: 43 + person3: + age: 74 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2, person3] + heating_type: NATURAL_GAS + tax_units: + tax_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: MO + output: + # The 74-year-old is neither the applicant nor the spouse. + mo_liheap_medical_deduction: 0 + +- name: Case 7, elderly couple receives a single deduction. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + person2: + age: 67 + spm_units: + spm_unit: + members: [person1, person2] + heating_type: PROPANE + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MO + output: + # One deduction per household: 1,200, not 2,400. + mo_liheap_medical_deduction: 1_200 + +- name: Case 8, elderly undocumented spouse does not qualify the household. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 60 + immigration_status: CITIZEN + person2: + age: 67 + immigration_status: UNDOCUMENTED + spm_units: + spm_unit: + members: [person1, person2] + heating_type: NATURAL_GAS + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MO + output: + # The 67-year-old is undocumented and left out of the household count; + # the 2025 manual does not say that such a spouse qualifies the + # household, and the 60-year-old citizen is neither elderly nor disabled. + mo_liheap_medical_deduction: 0 + +- name: Case 9, disabled applicant whose only listed benefit is Medicaid qualifies. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 45 + is_disabled: true + medicaid: 21_297 + ssi: 0 + social_security_disability: 0 + mo_ssp: 0 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: MO + output: + # MO HealthNet coverage valued at the model's per-capita Medicaid cost + # for the aged and disabled group (21,297); no SSI, Social Security + # disability or state supplementary payment. Medicaid is a listed + # benefit: 100 x 12 = 1,200. + mo_liheap_medical_deduction: 1_200 diff --git a/policyengine_us/tests/policy/baseline/gov/states/mo/dss/liheap/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/mo/dss/liheap/integration.yaml new file mode 100644 index 00000000000..4212cb070f3 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/mo/dss/liheap/integration.yaml @@ -0,0 +1,130 @@ +# Missouri LIHEAP Energy Assistance end to end, from household inputs to the +# payment. FFY2026 is model year 2026 and FFY2027 is model year 2027. + +- name: Case 1, FFY2026 working family of four heating with natural gas. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 38 + employment_income_before_lsr: 31_200 + bank_account_assets: 1_200 + person2: + age: 36 + employment_income_before_lsr: 18_720 + person3: + age: 9 + person4: + age: 5 + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + heating_type: NATURAL_GAS + gas_expense: 1_100 + households: + household: + members: [person1, person2, person3, person4] + state_code: MO + output: + # Full time at $15.00: 31,200 x 0.8 = 24,960. + # 24 hours a week at $15.00: 18,720 x 0.8 = 14,976. + # Missouri TANF: (31,200 + 18,720) / 12 = 4,160 a month, above the gross + # limit of 990 x 1.85 = 1,831.50 for four, so TANF is 0. + # Total 39,936; no medical deduction. + # Size 4 limit: 5,461 x 12 = 65,532. Assets 1,200 <= 3,000. + # Natural gas pays 326. + mo_liheap_household_size: 4 + mo_liheap_countable_income_person: [24_960, 14_976, 0, 0] + mo_tanf: 0 + mo_liheap_medical_deduction: 0 + mo_liheap_countable_income: 39_936 + mo_liheap_income_limit: 65_532 + has_heating_expense: true + mo_liheap_eligible: true + mo_liheap: 326 + +- name: Case 2, FFY2026 retired couple heating with tank propane. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 72 + social_security_retirement: 25_200 + taxable_pension_income: 4_800 + medicare_part_b_premium: 2_434.80 + bank_account_assets: 2_500 + person2: + age: 69 + social_security_retirement: 13_200 + medicare_part_b_premium: 2_434.80 + spm_units: + spm_unit: + members: [person1, person2] + heating_type: PROPANE + bottled_gas_expense: 1_800 + households: + household: + members: [person1, person2] + state_code: MO + output: + # 2026 Part B premium 202.90 x 12 = 2,434.80 each. + # Person 1: 2,100 a month = 25,200 - 2,434.80 + pension 4,800 = 27,565.20. + # Person 2: 1,100 a month = 13,200 - 2,434.80 = 10,765.20. + # Total 38,330.40 - one medical deduction 1,200 = 37,130.40. + # Size 2 limit: 3,714 x 12 = 44,568. Assets 2,500 <= 3,000. + # Tank propane pays 495. + mo_liheap_household_size: 2 + mo_liheap_countable_income_person: [27_565.20, 10_765.20] + mo_liheap_medical_deduction: 1_200 + mo_liheap_countable_income: 37_130.40 + mo_liheap_income_limit: 44_568 + mo_liheap_eligible: true + mo_liheap: 495 + +- name: Case 3, FFY2027 mixed-status renter family with heat included in the rent. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + employment_income_before_lsr: 31_200 + pre_subsidy_rent: 10_200 + person2: + age: 29 + immigration_status: UNDOCUMENTED + employment_income_before_lsr: 26_000 + person3: + age: 4 + immigration_status: CITIZEN + spm_units: + spm_unit: + members: [person1, person2, person3] + heating_type: NATURAL_GAS + heat_expense_included_in_rent: true + households: + household: + members: [person1, person2, person3] + state_code: MO + output: + # The undocumented parent is left out of the household size (3 - 1 = 2), + # but the 2025 manual counts that parent's income. + # Citizen parent: 31,200 x 0.8 = 24,960. + # Undocumented parent: $12.50 an hour x 2,080 hours = 26,000 x 0.8 + # = 20,800. Total 45,760; no medical deduction or child support paid. + # Missouri TANF: 31,200 / 12 = 2,600 a month from the citizen parent alone + # is above the gross limit even for three (846 x 1.85 = 1,565.10), so TANF + # is 0. + # Size 2 limit (FFY2027): 3,847 x 12 = 46,164; 45,760 <= 46,164. + # No own fuel bill, but heat is in unsubsidized rent. + # Rent 850 a month = 10,200 x 0.08 = 816, capped at natural gas 326. + mo_liheap_household_size: 2 + mo_liheap_countable_income_person: [24_960, 20_800, 0] + mo_liheap_countable_income: 45_760 + mo_liheap_income_limit: 46_164 + has_heating_expense: false + mo_liheap_eligible: true + mo_liheap: 326 diff --git a/policyengine_us/tests/policy/baseline/gov/states/mo/dss/liheap/mo_liheap.yaml b/policyengine_us/tests/policy/baseline/gov/states/mo/dss/liheap/mo_liheap.yaml new file mode 100644 index 00000000000..0b97f29349c --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/mo/dss/liheap/mo_liheap.yaml @@ -0,0 +1,145 @@ +# Missouri LIHEAP Energy Assistance: a one-time payment by primary heating +# fuel (FFY2026 Appendix K; FFY2027 application MO 886-4576). A renter whose +# heat is included in the rent receives 8% of annual rent, capped at the +# amount for the household's fuel (13 CSR 40-19.020(13)). Zero when +# ineligible. + +- name: Case 1, payment for every heating fuel. + period: 2026 + absolute_error_margin: 0.01 + input: + state_code: [MO, MO, MO, MO, MO, MO, MO, MO, MO, MO, MO] + heating_type: [NATURAL_GAS, PROPANE, ELECTRICITY, FUEL_OIL, WOOD, KEROSENE, SOLAR, OTHER, UNSPECIFIED, NONE, COAL] + has_heating_expense: [true, true, true, true, true, true, true, true, true, false, true] + mo_liheap_countable_income: [18_000, 18_000, 18_000, 18_000, 18_000, 18_000, 18_000, 18_000, 18_000, 18_000, 18_000] + output: + # Natural gas 326, tank propane 495, electric 318, fuel oil 326, wood 219, + # kerosene 153; solar is paid on the electric account (318). Other fuels + # have no schedule row and an unspecified fuel matches no row, so both are + # eligible for 0. A home with no heating has no heating cost, and coal is + # denied (manual denial code O). + mo_liheap_eligible: [true, true, true, true, true, true, true, true, true, false, false] + mo_liheap: [326, 495, 318, 326, 219, 153, 318, 0, 0, 0, 0] + +- name: Case 2, renter share of rent split between two partners is below the propane amount. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 27 + pre_subsidy_rent: 3_000 + person2: + age: 26 + pre_subsidy_rent: 3_000 + spm_units: + spm_unit: + members: [person1, person2] + heating_type: PROPANE + heat_expense_included_in_rent: true + mo_liheap_countable_income: 20_000 + households: + household: + members: [person1, person2] + state_code: MO + output: + # Annual rent 3,000 + 3,000 = 6,000 ($500 a month); + # 6,000 x 0.08 = 480 < 495 -> 480. + mo_liheap: 480 + +- name: Case 3, renter share of rent above the natural gas amount is capped. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 33 + pre_subsidy_rent: 9_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + heat_expense_included_in_rent: true + mo_liheap_countable_income: 22_000 + households: + household: + members: [person1] + state_code: MO + output: + # 750 x 12 = 9,000 x 0.08 = 720 > 326 -> 326. + mo_liheap: 326 + +- name: Case 4, renter with heat in the rent and an unspecified fuel receives nothing. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 33 + pre_subsidy_rent: 9_000 + spm_units: + spm_unit: + members: [person1] + heating_type: UNSPECIFIED + heat_expense_included_in_rent: true + mo_liheap_countable_income: 22_000 + households: + household: + members: [person1] + state_code: MO + output: + # Eligible, but the cap is the amount for an unspecified fuel: + # min(9,000 x 0.08 = 720, 0) = 0. + mo_liheap_eligible: true + mo_liheap: 0 + +- name: Case 5, Kansas household is outside the Missouri program. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 20_800 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + households: + household: + members: [person1] + state_code: KS + output: + mo_liheap: 0 + +- name: Case 6, FFY2027 single parent heating with kerosene, teenager's wages excluded. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 41 + employment_income_before_lsr: 41_600 + bank_account_assets: 900 + person2: + age: 16 + employment_income_before_lsr: 5_200 + spm_units: + spm_unit: + members: [person1, person2] + heating_type: KEROSENE + fuel_oil_expense: 1_500 + households: + household: + members: [person1, person2] + state_code: MO + output: + # Parent: $20 an hour x 2,080 hours = 41,600 x (1 - 0.2) = 33,280. + # The 16-year-old's 5,200 is excluded. Size 2 limit (FFY2027): + # 3,847 x 12 = 46,164. Counting the teenager's wages without the 20% + # deduction (46,800) would exceed it. Kerosene pays 153. + mo_liheap_countable_income: 33_280 + mo_liheap_income_limit: 46_164 + mo_liheap_eligible: true + mo_liheap: 153 diff --git a/policyengine_us/tests/policy/baseline/gov/states/mo/dss/liheap/mo_liheap_household_size.yaml b/policyengine_us/tests/policy/baseline/gov/states/mo/dss/liheap/mo_liheap_household_size.yaml new file mode 100644 index 00000000000..3266ae322ed --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/mo/dss/liheap/mo_liheap_household_size.yaml @@ -0,0 +1,99 @@ +# Missouri LIHEAP household size: SPM unit members who are U.S. citizens or +# qualified noncitizens. Other members are left out of the household count +# (13 CSR 40-19.020(6)(A) and (8)(A)). + +- name: Case 1, family of four citizens counts four. + period: 2026 + input: + people: + person1: + age: 36 + person2: + age: 34 + person3: + age: 9 + person4: + age: 6 + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + heating_type: NATURAL_GAS + households: + household: + members: [person1, person2, person3, person4] + state_code: MO + output: + mo_liheap_household_size: 4 + +- name: Case 2, lawful permanent resident and refugee parents count with their citizen child. + period: 2026 + input: + people: + person1: + age: 44 + immigration_status: LEGAL_PERMANENT_RESIDENT + person2: + age: 40 + immigration_status: REFUGEE + person3: + age: 8 + immigration_status: CITIZEN + spm_units: + spm_unit: + members: [person1, person2, person3] + heating_type: ELECTRICITY + households: + household: + members: [person1, person2, person3] + state_code: MO + output: + mo_liheap_household_size: 3 + +- name: Case 3, undocumented parent is left out of the household count. + period: 2026 + input: + people: + person1: + age: 35 + immigration_status: CITIZEN + person2: + age: 33 + immigration_status: UNDOCUMENTED + person3: + age: 10 + immigration_status: CITIZEN + person4: + age: 7 + immigration_status: CITIZEN + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + heating_type: NATURAL_GAS + households: + household: + members: [person1, person2, person3, person4] + state_code: MO + output: + # 4 members - 1 undocumented = 3. + mo_liheap_household_size: 3 + +- name: Case 4, household with no citizen or qualified noncitizen counts zero. + period: 2026 + input: + people: + person1: + age: 30 + immigration_status: UNDOCUMENTED + person2: + age: 28 + immigration_status: UNDOCUMENTED + spm_units: + spm_unit: + members: [person1, person2] + heating_type: NATURAL_GAS + households: + household: + members: [person1, person2] + state_code: MO + output: + mo_liheap_household_size: 0 diff --git a/policyengine_us/variables/gov/states/mo/dss/liheap/eligibility/mo_liheap_eligible.py b/policyengine_us/variables/gov/states/mo/dss/liheap/eligibility/mo_liheap_eligible.py new file mode 100644 index 00000000000..8bf0cb2fabd --- /dev/null +++ b/policyengine_us/variables/gov/states/mo/dss/liheap/eligibility/mo_liheap_eligible.py @@ -0,0 +1,52 @@ +from policyengine_us.model_api import * +from policyengine_us.variables.gov.hhs.tax_unit_fpg import fpg + + +class mo_liheap_eligible(Variable): + value_type = bool + entity = SPMUnit + definition_period = YEAR + label = "Eligible for Missouri LIHEAP Energy Assistance" + documentation = "A Missouri household with at least one citizen or legal immigrant member that meets the income limit or the federal 110 percent poverty floor, has resources within the resource limit, pays for heat either through its own fuel bill or through unsubsidized rent that includes heat, and does not heat with coal. Not modeled: the exclusions in 13 CSR 40-19.020(7)(B), (C) and (E)-(H) (nursing or boarding homes, hotels and shelters, Department of Mental Health transitional living, fuel credit balances over $500, self-cut wood and shared-meter dwellings) and the limit of one Energy Assistance payment per household per year." + reference = ( + # PDF pages 2-3 + "https://www.sos.mo.gov/cmsimages/adrules/csr/current/13csr/13c40-19.pdf#page=2", + "https://liheapch.acf.gov/docs/2026/state-plans/MO_Plan_2026.pdf#page=8", + # PDF pages 40, 42-43, 122 + "https://dss.mo.gov/sites/mydss/files/media/pdf/2025/10/liheap-policy-procedure-manual.pdf#page=40", + "https://www.law.cornell.edu/uscode/text/42/8624#b_2_B", + ) + defined_for = StateCode.MO + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.mo.dss.liheap.eligibility + size = spm_unit("mo_liheap_household_size", period) + income = spm_unit("mo_liheap_countable_income", period) + limit = spm_unit("mo_liheap_income_limit", period) + # 42 U.S.C. 8624(b)(2)(B) bars excluding a household on income below 110% + # of the poverty guideline. The 60% SMI limit falls below that floor from + # household size 16 in FFY2026 and FFY2027. + state_group = spm_unit.household("state_group_str", period) + guideline = fpg(size, state_group, period, parameters, year_lag=p.fpg_year_lag) + floor = np.round(guideline * parameters(period).gov.hhs.liheap.fpg_floor, 2) + income_eligible = (income <= limit) | (income < floor) + resource_eligible = spm_unit("spm_unit_cash_assets", period) <= p.resource_limit + # 13 CSR 40-19.020(7)(D): subsidized housing is ineligible unless the + # household pays an energy supplier or is billed for heating costs. + subsidized = spm_unit("receives_housing_assistance", period) | ( + spm_unit.household("is_in_public_housing", period) + ) + heat_in_rent = spm_unit("heat_expense_included_in_rent", period) + pays_for_heat = spm_unit("has_heating_expense", period) | ( + heat_in_rent & ~subsidized + ) + # 2025 manual Appendix E, denial code O: "Heats with Coal". + heating_type = spm_unit("heating_type", period) + heats_with_coal = heating_type == heating_type.possible_values.COAL + return ( + (size > 0) + & income_eligible + & resource_eligible + & pays_for_heat + & ~heats_with_coal + ) diff --git a/policyengine_us/variables/gov/states/mo/dss/liheap/eligibility/mo_liheap_income_limit.py b/policyengine_us/variables/gov/states/mo/dss/liheap/eligibility/mo_liheap_income_limit.py new file mode 100644 index 00000000000..691d633c5f9 --- /dev/null +++ b/policyengine_us/variables/gov/states/mo/dss/liheap/eligibility/mo_liheap_income_limit.py @@ -0,0 +1,27 @@ +from policyengine_us.model_api import * +from policyengine_us.variables.gov.hhs.hhs_smi import liheap_smi_limit + + +class mo_liheap_income_limit(Variable): + value_type = float + entity = SPMUnit + definition_period = YEAR + unit = USD + label = "Missouri LIHEAP annual income limit" + documentation = "Twelve times Missouri's monthly income limit, a share of state median income. The HHS LIHEAP limit for the household size, divided by twelve and rounded to the nearest dollar, reproduces the published monthly limits for FFY2026 (sizes 1-20) and FFY2027 (sizes 1-10). For households above ten members, the FFY2027 application adds a rounded $170 a month per additional member; that shorthand runs $1 to $2 a month above the 60% SMI amount for twelve to fifteen members (the federal poverty floor governs from sixteen), and the model keeps the 60% SMI amount of the plan." + reference = ( + "https://liheapch.acf.gov/docs/2026/state-plans/MO_Plan_2026.pdf#page=8", + "https://liheapch.acf.gov/docs/2026/benefits-matricies/MO_BenefitMatrix_2026.docx", + "https://dssmanuals.mo.gov/wp-content/uploads/2022/02/liheap-application.pdf#page=1", + # DSS draft FFY2027 plan (report status "Saved -- with Errors"). + "https://dss.mo.gov/sites/mydss/files/media/pdf/2026/08/liheap-active-ffy2027.pdf#page=8", + ) + defined_for = StateCode.MO + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.mo.dss.liheap.eligibility + size = spm_unit("mo_liheap_household_size", period) + state = spm_unit.household("state_code_str", period) + annual_limit = liheap_smi_limit(size, state, p.smi_rate, period, parameters) + monthly_limit = np.floor(annual_limit / MONTHS_IN_YEAR + 0.5) + return monthly_limit * MONTHS_IN_YEAR diff --git a/policyengine_us/variables/gov/states/mo/dss/liheap/income/mo_liheap_countable_income.py b/policyengine_us/variables/gov/states/mo/dss/liheap/income/mo_liheap_countable_income.py new file mode 100644 index 00000000000..88046f23d18 --- /dev/null +++ b/policyengine_us/variables/gov/states/mo/dss/liheap/income/mo_liheap_countable_income.py @@ -0,0 +1,34 @@ +from policyengine_us.model_api import * + + +class mo_liheap_countable_income(Variable): + value_type = float + entity = SPMUnit + definition_period = YEAR + unit = USD + label = "Missouri LIHEAP countable income" + documentation = "Countable income of all members, including members left out of the household size as non-citizens, plus Missouri TANF, less court-ordered child support members pay to someone outside the household and the medical deduction. The child support input does not identify court orders, so all child support paid is deducted." + reference = ( + # PDF pages 5-7 + "https://liheapch.acf.gov/docs/2026/state-plans/MO_Plan_2026.pdf#page=5", + "https://dssmanuals.mo.gov/wp-content/uploads/2022/02/liheap-application.pdf#page=5", + # PDF pages 2-3 + "https://www.sos.mo.gov/cmsimages/adrules/csr/current/13csr/13c40-19.pdf#page=2", + # PDF pages 36, 42-43 + "https://dss.mo.gov/sites/mydss/files/media/pdf/2025/10/liheap-policy-procedure-manual.pdf#page=36", + ) + defined_for = StateCode.MO + + def formula(spm_unit, period, parameters): + income = add(spm_unit, period, ["mo_liheap_countable_income_person", "mo_tanf"]) + # The 2025 manual deducts child support "paid by any household member + # to someone not included in the LIHEAP household" (page 36) and calls + # members left out as non-citizens "ineligible household members" + # (page 42), so their child support paid is deducted like that of + # other members. + deductions = add( + spm_unit, + period, + ["child_support_expense", "mo_liheap_medical_deduction"], + ) + return max_(income - deductions, 0) diff --git a/policyengine_us/variables/gov/states/mo/dss/liheap/income/mo_liheap_countable_income_person.py b/policyengine_us/variables/gov/states/mo/dss/liheap/income/mo_liheap_countable_income_person.py new file mode 100644 index 00000000000..055aabbc053 --- /dev/null +++ b/policyengine_us/variables/gov/states/mo/dss/liheap/income/mo_liheap_countable_income_person.py @@ -0,0 +1,43 @@ +from policyengine_us.model_api import * + + +class mo_liheap_countable_income_person(Variable): + value_type = float + entity = Person + definition_period = YEAR + unit = USD + label = "Missouri LIHEAP countable income per person" + documentation = "Gross income Missouri counts for a household member, including a member left out of the household size as a non-citizen: earned income after the earned income deduction, unearned income, and Social Security net of the Medicare Part B premium. Each earned source is floored at zero, so business and farm losses do not offset other income. Members under 18 have their earned income and their non-Social Security disability payments excluded; their Social Security and SSI count. Not modeled: a Part B premium paid by a member without Social Security (for example a Railroad Retirement beneficiary) and Medicare Part D premiums. Annual income stands in for twelve times the income of the month before application." + reference = ( + # PDF pages 5-7 + "https://liheapch.acf.gov/docs/2026/state-plans/MO_Plan_2026.pdf#page=5", + # PDF pages 4-5 + "https://dssmanuals.mo.gov/wp-content/uploads/2022/02/liheap-application.pdf#page=4", + # DSS draft FFY2027 plan (report status "Saved -- with Errors"). + # PDF pages 5-7 + "https://dss.mo.gov/sites/mydss/files/media/pdf/2026/08/liheap-active-ffy2027.pdf#page=5", + # PDF pages 32, 36, 38, 42-43 + "https://dss.mo.gov/sites/mydss/files/media/pdf/2025/10/liheap-policy-procedure-manual.pdf#page=32", + ) + defined_for = StateCode.MO + + def formula(person, period, parameters): + p = parameters(period).gov.states.mo.dss.liheap.income + earned = 0 + for source in p.earned_sources: + earned = earned + max_(person(source, period), 0) + countable_earned = earned * (1 - p.earned_income_deduction_rate) + # The 2025 manual (Earnings of Children) leaves out the earned income + # and the disability income of members under 18 but counts their SSA + # income, read here as Social Security and SSI. + adult_income = countable_earned + add(person, period, p.adult_unearned_sources) + adult = person("age", period) >= p.adult_age + unearned = add(person, period, p.unearned_sources) + # Plan section 1.9 counts Social Security excluding the Medicare + # deduction. + social_security = max_( + person("social_security", period) + - person("medicare_part_b_premium", period), + 0, + ) + return unearned + social_security + where(adult, adult_income, 0) diff --git a/policyengine_us/variables/gov/states/mo/dss/liheap/income/mo_liheap_medical_deduction.py b/policyengine_us/variables/gov/states/mo/dss/liheap/income/mo_liheap_medical_deduction.py new file mode 100644 index 00000000000..2b4a77e0284 --- /dev/null +++ b/policyengine_us/variables/gov/states/mo/dss/liheap/income/mo_liheap_medical_deduction.py @@ -0,0 +1,39 @@ +from policyengine_us.model_api import * + + +class mo_liheap_medical_deduction(Variable): + value_type = float + entity = SPMUnit + definition_period = YEAR + unit = USD + label = "Missouri LIHEAP medical deduction" + documentation = "Missouri's monthly medical deduction, annualized and given once per household when the applicant or spouse is elderly or disabled. Disabled means totally and permanently disabled or blind and receiving a listed disability benefit. Tax-unit heads and spouses who are citizens or legal immigrants stand in for the applicant and spouse." + reference = ( + # PDF pages 2-3 + "https://www.sos.mo.gov/cmsimages/adrules/csr/current/13csr/13c40-19.pdf#page=2", + # PDF pages 36, 48 + "https://dss.mo.gov/sites/mydss/files/media/pdf/2025/10/liheap-policy-procedure-manual.pdf#page=36", + ) + defined_for = StateCode.MO + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.mo.dss.liheap.income + person = spm_unit.members + applicant_or_spouse = person("is_tax_unit_head", period) | person( + "is_tax_unit_spouse", period + ) + # The 2025 manual (page 36) is silent on a spouse left out of the + # household as a non-citizen, and a non-citizen applicant makes the case + # ineligible (page 43); the model keeps the citizenship requirement. + qualified = person("is_citizen_or_legal_immigrant", period) + elderly = person("age", period) >= p.elderly_age + disabled_or_blind = person("is_disabled", period) | person("is_blind", period) + receives_disability_benefit = ( + add(person, period, p.disability_benefit_sources) > 0 + ) + qualifies = ( + applicant_or_spouse + & qualified + & (elderly | (disabled_or_blind & receives_disability_benefit)) + ) + return spm_unit.any(qualifies) * p.medical_deduction * MONTHS_IN_YEAR diff --git a/policyengine_us/variables/gov/states/mo/dss/liheap/mo_liheap.py b/policyengine_us/variables/gov/states/mo/dss/liheap/mo_liheap.py new file mode 100644 index 00000000000..6b1380d189f --- /dev/null +++ b/policyengine_us/variables/gov/states/mo/dss/liheap/mo_liheap.py @@ -0,0 +1,29 @@ +from policyengine_us.model_api import * + + +class mo_liheap(Variable): + value_type = float + entity = SPMUnit + definition_period = YEAR + unit = USD + label = "Missouri LIHEAP Energy Assistance" + documentation = "Missouri's one-time regular heating Energy Assistance payment: the amount for the household's primary heating fuel, or for a renter household whose heat is included in the rent, the rent share of annual rent up to that amount. The regular monthly rental charge is pre_subsidy_rent, since only unsubsidized renters with heat in rent are eligible. Verified for FY2026-FY2027; earlier years use model parameter backfilling and are unverified historical estimates. Energy Crisis Intervention Program (ECIP) crisis payments are excluded." + reference = ( + # PDF pages 2-4 + "https://www.sos.mo.gov/cmsimages/adrules/csr/current/13csr/13c40-19.pdf#page=2", + "https://liheapch.acf.gov/docs/2026/state-plans/MO_Plan_2026.pdf#page=9", + "https://liheapch.acf.gov/docs/2026/benefits-matricies/MO_BenefitMatrix_2026.docx", + "https://dssmanuals.mo.gov/wp-content/uploads/2022/02/liheap-application.pdf#page=1", + # PDF pages 62-63, 129 + "https://dss.mo.gov/sites/mydss/files/media/pdf/2025/10/liheap-policy-procedure-manual.pdf#page=62", + ) + defined_for = "mo_liheap_eligible" + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.mo.dss.liheap + heating_type = spm_unit("heating_type", period) + fuel_amount = p.amount[heating_type] + annual_rent = add(spm_unit, period, ["pre_subsidy_rent"]) + renter_amount = min_(annual_rent * p.rent_share, fuel_amount) + heat_in_rent = spm_unit("heat_expense_included_in_rent", period) + return where(heat_in_rent, renter_amount, fuel_amount) diff --git a/policyengine_us/variables/gov/states/mo/dss/liheap/mo_liheap_household_size.py b/policyengine_us/variables/gov/states/mo/dss/liheap/mo_liheap_household_size.py new file mode 100644 index 00000000000..aa118c64c4e --- /dev/null +++ b/policyengine_us/variables/gov/states/mo/dss/liheap/mo_liheap_household_size.py @@ -0,0 +1,18 @@ +from policyengine_us.model_api import * + + +class mo_liheap_household_size(Variable): + value_type = int + entity = SPMUnit + definition_period = YEAR + label = "Missouri LIHEAP household size" + documentation = "Number of SPM unit members who are U.S. citizens or legal immigrants. Missouri leaves members who are not citizens or legal permanent residents out of the household count but counts their income (mo_liheap_countable_income_person). The SPM unit approximates the household living in private quarters that purchases residential heat in common; roomers, boarders and live-in attendants have no inputs and are not excluded." + reference = ( + # PDF pages 2-3 + "https://www.sos.mo.gov/cmsimages/adrules/csr/current/13csr/13c40-19.pdf#page=2", + # PDF pages 40-43 + "https://dss.mo.gov/sites/mydss/files/media/pdf/2025/10/liheap-policy-procedure-manual.pdf#page=40", + ) + defined_for = StateCode.MO + + adds = ["is_citizen_or_legal_immigrant"] diff --git a/source_conflicts/candidates.yaml b/source_conflicts/candidates.yaml index 843ddcbe21c..bbe3ce296cd 100644 --- a/source_conflicts/candidates.yaml +++ b/source_conflicts/candidates.yaml @@ -3418,6 +3418,76 @@ candidates: state: ruled note: 'Ruled in October 2026 to follow worksheets; the later statute-first rule requires a model change if this credit is outside the statutory exception. Code not yet on main: mo_federal_income_tax_deduction.' +- id: us-mo:liheap-110-percent-poverty-floor + program: liheap + years: + from: 2026 + to: 2027 + type: federal-fiscal + question: Can Missouri's printed 60% SMI limit exclude a large household whose income is below the federal 110% + poverty-guideline floor? + sources: + - kind: statute + citation: 42 U.S.C. 8624(b)(2)(B) + url: https://www.law.cornell.edu/uscode/text/42/8624 + - kind: plan + citation: Missouri FFY2026 LIHEAP State Plan, section 2.1, 60% SMI for all household sizes + url: https://liheapch.acf.gov/docs/2026/state-plans/MO_Plan_2026.pdf#page=8 + - kind: guidance + citation: Missouri FFY26 Appendix K, Income Ranges and Benefit Amounts, 60% SMI monthly limits for sizes 1-20 + url: https://liheapch.acf.gov/docs/2026/benefits-matricies/MO_BenefitMatrix_2026.docx + readings: + statute: Income below 110% of the poverty guideline cannot by itself exclude the household. + other: The printed Missouri limits fall below that floor starting at household size 16 in FFY2026 and FFY2027. + example: In FFY2026, a 16-person household with $107,000 of countable income exceeds the $106,164 state limit + but is below the $107,965 floor and receives the $326 natural-gas Energy Assistance payment. + pe_us: + follows: statute + code: [] + prs: [] + state: unreviewed + note: 'The implementation applies the federal floor gov.hhs.liheap.fpg_floor with the poverty guidelines lagged + one year; no PR is open yet. Code not yet on main: mo_liheap_eligible.' +- id: us-mo:liheap-rule-income-ranges-and-payments + program: liheap + years: + from: 2026 + to: 2027 + type: federal-fiscal + question: Does Missouri Energy Assistance use the income ranges up to 135% of the poverty level and the tiered + payments in 13 CSR 40-19.020(14), or the 60% SMI limit and flat fuel amounts in the FFY2026-FFY2027 agency + documents? + sources: + - kind: regulation + citation: 13 CSR 40-19.020(6)(D) and (14), Payment Levels for Missouri (amended effective May 30, 2017) + url: https://www.sos.mo.gov/cmsimages/adrules/csr/current/13csr/13c40-19.pdf#page=4 + - kind: plan + citation: Missouri FFY2026 LIHEAP State Plan, sections 2.1, 2.5 and 2.6 + url: https://liheapch.acf.gov/docs/2026/state-plans/MO_Plan_2026.pdf#page=8 + - kind: guidance + citation: Missouri FFY26 Appendix K, Income Ranges and Benefit Amounts + url: https://liheapch.acf.gov/docs/2026/benefits-matricies/MO_BenefitMatrix_2026.docx + - kind: manual + citation: Missouri LIHEAP Policy and Procedure Manual (October 2025), Appendix K + url: https://dss.mo.gov/sites/mydss/files/media/pdf/2025/10/liheap-policy-procedure-manual.pdf#page=129 + - kind: form + citation: Missouri LIHEAP application MO 886-4576 (8-2026), Program Description + url: https://dssmanuals.mo.gov/wp-content/uploads/2022/02/liheap-application.pdf#page=1 + readings: + statute: No statute is supplied; the rule sets monthly income ranges A-F from 0 to 135% of the poverty level, + with natural gas paying $296 in range A down to $203 in range F. + other: The plan, Appendix K, manual and application set 60% SMI for every size and one amount per fuel, such as + $326 for natural gas. + example: In FFY2026, a family of four with $39,936 of countable income ($3,328 a month, 124% of the 2025 guideline) + that heats with natural gas receives $221 in the rule's range E and $326 under the agency documents. + pe_us: + follows: unknown + code: [] + prs: [] + state: unreviewed + note: 'PE-US follows the plan, Appendix K, manual and application; no FFY2026 or FFY2027 agency document uses the + 2017 rule table. The renter share follows 13 CSR 40-19.020(13) (8% of annual rent) over the 16% in the manual + and plans. Code not yet on main: mo_liheap_eligible, mo_liheap_income_limit and the mo_liheap amount parameters.' - id: us-mo:medicaid-published-dollar-limit-rounding program: medicaid years: