From c2b65ad053308193b660a392407620701ee2cf72 Mon Sep 17 00:00:00 2001 From: Ziming Date: Sat, 5 Sep 2026 15:28:51 -0400 Subject: [PATCH 01/12] Implement Kansas LIEAP heating benefit Adds ks_liheap: eligibility (150% of prior-year FPG on a citizenship-adjusted household size, categorical TANF/SSI/SNAP route, energy vulnerability and subsidized heat-in-rent exclusion), countable gross income, and the published FY2025 (100%) and FY2026 (80% adjusted) benefit matrices by fuel, income band, utility rate tier, dwelling type and household size group, with the $100/$130 minimum benefit. Sources: KEESM 13000-13400; Kansas LIHEAP State Plans FFY2025/FFY2026; LIHEAP Clearinghouse Kansas benefit matrices FY2025/FY2026. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01A6rihVz3MtZQKCzzkCib35 --- changelog.d/ks-liheap.added.md | 1 + .../ks/dcf/liheap/eligibility/fpg_limit.yaml | 17 + .../liheap/income/earned_income_min_age.yaml | 13 + .../ks/dcf/liheap/income/sources/earned.yaml | 15 + .../dcf/liheap/income/sources/unearned.yaml | 34 + .../liheap/payment/household_size_group.yaml | 26 + .../ks/dcf/liheap/payment/income_band.yaml | 32 + .../liheap/payment/matrix/electricity.yaml | 1198 +++++++++++++++++ .../liheap/payment/matrix/natural_gas.yaml | 1198 +++++++++++++++++ .../ks/dcf/liheap/payment/matrix/other.yaml | 148 ++ .../ks/dcf/liheap/payment/matrix/propane.yaml | 1198 +++++++++++++++++ .../ks/dcf/liheap/payment/min_benefit.yaml | 18 + policyengine_us/programs.yaml | 7 +- ..._liheap_categorically_income_eligible.yaml | 107 ++ .../eligibility/ks_liheap_eligible.yaml | 235 ++++ .../dcf/liheap/eligibility/ks_liheap_fpg.yaml | 119 ++ .../ks_liheap_income_eligible.yaml | 280 ++++ .../ks_liheap_countable_earned_income.yaml | 104 ++ .../income/ks_liheap_countable_income.yaml | 191 +++ .../gov/states/ks/dcf/liheap/integration.yaml | 475 +++++++ .../gov/states/ks/dcf/liheap/ks_liheap.yaml | 317 +++++ .../dcf/liheap/ks_liheap_fuel_category.yaml | 175 +++ .../dcf/liheap/ks_liheap_household_size.yaml | 158 +++ .../ks_liheap_household_size_group.yaml | 152 +++ .../liheap/payment/ks_liheap_income_band.yaml | 199 +++ .../payment/ks_liheap_matrix_amount.yaml | 668 +++++++++ ...ks_liheap_categorically_income_eligible.py | 17 + .../liheap/eligibility/ks_liheap_eligible.py | 24 + .../dcf/liheap/eligibility/ks_liheap_fpg.py | 24 + .../eligibility/ks_liheap_income_eligible.py | 24 + .../ks_liheap_countable_earned_income.py | 21 + .../income/ks_liheap_countable_income.py | 20 + .../ks_liheap_countable_unearned_income.py | 14 + .../gov/states/ks/dcf/liheap/ks_liheap.py | 20 + .../ks/dcf/liheap/ks_liheap_dwelling_type.py | 19 + .../ks/dcf/liheap/ks_liheap_fuel_category.py | 43 + .../ks/dcf/liheap/ks_liheap_household_size.py | 13 + .../dcf/liheap/ks_liheap_utility_rate_tier.py | 28 + .../payment/ks_liheap_household_size_group.py | 16 + .../liheap/payment/ks_liheap_income_band.py | 20 + .../liheap/payment/ks_liheap_matrix_amount.py | 40 + 41 files changed, 7427 insertions(+), 1 deletion(-) create mode 100644 changelog.d/ks-liheap.added.md create mode 100644 policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/fpg_limit.yaml create mode 100644 policyengine_us/parameters/gov/states/ks/dcf/liheap/income/earned_income_min_age.yaml create mode 100644 policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/earned.yaml create mode 100644 policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/unearned.yaml create mode 100644 policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/household_size_group.yaml create mode 100644 policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/income_band.yaml create mode 100644 policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/electricity.yaml create mode 100644 policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/natural_gas.yaml create mode 100644 policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/other.yaml create mode 100644 policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/propane.yaml create mode 100644 policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/min_benefit.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_categorically_income_eligible.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_eligible.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_fpg.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_eligible.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_earned_income.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_income.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/integration.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/ks_liheap.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/ks_liheap_fuel_category.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/ks_liheap_household_size.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/payment/ks_liheap_household_size_group.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/payment/ks_liheap_income_band.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/payment/ks_liheap_matrix_amount.yaml create mode 100644 policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_categorically_income_eligible.py create mode 100644 policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_eligible.py create mode 100644 policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_fpg.py create mode 100644 policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_eligible.py create mode 100644 policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_earned_income.py create mode 100644 policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_income.py create mode 100644 policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_unearned_income.py create mode 100644 policyengine_us/variables/gov/states/ks/dcf/liheap/ks_liheap.py create mode 100644 policyengine_us/variables/gov/states/ks/dcf/liheap/ks_liheap_dwelling_type.py create mode 100644 policyengine_us/variables/gov/states/ks/dcf/liheap/ks_liheap_fuel_category.py create mode 100644 policyengine_us/variables/gov/states/ks/dcf/liheap/ks_liheap_household_size.py create mode 100644 policyengine_us/variables/gov/states/ks/dcf/liheap/ks_liheap_utility_rate_tier.py create mode 100644 policyengine_us/variables/gov/states/ks/dcf/liheap/payment/ks_liheap_household_size_group.py create mode 100644 policyengine_us/variables/gov/states/ks/dcf/liheap/payment/ks_liheap_income_band.py create mode 100644 policyengine_us/variables/gov/states/ks/dcf/liheap/payment/ks_liheap_matrix_amount.py diff --git a/changelog.d/ks-liheap.added.md b/changelog.d/ks-liheap.added.md new file mode 100644 index 00000000000..c5c199bb403 --- /dev/null +++ b/changelog.d/ks-liheap.added.md @@ -0,0 +1 @@ +Kansas LIEAP (Low Income Energy Assistance Program) heating benefit: eligibility, countable income, and the FY2025-FY2026 benefit matrices. diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/fpg_limit.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/fpg_limit.yaml new file mode 100644 index 00000000000..d9a32fde2da --- /dev/null +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/fpg_limit.yaml @@ -0,0 +1,17 @@ +description: Kansas limits the Low Income Energy Assistance Program to households whose combined gross income does not exceed this multiple of the federal poverty guidelines. +values: + 2024-10-01: 1.5 + +metadata: + unit: /1 + period: year + label: Kansas LIEAP income limit as a multiple of the federal poverty guidelines + reference: + - title: Kansas LIHEAP FY2026 State Plan, Section 2.1 (heating income eligibility threshold, 150% of HHS Poverty Guidelines) + href: https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=8 + - title: Kansas LIHEAP FY2025 State Plan, Section 2.1 (heating income eligibility threshold, 150% of HHS Poverty Guidelines) + href: https://liheapch.acf.gov/docs/2025/state-plans/KS_Plan_2025.pdf#page=8 + - title: KEESM 13100 Program Summary (combined income must not exceed 150% of the federal poverty level) + href: https://content.dcf.ks.gov/ees/keesm/current/keesm13000.htm + - title: Kansas DCF Energy Assistance (LIEAP) income eligibility table + href: https://www.dcf.ks.gov/services/ees/pages/energyassistance.aspx diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/earned_income_min_age.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/earned_income_min_age.yaml new file mode 100644 index 00000000000..f2a90dcab62 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/earned_income_min_age.yaml @@ -0,0 +1,13 @@ +description: Kansas counts the earned income of household members at or above this age under the Low Income Energy Assistance Program. +values: + 2024-10-01: 18 + +metadata: + unit: year + period: year + label: Kansas LIEAP earned income minimum age + reference: + - title: Kansas LIHEAP FY2026 State Plan, Section 1.9 (earned income of a child under the age of 18 is not counted) + href: https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=7 + - title: KEESM 13320 Household Definition (a member who is or turns eighteen in the month of application has countable income) + href: https://content.dcf.ks.gov/ees/keesm/current/keesm13300.htm diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/earned.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/earned.yaml new file mode 100644 index 00000000000..d2684d81036 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/earned.yaml @@ -0,0 +1,15 @@ +description: Kansas counts these earned income sources in gross household income under the Low Income Energy Assistance Program. +values: + 2024-10-01: + - employment_income + - self_employment_income + +metadata: + unit: list + period: year + label: Kansas LIEAP countable earned income sources + reference: + - title: Kansas LIHEAP FY2026 State Plan, Section 1.8-1.9 (gross income; wages, self-employment income, contract income and commissions counted) + href: https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=6 + - title: KEESM 13320 Household Definition (income of all household members living together is used) + href: https://content.dcf.ks.gov/ees/keesm/current/keesm13300.htm diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/unearned.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/unearned.yaml new file mode 100644 index 00000000000..7253348ad11 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/unearned.yaml @@ -0,0 +1,34 @@ +description: Kansas counts these unearned income sources in gross household income under the Low Income Energy Assistance Program. +values: + 2024-10-01: + - unemployment_compensation + - strike_benefits + # SSA benefits are counted gross, including the Medicare deduction. + - social_security + - ssi + - pension_income + - general_assistance + - ks_tanf + - rental_income + - alimony_income + - child_support_received + # Plan counts "insurance payments made directly to the insured". + - workers_compensation + - veterans_benefits + # Not counted (plan boxes unchecked): loans, savings balances, one-time + # lump sums, WIA and work-study income, interest, dividends and + # royalties, insurance payments for repayment of a bill, retirement + # account balances, tax refunds, VISTA stipends, foster care payments, + # AmeriCorps payments and reimbursements. + +metadata: + unit: list + period: year + label: Kansas LIEAP countable unearned income sources + reference: + - title: Kansas LIHEAP FY2026 State Plan, Section 1.9 (countable income sources) + href: https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=6 + - title: Kansas LIHEAP FY2026 State Plan, Section 1.9 (income sources not counted) + href: https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=7 + - title: KEESM 13320 Household Definition (income of all household members living together is used) + href: https://content.dcf.ks.gov/ees/keesm/current/keesm13300.htm diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/household_size_group.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/household_size_group.yaml new file mode 100644 index 00000000000..b92ea501c29 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/household_size_group.yaml @@ -0,0 +1,26 @@ +description: Kansas assigns households to this benefit matrix size group based on the number of countable household members under the Low Income Energy Assistance Program. +brackets: + # Household size 1-4. + - threshold: + 2024-10-01: 0 + amount: + 2024-10-01: 1 + # Household size 5 and over. + - threshold: + 2024-10-01: 5 + amount: + 2024-10-01: 2 + +metadata: + type: single_amount + threshold_unit: person + amount_unit: /1 + period: year + label: Kansas LIEAP household size group + reference: + - title: Kansas LIEAP FY2026 Benefit Matrix (Household Size 1-4 and Household Size 5 and Over columns) + href: https://liheapch.acf.gov/docs/2026/benefits-matricies/KS_BenefitMatrix_2026.pdf#page=1 + - title: Kansas LIEAP FY2025 Benefit Matrix + href: https://liheapch.acf.gov/docs/2025/benefits-matricies/KS_BenefitMatrix_2025.pdf#page=1 + - title: KEESM 13330 Citizenship and Alienage Requirements (non-citizen members excluded from household size) + href: https://content.dcf.ks.gov/ees/keesm/current/keesm13300.htm diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/income_band.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/income_band.yaml new file mode 100644 index 00000000000..7b6468117ff --- /dev/null +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/income_band.yaml @@ -0,0 +1,32 @@ +description: Kansas assigns households to this benefit matrix income band based on one-month gross countable income under the Low Income Energy Assistance Program. +brackets: + - threshold: + 2024-10-01: 0 + amount: + 2024-10-01: 1 + - threshold: + 2024-10-01: 900 + amount: + 2024-10-01: 2 + - threshold: + 2024-10-01: 1_200 + amount: + 2024-10-01: 3 + - threshold: + 2024-10-01: 1_700 + amount: + 2024-10-01: 4 + +metadata: + type: single_amount + threshold_unit: currency-USD + amount_unit: /1 + period: month + label: Kansas LIEAP one-month income band + reference: + - title: Kansas LIEAP FY2026 Benefit Matrix (one-month income rows 0-899, 900-1,199, 1,200-1,699, 1,700 and over) + href: https://liheapch.acf.gov/docs/2026/benefits-matricies/KS_BenefitMatrix_2026.pdf#page=1 + - title: Kansas LIEAP FY2025 Benefit Matrix + href: https://liheapch.acf.gov/docs/2025/benefits-matricies/KS_BenefitMatrix_2025.pdf#page=1 + - title: KEESM 13230 Proof of Information Requirement (gross income of the month of application) + href: https://content.dcf.ks.gov/ees/keesm/current/keesm13200.htm diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/electricity.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/electricity.yaml new file mode 100644 index 00000000000..e38679ad549 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/electricity.yaml @@ -0,0 +1,1198 @@ +description: Kansas provides this annual benefit to households heating primarily with electricity under the Low Income Energy Assistance Program, by one-month income band, utility rate tier, dwelling type and household size group. + +# Income band 1: one-month income $0 to $899 +1: + A: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 848 + 2025-10-01: 639 + 2: + 2024-10-01: 970 + 2025-10-01: 731 + DUPLEX: + 1: + 2024-10-01: 636 + 2025-10-01: 479 + 2: + 2024-10-01: 728 + 2025-10-01: 548 + APARTMENT: + 1: + 2024-10-01: 424 + 2025-10-01: 320 + 2: + 2024-10-01: 485 + 2025-10-01: 366 + TRAILER_OTHER: + 1: + 2024-10-01: 212 + 2025-10-01: 160 + 2: + 2024-10-01: 243 + 2025-10-01: 183 + B: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 1_069 + 2025-10-01: 806 + 2: + 2024-10-01: 1_223 + 2025-10-01: 922 + DUPLEX: + 1: + 2024-10-01: 802 + 2025-10-01: 604 + 2: + 2024-10-01: 917 + 2025-10-01: 691 + APARTMENT: + 1: + 2024-10-01: 535 + 2025-10-01: 403 + 2: + 2024-10-01: 612 + 2025-10-01: 461 + TRAILER_OTHER: + 1: + 2024-10-01: 267 + 2025-10-01: 201 + 2: + 2024-10-01: 306 + 2025-10-01: 230 + C: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 1_207 + 2025-10-01: 910 + 2: + 2024-10-01: 1_381 + 2025-10-01: 1_040 + DUPLEX: + 1: + 2024-10-01: 905 + 2025-10-01: 682 + 2: + 2024-10-01: 1_036 + 2025-10-01: 780 + APARTMENT: + 1: + 2024-10-01: 604 + 2025-10-01: 455 + 2: + 2024-10-01: 691 + 2025-10-01: 520 + TRAILER_OTHER: + 1: + 2024-10-01: 302 + 2025-10-01: 227 + 2: + 2024-10-01: 345 + 2025-10-01: 260 + D: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 1_321 + 2025-10-01: 995 + 2: + 2024-10-01: 1_511 + 2025-10-01: 1_138 + DUPLEX: + 1: + 2024-10-01: 991 + 2025-10-01: 746 + 2: + 2024-10-01: 1_133 + 2025-10-01: 854 + APARTMENT: + 1: + 2024-10-01: 661 + 2025-10-01: 498 + 2: + 2024-10-01: 756 + 2025-10-01: 569 + TRAILER_OTHER: + 1: + 2024-10-01: 330 + 2025-10-01: 249 + 2: + 2024-10-01: 378 + 2025-10-01: 285 + E: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 1_384 + 2025-10-01: 1_043 + 2: + 2024-10-01: 1_584 + 2025-10-01: 1_193 + DUPLEX: + 1: + 2024-10-01: 1_038 + 2025-10-01: 782 + 2: + 2024-10-01: 1_188 + 2025-10-01: 895 + APARTMENT: + 1: + 2024-10-01: 692 + 2025-10-01: 522 + 2: + 2024-10-01: 792 + 2025-10-01: 596 + TRAILER_OTHER: + 1: + 2024-10-01: 346 + 2025-10-01: 261 + 2: + 2024-10-01: 396 + 2025-10-01: 298 + F: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 1_419 + 2025-10-01: 1_069 + 2: + 2024-10-01: 1_623 + 2025-10-01: 1_222 + DUPLEX: + 1: + 2024-10-01: 1_064 + 2025-10-01: 802 + 2: + 2024-10-01: 1_217 + 2025-10-01: 917 + APARTMENT: + 1: + 2024-10-01: 710 + 2025-10-01: 534 + 2: + 2024-10-01: 812 + 2025-10-01: 611 + TRAILER_OTHER: + 1: + 2024-10-01: 355 + 2025-10-01: 267 + 2: + 2024-10-01: 406 + 2025-10-01: 306 + G: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 1_462 + 2025-10-01: 1_102 + 2: + 2024-10-01: 1_673 + 2025-10-01: 1_261 + DUPLEX: + 1: + 2024-10-01: 1_097 + 2025-10-01: 826 + 2: + 2024-10-01: 1_255 + 2025-10-01: 946 + APARTMENT: + 1: + 2024-10-01: 731 + 2025-10-01: 551 + 2: + 2024-10-01: 837 + 2025-10-01: 630 + TRAILER_OTHER: + 1: + 2024-10-01: 366 + 2025-10-01: 275 + 2: + 2024-10-01: 418 + 2025-10-01: 315 + H: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 1_543 + 2025-10-01: 1_162 + 2: + 2024-10-01: 1_765 + 2025-10-01: 1_330 + DUPLEX: + 1: + 2024-10-01: 1_157 + 2025-10-01: 872 + 2: + 2024-10-01: 1_324 + 2025-10-01: 997 + APARTMENT: + 1: + 2024-10-01: 772 + 2025-10-01: 581 + 2: + 2024-10-01: 883 + 2025-10-01: 665 + TRAILER_OTHER: + 1: + 2024-10-01: 386 + 2025-10-01: 291 + 2: + 2024-10-01: 441 + 2025-10-01: 332 + I: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 1_633 + 2025-10-01: 1_230 + 2: + 2024-10-01: 1_868 + 2025-10-01: 1_407 + DUPLEX: + 1: + 2024-10-01: 1_225 + 2025-10-01: 923 + 2: + 2024-10-01: 1_401 + 2025-10-01: 1_055 + APARTMENT: + 1: + 2024-10-01: 817 + 2025-10-01: 615 + 2: + 2024-10-01: 934 + 2025-10-01: 704 + TRAILER_OTHER: + 1: + 2024-10-01: 408 + 2025-10-01: 308 + 2: + 2024-10-01: 467 + 2025-10-01: 352 + J: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 1_951 + 2025-10-01: 1_470 + 2: + 2024-10-01: 2_232 + 2025-10-01: 1_682 + DUPLEX: + 1: + 2024-10-01: 1_463 + 2025-10-01: 1_102 + 2: + 2024-10-01: 1_674 + 2025-10-01: 1_261 + APARTMENT: + 1: + 2024-10-01: 976 + 2025-10-01: 735 + 2: + 2024-10-01: 1_116 + 2025-10-01: 841 + TRAILER_OTHER: + 1: + 2024-10-01: 488 + 2025-10-01: 367 + 2: + 2024-10-01: 558 + 2025-10-01: 420 + +# Income band 2: one-month income $900 to $1,199 +2: + A: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 763 + 2025-10-01: 575 + 2: + 2024-10-01: 873 + 2025-10-01: 658 + DUPLEX: + 1: + 2024-10-01: 572 + 2025-10-01: 431 + 2: + 2024-10-01: 655 + 2025-10-01: 494 + APARTMENT: + 1: + 2024-10-01: 382 + 2025-10-01: 288 + 2: + 2024-10-01: 437 + 2025-10-01: 329 + TRAILER_OTHER: + 1: + 2024-10-01: 191 + 2025-10-01: 144 + 2: + 2024-10-01: 218 + 2025-10-01: 165 + B: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 962 + 2025-10-01: 725 + 2: + 2024-10-01: 1_101 + 2025-10-01: 829 + DUPLEX: + 1: + 2024-10-01: 722 + 2025-10-01: 544 + 2: + 2024-10-01: 826 + 2025-10-01: 622 + APARTMENT: + 1: + 2024-10-01: 481 + 2025-10-01: 363 + 2: + 2024-10-01: 550 + 2025-10-01: 415 + TRAILER_OTHER: + 1: + 2024-10-01: 241 + 2025-10-01: 181 + 2: + 2024-10-01: 275 + 2025-10-01: 207 + C: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 1_086 + 2025-10-01: 819 + 2: + 2024-10-01: 1_243 + 2025-10-01: 936 + DUPLEX: + 1: + 2024-10-01: 815 + 2025-10-01: 614 + 2: + 2024-10-01: 932 + 2025-10-01: 702 + APARTMENT: + 1: + 2024-10-01: 543 + 2025-10-01: 409 + 2: + 2024-10-01: 621 + 2025-10-01: 468 + TRAILER_OTHER: + 1: + 2024-10-01: 272 + 2025-10-01: 205 + 2: + 2024-10-01: 311 + 2025-10-01: 234 + D: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 1_189 + 2025-10-01: 896 + 2: + 2024-10-01: 1_360 + 2025-10-01: 1_025 + DUPLEX: + 1: + 2024-10-01: 892 + 2025-10-01: 672 + 2: + 2024-10-01: 1_020 + 2025-10-01: 768 + APARTMENT: + 1: + 2024-10-01: 594 + 2025-10-01: 448 + 2: + 2024-10-01: 680 + 2025-10-01: 512 + TRAILER_OTHER: + 1: + 2024-10-01: 297 + 2025-10-01: 224 + 2: + 2024-10-01: 340 + 2025-10-01: 256 + E: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 1_246 + 2025-10-01: 939 + 2: + 2024-10-01: 1_426 + 2025-10-01: 1_074 + DUPLEX: + 1: + 2024-10-01: 934 + 2025-10-01: 704 + 2: + 2024-10-01: 1_069 + 2025-10-01: 805 + APARTMENT: + 1: + 2024-10-01: 623 + 2025-10-01: 469 + 2: + 2024-10-01: 713 + 2025-10-01: 537 + TRAILER_OTHER: + 1: + 2024-10-01: 311 + 2025-10-01: 235 + 2: + 2024-10-01: 356 + 2025-10-01: 268 + F: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 1_277 + 2025-10-01: 962 + 2: + 2024-10-01: 1_461 + 2025-10-01: 1_100 + DUPLEX: + 1: + 2024-10-01: 958 + 2025-10-01: 721 + 2: + 2024-10-01: 1_096 + 2025-10-01: 825 + APARTMENT: + 1: + 2024-10-01: 639 + 2025-10-01: 481 + 2: + 2024-10-01: 730 + 2025-10-01: 550 + TRAILER_OTHER: + 1: + 2024-10-01: 319 + 2025-10-01: 240 + 2: + 2024-10-01: 365 + 2025-10-01: 275 + G: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 1_316 + 2025-10-01: 991 + 2: + 2024-10-01: 1_506 + 2025-10-01: 1_135 + DUPLEX: + 1: + 2024-10-01: 987 + 2025-10-01: 744 + 2: + 2024-10-01: 1_129 + 2025-10-01: 851 + APARTMENT: + 1: + 2024-10-01: 658 + 2025-10-01: 496 + 2: + 2024-10-01: 753 + 2025-10-01: 567 + TRAILER_OTHER: + 1: + 2024-10-01: 329 + 2025-10-01: 248 + 2: + 2024-10-01: 376 + 2025-10-01: 284 + H: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 1_389 + 2025-10-01: 1_046 + 2: + 2024-10-01: 1_589 + 2025-10-01: 1_197 + DUPLEX: + 1: + 2024-10-01: 1_042 + 2025-10-01: 785 + 2: + 2024-10-01: 1_191 + 2025-10-01: 897 + APARTMENT: + 1: + 2024-10-01: 694 + 2025-10-01: 523 + 2: + 2024-10-01: 794 + 2025-10-01: 598 + TRAILER_OTHER: + 1: + 2024-10-01: 347 + 2025-10-01: 262 + 2: + 2024-10-01: 397 + 2025-10-01: 299 + I: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 1_470 + 2025-10-01: 1_107 + 2: + 2024-10-01: 1_681 + 2025-10-01: 1_266 + DUPLEX: + 1: + 2024-10-01: 1_102 + 2025-10-01: 831 + 2: + 2024-10-01: 1_261 + 2025-10-01: 950 + APARTMENT: + 1: + 2024-10-01: 735 + 2025-10-01: 554 + 2: + 2024-10-01: 841 + 2025-10-01: 633 + TRAILER_OTHER: + 1: + 2024-10-01: 367 + 2025-10-01: 277 + 2: + 2024-10-01: 420 + 2025-10-01: 317 + J: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 1_756 + 2025-10-01: 1_323 + 2: + 2024-10-01: 2_009 + 2025-10-01: 1_513 + DUPLEX: + 1: + 2024-10-01: 1_317 + 2025-10-01: 992 + 2: + 2024-10-01: 1_507 + 2025-10-01: 1_135 + APARTMENT: + 1: + 2024-10-01: 878 + 2025-10-01: 661 + 2: + 2024-10-01: 1_004 + 2025-10-01: 757 + TRAILER_OTHER: + 1: + 2024-10-01: 439 + 2025-10-01: 331 + 2: + 2024-10-01: 502 + 2025-10-01: 378 + +# Income band 3: one-month income $1,200 to $1,699 +3: + A: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 678 + 2025-10-01: 511 + 2: + 2024-10-01: 776 + 2025-10-01: 585 + DUPLEX: + 1: + 2024-10-01: 509 + 2025-10-01: 384 + 2: + 2024-10-01: 582 + 2025-10-01: 439 + APARTMENT: + 1: + 2024-10-01: 339 + 2025-10-01: 256 + 2: + 2024-10-01: 388 + 2025-10-01: 292 + TRAILER_OTHER: + 1: + 2024-10-01: 170 + 2025-10-01: 128 + 2: + 2024-10-01: 194 + 2025-10-01: 146 + B: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 855 + 2025-10-01: 644 + 2: + 2024-10-01: 978 + 2025-10-01: 737 + DUPLEX: + 1: + 2024-10-01: 641 + 2025-10-01: 483 + 2: + 2024-10-01: 734 + 2025-10-01: 553 + APARTMENT: + 1: + 2024-10-01: 428 + 2025-10-01: 322 + 2: + 2024-10-01: 489 + 2025-10-01: 369 + TRAILER_OTHER: + 1: + 2024-10-01: 214 + 2025-10-01: 161 + 2: + 2024-10-01: 245 + 2025-10-01: 184 + C: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 966 + 2025-10-01: 728 + 2: + 2024-10-01: 1_105 + 2025-10-01: 832 + DUPLEX: + 1: + 2024-10-01: 724 + 2025-10-01: 546 + 2: + 2024-10-01: 829 + 2025-10-01: 624 + APARTMENT: + 1: + 2024-10-01: 483 + 2025-10-01: 364 + 2: + 2024-10-01: 552 + 2025-10-01: 416 + TRAILER_OTHER: + 1: + 2024-10-01: 241 + 2025-10-01: 182 + 2: + 2024-10-01: 276 + 2025-10-01: 208 + D: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 1_057 + 2025-10-01: 796 + 2: + 2024-10-01: 1_209 + 2025-10-01: 911 + DUPLEX: + 1: + 2024-10-01: 793 + 2025-10-01: 597 + 2: + 2024-10-01: 907 + 2025-10-01: 683 + APARTMENT: + 1: + 2024-10-01: 528 + 2025-10-01: 398 + 2: + 2024-10-01: 604 + 2025-10-01: 455 + TRAILER_OTHER: + 1: + 2024-10-01: 264 + 2025-10-01: 199 + 2: + 2024-10-01: 302 + 2025-10-01: 228 + E: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 1_107 + 2025-10-01: 835 + 2: + 2024-10-01: 1_267 + 2025-10-01: 954 + DUPLEX: + 1: + 2024-10-01: 830 + 2025-10-01: 626 + 2: + 2024-10-01: 950 + 2025-10-01: 716 + APARTMENT: + 1: + 2024-10-01: 554 + 2025-10-01: 417 + 2: + 2024-10-01: 634 + 2025-10-01: 477 + TRAILER_OTHER: + 1: + 2024-10-01: 277 + 2025-10-01: 209 + 2: + 2024-10-01: 317 + 2025-10-01: 239 + F: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 1_135 + 2025-10-01: 855 + 2: + 2024-10-01: 1_298 + 2025-10-01: 978 + DUPLEX: + 1: + 2024-10-01: 851 + 2025-10-01: 641 + 2: + 2024-10-01: 974 + 2025-10-01: 733 + APARTMENT: + 1: + 2024-10-01: 568 + 2025-10-01: 428 + 2: + 2024-10-01: 649 + 2025-10-01: 489 + TRAILER_OTHER: + 1: + 2024-10-01: 284 + 2025-10-01: 214 + 2: + 2024-10-01: 325 + 2025-10-01: 244 + G: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 1_170 + 2025-10-01: 881 + 2: + 2024-10-01: 1_338 + 2025-10-01: 1_009 + DUPLEX: + 1: + 2024-10-01: 877 + 2025-10-01: 661 + 2: + 2024-10-01: 1_004 + 2025-10-01: 756 + APARTMENT: + 1: + 2024-10-01: 585 + 2025-10-01: 441 + 2: + 2024-10-01: 669 + 2025-10-01: 504 + TRAILER_OTHER: + 1: + 2024-10-01: 292 + 2025-10-01: 220 + 2: + 2024-10-01: 335 + 2025-10-01: 252 + H: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 1_234 + 2025-10-01: 930 + 2: + 2024-10-01: 1_412 + 2025-10-01: 1_064 + DUPLEX: + 1: + 2024-10-01: 926 + 2025-10-01: 697 + 2: + 2024-10-01: 1_059 + 2025-10-01: 798 + APARTMENT: + 1: + 2024-10-01: 617 + 2025-10-01: 465 + 2: + 2024-10-01: 706 + 2025-10-01: 532 + TRAILER_OTHER: + 1: + 2024-10-01: 309 + 2025-10-01: 232 + 2: + 2024-10-01: 353 + 2025-10-01: 266 + I: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 1_306 + 2025-10-01: 984 + 2: + 2024-10-01: 1_494 + 2025-10-01: 1_126 + DUPLEX: + 1: + 2024-10-01: 980 + 2025-10-01: 738 + 2: + 2024-10-01: 1_121 + 2025-10-01: 844 + APARTMENT: + 1: + 2024-10-01: 653 + 2025-10-01: 492 + 2: + 2024-10-01: 747 + 2025-10-01: 563 + TRAILER_OTHER: + 1: + 2024-10-01: 327 + 2025-10-01: 246 + 2: + 2024-10-01: 374 + 2025-10-01: 281 + J: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 1_561 + 2025-10-01: 1_176 + 2: + 2024-10-01: 1_786 + 2025-10-01: 1_345 + DUPLEX: + 1: + 2024-10-01: 1_171 + 2025-10-01: 882 + 2: + 2024-10-01: 1_339 + 2025-10-01: 1_009 + APARTMENT: + 1: + 2024-10-01: 780 + 2025-10-01: 588 + 2: + 2024-10-01: 893 + 2025-10-01: 673 + TRAILER_OTHER: + 1: + 2024-10-01: 390 + 2025-10-01: 294 + 2: + 2024-10-01: 446 + 2025-10-01: 336 + +# Income band 4: one-month income $1,700 and over +4: + A: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 594 + 2025-10-01: 447 + 2: + 2024-10-01: 679 + 2025-10-01: 512 + DUPLEX: + 1: + 2024-10-01: 445 + 2025-10-01: 336 + 2: + 2024-10-01: 509 + 2025-10-01: 384 + APARTMENT: + 1: + 2024-10-01: 297 + 2025-10-01: 224 + 2: + 2024-10-01: 340 + 2025-10-01: 256 + TRAILER_OTHER: + 1: + 2024-10-01: 148 + 2025-10-01: 112 + 2: + 2024-10-01: 170 + 2025-10-01: 128 + B: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 748 + 2025-10-01: 564 + 2: + 2024-10-01: 856 + 2025-10-01: 645 + DUPLEX: + 1: + 2024-10-01: 561 + 2025-10-01: 423 + 2: + 2024-10-01: 642 + 2025-10-01: 484 + APARTMENT: + 1: + 2024-10-01: 374 + 2025-10-01: 282 + 2: + 2024-10-01: 428 + 2025-10-01: 323 + TRAILER_OTHER: + 1: + 2024-10-01: 187 + 2025-10-01: 141 + 2: + 2024-10-01: 214 + 2025-10-01: 161 + C: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 845 + 2025-10-01: 637 + 2: + 2024-10-01: 967 + 2025-10-01: 728 + DUPLEX: + 1: + 2024-10-01: 634 + 2025-10-01: 478 + 2: + 2024-10-01: 725 + 2025-10-01: 546 + APARTMENT: + 1: + 2024-10-01: 422 + 2025-10-01: 318 + 2: + 2024-10-01: 483 + 2025-10-01: 364 + TRAILER_OTHER: + 1: + 2024-10-01: 211 + 2025-10-01: 159 + 2: + 2024-10-01: 242 + 2025-10-01: 182 + D: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 925 + 2025-10-01: 697 + 2: + 2024-10-01: 1_058 + 2025-10-01: 797 + DUPLEX: + 1: + 2024-10-01: 694 + 2025-10-01: 522 + 2: + 2024-10-01: 793 + 2025-10-01: 598 + APARTMENT: + 1: + 2024-10-01: 462 + 2025-10-01: 348 + 2: + 2024-10-01: 529 + 2025-10-01: 398 + TRAILER_OTHER: + 1: + 2024-10-01: 231 + 2025-10-01: 174 + 2: + 2024-10-01: 264 + 2025-10-01: 199 + E: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 969 + 2025-10-01: 730 + 2: + 2024-10-01: 1_109 + 2025-10-01: 835 + DUPLEX: + 1: + 2024-10-01: 727 + 2025-10-01: 548 + 2: + 2024-10-01: 832 + 2025-10-01: 626 + APARTMENT: + 1: + 2024-10-01: 484 + 2025-10-01: 365 + 2: + 2024-10-01: 554 + 2025-10-01: 417 + TRAILER_OTHER: + 1: + 2024-10-01: 242 + 2025-10-01: 183 + 2: + 2024-10-01: 277 + 2025-10-01: 209 + F: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 993 + 2025-10-01: 748 + 2: + 2024-10-01: 1_136 + 2025-10-01: 856 + DUPLEX: + 1: + 2024-10-01: 745 + 2025-10-01: 561 + 2: + 2024-10-01: 852 + 2025-10-01: 642 + APARTMENT: + 1: + 2024-10-01: 497 + 2025-10-01: 374 + 2: + 2024-10-01: 568 + 2025-10-01: 428 + TRAILER_OTHER: + 1: + 2024-10-01: 248 + 2025-10-01: 187 + 2: + 2024-10-01: 284 + 2025-10-01: 214 + G: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 1_023 + 2025-10-01: 771 + 2: + 2024-10-01: 1_171 + 2025-10-01: 883 + DUPLEX: + 1: + 2024-10-01: 768 + 2025-10-01: 578 + 2: + 2024-10-01: 878 + 2025-10-01: 662 + APARTMENT: + 1: + 2024-10-01: 512 + 2025-10-01: 386 + 2: + 2024-10-01: 586 + 2025-10-01: 441 + TRAILER_OTHER: + 1: + 2024-10-01: 256 + 2025-10-01: 193 + 2: + 2024-10-01: 293 + 2025-10-01: 221 + H: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 1_080 + 2025-10-01: 814 + 2: + 2024-10-01: 1_236 + 2025-10-01: 931 + DUPLEX: + 1: + 2024-10-01: 810 + 2025-10-01: 610 + 2: + 2024-10-01: 927 + 2025-10-01: 698 + APARTMENT: + 1: + 2024-10-01: 540 + 2025-10-01: 407 + 2: + 2024-10-01: 618 + 2025-10-01: 465 + TRAILER_OTHER: + 1: + 2024-10-01: 270 + 2025-10-01: 203 + 2: + 2024-10-01: 309 + 2025-10-01: 233 + I: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 1_143 + 2025-10-01: 861 + 2: + 2024-10-01: 1_308 + 2025-10-01: 985 + DUPLEX: + 1: + 2024-10-01: 857 + 2025-10-01: 646 + 2: + 2024-10-01: 981 + 2025-10-01: 739 + APARTMENT: + 1: + 2024-10-01: 572 + 2025-10-01: 431 + 2: + 2024-10-01: 654 + 2025-10-01: 493 + TRAILER_OTHER: + 1: + 2024-10-01: 286 + 2025-10-01: 215 + 2: + 2024-10-01: 327 + 2025-10-01: 246 + J: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 1_366 + 2025-10-01: 1_029 + 2: + 2024-10-01: 1_562 + 2025-10-01: 1_177 + DUPLEX: + 1: + 2024-10-01: 1_024 + 2025-10-01: 772 + 2: + 2024-10-01: 1_172 + 2025-10-01: 883 + APARTMENT: + 1: + 2024-10-01: 683 + 2025-10-01: 514 + 2: + 2024-10-01: 781 + 2025-10-01: 589 + TRAILER_OTHER: + 1: + 2024-10-01: 341 + 2025-10-01: 257 + 2: + 2024-10-01: 391 + 2025-10-01: 294 + +metadata: + propagate_metadata_to_children: true + period: year + unit: currency-USD + label: Kansas LIEAP electricity benefit matrix + breakdown: + - range(1, 5) # one-month income band + - ks_liheap_utility_rate_tier + - ks_liheap_dwelling_type + - range(1, 3) # household size group (1 = size 1-4, 2 = size 5+) + breakdown_labels: + - One-month income band + - Utility rate tier + - Dwelling type + - Household size group + reference: + - title: Kansas LIEAP FY2026 Benefit Matrix, Electricity (Benefit Adjustment @ 80% table) + href: https://liheapch.acf.gov/docs/2026/benefits-matricies/KS_BenefitMatrix_2026.pdf#page=2 + - title: Kansas LIEAP FY2025 Benefit Matrix, Electricity (Ben Adj 100.0%) + href: https://liheapch.acf.gov/docs/2025/benefits-matricies/KS_BenefitMatrix_2025.pdf#page=1 + - title: Kansas LIHEAP FY2026 State Plan, Section 2.5 (benefit variables) + href: https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=9 + - title: KEESM 13410 Benefit Levels + href: https://content.dcf.ks.gov/ees/keesm/current/keesm13400.htm diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/natural_gas.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/natural_gas.yaml new file mode 100644 index 00000000000..56e0da0332a --- /dev/null +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/natural_gas.yaml @@ -0,0 +1,1198 @@ +description: Kansas provides this annual benefit to households heating primarily with natural gas under the Low Income Energy Assistance Program, by one-month income band, utility rate tier, dwelling type and household size group. + +# Income band 1: one-month income $0 to $899 +1: + A: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 640 + 2025-10-01: 482 + 2: + 2024-10-01: 732 + 2025-10-01: 551 + DUPLEX: + 1: + 2024-10-01: 480 + 2025-10-01: 362 + 2: + 2024-10-01: 549 + 2025-10-01: 413 + APARTMENT: + 1: + 2024-10-01: 320 + 2025-10-01: 241 + 2: + 2024-10-01: 366 + 2025-10-01: 276 + TRAILER_OTHER: + 1: + 2024-10-01: 160 + 2025-10-01: 121 + 2: + 2024-10-01: 183 + 2025-10-01: 138 + B: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 776 + 2025-10-01: 585 + 2: + 2024-10-01: 888 + 2025-10-01: 669 + DUPLEX: + 1: + 2024-10-01: 582 + 2025-10-01: 439 + 2: + 2024-10-01: 666 + 2025-10-01: 502 + APARTMENT: + 1: + 2024-10-01: 388 + 2025-10-01: 292 + 2: + 2024-10-01: 444 + 2025-10-01: 334 + TRAILER_OTHER: + 1: + 2024-10-01: 194 + 2025-10-01: 146 + 2: + 2024-10-01: 222 + 2025-10-01: 167 + C: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 880 + 2025-10-01: 662 + 2: + 2024-10-01: 1_006 + 2025-10-01: 758 + DUPLEX: + 1: + 2024-10-01: 660 + 2025-10-01: 497 + 2: + 2024-10-01: 755 + 2025-10-01: 569 + APARTMENT: + 1: + 2024-10-01: 440 + 2025-10-01: 331 + 2: + 2024-10-01: 503 + 2025-10-01: 379 + TRAILER_OTHER: + 1: + 2024-10-01: 220 + 2025-10-01: 166 + 2: + 2024-10-01: 252 + 2025-10-01: 190 + D: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 920 + 2025-10-01: 693 + 2: + 2024-10-01: 1_053 + 2025-10-01: 793 + DUPLEX: + 1: + 2024-10-01: 690 + 2025-10-01: 520 + 2: + 2024-10-01: 790 + 2025-10-01: 595 + APARTMENT: + 1: + 2024-10-01: 460 + 2025-10-01: 346 + 2: + 2024-10-01: 527 + 2025-10-01: 396 + TRAILER_OTHER: + 1: + 2024-10-01: 230 + 2025-10-01: 173 + 2: + 2024-10-01: 263 + 2025-10-01: 198 + E: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 941 + 2025-10-01: 709 + 2: + 2024-10-01: 1_076 + 2025-10-01: 810 + DUPLEX: + 1: + 2024-10-01: 706 + 2025-10-01: 532 + 2: + 2024-10-01: 807 + 2025-10-01: 608 + APARTMENT: + 1: + 2024-10-01: 471 + 2025-10-01: 354 + 2: + 2024-10-01: 538 + 2025-10-01: 405 + TRAILER_OTHER: + 1: + 2024-10-01: 235 + 2025-10-01: 177 + 2: + 2024-10-01: 269 + 2025-10-01: 203 + F: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 941 + 2025-10-01: 709 + 2: + 2024-10-01: 1_077 + 2025-10-01: 811 + DUPLEX: + 1: + 2024-10-01: 706 + 2025-10-01: 532 + 2: + 2024-10-01: 808 + 2025-10-01: 608 + APARTMENT: + 1: + 2024-10-01: 471 + 2025-10-01: 354 + 2: + 2024-10-01: 539 + 2025-10-01: 406 + TRAILER_OTHER: + 1: + 2024-10-01: 235 + 2025-10-01: 177 + 2: + 2024-10-01: 269 + 2025-10-01: 203 + G: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 1_006 + 2025-10-01: 758 + 2: + 2024-10-01: 1_151 + 2025-10-01: 867 + DUPLEX: + 1: + 2024-10-01: 755 + 2025-10-01: 568 + 2: + 2024-10-01: 863 + 2025-10-01: 650 + APARTMENT: + 1: + 2024-10-01: 503 + 2025-10-01: 379 + 2: + 2024-10-01: 576 + 2025-10-01: 434 + TRAILER_OTHER: + 1: + 2024-10-01: 252 + 2025-10-01: 189 + 2: + 2024-10-01: 288 + 2025-10-01: 217 + H: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 1_107 + 2025-10-01: 834 + 2: + 2024-10-01: 1_266 + 2025-10-01: 954 + DUPLEX: + 1: + 2024-10-01: 830 + 2025-10-01: 625 + 2: + 2024-10-01: 950 + 2025-10-01: 716 + APARTMENT: + 1: + 2024-10-01: 554 + 2025-10-01: 417 + 2: + 2024-10-01: 633 + 2025-10-01: 477 + TRAILER_OTHER: + 1: + 2024-10-01: 277 + 2025-10-01: 208 + 2: + 2024-10-01: 317 + 2025-10-01: 239 + I: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 1_222 + 2025-10-01: 921 + 2: + 2024-10-01: 1_398 + 2025-10-01: 1_053 + DUPLEX: + 1: + 2024-10-01: 917 + 2025-10-01: 691 + 2: + 2024-10-01: 1_049 + 2025-10-01: 790 + APARTMENT: + 1: + 2024-10-01: 611 + 2025-10-01: 460 + 2: + 2024-10-01: 699 + 2025-10-01: 526 + TRAILER_OTHER: + 1: + 2024-10-01: 306 + 2025-10-01: 230 + 2: + 2024-10-01: 350 + 2025-10-01: 263 + J: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 1_508 + 2025-10-01: 1_136 + 2: + 2024-10-01: 1_725 + 2025-10-01: 1_299 + DUPLEX: + 1: + 2024-10-01: 1_131 + 2025-10-01: 852 + 2: + 2024-10-01: 1_294 + 2025-10-01: 974 + APARTMENT: + 1: + 2024-10-01: 754 + 2025-10-01: 568 + 2: + 2024-10-01: 863 + 2025-10-01: 650 + TRAILER_OTHER: + 1: + 2024-10-01: 377 + 2025-10-01: 284 + 2: + 2024-10-01: 431 + 2025-10-01: 325 + +# Income band 2: one-month income $900 to $1,199 +2: + A: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 576 + 2025-10-01: 434 + 2: + 2024-10-01: 659 + 2025-10-01: 496 + DUPLEX: + 1: + 2024-10-01: 432 + 2025-10-01: 326 + 2: + 2024-10-01: 494 + 2025-10-01: 372 + APARTMENT: + 1: + 2024-10-01: 288 + 2025-10-01: 217 + 2: + 2024-10-01: 329 + 2025-10-01: 248 + TRAILER_OTHER: + 1: + 2024-10-01: 144 + 2025-10-01: 109 + 2: + 2024-10-01: 165 + 2025-10-01: 124 + B: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 698 + 2025-10-01: 526 + 2: + 2024-10-01: 799 + 2025-10-01: 602 + DUPLEX: + 1: + 2024-10-01: 524 + 2025-10-01: 395 + 2: + 2024-10-01: 599 + 2025-10-01: 451 + APARTMENT: + 1: + 2024-10-01: 349 + 2025-10-01: 263 + 2: + 2024-10-01: 400 + 2025-10-01: 301 + TRAILER_OTHER: + 1: + 2024-10-01: 175 + 2025-10-01: 132 + 2: + 2024-10-01: 200 + 2025-10-01: 150 + C: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 792 + 2025-10-01: 596 + 2: + 2024-10-01: 905 + 2025-10-01: 683 + DUPLEX: + 1: + 2024-10-01: 594 + 2025-10-01: 447 + 2: + 2024-10-01: 679 + 2025-10-01: 512 + APARTMENT: + 1: + 2024-10-01: 396 + 2025-10-01: 298 + 2: + 2024-10-01: 453 + 2025-10-01: 341 + TRAILER_OTHER: + 1: + 2024-10-01: 198 + 2025-10-01: 149 + 2: + 2024-10-01: 226 + 2025-10-01: 171 + D: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 828 + 2025-10-01: 624 + 2: + 2024-10-01: 948 + 2025-10-01: 714 + DUPLEX: + 1: + 2024-10-01: 621 + 2025-10-01: 468 + 2: + 2024-10-01: 711 + 2025-10-01: 535 + APARTMENT: + 1: + 2024-10-01: 414 + 2025-10-01: 312 + 2: + 2024-10-01: 474 + 2025-10-01: 357 + TRAILER_OTHER: + 1: + 2024-10-01: 207 + 2025-10-01: 156 + 2: + 2024-10-01: 237 + 2025-10-01: 178 + E: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 847 + 2025-10-01: 638 + 2: + 2024-10-01: 968 + 2025-10-01: 729 + DUPLEX: + 1: + 2024-10-01: 635 + 2025-10-01: 478 + 2: + 2024-10-01: 726 + 2025-10-01: 547 + APARTMENT: + 1: + 2024-10-01: 423 + 2025-10-01: 319 + 2: + 2024-10-01: 484 + 2025-10-01: 365 + TRAILER_OTHER: + 1: + 2024-10-01: 212 + 2025-10-01: 159 + 2: + 2024-10-01: 242 + 2025-10-01: 182 + F: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 847 + 2025-10-01: 638 + 2: + 2024-10-01: 969 + 2025-10-01: 730 + DUPLEX: + 1: + 2024-10-01: 635 + 2025-10-01: 478 + 2: + 2024-10-01: 727 + 2025-10-01: 548 + APARTMENT: + 1: + 2024-10-01: 423 + 2025-10-01: 319 + 2: + 2024-10-01: 485 + 2025-10-01: 365 + TRAILER_OTHER: + 1: + 2024-10-01: 212 + 2025-10-01: 159 + 2: + 2024-10-01: 242 + 2025-10-01: 183 + G: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 905 + 2025-10-01: 682 + 2: + 2024-10-01: 1_036 + 2025-10-01: 780 + DUPLEX: + 1: + 2024-10-01: 679 + 2025-10-01: 511 + 2: + 2024-10-01: 777 + 2025-10-01: 585 + APARTMENT: + 1: + 2024-10-01: 453 + 2025-10-01: 341 + 2: + 2024-10-01: 518 + 2025-10-01: 390 + TRAILER_OTHER: + 1: + 2024-10-01: 226 + 2025-10-01: 170 + 2: + 2024-10-01: 259 + 2025-10-01: 195 + H: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 996 + 2025-10-01: 750 + 2: + 2024-10-01: 1_139 + 2025-10-01: 859 + DUPLEX: + 1: + 2024-10-01: 747 + 2025-10-01: 563 + 2: + 2024-10-01: 855 + 2025-10-01: 644 + APARTMENT: + 1: + 2024-10-01: 498 + 2025-10-01: 375 + 2: + 2024-10-01: 570 + 2025-10-01: 429 + TRAILER_OTHER: + 1: + 2024-10-01: 249 + 2025-10-01: 188 + 2: + 2024-10-01: 285 + 2025-10-01: 215 + I: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 1_100 + 2025-10-01: 829 + 2: + 2024-10-01: 1_258 + 2025-10-01: 948 + DUPLEX: + 1: + 2024-10-01: 825 + 2025-10-01: 622 + 2: + 2024-10-01: 944 + 2025-10-01: 711 + APARTMENT: + 1: + 2024-10-01: 550 + 2025-10-01: 414 + 2: + 2024-10-01: 629 + 2025-10-01: 474 + TRAILER_OTHER: + 1: + 2024-10-01: 275 + 2025-10-01: 207 + 2: + 2024-10-01: 315 + 2025-10-01: 237 + J: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 1_357 + 2025-10-01: 1_022 + 2: + 2024-10-01: 1_553 + 2025-10-01: 1_169 + DUPLEX: + 1: + 2024-10-01: 1_018 + 2025-10-01: 767 + 2: + 2024-10-01: 1_164 + 2025-10-01: 877 + APARTMENT: + 1: + 2024-10-01: 679 + 2025-10-01: 511 + 2: + 2024-10-01: 776 + 2025-10-01: 585 + TRAILER_OTHER: + 1: + 2024-10-01: 339 + 2025-10-01: 256 + 2: + 2024-10-01: 388 + 2025-10-01: 292 + +# Income band 3: one-month income $1,200 to $1,699 +3: + A: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 512 + 2025-10-01: 386 + 2: + 2024-10-01: 586 + 2025-10-01: 441 + DUPLEX: + 1: + 2024-10-01: 384 + 2025-10-01: 289 + 2: + 2024-10-01: 439 + 2025-10-01: 331 + APARTMENT: + 1: + 2024-10-01: 256 + 2025-10-01: 193 + 2: + 2024-10-01: 293 + 2025-10-01: 220 + TRAILER_OTHER: + 1: + 2024-10-01: 128 + 2025-10-01: 96 + 2: + 2024-10-01: 146 + 2025-10-01: 110 + B: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 621 + 2025-10-01: 468 + 2: + 2024-10-01: 710 + 2025-10-01: 535 + DUPLEX: + 1: + 2024-10-01: 466 + 2025-10-01: 351 + 2: + 2024-10-01: 533 + 2025-10-01: 401 + APARTMENT: + 1: + 2024-10-01: 310 + 2025-10-01: 234 + 2: + 2024-10-01: 355 + 2025-10-01: 268 + TRAILER_OTHER: + 1: + 2024-10-01: 155 + 2025-10-01: 117 + 2: + 2024-10-01: 178 + 2025-10-01: 134 + C: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 704 + 2025-10-01: 530 + 2: + 2024-10-01: 805 + 2025-10-01: 607 + DUPLEX: + 1: + 2024-10-01: 528 + 2025-10-01: 397 + 2: + 2024-10-01: 604 + 2025-10-01: 455 + APARTMENT: + 1: + 2024-10-01: 352 + 2025-10-01: 265 + 2: + 2024-10-01: 402 + 2025-10-01: 303 + TRAILER_OTHER: + 1: + 2024-10-01: 176 + 2025-10-01: 132 + 2: + 2024-10-01: 201 + 2025-10-01: 152 + D: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 736 + 2025-10-01: 554 + 2: + 2024-10-01: 842 + 2025-10-01: 634 + DUPLEX: + 1: + 2024-10-01: 552 + 2025-10-01: 416 + 2: + 2024-10-01: 632 + 2025-10-01: 476 + APARTMENT: + 1: + 2024-10-01: 368 + 2025-10-01: 277 + 2: + 2024-10-01: 421 + 2025-10-01: 317 + TRAILER_OTHER: + 1: + 2024-10-01: 184 + 2025-10-01: 139 + 2: + 2024-10-01: 211 + 2025-10-01: 159 + E: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 753 + 2025-10-01: 567 + 2: + 2024-10-01: 861 + 2025-10-01: 648 + DUPLEX: + 1: + 2024-10-01: 565 + 2025-10-01: 425 + 2: + 2024-10-01: 646 + 2025-10-01: 486 + APARTMENT: + 1: + 2024-10-01: 376 + 2025-10-01: 284 + 2: + 2024-10-01: 430 + 2025-10-01: 324 + TRAILER_OTHER: + 1: + 2024-10-01: 188 + 2025-10-01: 142 + 2: + 2024-10-01: 215 + 2025-10-01: 162 + F: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 753 + 2025-10-01: 567 + 2: + 2024-10-01: 862 + 2025-10-01: 649 + DUPLEX: + 1: + 2024-10-01: 565 + 2025-10-01: 425 + 2: + 2024-10-01: 646 + 2025-10-01: 487 + APARTMENT: + 1: + 2024-10-01: 376 + 2025-10-01: 284 + 2: + 2024-10-01: 431 + 2025-10-01: 324 + TRAILER_OTHER: + 1: + 2024-10-01: 188 + 2025-10-01: 142 + 2: + 2024-10-01: 215 + 2025-10-01: 162 + G: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 805 + 2025-10-01: 606 + 2: + 2024-10-01: 921 + 2025-10-01: 694 + DUPLEX: + 1: + 2024-10-01: 604 + 2025-10-01: 455 + 2: + 2024-10-01: 691 + 2025-10-01: 520 + APARTMENT: + 1: + 2024-10-01: 402 + 2025-10-01: 303 + 2: + 2024-10-01: 460 + 2025-10-01: 347 + TRAILER_OTHER: + 1: + 2024-10-01: 201 + 2025-10-01: 152 + 2: + 2024-10-01: 230 + 2025-10-01: 173 + H: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 886 + 2025-10-01: 667 + 2: + 2024-10-01: 1_013 + 2025-10-01: 764 + DUPLEX: + 1: + 2024-10-01: 664 + 2025-10-01: 500 + 2: + 2024-10-01: 760 + 2025-10-01: 573 + APARTMENT: + 1: + 2024-10-01: 443 + 2025-10-01: 333 + 2: + 2024-10-01: 506 + 2025-10-01: 382 + TRAILER_OTHER: + 1: + 2024-10-01: 221 + 2025-10-01: 167 + 2: + 2024-10-01: 253 + 2025-10-01: 191 + I: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 978 + 2025-10-01: 737 + 2: + 2024-10-01: 1_118 + 2025-10-01: 842 + DUPLEX: + 1: + 2024-10-01: 733 + 2025-10-01: 552 + 2: + 2024-10-01: 839 + 2025-10-01: 632 + APARTMENT: + 1: + 2024-10-01: 489 + 2025-10-01: 368 + 2: + 2024-10-01: 559 + 2025-10-01: 421 + TRAILER_OTHER: + 1: + 2024-10-01: 244 + 2025-10-01: 184 + 2: + 2024-10-01: 280 + 2025-10-01: 211 + J: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 1_206 + 2025-10-01: 909 + 2: + 2024-10-01: 1_380 + 2025-10-01: 1_039 + DUPLEX: + 1: + 2024-10-01: 905 + 2025-10-01: 682 + 2: + 2024-10-01: 1_035 + 2025-10-01: 780 + APARTMENT: + 1: + 2024-10-01: 603 + 2025-10-01: 454 + 2: + 2024-10-01: 690 + 2025-10-01: 520 + TRAILER_OTHER: + 1: + 2024-10-01: 302 + 2025-10-01: 227 + 2: + 2024-10-01: 345 + 2025-10-01: 260 + +# Income band 4: one-month income $1,700 and over +4: + A: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 448 + 2025-10-01: 338 + 2: + 2024-10-01: 512 + 2025-10-01: 386 + DUPLEX: + 1: + 2024-10-01: 336 + 2025-10-01: 253 + 2: + 2024-10-01: 384 + 2025-10-01: 289 + APARTMENT: + 1: + 2024-10-01: 224 + 2025-10-01: 169 + 2: + 2024-10-01: 256 + 2025-10-01: 193 + TRAILER_OTHER: + 1: + 2024-10-01: 112 + 2025-10-01: 84 + 2: + 2024-10-01: 128 + 2025-10-01: 96 + B: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 543 + 2025-10-01: 409 + 2: + 2024-10-01: 622 + 2025-10-01: 468 + DUPLEX: + 1: + 2024-10-01: 407 + 2025-10-01: 307 + 2: + 2024-10-01: 466 + 2025-10-01: 351 + APARTMENT: + 1: + 2024-10-01: 272 + 2025-10-01: 205 + 2: + 2024-10-01: 311 + 2025-10-01: 234 + TRAILER_OTHER: + 1: + 2024-10-01: 136 + 2025-10-01: 102 + 2: + 2024-10-01: 155 + 2025-10-01: 117 + C: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 616 + 2025-10-01: 464 + 2: + 2024-10-01: 704 + 2025-10-01: 531 + DUPLEX: + 1: + 2024-10-01: 462 + 2025-10-01: 348 + 2: + 2024-10-01: 528 + 2025-10-01: 398 + APARTMENT: + 1: + 2024-10-01: 308 + 2025-10-01: 232 + 2: + 2024-10-01: 352 + 2025-10-01: 265 + TRAILER_OTHER: + 1: + 2024-10-01: 154 + 2025-10-01: 116 + 2: + 2024-10-01: 176 + 2025-10-01: 133 + D: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 644 + 2025-10-01: 485 + 2: + 2024-10-01: 737 + 2025-10-01: 555 + DUPLEX: + 1: + 2024-10-01: 483 + 2025-10-01: 364 + 2: + 2024-10-01: 553 + 2025-10-01: 416 + APARTMENT: + 1: + 2024-10-01: 322 + 2025-10-01: 242 + 2: + 2024-10-01: 369 + 2025-10-01: 277 + TRAILER_OTHER: + 1: + 2024-10-01: 161 + 2025-10-01: 121 + 2: + 2024-10-01: 184 + 2025-10-01: 139 + E: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 659 + 2025-10-01: 496 + 2: + 2024-10-01: 753 + 2025-10-01: 567 + DUPLEX: + 1: + 2024-10-01: 494 + 2025-10-01: 372 + 2: + 2024-10-01: 565 + 2025-10-01: 425 + APARTMENT: + 1: + 2024-10-01: 329 + 2025-10-01: 248 + 2: + 2024-10-01: 377 + 2025-10-01: 284 + TRAILER_OTHER: + 1: + 2024-10-01: 165 + 2025-10-01: 124 + 2: + 2024-10-01: 188 + 2025-10-01: 142 + F: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 659 + 2025-10-01: 496 + 2: + 2024-10-01: 754 + 2025-10-01: 568 + DUPLEX: + 1: + 2024-10-01: 494 + 2025-10-01: 372 + 2: + 2024-10-01: 565 + 2025-10-01: 426 + APARTMENT: + 1: + 2024-10-01: 329 + 2025-10-01: 248 + 2: + 2024-10-01: 377 + 2025-10-01: 284 + TRAILER_OTHER: + 1: + 2024-10-01: 165 + 2025-10-01: 124 + 2: + 2024-10-01: 188 + 2025-10-01: 142 + G: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 704 + 2025-10-01: 530 + 2: + 2024-10-01: 806 + 2025-10-01: 607 + DUPLEX: + 1: + 2024-10-01: 528 + 2025-10-01: 398 + 2: + 2024-10-01: 604 + 2025-10-01: 455 + APARTMENT: + 1: + 2024-10-01: 352 + 2025-10-01: 265 + 2: + 2024-10-01: 403 + 2025-10-01: 304 + TRAILER_OTHER: + 1: + 2024-10-01: 176 + 2025-10-01: 133 + 2: + 2024-10-01: 201 + 2025-10-01: 152 + H: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 775 + 2025-10-01: 584 + 2: + 2024-10-01: 886 + 2025-10-01: 668 + DUPLEX: + 1: + 2024-10-01: 581 + 2025-10-01: 438 + 2: + 2024-10-01: 665 + 2025-10-01: 501 + APARTMENT: + 1: + 2024-10-01: 387 + 2025-10-01: 292 + 2: + 2024-10-01: 443 + 2025-10-01: 334 + TRAILER_OTHER: + 1: + 2024-10-01: 194 + 2025-10-01: 146 + 2: + 2024-10-01: 222 + 2025-10-01: 167 + I: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 855 + 2025-10-01: 645 + 2: + 2024-10-01: 979 + 2025-10-01: 737 + DUPLEX: + 1: + 2024-10-01: 642 + 2025-10-01: 483 + 2: + 2024-10-01: 734 + 2025-10-01: 553 + APARTMENT: + 1: + 2024-10-01: 428 + 2025-10-01: 322 + 2: + 2024-10-01: 489 + 2025-10-01: 368 + TRAILER_OTHER: + 1: + 2024-10-01: 214 + 2025-10-01: 161 + 2: + 2024-10-01: 245 + 2025-10-01: 184 + J: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 1_056 + 2025-10-01: 795 + 2: + 2024-10-01: 1_208 + 2025-10-01: 909 + DUPLEX: + 1: + 2024-10-01: 792 + 2025-10-01: 596 + 2: + 2024-10-01: 906 + 2025-10-01: 682 + APARTMENT: + 1: + 2024-10-01: 528 + 2025-10-01: 398 + 2: + 2024-10-01: 604 + 2025-10-01: 455 + TRAILER_OTHER: + 1: + 2024-10-01: 264 + 2025-10-01: 199 + 2: + 2024-10-01: 302 + 2025-10-01: 227 + +metadata: + propagate_metadata_to_children: true + period: year + unit: currency-USD + label: Kansas LIEAP natural gas benefit matrix + breakdown: + - range(1, 5) # one-month income band + - ks_liheap_utility_rate_tier + - ks_liheap_dwelling_type + - range(1, 3) # household size group (1 = size 1-4, 2 = size 5+) + breakdown_labels: + - One-month income band + - Utility rate tier + - Dwelling type + - Household size group + reference: + - title: Kansas LIEAP FY2026 Benefit Matrix, Natural gas (Benefit Adjustment @ 80% table) + href: https://liheapch.acf.gov/docs/2026/benefits-matricies/KS_BenefitMatrix_2026.pdf#page=1 + - title: Kansas LIEAP FY2025 Benefit Matrix, Natural gas (Ben Adj 100.0%) + href: https://liheapch.acf.gov/docs/2025/benefits-matricies/KS_BenefitMatrix_2025.pdf#page=1 + - title: Kansas LIHEAP FY2026 State Plan, Section 2.5 (benefit variables) + href: https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=9 + - title: KEESM 13410 Benefit Levels + href: https://content.dcf.ks.gov/ees/keesm/current/keesm13400.htm diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/other.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/other.yaml new file mode 100644 index 00000000000..fbf0e702b76 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/other.yaml @@ -0,0 +1,148 @@ +description: Kansas provides this annual benefit to households heating primarily with other fuels under the Low Income Energy Assistance Program, by one-month income band, dwelling type and household size group. + +# Income band 1: one-month income $0 to $899 +1: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 848 + 2025-10-01: 639 + 2: + 2024-10-01: 970 + 2025-10-01: 731 + DUPLEX: + 1: + 2024-10-01: 636 + 2025-10-01: 479 + 2: + 2024-10-01: 728 + 2025-10-01: 548 + APARTMENT: + 1: + 2024-10-01: 424 + 2025-10-01: 319 + 2: + 2024-10-01: 485 + 2025-10-01: 365 + TRAILER_OTHER: + 1: + 2024-10-01: 212 + 2025-10-01: 160 + 2: + 2024-10-01: 243 + 2025-10-01: 183 + +# Income band 2: one-month income $900 to $1,199 +2: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 763 + 2025-10-01: 575 + 2: + 2024-10-01: 873 + 2025-10-01: 658 + DUPLEX: + 1: + 2024-10-01: 572 + 2025-10-01: 431 + 2: + 2024-10-01: 655 + 2025-10-01: 493 + APARTMENT: + 1: + 2024-10-01: 382 + 2025-10-01: 287 + 2: + 2024-10-01: 437 + 2025-10-01: 329 + TRAILER_OTHER: + 1: + 2024-10-01: 191 + 2025-10-01: 144 + 2: + 2024-10-01: 218 + 2025-10-01: 164 + +# Income band 3: one-month income $1,200 to $1,699 +3: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 678 + 2025-10-01: 511 + 2: + 2024-10-01: 776 + 2025-10-01: 585 + DUPLEX: + 1: + 2024-10-01: 509 + 2025-10-01: 383 + 2: + 2024-10-01: 582 + 2025-10-01: 439 + APARTMENT: + 1: + 2024-10-01: 339 + 2025-10-01: 256 + 2: + 2024-10-01: 388 + 2025-10-01: 292 + TRAILER_OTHER: + 1: + 2024-10-01: 170 + 2025-10-01: 128 + 2: + 2024-10-01: 194 + 2025-10-01: 146 + +# Income band 4: one-month income $1,700 and over +4: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 594 + 2025-10-01: 447 + 2: + 2024-10-01: 679 + 2025-10-01: 512 + DUPLEX: + 1: + 2024-10-01: 445 + 2025-10-01: 335 + 2: + 2024-10-01: 509 + 2025-10-01: 384 + APARTMENT: + 1: + 2024-10-01: 297 + 2025-10-01: 224 + 2: + 2024-10-01: 340 + 2025-10-01: 256 + TRAILER_OTHER: + 1: + 2024-10-01: 148 + 2025-10-01: 112 + 2: + 2024-10-01: 170 + 2025-10-01: 128 + +metadata: + propagate_metadata_to_children: true + period: year + unit: currency-USD + label: Kansas LIEAP other fuels benefit matrix + breakdown: + - range(1, 5) # one-month income band + - ks_liheap_dwelling_type + - range(1, 3) # household size group (1 = size 1-4, 2 = size 5+) + breakdown_labels: + - One-month income band + - Dwelling type + - Household size group + reference: + - title: Kansas LIEAP FY2026 Benefit Matrix, Other fuels (Benefit Adjustment @ 80% table) + href: https://liheapch.acf.gov/docs/2026/benefits-matricies/KS_BenefitMatrix_2026.pdf#page=4 + - title: Kansas LIEAP FY2025 Benefit Matrix, Other fuels (Ben Adj 100.0%) + href: https://liheapch.acf.gov/docs/2025/benefits-matricies/KS_BenefitMatrix_2025.pdf#page=3 + - title: Kansas LIHEAP FY2026 State Plan, Section 2.5 (benefit variables) + href: https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=9 + - title: KEESM 13410 Benefit Levels + href: https://content.dcf.ks.gov/ees/keesm/current/keesm13400.htm diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/propane.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/propane.yaml new file mode 100644 index 00000000000..450a344ab2b --- /dev/null +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/propane.yaml @@ -0,0 +1,1198 @@ +description: Kansas provides this annual benefit to households heating primarily with propane under the Low Income Energy Assistance Program, by one-month income band, utility rate tier, dwelling type and household size group. + +# Income band 1: one-month income $0 to $899 +1: + A: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 570 + 2025-10-01: 430 + 2: + 2024-10-01: 652 + 2025-10-01: 491 + DUPLEX: + 1: + 2024-10-01: 428 + 2025-10-01: 322 + 2: + 2024-10-01: 489 + 2025-10-01: 368 + APARTMENT: + 1: + 2024-10-01: 285 + 2025-10-01: 215 + 2: + 2024-10-01: 326 + 2025-10-01: 246 + TRAILER_OTHER: + 1: + 2024-10-01: 143 + 2025-10-01: 107 + 2: + 2024-10-01: 163 + 2025-10-01: 123 + B: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 639 + 2025-10-01: 482 + 2: + 2024-10-01: 731 + 2025-10-01: 550 + DUPLEX: + 1: + 2024-10-01: 479 + 2025-10-01: 361 + 2: + 2024-10-01: 548 + 2025-10-01: 413 + APARTMENT: + 1: + 2024-10-01: 320 + 2025-10-01: 241 + 2: + 2024-10-01: 366 + 2025-10-01: 275 + TRAILER_OTHER: + 1: + 2024-10-01: 160 + 2025-10-01: 120 + 2: + 2024-10-01: 183 + 2025-10-01: 138 + C: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 675 + 2025-10-01: 509 + 2: + 2024-10-01: 772 + 2025-10-01: 582 + DUPLEX: + 1: + 2024-10-01: 506 + 2025-10-01: 382 + 2: + 2024-10-01: 579 + 2025-10-01: 436 + APARTMENT: + 1: + 2024-10-01: 338 + 2025-10-01: 254 + 2: + 2024-10-01: 386 + 2025-10-01: 291 + TRAILER_OTHER: + 1: + 2024-10-01: 169 + 2025-10-01: 127 + 2: + 2024-10-01: 193 + 2025-10-01: 145 + D: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 712 + 2025-10-01: 537 + 2: + 2024-10-01: 815 + 2025-10-01: 614 + DUPLEX: + 1: + 2024-10-01: 534 + 2025-10-01: 403 + 2: + 2024-10-01: 611 + 2025-10-01: 460 + APARTMENT: + 1: + 2024-10-01: 356 + 2025-10-01: 268 + 2: + 2024-10-01: 408 + 2025-10-01: 307 + TRAILER_OTHER: + 1: + 2024-10-01: 178 + 2025-10-01: 134 + 2: + 2024-10-01: 204 + 2025-10-01: 153 + E: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 733 + 2025-10-01: 553 + 2: + 2024-10-01: 839 + 2025-10-01: 632 + DUPLEX: + 1: + 2024-10-01: 550 + 2025-10-01: 415 + 2: + 2024-10-01: 629 + 2025-10-01: 474 + APARTMENT: + 1: + 2024-10-01: 367 + 2025-10-01: 276 + 2: + 2024-10-01: 420 + 2025-10-01: 316 + TRAILER_OTHER: + 1: + 2024-10-01: 183 + 2025-10-01: 138 + 2: + 2024-10-01: 210 + 2025-10-01: 158 + F: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 751 + 2025-10-01: 566 + 2: + 2024-10-01: 859 + 2025-10-01: 647 + DUPLEX: + 1: + 2024-10-01: 563 + 2025-10-01: 424 + 2: + 2024-10-01: 644 + 2025-10-01: 485 + APARTMENT: + 1: + 2024-10-01: 376 + 2025-10-01: 283 + 2: + 2024-10-01: 430 + 2025-10-01: 324 + TRAILER_OTHER: + 1: + 2024-10-01: 188 + 2025-10-01: 141 + 2: + 2024-10-01: 215 + 2025-10-01: 162 + G: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 772 + 2025-10-01: 582 + 2: + 2024-10-01: 883 + 2025-10-01: 666 + DUPLEX: + 1: + 2024-10-01: 579 + 2025-10-01: 436 + 2: + 2024-10-01: 662 + 2025-10-01: 499 + APARTMENT: + 1: + 2024-10-01: 386 + 2025-10-01: 291 + 2: + 2024-10-01: 442 + 2025-10-01: 333 + TRAILER_OTHER: + 1: + 2024-10-01: 193 + 2025-10-01: 145 + 2: + 2024-10-01: 221 + 2025-10-01: 166 + H: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 812 + 2025-10-01: 612 + 2: + 2024-10-01: 929 + 2025-10-01: 700 + DUPLEX: + 1: + 2024-10-01: 609 + 2025-10-01: 459 + 2: + 2024-10-01: 697 + 2025-10-01: 525 + APARTMENT: + 1: + 2024-10-01: 406 + 2025-10-01: 306 + 2: + 2024-10-01: 465 + 2025-10-01: 350 + TRAILER_OTHER: + 1: + 2024-10-01: 203 + 2025-10-01: 153 + 2: + 2024-10-01: 232 + 2025-10-01: 175 + I: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 865 + 2025-10-01: 652 + 2: + 2024-10-01: 990 + 2025-10-01: 746 + DUPLEX: + 1: + 2024-10-01: 649 + 2025-10-01: 489 + 2: + 2024-10-01: 743 + 2025-10-01: 559 + APARTMENT: + 1: + 2024-10-01: 433 + 2025-10-01: 326 + 2: + 2024-10-01: 495 + 2025-10-01: 373 + TRAILER_OTHER: + 1: + 2024-10-01: 216 + 2025-10-01: 163 + 2: + 2024-10-01: 248 + 2025-10-01: 186 + J: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 1_286 + 2025-10-01: 969 + 2: + 2024-10-01: 1_472 + 2025-10-01: 1_109 + DUPLEX: + 1: + 2024-10-01: 965 + 2025-10-01: 727 + 2: + 2024-10-01: 1_104 + 2025-10-01: 832 + APARTMENT: + 1: + 2024-10-01: 643 + 2025-10-01: 484 + 2: + 2024-10-01: 736 + 2025-10-01: 554 + TRAILER_OTHER: + 1: + 2024-10-01: 322 + 2025-10-01: 242 + 2: + 2024-10-01: 368 + 2025-10-01: 277 + +# Income band 2: one-month income $900 to $1,199 +2: + A: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 513 + 2025-10-01: 387 + 2: + 2024-10-01: 587 + 2025-10-01: 442 + DUPLEX: + 1: + 2024-10-01: 385 + 2025-10-01: 290 + 2: + 2024-10-01: 440 + 2025-10-01: 332 + APARTMENT: + 1: + 2024-10-01: 257 + 2025-10-01: 193 + 2: + 2024-10-01: 293 + 2025-10-01: 221 + TRAILER_OTHER: + 1: + 2024-10-01: 128 + 2025-10-01: 97 + 2: + 2024-10-01: 147 + 2025-10-01: 111 + B: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 575 + 2025-10-01: 433 + 2: + 2024-10-01: 658 + 2025-10-01: 495 + DUPLEX: + 1: + 2024-10-01: 431 + 2025-10-01: 325 + 2: + 2024-10-01: 493 + 2025-10-01: 372 + APARTMENT: + 1: + 2024-10-01: 288 + 2025-10-01: 217 + 2: + 2024-10-01: 329 + 2025-10-01: 248 + TRAILER_OTHER: + 1: + 2024-10-01: 144 + 2025-10-01: 108 + 2: + 2024-10-01: 164 + 2025-10-01: 124 + C: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 608 + 2025-10-01: 458 + 2: + 2024-10-01: 695 + 2025-10-01: 523 + DUPLEX: + 1: + 2024-10-01: 456 + 2025-10-01: 343 + 2: + 2024-10-01: 521 + 2025-10-01: 393 + APARTMENT: + 1: + 2024-10-01: 304 + 2025-10-01: 229 + 2: + 2024-10-01: 347 + 2025-10-01: 262 + TRAILER_OTHER: + 1: + 2024-10-01: 152 + 2025-10-01: 114 + 2: + 2024-10-01: 174 + 2025-10-01: 131 + D: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 641 + 2025-10-01: 483 + 2: + 2024-10-01: 734 + 2025-10-01: 552 + DUPLEX: + 1: + 2024-10-01: 481 + 2025-10-01: 362 + 2: + 2024-10-01: 550 + 2025-10-01: 414 + APARTMENT: + 1: + 2024-10-01: 320 + 2025-10-01: 242 + 2: + 2024-10-01: 367 + 2025-10-01: 276 + TRAILER_OTHER: + 1: + 2024-10-01: 160 + 2025-10-01: 121 + 2: + 2024-10-01: 183 + 2025-10-01: 138 + E: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 660 + 2025-10-01: 498 + 2: + 2024-10-01: 755 + 2025-10-01: 569 + DUPLEX: + 1: + 2024-10-01: 495 + 2025-10-01: 373 + 2: + 2024-10-01: 566 + 2025-10-01: 427 + APARTMENT: + 1: + 2024-10-01: 330 + 2025-10-01: 249 + 2: + 2024-10-01: 378 + 2025-10-01: 284 + TRAILER_OTHER: + 1: + 2024-10-01: 165 + 2025-10-01: 124 + 2: + 2024-10-01: 189 + 2025-10-01: 142 + F: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 676 + 2025-10-01: 509 + 2: + 2024-10-01: 773 + 2025-10-01: 582 + DUPLEX: + 1: + 2024-10-01: 507 + 2025-10-01: 382 + 2: + 2024-10-01: 580 + 2025-10-01: 437 + APARTMENT: + 1: + 2024-10-01: 338 + 2025-10-01: 255 + 2: + 2024-10-01: 387 + 2025-10-01: 291 + TRAILER_OTHER: + 1: + 2024-10-01: 169 + 2025-10-01: 127 + 2: + 2024-10-01: 193 + 2025-10-01: 146 + G: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 695 + 2025-10-01: 523 + 2: + 2024-10-01: 795 + 2025-10-01: 599 + DUPLEX: + 1: + 2024-10-01: 521 + 2025-10-01: 393 + 2: + 2024-10-01: 596 + 2025-10-01: 449 + APARTMENT: + 1: + 2024-10-01: 347 + 2025-10-01: 262 + 2: + 2024-10-01: 397 + 2025-10-01: 300 + TRAILER_OTHER: + 1: + 2024-10-01: 174 + 2025-10-01: 131 + 2: + 2024-10-01: 199 + 2025-10-01: 150 + H: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 731 + 2025-10-01: 551 + 2: + 2024-10-01: 836 + 2025-10-01: 630 + DUPLEX: + 1: + 2024-10-01: 548 + 2025-10-01: 413 + 2: + 2024-10-01: 627 + 2025-10-01: 473 + APARTMENT: + 1: + 2024-10-01: 365 + 2025-10-01: 275 + 2: + 2024-10-01: 418 + 2025-10-01: 315 + TRAILER_OTHER: + 1: + 2024-10-01: 183 + 2025-10-01: 138 + 2: + 2024-10-01: 209 + 2025-10-01: 158 + I: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 779 + 2025-10-01: 587 + 2: + 2024-10-01: 891 + 2025-10-01: 671 + DUPLEX: + 1: + 2024-10-01: 584 + 2025-10-01: 440 + 2: + 2024-10-01: 668 + 2025-10-01: 503 + APARTMENT: + 1: + 2024-10-01: 389 + 2025-10-01: 293 + 2: + 2024-10-01: 446 + 2025-10-01: 336 + TRAILER_OTHER: + 1: + 2024-10-01: 195 + 2025-10-01: 147 + 2: + 2024-10-01: 223 + 2025-10-01: 168 + J: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 1_157 + 2025-10-01: 872 + 2: + 2024-10-01: 1_325 + 2025-10-01: 998 + DUPLEX: + 1: + 2024-10-01: 868 + 2025-10-01: 654 + 2: + 2024-10-01: 994 + 2025-10-01: 748 + APARTMENT: + 1: + 2024-10-01: 579 + 2025-10-01: 436 + 2: + 2024-10-01: 662 + 2025-10-01: 499 + TRAILER_OTHER: + 1: + 2024-10-01: 289 + 2025-10-01: 218 + 2: + 2024-10-01: 331 + 2025-10-01: 249 + +# Income band 3: one-month income $1,200 to $1,699 +3: + A: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 456 + 2025-10-01: 344 + 2: + 2024-10-01: 522 + 2025-10-01: 393 + DUPLEX: + 1: + 2024-10-01: 342 + 2025-10-01: 258 + 2: + 2024-10-01: 391 + 2025-10-01: 295 + APARTMENT: + 1: + 2024-10-01: 228 + 2025-10-01: 172 + 2: + 2024-10-01: 261 + 2025-10-01: 196 + TRAILER_OTHER: + 1: + 2024-10-01: 114 + 2025-10-01: 86 + 2: + 2024-10-01: 130 + 2025-10-01: 98 + B: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 511 + 2025-10-01: 385 + 2: + 2024-10-01: 585 + 2025-10-01: 440 + DUPLEX: + 1: + 2024-10-01: 383 + 2025-10-01: 289 + 2: + 2024-10-01: 439 + 2025-10-01: 330 + APARTMENT: + 1: + 2024-10-01: 256 + 2025-10-01: 193 + 2: + 2024-10-01: 292 + 2025-10-01: 220 + TRAILER_OTHER: + 1: + 2024-10-01: 128 + 2025-10-01: 96 + 2: + 2024-10-01: 146 + 2025-10-01: 110 + C: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 540 + 2025-10-01: 407 + 2: + 2024-10-01: 618 + 2025-10-01: 465 + DUPLEX: + 1: + 2024-10-01: 405 + 2025-10-01: 305 + 2: + 2024-10-01: 463 + 2025-10-01: 349 + APARTMENT: + 1: + 2024-10-01: 270 + 2025-10-01: 204 + 2: + 2024-10-01: 309 + 2025-10-01: 233 + TRAILER_OTHER: + 1: + 2024-10-01: 135 + 2025-10-01: 102 + 2: + 2024-10-01: 154 + 2025-10-01: 116 + D: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 570 + 2025-10-01: 429 + 2: + 2024-10-01: 652 + 2025-10-01: 491 + DUPLEX: + 1: + 2024-10-01: 427 + 2025-10-01: 322 + 2: + 2024-10-01: 489 + 2025-10-01: 368 + APARTMENT: + 1: + 2024-10-01: 285 + 2025-10-01: 215 + 2: + 2024-10-01: 326 + 2025-10-01: 245 + TRAILER_OTHER: + 1: + 2024-10-01: 142 + 2025-10-01: 107 + 2: + 2024-10-01: 163 + 2025-10-01: 123 + E: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 586 + 2025-10-01: 442 + 2: + 2024-10-01: 671 + 2025-10-01: 506 + DUPLEX: + 1: + 2024-10-01: 440 + 2025-10-01: 332 + 2: + 2024-10-01: 503 + 2025-10-01: 379 + APARTMENT: + 1: + 2024-10-01: 293 + 2025-10-01: 221 + 2: + 2024-10-01: 336 + 2025-10-01: 253 + TRAILER_OTHER: + 1: + 2024-10-01: 147 + 2025-10-01: 111 + 2: + 2024-10-01: 168 + 2025-10-01: 126 + F: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 601 + 2025-10-01: 452 + 2: + 2024-10-01: 687 + 2025-10-01: 518 + DUPLEX: + 1: + 2024-10-01: 451 + 2025-10-01: 339 + 2: + 2024-10-01: 515 + 2025-10-01: 388 + APARTMENT: + 1: + 2024-10-01: 300 + 2025-10-01: 226 + 2: + 2024-10-01: 344 + 2025-10-01: 259 + TRAILER_OTHER: + 1: + 2024-10-01: 150 + 2025-10-01: 113 + 2: + 2024-10-01: 172 + 2025-10-01: 129 + G: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 618 + 2025-10-01: 465 + 2: + 2024-10-01: 706 + 2025-10-01: 532 + DUPLEX: + 1: + 2024-10-01: 463 + 2025-10-01: 349 + 2: + 2024-10-01: 530 + 2025-10-01: 399 + APARTMENT: + 1: + 2024-10-01: 309 + 2025-10-01: 233 + 2: + 2024-10-01: 353 + 2025-10-01: 266 + TRAILER_OTHER: + 1: + 2024-10-01: 154 + 2025-10-01: 116 + 2: + 2024-10-01: 177 + 2025-10-01: 133 + H: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 650 + 2025-10-01: 490 + 2: + 2024-10-01: 743 + 2025-10-01: 560 + DUPLEX: + 1: + 2024-10-01: 487 + 2025-10-01: 367 + 2: + 2024-10-01: 557 + 2025-10-01: 420 + APARTMENT: + 1: + 2024-10-01: 325 + 2025-10-01: 245 + 2: + 2024-10-01: 372 + 2025-10-01: 280 + TRAILER_OTHER: + 1: + 2024-10-01: 162 + 2025-10-01: 122 + 2: + 2024-10-01: 186 + 2025-10-01: 140 + I: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 692 + 2025-10-01: 522 + 2: + 2024-10-01: 792 + 2025-10-01: 596 + DUPLEX: + 1: + 2024-10-01: 519 + 2025-10-01: 391 + 2: + 2024-10-01: 594 + 2025-10-01: 447 + APARTMENT: + 1: + 2024-10-01: 346 + 2025-10-01: 261 + 2: + 2024-10-01: 396 + 2025-10-01: 298 + TRAILER_OTHER: + 1: + 2024-10-01: 173 + 2025-10-01: 130 + 2: + 2024-10-01: 198 + 2025-10-01: 149 + J: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 1_029 + 2025-10-01: 775 + 2: + 2024-10-01: 1_178 + 2025-10-01: 887 + DUPLEX: + 1: + 2024-10-01: 772 + 2025-10-01: 581 + 2: + 2024-10-01: 883 + 2025-10-01: 665 + APARTMENT: + 1: + 2024-10-01: 514 + 2025-10-01: 388 + 2: + 2024-10-01: 589 + 2025-10-01: 444 + TRAILER_OTHER: + 1: + 2024-10-01: 257 + 2025-10-01: 194 + 2: + 2024-10-01: 294 + 2025-10-01: 222 + +# Income band 4: one-month income $1,700 and over +4: + A: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 399 + 2025-10-01: 301 + 2: + 2024-10-01: 456 + 2025-10-01: 344 + DUPLEX: + 1: + 2024-10-01: 299 + 2025-10-01: 226 + 2: + 2024-10-01: 342 + 2025-10-01: 258 + APARTMENT: + 1: + 2024-10-01: 200 + 2025-10-01: 150 + 2: + 2024-10-01: 228 + 2025-10-01: 172 + TRAILER_OTHER: + 1: + 2024-10-01: 100 + 2025-10-01: 75 + 2: + 2024-10-01: 114 + 2025-10-01: 86 + B: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 447 + 2025-10-01: 337 + 2: + 2024-10-01: 512 + 2025-10-01: 385 + DUPLEX: + 1: + 2024-10-01: 335 + 2025-10-01: 253 + 2: + 2024-10-01: 384 + 2025-10-01: 289 + APARTMENT: + 1: + 2024-10-01: 224 + 2025-10-01: 169 + 2: + 2024-10-01: 256 + 2025-10-01: 193 + TRAILER_OTHER: + 1: + 2024-10-01: 112 + 2025-10-01: 84 + 2: + 2024-10-01: 128 + 2025-10-01: 96 + C: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 473 + 2025-10-01: 356 + 2: + 2024-10-01: 540 + 2025-10-01: 407 + DUPLEX: + 1: + 2024-10-01: 354 + 2025-10-01: 267 + 2: + 2024-10-01: 405 + 2025-10-01: 305 + APARTMENT: + 1: + 2024-10-01: 236 + 2025-10-01: 178 + 2: + 2024-10-01: 270 + 2025-10-01: 204 + TRAILER_OTHER: + 1: + 2024-10-01: 118 + 2025-10-01: 89 + 2: + 2024-10-01: 135 + 2025-10-01: 102 + D: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 498 + 2025-10-01: 376 + 2: + 2024-10-01: 571 + 2025-10-01: 430 + DUPLEX: + 1: + 2024-10-01: 374 + 2025-10-01: 282 + 2: + 2024-10-01: 428 + 2025-10-01: 322 + APARTMENT: + 1: + 2024-10-01: 249 + 2025-10-01: 188 + 2: + 2024-10-01: 285 + 2025-10-01: 215 + TRAILER_OTHER: + 1: + 2024-10-01: 125 + 2025-10-01: 94 + 2: + 2024-10-01: 143 + 2025-10-01: 107 + E: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 513 + 2025-10-01: 387 + 2: + 2024-10-01: 587 + 2025-10-01: 442 + DUPLEX: + 1: + 2024-10-01: 385 + 2025-10-01: 290 + 2: + 2024-10-01: 440 + 2025-10-01: 332 + APARTMENT: + 1: + 2024-10-01: 257 + 2025-10-01: 193 + 2: + 2024-10-01: 294 + 2025-10-01: 221 + TRAILER_OTHER: + 1: + 2024-10-01: 128 + 2025-10-01: 97 + 2: + 2024-10-01: 147 + 2025-10-01: 111 + F: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 526 + 2025-10-01: 396 + 2: + 2024-10-01: 601 + 2025-10-01: 453 + DUPLEX: + 1: + 2024-10-01: 394 + 2025-10-01: 297 + 2: + 2024-10-01: 451 + 2025-10-01: 340 + APARTMENT: + 1: + 2024-10-01: 263 + 2025-10-01: 198 + 2: + 2024-10-01: 301 + 2025-10-01: 227 + TRAILER_OTHER: + 1: + 2024-10-01: 131 + 2025-10-01: 99 + 2: + 2024-10-01: 150 + 2025-10-01: 113 + G: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 540 + 2025-10-01: 407 + 2: + 2024-10-01: 618 + 2025-10-01: 466 + DUPLEX: + 1: + 2024-10-01: 405 + 2025-10-01: 305 + 2: + 2024-10-01: 464 + 2025-10-01: 349 + APARTMENT: + 1: + 2024-10-01: 270 + 2025-10-01: 204 + 2: + 2024-10-01: 309 + 2025-10-01: 233 + TRAILER_OTHER: + 1: + 2024-10-01: 135 + 2025-10-01: 102 + 2: + 2024-10-01: 155 + 2025-10-01: 116 + H: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 568 + 2025-10-01: 428 + 2: + 2024-10-01: 650 + 2025-10-01: 490 + DUPLEX: + 1: + 2024-10-01: 426 + 2025-10-01: 321 + 2: + 2024-10-01: 488 + 2025-10-01: 368 + APARTMENT: + 1: + 2024-10-01: 284 + 2025-10-01: 214 + 2: + 2024-10-01: 325 + 2025-10-01: 245 + TRAILER_OTHER: + 1: + 2024-10-01: 142 + 2025-10-01: 107 + 2: + 2024-10-01: 163 + 2025-10-01: 123 + I: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 606 + 2025-10-01: 456 + 2: + 2024-10-01: 693 + 2025-10-01: 522 + DUPLEX: + 1: + 2024-10-01: 454 + 2025-10-01: 342 + 2: + 2024-10-01: 520 + 2025-10-01: 391 + APARTMENT: + 1: + 2024-10-01: 303 + 2025-10-01: 228 + 2: + 2024-10-01: 347 + 2025-10-01: 261 + TRAILER_OTHER: + 1: + 2024-10-01: 151 + 2025-10-01: 114 + 2: + 2024-10-01: 173 + 2025-10-01: 130 + J: + HOUSE_MODULAR_MOBILE: + 1: + 2024-10-01: 900 + 2025-10-01: 678 + 2: + 2024-10-01: 1_030 + 2025-10-01: 776 + DUPLEX: + 1: + 2024-10-01: 675 + 2025-10-01: 509 + 2: + 2024-10-01: 773 + 2025-10-01: 582 + APARTMENT: + 1: + 2024-10-01: 450 + 2025-10-01: 339 + 2: + 2024-10-01: 515 + 2025-10-01: 388 + TRAILER_OTHER: + 1: + 2024-10-01: 225 + 2025-10-01: 170 + 2: + 2024-10-01: 258 + 2025-10-01: 194 + +metadata: + propagate_metadata_to_children: true + period: year + unit: currency-USD + label: Kansas LIEAP propane benefit matrix + breakdown: + - range(1, 5) # one-month income band + - ks_liheap_utility_rate_tier + - ks_liheap_dwelling_type + - range(1, 3) # household size group (1 = size 1-4, 2 = size 5+) + breakdown_labels: + - One-month income band + - Utility rate tier + - Dwelling type + - Household size group + reference: + - title: Kansas LIEAP FY2026 Benefit Matrix, Propane (Benefit Adjustment @ 80% table) + href: https://liheapch.acf.gov/docs/2026/benefits-matricies/KS_BenefitMatrix_2026.pdf#page=3 + - title: Kansas LIEAP FY2025 Benefit Matrix, Propane (Ben Adj 100.0%) + href: https://liheapch.acf.gov/docs/2025/benefits-matricies/KS_BenefitMatrix_2025.pdf#page=2 + - title: Kansas LIHEAP FY2026 State Plan, Section 2.5 (benefit variables) + href: https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=9 + - title: KEESM 13410 Benefit Levels + href: https://content.dcf.ks.gov/ees/keesm/current/keesm13400.htm diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/min_benefit.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/min_benefit.yaml new file mode 100644 index 00000000000..29184932be4 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/min_benefit.yaml @@ -0,0 +1,18 @@ +description: Kansas pays at least this annual benefit to eligible households under the Low Income Energy Assistance Program. +# The state plans also report a maximum benefit ($2,232 for FY2025, $4,301 for +# FY2026) that exceeds every matrix cell in its year and is therefore not applied. +values: + 2024-10-01: 100 + 2025-10-01: 130 + +metadata: + unit: currency-USD + period: year + label: Kansas LIEAP minimum benefit + reference: + - title: Kansas LIHEAP FY2026 State Plan, Section 2.6 (minimum benefit $130, maximum benefit $4,301) + href: https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=9 + - title: Kansas LIHEAP FY2025 State Plan, Section 2.6 (minimum benefit $100, maximum benefit $2,232) + href: https://liheapch.acf.gov/docs/2025/state-plans/KS_Plan_2025.pdf#page=9 + - title: LIHEAP Clearinghouse Kansas state profile (heating $130 minimum, $4,301 maximum) + href: https://liheapch.acf.gov/profiles/Kansas.htm diff --git a/policyengine_us/programs.yaml b/policyengine_us/programs.yaml index f08e080d0c0..fcfc0acdea5 100644 --- a/policyengine_us/programs.yaml +++ b/policyengine_us/programs.yaml @@ -789,7 +789,7 @@ programs: category: Benefits agency: HHS status: partial - coverage: OR, DC, Riverside County, MA, IL, TX + coverage: OR, DC, Riverside County, MA, IL, KS, TX state_implementations: - state: OR status: in_progress @@ -810,6 +810,11 @@ programs: name: Illinois LIHEAP full_name: Illinois Low Income Home Energy Assistance Program variable: il_liheap + - state: KS + status: complete + name: Kansas LIEAP + full_name: Kansas Low Income Energy Assistance Program + variable: ks_liheap - state: TX status: in_progress name: Texas CEAP diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_categorically_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_categorically_income_eligible.yaml new file mode 100644 index 00000000000..2a1456aabff --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_categorically_income_eligible.yaml @@ -0,0 +1,107 @@ +# Kansas LIEAP categorical income eligibility (KS LIHEAP State Plan FY2026 +# section 1.4, #page=5): a household with at least one member receiving TANF, +# SSI or SNAP is considered income eligible for heating assistance. Modeled +# on receipt: any member ssi > 0, spm_unit snap > 0, or spm_unit ks_tanf > 0. +# Means-tested veterans programs are not a categorical route (plan 1.4: No). + +- name: Case 1, a member receiving SSI makes the household categorically eligible. + period: 2026 + input: + people: + person1: + age: 45 + employment_income: 40_000 + person2: + age: 68 + ssi: 6_000 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: KS + output: + ks_liheap_categorically_income_eligible: true + +- name: Case 2, SNAP receipt makes the household categorically eligible. + period: 2026 + input: + people: + person1: + age: 30 + employment_income: 20_000 + person2: + age: 3 + spm_units: + spm_unit: + members: [person1, person2] + ks_tanf: 0 + snap: 2_400 + households: + household: + members: [person1, person2] + state_code: KS + output: + ks_liheap_categorically_income_eligible: true + +- name: Case 3, TANF receipt makes the household categorically eligible. + period: 2026 + input: + people: + person1: + age: 28 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + ks_tanf: 3_600 + households: + household: + members: [person1, person2] + state_code: KS + output: + ks_liheap_categorically_income_eligible: true + +- name: Case 4, no TANF, SSI or SNAP receipt is not categorically eligible. + period: 2026 + input: + people: + person1: + age: 45 + employment_income: 40_000 + person2: + age: 68 + social_security: 15_000 + spm_units: + spm_unit: + members: [person1, person2] + snap: 0 + ks_tanf: 0 + households: + household: + members: [person1, person2] + state_code: KS + output: + ks_liheap_categorically_income_eligible: false + +- name: Case 5, veterans benefits alone are not a categorical route. + period: 2026 + input: + people: + person1: + age: 60 + veterans_benefits: 30_000 + spm_units: + spm_unit: + members: [person1] + snap: 0 + ks_tanf: 0 + households: + household: + members: [person1] + state_code: KS + output: + # Plan 1.4: means-tested veterans programs -> No for heating. + ks_liheap_categorically_income_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_eligible.yaml new file mode 100644 index 00000000000..81e1fe4def0 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_eligible.yaml @@ -0,0 +1,235 @@ +# Kansas LIEAP overall eligibility: Kansas residence (KEESM 13310), income +# (KEESM 13100), at least one citizen or qualified-alien member (KEESM 13330), +# energy vulnerability - responsible for the primary heating cost, so a home +# with no heating is not vulnerable (KEESM 13340), and not a renter in +# subsidized housing whose heating fuel costs are included in the rent +# (KEESM 13340; KS LIHEAP State Plan FY2026 2.3, #page=8). No asset test +# (plan 2.3). + +- name: Case 1, low-income Kansas household paying for natural gas is eligible. + period: 2026 + input: + people: + person1: + age: 40 + employment_income: 15_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + households: + household: + members: [person1] + state_code: KS + output: + ks_liheap_eligible: true + +- name: Case 2, the same household in Missouri is not eligible. + period: 2026 + input: + people: + person1: + age: 40 + employment_income: 15_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + households: + household: + members: [person1] + state_code: MO + output: + ks_liheap_eligible: false + +- name: Case 3, a home with no heating is not energy vulnerable. + period: 2026 + input: + people: + person1: + age: 40 + employment_income: 15_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NONE + households: + household: + members: [person1] + state_code: KS + output: + ks_liheap_eligible: false + +- name: Case 4, household with no citizen or qualified member is not eligible. + period: 2026 + input: + people: + person1: + age: 30 + immigration_status: UNDOCUMENTED + employment_income: 12_000 + person2: + age: 28 + immigration_status: UNDOCUMENTED + spm_units: + spm_unit: + members: [person1, person2] + heating_type: NATURAL_GAS + households: + household: + members: [person1, person2] + state_code: KS + output: + ks_liheap_eligible: false + +- name: Case 5, mixed-status household with one citizen member is eligible. + period: 2026 + input: + people: + person1: + age: 30 + immigration_status: UNDOCUMENTED + employment_income: 12_000 + person2: + age: 4 + immigration_status: CITIZEN + spm_units: + spm_unit: + members: [person1, person2] + ks_tanf: 0 + heating_type: NATURAL_GAS + households: + household: + members: [person1, person2] + state_code: KS + output: + # KEESM 13330: at least one citizen (the child); size 1 limit 23,475 > + # 12,000 (the parent's income counts). + ks_liheap_eligible: true + +- name: Case 6, subsidized-housing renter with heat included in rent is not eligible. + period: 2026 + input: + people: + person1: + age: 40 + employment_income: 15_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + receives_housing_assistance: true + heat_expense_included_in_rent: true + households: + household: + members: [person1] + state_code: KS + output: + ks_liheap_eligible: false + +- name: Case 7, subsidized-housing renter who pays heat separately is eligible. + period: 2026 + input: + people: + person1: + age: 40 + employment_income: 15_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + receives_housing_assistance: true + heat_expense_included_in_rent: false + households: + household: + members: [person1] + state_code: KS + output: + # KEESM 13340: pays heating costs directly to a utility -> vulnerable. + ks_liheap_eligible: true + +- name: Case 8, unsubsidized renter with heat included in rent is eligible. + period: 2026 + input: + people: + person1: + age: 40 + employment_income: 15_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + receives_housing_assistance: false + heat_expense_included_in_rent: true + households: + household: + members: [person1] + state_code: KS + output: + # KEESM 13340: paying the landlord for fuel included in rent qualifies. + ks_liheap_eligible: true + +- name: Case 9, household over the income limit is not eligible. + period: 2026 + input: + people: + person1: + age: 40 + employment_income: 30_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + snap: 0 + ks_tanf: 0 + households: + household: + members: [person1] + state_code: KS + output: + # 30,000 > 23,475 and no categorical route. + ks_liheap_eligible: false + +- name: Case 10, no asset test so large savings do not disqualify. + period: 2026 + input: + people: + person1: + age: 66 + social_security: 14_000 + spm_units: + spm_unit: + members: [person1] + spm_unit_cash_assets: 50_000 + heating_type: ELECTRICITY + households: + household: + members: [person1] + state_code: KS + output: + # Plan 2.3: "Do you require an Assets test? No". + ks_liheap_eligible: true + +- name: Case 11, household over the limit but receiving TANF is eligible. + period: 2025 + input: + people: + person1: + age: 30 + employment_income: 32_000 + person2: + age: 6 + spm_units: + spm_unit: + members: [person1, person2] + heating_type: PROPANE + ks_tanf: 1_200 + households: + household: + members: [person1, person2] + state_code: KS + output: + # 2025 season size 2 limit: 1.5 x (15,060 + 5,380) = 30,660 < 33,200 + # gross, but TANF receipt makes the household categorically income + # eligible (plan 1.4). + ks_liheap_eligible: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_fpg.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_fpg.yaml new file mode 100644 index 00000000000..e05651fb3af --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_fpg.yaml @@ -0,0 +1,119 @@ +# Kansas LIEAP federal poverty guideline for the income limit. The season's +# published table is 150% of the prior calendar year's HHS guidelines (2026 +# flyer: $1,956/month for one person = 1.5 x 15,650 / 12), so program year Y +# uses the year Y-1 guideline. Household size counts only citizens and +# qualified aliens (KEESM 13330). Contiguous-US guidelines (gov/hhs/fpg.yaml): +# 2025 = 15,650 + 5,500 per additional person; 2024 = 15,060 + 5,380. + +- name: Case 1, single citizen in the 2026 season uses the 2025 one-person guideline. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: KS + output: + # 2025 guideline, size 1 = 15,650 + ks_liheap_fpg: 15_650 + +- name: Case 2, four citizens in the 2026 season use the 2025 four-person guideline. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + person2: + age: 38 + person3: + age: 10 + person4: + age: 7 + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + households: + household: + members: [person1, person2, person3, person4] + state_code: KS + output: + # 15,650 + 3 x 5,500 = 32,150 + ks_liheap_fpg: 32_150 + +- name: Case 3, five members with one undocumented member use the four-person guideline. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + immigration_status: CITIZEN + person2: + age: 33 + immigration_status: UNDOCUMENTED + person3: + age: 10 + person4: + age: 7 + person5: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5] + households: + household: + members: [person1, person2, person3, person4, person5] + state_code: KS + output: + # KEESM 13330: the undocumented member is not counted in household size, + # so size 4: 15,650 + 3 x 5,500 = 32,150 (size 5 would be 37,650). + ks_liheap_fpg: 32_150 + +- name: Case 4, single citizen in the 2025 season uses the 2024 one-person guideline. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: KS + output: + # 2024 guideline, size 1 = 15,060 (the 2025 guideline would be 15,650) + ks_liheap_fpg: 15_060 + +- name: Case 5, four citizens in the 2025 season use the 2024 four-person guideline. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + person2: + age: 38 + person3: + age: 10 + person4: + age: 7 + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + households: + household: + members: [person1, person2, person3, person4] + state_code: KS + output: + # 15,060 + 3 x 5,380 = 31,200 + ks_liheap_fpg: 31_200 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_eligible.yaml new file mode 100644 index 00000000000..bf0eddc69b7 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_eligible.yaml @@ -0,0 +1,280 @@ +# Kansas LIEAP income eligibility (KEESM 13100; KS LIHEAP State Plan FY2026 +# 2.1, #page=8): combined gross income of all persons at the address must not +# exceed 150% of the HHS poverty guideline for the household size. The season +# runs January-March, so the program-year Y table equals 150% of the year Y-1 +# guidelines (the 2026 flyer's $1,956/month for one person = 1.5 x 15,650 / 12). +# Contiguous-US guidelines: 2025 = 15,650 + 5,500 per additional person; +# 2024 = 15,060 + 5,380. Households with a member receiving TANF, SSI or SNAP +# are income eligible regardless (plan 1.4, #page=5). + +- name: Case 1, one person in 2026 exactly at 150% of the 2025 guideline is eligible. + period: 2026 + input: + people: + person1: + age: 35 + employment_income: 23_475 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: KS + output: + # 1.5 x 15,650 = 23,475; 23,475 <= 23,475 + ks_liheap_income_eligible: true + +- name: Case 2, one person in 2026 one dollar over the limit is ineligible. + period: 2026 + input: + people: + person1: + age: 35 + employment_income: 23_476 + spm_units: + spm_unit: + members: [person1] + snap: 0 + ks_tanf: 0 + households: + household: + members: [person1] + state_code: KS + output: + # 23,476 > 23,475 + ks_liheap_income_eligible: false + +- name: Case 3, one person in 2026 under the current-year limit but over the prior-year limit is ineligible. + period: 2026 + input: + people: + person1: + age: 35 + employment_income: 23_600 + spm_units: + spm_unit: + members: [person1] + snap: 0 + ks_tanf: 0 + households: + household: + members: [person1] + state_code: KS + output: + # Prior-year (2025) guideline: 1.5 x 15,650 = 23,475 < 23,600 -> ineligible. + # The 2026 guideline would give 1.5 x 15,960 = 23,940 and wrongly pass. + ks_liheap_income_eligible: false + +- name: Case 4, four-person household in 2026 exactly at the limit is eligible. + period: 2026 + input: + people: + person1: + age: 40 + employment_income: 30_000 + person2: + age: 38 + employment_income: 18_225 + person3: + age: 10 + person4: + age: 7 + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + ks_tanf: 0 + households: + household: + members: [person1, person2, person3, person4] + state_code: KS + output: + # 2025 guideline size 4: 15,650 + 3 x 5,500 = 32,150; x 1.5 = 48,225. + # 30,000 + 18,225 = 48,225 <= 48,225 + ks_liheap_income_eligible: true + +- name: Case 5, four-person household in 2026 one dollar over the limit is ineligible. + period: 2026 + input: + people: + person1: + age: 40 + employment_income: 30_000 + person2: + age: 38 + employment_income: 18_226 + person3: + age: 10 + person4: + age: 7 + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + snap: 0 + ks_tanf: 0 + households: + household: + members: [person1, person2, person3, person4] + state_code: KS + output: + # 48,226 > 48,225 + ks_liheap_income_eligible: false + +- name: Case 6, one person in 2025 exactly at 150% of the 2024 guideline is eligible. + period: 2025 + input: + people: + person1: + age: 35 + employment_income: 22_590 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: KS + output: + # 1.5 x 15,060 = 22,590 + ks_liheap_income_eligible: true + +- name: Case 7, one person in 2025 one dollar over the limit is ineligible. + period: 2025 + input: + people: + person1: + age: 35 + employment_income: 22_591 + spm_units: + spm_unit: + members: [person1] + snap: 0 + ks_tanf: 0 + households: + household: + members: [person1] + state_code: KS + output: + # 22,591 > 22,590 (the 2025 guideline would give 23,475 and wrongly pass) + ks_liheap_income_eligible: false + +- name: Case 8, excluded interest income does not count toward the limit. + period: 2026 + input: + people: + person1: + age: 60 + employment_income: 23_000 + interest_income: 5_000 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: KS + output: + # Countable 23,000 <= 23,475 (28,000 gross with interest would fail). + ks_liheap_income_eligible: true + +- name: Case 9, household over the limit with an SSI recipient is categorically eligible. + period: 2026 + input: + people: + person1: + age: 45 + employment_income: 40_000 + person2: + age: 70 + social_security: 8_000 + ssi: 1_200 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: KS + output: + # Size 2 limit: 1.5 x (15,650 + 5,500) = 31,725 < 49,200 gross, but + # person2 receives SSI -> income eligible (plan 1.4). + ks_liheap_income_eligible: true + +- name: Case 10, the same household without SSI receipt is ineligible. + period: 2026 + input: + people: + person1: + age: 45 + employment_income: 40_000 + person2: + age: 70 + social_security: 8_000 + ssi: 0 + spm_units: + spm_unit: + members: [person1, person2] + snap: 0 + ks_tanf: 0 + households: + household: + members: [person1, person2] + state_code: KS + output: + # 48,000 > 31,725 and no categorical route. + ks_liheap_income_eligible: false + +- name: Case 11, household over the limit receiving SNAP is categorically eligible. + period: 2026 + input: + people: + person1: + age: 45 + employment_income: 40_000 + person2: + age: 12 + spm_units: + spm_unit: + members: [person1, person2] + ks_tanf: 0 + snap: 1_200 + households: + household: + members: [person1, person2] + state_code: KS + output: + # 40,000 > 31,725, but the household receives SNAP -> income eligible. + ks_liheap_income_eligible: true + +- name: Case 12, five members with one undocumented member use the four-person limit. + period: 2026 + input: + people: + person1: + age: 35 + immigration_status: CITIZEN + employment_income: 30_000 + person2: + age: 33 + immigration_status: UNDOCUMENTED + employment_income: 20_000 + person3: + age: 10 + person4: + age: 7 + person5: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5] + snap: 0 + ks_tanf: 0 + households: + household: + members: [person1, person2, person3, person4, person5] + state_code: KS + output: + # KEESM 13330: the undocumented member is not counted in household size + # but their income is. Size 4 limit = 48,225 < 50,000 gross -> ineligible + # (the five-person limit of 56,475 would wrongly pass). + ks_liheap_income_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_earned_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_earned_income.yaml new file mode 100644 index 00000000000..ad2e50b680d --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_earned_income.yaml @@ -0,0 +1,104 @@ +# Kansas LIEAP countable earned income per person (KS LIHEAP State Plan FY2026 +# 1.8-1.9, #page=6-7): gross wages and self-employment income are counted, +# except the earned income of a child under 18. KEESM 13320: a member who is +# or turns 18 in the application month has countable income. + +- name: Case 1, adult wages are counted in full. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 24_000 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: KS + output: + ks_liheap_countable_earned_income: 24_000 + +- name: Case 2, wages and self-employment income are both earned income. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 15_000 + self_employment_income: 4_000 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: KS + output: + # 15,000 + 4,000 + ks_liheap_countable_earned_income: 19_000 + +- name: Case 3, a 17-year-old's wages are excluded while the parent's count. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 42 + employment_income: 18_000 + person2: + age: 17 + employment_income: 5_000 + spm_units: + spm_unit: + members: [person1, person2] + ks_tanf: 0 + households: + household: + members: [person1, person2] + state_code: KS + output: + ks_liheap_countable_earned_income: [18_000, 0] + +- name: Case 4, an 18-year-old's wages are counted. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 45 + employment_income: 18_000 + person2: + age: 18 + employment_income: 5_000 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: KS + output: + ks_liheap_countable_earned_income: [18_000, 5_000] + +- name: Case 5, unearned income is not part of earned income. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + social_security: 12_000 + pension_income: 6_000 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: KS + output: + ks_liheap_countable_earned_income: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_income.yaml new file mode 100644 index 00000000000..dbfcc693cff --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_income.yaml @@ -0,0 +1,191 @@ +# Kansas LIEAP countable gross income (KS LIHEAP State Plan FY2026 sections +# 1.8-1.9, #page=5-6; KEESM 13320). Counted: wages, self-employment, +# unemployment insurance, SSA benefits, SSI, retirement/pension, TANF, child +# support, alimony, rental income, VA benefits. Not counted: interest, +# dividends, royalties, earned income of a child under 18. Income of all +# household members counts, including non-qualified noncitizens (KEESM 13330). +# All amounts are annual (YEAR variable). + +- name: Case 1, interest and dividends are not counted. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 20_000 + interest_income: 3_000 + dividend_income: 2_000 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: KS + output: + # 20,000 wages; 3,000 interest + 2,000 dividends excluded (plan 1.9). + ks_liheap_countable_income: 20_000 + +- name: Case 2, earned income of a child under 18 is not counted. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 42 + employment_income: 18_000 + person2: + age: 16 + employment_income: 5_000 + spm_units: + spm_unit: + members: [person1, person2] + ks_tanf: 0 + households: + household: + members: [person1, person2] + state_code: KS + output: + # 18,000 parent wages; the 16-year-old's 5,000 wages are excluded. + ks_liheap_countable_income: 18_000 + +- name: Case 3, Social Security and SSI are counted. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + social_security: 12_000 + ssi: 3_000 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: KS + output: + # 12,000 SSA + 3,000 SSI = 15,000 (plan 1.8: SSA and SSI checked). + ks_liheap_countable_income: 15_000 + +- name: Case 4, an 18-year-old member's earnings are counted. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 45 + employment_income: 18_000 + person2: + age: 18 + employment_income: 5_000 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: KS + output: + # KEESM 13320: a member who is 18 has countable income -> 18,000 + 5,000. + ks_liheap_countable_income: 23_000 + +- name: Case 5, unearned income of a child under 18 is still counted. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 38 + employment_income: 18_000 + person2: + age: 12 + social_security: 4_000 + employment_income: 1_000 + spm_units: + spm_unit: + members: [person1, person2] + ks_tanf: 0 + households: + household: + members: [person1, person2] + state_code: KS + output: + # Only the child's *earned* income is excluded (plan 1.9); the child's + # 4,000 SSA survivor benefit counts: 18,000 + 4,000 = 22,000. + ks_liheap_countable_income: 22_000 + +- name: Case 6, other checked income sources are summed. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 50 + self_employment_income: 8_000 + unemployment_compensation: 6_000 + pension_income: 10_000 + child_support_received: 3_000 + alimony_income: 2_000 + rental_income: 4_000 + veterans_benefits: 5_000 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: KS + output: + # 8,000 + 6,000 + 10,000 + 3,000 + 2,000 + 4,000 + 5,000 = 38,000 + # (plan 1.8 checked boxes: self-employment, UI, retirement, child support, + # alimony, rental income, VA benefits). + ks_liheap_countable_income: 38_000 + +- name: Case 7, TANF cash assistance is counted. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 3_000 + person2: + age: 4 + spm_units: + spm_unit: + members: [person1, person2] + ks_tanf: 2_400 + households: + household: + members: [person1, person2] + state_code: KS + output: + # 3,000 wages + 2,400 TANF (plan 1.8: TANF checked) = 5,400. + ks_liheap_countable_income: 5_400 + +- name: Case 8, income of a non-qualified noncitizen member is counted. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + immigration_status: CITIZEN + employment_income: 6_000 + person2: + age: 33 + immigration_status: UNDOCUMENTED + employment_income: 12_000 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: KS + output: + # KEESM 13330: income from non-qualified members is counted -> 18,000. + ks_liheap_countable_income: 18_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/integration.yaml new file mode 100644 index 00000000000..426fb0f27ac --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/integration.yaml @@ -0,0 +1,475 @@ +# Kansas LIEAP end-to-end integration tests. +# Sources: KEESM 13100-13400 (eligibility, household, citizenship, energy +# vulnerability, benefit levels); KS LIHEAP State Plan FY2026 (income sources +# 1.8-1.9 #page=5-6, categorical eligibility 1.4 #page=5, 150% FPG 2.1 and +# subsidized housing 2.3 #page=8, $130 minimum 2.6 #page=9); +# KS_BenefitMatrix_2026.pdf (FY2026 season, "Benefit Adjustment @ 80%" table); +# KS_BenefitMatrix_2025.pdf (FY2025 season, 100%). +# Income limit for program year Y = 1.5 x prior-year (Y-1) HHS guideline: +# 2026: 23,475 (1) / 31,725 (2) / 48,225 (4) / 56,475 (5); +# 2025: 22,590 (1) / 46,800 (4). +# Monthly income band = annual countable income / 12: +# 1 = 0-899, 2 = 900-1,199, 3 = 1,200-1,699, 4 = 1,700+. + +- name: Case 1, single adult renting an apartment with natural gas heat. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 34 + employment_income: 22_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + ks_liheap_dwelling_type: APARTMENT + snap: 0 + ks_tanf: 0 + households: + household: + members: [person1] + state_code: KS + output: + ks_liheap_household_size: 1 + ks_liheap_household_size_group: 1 + ks_liheap_countable_income: 22_000 + # 22,000 <= 23,475 + ks_liheap_income_eligible: true + ks_liheap_categorically_income_eligible: false + ks_liheap_eligible: true + # 22,000 / 12 = 1,833 -> 1,700 & over + ks_liheap_income_band: 4 + ks_liheap_fuel_category: NATURAL_GAS + # matrix p.1 (80%) 1,700 & over, tier E (default), Apt, size 1-4 = 248 + ks_liheap_matrix_amount: 248 + ks_liheap: 248 + +- name: Case 2, family of four in an all-electric house. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 30_000 + person2: + age: 38 + employment_income: 15_000 + person3: + age: 8 + person4: + age: 5 + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + heating_type: ELECTRICITY + ks_liheap_dwelling_type: HOUSE_MODULAR_MOBILE + ks_liheap_utility_rate_tier: E + snap: 0 + ks_tanf: 0 + households: + household: + members: [person1, person2, person3, person4] + state_code: KS + output: + ks_liheap_household_size: 4 + ks_liheap_household_size_group: 1 + ks_liheap_countable_income: 45_000 + # 45,000 <= 1.5 x (15,650 + 3 x 5,500) = 48,225 + ks_liheap_income_eligible: true + ks_liheap_categorically_income_eligible: false + ks_liheap_eligible: true + # 45,000 / 12 = 3,750 -> 1,700 & over + ks_liheap_income_band: 4 + ks_liheap_fuel_category: ELECTRICITY + # matrix p.2 electricity (80%) 1,700 & over, tier E, House, size 1-4 = 730 + ks_liheap_matrix_amount: 730 + ks_liheap: 730 + +- name: Case 3, family of five in a propane-heated duplex on a tier C provider. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 36 + employment_income: 13_200 + person2: + age: 35 + person3: + age: 11 + person4: + age: 8 + person5: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5] + ks_tanf: 0 + heating_type: PROPANE + ks_liheap_dwelling_type: DUPLEX + ks_liheap_utility_rate_tier: C + households: + household: + members: [person1, person2, person3, person4, person5] + state_code: KS + output: + ks_liheap_household_size: 5 + ks_liheap_household_size_group: 2 + ks_liheap_countable_income: 13_200 + # 13,200 <= 56,475 + ks_liheap_income_eligible: true + ks_liheap_eligible: true + # 13,200 / 12 = 1,100 -> 900-1,199 + ks_liheap_income_band: 2 + ks_liheap_fuel_category: PROPANE + # matrix p.3 propane (80%) 900-1,199, tier C, Duplex, size 5+ = 393 + ks_liheap_matrix_amount: 393 + ks_liheap: 393 + +- name: Case 4, mixed-status family of five with an undocumented earner. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 33 + immigration_status: CITIZEN + employment_income: 6_000 + person2: + age: 35 + immigration_status: UNDOCUMENTED + employment_income: 12_000 + person3: + age: 9 + immigration_status: CITIZEN + person4: + age: 6 + immigration_status: CITIZEN + person5: + age: 2 + immigration_status: CITIZEN + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5] + heating_type: NATURAL_GAS + ks_liheap_dwelling_type: HOUSE_MODULAR_MOBILE + ks_liheap_utility_rate_tier: E + snap: 0 + ks_tanf: 0 + households: + household: + members: [person1, person2, person3, person4, person5] + state_code: KS + output: + # KEESM 13330: undocumented member excluded from size, income counted. + ks_liheap_household_size: 4 + ks_liheap_household_size_group: 1 + ks_liheap_countable_income: 18_000 + # 18,000 <= 48,225 (size 4) + ks_liheap_income_eligible: true + ks_liheap_categorically_income_eligible: false + ks_liheap_eligible: true + # 18,000 / 12 = 1,500 -> 1,200-1,699 + ks_liheap_income_band: 3 + ks_liheap_fuel_category: NATURAL_GAS + # size 4 -> 1-4 column: matrix p.1 (80%) 1,200-1,699, tier E, House = 567 + # (the 5+ column would give 648) + ks_liheap_matrix_amount: 567 + ks_liheap: 567 + +- name: Case 5, retired couple over the income limit but one spouse receives SSI. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 72 + social_security: 20_000 + person2: + age: 70 + social_security: 15_000 + ssi: 1_200 + spm_units: + spm_unit: + members: [person1, person2] + heating_type: ELECTRICITY + ks_liheap_dwelling_type: APARTMENT + ks_liheap_utility_rate_tier: E + households: + household: + members: [person1, person2] + state_code: KS + output: + ks_liheap_household_size: 2 + ks_liheap_household_size_group: 1 + # 20,000 + 15,000 + 1,200 SSI = 36,200 (SSA and SSI both counted) + ks_liheap_countable_income: 36_200 + # 36,200 > 1.5 x (15,650 + 5,500) = 31,725, but SSI receipt -> eligible + ks_liheap_categorically_income_eligible: true + ks_liheap_income_eligible: true + ks_liheap_eligible: true + # 36,200 / 12 = 3,017 -> 1,700 & over + ks_liheap_income_band: 4 + ks_liheap_fuel_category: ELECTRICITY + # matrix p.2 electricity (80%) 1,700 & over, tier E, Apt, size 1-4 = 365 + ks_liheap_matrix_amount: 365 + ks_liheap: 365 + +- name: Case 6, family of four with natural gas in the FY2025 season. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 10_000 + person2: + age: 38 + person3: + age: 8 + person4: + age: 5 + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + ks_tanf: 0 + heating_type: NATURAL_GAS + ks_liheap_dwelling_type: HOUSE_MODULAR_MOBILE + ks_liheap_utility_rate_tier: E + households: + household: + members: [person1, person2, person3, person4] + state_code: KS + output: + ks_liheap_household_size: 4 + ks_liheap_household_size_group: 1 + ks_liheap_countable_income: 10_000 + # 10,000 <= 1.5 x (15,060 + 3 x 5,380) = 46,800 + ks_liheap_income_eligible: true + ks_liheap_eligible: true + # 10,000 / 12 = 833 -> 0-899 + ks_liheap_income_band: 1 + ks_liheap_fuel_category: NATURAL_GAS + # KS_BenefitMatrix_2025.pdf p.1 (100%) 0-899, tier E, House, size 1-4 = 941 + ks_liheap_matrix_amount: 941 + ks_liheap: 941 + +- name: Case 7, the same family of four in the FY2026 season gets the 80 percent value. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 10_000 + person2: + age: 38 + person3: + age: 8 + person4: + age: 5 + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + ks_tanf: 0 + heating_type: NATURAL_GAS + ks_liheap_dwelling_type: HOUSE_MODULAR_MOBILE + ks_liheap_utility_rate_tier: E + households: + household: + members: [person1, person2, person3, person4] + state_code: KS + output: + ks_liheap_household_size: 4 + ks_liheap_household_size_group: 1 + ks_liheap_countable_income: 10_000 + ks_liheap_income_eligible: true + ks_liheap_eligible: true + ks_liheap_income_band: 1 + ks_liheap_fuel_category: NATURAL_GAS + # matrix p.1 (80%) 0-899, tier E, House, size 1-4 = 709 (941 x 0.8 = 752.8; + # the published 80% table cell is 709) + ks_liheap_matrix_amount: 709 + ks_liheap: 709 + +- name: Case 8, subsidized-housing renter with heat in rent is income eligible but not vulnerable. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 29 + employment_income: 12_000 + spm_units: + spm_unit: + members: [person1] + heating_type: ELECTRICITY + ks_liheap_dwelling_type: APARTMENT + receives_housing_assistance: true + heat_expense_included_in_rent: true + households: + household: + members: [person1] + state_code: KS + output: + ks_liheap_household_size: 1 + ks_liheap_household_size_group: 1 + ks_liheap_countable_income: 12_000 + ks_liheap_income_eligible: true + # KEESM 13340 / plan 2.3: heat included in subsidized rent -> ineligible + ks_liheap_eligible: false + ks_liheap_income_band: 2 + ks_liheap_fuel_category: ELECTRICITY + ks_liheap: 0 + +- name: Case 9, single adult in a propane trailer on the lowest tier gets the 130 minimum. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 55 + employment_income: 21_600 + spm_units: + spm_unit: + members: [person1] + heating_type: PROPANE + ks_liheap_dwelling_type: TRAILER_OTHER + ks_liheap_utility_rate_tier: A + households: + household: + members: [person1] + state_code: KS + output: + ks_liheap_household_size: 1 + ks_liheap_household_size_group: 1 + ks_liheap_countable_income: 21_600 + # 21,600 <= 23,475 + ks_liheap_income_eligible: true + ks_liheap_eligible: true + # 21,600 / 12 = 1,800 -> 1,700 & over + ks_liheap_income_band: 4 + ks_liheap_fuel_category: PROPANE + # matrix p.3 propane (80%) 1,700 & over, tier A, Trailer/Other, size 1-4 = 75 + ks_liheap_matrix_amount: 75 + # max(75, 130) = 130 (plan 2.6 minimum benefit) + ks_liheap: 130 + +- name: Case 10, single parent on TANF heating with purchased wood. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 26 + employment_income: 0 + person2: + age: 2 + spm_units: + spm_unit: + members: [person1, person2] + heating_type: WOOD + ks_liheap_dwelling_type: HOUSE_MODULAR_MOBILE + ks_tanf: 3_600 + households: + household: + members: [person1, person2] + state_code: KS + output: + ks_liheap_household_size: 2 + ks_liheap_household_size_group: 1 + # TANF counts as income (plan 1.8): 3,600 + ks_liheap_countable_income: 3_600 + ks_liheap_categorically_income_eligible: true + ks_liheap_income_eligible: true + ks_liheap_eligible: true + # 3,600 / 12 = 300 -> 0-899 + ks_liheap_income_band: 1 + # WOOD -> other table (no utility tier) + ks_liheap_fuel_category: OTHER + # matrix p.4 other (80%) 0-899, House, size 1-4 = 639 + ks_liheap_matrix_amount: 639 + ks_liheap: 639 + +- name: Case 11, working household with a teenager whose earnings are excluded. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 44 + employment_income: 20_000 + person2: + age: 42 + employment_income: 8_000 + interest_income: 1_500 + person3: + age: 17 + employment_income: 6_000 + spm_units: + spm_unit: + members: [person1, person2, person3] + heating_type: NATURAL_GAS + ks_liheap_dwelling_type: DUPLEX + ks_liheap_utility_rate_tier: B + snap: 0 + ks_tanf: 0 + households: + household: + members: [person1, person2, person3] + state_code: KS + output: + ks_liheap_household_size: 3 + ks_liheap_household_size_group: 1 + # 20,000 + 8,000 = 28,000; interest and the 17-year-old's wages excluded + ks_liheap_countable_income: 28_000 + # 28,000 <= 1.5 x (15,650 + 2 x 5,500) = 39,975 + ks_liheap_income_eligible: true + ks_liheap_categorically_income_eligible: false + ks_liheap_eligible: true + # 28,000 / 12 = 2,333 -> 1,700 & over + ks_liheap_income_band: 4 + ks_liheap_fuel_category: NATURAL_GAS + # matrix p.1 (80%) 1,700 & over, tier B, Duplex, size 1-4 = 307 + ks_liheap_matrix_amount: 307 + ks_liheap: 307 + +- name: Case 12, single adult in a propane trailer on the lowest tier in the FY2025 season gets the 100 minimum. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 55 + employment_income: 21_600 + spm_units: + spm_unit: + members: [person1] + heating_type: PROPANE + ks_liheap_dwelling_type: TRAILER_OTHER + ks_liheap_utility_rate_tier: A + snap: 0 + ks_tanf: 0 + households: + household: + members: [person1] + state_code: KS + output: + ks_liheap_household_size: 1 + ks_liheap_household_size_group: 1 + ks_liheap_countable_income: 21_600 + # 21,600 <= 1.5 x 15,060 = 22,590 (2025 season uses 2024 guidelines) + ks_liheap_income_eligible: true + ks_liheap_categorically_income_eligible: false + ks_liheap_eligible: true + # 21,600 / 12 = 1,800 -> 1,700 & over + ks_liheap_income_band: 4 + ks_liheap_fuel_category: PROPANE + # KS_BenefitMatrix_2025.pdf p.2 (100%) propane 1,700 & over, tier A, + # Trailer/Other, size 1-4 = 100 + ks_liheap_matrix_amount: 100 + # FY2025 minimum benefit $100 (KS LIHEAP State Plan FY2025 2.6, #page=9): + # max(100, 100) = 100 (Case 9 shows the same household in FY2026: 75 -> 130) + ks_liheap: 100 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/ks_liheap.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/ks_liheap.yaml new file mode 100644 index 00000000000..05a7d4f69b2 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/ks_liheap.yaml @@ -0,0 +1,317 @@ +# Kansas LIEAP annual heating benefit: one regular benefit per program year +# (KEESM 13310), equal to the matrix cell (KEESM 13410; KS_BenefitMatrix_2026 +# at 80%, KS_BenefitMatrix_2025 at 100%) with the $130 minimum benefit applied +# as a floor (KS LIHEAP State Plan FY2026 2.6, #page=9). The FY2025 season +# minimum is $100 (KS LIHEAP State Plan FY2025 2.6, #page=9). Zero when +# ineligible. + +- name: Case 1, eligible natural gas household receives the matrix cell. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 9_600 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + ks_liheap_utility_rate_tier: E + ks_liheap_dwelling_type: HOUSE_MODULAR_MOBILE + households: + household: + members: [person1] + state_code: KS + output: + # 800/mo -> 0-899; matrix p.1 (80%) tier E, House, size 1-4 = 709 >= 130 + ks_liheap: 709 + +- name: Case 2, propane trailer cell of 75 is raised to the 130 minimum. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 21_600 + spm_units: + spm_unit: + members: [person1] + heating_type: PROPANE + ks_liheap_utility_rate_tier: A + ks_liheap_dwelling_type: TRAILER_OTHER + households: + household: + members: [person1] + state_code: KS + output: + # 1,800/mo -> 1,700 & over; matrix p.3 (80%) tier A, Trailer/Other, + # size 1-4 = 75; max(75, 130) = 130 (plan 2.6 minimum benefit) + ks_liheap: 130 + +- name: Case 3, natural gas trailer cell of 84 is raised to the 130 minimum. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 21_600 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + ks_liheap_utility_rate_tier: A + ks_liheap_dwelling_type: TRAILER_OTHER + households: + household: + members: [person1] + state_code: KS + output: + # matrix p.1 (80%) 1,700 & over tier A, Trailer/Other, size 1-4 = 84; + # max(84, 130) = 130 + ks_liheap: 130 + +- name: Case 4, other fuel trailer cell of 128 for a large family is raised to 130. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 30_000 + person2: + age: 38 + person3: + age: 12 + person4: + age: 9 + person5: + age: 4 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5] + ks_tanf: 0 + heating_type: WOOD + ks_liheap_dwelling_type: TRAILER_OTHER + households: + household: + members: [person1, person2, person3, person4, person5] + state_code: KS + output: + # 2,500/mo -> 1,700 & over; matrix p.4 other (80%), Trailer/Other, + # size 5+ = 128; max(128, 130) = 130 + ks_liheap: 130 + +- name: Case 5, cell just above the minimum is paid unchanged. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 9_600 + person2: + age: 38 + person3: + age: 12 + person4: + age: 9 + person5: + age: 4 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5] + ks_tanf: 0 + heating_type: NATURAL_GAS + ks_liheap_utility_rate_tier: A + ks_liheap_dwelling_type: TRAILER_OTHER + households: + household: + members: [person1, person2, person3, person4, person5] + state_code: KS + output: + # 800/mo -> 0-899; matrix p.1 (80%) tier A, Trailer/Other, size 5+ = 138; + # max(138, 130) = 138 + ks_liheap: 138 + +- name: Case 6, home with no heating receives nothing. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 9_600 + spm_units: + spm_unit: + members: [person1] + heating_type: NONE + households: + household: + members: [person1] + state_code: KS + output: + ks_liheap: 0 + +- name: Case 7, household over the income limit receives nothing. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 30_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + snap: 0 + ks_tanf: 0 + households: + household: + members: [person1] + state_code: KS + output: + # 30,000 > 1.5 x 15,650 = 23,475 + ks_liheap: 0 + +- name: Case 8, subsidized-housing renter with heat in rent receives nothing. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 9_600 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + receives_housing_assistance: true + heat_expense_included_in_rent: true + households: + household: + members: [person1] + state_code: KS + output: + ks_liheap: 0 + +- name: Case 9, negative self-employment income does not inflate the benefit. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + self_employment_income: -60_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + ks_liheap_utility_rate_tier: E + ks_liheap_dwelling_type: HOUSE_MODULAR_MOBILE + households: + household: + members: [person1] + state_code: KS + output: + # Negative gross income is in the 0-899 band: matrix p.1 (80%) tier E, + # House, size 1-4 = 709, the same as zero income. + ks_liheap: 709 + +- name: Case 10, FY2025 season pays the 100 percent value. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 9_600 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + ks_liheap_utility_rate_tier: E + ks_liheap_dwelling_type: HOUSE_MODULAR_MOBILE + households: + household: + members: [person1] + state_code: KS + output: + # KS_BenefitMatrix_2025.pdf p.1 (100%) 0-899 tier E, House, size 1-4 = 941 + ks_liheap: 941 + +- name: Case 11, household outside Kansas receives nothing. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 9_600 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + households: + household: + members: [person1] + state_code: OK + output: + ks_liheap: 0 + +- name: Case 12, FY2025 propane trailer cell of 100 meets the 100 minimum and is paid as is. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 21_600 + spm_units: + spm_unit: + members: [person1] + heating_type: PROPANE + ks_liheap_utility_rate_tier: A + ks_liheap_dwelling_type: TRAILER_OTHER + snap: 0 + ks_tanf: 0 + households: + household: + members: [person1] + state_code: KS + output: + # 21,600 <= 1.5 x 15,060 = 22,590 -> eligible; 1,800/mo -> 1,700 & over; + # KS_BenefitMatrix_2025.pdf p.2 (100%) propane tier A, Trailer/Other, + # size 1-4 = 100; FY2025 minimum benefit is $100 (KS LIHEAP State Plan + # FY2025 2.6, #page=9): max(100, 100) = 100 (the FY2026 $130 floor does + # not apply to the FY2025 season). + ks_liheap: 100 + +- name: Case 13, FY2025 natural gas trailer cell of 112 is above the 100 minimum and unchanged. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 21_600 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + ks_liheap_utility_rate_tier: A + ks_liheap_dwelling_type: TRAILER_OTHER + snap: 0 + ks_tanf: 0 + households: + household: + members: [person1] + state_code: KS + output: + # KS_BenefitMatrix_2025.pdf p.1 (100%) 1,700 & over tier A, Trailer/Other, + # size 1-4 = 112; max(112, 100) = 112 (would be 130 under the FY2026 + # minimum, KS LIHEAP State Plan FY2025 2.6, #page=9 gives $100). + ks_liheap: 112 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/ks_liheap_fuel_category.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/ks_liheap_fuel_category.yaml new file mode 100644 index 00000000000..8479784972b --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/ks_liheap_fuel_category.yaml @@ -0,0 +1,175 @@ +# Kansas LIEAP primary heating fuel category (KEESM 13410; KS LIHEAP State +# Plan FY2026 2.5, #page=8-9; KS_BenefitMatrix_2026.pdf pages 1-4: Natural Gas, +# Electricity, Propane, Other). Mapping from the canonical heating_type input: +# NATURAL_GAS -> natural gas; ELECTRICITY, SOLAR -> electricity; PROPANE -> +# propane; FUEL_OIL, KEROSENE, WOOD, COAL, OTHER, UNSPECIFIED -> other. + +- name: Case 1, natural gas maps to the natural gas table. + period: 2026 + input: + people: + person1: + age: 30 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + households: + household: + members: [person1] + state_code: KS + output: + ks_liheap_fuel_category: NATURAL_GAS + +- name: Case 2, electricity maps to the electricity table. + period: 2026 + input: + people: + person1: + age: 30 + spm_units: + spm_unit: + members: [person1] + heating_type: ELECTRICITY + households: + household: + members: [person1] + state_code: KS + output: + ks_liheap_fuel_category: ELECTRICITY + +- name: Case 3, solar maps to the electricity table. + period: 2026 + input: + people: + person1: + age: 30 + spm_units: + spm_unit: + members: [person1] + heating_type: SOLAR + households: + household: + members: [person1] + state_code: KS + output: + ks_liheap_fuel_category: ELECTRICITY + +- name: Case 4, propane maps to the propane table. + period: 2026 + input: + people: + person1: + age: 30 + spm_units: + spm_unit: + members: [person1] + heating_type: PROPANE + households: + household: + members: [person1] + state_code: KS + output: + ks_liheap_fuel_category: PROPANE + +- name: Case 5, fuel oil maps to the other table. + period: 2026 + input: + people: + person1: + age: 30 + spm_units: + spm_unit: + members: [person1] + heating_type: FUEL_OIL + households: + household: + members: [person1] + state_code: KS + output: + ks_liheap_fuel_category: OTHER + +- name: Case 6, kerosene maps to the other table. + period: 2026 + input: + people: + person1: + age: 30 + spm_units: + spm_unit: + members: [person1] + heating_type: KEROSENE + households: + household: + members: [person1] + state_code: KS + output: + ks_liheap_fuel_category: OTHER + +- name: Case 7, wood maps to the other table. + period: 2026 + input: + people: + person1: + age: 30 + spm_units: + spm_unit: + members: [person1] + heating_type: WOOD + households: + household: + members: [person1] + state_code: KS + output: + ks_liheap_fuel_category: OTHER + +- name: Case 8, coal maps to the other table. + period: 2026 + input: + people: + person1: + age: 30 + spm_units: + spm_unit: + members: [person1] + heating_type: COAL + households: + household: + members: [person1] + state_code: KS + output: + ks_liheap_fuel_category: OTHER + +- name: Case 9, other fuel maps to the other table. + period: 2026 + input: + people: + person1: + age: 30 + spm_units: + spm_unit: + members: [person1] + heating_type: OTHER + households: + household: + members: [person1] + state_code: KS + output: + ks_liheap_fuel_category: OTHER + +- name: Case 10, unspecified heating type defaults to the other table. + period: 2026 + input: + people: + person1: + age: 30 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: KS + output: + # heating_type defaults to UNSPECIFIED -> other (scope decision). + ks_liheap_fuel_category: OTHER diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/ks_liheap_household_size.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/ks_liheap_household_size.yaml new file mode 100644 index 00000000000..016bf6d9ffa --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/ks_liheap_household_size.yaml @@ -0,0 +1,158 @@ +# Kansas LIEAP household size (KEESM 13330): members who are U.S. citizens or +# qualified noncitizens. Non-qualified members are not counted in the household +# size, although their income still counts (see ks_liheap_countable_income.yaml). +# Qualified aliens per KEESM 13330: legal permanent residents, refugees, +# asylees, parolees (1+ year), deportation withheld, conditional entrants. + +- name: Case 1, single citizen counts as one. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: KS + output: + ks_liheap_household_size: 1 + +- name: Case 2, family of four citizens counts four. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + person2: + age: 33 + person3: + age: 8 + person4: + age: 5 + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + households: + household: + members: [person1, person2, person3, person4] + state_code: KS + output: + ks_liheap_household_size: 4 + +- name: Case 3, five members with one undocumented adult counts four. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + immigration_status: CITIZEN + person2: + age: 33 + immigration_status: UNDOCUMENTED + person3: + age: 10 + person4: + age: 7 + person5: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5] + households: + household: + members: [person1, person2, person3, person4, person5] + state_code: KS + output: + # KEESM 13330: the undocumented member is excluded -> 5 - 1 = 4. + ks_liheap_household_size: 4 + +- name: Case 4, lawful permanent resident is a qualified noncitizen and counts. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 45 + immigration_status: CITIZEN + person2: + age: 44 + immigration_status: LEGAL_PERMANENT_RESIDENT + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: KS + output: + ks_liheap_household_size: 2 + +- name: Case 5, household of two undocumented members counts zero. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + immigration_status: UNDOCUMENTED + person2: + age: 28 + immigration_status: UNDOCUMENTED + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: KS + output: + ks_liheap_household_size: 0 + +- name: Case 6, DACA member is not a qualified noncitizen and is excluded. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 50 + immigration_status: CITIZEN + person2: + age: 22 + immigration_status: DACA + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: KS + output: + # DACA is not on the KEESM 13330 qualified-alien list (8 USC 1641). + ks_liheap_household_size: 1 + +- name: Case 7, refugee with a citizen child counts two. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 36 + immigration_status: REFUGEE + person2: + age: 6 + immigration_status: CITIZEN + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: KS + output: + ks_liheap_household_size: 2 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/payment/ks_liheap_household_size_group.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/payment/ks_liheap_household_size_group.yaml new file mode 100644 index 00000000000..af0aa2ddd90 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/payment/ks_liheap_household_size_group.yaml @@ -0,0 +1,152 @@ +# Kansas LIEAP benefit matrix household size group +# (KS_BenefitMatrix_2026.pdf columns "Household Size 1-4" and "Household Size +# 5 and Over"): group 1 for one to four countable members, group 2 for five +# or more. Size counts only citizens and qualified aliens (KEESM 13330). + +- name: Case 1, single person is in the 1-4 group. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: KS + output: + ks_liheap_household_size_group: 1 + +- name: Case 2, four members are the top of the 1-4 group. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + person2: + age: 38 + person3: + age: 10 + person4: + age: 6 + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + households: + household: + members: [person1, person2, person3, person4] + state_code: KS + output: + ks_liheap_household_size_group: 1 + +- name: Case 3, five members are the bottom of the 5 and over group. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + person2: + age: 38 + person3: + age: 10 + person4: + age: 6 + person5: + age: 2 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5] + households: + household: + members: [person1, person2, person3, person4, person5] + state_code: KS + output: + ks_liheap_household_size_group: 2 + +- name: Case 4, seven members are in the 5 and over group. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + person2: + age: 38 + person3: + age: 16 + person4: + age: 12 + person5: + age: 9 + person6: + age: 5 + person7: + age: 2 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5, person6, person7] + households: + household: + members: [person1, person2, person3, person4, person5, person6, person7] + state_code: KS + output: + ks_liheap_household_size_group: 2 + +- name: Case 5, five members with one undocumented member fall in the 1-4 group. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + person2: + age: 38 + immigration_status: UNDOCUMENTED + person3: + age: 10 + person4: + age: 6 + person5: + age: 2 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5] + households: + household: + members: [person1, person2, person3, person4, person5] + state_code: KS + output: + # KEESM 13330: countable size 4 -> "Household Size 1-4" + ks_liheap_household_size_group: 1 + +- name: Case 6, FY2025 season uses the same size groups. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + person2: + age: 38 + person3: + age: 10 + person4: + age: 6 + person5: + age: 2 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5] + households: + household: + members: [person1, person2, person3, person4, person5] + state_code: KS + output: + # KS_BenefitMatrix_2025.pdf columns are the same 1-4 / 5 and over split. + ks_liheap_household_size_group: 2 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/payment/ks_liheap_income_band.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/payment/ks_liheap_income_band.yaml new file mode 100644 index 00000000000..3864574ef62 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/payment/ks_liheap_income_band.yaml @@ -0,0 +1,199 @@ +# Kansas LIEAP one-month income band (KS_BenefitMatrix_2026.pdf rows; +# KEESM 13230 uses income of the application month). Monthly income = +# annual countable income / 12. Bands: 1 = 0-899, 2 = 900-1,199, +# 3 = 1,200-1,699, 4 = 1,700 and over. + +- name: Case 1, zero income is in the lowest band. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 0 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: KS + output: + # 0 / 12 = 0 -> "0 - 899" + ks_liheap_income_band: 1 + +- name: Case 2, 899 per month is the top of band 1. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 10_788 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: KS + output: + # 10,788 / 12 = 899 -> "0 - 899" + ks_liheap_income_band: 1 + +- name: Case 3, 900 per month is the bottom of band 2. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 10_800 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: KS + output: + # 10,800 / 12 = 900 -> "900 - 1,199" + ks_liheap_income_band: 2 + +- name: Case 4, 1,199 per month is the top of band 2. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 14_388 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: KS + output: + # 14,388 / 12 = 1,199 -> "900 - 1,199" + ks_liheap_income_band: 2 + +- name: Case 5, 1,200 per month is the bottom of band 3. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 14_400 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: KS + output: + # 14,400 / 12 = 1,200 -> "1,200 - 1,699" + ks_liheap_income_band: 3 + +- name: Case 6, 1,699 per month is the top of band 3. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 20_388 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: KS + output: + # 20,388 / 12 = 1,699 -> "1,200 - 1,699" + ks_liheap_income_band: 3 + +- name: Case 7, 1,700 per month is the bottom of band 4. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 20_400 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: KS + output: + # 20,400 / 12 = 1,700 -> "1,700 & over" + ks_liheap_income_band: 4 + +- name: Case 8, high income is in band 4. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 30_000 + person2: + age: 38 + employment_income: 30_000 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: KS + output: + # 60,000 / 12 = 5,000 -> "1,700 & over" + ks_liheap_income_band: 4 + +- name: Case 9, band uses countable income so excluded interest does not move it. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 10_800 + interest_income: 6_000 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: KS + output: + # Countable 10,800 / 12 = 900 -> band 2 (interest excluded; 16,800 / 12 + # = 1,400 would wrongly be band 3). + ks_liheap_income_band: 2 + +- name: Case 10, FY2025 season uses the same band thresholds. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 14_400 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: KS + output: + # 14,400 / 12 = 1,200 -> "1,200 - 1,699" (KS_BenefitMatrix_2025.pdf rows) + ks_liheap_income_band: 3 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/payment/ks_liheap_matrix_amount.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/payment/ks_liheap_matrix_amount.yaml new file mode 100644 index 00000000000..e494f7afbc4 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/payment/ks_liheap_matrix_amount.yaml @@ -0,0 +1,668 @@ +# Kansas LIEAP benefit matrix lookup (KEESM 13410; KS LIHEAP State Plan FY2026 +# 2.5, #page=8-9). Dimensions: primary fuel table (natural gas p.1, +# electricity p.2, propane p.3, other p.4 of KS_BenefitMatrix_2026.pdf), +# one-month income band, utility range tier A-J (no tier on the Other table), +# dwelling type (House/Modular/Mobile, Duplex, Apt, Trailer/Other) and +# household size group (1-4, 5 and over). FY2026 (period 2026) pays the +# right-hand "Benefit Adjustment @ 80%" values; FY2025 (period 2025) pays the +# KS_BenefitMatrix_2025.pdf values at 100%. Raw cell values: the $130 minimum +# benefit floor is applied in ks_liheap, not here. Inputs are annual; monthly +# income = annual / 12. Defaults: tier E, dwelling House/Modular/Mobile. + +- name: Case 1, natural gas, band 1, default tier E and house, size 1. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 9_600 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + households: + household: + members: [person1] + state_code: KS + output: + # 9,600 / 12 = 800 -> 0-899; matrix p.1 (80%) tier E, House, size 1-4 = 709 + ks_liheap_matrix_amount: 709 + +- name: Case 2, natural gas, band 1, tier E, duplex. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 9_600 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + ks_liheap_utility_rate_tier: E + ks_liheap_dwelling_type: DUPLEX + households: + household: + members: [person1] + state_code: KS + output: + # matrix p.1 (80%) 0-899 tier E, Duplex, size 1-4 = 532 + ks_liheap_matrix_amount: 532 + +- name: Case 3, natural gas, band 1, tier E, apartment. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 9_600 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + ks_liheap_utility_rate_tier: E + ks_liheap_dwelling_type: APARTMENT + households: + household: + members: [person1] + state_code: KS + output: + # matrix p.1 (80%) 0-899 tier E, Apt, size 1-4 = 354 + ks_liheap_matrix_amount: 354 + +- name: Case 4, natural gas, band 1, tier E, trailer. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 9_600 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + ks_liheap_utility_rate_tier: E + ks_liheap_dwelling_type: TRAILER_OTHER + households: + household: + members: [person1] + state_code: KS + output: + # matrix p.1 (80%) 0-899 tier E, Trailer/Other, size 1-4 = 177 + ks_liheap_matrix_amount: 177 + +- name: Case 5, natural gas, band 1, lowest tier A, house. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 9_600 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + ks_liheap_utility_rate_tier: A + ks_liheap_dwelling_type: HOUSE_MODULAR_MOBILE + households: + household: + members: [person1] + state_code: KS + output: + # matrix p.1 (80%) 0-899 tier A, House, size 1-4 = 482 + ks_liheap_matrix_amount: 482 + +- name: Case 6, natural gas, band 1, highest tier J, house. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 9_600 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + ks_liheap_utility_rate_tier: J + ks_liheap_dwelling_type: HOUSE_MODULAR_MOBILE + households: + household: + members: [person1] + state_code: KS + output: + # matrix p.1 (80%) 0-899 tier J, House, size 1-4 = 1,136 + ks_liheap_matrix_amount: 1_136 + +- name: Case 7, natural gas, band 1, tier E, house, family of four uses the 1-4 column. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 9_600 + person2: + age: 38 + person3: + age: 10 + person4: + age: 6 + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + ks_tanf: 0 + heating_type: NATURAL_GAS + ks_liheap_utility_rate_tier: E + ks_liheap_dwelling_type: HOUSE_MODULAR_MOBILE + households: + household: + members: [person1, person2, person3, person4] + state_code: KS + output: + # size 4 -> "Household Size 1-4": matrix p.1 (80%) 0-899 tier E, House = 709 + ks_liheap_matrix_amount: 709 + +- name: Case 8, natural gas, band 1, tier E, house, family of five uses the 5+ column. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 9_600 + person2: + age: 38 + person3: + age: 10 + person4: + age: 6 + person5: + age: 2 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5] + ks_tanf: 0 + heating_type: NATURAL_GAS + ks_liheap_utility_rate_tier: E + ks_liheap_dwelling_type: HOUSE_MODULAR_MOBILE + households: + household: + members: [person1, person2, person3, person4, person5] + state_code: KS + output: + # size 5 -> "Household Size 5 and Over": matrix p.1 (80%) 0-899 tier E, + # House = 810 + ks_liheap_matrix_amount: 810 + +- name: Case 9, natural gas, band 2, tier E, house. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 13_200 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + ks_liheap_utility_rate_tier: E + ks_liheap_dwelling_type: HOUSE_MODULAR_MOBILE + households: + household: + members: [person1] + state_code: KS + output: + # 13,200 / 12 = 1,100 -> 900-1,199; matrix p.1 (80%) tier E, House = 638 + ks_liheap_matrix_amount: 638 + +- name: Case 10, natural gas, band 3, tier E, house. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 18_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + ks_liheap_utility_rate_tier: E + ks_liheap_dwelling_type: HOUSE_MODULAR_MOBILE + households: + household: + members: [person1] + state_code: KS + output: + # 18,000 / 12 = 1,500 -> 1,200-1,699; matrix p.1 (80%) tier E, House = 567 + ks_liheap_matrix_amount: 567 + +- name: Case 11, natural gas, band 4, tier E, house. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 21_600 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + ks_liheap_utility_rate_tier: E + ks_liheap_dwelling_type: HOUSE_MODULAR_MOBILE + households: + household: + members: [person1] + state_code: KS + output: + # 21,600 / 12 = 1,800 -> 1,700 & over; matrix p.1 (80%) tier E, House = 496 + ks_liheap_matrix_amount: 496 + +- name: Case 12, natural gas, band 2, tier G, duplex, size 5+. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 13_200 + person2: + age: 38 + person3: + age: 12 + person4: + age: 9 + person5: + age: 4 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5] + ks_tanf: 0 + heating_type: NATURAL_GAS + ks_liheap_utility_rate_tier: G + ks_liheap_dwelling_type: DUPLEX + households: + household: + members: [person1, person2, person3, person4, person5] + state_code: KS + output: + # 1,100/mo -> 900-1,199; matrix p.1 (80%) tier G, Duplex, size 5+ = 585 + ks_liheap_matrix_amount: 585 + +- name: Case 13, electricity, band 1, tier E, house. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 9_600 + spm_units: + spm_unit: + members: [person1] + heating_type: ELECTRICITY + ks_liheap_utility_rate_tier: E + ks_liheap_dwelling_type: HOUSE_MODULAR_MOBILE + households: + household: + members: [person1] + state_code: KS + output: + # matrix p.2 electricity (80%) 0-899 tier E, House, size 1-4 = 1,043 + ks_liheap_matrix_amount: 1_043 + +- name: Case 14, electricity, band 4, tier E, apartment, size 5+. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 30_000 + person2: + age: 38 + person3: + age: 12 + person4: + age: 9 + person5: + age: 4 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5] + ks_tanf: 0 + heating_type: ELECTRICITY + ks_liheap_utility_rate_tier: E + ks_liheap_dwelling_type: APARTMENT + households: + household: + members: [person1, person2, person3, person4, person5] + state_code: KS + output: + # 30,000 / 12 = 2,500 -> 1,700 & over; matrix p.2 (80%) tier E, Apt, + # size 5+ = 417 + ks_liheap_matrix_amount: 417 + +- name: Case 15, electricity, band 3, tier H, trailer. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 18_000 + spm_units: + spm_unit: + members: [person1] + heating_type: ELECTRICITY + ks_liheap_utility_rate_tier: H + ks_liheap_dwelling_type: TRAILER_OTHER + households: + household: + members: [person1] + state_code: KS + output: + # 1,500/mo -> 1,200-1,699; matrix p.2 (80%) tier H, Trailer/Other, + # size 1-4 = 232 + ks_liheap_matrix_amount: 232 + +- name: Case 16, solar heating uses the electricity table. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 9_600 + spm_units: + spm_unit: + members: [person1] + heating_type: SOLAR + ks_liheap_utility_rate_tier: E + ks_liheap_dwelling_type: HOUSE_MODULAR_MOBILE + households: + household: + members: [person1] + state_code: KS + output: + # SOLAR -> electricity: matrix p.2 (80%) 0-899 tier E, House = 1,043 + ks_liheap_matrix_amount: 1_043 + +- name: Case 17, propane, band 1, tier E, house. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 9_600 + spm_units: + spm_unit: + members: [person1] + heating_type: PROPANE + ks_liheap_utility_rate_tier: E + ks_liheap_dwelling_type: HOUSE_MODULAR_MOBILE + households: + household: + members: [person1] + state_code: KS + output: + # matrix p.3 propane (80%) 0-899 tier E, House, size 1-4 = 553 + ks_liheap_matrix_amount: 553 + +- name: Case 18, propane, band 4, tier A, trailer returns the raw cell below the floor. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 21_600 + spm_units: + spm_unit: + members: [person1] + heating_type: PROPANE + ks_liheap_utility_rate_tier: A + ks_liheap_dwelling_type: TRAILER_OTHER + households: + household: + members: [person1] + state_code: KS + output: + # 1,800/mo -> 1,700 & over; matrix p.3 (80%) tier A, Trailer/Other, + # size 1-4 = 75 (the $130 floor is applied in ks_liheap) + ks_liheap_matrix_amount: 75 + +- name: Case 19, propane, band 3, tier C, apartment, size 5+. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 18_000 + person2: + age: 38 + person3: + age: 12 + person4: + age: 9 + person5: + age: 4 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5] + ks_tanf: 0 + heating_type: PROPANE + ks_liheap_utility_rate_tier: C + ks_liheap_dwelling_type: APARTMENT + households: + household: + members: [person1, person2, person3, person4, person5] + state_code: KS + output: + # 1,500/mo -> 1,200-1,699; matrix p.3 (80%) tier C, Apt, size 5+ = 233 + ks_liheap_matrix_amount: 233 + +- name: Case 20, wood heat uses the other table, band 1, house. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 9_600 + spm_units: + spm_unit: + members: [person1] + heating_type: WOOD + ks_liheap_dwelling_type: HOUSE_MODULAR_MOBILE + households: + household: + members: [person1] + state_code: KS + output: + # matrix p.4 other (80%) 0-899, House, size 1-4 = 639 (no tier) + ks_liheap_matrix_amount: 639 + +- name: Case 21, fuel oil on the other table ignores the utility tier. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 9_600 + spm_units: + spm_unit: + members: [person1] + heating_type: FUEL_OIL + ks_liheap_utility_rate_tier: J + ks_liheap_dwelling_type: HOUSE_MODULAR_MOBILE + households: + household: + members: [person1] + state_code: KS + output: + # matrix p.4 other (80%) 0-899, House, size 1-4 = 639 regardless of tier J + ks_liheap_matrix_amount: 639 + +- name: Case 22, other fuel, band 4, trailer, size 5+. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 30_000 + person2: + age: 38 + person3: + age: 12 + person4: + age: 9 + person5: + age: 4 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5] + ks_tanf: 0 + heating_type: OTHER + ks_liheap_dwelling_type: TRAILER_OTHER + households: + household: + members: [person1, person2, person3, person4, person5] + state_code: KS + output: + # 2,500/mo -> 1,700 & over; matrix p.4 other (80%), Trailer/Other, + # size 5+ = 128 + ks_liheap_matrix_amount: 128 + +- name: Case 23, zero income lands in band 1. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 0 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + ks_liheap_utility_rate_tier: E + ks_liheap_dwelling_type: HOUSE_MODULAR_MOBILE + households: + household: + members: [person1] + state_code: KS + output: + # 0/mo -> 0-899; matrix p.1 (80%) tier E, House, size 1-4 = 709 + ks_liheap_matrix_amount: 709 + +- name: Case 24, FY2025 season pays the 100 percent natural gas value for the Case 1 household. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 9_600 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + ks_liheap_utility_rate_tier: E + ks_liheap_dwelling_type: HOUSE_MODULAR_MOBILE + households: + household: + members: [person1] + state_code: KS + output: + # KS_BenefitMatrix_2025.pdf p.1 (100%) 0-899 tier E, House, size 1-4 = 941 + # (vs 709 at 80% in FY2026, Case 1) + ks_liheap_matrix_amount: 941 + +- name: Case 25, FY2025 electricity, band 1, tier E, house, size 5+. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 9_600 + person2: + age: 38 + person3: + age: 12 + person4: + age: 9 + person5: + age: 4 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5] + ks_tanf: 0 + heating_type: ELECTRICITY + ks_liheap_utility_rate_tier: E + ks_liheap_dwelling_type: HOUSE_MODULAR_MOBILE + households: + household: + members: [person1, person2, person3, person4, person5] + state_code: KS + output: + # KS_BenefitMatrix_2025.pdf p.2 (100%) 0-899 tier E, House, size 5+ = 1,584 + ks_liheap_matrix_amount: 1_584 + +- name: Case 26, FY2025 propane, band 2, tier J, duplex. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 13_200 + spm_units: + spm_unit: + members: [person1] + heating_type: PROPANE + ks_liheap_utility_rate_tier: J + ks_liheap_dwelling_type: DUPLEX + households: + household: + members: [person1] + state_code: KS + output: + # 1,100/mo -> 900-1,199; KS_BenefitMatrix_2025.pdf p.3 (100%) tier J, + # Duplex, size 1-4 = 868 + ks_liheap_matrix_amount: 868 + +- name: Case 27, FY2025 other fuel, band 4, house. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 21_600 + spm_units: + spm_unit: + members: [person1] + heating_type: KEROSENE + ks_liheap_dwelling_type: HOUSE_MODULAR_MOBILE + households: + household: + members: [person1] + state_code: KS + output: + # 1,800/mo -> 1,700 & over; KS_BenefitMatrix_2025.pdf p.4 (100%) other, + # House, size 1-4 = 594 + ks_liheap_matrix_amount: 594 diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_categorically_income_eligible.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_categorically_income_eligible.py new file mode 100644 index 00000000000..d33b70e219a --- /dev/null +++ b/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_categorically_income_eligible.py @@ -0,0 +1,17 @@ +from policyengine_us.model_api import * + + +class ks_liheap_categorically_income_eligible(Variable): + value_type = bool + entity = SPMUnit + definition_period = YEAR + label = "Kansas LIEAP categorically income eligible" + documentation = "Households with a member receiving TANF, SSI or SNAP are considered income eligible for Kansas LIEAP heating assistance." + reference = "https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=5" + defined_for = StateCode.KS + + def formula(spm_unit, period, parameters): + receives_ssi = add(spm_unit, period, ["ssi"]) > 0 + receives_snap = spm_unit("snap", period) > 0 + receives_tanf = spm_unit("ks_tanf", period) > 0 + return receives_ssi | receives_snap | receives_tanf diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_eligible.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_eligible.py new file mode 100644 index 00000000000..7a06964bcbd --- /dev/null +++ b/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_eligible.py @@ -0,0 +1,24 @@ +from policyengine_us.model_api import * + + +class ks_liheap_eligible(Variable): + value_type = bool + entity = SPMUnit + definition_period = YEAR + label = "Eligible for Kansas LIEAP" + documentation = "Kansas household that is income eligible, has at least one U.S. citizen or qualified alien member, heats its home (energy vulnerability), and is not a subsidized-housing renter whose heating costs are included in the rent." + reference = ( + "https://content.dcf.ks.gov/ees/keesm/current/keesm13300.htm", + "https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=8", + ) + defined_for = StateCode.KS + + def formula(spm_unit, period, parameters): + income_eligible = spm_unit("ks_liheap_income_eligible", period) + has_citizen = spm_unit("ks_liheap_household_size", period) > 0 + heating_type = spm_unit("heating_type", period) + has_heating = heating_type != heating_type.possible_values.NONE + housing_assistance = spm_unit("receives_housing_assistance", period) + heat_in_rent = spm_unit("heat_expense_included_in_rent", period) + subsidized_heat_in_rent = housing_assistance & heat_in_rent + return income_eligible & has_citizen & has_heating & ~subsidized_heat_in_rent diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_fpg.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_fpg.py new file mode 100644 index 00000000000..d5a25563656 --- /dev/null +++ b/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_fpg.py @@ -0,0 +1,24 @@ +from policyengine_us.model_api import * + + +class ks_liheap_fpg(Variable): + value_type = float + entity = SPMUnit + definition_period = YEAR + label = "Kansas LIEAP federal poverty guideline" + documentation = "Federal poverty guideline used for the Kansas LIEAP income limit. The household size counts only U.S. citizens and qualified aliens (KEESM 13330), and the guideline is the prior calendar year's because each season's published income table is 150% of the prior year's HHS poverty guidelines." + unit = USD + reference = ( + "https://content.dcf.ks.gov/ees/keesm/current/keesm13300.htm", + "https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=8", + "https://www.dcf.ks.gov/services/ees/pages/energyassistance.aspx", + ) + defined_for = StateCode.KS + + def formula(spm_unit, period, parameters): + size = spm_unit("ks_liheap_household_size", period) + state_group = spm_unit.household("state_group_str", period) + p_fpg = parameters(period.last_year).gov.hhs.fpg + first_person = p_fpg.first_person[state_group] + additional_person = p_fpg.additional_person[state_group] + return first_person + additional_person * max_(size - 1, 0) diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_eligible.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_eligible.py new file mode 100644 index 00000000000..f687202f343 --- /dev/null +++ b/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_eligible.py @@ -0,0 +1,24 @@ +from policyengine_us.model_api import * + + +class ks_liheap_income_eligible(Variable): + value_type = bool + entity = SPMUnit + definition_period = YEAR + label = "Kansas LIEAP income eligible" + documentation = "Combined gross income of all household members does not exceed 150% of the federal poverty guideline for the countable household size, or the household is categorically income eligible." + reference = ( + "https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=8", + "https://content.dcf.ks.gov/ees/keesm/current/keesm13000.htm", + "https://content.dcf.ks.gov/ees/keesm/current/keesm13300.htm", + ) + defined_for = StateCode.KS + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ks.dcf.liheap.eligibility + income = spm_unit("ks_liheap_countable_income", period) + fpg = spm_unit("ks_liheap_fpg", period) + categorically_eligible = spm_unit( + "ks_liheap_categorically_income_eligible", period + ) + return categorically_eligible | (income <= fpg * p.fpg_limit) diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_earned_income.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_earned_income.py new file mode 100644 index 00000000000..a50b4cdb6cd --- /dev/null +++ b/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_earned_income.py @@ -0,0 +1,21 @@ +from policyengine_us.model_api import * + + +class ks_liheap_countable_earned_income(Variable): + value_type = float + entity = Person + definition_period = YEAR + label = "Kansas LIEAP countable earned income" + documentation = "Gross earned income counted toward Kansas LIEAP household income. Earned income of a child under 18 is not counted." + unit = USD + reference = ( + "https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=6", + "https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=7", + ) + defined_for = StateCode.KS + + def formula(person, period, parameters): + p = parameters(period).gov.states.ks.dcf.liheap.income + earned = add(person, period, p.sources.earned) + age = person("age", period) + return where(age >= p.earned_income_min_age, earned, 0) diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_income.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_income.py new file mode 100644 index 00000000000..408fb6ef8fa --- /dev/null +++ b/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_income.py @@ -0,0 +1,20 @@ +from policyengine_us.model_api import * + + +class ks_liheap_countable_income(Variable): + value_type = float + entity = SPMUnit + definition_period = YEAR + label = "Kansas LIEAP countable income" + documentation = "Combined gross income of all persons living at the address counted under Kansas LIEAP, including the income of members who are not citizens or qualified aliens." + unit = USD + reference = ( + "https://content.dcf.ks.gov/ees/keesm/current/keesm13000.htm", + "https://content.dcf.ks.gov/ees/keesm/current/keesm13300.htm", + ) + defined_for = StateCode.KS + + adds = [ + "ks_liheap_countable_earned_income", + "ks_liheap_countable_unearned_income", + ] diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_unearned_income.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_unearned_income.py new file mode 100644 index 00000000000..f79bceed22f --- /dev/null +++ b/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_unearned_income.py @@ -0,0 +1,14 @@ +from policyengine_us.model_api import * + + +class ks_liheap_countable_unearned_income(Variable): + value_type = float + entity = SPMUnit + definition_period = YEAR + label = "Kansas LIEAP countable unearned income" + documentation = "Gross unearned income of all household members counted toward Kansas LIEAP household income." + unit = USD + reference = "https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=6" + defined_for = StateCode.KS + + adds = "gov.states.ks.dcf.liheap.income.sources.unearned" diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/ks_liheap.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/ks_liheap.py new file mode 100644 index 00000000000..a3f47049e6b --- /dev/null +++ b/policyengine_us/variables/gov/states/ks/dcf/liheap/ks_liheap.py @@ -0,0 +1,20 @@ +from policyengine_us.model_api import * + + +class ks_liheap(Variable): + value_type = float + entity = SPMUnit + label = "Kansas LIEAP" + documentation = "Annual Kansas Low Income Energy Assistance Program (LIEAP) heating benefit: the benefit matrix amount, subject to the minimum benefit." + unit = USD + definition_period = YEAR + defined_for = "ks_liheap_eligible" + reference = ( + "https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=9", + "https://content.dcf.ks.gov/ees/keesm/current/keesm13400.htm", + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ks.dcf.liheap.payment + matrix_amount = spm_unit("ks_liheap_matrix_amount", period) + return max_(matrix_amount, p.min_benefit) diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/ks_liheap_dwelling_type.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/ks_liheap_dwelling_type.py new file mode 100644 index 00000000000..3f4979ea2ef --- /dev/null +++ b/policyengine_us/variables/gov/states/ks/dcf/liheap/ks_liheap_dwelling_type.py @@ -0,0 +1,19 @@ +from policyengine_us.model_api import * + + +class KSLIEAPDwellingType(Enum): + HOUSE_MODULAR_MOBILE = "House, modular home or mobile home" + DUPLEX = "Duplex" + APARTMENT = "Apartment" + TRAILER_OTHER = "Trailer or other dwelling" + + +class ks_liheap_dwelling_type(Variable): + value_type = Enum + entity = SPMUnit + possible_values = KSLIEAPDwellingType + default_value = KSLIEAPDwellingType.HOUSE_MODULAR_MOBILE + definition_period = YEAR + label = "Kansas LIEAP dwelling type" + documentation = "Dwelling type column of the Kansas LIEAP benefit matrix: house, modular home or mobile home; duplex; apartment; or trailer or other dwelling. Defaults to the house, modular or mobile home column." + reference = "https://liheapch.acf.gov/docs/2026/benefits-matricies/KS_BenefitMatrix_2026.pdf#page=1" diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/ks_liheap_fuel_category.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/ks_liheap_fuel_category.py new file mode 100644 index 00000000000..89f9a56005d --- /dev/null +++ b/policyengine_us/variables/gov/states/ks/dcf/liheap/ks_liheap_fuel_category.py @@ -0,0 +1,43 @@ +from policyengine_us.model_api import * + + +class KSLIEAPFuelCategory(Enum): + NATURAL_GAS = "Natural gas" + ELECTRICITY = "Electricity" + PROPANE = "Propane" + OTHER = "Other" + + +class ks_liheap_fuel_category(Variable): + value_type = Enum + entity = SPMUnit + possible_values = KSLIEAPFuelCategory + default_value = KSLIEAPFuelCategory.OTHER + definition_period = YEAR + label = "Kansas LIEAP primary heating fuel category" + documentation = "Benefit matrix fuel table derived from the canonical heating_type input: natural gas; electricity (including solar); propane; and other for fuel oil, kerosene, wood, coal, other fuels, no heating and an unspecified fuel." + reference = ( + "https://liheapch.acf.gov/docs/2026/benefits-matricies/KS_BenefitMatrix_2026.pdf#page=4", + "https://content.dcf.ks.gov/ees/keesm/current/keesm13400.htm", + ) + defined_for = StateCode.KS + + def formula(spm_unit, period, parameters): + heating_type = spm_unit("heating_type", period) + types = heating_type.possible_values + natural_gas = heating_type == types.NATURAL_GAS + electricity = (heating_type == types.ELECTRICITY) | ( + heating_type == types.SOLAR + ) + propane = heating_type == types.PROPANE + other = ~(natural_gas | electricity | propane) + return select( + [natural_gas, electricity, propane, other], + [ + KSLIEAPFuelCategory.NATURAL_GAS, + KSLIEAPFuelCategory.ELECTRICITY, + KSLIEAPFuelCategory.PROPANE, + KSLIEAPFuelCategory.OTHER, + ], + default=KSLIEAPFuelCategory.OTHER, + ) diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/ks_liheap_household_size.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/ks_liheap_household_size.py new file mode 100644 index 00000000000..0fbca27a8d7 --- /dev/null +++ b/policyengine_us/variables/gov/states/ks/dcf/liheap/ks_liheap_household_size.py @@ -0,0 +1,13 @@ +from policyengine_us.model_api import * + + +class ks_liheap_household_size(Variable): + value_type = int + entity = SPMUnit + definition_period = YEAR + label = "Kansas LIEAP household size" + documentation = "Number of household members who are U.S. citizens or qualified aliens. Other members are not counted in household size, although their income counts toward household income." + reference = "https://content.dcf.ks.gov/ees/keesm/current/keesm13300.htm" + defined_for = StateCode.KS + + adds = ["is_citizen_or_legal_immigrant"] diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/ks_liheap_utility_rate_tier.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/ks_liheap_utility_rate_tier.py new file mode 100644 index 00000000000..b12422e1c01 --- /dev/null +++ b/policyengine_us/variables/gov/states/ks/dcf/liheap/ks_liheap_utility_rate_tier.py @@ -0,0 +1,28 @@ +from policyengine_us.model_api import * + + +class KSLIEAPUtilityRateTier(Enum): + A = "Tier A (lowest rates)" + B = "Tier B" + C = "Tier C" + D = "Tier D" + E = "Tier E" + F = "Tier F" + G = "Tier G" + H = "Tier H" + I = "Tier I" + J = "Tier J (highest rates)" + + +class ks_liheap_utility_rate_tier(Variable): + value_type = Enum + entity = SPMUnit + possible_values = KSLIEAPUtilityRateTier + default_value = KSLIEAPUtilityRateTier.E + definition_period = YEAR + label = "Kansas LIEAP utility rate tier" + documentation = "Utility range tier of the household's primary heating fuel provider in the Kansas LIEAP benefit matrix. Kansas groups fuel providers into tiers A (lowest rates) through J (highest rates) from a periodic rate survey. The tier is a provider attribute the model cannot derive, so it is an input defaulting to the midpoint tier E. The other-fuel matrix has no tier." + reference = ( + "https://liheapch.acf.gov/docs/2026/benefits-matricies/KS_BenefitMatrix_2026.pdf#page=1", + "https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=9", + ) diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/payment/ks_liheap_household_size_group.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/payment/ks_liheap_household_size_group.py new file mode 100644 index 00000000000..a5fceb2ba6c --- /dev/null +++ b/policyengine_us/variables/gov/states/ks/dcf/liheap/payment/ks_liheap_household_size_group.py @@ -0,0 +1,16 @@ +from policyengine_us.model_api import * + + +class ks_liheap_household_size_group(Variable): + value_type = int + entity = SPMUnit + definition_period = YEAR + label = "Kansas LIEAP household size group" + documentation = "Benefit matrix household size group: 1 for households of one to four countable members, 2 for five or more." + reference = "https://liheapch.acf.gov/docs/2026/benefits-matricies/KS_BenefitMatrix_2026.pdf#page=1" + defined_for = StateCode.KS + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ks.dcf.liheap.payment + size = spm_unit("ks_liheap_household_size", period) + return p.household_size_group.calc(size) diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/payment/ks_liheap_income_band.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/payment/ks_liheap_income_band.py new file mode 100644 index 00000000000..975a76da9fe --- /dev/null +++ b/policyengine_us/variables/gov/states/ks/dcf/liheap/payment/ks_liheap_income_band.py @@ -0,0 +1,20 @@ +from policyengine_us.model_api import * + + +class ks_liheap_income_band(Variable): + value_type = int + entity = SPMUnit + definition_period = YEAR + label = "Kansas LIEAP one-month income band" + documentation = "Benefit matrix income band (1-4) from one-month gross countable income, taken as one twelfth of annual countable income." + reference = ( + "https://liheapch.acf.gov/docs/2026/benefits-matricies/KS_BenefitMatrix_2026.pdf#page=1", + "https://content.dcf.ks.gov/ees/keesm/current/keesm13200.htm", + ) + defined_for = StateCode.KS + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ks.dcf.liheap.payment + income = spm_unit("ks_liheap_countable_income", period) + monthly_income = max_(income, 0) / MONTHS_IN_YEAR + return p.income_band.calc(monthly_income) diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/payment/ks_liheap_matrix_amount.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/payment/ks_liheap_matrix_amount.py new file mode 100644 index 00000000000..751ca3406fe --- /dev/null +++ b/policyengine_us/variables/gov/states/ks/dcf/liheap/payment/ks_liheap_matrix_amount.py @@ -0,0 +1,40 @@ +from policyengine_us.model_api import * + + +class ks_liheap_matrix_amount(Variable): + value_type = float + entity = SPMUnit + definition_period = YEAR + label = "Kansas LIEAP benefit matrix amount" + documentation = "Annual benefit from the Kansas LIEAP benefit matrix for the household's primary heating fuel, one-month income band, utility rate tier, dwelling type and household size group, before the minimum benefit." + unit = USD + reference = ( + "https://liheapch.acf.gov/docs/2026/benefits-matricies/KS_BenefitMatrix_2026.pdf#page=1", + "https://liheapch.acf.gov/docs/2025/benefits-matricies/KS_BenefitMatrix_2025.pdf#page=1", + "https://content.dcf.ks.gov/ees/keesm/current/keesm13400.htm", + ) + defined_for = StateCode.KS + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ks.dcf.liheap.payment.matrix + fuel = spm_unit("ks_liheap_fuel_category", period) + fuels = fuel.possible_values + band = spm_unit("ks_liheap_income_band", period) + tier = spm_unit("ks_liheap_utility_rate_tier", period) + dwelling = spm_unit("ks_liheap_dwelling_type", period) + size_group = spm_unit("ks_liheap_household_size_group", period) + return select( + [ + fuel == fuels.NATURAL_GAS, + fuel == fuels.ELECTRICITY, + fuel == fuels.PROPANE, + fuel == fuels.OTHER, + ], + [ + p.natural_gas[band][tier][dwelling][size_group], + p.electricity[band][tier][dwelling][size_group], + p.propane[band][tier][dwelling][size_group], + p.other[band][dwelling][size_group], + ], + default=0, + ) From 4f3c5d0c85297f5996fcb3a7389181002e2e72a4 Mon Sep 17 00:00:00 2001 From: Ziming Date: Mon, 28 Sep 2026 14:51:41 -0400 Subject: [PATCH 02/12] Validate Kansas LIEAP rules and fix income and heating eligibility --- .../gov/states/ks/dcf/liheap/README.md | 78 ++++ .../additional_person_income_limit.yaml | 14 + .../ks/dcf/liheap/eligibility/fpg_limit.yaml | 17 - .../dcf/liheap/eligibility/income_limit.yaml | 45 +++ .../liheap/eligibility/max_table_size.yaml | 13 + .../income/interest_income_min_age.yaml | 13 + .../regular_interest_dividend_exemption.yaml | 14 + .../income/self_employment_expense_rate.yaml | 13 + .../ks/dcf/liheap/income/sources/earned.yaml | 2 +- .../income/sources/self_employment.yaml | 14 + .../dcf/liheap/income/sources/unearned.yaml | 14 +- .../ks/dcf/liheap/payment/min_benefit.yaml | 2 +- policyengine_us/programs.yaml | 5 +- ..._liheap_categorically_income_eligible.yaml | 107 ------ .../eligibility/ks_liheap_eligible.yaml | 21 +- .../ks_liheap_energy_vulnerable.yaml | 76 ++++ .../dcf/liheap/eligibility/ks_liheap_fpg.yaml | 119 ------- .../ks_liheap_income_eligible.yaml | 333 +++++------------- .../income/ks_liheap_countable_income.yaml | 10 +- ...ap_countable_interest_dividend_income.yaml | 46 +++ ...heap_countable_self_employment_income.yaml | 140 ++++++++ .../gov/states/ks/dcf/liheap/integration.yaml | 51 +-- .../gov/states/ks/dcf/liheap/ks_liheap.yaml | 14 +- .../liheap/payment/ks_liheap_income_band.yaml | 7 +- .../ks/dcf/liheap/review_regressions.yaml | 65 ++++ .../gov/states/ks/dcf/liheap/vectorized.yaml | 129 +++++++ ...ks_liheap_categorically_income_eligible.py | 17 - .../liheap/eligibility/ks_liheap_eligible.py | 12 +- .../ks_liheap_energy_vulnerable.py | 17 + .../dcf/liheap/eligibility/ks_liheap_fpg.py | 24 -- .../eligibility/ks_liheap_income_eligible.py | 12 +- .../eligibility/ks_liheap_income_limit.py | 25 ++ ...heap_countable_interest_dividend_income.py | 27 ++ ...liheap_countable_self_employment_income.py | 25 ++ .../ks_liheap_countable_unearned_income.py | 5 +- .../ks_liheap_self_employment_expenses.py | 11 + .../ks_liheap_self_employment_gross_income.py | 12 + .../liheap/payment/ks_liheap_matrix_amount.py | 6 +- 38 files changed, 966 insertions(+), 589 deletions(-) create mode 100644 policyengine_us/parameters/gov/states/ks/dcf/liheap/README.md create mode 100644 policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/additional_person_income_limit.yaml delete mode 100644 policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/fpg_limit.yaml create mode 100644 policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/income_limit.yaml create mode 100644 policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/max_table_size.yaml create mode 100644 policyengine_us/parameters/gov/states/ks/dcf/liheap/income/interest_income_min_age.yaml create mode 100644 policyengine_us/parameters/gov/states/ks/dcf/liheap/income/regular_interest_dividend_exemption.yaml create mode 100644 policyengine_us/parameters/gov/states/ks/dcf/liheap/income/self_employment_expense_rate.yaml create mode 100644 policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/self_employment.yaml delete mode 100644 policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_categorically_income_eligible.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_energy_vulnerable.yaml delete mode 100644 policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_fpg.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_interest_dividend_income.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_self_employment_income.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/review_regressions.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/vectorized.yaml delete mode 100644 policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_categorically_income_eligible.py create mode 100644 policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_energy_vulnerable.py delete mode 100644 policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_fpg.py create mode 100644 policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_limit.py create mode 100644 policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_interest_dividend_income.py create mode 100644 policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_self_employment_income.py create mode 100644 policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_self_employment_expenses.py create mode 100644 policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_self_employment_gross_income.py diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/README.md b/policyengine_us/parameters/gov/states/ks/dcf/liheap/README.md new file mode 100644 index 00000000000..a7767bd9f7f --- /dev/null +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/README.md @@ -0,0 +1,78 @@ +# Kansas LIEAP regular heating assistance + +Coverage is partial for the FY2025 and FY2026 heating seasons. Cooling, crisis, +weatherization, and equipment assistance are outside this implementation. + +## Rules and authorities + +| Component | Authority | Implementation | +| --- | --- | --- | +| Kansas residence, household membership and qualified members | KEESM 13310-13330 | Kansas SPM units; qualified members determine size, all members' countable income enters the income test. | +| Heating cost responsibility | KEESM 13340 | Separately purchased heat or heat included in unsubsidized rent; a direct input handles exceptional housing/debt arrangements. | +| Income test and reuse of verified income | KEESM 13360 | Every household must meet the income limit; SNAP, TANF or SSI receipt does not waive the total-income test. | +| Self-employment | KEESM 13360 | Gross receipts less 25%, or higher allowable actual costs, when gross receipts are supplied. | +| Child earnings, interest and other income | KEESM 13360-13361 | Exclude earnings and interest of children under 18; count modeled income sources subject to the documented limitations below. | +| Income limits | KEESM 13362 | Published monthly tables, annualized; do not substitute unrounded 150% FPG calculations. | +| Benefit amount | KEESM 13410; annual benefit matrices | Fuel, monthly income band, utility rate tier, dwelling type and eligible household size group. | +| Minimum payment | FY2025/FY2026 state plans, section 2.6 | $100/$130 respectively. | + +Historical manual editions: + +- [October 2024 eligibility](https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13300.htm) +- [October 2024 income rules and limits](https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13360.htm) +- [January 2026 eligibility](https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13300.htm) +- [January 2026 income rules and limits](https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13360.htm) +- [Benefit rules](https://content.dcf.ks.gov/ees/keesm/current/keesm13400.htm) + +Benefit sources: + +- [FY2025 state plan, section 2](https://liheapch.acf.gov/docs/2025/state-plans/KS_Plan_2025.pdf#page=8) +- [FY2026 state plan, section 2](https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=8) +- [FY2025 matrix, 100% values](https://liheapch.acf.gov/docs/2025/benefits-matricies/KS_BenefitMatrix_2025.pdf) +- [FY2026 matrix, adjusted 80% values](https://liheapch.acf.gov/docs/2026/benefits-matricies/KS_BenefitMatrix_2026.pdf) + +All 1,984 encoded cells were compared with the official PDFs on September 28, +2026. The matrix maxima are $2,232 and $1,682 respectively. The plans' maximum +benefits do not reduce any cell, so an extra maximum cap cannot bind. + +## Source reconciliation + +The state plan's categorical-eligibility wording describes reuse of verified +income. KEESM 13360 explicitly still tests the combined household income. The +plan's unchecked combined interest/dividends/royalties box is not treated as a +blanket exclusion: KEESM 13361 specifies the exemptions. The October 2024 +LIEAP-specific text exempts interest and dividends up to $50 monthly, counting +the full amount above that threshold. The January 2026 text instead exempts +small irregular, unpredictable payments, not regular interest generally. +The model follows each season's LIEAP-specific manual; the FY2026 irregular +payment exception requires a direct countable-income input. + +There is no modeled household contribution requirement. DCF eliminated the +former self-payment rule in [revision 114, effective February 2024](https://content.dcf.ks.gov/EES/KEESM/SOC_Rev_114_02_24.html). + +## Periods and modeling limitations + +- A YEAR calculation for 2025 or 2026 selects that year's heating season. + October parameter dates index the federal fiscal-year schedules. They do not + represent application opening dates. Income divided by twelve approximates + the application month; callers can supply annualized application-month + countable income directly. Weekly/biweekly conversions and irregular receipt + timing are not inferred from annual data. +- The SPM unit approximates the energy household. Shared addresses, paid + attendants, college dormitories, duplicate state/tribal awards, and application + administration are not independently resolved. +- Tier E and house/modular/mobile are modeling defaults, not legal findings + about a household. Supply the actual vendor tier and dwelling type. Solar + heat follows the shared grid-tied electric-heat convention. +- Supply `ks_liheap_energy_vulnerable` for shared unmetered heat, qualifying + prior-address heating debt, excess subsidized-housing charges, or limited FHA + assistance. A fuel type alone does not establish purchased heating costs. +- Self-employment receipts default to -1 (unknown). Without gross receipts, + positive reported net business/farm income is a fallback; it receives no + second expense deduction. Actual allowable costs and the standard deduction + require the gross-receipts input. +- Source-specific exemptions and missing receipt types, including irregular + interest, burial-fund interest, some cash gifts, contract payments, royalties, + settlements and foster/adoption payments, are not fully distinguished by + available inputs. Use directly supplied countable income for such cases. + Coverage remains partial rather than implying those amounts are all exempt. diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/additional_person_income_limit.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/additional_person_income_limit.yaml new file mode 100644 index 00000000000..1243a627e0a --- /dev/null +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/additional_person_income_limit.yaml @@ -0,0 +1,14 @@ +description: Kansas increases the monthly Low Income Energy Assistance Program income limit by this amount for each person beyond the maximum tabulated household size. +values: + 2024-10-01: 672.5 + 2025-10-01: 688 + +metadata: + unit: currency-USD + period: month + label: Kansas LIEAP additional person monthly income limit + reference: + - title: KEESM 13360-13362, October 2024 edition + href: https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13360.htm + - title: KEESM 13360-13362, January 2026 edition + href: https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13360.htm diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/fpg_limit.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/fpg_limit.yaml deleted file mode 100644 index d9a32fde2da..00000000000 --- a/policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/fpg_limit.yaml +++ /dev/null @@ -1,17 +0,0 @@ -description: Kansas limits the Low Income Energy Assistance Program to households whose combined gross income does not exceed this multiple of the federal poverty guidelines. -values: - 2024-10-01: 1.5 - -metadata: - unit: /1 - period: year - label: Kansas LIEAP income limit as a multiple of the federal poverty guidelines - reference: - - title: Kansas LIHEAP FY2026 State Plan, Section 2.1 (heating income eligibility threshold, 150% of HHS Poverty Guidelines) - href: https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=8 - - title: Kansas LIHEAP FY2025 State Plan, Section 2.1 (heating income eligibility threshold, 150% of HHS Poverty Guidelines) - href: https://liheapch.acf.gov/docs/2025/state-plans/KS_Plan_2025.pdf#page=8 - - title: KEESM 13100 Program Summary (combined income must not exceed 150% of the federal poverty level) - href: https://content.dcf.ks.gov/ees/keesm/current/keesm13000.htm - - title: Kansas DCF Energy Assistance (LIEAP) income eligibility table - href: https://www.dcf.ks.gov/services/ees/pages/energyassistance.aspx diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/income_limit.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/income_limit.yaml new file mode 100644 index 00000000000..cdfef9972f3 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/income_limit.yaml @@ -0,0 +1,45 @@ +description: Kansas limits monthly countable income to these amounts under the Low Income Energy Assistance Program, by household size. + +1: + 2024-10-01: 1882.5 + 2025-10-01: 1956 + +2: + 2024-10-01: 2555 + 2025-10-01: 2644 + +3: + 2024-10-01: 3227.5 + 2025-10-01: 3331 + +4: + 2024-10-01: 3900 + 2025-10-01: 4019 + +5: + 2024-10-01: 4572.5 + 2025-10-01: 4706 + +6: + 2024-10-01: 5245 + 2025-10-01: 5394 + +7: + 2024-10-01: 5917.5 + 2025-10-01: 6081 + +8: + 2024-10-01: 6590 + 2025-10-01: 6769 + +metadata: + unit: currency-USD + period: month + label: Kansas LIEAP monthly income limit + breakdown: + - range(1, 9) + reference: + - title: KEESM 13362 Income Guidelines, October 2024 edition + href: https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13360.htm + - title: KEESM 13362 Income Guidelines, January 2026 edition + href: https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13360.htm diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/max_table_size.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/max_table_size.yaml new file mode 100644 index 00000000000..3b15c75243a --- /dev/null +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/max_table_size.yaml @@ -0,0 +1,13 @@ +description: Kansas publishes Low Income Energy Assistance Program income limits through this household size, with an increment for each additional person. +values: + 2024-10-01: 8 + +metadata: + unit: person + period: year + label: Kansas LIEAP maximum tabulated household size + reference: + - title: KEESM 13360-13362, October 2024 edition + href: https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13360.htm + - title: KEESM 13360-13362, January 2026 edition + href: https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13360.htm diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/interest_income_min_age.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/interest_income_min_age.yaml new file mode 100644 index 00000000000..add0ea6c4e2 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/interest_income_min_age.yaml @@ -0,0 +1,13 @@ +description: Kansas counts interest income of household members at or above this age under the Low Income Energy Assistance Program. +values: + 2024-10-01: 18 + +metadata: + unit: year + period: year + label: Kansas LIEAP minimum age for countable interest + reference: + - title: KEESM 13360-13362, October 2024 edition + href: https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13360.htm + - title: KEESM 13360-13362, January 2026 edition + href: https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13360.htm diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/regular_interest_dividend_exemption.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/regular_interest_dividend_exemption.yaml new file mode 100644 index 00000000000..40085af1718 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/regular_interest_dividend_exemption.yaml @@ -0,0 +1,14 @@ +description: Kansas excludes recurring interest and dividends not exceeding this monthly amount under the Low Income Energy Assistance Program; above it the full amount counts. +values: + 2024-10-01: 50 + 2025-10-01: 0 + +metadata: + unit: currency-USD + period: month + label: Kansas LIEAP recurring interest and dividend exemption + reference: + - title: KEESM 13360-13362, October 2024 edition + href: https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13360.htm + - title: KEESM 13360-13362, January 2026 edition + href: https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13360.htm diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/self_employment_expense_rate.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/self_employment_expense_rate.yaml new file mode 100644 index 00000000000..9baccd133c6 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/self_employment_expense_rate.yaml @@ -0,0 +1,13 @@ +description: Kansas deducts this share of gross self-employment receipts for expenses under the Low Income Energy Assistance Program unless the household claims higher allowable actual costs. +values: + 2024-10-01: 0.25 + +metadata: + unit: /1 + period: year + label: Kansas LIEAP standard self-employment expense rate + reference: + - title: KEESM 13360-13362, October 2024 edition + href: https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13360.htm + - title: KEESM 13360-13362, January 2026 edition + href: https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13360.htm diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/earned.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/earned.yaml index d2684d81036..60d982d5c45 100644 --- a/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/earned.yaml +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/earned.yaml @@ -2,7 +2,7 @@ description: Kansas counts these earned income sources in gross household income values: 2024-10-01: - employment_income - - self_employment_income + - ks_liheap_countable_self_employment_income metadata: unit: list diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/self_employment.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/self_employment.yaml new file mode 100644 index 00000000000..4e04592ffd7 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/self_employment.yaml @@ -0,0 +1,14 @@ +description: Kansas uses these net self-employment income sources as a fallback under the Low Income Energy Assistance Program when gross receipts and allowable business costs are unavailable. +values: + 2024-10-01: + - self_employment_income + - sstb_self_employment_income + - farm_operations_income + +metadata: + unit: list + period: year + label: Kansas LIEAP net self-employment income fallback sources + reference: + - title: KEESM 13360 Income Eligibility (gross receipts less business costs) + href: https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13360.htm diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/unearned.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/unearned.yaml index 7253348ad11..775c6f81305 100644 --- a/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/unearned.yaml +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/unearned.yaml @@ -15,11 +15,11 @@ values: # Plan counts "insurance payments made directly to the insured". - workers_compensation - veterans_benefits - # Not counted (plan boxes unchecked): loans, savings balances, one-time - # lump sums, WIA and work-study income, interest, dividends and - # royalties, insurance payments for repayment of a bill, retirement - # account balances, tax refunds, VISTA stipends, foster care payments, - # AmeriCorps payments and reimbursements. + - ks_liheap_countable_interest_dividend_income + # KEESM 13360-13361 explicitly count interest except for specific + # exemptions; the plan's unchecked combined interest/dividend/royalty + # box is not a blanket exclusion. Other irregular receipts and source- + # specific exclusions require a direct countable-income input. metadata: unit: list @@ -28,7 +28,7 @@ metadata: reference: - title: Kansas LIHEAP FY2026 State Plan, Section 1.9 (countable income sources) href: https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=6 - - title: Kansas LIHEAP FY2026 State Plan, Section 1.9 (income sources not counted) - href: https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=7 + - title: KEESM 13360-13361 (countable income and specific exemptions) + href: https://content.dcf.ks.gov/ees/keesm/current/keesm13360.htm - title: KEESM 13320 Household Definition (income of all household members living together is used) href: https://content.dcf.ks.gov/ees/keesm/current/keesm13300.htm diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/min_benefit.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/min_benefit.yaml index 29184932be4..fd94c628a6f 100644 --- a/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/min_benefit.yaml +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/min_benefit.yaml @@ -1,6 +1,6 @@ description: Kansas pays at least this annual benefit to eligible households under the Low Income Energy Assistance Program. # The state plans also report a maximum benefit ($2,232 for FY2025, $4,301 for -# FY2026) that exceeds every matrix cell in its year and is therefore not applied. +# FY2026) that is at least every matrix cell in its year, so an additional cap cannot bind. values: 2024-10-01: 100 2025-10-01: 130 diff --git a/policyengine_us/programs.yaml b/policyengine_us/programs.yaml index f960aea8470..b3c47d276e7 100644 --- a/policyengine_us/programs.yaml +++ b/policyengine_us/programs.yaml @@ -824,10 +824,13 @@ programs: full_name: Illinois Low Income Home Energy Assistance Program variable: il_liheap - state: KS - status: complete + status: partial name: Kansas LIEAP full_name: Kansas Low Income Energy Assistance Program variable: ks_liheap + parameter_prefix: gov.states.ks.dcf.liheap + verified_years: "2025-2026" + notes: Models regular heating assistance using FY2025 and FY2026 benefit matrices and published income limits. Annual income approximates the application month; the SPM unit approximates the energy household. Utility tier defaults to E and dwelling type to house/mobile. Gross self-employment receipts and allowable costs enable the expense deduction; otherwise net earnings are a fallback. Special energy-vulnerability cases require a direct input. Some irregular receipts and source-specific income exemptions are not modeled. Cooling, crisis, weatherization, and equipment assistance are outside scope. - state: TX status: partial name: Texas CEAP diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_categorically_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_categorically_income_eligible.yaml deleted file mode 100644 index 2a1456aabff..00000000000 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_categorically_income_eligible.yaml +++ /dev/null @@ -1,107 +0,0 @@ -# Kansas LIEAP categorical income eligibility (KS LIHEAP State Plan FY2026 -# section 1.4, #page=5): a household with at least one member receiving TANF, -# SSI or SNAP is considered income eligible for heating assistance. Modeled -# on receipt: any member ssi > 0, spm_unit snap > 0, or spm_unit ks_tanf > 0. -# Means-tested veterans programs are not a categorical route (plan 1.4: No). - -- name: Case 1, a member receiving SSI makes the household categorically eligible. - period: 2026 - input: - people: - person1: - age: 45 - employment_income: 40_000 - person2: - age: 68 - ssi: 6_000 - spm_units: - spm_unit: - members: [person1, person2] - households: - household: - members: [person1, person2] - state_code: KS - output: - ks_liheap_categorically_income_eligible: true - -- name: Case 2, SNAP receipt makes the household categorically eligible. - period: 2026 - input: - people: - person1: - age: 30 - employment_income: 20_000 - person2: - age: 3 - spm_units: - spm_unit: - members: [person1, person2] - ks_tanf: 0 - snap: 2_400 - households: - household: - members: [person1, person2] - state_code: KS - output: - ks_liheap_categorically_income_eligible: true - -- name: Case 3, TANF receipt makes the household categorically eligible. - period: 2026 - input: - people: - person1: - age: 28 - person2: - age: 5 - spm_units: - spm_unit: - members: [person1, person2] - ks_tanf: 3_600 - households: - household: - members: [person1, person2] - state_code: KS - output: - ks_liheap_categorically_income_eligible: true - -- name: Case 4, no TANF, SSI or SNAP receipt is not categorically eligible. - period: 2026 - input: - people: - person1: - age: 45 - employment_income: 40_000 - person2: - age: 68 - social_security: 15_000 - spm_units: - spm_unit: - members: [person1, person2] - snap: 0 - ks_tanf: 0 - households: - household: - members: [person1, person2] - state_code: KS - output: - ks_liheap_categorically_income_eligible: false - -- name: Case 5, veterans benefits alone are not a categorical route. - period: 2026 - input: - people: - person1: - age: 60 - veterans_benefits: 30_000 - spm_units: - spm_unit: - members: [person1] - snap: 0 - ks_tanf: 0 - households: - household: - members: [person1] - state_code: KS - output: - # Plan 1.4: means-tested veterans programs -> No for heating. - ks_liheap_categorically_income_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_eligible.yaml index 81e1fe4def0..ab4ee9e7488 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_eligible.yaml @@ -17,6 +17,7 @@ spm_unit: members: [person1] heating_type: NATURAL_GAS + gas_expense: 1_200 households: household: members: [person1] @@ -35,6 +36,7 @@ spm_unit: members: [person1] heating_type: NATURAL_GAS + gas_expense: 1_200 households: household: members: [person1] @@ -75,6 +77,7 @@ spm_unit: members: [person1, person2] heating_type: NATURAL_GAS + gas_expense: 1_200 households: household: members: [person1, person2] @@ -98,12 +101,13 @@ members: [person1, person2] ks_tanf: 0 heating_type: NATURAL_GAS + gas_expense: 1_200 households: household: members: [person1, person2] state_code: KS output: - # KEESM 13330: at least one citizen (the child); size 1 limit 23,475 > + # KEESM 13330: at least one citizen (the child); size 1 limit 23,472 > # 12,000 (the parent's income counts). ks_liheap_eligible: true @@ -118,6 +122,7 @@ spm_unit: members: [person1] heating_type: NATURAL_GAS + gas_expense: 1_200 receives_housing_assistance: true heat_expense_included_in_rent: true households: @@ -138,6 +143,7 @@ spm_unit: members: [person1] heating_type: NATURAL_GAS + gas_expense: 1_200 receives_housing_assistance: true heat_expense_included_in_rent: false households: @@ -159,6 +165,7 @@ spm_unit: members: [person1] heating_type: NATURAL_GAS + gas_expense: 1_200 receives_housing_assistance: false heat_expense_included_in_rent: true households: @@ -180,6 +187,7 @@ spm_unit: members: [person1] heating_type: NATURAL_GAS + gas_expense: 1_200 snap: 0 ks_tanf: 0 households: @@ -187,7 +195,7 @@ members: [person1] state_code: KS output: - # 30,000 > 23,475 and no categorical route. + # 30,000 > 23,472 and no categorical route. ks_liheap_eligible: false - name: Case 10, no asset test so large savings do not disqualify. @@ -202,6 +210,7 @@ members: [person1] spm_unit_cash_assets: 50_000 heating_type: ELECTRICITY + pre_subsidy_electricity_expense: 1_200 households: household: members: [person1] @@ -210,7 +219,7 @@ # Plan 2.3: "Do you require an Assets test? No". ks_liheap_eligible: true -- name: Case 11, household over the limit but receiving TANF is eligible. +- name: Case 11, TANF receipt does not waive the household income limit. period: 2025 input: people: @@ -223,6 +232,7 @@ spm_unit: members: [person1, person2] heating_type: PROPANE + bottled_gas_expense: 1_200 ks_tanf: 1_200 households: household: @@ -230,6 +240,5 @@ state_code: KS output: # 2025 season size 2 limit: 1.5 x (15,060 + 5,380) = 30,660 < 33,200 - # gross, but TANF receipt makes the household categorically income - # eligible (plan 1.4). - ks_liheap_eligible: true + # gross; verified TANF income still enters the household test (KEESM 13360). + ks_liheap_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_energy_vulnerable.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_energy_vulnerable.yaml new file mode 100644 index 00000000000..ac9942f790f --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_energy_vulnerable.yaml @@ -0,0 +1,76 @@ +# KEESM 13340, including facts that cannot be inferred from fuel bills. +- name: Purchased wood qualifies + period: 2026 + input: + state_code: KS + age: 40 + ks_liheap_countable_income: 10000 + heating_type: WOOD + wood_expense: 600 + output: + ks_liheap_energy_vulnerable: true + ks_liheap_eligible: true +- name: An unknown heating fuel with no cost information does not establish vulnerability + period: 2026 + input: + state_code: KS + age: 40 + ks_liheap_countable_income: 10000 + output: + ks_liheap_energy_vulnerable: false + ks_liheap_eligible: false +- name: Unsubsidized heat included in rent qualifies + period: 2026 + input: + state_code: KS + age: 40 + ks_liheap_countable_income: 10000 + heat_expense_included_in_rent: true + output: + ks_liheap_energy_vulnerable: true + ks_liheap_eligible: true +- name: Subsidized heat included in rent does not qualify by default + period: 2026 + input: + state_code: KS + age: 40 + ks_liheap_countable_income: 10000 + heat_expense_included_in_rent: true + receives_housing_assistance: true + output: + ks_liheap_energy_vulnerable: false + ks_liheap_eligible: false +- name: Subsidized excess heating charges can establish vulnerability + period: 2026 + input: + state_code: KS + age: 40 + ks_liheap_countable_income: 10000 + heat_expense_included_in_rent: true + receives_housing_assistance: true + ks_liheap_energy_vulnerable: true + output: + ks_liheap_energy_vulnerable: true + ks_liheap_eligible: true +- name: Shared unmetered heat can be explicitly excluded + period: 2026 + input: + state_code: KS + age: 40 + ks_liheap_countable_income: 10000 + heat_expense_included_in_rent: true + ks_liheap_energy_vulnerable: false + output: + ks_liheap_energy_vulnerable: false + ks_liheap_eligible: false +- name: A homeless household with qualifying prior-address heating debt can qualify + period: 2026 + input: + state_code: KS + age: 40 + ks_liheap_countable_income: 10000 + heating_type: NONE + ks_liheap_energy_vulnerable: true + output: + ks_liheap_energy_vulnerable: true + ks_liheap_eligible: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_fpg.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_fpg.yaml deleted file mode 100644 index e05651fb3af..00000000000 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_fpg.yaml +++ /dev/null @@ -1,119 +0,0 @@ -# Kansas LIEAP federal poverty guideline for the income limit. The season's -# published table is 150% of the prior calendar year's HHS guidelines (2026 -# flyer: $1,956/month for one person = 1.5 x 15,650 / 12), so program year Y -# uses the year Y-1 guideline. Household size counts only citizens and -# qualified aliens (KEESM 13330). Contiguous-US guidelines (gov/hhs/fpg.yaml): -# 2025 = 15,650 + 5,500 per additional person; 2024 = 15,060 + 5,380. - -- name: Case 1, single citizen in the 2026 season uses the 2025 one-person guideline. - period: 2026 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 40 - spm_units: - spm_unit: - members: [person1] - households: - household: - members: [person1] - state_code: KS - output: - # 2025 guideline, size 1 = 15,650 - ks_liheap_fpg: 15_650 - -- name: Case 2, four citizens in the 2026 season use the 2025 four-person guideline. - period: 2026 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 40 - person2: - age: 38 - person3: - age: 10 - person4: - age: 7 - spm_units: - spm_unit: - members: [person1, person2, person3, person4] - households: - household: - members: [person1, person2, person3, person4] - state_code: KS - output: - # 15,650 + 3 x 5,500 = 32,150 - ks_liheap_fpg: 32_150 - -- name: Case 3, five members with one undocumented member use the four-person guideline. - period: 2026 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 35 - immigration_status: CITIZEN - person2: - age: 33 - immigration_status: UNDOCUMENTED - person3: - age: 10 - person4: - age: 7 - person5: - age: 3 - spm_units: - spm_unit: - members: [person1, person2, person3, person4, person5] - households: - household: - members: [person1, person2, person3, person4, person5] - state_code: KS - output: - # KEESM 13330: the undocumented member is not counted in household size, - # so size 4: 15,650 + 3 x 5,500 = 32,150 (size 5 would be 37,650). - ks_liheap_fpg: 32_150 - -- name: Case 4, single citizen in the 2025 season uses the 2024 one-person guideline. - period: 2025 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 40 - spm_units: - spm_unit: - members: [person1] - households: - household: - members: [person1] - state_code: KS - output: - # 2024 guideline, size 1 = 15,060 (the 2025 guideline would be 15,650) - ks_liheap_fpg: 15_060 - -- name: Case 5, four citizens in the 2025 season use the 2024 four-person guideline. - period: 2025 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 40 - person2: - age: 38 - person3: - age: 10 - person4: - age: 7 - spm_units: - spm_unit: - members: [person1, person2, person3, person4] - households: - household: - members: [person1, person2, person3, person4] - state_code: KS - output: - # 15,060 + 3 x 5,380 = 31,200 - ks_liheap_fpg: 31_200 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_eligible.yaml index bf0eddc69b7..7e147797ccb 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_eligible.yaml @@ -1,280 +1,137 @@ -# Kansas LIEAP income eligibility (KEESM 13100; KS LIHEAP State Plan FY2026 -# 2.1, #page=8): combined gross income of all persons at the address must not -# exceed 150% of the HHS poverty guideline for the household size. The season -# runs January-March, so the program-year Y table equals 150% of the year Y-1 -# guidelines (the 2026 flyer's $1,956/month for one person = 1.5 x 15,650 / 12). -# Contiguous-US guidelines: 2025 = 15,650 + 5,500 per additional person; -# 2024 = 15,060 + 5,380. Households with a member receiving TANF, SSI or SNAP -# are income eligible regardless (plan 1.4, #page=5). - -- name: Case 1, one person in 2026 exactly at 150% of the 2025 guideline is eligible. - period: 2026 +# KEESM 13360-13362, October 2024 and January 2026 editions. +# Values annualize the published monthly limits; FY2026 includes rounding. +- name: 2025 household size 1, income 0 dollar above the published limit. + period: 2025 input: - people: - person1: - age: 35 - employment_income: 23_475 - spm_units: - spm_unit: - members: [person1] - households: - household: - members: [person1] - state_code: KS + state_code: KS + ks_liheap_household_size: 1 + ks_liheap_countable_income: 22590 output: - # 1.5 x 15,650 = 23,475; 23,475 <= 23,475 + ks_liheap_income_limit: 22590 ks_liheap_income_eligible: true - -- name: Case 2, one person in 2026 one dollar over the limit is ineligible. - period: 2026 +- name: 2025 household size 1, income 1 dollar above the published limit. + period: 2025 input: - people: - person1: - age: 35 - employment_income: 23_476 - spm_units: - spm_unit: - members: [person1] - snap: 0 - ks_tanf: 0 - households: - household: - members: [person1] - state_code: KS + state_code: KS + ks_liheap_household_size: 1 + ks_liheap_countable_income: 22591 output: - # 23,476 > 23,475 + ks_liheap_income_limit: 22590 ks_liheap_income_eligible: false - -- name: Case 3, one person in 2026 under the current-year limit but over the prior-year limit is ineligible. - period: 2026 +- name: 2025 household size 4, income 0 dollar above the published limit. + period: 2025 input: - people: - person1: - age: 35 - employment_income: 23_600 - spm_units: - spm_unit: - members: [person1] - snap: 0 - ks_tanf: 0 - households: - household: - members: [person1] - state_code: KS + state_code: KS + ks_liheap_household_size: 4 + ks_liheap_countable_income: 46800 output: - # Prior-year (2025) guideline: 1.5 x 15,650 = 23,475 < 23,600 -> ineligible. - # The 2026 guideline would give 1.5 x 15,960 = 23,940 and wrongly pass. + ks_liheap_income_limit: 46800 + ks_liheap_income_eligible: true +- name: 2025 household size 4, income 1 dollar above the published limit. + period: 2025 + input: + state_code: KS + ks_liheap_household_size: 4 + ks_liheap_countable_income: 46801 + output: + ks_liheap_income_limit: 46800 ks_liheap_income_eligible: false - -- name: Case 4, four-person household in 2026 exactly at the limit is eligible. +- name: 2026 household size 1, income 0 dollar above the published limit. period: 2026 input: - people: - person1: - age: 40 - employment_income: 30_000 - person2: - age: 38 - employment_income: 18_225 - person3: - age: 10 - person4: - age: 7 - spm_units: - spm_unit: - members: [person1, person2, person3, person4] - ks_tanf: 0 - households: - household: - members: [person1, person2, person3, person4] - state_code: KS + state_code: KS + ks_liheap_household_size: 1 + ks_liheap_countable_income: 23472 output: - # 2025 guideline size 4: 15,650 + 3 x 5,500 = 32,150; x 1.5 = 48,225. - # 30,000 + 18,225 = 48,225 <= 48,225 + ks_liheap_income_limit: 23472 ks_liheap_income_eligible: true - -- name: Case 5, four-person household in 2026 one dollar over the limit is ineligible. +- name: 2026 household size 1, income 1 dollar above the published limit. period: 2026 input: - people: - person1: - age: 40 - employment_income: 30_000 - person2: - age: 38 - employment_income: 18_226 - person3: - age: 10 - person4: - age: 7 - spm_units: - spm_unit: - members: [person1, person2, person3, person4] - snap: 0 - ks_tanf: 0 - households: - household: - members: [person1, person2, person3, person4] - state_code: KS + state_code: KS + ks_liheap_household_size: 1 + ks_liheap_countable_income: 23473 output: - # 48,226 > 48,225 + ks_liheap_income_limit: 23472 ks_liheap_income_eligible: false - -- name: Case 6, one person in 2025 exactly at 150% of the 2024 guideline is eligible. - period: 2025 +- name: 2026 household size 4, income 0 dollar above the published limit. + period: 2026 input: - people: - person1: - age: 35 - employment_income: 22_590 - spm_units: - spm_unit: - members: [person1] - households: - household: - members: [person1] - state_code: KS + state_code: KS + ks_liheap_household_size: 4 + ks_liheap_countable_income: 48228 output: - # 1.5 x 15,060 = 22,590 + ks_liheap_income_limit: 48228 ks_liheap_income_eligible: true - -- name: Case 7, one person in 2025 one dollar over the limit is ineligible. - period: 2025 +- name: 2026 household size 4, income 1 dollar above the published limit. + period: 2026 input: - people: - person1: - age: 35 - employment_income: 22_591 - spm_units: - spm_unit: - members: [person1] - snap: 0 - ks_tanf: 0 - households: - household: - members: [person1] - state_code: KS + state_code: KS + ks_liheap_household_size: 4 + ks_liheap_countable_income: 48229 output: - # 22,591 > 22,590 (the 2025 guideline would give 23,475 and wrongly pass) + ks_liheap_income_limit: 48228 ks_liheap_income_eligible: false - -- name: Case 8, excluded interest income does not count toward the limit. +- name: 2026 household size 9, income 0 dollar above the published limit. period: 2026 input: - people: - person1: - age: 60 - employment_income: 23_000 - interest_income: 5_000 - spm_units: - spm_unit: - members: [person1] - households: - household: - members: [person1] - state_code: KS + state_code: KS + ks_liheap_household_size: 9 + ks_liheap_countable_income: 89484 output: - # Countable 23,000 <= 23,475 (28,000 gross with interest would fail). + ks_liheap_income_limit: 89484 ks_liheap_income_eligible: true - -- name: Case 9, household over the limit with an SSI recipient is categorically eligible. +- name: 2026 household size 9, income 1 dollar above the published limit. + period: 2026 + input: + state_code: KS + ks_liheap_household_size: 9 + ks_liheap_countable_income: 89485 + output: + ks_liheap_income_limit: 89484 + ks_liheap_income_eligible: false +- name: 2026 household size 10, income 0 dollar above the published limit. period: 2026 input: - people: - person1: - age: 45 - employment_income: 40_000 - person2: - age: 70 - social_security: 8_000 - ssi: 1_200 - spm_units: - spm_unit: - members: [person1, person2] - households: - household: - members: [person1, person2] - state_code: KS + state_code: KS + ks_liheap_household_size: 10 + ks_liheap_countable_income: 97740 output: - # Size 2 limit: 1.5 x (15,650 + 5,500) = 31,725 < 49,200 gross, but - # person2 receives SSI -> income eligible (plan 1.4). + ks_liheap_income_limit: 97740 ks_liheap_income_eligible: true - -- name: Case 10, the same household without SSI receipt is ineligible. +- name: 2026 household size 10, income 1 dollar above the published limit. period: 2026 input: - people: - person1: - age: 45 - employment_income: 40_000 - person2: - age: 70 - social_security: 8_000 - ssi: 0 - spm_units: - spm_unit: - members: [person1, person2] - snap: 0 - ks_tanf: 0 - households: - household: - members: [person1, person2] - state_code: KS + state_code: KS + ks_liheap_household_size: 10 + ks_liheap_countable_income: 97741 output: - # 48,000 > 31,725 and no categorical route. + ks_liheap_income_limit: 97740 ks_liheap_income_eligible: false - -- name: Case 11, household over the limit receiving SNAP is categorically eligible. +- name: snap receipt does not waive the household income limit. period: 2026 input: - people: - person1: - age: 45 - employment_income: 40_000 - person2: - age: 12 - spm_units: - spm_unit: - members: [person1, person2] - ks_tanf: 0 - snap: 1_200 - households: - household: - members: [person1, person2] - state_code: KS + state_code: KS + ks_liheap_household_size: 2 + ks_liheap_countable_income: 40000 + snap: 1200 output: - # 40,000 > 31,725, but the household receives SNAP -> income eligible. - ks_liheap_income_eligible: true - -- name: Case 12, five members with one undocumented member use the four-person limit. + ks_liheap_income_eligible: false +- name: ssi receipt does not waive the household income limit. + period: 2026 + input: + state_code: KS + ks_liheap_household_size: 2 + ks_liheap_countable_income: 40000 + ssi: 1200 + output: + ks_liheap_income_eligible: false +- name: ks_tanf receipt does not waive the household income limit. period: 2026 input: - people: - person1: - age: 35 - immigration_status: CITIZEN - employment_income: 30_000 - person2: - age: 33 - immigration_status: UNDOCUMENTED - employment_income: 20_000 - person3: - age: 10 - person4: - age: 7 - person5: - age: 3 - spm_units: - spm_unit: - members: [person1, person2, person3, person4, person5] - snap: 0 - ks_tanf: 0 - households: - household: - members: [person1, person2, person3, person4, person5] - state_code: KS + state_code: KS + ks_liheap_household_size: 2 + ks_liheap_countable_income: 40000 + ks_tanf: 1200 output: - # KEESM 13330: the undocumented member is not counted in household size - # but their income is. Size 4 limit = 48,225 < 50,000 gross -> ineligible - # (the five-person limit of 56,475 would wrongly pass). ks_liheap_income_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_income.yaml index dbfcc693cff..fb40dfccb45 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_income.yaml @@ -1,12 +1,12 @@ # Kansas LIEAP countable gross income (KS LIHEAP State Plan FY2026 sections # 1.8-1.9, #page=5-6; KEESM 13320). Counted: wages, self-employment, # unemployment insurance, SSA benefits, SSI, retirement/pension, TANF, child -# support, alimony, rental income, VA benefits. Not counted: interest, -# dividends, royalties, earned income of a child under 18. Income of all +# support, alimony, rental income, VA benefits and recurring adult interest. +# Earned income of children under 18 is excluded. Income of other # household members counts, including non-qualified noncitizens (KEESM 13330). # All amounts are annual (YEAR variable). -- name: Case 1, interest and dividends are not counted. +- name: Case 1, recurring adult interest and dividends are counted. period: 2026 absolute_error_margin: 0.01 input: @@ -24,8 +24,8 @@ members: [person1] state_code: KS output: - # 20,000 wages; 3,000 interest + 2,000 dividends excluded (plan 1.9). - ks_liheap_countable_income: 20_000 + # 20,000 wages + 3,000 interest + 2,000 dividends (KEESM 13360). + ks_liheap_countable_income: 25_000 - name: Case 2, earned income of a child under 18 is not counted. period: 2026 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_interest_dividend_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_interest_dividend_income.yaml new file mode 100644 index 00000000000..0bef061387b --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_interest_dividend_income.yaml @@ -0,0 +1,46 @@ +# KEESM 13361: child interest exclusion and year-specific interest exemptions. +- name: FY2025 exactly at monthly exemption + period: 2025 + input: + state_code: KS + age: 40 + interest_income: 360 + dividend_income: 240 + output: + ks_liheap_countable_interest_dividend_income: 0 +- name: FY2025 above exemption counts the full amount + period: 2025 + input: + state_code: KS + age: 40 + interest_income: 361 + dividend_income: 240 + output: + ks_liheap_countable_interest_dividend_income: 601 +- name: FY2026 regular small interest has no blanket exemption + period: 2026 + input: + state_code: KS + age: 40 + interest_income: 120 + dividend_income: 0 + output: + ks_liheap_countable_interest_dividend_income: 120 +- name: FY2026 interest of a 17-year-old is exempt but dividends count + period: 2026 + input: + state_code: KS + age: 17 + interest_income: 1000 + dividend_income: 300 + output: + ks_liheap_countable_interest_dividend_income: 300 +- name: FY2026 interest counts at age 18 + period: 2026 + input: + state_code: KS + age: 18 + interest_income: 1000 + dividend_income: 300 + output: + ks_liheap_countable_interest_dividend_income: 1300 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_self_employment_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_self_employment_income.yaml new file mode 100644 index 00000000000..9b26ff42d7c --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_self_employment_income.yaml @@ -0,0 +1,140 @@ +# KEESM 13360, October 2024 and January 2026: gross receipts less 25% +# or elected actual costs. Tax-net fallback is a documented approximation. +- name: 2025 self-employment, standard deduction. + period: 2025 + input: + state_code: KS + age: 40 + ks_liheap_self_employment_gross_income: 24000 + ks_liheap_self_employment_expenses: 0 + self_employment_income: 5000 + output: + ks_liheap_countable_self_employment_income: 18000 + ks_liheap_countable_earned_income: 18000 +- name: 2025 self-employment, higher actual costs. + period: 2025 + input: + state_code: KS + age: 40 + ks_liheap_self_employment_gross_income: 24000 + ks_liheap_self_employment_expenses: 10000 + self_employment_income: 5000 + output: + ks_liheap_countable_self_employment_income: 14000 + ks_liheap_countable_earned_income: 14000 +- name: 2025 self-employment, lower actual costs retain standard deduction. + period: 2025 + input: + state_code: KS + age: 40 + ks_liheap_self_employment_gross_income: 24000 + ks_liheap_self_employment_expenses: 1000 + self_employment_income: 5000 + output: + ks_liheap_countable_self_employment_income: 18000 + ks_liheap_countable_earned_income: 18000 +- name: 2025 self-employment, expenses exceed receipts. + period: 2025 + input: + state_code: KS + age: 40 + ks_liheap_self_employment_gross_income: 12000 + ks_liheap_self_employment_expenses: 15000 + self_employment_income: 5000 + output: + ks_liheap_countable_self_employment_income: 0 + ks_liheap_countable_earned_income: 0 +- name: 2025 self-employment, explicit zero gross receipts. + period: 2025 + input: + state_code: KS + age: 40 + ks_liheap_self_employment_gross_income: 0 + ks_liheap_self_employment_expenses: 0 + self_employment_income: 5000 + output: + ks_liheap_countable_self_employment_income: 0 + ks_liheap_countable_earned_income: 0 +- name: 2026 self-employment, standard deduction. + period: 2026 + input: + state_code: KS + age: 40 + ks_liheap_self_employment_gross_income: 24000 + ks_liheap_self_employment_expenses: 0 + self_employment_income: 5000 + output: + ks_liheap_countable_self_employment_income: 18000 + ks_liheap_countable_earned_income: 18000 +- name: 2026 self-employment, higher actual costs. + period: 2026 + input: + state_code: KS + age: 40 + ks_liheap_self_employment_gross_income: 24000 + ks_liheap_self_employment_expenses: 10000 + self_employment_income: 5000 + output: + ks_liheap_countable_self_employment_income: 14000 + ks_liheap_countable_earned_income: 14000 +- name: 2026 self-employment, lower actual costs retain standard deduction. + period: 2026 + input: + state_code: KS + age: 40 + ks_liheap_self_employment_gross_income: 24000 + ks_liheap_self_employment_expenses: 1000 + self_employment_income: 5000 + output: + ks_liheap_countable_self_employment_income: 18000 + ks_liheap_countable_earned_income: 18000 +- name: 2026 self-employment, expenses exceed receipts. + period: 2026 + input: + state_code: KS + age: 40 + ks_liheap_self_employment_gross_income: 12000 + ks_liheap_self_employment_expenses: 15000 + self_employment_income: 5000 + output: + ks_liheap_countable_self_employment_income: 0 + ks_liheap_countable_earned_income: 0 +- name: 2026 self-employment, explicit zero gross receipts. + period: 2026 + input: + state_code: KS + age: 40 + ks_liheap_self_employment_gross_income: 0 + ks_liheap_self_employment_expenses: 0 + self_employment_income: 5000 + output: + ks_liheap_countable_self_employment_income: 0 + ks_liheap_countable_earned_income: 0 +- name: Net income fallback does not deduct business costs a second time. + period: 2026 + input: + state_code: KS + age: 40 + self_employment_income: 5000 + sstb_self_employment_income: 2000 + farm_operations_income: 3000 + output: + ks_liheap_countable_self_employment_income: 10000 +- name: A non-farm business loss does not offset wages or another business. + period: 2026 + input: + state_code: KS + age: 40 + employment_income: 15000 + self_employment_income: -5000 + sstb_self_employment_income: 2000 + output: + ks_liheap_countable_earned_income: 17000 +- name: Self-employment income of a child under 18 is excluded. + period: 2026 + input: + state_code: KS + age: 17 + ks_liheap_self_employment_gross_income: 24000 + output: + ks_liheap_countable_earned_income: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/integration.yaml index 426fb0f27ac..def0a014ac6 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/integration.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/integration.yaml @@ -1,12 +1,12 @@ # Kansas LIEAP end-to-end integration tests. # Sources: KEESM 13100-13400 (eligibility, household, citizenship, energy # vulnerability, benefit levels); KS LIHEAP State Plan FY2026 (income sources -# 1.8-1.9 #page=5-6, categorical eligibility 1.4 #page=5, 150% FPG 2.1 and +# 1.8-1.9 #page=5-6, income verification 1.4 #page=5, 150% FPG 2.1 and # subsidized housing 2.3 #page=8, $130 minimum 2.6 #page=9); # KS_BenefitMatrix_2026.pdf (FY2026 season, "Benefit Adjustment @ 80%" table); # KS_BenefitMatrix_2025.pdf (FY2025 season, 100%). -# Income limit for program year Y = 1.5 x prior-year (Y-1) HHS guideline: -# 2026: 23,475 (1) / 31,725 (2) / 48,225 (4) / 56,475 (5); +# Annualized published monthly income limits (KEESM 13362): +# 2026: 23,472 (1) / 31,728 (2) / 48,228 (4) / 56,472 (5); # 2025: 22,590 (1) / 46,800 (4). # Monthly income band = annual countable income / 12: # 1 = 0-899, 2 = 900-1,199, 3 = 1,200-1,699, 4 = 1,700+. @@ -23,6 +23,7 @@ spm_unit: members: [person1] heating_type: NATURAL_GAS + gas_expense: 1_200 ks_liheap_dwelling_type: APARTMENT snap: 0 ks_tanf: 0 @@ -34,9 +35,8 @@ ks_liheap_household_size: 1 ks_liheap_household_size_group: 1 ks_liheap_countable_income: 22_000 - # 22,000 <= 23,475 + # 22,000 <= 23,472 ks_liheap_income_eligible: true - ks_liheap_categorically_income_eligible: false ks_liheap_eligible: true # 22,000 / 12 = 1,833 -> 1,700 & over ks_liheap_income_band: 4 @@ -64,6 +64,7 @@ spm_unit: members: [person1, person2, person3, person4] heating_type: ELECTRICITY + pre_subsidy_electricity_expense: 1_200 ks_liheap_dwelling_type: HOUSE_MODULAR_MOBILE ks_liheap_utility_rate_tier: E snap: 0 @@ -76,9 +77,8 @@ ks_liheap_household_size: 4 ks_liheap_household_size_group: 1 ks_liheap_countable_income: 45_000 - # 45,000 <= 1.5 x (15,650 + 3 x 5,500) = 48,225 + # 45,000 <= 4,019 x 12 = 48,228 ks_liheap_income_eligible: true - ks_liheap_categorically_income_eligible: false ks_liheap_eligible: true # 45,000 / 12 = 3,750 -> 1,700 & over ks_liheap_income_band: 4 @@ -108,6 +108,7 @@ members: [person1, person2, person3, person4, person5] ks_tanf: 0 heating_type: PROPANE + bottled_gas_expense: 1_200 ks_liheap_dwelling_type: DUPLEX ks_liheap_utility_rate_tier: C households: @@ -118,7 +119,7 @@ ks_liheap_household_size: 5 ks_liheap_household_size_group: 2 ks_liheap_countable_income: 13_200 - # 13,200 <= 56,475 + # 13,200 <= 56,472 ks_liheap_income_eligible: true ks_liheap_eligible: true # 13,200 / 12 = 1,100 -> 900-1,199 @@ -154,6 +155,7 @@ spm_unit: members: [person1, person2, person3, person4, person5] heating_type: NATURAL_GAS + gas_expense: 1_200 ks_liheap_dwelling_type: HOUSE_MODULAR_MOBILE ks_liheap_utility_rate_tier: E snap: 0 @@ -167,9 +169,8 @@ ks_liheap_household_size: 4 ks_liheap_household_size_group: 1 ks_liheap_countable_income: 18_000 - # 18,000 <= 48,225 (size 4) + # 18,000 <= 48,228 (size 4) ks_liheap_income_eligible: true - ks_liheap_categorically_income_eligible: false ks_liheap_eligible: true # 18,000 / 12 = 1,500 -> 1,200-1,699 ks_liheap_income_band: 3 @@ -195,6 +196,7 @@ spm_unit: members: [person1, person2] heating_type: ELECTRICITY + pre_subsidy_electricity_expense: 1_200 ks_liheap_dwelling_type: APARTMENT ks_liheap_utility_rate_tier: E households: @@ -206,16 +208,15 @@ ks_liheap_household_size_group: 1 # 20,000 + 15,000 + 1,200 SSI = 36,200 (SSA and SSI both counted) ks_liheap_countable_income: 36_200 - # 36,200 > 1.5 x (15,650 + 5,500) = 31,725, but SSI receipt -> eligible - ks_liheap_categorically_income_eligible: true - ks_liheap_income_eligible: true - ks_liheap_eligible: true + # 36,200 > 2,644 x 12 = 31,728; SSI receipt does not waive the limit. + ks_liheap_income_eligible: false + ks_liheap_eligible: false # 36,200 / 12 = 3,017 -> 1,700 & over ks_liheap_income_band: 4 ks_liheap_fuel_category: ELECTRICITY # matrix p.2 electricity (80%) 1,700 & over, tier E, Apt, size 1-4 = 365 ks_liheap_matrix_amount: 365 - ks_liheap: 365 + ks_liheap: 0 - name: Case 6, family of four with natural gas in the FY2025 season. period: 2025 @@ -236,6 +237,7 @@ members: [person1, person2, person3, person4] ks_tanf: 0 heating_type: NATURAL_GAS + gas_expense: 1_200 ks_liheap_dwelling_type: HOUSE_MODULAR_MOBILE ks_liheap_utility_rate_tier: E households: @@ -275,6 +277,7 @@ members: [person1, person2, person3, person4] ks_tanf: 0 heating_type: NATURAL_GAS + gas_expense: 1_200 ks_liheap_dwelling_type: HOUSE_MODULAR_MOBILE ks_liheap_utility_rate_tier: E households: @@ -306,6 +309,7 @@ spm_unit: members: [person1] heating_type: ELECTRICITY + pre_subsidy_electricity_expense: 1_200 ks_liheap_dwelling_type: APARTMENT receives_housing_assistance: true heat_expense_included_in_rent: true @@ -336,6 +340,7 @@ spm_unit: members: [person1] heating_type: PROPANE + bottled_gas_expense: 1_200 ks_liheap_dwelling_type: TRAILER_OTHER ks_liheap_utility_rate_tier: A households: @@ -346,7 +351,7 @@ ks_liheap_household_size: 1 ks_liheap_household_size_group: 1 ks_liheap_countable_income: 21_600 - # 21,600 <= 23,475 + # 21,600 <= 23,472 ks_liheap_income_eligible: true ks_liheap_eligible: true # 21,600 / 12 = 1,800 -> 1,700 & over @@ -371,6 +376,7 @@ spm_unit: members: [person1, person2] heating_type: WOOD + wood_expense: 1_200 ks_liheap_dwelling_type: HOUSE_MODULAR_MOBILE ks_tanf: 3_600 households: @@ -382,7 +388,6 @@ ks_liheap_household_size_group: 1 # TANF counts as income (plan 1.8): 3,600 ks_liheap_countable_income: 3_600 - ks_liheap_categorically_income_eligible: true ks_liheap_income_eligible: true ks_liheap_eligible: true # 3,600 / 12 = 300 -> 0-899 @@ -412,6 +417,7 @@ spm_unit: members: [person1, person2, person3] heating_type: NATURAL_GAS + gas_expense: 1_200 ks_liheap_dwelling_type: DUPLEX ks_liheap_utility_rate_tier: B snap: 0 @@ -423,13 +429,12 @@ output: ks_liheap_household_size: 3 ks_liheap_household_size_group: 1 - # 20,000 + 8,000 = 28,000; interest and the 17-year-old's wages excluded - ks_liheap_countable_income: 28_000 - # 28,000 <= 1.5 x (15,650 + 2 x 5,500) = 39,975 + # 20,000 + 8,000 + 1,500 = 29,500; only the teenager's wages excluded + ks_liheap_countable_income: 29_500 + # 29,500 <= 3,331 x 12 = 39,972 ks_liheap_income_eligible: true - ks_liheap_categorically_income_eligible: false ks_liheap_eligible: true - # 28,000 / 12 = 2,333 -> 1,700 & over + # 29,500 / 12 = 2,458 -> 1,700 & over ks_liheap_income_band: 4 ks_liheap_fuel_category: NATURAL_GAS # matrix p.1 (80%) 1,700 & over, tier B, Duplex, size 1-4 = 307 @@ -448,6 +453,7 @@ spm_unit: members: [person1] heating_type: PROPANE + bottled_gas_expense: 1_200 ks_liheap_dwelling_type: TRAILER_OTHER ks_liheap_utility_rate_tier: A snap: 0 @@ -462,7 +468,6 @@ ks_liheap_countable_income: 21_600 # 21,600 <= 1.5 x 15,060 = 22,590 (2025 season uses 2024 guidelines) ks_liheap_income_eligible: true - ks_liheap_categorically_income_eligible: false ks_liheap_eligible: true # 21,600 / 12 = 1,800 -> 1,700 & over ks_liheap_income_band: 4 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/ks_liheap.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/ks_liheap.yaml index 05a7d4f69b2..f0686076874 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/ks_liheap.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/ks_liheap.yaml @@ -17,6 +17,7 @@ spm_unit: members: [person1] heating_type: NATURAL_GAS + gas_expense: 1_200 ks_liheap_utility_rate_tier: E ks_liheap_dwelling_type: HOUSE_MODULAR_MOBILE households: @@ -39,6 +40,7 @@ spm_unit: members: [person1] heating_type: PROPANE + bottled_gas_expense: 1_200 ks_liheap_utility_rate_tier: A ks_liheap_dwelling_type: TRAILER_OTHER households: @@ -62,6 +64,7 @@ spm_unit: members: [person1] heating_type: NATURAL_GAS + gas_expense: 1_200 ks_liheap_utility_rate_tier: A ks_liheap_dwelling_type: TRAILER_OTHER households: @@ -94,6 +97,7 @@ members: [person1, person2, person3, person4, person5] ks_tanf: 0 heating_type: WOOD + wood_expense: 1_200 ks_liheap_dwelling_type: TRAILER_OTHER households: household: @@ -125,6 +129,7 @@ members: [person1, person2, person3, person4, person5] ks_tanf: 0 heating_type: NATURAL_GAS + gas_expense: 1_200 ks_liheap_utility_rate_tier: A ks_liheap_dwelling_type: TRAILER_OTHER households: @@ -167,6 +172,7 @@ spm_unit: members: [person1] heating_type: NATURAL_GAS + gas_expense: 1_200 snap: 0 ks_tanf: 0 households: @@ -174,7 +180,7 @@ members: [person1] state_code: KS output: - # 30,000 > 1.5 x 15,650 = 23,475 + # 30,000 > 1,956 x 12 = 23,472 ks_liheap: 0 - name: Case 8, subsidized-housing renter with heat in rent receives nothing. @@ -189,6 +195,7 @@ spm_unit: members: [person1] heating_type: NATURAL_GAS + gas_expense: 1_200 receives_housing_assistance: true heat_expense_included_in_rent: true households: @@ -210,6 +217,7 @@ spm_unit: members: [person1] heating_type: NATURAL_GAS + gas_expense: 1_200 ks_liheap_utility_rate_tier: E ks_liheap_dwelling_type: HOUSE_MODULAR_MOBILE households: @@ -233,6 +241,7 @@ spm_unit: members: [person1] heating_type: NATURAL_GAS + gas_expense: 1_200 ks_liheap_utility_rate_tier: E ks_liheap_dwelling_type: HOUSE_MODULAR_MOBILE households: @@ -255,6 +264,7 @@ spm_unit: members: [person1] heating_type: NATURAL_GAS + gas_expense: 1_200 households: household: members: [person1] @@ -274,6 +284,7 @@ spm_unit: members: [person1] heating_type: PROPANE + bottled_gas_expense: 1_200 ks_liheap_utility_rate_tier: A ks_liheap_dwelling_type: TRAILER_OTHER snap: 0 @@ -302,6 +313,7 @@ spm_unit: members: [person1] heating_type: NATURAL_GAS + gas_expense: 1_200 ks_liheap_utility_rate_tier: A ks_liheap_dwelling_type: TRAILER_OTHER snap: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/payment/ks_liheap_income_band.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/payment/ks_liheap_income_band.yaml index 3864574ef62..c96c29fa3df 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/payment/ks_liheap_income_band.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/payment/ks_liheap_income_band.yaml @@ -158,7 +158,7 @@ # 60,000 / 12 = 5,000 -> "1,700 & over" ks_liheap_income_band: 4 -- name: Case 9, band uses countable income so excluded interest does not move it. +- name: Case 9, band uses countable income so counted adult interest can move it. period: 2026 absolute_error_margin: 0.01 input: @@ -175,9 +175,8 @@ members: [person1] state_code: KS output: - # Countable 10,800 / 12 = 900 -> band 2 (interest excluded; 16,800 / 12 - # = 1,400 would wrongly be band 3). - ks_liheap_income_band: 2 + # Countable (10,800 + 6,000) / 12 = 1,400 -> band 3 (KEESM 13360). + ks_liheap_income_band: 3 - name: Case 10, FY2025 season uses the same band thresholds. period: 2025 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/review_regressions.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/review_regressions.yaml new file mode 100644 index 00000000000..c8e35532935 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/review_regressions.yaml @@ -0,0 +1,65 @@ +# KEESM 13360: verified SNAP/TANF income still enters the household test. +# KEESM 13361(29)-(30): only specified interest/dividend income is exempt. +# KEESM 13340: heating equipment alone does not establish fuel responsibility. +# KEESM 13362: FY2026 uses the published monthly limits, including rounding. +- name: SNAP receipt does not exempt an over-income household from the income test. + period: 2026 + input: + state_code: KS + age: 40 + ks_liheap_household_size: 2 + ks_liheap_countable_income: 40_000 + snap: 1_200 + output: + ks_liheap_income_eligible: false + +- name: Regular adult interest and dividends count toward household income. + period: 2026 + input: + state_code: KS + age: 40 + employment_income: 20_000 + interest_income: 3_000 + dividend_income: 2_000 + ks_tanf: 0 + output: + ks_liheap_countable_income: 25_000 + +- name: A household gathering its own wood has no purchased heating costs. + period: 2026 + input: + state_code: KS + age: 40 + employment_income: 15_000 + heating_type: WOOD + wood_expense: 0 + heat_expense_included_in_rent: false + output: + ks_liheap_eligible: false + ks_liheap: 0 + +- name: FY2026 one-person income above the published monthly limit is ineligible. + period: 2026 + input: + state_code: KS + ks_liheap_household_size: 1 + # Published monthly limit is 1,956; 1,956.25 exceeds it. + ks_liheap_countable_income: 23_475 + snap: 0 + ssi: 0 + ks_tanf: 0 + output: + ks_liheap_income_eligible: false + +- name: FY2026 four-person household exactly at the published monthly limit qualifies. + period: 2026 + input: + state_code: KS + ks_liheap_household_size: 4 + # Published monthly limit is 4,019. + ks_liheap_countable_income: 48_228 + snap: 0 + ssi: 0 + ks_tanf: 0 + output: + ks_liheap_income_eligible: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/vectorized.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/vectorized.yaml new file mode 100644 index 00000000000..3e231aa4f51 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/vectorized.yaml @@ -0,0 +1,129 @@ +# Published FY2026 adjusted matrix cells (pages 1-4) and KEESM 13340/13362. +# Seven SPM units evaluate mixed inputs and a non-Kansas mask together. +- name: Mixed households evaluate Kansas LIEAP in one vectorized simulation. + period: 2026 + input: + people: + gas: + age: 40 + employment_income: 9600 + electric: + age: 40 + employment_income: 22000 + propane: + age: 40 + employment_income: 21600 + wood: + age: 40 + employment_income: 12000 + over_limit: + age: 40 + employment_income: 30000 + free_wood: + age: 40 + employment_income: 12000 + missouri: + age: 40 + employment_income: 9600 + spm_units: + gas: + members: + - gas + heating_type: NATURAL_GAS + gas_expense: 1200 + ks_liheap_utility_rate_tier: E + ks_liheap_dwelling_type: HOUSE_MODULAR_MOBILE + ks_tanf: 0 + electric: + members: + - electric + heating_type: ELECTRICITY + pre_subsidy_electricity_expense: 1200 + ks_liheap_utility_rate_tier: E + ks_liheap_dwelling_type: APARTMENT + ks_tanf: 0 + propane: + members: + - propane + heating_type: PROPANE + bottled_gas_expense: 1200 + ks_liheap_utility_rate_tier: A + ks_liheap_dwelling_type: TRAILER_OTHER + ks_tanf: 0 + wood: + members: + - wood + heating_type: WOOD + wood_expense: 1200 + ks_liheap_utility_rate_tier: J + ks_liheap_dwelling_type: DUPLEX + ks_tanf: 0 + over_limit: + members: + - over_limit + heating_type: NATURAL_GAS + gas_expense: 1200 + ks_liheap_utility_rate_tier: B + ks_liheap_dwelling_type: DUPLEX + ks_tanf: 0 + free_wood: + members: + - free_wood + heating_type: WOOD + wood_expense: 0 + ks_liheap_utility_rate_tier: A + ks_liheap_dwelling_type: HOUSE_MODULAR_MOBILE + ks_tanf: 0 + missouri: + members: + - missouri + heating_type: NATURAL_GAS + gas_expense: 1200 + ks_liheap_utility_rate_tier: E + ks_liheap_dwelling_type: HOUSE_MODULAR_MOBILE + ks_tanf: 0 + households: + gas: + members: + - gas + state_code: KS + electric: + members: + - electric + state_code: KS + propane: + members: + - propane + state_code: KS + wood: + members: + - wood + state_code: KS + over_limit: + members: + - over_limit + state_code: KS + free_wood: + members: + - free_wood + state_code: KS + missouri: + members: + - missouri + state_code: MO + output: + spm_units: + gas: + ks_liheap: 709 + electric: + ks_liheap: 365 + propane: + ks_liheap: 130 + wood: + ks_liheap: 431 + over_limit: + ks_liheap: 0 + free_wood: + ks_liheap: 0 + missouri: + ks_liheap: 0 diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_categorically_income_eligible.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_categorically_income_eligible.py deleted file mode 100644 index d33b70e219a..00000000000 --- a/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_categorically_income_eligible.py +++ /dev/null @@ -1,17 +0,0 @@ -from policyengine_us.model_api import * - - -class ks_liheap_categorically_income_eligible(Variable): - value_type = bool - entity = SPMUnit - definition_period = YEAR - label = "Kansas LIEAP categorically income eligible" - documentation = "Households with a member receiving TANF, SSI or SNAP are considered income eligible for Kansas LIEAP heating assistance." - reference = "https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=5" - defined_for = StateCode.KS - - def formula(spm_unit, period, parameters): - receives_ssi = add(spm_unit, period, ["ssi"]) > 0 - receives_snap = spm_unit("snap", period) > 0 - receives_tanf = spm_unit("ks_tanf", period) > 0 - return receives_ssi | receives_snap | receives_tanf diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_eligible.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_eligible.py index 7a06964bcbd..c3cb5b0ab20 100644 --- a/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_eligible.py +++ b/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_eligible.py @@ -6,7 +6,7 @@ class ks_liheap_eligible(Variable): entity = SPMUnit definition_period = YEAR label = "Eligible for Kansas LIEAP" - documentation = "Kansas household that is income eligible, has at least one U.S. citizen or qualified alien member, heats its home (energy vulnerability), and is not a subsidized-housing renter whose heating costs are included in the rent." + documentation = "Kansas household that is income eligible, contains at least one citizen or qualified noncitizen, and meets the heating energy vulnerability requirement." reference = ( "https://content.dcf.ks.gov/ees/keesm/current/keesm13300.htm", "https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=8", @@ -15,10 +15,6 @@ class ks_liheap_eligible(Variable): def formula(spm_unit, period, parameters): income_eligible = spm_unit("ks_liheap_income_eligible", period) - has_citizen = spm_unit("ks_liheap_household_size", period) > 0 - heating_type = spm_unit("heating_type", period) - has_heating = heating_type != heating_type.possible_values.NONE - housing_assistance = spm_unit("receives_housing_assistance", period) - heat_in_rent = spm_unit("heat_expense_included_in_rent", period) - subsidized_heat_in_rent = housing_assistance & heat_in_rent - return income_eligible & has_citizen & has_heating & ~subsidized_heat_in_rent + has_qualified_member = spm_unit("ks_liheap_household_size", period) > 0 + energy_vulnerable = spm_unit("ks_liheap_energy_vulnerable", period) + return income_eligible & has_qualified_member & energy_vulnerable diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_energy_vulnerable.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_energy_vulnerable.py new file mode 100644 index 00000000000..71144cb15c8 --- /dev/null +++ b/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_energy_vulnerable.py @@ -0,0 +1,17 @@ +from policyengine_us.model_api import * + + +class ks_liheap_energy_vulnerable(Variable): + value_type = bool + entity = SPMUnit + definition_period = YEAR + label = "Kansas LIEAP household meets heating cost responsibility rules" + documentation = "Defaults to separately paid heating costs or heat included in unsubsidized rent. Set this fact directly for shared unmetered heat, subsidized tenants paying excess heating charges, limited FHA subsidies, or homeless households owing qualifying heating debt from a prior Kansas address. The default assumes an adult household member is responsible for separately metered purchased fuel." + defined_for = StateCode.KS + reference = "https://content.dcf.ks.gov/ees/keesm/current/keesm13300.htm" + + def formula(spm_unit, period, parameters): + pays_for_heat = spm_unit("has_heating_expense", period) + heat_in_rent = spm_unit("heat_expense_included_in_rent", period) + subsidized = spm_unit("receives_housing_assistance", period) + return pays_for_heat | (heat_in_rent & ~subsidized) diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_fpg.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_fpg.py deleted file mode 100644 index d5a25563656..00000000000 --- a/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_fpg.py +++ /dev/null @@ -1,24 +0,0 @@ -from policyengine_us.model_api import * - - -class ks_liheap_fpg(Variable): - value_type = float - entity = SPMUnit - definition_period = YEAR - label = "Kansas LIEAP federal poverty guideline" - documentation = "Federal poverty guideline used for the Kansas LIEAP income limit. The household size counts only U.S. citizens and qualified aliens (KEESM 13330), and the guideline is the prior calendar year's because each season's published income table is 150% of the prior year's HHS poverty guidelines." - unit = USD - reference = ( - "https://content.dcf.ks.gov/ees/keesm/current/keesm13300.htm", - "https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=8", - "https://www.dcf.ks.gov/services/ees/pages/energyassistance.aspx", - ) - defined_for = StateCode.KS - - def formula(spm_unit, period, parameters): - size = spm_unit("ks_liheap_household_size", period) - state_group = spm_unit.household("state_group_str", period) - p_fpg = parameters(period.last_year).gov.hhs.fpg - first_person = p_fpg.first_person[state_group] - additional_person = p_fpg.additional_person[state_group] - return first_person + additional_person * max_(size - 1, 0) diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_eligible.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_eligible.py index f687202f343..017f1641309 100644 --- a/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_eligible.py +++ b/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_eligible.py @@ -6,8 +6,10 @@ class ks_liheap_income_eligible(Variable): entity = SPMUnit definition_period = YEAR label = "Kansas LIEAP income eligible" - documentation = "Combined gross income of all household members does not exceed 150% of the federal poverty guideline for the countable household size, or the household is categorically income eligible." + documentation = "Countable household income does not exceed the published seasonal income limit. Kansas reuses income verified for other benefits but still tests total household income. Annual income represents twelve times income in the application month." reference = ( + "https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13360.htm", + "https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13360.htm", "https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=8", "https://content.dcf.ks.gov/ees/keesm/current/keesm13000.htm", "https://content.dcf.ks.gov/ees/keesm/current/keesm13300.htm", @@ -15,10 +17,6 @@ class ks_liheap_income_eligible(Variable): defined_for = StateCode.KS def formula(spm_unit, period, parameters): - p = parameters(period).gov.states.ks.dcf.liheap.eligibility income = spm_unit("ks_liheap_countable_income", period) - fpg = spm_unit("ks_liheap_fpg", period) - categorically_eligible = spm_unit( - "ks_liheap_categorically_income_eligible", period - ) - return categorically_eligible | (income <= fpg * p.fpg_limit) + limit = spm_unit("ks_liheap_income_limit", period) + return income <= limit diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_limit.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_limit.py new file mode 100644 index 00000000000..345c2835aab --- /dev/null +++ b/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_limit.py @@ -0,0 +1,25 @@ +from policyengine_us.model_api import * + + +class ks_liheap_income_limit(Variable): + value_type = float + entity = SPMUnit + definition_period = YEAR + unit = USD + label = "Kansas LIEAP annualized income limit" + defined_for = StateCode.KS + reference = ( + "https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13360.htm", + "https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13360.htm", + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ks.dcf.liheap.eligibility + size = spm_unit("ks_liheap_household_size", period) + capped_size = clip(size, 1, p.max_table_size) + additional_people = max_(size - p.max_table_size, 0) + monthly_limit = ( + p.income_limit[capped_size] + + additional_people * p.additional_person_income_limit + ) + return monthly_limit * MONTHS_IN_YEAR diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_interest_dividend_income.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_interest_dividend_income.py new file mode 100644 index 00000000000..9337a01ae96 --- /dev/null +++ b/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_interest_dividend_income.py @@ -0,0 +1,27 @@ +from policyengine_us.model_api import * + + +class ks_liheap_countable_interest_dividend_income(Variable): + value_type = float + entity = SPMUnit + definition_period = YEAR + unit = USD + label = "Kansas LIEAP countable interest and dividend income" + documentation = "Recurring interest and dividends, excluding interest of children under 18 and the FY2025 monthly exemption. Set countable income directly for exempt burial-fund interest or FY2026 irregular, unpredictable payments below the quarterly exemption." + defined_for = StateCode.KS + reference = ( + "https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13360.htm", + "https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13360.htm", + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ks.dcf.liheap.income + age = spm_unit.members("age", period) + interest = spm_unit.members("interest_income", period) + adult_interest = spm_unit.sum( + where(age >= p.interest_income_min_age, interest, 0) + ) + dividends = add(spm_unit, period, ["dividend_income"]) + total = adult_interest + dividends + threshold = p.regular_interest_dividend_exemption * MONTHS_IN_YEAR + return where(total > threshold, total, 0) diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_self_employment_income.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_self_employment_income.py new file mode 100644 index 00000000000..a0a7db38482 --- /dev/null +++ b/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_self_employment_income.py @@ -0,0 +1,25 @@ +from policyengine_us.model_api import * + + +class ks_liheap_countable_self_employment_income(Variable): + value_type = float + entity = Person + definition_period = YEAR + unit = USD + label = "Kansas LIEAP countable self-employment income" + defined_for = StateCode.KS + reference = ( + "https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13360.htm", + "https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13360.htm", + ) + + def formula(person, period, parameters): + p = parameters(period).gov.states.ks.dcf.liheap.income + gross = person("ks_liheap_self_employment_gross_income", period) + expenses = person("ks_liheap_self_employment_expenses", period) + deduction = max_(gross * p.self_employment_expense_rate, expenses) + # Tax-net earnings cannot identify gross receipts or allowable costs. + net_fallback = sum( + max_(person(source, period), 0) for source in p.sources.self_employment + ) + return where(gross >= 0, max_(gross - deduction, 0), net_fallback) diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_unearned_income.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_unearned_income.py index f79bceed22f..fd665d871a0 100644 --- a/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_unearned_income.py +++ b/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_unearned_income.py @@ -8,7 +8,10 @@ class ks_liheap_countable_unearned_income(Variable): label = "Kansas LIEAP countable unearned income" documentation = "Gross unearned income of all household members counted toward Kansas LIEAP household income." unit = USD - reference = "https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=6" + reference = ( + "https://content.dcf.ks.gov/ees/keesm/current/keesm13360.htm", + "https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=6", + ) defined_for = StateCode.KS adds = "gov.states.ks.dcf.liheap.income.sources.unearned" diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_self_employment_expenses.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_self_employment_expenses.py new file mode 100644 index 00000000000..8489624f123 --- /dev/null +++ b/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_self_employment_expenses.py @@ -0,0 +1,11 @@ +from policyengine_us.model_api import * + + +class ks_liheap_self_employment_expenses(Variable): + value_type = float + entity = Person + definition_period = YEAR + unit = USD + label = "Kansas LIEAP allowable self-employment expenses" + documentation = "Annual actual income-producing costs allowable under KEESM 13360. Used with gross receipts when claiming actual costs gives a larger deduction than the standard percentage." + reference = "https://content.dcf.ks.gov/ees/keesm/current/keesm13360.htm" diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_self_employment_gross_income.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_self_employment_gross_income.py new file mode 100644 index 00000000000..e6e8a7ea626 --- /dev/null +++ b/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_self_employment_gross_income.py @@ -0,0 +1,12 @@ +from policyengine_us.model_api import * + + +class ks_liheap_self_employment_gross_income(Variable): + value_type = float + entity = Person + definition_period = YEAR + unit = USD + default_value = -1 + label = "Kansas LIEAP gross self-employment receipts" + documentation = "Annual gross receipts before business expenses, including farming. A value of -1 means receipts are unavailable; the countable-income formula then uses reported net self-employment income without taking a second expense deduction." + reference = "https://content.dcf.ks.gov/ees/keesm/current/keesm13360.htm" diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/payment/ks_liheap_matrix_amount.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/payment/ks_liheap_matrix_amount.py index 751ca3406fe..90dab5cd8f3 100644 --- a/policyengine_us/variables/gov/states/ks/dcf/liheap/payment/ks_liheap_matrix_amount.py +++ b/policyengine_us/variables/gov/states/ks/dcf/liheap/payment/ks_liheap_matrix_amount.py @@ -19,10 +19,12 @@ def formula(spm_unit, period, parameters): p = parameters(period).gov.states.ks.dcf.liheap.payment.matrix fuel = spm_unit("ks_liheap_fuel_category", period) fuels = fuel.possible_values - band = spm_unit("ks_liheap_income_band", period) + # State-masked helpers return zero outside Kansas. Keep lookup keys + # valid while the framework evaluates mixed-state arrays. + band = max_(spm_unit("ks_liheap_income_band", period), 1) tier = spm_unit("ks_liheap_utility_rate_tier", period) dwelling = spm_unit("ks_liheap_dwelling_type", period) - size_group = spm_unit("ks_liheap_household_size_group", period) + size_group = max_(spm_unit("ks_liheap_household_size_group", period), 1) return select( [ fuel == fuels.NATURAL_GAS, From 6aa2b0ae9de2b314fc624fc1ee959c3de0f99a4e Mon Sep 17 00:00:00 2001 From: Ziming Date: Mon, 28 Sep 2026 15:53:45 -0400 Subject: [PATCH 03/12] Refactor Kansas LIEAP income limits around shared FPG rules --- .../gov/states/ks/dcf/liheap/README.md | 78 ---------------- .../additional_person_income_limit.yaml | 14 --- .../ks/dcf/liheap/eligibility/fpg_rate.yaml | 13 +++ .../dcf/liheap/eligibility/fpg_year_lag.yaml | 18 ++++ .../dcf/liheap/eligibility/income_limit.yaml | 45 --------- .../eligibility/rounding_increment.yaml | 18 ++++ .../eligibility/ks_liheap_income_limit.yaml | 92 +++++++++++++++++++ policyengine_us/tools/liheap.py | 32 +++++++ .../eligibility/ks_liheap_income_limit.py | 10 +- ...liheap_countable_self_employment_income.py | 6 +- 10 files changed, 180 insertions(+), 146 deletions(-) delete mode 100644 policyengine_us/parameters/gov/states/ks/dcf/liheap/README.md delete mode 100644 policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/additional_person_income_limit.yaml create mode 100644 policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/fpg_rate.yaml create mode 100644 policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/fpg_year_lag.yaml delete mode 100644 policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/income_limit.yaml create mode 100644 policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/rounding_increment.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_limit.yaml create mode 100644 policyengine_us/tools/liheap.py diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/README.md b/policyengine_us/parameters/gov/states/ks/dcf/liheap/README.md deleted file mode 100644 index a7767bd9f7f..00000000000 --- a/policyengine_us/parameters/gov/states/ks/dcf/liheap/README.md +++ /dev/null @@ -1,78 +0,0 @@ -# Kansas LIEAP regular heating assistance - -Coverage is partial for the FY2025 and FY2026 heating seasons. Cooling, crisis, -weatherization, and equipment assistance are outside this implementation. - -## Rules and authorities - -| Component | Authority | Implementation | -| --- | --- | --- | -| Kansas residence, household membership and qualified members | KEESM 13310-13330 | Kansas SPM units; qualified members determine size, all members' countable income enters the income test. | -| Heating cost responsibility | KEESM 13340 | Separately purchased heat or heat included in unsubsidized rent; a direct input handles exceptional housing/debt arrangements. | -| Income test and reuse of verified income | KEESM 13360 | Every household must meet the income limit; SNAP, TANF or SSI receipt does not waive the total-income test. | -| Self-employment | KEESM 13360 | Gross receipts less 25%, or higher allowable actual costs, when gross receipts are supplied. | -| Child earnings, interest and other income | KEESM 13360-13361 | Exclude earnings and interest of children under 18; count modeled income sources subject to the documented limitations below. | -| Income limits | KEESM 13362 | Published monthly tables, annualized; do not substitute unrounded 150% FPG calculations. | -| Benefit amount | KEESM 13410; annual benefit matrices | Fuel, monthly income band, utility rate tier, dwelling type and eligible household size group. | -| Minimum payment | FY2025/FY2026 state plans, section 2.6 | $100/$130 respectively. | - -Historical manual editions: - -- [October 2024 eligibility](https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13300.htm) -- [October 2024 income rules and limits](https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13360.htm) -- [January 2026 eligibility](https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13300.htm) -- [January 2026 income rules and limits](https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13360.htm) -- [Benefit rules](https://content.dcf.ks.gov/ees/keesm/current/keesm13400.htm) - -Benefit sources: - -- [FY2025 state plan, section 2](https://liheapch.acf.gov/docs/2025/state-plans/KS_Plan_2025.pdf#page=8) -- [FY2026 state plan, section 2](https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=8) -- [FY2025 matrix, 100% values](https://liheapch.acf.gov/docs/2025/benefits-matricies/KS_BenefitMatrix_2025.pdf) -- [FY2026 matrix, adjusted 80% values](https://liheapch.acf.gov/docs/2026/benefits-matricies/KS_BenefitMatrix_2026.pdf) - -All 1,984 encoded cells were compared with the official PDFs on September 28, -2026. The matrix maxima are $2,232 and $1,682 respectively. The plans' maximum -benefits do not reduce any cell, so an extra maximum cap cannot bind. - -## Source reconciliation - -The state plan's categorical-eligibility wording describes reuse of verified -income. KEESM 13360 explicitly still tests the combined household income. The -plan's unchecked combined interest/dividends/royalties box is not treated as a -blanket exclusion: KEESM 13361 specifies the exemptions. The October 2024 -LIEAP-specific text exempts interest and dividends up to $50 monthly, counting -the full amount above that threshold. The January 2026 text instead exempts -small irregular, unpredictable payments, not regular interest generally. -The model follows each season's LIEAP-specific manual; the FY2026 irregular -payment exception requires a direct countable-income input. - -There is no modeled household contribution requirement. DCF eliminated the -former self-payment rule in [revision 114, effective February 2024](https://content.dcf.ks.gov/EES/KEESM/SOC_Rev_114_02_24.html). - -## Periods and modeling limitations - -- A YEAR calculation for 2025 or 2026 selects that year's heating season. - October parameter dates index the federal fiscal-year schedules. They do not - represent application opening dates. Income divided by twelve approximates - the application month; callers can supply annualized application-month - countable income directly. Weekly/biweekly conversions and irregular receipt - timing are not inferred from annual data. -- The SPM unit approximates the energy household. Shared addresses, paid - attendants, college dormitories, duplicate state/tribal awards, and application - administration are not independently resolved. -- Tier E and house/modular/mobile are modeling defaults, not legal findings - about a household. Supply the actual vendor tier and dwelling type. Solar - heat follows the shared grid-tied electric-heat convention. -- Supply `ks_liheap_energy_vulnerable` for shared unmetered heat, qualifying - prior-address heating debt, excess subsidized-housing charges, or limited FHA - assistance. A fuel type alone does not establish purchased heating costs. -- Self-employment receipts default to -1 (unknown). Without gross receipts, - positive reported net business/farm income is a fallback; it receives no - second expense deduction. Actual allowable costs and the standard deduction - require the gross-receipts input. -- Source-specific exemptions and missing receipt types, including irregular - interest, burial-fund interest, some cash gifts, contract payments, royalties, - settlements and foster/adoption payments, are not fully distinguished by - available inputs. Use directly supplied countable income for such cases. - Coverage remains partial rather than implying those amounts are all exempt. diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/additional_person_income_limit.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/additional_person_income_limit.yaml deleted file mode 100644 index 1243a627e0a..00000000000 --- a/policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/additional_person_income_limit.yaml +++ /dev/null @@ -1,14 +0,0 @@ -description: Kansas increases the monthly Low Income Energy Assistance Program income limit by this amount for each person beyond the maximum tabulated household size. -values: - 2024-10-01: 672.5 - 2025-10-01: 688 - -metadata: - unit: currency-USD - period: month - label: Kansas LIEAP additional person monthly income limit - reference: - - title: KEESM 13360-13362, October 2024 edition - href: https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13360.htm - - title: KEESM 13360-13362, January 2026 edition - href: https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13360.htm diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/fpg_rate.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/fpg_rate.yaml new file mode 100644 index 00000000000..9b51e52da84 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/fpg_rate.yaml @@ -0,0 +1,13 @@ +description: Kansas limits countable income to this multiple of the federal poverty guidelines under the Low Income Energy Assistance Program. +values: + 2024-10-01: 1.5 + +metadata: + unit: /1 + period: year + label: Kansas LIEAP federal poverty guideline rate + reference: + - title: KEESM 13360 Income Eligibility, October 2024 edition + href: https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13360.htm + - title: KEESM 13360 Income Eligibility, January 2026 edition + href: https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13360.htm diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/fpg_year_lag.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/fpg_year_lag.yaml new file mode 100644 index 00000000000..8b271510508 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/fpg_year_lag.yaml @@ -0,0 +1,18 @@ +description: Kansas uses federal poverty guidelines from this many years before the modeled heating season for the Low Income Energy Assistance Program income limit. +# Verified for FY2025 and FY2026: their limits use the 2024 and 2025 +# guidelines, respectively. This is a relative year selection, not a fixed +# guideline year. Earlier and later Kansas policy remains unverified. +values: + 2024-10-01: 1 + +metadata: + unit: year + period: year + label: Kansas LIEAP federal poverty guideline year lag + reference: + - title: KEESM 13362 Income Guidelines, October 2024 edition + href: https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13360.htm + - title: KEESM 13362 Income Guidelines, January 2026 edition + href: https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13360.htm + - title: HHS poverty guidelines, 2024 and 2025 + href: https://aspe.hhs.gov/topics/poverty-economic-mobility/poverty-guidelines/prior-hhs-poverty-guidelines-federal-register-references diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/income_limit.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/income_limit.yaml deleted file mode 100644 index cdfef9972f3..00000000000 --- a/policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/income_limit.yaml +++ /dev/null @@ -1,45 +0,0 @@ -description: Kansas limits monthly countable income to these amounts under the Low Income Energy Assistance Program, by household size. - -1: - 2024-10-01: 1882.5 - 2025-10-01: 1956 - -2: - 2024-10-01: 2555 - 2025-10-01: 2644 - -3: - 2024-10-01: 3227.5 - 2025-10-01: 3331 - -4: - 2024-10-01: 3900 - 2025-10-01: 4019 - -5: - 2024-10-01: 4572.5 - 2025-10-01: 4706 - -6: - 2024-10-01: 5245 - 2025-10-01: 5394 - -7: - 2024-10-01: 5917.5 - 2025-10-01: 6081 - -8: - 2024-10-01: 6590 - 2025-10-01: 6769 - -metadata: - unit: currency-USD - period: month - label: Kansas LIEAP monthly income limit - breakdown: - - range(1, 9) - reference: - - title: KEESM 13362 Income Guidelines, October 2024 edition - href: https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13360.htm - - title: KEESM 13362 Income Guidelines, January 2026 edition - href: https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13360.htm diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/rounding_increment.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/rounding_increment.yaml new file mode 100644 index 00000000000..96e0841571f --- /dev/null +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/rounding_increment.yaml @@ -0,0 +1,18 @@ +description: Kansas expresses monthly Low Income Energy Assistance Program income limits in increments of this amount. +# Precision inferred from the published tables, not an express rounding rule: +# FY2025 retains cents and exactly matches 150% of the 2024 guidelines. +# FY2026 matches nearest-dollar rounding of 150% of the 2025 guidelines, +# including a separately rounded $688 increment for each person beyond eight. +values: + 2024-10-01: 0.01 + 2025-10-01: 1 + +metadata: + unit: currency-USD + period: month + label: Kansas LIEAP monthly income limit rounding increment + reference: + - title: KEESM 13362 Income Guidelines, October 2024 edition + href: https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13360.htm + - title: KEESM 13362 Income Guidelines, January 2026 edition + href: https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13360.htm diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_limit.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_limit.yaml new file mode 100644 index 00000000000..004482bb5ba --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_limit.yaml @@ -0,0 +1,92 @@ +# KEESM 13362, October 2024 and January 2026 editions: +# https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13360.htm +# https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13360.htm +# Expected amounts below annualize the published monthly limits. Sizes 9 and +# 10 use the published additional-person increment; the final row is outside KS. +- name: Case 1, FY2025 published income limits retain cents for all household sizes. + period: 2025 + absolute_error_margin: 0.01 + input: + state_code: [KS, KS, KS, KS, KS, KS, KS, KS, KS, KS, MO] + ks_liheap_household_size: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1] + output: + ks_liheap_income_limit: [22_590, 30_660, 38_730, 46_800, 54_870, 62_940, 71_010, 79_080, 87_150, 95_220, 0] + +- name: Case 2, FY2026 published income limits round the base and additional-person increment separately. + period: 2026 + absolute_error_margin: 0.01 + input: + state_code: [KS, KS, KS, KS, KS, KS, KS, KS, KS, KS, MO] + ks_liheap_household_size: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1] + output: + ks_liheap_income_limit: [23_472, 31_728, 39_972, 48_228, 56_472, 64_728, 72_972, 81_228, 89_484, 97_740, 0] + +# Hypothetical reforms ensure the calculation follows the policy parameters +# instead of retaining the baseline dollar amounts in another lookup table. +- name: Case 3, an income-limit rate reform changes the derived threshold. + period: 2026 + absolute_error_margin: 0.01 + input: + gov.states.ks.dcf.liheap.eligibility.fpg_rate: 2 + state_code: KS + ks_liheap_household_size: 1 + output: + # $15,650 * 2 / 12 = $2,608.333... -> $2,608 per month. + ks_liheap_income_limit: 31_296 + +- name: Case 4, a guideline-year lag reform selects an earlier poverty guideline. + period: 2026 + absolute_error_margin: 0.01 + input: + gov.states.ks.dcf.liheap.eligibility.fpg_year_lag: 2 + state_code: KS + ks_liheap_household_size: 1 + output: + # Two-year lag selects 2024: $15,060 * 1.5 / 12 = $1,882.50 -> $1,883. + ks_liheap_income_limit: 22_596 + +- name: Case 5, a cents-precision reform retains the exact FPG amount above eight people. + period: 2026 + absolute_error_margin: 0.01 + input: + gov.states.ks.dcf.liheap.eligibility.rounding_increment: 0.01 + state_code: KS + ks_liheap_household_size: 9 + output: + # ($15,650 + 8 * $5,500) * 1.5 = $89,475. + ks_liheap_income_limit: 89_475 + +- name: Case 6, the separately rounded additional-person rule uses the parameterized breakpoint. + period: 2026 + absolute_error_margin: 0.01 + input: + gov.states.ks.dcf.liheap.eligibility.max_table_size: 6 + state_code: KS + ks_liheap_household_size: 7 + output: + # Six-person $5,394 monthly limit plus rounded $688 increment. + ks_liheap_income_limit: 72_984 + +# These are regression checks on the fallback year selection, not verification +# of Kansas policy outside the supported FY2025-FY2026 seasons. The rate and +# rounding parameters still carry the earliest/latest available policy values. +- name: Case 7, historical fallback guideline year follows the modeled year. + period: 2022 + absolute_error_margin: 0.01 + input: + state_code: KS + ks_liheap_household_size: 1 + output: + # One-year lag: 2021 FPG of $12,880, using the fallback 150% rate. + ks_liheap_income_limit: 19_320 + +- name: Case 8, future fallback guideline year follows the modeled year. + period: 2027 + absolute_error_margin: 0.01 + input: + state_code: KS + ks_liheap_household_size: 1 + output: + # One-year lag: 2026 FPG of $15,960, using the fallback 150% rate. + # $15,960 * 1.5 / 12 = $1,995, so whole-dollar rounding is unchanged. + ks_liheap_income_limit: 23_940 diff --git a/policyengine_us/tools/liheap.py b/policyengine_us/tools/liheap.py new file mode 100644 index 00000000000..c2b5ab2c06c --- /dev/null +++ b/policyengine_us/tools/liheap.py @@ -0,0 +1,32 @@ +"""Shared calculations for state LIHEAP regular heating assistance.""" + +import numpy as np +from policyengine_core.model_api import MONTHS_IN_YEAR, clip, max_ + + +def calculate_liheap_fpg_income_limit( + household_size, state_group, period, parameters, policy +): + """Annualize a monthly FPG limit with separately rounded size increments. + + The caller supplies its policy household size, modeled period, and dated + parameters: fpg_year_lag, fpg_rate, rounding_increment, and max_table_size. + Guideline amounts come from the shared federal parameters for the modeled + year minus the guideline-year lag. Round to the nearest + increment, with ties rounded up, before adding people beyond the breakpoint. + """ + fpg_year = period.start.year - int(policy.fpg_year_lag) + fpg = parameters(f"{fpg_year}-01-01").gov.hhs.fpg + first_person = fpg.first_person[state_group] + additional_person = fpg.additional_person[state_group] + capped_size = clip(household_size, 1, policy.max_table_size) + additional_people = max_(household_size - policy.max_table_size, 0) + monthly_factor = policy.fpg_rate / MONTHS_IN_YEAR + monthly_limit = ( + first_person + additional_person * (capped_size - 1) + ) * monthly_factor + monthly_increment = additional_person * monthly_factor + rounding = policy.rounding_increment + rounded_limit = np.floor(monthly_limit / rounding + 0.5) * rounding + rounded_increment = np.floor(monthly_increment / rounding + 0.5) * rounding + return (rounded_limit + additional_people * rounded_increment) * MONTHS_IN_YEAR diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_limit.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_limit.py index 345c2835aab..ed3373ec585 100644 --- a/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_limit.py +++ b/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_limit.py @@ -1,4 +1,5 @@ from policyengine_us.model_api import * +from policyengine_us.tools.liheap import calculate_liheap_fpg_income_limit class ks_liheap_income_limit(Variable): @@ -16,10 +17,7 @@ class ks_liheap_income_limit(Variable): def formula(spm_unit, period, parameters): p = parameters(period).gov.states.ks.dcf.liheap.eligibility size = spm_unit("ks_liheap_household_size", period) - capped_size = clip(size, 1, p.max_table_size) - additional_people = max_(size - p.max_table_size, 0) - monthly_limit = ( - p.income_limit[capped_size] - + additional_people * p.additional_person_income_limit + state_group = spm_unit.household("state_group_str", period) + return calculate_liheap_fpg_income_limit( + size, state_group, period, parameters, p ) - return monthly_limit * MONTHS_IN_YEAR diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_self_employment_income.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_self_employment_income.py index a0a7db38482..7a365aa28c2 100644 --- a/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_self_employment_income.py +++ b/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_self_employment_income.py @@ -19,7 +19,7 @@ def formula(person, period, parameters): expenses = person("ks_liheap_self_employment_expenses", period) deduction = max_(gross * p.self_employment_expense_rate, expenses) # Tax-net earnings cannot identify gross receipts or allowable costs. - net_fallback = sum( - max_(person(source, period), 0) for source in p.sources.self_employment - ) + net_fallback = 0 + for source in p.sources.self_employment: + net_fallback = net_fallback + max_(person(source, period), 0) return where(gross >= 0, max_(gross - deduction, 0), net_fallback) From ba7fe760ed464e6a2b261d5944de578e6cd9a0b5 Mon Sep 17 00:00:00 2001 From: Ziming Date: Tue, 29 Sep 2026 15:00:02 -0400 Subject: [PATCH 04/12] Simplify Kansas LIEAP self-employment income inputs --- changelog.d/ks-liheap.added.md | 2 +- .../income/self_employment_expense_rate.yaml | 13 -- .../ks/dcf/liheap/income/sources/earned.yaml | 11 +- .../income/sources/self_employment.yaml | 14 -- .../ks_liheap_countable_earned_income.yaml | 93 ++++++++++++ ...heap_countable_self_employment_income.yaml | 140 ------------------ .../ks_liheap_countable_earned_income.py | 17 ++- ...liheap_countable_self_employment_income.py | 25 ---- .../ks_liheap_self_employment_expenses.py | 11 -- .../ks_liheap_self_employment_gross_income.py | 12 -- 10 files changed, 118 insertions(+), 220 deletions(-) delete mode 100644 policyengine_us/parameters/gov/states/ks/dcf/liheap/income/self_employment_expense_rate.yaml delete mode 100644 policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/self_employment.yaml delete mode 100644 policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_self_employment_income.yaml delete mode 100644 policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_self_employment_income.py delete mode 100644 policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_self_employment_expenses.py delete mode 100644 policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_self_employment_gross_income.py diff --git a/changelog.d/ks-liheap.added.md b/changelog.d/ks-liheap.added.md index c5c199bb403..9993101a793 100644 --- a/changelog.d/ks-liheap.added.md +++ b/changelog.d/ks-liheap.added.md @@ -1 +1 @@ -Kansas LIEAP (Low Income Energy Assistance Program) heating benefit: eligibility, countable income, and the FY2025-FY2026 benefit matrices. +Kansas LIEAP (Low Income Energy Assistance Program) heating benefit: eligibility, countable income, and the FY2025-FY2026 benefit matrices. Self-employment income is approximated using existing net-income inputs without an additional expense deduction. diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/self_employment_expense_rate.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/self_employment_expense_rate.yaml deleted file mode 100644 index 9baccd133c6..00000000000 --- a/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/self_employment_expense_rate.yaml +++ /dev/null @@ -1,13 +0,0 @@ -description: Kansas deducts this share of gross self-employment receipts for expenses under the Low Income Energy Assistance Program unless the household claims higher allowable actual costs. -values: - 2024-10-01: 0.25 - -metadata: - unit: /1 - period: year - label: Kansas LIEAP standard self-employment expense rate - reference: - - title: KEESM 13360-13362, October 2024 edition - href: https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13360.htm - - title: KEESM 13360-13362, January 2026 edition - href: https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13360.htm diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/earned.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/earned.yaml index 60d982d5c45..1630f12b527 100644 --- a/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/earned.yaml +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/earned.yaml @@ -1,14 +1,21 @@ -description: Kansas counts these earned income sources in gross household income under the Low Income Energy Assistance Program. +description: Kansas uses these earned income sources to approximate countable household earnings under the Low Income Energy Assistance Program. +# Existing net self-employment inputs are used without an additional expense +# deduction. They approximate KEESM 13360's gross-receipts calculation and do +# not reproduce its standard deduction or actual-cost election in every case. values: 2024-10-01: - employment_income - - ks_liheap_countable_self_employment_income + - self_employment_income + - sstb_self_employment_income + - farm_operations_income metadata: unit: list period: year label: Kansas LIEAP countable earned income sources reference: + - title: KEESM 13360 Income Eligibility, January 2026 edition (self-employment expense rule approximated using existing net income) + href: https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13360.htm - title: Kansas LIHEAP FY2026 State Plan, Section 1.8-1.9 (gross income; wages, self-employment income, contract income and commissions counted) href: https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=6 - title: KEESM 13320 Household Definition (income of all household members living together is used) diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/self_employment.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/self_employment.yaml deleted file mode 100644 index 4e04592ffd7..00000000000 --- a/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/self_employment.yaml +++ /dev/null @@ -1,14 +0,0 @@ -description: Kansas uses these net self-employment income sources as a fallback under the Low Income Energy Assistance Program when gross receipts and allowable business costs are unavailable. -values: - 2024-10-01: - - self_employment_income - - sstb_self_employment_income - - farm_operations_income - -metadata: - unit: list - period: year - label: Kansas LIEAP net self-employment income fallback sources - reference: - - title: KEESM 13360 Income Eligibility (gross receipts less business costs) - href: https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13360.htm diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_earned_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_earned_income.yaml index ad2e50b680d..6bcdb8bff8e 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_earned_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_earned_income.yaml @@ -2,6 +2,8 @@ # 1.8-1.9, #page=6-7): gross wages and self-employment income are counted, # except the earned income of a child under 18. KEESM 13320: a member who is # or turns 18 in the application month has countable income. +# Modeling simplification: use existing net business income directly, without +# applying KEESM 13360's gross-receipts expense deduction a second time. - name: Case 1, adult wages are counted in full. period: 2026 @@ -102,3 +104,94 @@ state_code: KS output: ks_liheap_countable_earned_income: 0 + +- name: Case 6, FY2025 reported net business income receives no additional deduction. + period: 2025 + input: + state_code: KS + age: 40 + self_employment_income: 24_000 + output: + ks_liheap_countable_earned_income: 24_000 + self_employment_income: 24_000 + +- name: Case 7, FY2026 includes regular, SSTB, and farm net income alongside wages. + period: 2026 + input: + state_code: KS + age: 40 + employment_income: 12_000 + self_employment_income: 6_000 + sstb_self_employment_income: 3_000 + farm_operations_income: 5_000 + ks_tanf: 0 + output: + ks_liheap_countable_earned_income: 26_000 + ks_liheap_countable_income: 26_000 + +- name: Case 8, a farm loss does not offset wages or other positive business income. + period: 2026 + input: + state_code: KS + age: 40 + employment_income: 12_000 + self_employment_income: 6_000 + sstb_self_employment_income: 4_000 + farm_operations_income: -15_000 + output: + ks_liheap_countable_earned_income: 22_000 + farm_operations_income: -15_000 + +- name: Case 9, an adult with only business losses has no countable earnings. + period: 2026 + input: + state_code: KS + age: 40 + self_employment_income: -3_000 + sstb_self_employment_income: -2_000 + farm_operations_income: -1_000 + output: + ks_liheap_countable_earned_income: 0 + +- name: Case 10, child business income is excluded and adult losses do not affect other people. + period: 2026 + input: + people: + parent: + age: 40 + employment_income: 12_000 + self_employment_income: -4_000 + child: + age: 17 + employment_income: 5_000 + self_employment_income: 4_000 + sstb_self_employment_income: 3_000 + farm_operations_income: 2_000 + adult_child: + age: 18 + self_employment_income: 6_000 + spm_units: + spm_unit: + members: [parent, child, adult_child] + ks_tanf: 0 + households: + household: + members: [parent, child, adult_child] + state_code: KS + output: + ks_liheap_countable_earned_income: [12_000, 0, 6_000] + ks_liheap_countable_income: 18_000 + self_employment_income: [-4_000, 4_000, 6_000] + +- name: Case 11, an explicitly supplied Kansas countable amount overrides the net approximation. + period: 2026 + input: + state_code: KS + age: 40 + self_employment_income: 5_000 + # Known gross receipts of 24,000 less the 25% standard expense deduction. + ks_liheap_countable_earned_income: 18_000 + ks_tanf: 0 + output: + ks_liheap_countable_income: 18_000 + self_employment_income: 5_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_self_employment_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_self_employment_income.yaml deleted file mode 100644 index 9b26ff42d7c..00000000000 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_self_employment_income.yaml +++ /dev/null @@ -1,140 +0,0 @@ -# KEESM 13360, October 2024 and January 2026: gross receipts less 25% -# or elected actual costs. Tax-net fallback is a documented approximation. -- name: 2025 self-employment, standard deduction. - period: 2025 - input: - state_code: KS - age: 40 - ks_liheap_self_employment_gross_income: 24000 - ks_liheap_self_employment_expenses: 0 - self_employment_income: 5000 - output: - ks_liheap_countable_self_employment_income: 18000 - ks_liheap_countable_earned_income: 18000 -- name: 2025 self-employment, higher actual costs. - period: 2025 - input: - state_code: KS - age: 40 - ks_liheap_self_employment_gross_income: 24000 - ks_liheap_self_employment_expenses: 10000 - self_employment_income: 5000 - output: - ks_liheap_countable_self_employment_income: 14000 - ks_liheap_countable_earned_income: 14000 -- name: 2025 self-employment, lower actual costs retain standard deduction. - period: 2025 - input: - state_code: KS - age: 40 - ks_liheap_self_employment_gross_income: 24000 - ks_liheap_self_employment_expenses: 1000 - self_employment_income: 5000 - output: - ks_liheap_countable_self_employment_income: 18000 - ks_liheap_countable_earned_income: 18000 -- name: 2025 self-employment, expenses exceed receipts. - period: 2025 - input: - state_code: KS - age: 40 - ks_liheap_self_employment_gross_income: 12000 - ks_liheap_self_employment_expenses: 15000 - self_employment_income: 5000 - output: - ks_liheap_countable_self_employment_income: 0 - ks_liheap_countable_earned_income: 0 -- name: 2025 self-employment, explicit zero gross receipts. - period: 2025 - input: - state_code: KS - age: 40 - ks_liheap_self_employment_gross_income: 0 - ks_liheap_self_employment_expenses: 0 - self_employment_income: 5000 - output: - ks_liheap_countable_self_employment_income: 0 - ks_liheap_countable_earned_income: 0 -- name: 2026 self-employment, standard deduction. - period: 2026 - input: - state_code: KS - age: 40 - ks_liheap_self_employment_gross_income: 24000 - ks_liheap_self_employment_expenses: 0 - self_employment_income: 5000 - output: - ks_liheap_countable_self_employment_income: 18000 - ks_liheap_countable_earned_income: 18000 -- name: 2026 self-employment, higher actual costs. - period: 2026 - input: - state_code: KS - age: 40 - ks_liheap_self_employment_gross_income: 24000 - ks_liheap_self_employment_expenses: 10000 - self_employment_income: 5000 - output: - ks_liheap_countable_self_employment_income: 14000 - ks_liheap_countable_earned_income: 14000 -- name: 2026 self-employment, lower actual costs retain standard deduction. - period: 2026 - input: - state_code: KS - age: 40 - ks_liheap_self_employment_gross_income: 24000 - ks_liheap_self_employment_expenses: 1000 - self_employment_income: 5000 - output: - ks_liheap_countable_self_employment_income: 18000 - ks_liheap_countable_earned_income: 18000 -- name: 2026 self-employment, expenses exceed receipts. - period: 2026 - input: - state_code: KS - age: 40 - ks_liheap_self_employment_gross_income: 12000 - ks_liheap_self_employment_expenses: 15000 - self_employment_income: 5000 - output: - ks_liheap_countable_self_employment_income: 0 - ks_liheap_countable_earned_income: 0 -- name: 2026 self-employment, explicit zero gross receipts. - period: 2026 - input: - state_code: KS - age: 40 - ks_liheap_self_employment_gross_income: 0 - ks_liheap_self_employment_expenses: 0 - self_employment_income: 5000 - output: - ks_liheap_countable_self_employment_income: 0 - ks_liheap_countable_earned_income: 0 -- name: Net income fallback does not deduct business costs a second time. - period: 2026 - input: - state_code: KS - age: 40 - self_employment_income: 5000 - sstb_self_employment_income: 2000 - farm_operations_income: 3000 - output: - ks_liheap_countable_self_employment_income: 10000 -- name: A non-farm business loss does not offset wages or another business. - period: 2026 - input: - state_code: KS - age: 40 - employment_income: 15000 - self_employment_income: -5000 - sstb_self_employment_income: 2000 - output: - ks_liheap_countable_earned_income: 17000 -- name: Self-employment income of a child under 18 is excluded. - period: 2026 - input: - state_code: KS - age: 17 - ks_liheap_self_employment_gross_income: 24000 - output: - ks_liheap_countable_earned_income: 0 diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_earned_income.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_earned_income.py index a50b4cdb6cd..950f41d50d6 100644 --- a/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_earned_income.py +++ b/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_earned_income.py @@ -6,9 +6,20 @@ class ks_liheap_countable_earned_income(Variable): entity = Person definition_period = YEAR label = "Kansas LIEAP countable earned income" - documentation = "Gross earned income counted toward Kansas LIEAP household income. Earned income of a child under 18 is not counted." + documentation = ( + "Gross wages and reported net self-employment income of adults. " + "Using net business income directly approximates KEESM 13360's gross " + "receipts less a 25% expense deduction or elected allowable actual " + "costs; no additional expense deduction is applied to net income. " + "Each income source is floored at zero, so business losses do not " + "offset other earnings. Earned income of children under 18 is excluded. " + "Supply countable earned income directly when the exact Kansas " + "self-employment amount is known." + ) unit = USD reference = ( + "https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13360.htm", + "https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13360.htm", "https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=6", "https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=7", ) @@ -16,6 +27,8 @@ class ks_liheap_countable_earned_income(Variable): def formula(person, period, parameters): p = parameters(period).gov.states.ks.dcf.liheap.income - earned = add(person, period, p.sources.earned) + earned = 0 + for source in p.sources.earned: + earned = earned + max_(person(source, period), 0) age = person("age", period) return where(age >= p.earned_income_min_age, earned, 0) diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_self_employment_income.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_self_employment_income.py deleted file mode 100644 index 7a365aa28c2..00000000000 --- a/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_self_employment_income.py +++ /dev/null @@ -1,25 +0,0 @@ -from policyengine_us.model_api import * - - -class ks_liheap_countable_self_employment_income(Variable): - value_type = float - entity = Person - definition_period = YEAR - unit = USD - label = "Kansas LIEAP countable self-employment income" - defined_for = StateCode.KS - reference = ( - "https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13360.htm", - "https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13360.htm", - ) - - def formula(person, period, parameters): - p = parameters(period).gov.states.ks.dcf.liheap.income - gross = person("ks_liheap_self_employment_gross_income", period) - expenses = person("ks_liheap_self_employment_expenses", period) - deduction = max_(gross * p.self_employment_expense_rate, expenses) - # Tax-net earnings cannot identify gross receipts or allowable costs. - net_fallback = 0 - for source in p.sources.self_employment: - net_fallback = net_fallback + max_(person(source, period), 0) - return where(gross >= 0, max_(gross - deduction, 0), net_fallback) diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_self_employment_expenses.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_self_employment_expenses.py deleted file mode 100644 index 8489624f123..00000000000 --- a/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_self_employment_expenses.py +++ /dev/null @@ -1,11 +0,0 @@ -from policyengine_us.model_api import * - - -class ks_liheap_self_employment_expenses(Variable): - value_type = float - entity = Person - definition_period = YEAR - unit = USD - label = "Kansas LIEAP allowable self-employment expenses" - documentation = "Annual actual income-producing costs allowable under KEESM 13360. Used with gross receipts when claiming actual costs gives a larger deduction than the standard percentage." - reference = "https://content.dcf.ks.gov/ees/keesm/current/keesm13360.htm" diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_self_employment_gross_income.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_self_employment_gross_income.py deleted file mode 100644 index e6e8a7ea626..00000000000 --- a/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_self_employment_gross_income.py +++ /dev/null @@ -1,12 +0,0 @@ -from policyengine_us.model_api import * - - -class ks_liheap_self_employment_gross_income(Variable): - value_type = float - entity = Person - definition_period = YEAR - unit = USD - default_value = -1 - label = "Kansas LIEAP gross self-employment receipts" - documentation = "Annual gross receipts before business expenses, including farming. A value of -1 means receipts are unavailable; the countable-income formula then uses reported net self-employment income without taking a second expense deduction." - reference = "https://content.dcf.ks.gov/ees/keesm/current/keesm13360.htm" From 00f291854ba2d6ef6d8c7b0de3b94dd589148dad Mon Sep 17 00:00:00 2001 From: Ziming Date: Tue, 29 Sep 2026 16:56:53 -0400 Subject: [PATCH 05/12] Refine Kansas LIEAP income coverage and references --- .../ks/dcf/liheap/income/sources/earned.yaml | 14 ++- .../dcf/liheap/income/sources/unearned.yaml | 16 ++- .../ks/dcf/liheap/payment/min_benefit.yaml | 12 ++- policyengine_us/programs.yaml | 2 +- .../ks_liheap_income_eligible.yaml | 102 ++++++++++-------- .../ks_liheap_countable_earned_income.yaml | 31 ++---- .../income/ks_liheap_countable_income.yaml | 46 ++++++++ ...ap_countable_interest_dividend_income.yaml | 21 ++-- .../gov/states/ks/dcf/liheap/ks_liheap.yaml | 5 +- .../ks/dcf/liheap/review_regressions.yaml | 12 ++- .../gov/states/ks/dcf/liheap/vectorized.yaml | 85 +++++++-------- .../ks_liheap_countable_earned_income.py | 5 +- 12 files changed, 209 insertions(+), 142 deletions(-) diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/earned.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/earned.yaml index 1630f12b527..9330ded4590 100644 --- a/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/earned.yaml +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/earned.yaml @@ -14,9 +14,17 @@ metadata: period: year label: Kansas LIEAP countable earned income sources reference: - - title: KEESM 13360 Income Eligibility, January 2026 edition (self-employment expense rule approximated using existing net income) + - title: KEESM 13360 Income Eligibility, October 2024 edition (countable income includes earnings by adults; self-employment income paragraph) + href: https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13360.htm + - title: KEESM 13360 Income Eligibility, January 2026 edition (countable income includes earnings by adults; self-employment income paragraph) href: https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13360.htm + - title: KEESM 7122.1 Income Producing Cost Deduction, October 2024 edition (a loss from self-employment cannot be deducted from other income) + href: https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm7122.htm + - title: KEESM 7122.1 Income Producing Cost Deduction, January 2026 edition (a loss from self-employment cannot be deducted from other income) + href: https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm7122.htm - title: Kansas LIHEAP FY2026 State Plan, Section 1.8-1.9 (gross income; wages, self-employment income, contract income and commissions counted) href: https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=6 - - title: KEESM 13320 Household Definition (income of all household members living together is used) - href: https://content.dcf.ks.gov/ees/keesm/current/keesm13300.htm + - title: KEESM 13320 Household Definition, October 2024 edition (income of all household members living together is used) + href: https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13300.htm + - title: KEESM 13320 Household Definition, January 2026 edition (income of all household members living together is used) + href: https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13300.htm diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/unearned.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/unearned.yaml index 775c6f81305..0644e2fb401 100644 --- a/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/unearned.yaml +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/unearned.yaml @@ -14,12 +14,16 @@ values: - child_support_received # Plan counts "insurance payments made directly to the insured". - workers_compensation + # KEESM 13361 exempts only the incomes it lists; employer disability benefits are not among them. + - disability_benefits - veterans_benefits - ks_liheap_countable_interest_dividend_income # KEESM 13360-13361 explicitly count interest except for specific # exemptions; the plan's unchecked combined interest/dividend/royalty # box is not a blanket exclusion. Other irregular receipts and source- # specific exclusions require a direct countable-income input. + # Contract or mortgage payments, legal settlements and adoption support + # have no model input and also require a direct countable-income input. metadata: unit: list @@ -28,7 +32,11 @@ metadata: reference: - title: Kansas LIHEAP FY2026 State Plan, Section 1.9 (countable income sources) href: https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=6 - - title: KEESM 13360-13361 (countable income and specific exemptions) - href: https://content.dcf.ks.gov/ees/keesm/current/keesm13360.htm - - title: KEESM 13320 Household Definition (income of all household members living together is used) - href: https://content.dcf.ks.gov/ees/keesm/current/keesm13300.htm + - title: KEESM 13360-13361, October 2024 edition (countable income and specific exemptions) + href: https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13360.htm + - title: KEESM 13360-13361, January 2026 edition (countable income and specific exemptions) + href: https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13360.htm + - title: KEESM 13320 Household Definition, October 2024 edition (income of all household members living together is used) + href: https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13300.htm + - title: KEESM 13320 Household Definition, January 2026 edition (income of all household members living together is used) + href: https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13300.htm diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/min_benefit.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/min_benefit.yaml index fd94c628a6f..2d10071815c 100644 --- a/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/min_benefit.yaml +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/min_benefit.yaml @@ -1,6 +1,14 @@ description: Kansas pays at least this annual benefit to eligible households under the Low Income Energy Assistance Program. -# The state plans also report a maximum benefit ($2,232 for FY2025, $4,301 for -# FY2026) that is at least every matrix cell in its year, so an additional cap cannot bind. +# Plan Section 2.6 reports a minimum and maximum benefit of $100 and $2,232 +# for FY2025 and $130 and $4,301 for FY2026. The FY2025 figures equal the +# FY2025 matrix minimum and maximum. The FY2026 matrix's adjusted 80% column +# ("Benefit Adjustment @ 80%") ranges from $75 to $1,682. Applying the plan's +# $130 floor yields $130 to $1,682. Cells below a separately applied minimum +# do not by themselves establish a schedule error. The plan's estimated +# $4,301 maximum remains unexplained by either the adjusted matrix or its +# $2,102 unadjusted maximum. No adjustment is inferred from that difference. +# Each plan's maximum exceeds or equals every selected matrix cell, so a cap +# at that amount cannot bind. values: 2024-10-01: 100 2025-10-01: 130 diff --git a/policyengine_us/programs.yaml b/policyengine_us/programs.yaml index b3c47d276e7..5da9cb35992 100644 --- a/policyengine_us/programs.yaml +++ b/policyengine_us/programs.yaml @@ -830,7 +830,7 @@ programs: variable: ks_liheap parameter_prefix: gov.states.ks.dcf.liheap verified_years: "2025-2026" - notes: Models regular heating assistance using FY2025 and FY2026 benefit matrices and published income limits. Annual income approximates the application month; the SPM unit approximates the energy household. Utility tier defaults to E and dwelling type to house/mobile. Gross self-employment receipts and allowable costs enable the expense deduction; otherwise net earnings are a fallback. Special energy-vulnerability cases require a direct input. Some irregular receipts and source-specific income exemptions are not modeled. Cooling, crisis, weatherization, and equipment assistance are outside scope. + notes: Models regular heating assistance using FY2025 and FY2026 benefit matrices and income limits derived from 150% of the prior year's federal poverty guidelines, which reproduce the published limits. Annual income approximates the application month; the SPM unit approximates the energy household. Utility tier defaults to E and dwelling type to house/mobile. Self-employment income uses existing net income with each source floored at zero; the 25% standard expense deduction is not modeled. Special energy-vulnerability cases require a direct input. Some irregular receipts and source-specific income exemptions are not modeled. Cooling, crisis, weatherization, and equipment assistance are outside scope. - state: TX status: partial name: Texas CEAP diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_eligible.yaml index 7e147797ccb..6908b8d8bb7 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_eligible.yaml @@ -1,137 +1,149 @@ # KEESM 13360-13362, October 2024 and January 2026 editions. # Values annualize the published monthly limits; FY2026 includes rounding. -- name: 2025 household size 1, income 0 dollar above the published limit. +- name: Case 1, 2025 household size 1, income 0 dollar above the published limit. period: 2025 + absolute_error_margin: 0.01 input: state_code: KS ks_liheap_household_size: 1 - ks_liheap_countable_income: 22590 + ks_liheap_countable_income: 22_590 output: - ks_liheap_income_limit: 22590 + ks_liheap_income_limit: 22_590 ks_liheap_income_eligible: true -- name: 2025 household size 1, income 1 dollar above the published limit. +- name: Case 2, 2025 household size 1, income 1 dollar above the published limit. period: 2025 + absolute_error_margin: 0.01 input: state_code: KS ks_liheap_household_size: 1 - ks_liheap_countable_income: 22591 + ks_liheap_countable_income: 22_591 output: - ks_liheap_income_limit: 22590 + ks_liheap_income_limit: 22_590 ks_liheap_income_eligible: false -- name: 2025 household size 4, income 0 dollar above the published limit. +- name: Case 3, 2025 household size 4, income 0 dollar above the published limit. period: 2025 + absolute_error_margin: 0.01 input: state_code: KS ks_liheap_household_size: 4 - ks_liheap_countable_income: 46800 + ks_liheap_countable_income: 46_800 output: - ks_liheap_income_limit: 46800 + ks_liheap_income_limit: 46_800 ks_liheap_income_eligible: true -- name: 2025 household size 4, income 1 dollar above the published limit. +- name: Case 4, 2025 household size 4, income 1 dollar above the published limit. period: 2025 + absolute_error_margin: 0.01 input: state_code: KS ks_liheap_household_size: 4 - ks_liheap_countable_income: 46801 + ks_liheap_countable_income: 46_801 output: - ks_liheap_income_limit: 46800 + ks_liheap_income_limit: 46_800 ks_liheap_income_eligible: false -- name: 2026 household size 1, income 0 dollar above the published limit. +- name: Case 5, 2026 household size 1, income 0 dollar above the published limit. period: 2026 + absolute_error_margin: 0.01 input: state_code: KS ks_liheap_household_size: 1 - ks_liheap_countable_income: 23472 + ks_liheap_countable_income: 23_472 output: - ks_liheap_income_limit: 23472 + ks_liheap_income_limit: 23_472 ks_liheap_income_eligible: true -- name: 2026 household size 1, income 1 dollar above the published limit. +- name: Case 6, 2026 household size 1, income 1 dollar above the published limit. period: 2026 + absolute_error_margin: 0.01 input: state_code: KS ks_liheap_household_size: 1 - ks_liheap_countable_income: 23473 + ks_liheap_countable_income: 23_473 output: - ks_liheap_income_limit: 23472 + ks_liheap_income_limit: 23_472 ks_liheap_income_eligible: false -- name: 2026 household size 4, income 0 dollar above the published limit. +- name: Case 7, 2026 household size 4, income 0 dollar above the published limit. period: 2026 + absolute_error_margin: 0.01 input: state_code: KS ks_liheap_household_size: 4 - ks_liheap_countable_income: 48228 + ks_liheap_countable_income: 48_228 output: - ks_liheap_income_limit: 48228 + ks_liheap_income_limit: 48_228 ks_liheap_income_eligible: true -- name: 2026 household size 4, income 1 dollar above the published limit. +- name: Case 8, 2026 household size 4, income 1 dollar above the published limit. period: 2026 + absolute_error_margin: 0.01 input: state_code: KS ks_liheap_household_size: 4 - ks_liheap_countable_income: 48229 + ks_liheap_countable_income: 48_229 output: - ks_liheap_income_limit: 48228 + ks_liheap_income_limit: 48_228 ks_liheap_income_eligible: false -- name: 2026 household size 9, income 0 dollar above the published limit. +- name: Case 9, 2026 household size 9, income 0 dollar above the published limit. period: 2026 + absolute_error_margin: 0.01 input: state_code: KS ks_liheap_household_size: 9 - ks_liheap_countable_income: 89484 + ks_liheap_countable_income: 89_484 output: - ks_liheap_income_limit: 89484 + ks_liheap_income_limit: 89_484 ks_liheap_income_eligible: true -- name: 2026 household size 9, income 1 dollar above the published limit. +- name: Case 10, 2026 household size 9, income 1 dollar above the published limit. period: 2026 + absolute_error_margin: 0.01 input: state_code: KS ks_liheap_household_size: 9 - ks_liheap_countable_income: 89485 + ks_liheap_countable_income: 89_485 output: - ks_liheap_income_limit: 89484 + ks_liheap_income_limit: 89_484 ks_liheap_income_eligible: false -- name: 2026 household size 10, income 0 dollar above the published limit. +- name: Case 11, 2026 household size 10, income 0 dollar above the published limit. period: 2026 + absolute_error_margin: 0.01 input: state_code: KS ks_liheap_household_size: 10 - ks_liheap_countable_income: 97740 + ks_liheap_countable_income: 97_740 output: - ks_liheap_income_limit: 97740 + ks_liheap_income_limit: 97_740 ks_liheap_income_eligible: true -- name: 2026 household size 10, income 1 dollar above the published limit. +- name: Case 12, 2026 household size 10, income 1 dollar above the published limit. period: 2026 + absolute_error_margin: 0.01 input: state_code: KS ks_liheap_household_size: 10 - ks_liheap_countable_income: 97741 + ks_liheap_countable_income: 97_741 output: - ks_liheap_income_limit: 97740 + ks_liheap_income_limit: 97_740 ks_liheap_income_eligible: false -- name: snap receipt does not waive the household income limit. +- name: Case 13, snap receipt does not waive the household income limit. period: 2026 input: state_code: KS ks_liheap_household_size: 2 - ks_liheap_countable_income: 40000 - snap: 1200 + ks_liheap_countable_income: 40_000 + snap: 1_200 output: ks_liheap_income_eligible: false -- name: ssi receipt does not waive the household income limit. +- name: Case 14, ssi receipt does not waive the household income limit. period: 2026 input: state_code: KS ks_liheap_household_size: 2 - ks_liheap_countable_income: 40000 - ssi: 1200 + ks_liheap_countable_income: 40_000 + ssi: 1_200 output: ks_liheap_income_eligible: false -- name: ks_tanf receipt does not waive the household income limit. +- name: Case 15, ks_tanf receipt does not waive the household income limit. period: 2026 input: state_code: KS ks_liheap_household_size: 2 - ks_liheap_countable_income: 40000 - ks_tanf: 1200 + ks_liheap_countable_income: 40_000 + ks_tanf: 1_200 output: ks_liheap_income_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_earned_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_earned_income.yaml index 6bcdb8bff8e..b8e5ece3fdd 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_earned_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_earned_income.yaml @@ -107,16 +107,17 @@ - name: Case 6, FY2025 reported net business income receives no additional deduction. period: 2025 + absolute_error_margin: 0.01 input: state_code: KS age: 40 self_employment_income: 24_000 output: ks_liheap_countable_earned_income: 24_000 - self_employment_income: 24_000 - name: Case 7, FY2026 includes regular, SSTB, and farm net income alongside wages. period: 2026 + absolute_error_margin: 0.01 input: state_code: KS age: 40 @@ -131,6 +132,7 @@ - name: Case 8, a farm loss does not offset wages or other positive business income. period: 2026 + absolute_error_margin: 0.01 input: state_code: KS age: 40 @@ -140,10 +142,10 @@ farm_operations_income: -15_000 output: ks_liheap_countable_earned_income: 22_000 - farm_operations_income: -15_000 - name: Case 9, an adult with only business losses has no countable earnings. period: 2026 + absolute_error_margin: 0.01 input: state_code: KS age: 40 @@ -155,43 +157,30 @@ - name: Case 10, child business income is excluded and adult losses do not affect other people. period: 2026 + absolute_error_margin: 0.01 input: people: - parent: + person1: age: 40 employment_income: 12_000 self_employment_income: -4_000 - child: + person2: age: 17 employment_income: 5_000 self_employment_income: 4_000 sstb_self_employment_income: 3_000 farm_operations_income: 2_000 - adult_child: + person3: age: 18 self_employment_income: 6_000 spm_units: spm_unit: - members: [parent, child, adult_child] + members: [person1, person2, person3] ks_tanf: 0 households: household: - members: [parent, child, adult_child] + members: [person1, person2, person3] state_code: KS output: ks_liheap_countable_earned_income: [12_000, 0, 6_000] ks_liheap_countable_income: 18_000 - self_employment_income: [-4_000, 4_000, 6_000] - -- name: Case 11, an explicitly supplied Kansas countable amount overrides the net approximation. - period: 2026 - input: - state_code: KS - age: 40 - self_employment_income: 5_000 - # Known gross receipts of 24,000 less the 25% standard expense deduction. - ks_liheap_countable_earned_income: 18_000 - ks_tanf: 0 - output: - ks_liheap_countable_income: 18_000 - self_employment_income: 5_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_income.yaml index fb40dfccb45..fb37ff1fabc 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_income.yaml @@ -189,3 +189,49 @@ output: # KEESM 13330: income from non-qualified members is counted -> 18,000. ks_liheap_countable_income: 18_000 + +- name: Case 9, countable earned income supplied by the caller is used as given. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + self_employment_income: 5_000 + # The caller supplies the countable earned income amount. + ks_liheap_countable_earned_income: 18_000 + spm_units: + spm_unit: + members: [person1] + ks_tanf: 0 + households: + household: + members: [person1] + state_code: KS + output: + # 18,000 supplied countable earned income + 0 unearned income = 18,000. + ks_liheap_countable_income: 18_000 + +- name: Case 10, employer disability benefits are counted as unearned income. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 52 + # Example amount: 1,200 a month of employer disability benefits. + disability_benefits: 14_400 + spm_units: + spm_unit: + members: [person1] + ks_tanf: 0 + households: + household: + members: [person1] + state_code: KS + output: + # disability_benefits is in the unearned source list: 1,200 x 12 = 14,400; + # every other listed source is 0. + ks_liheap_countable_unearned_income: 14_400 + # 0 earned income + 14,400 unearned income = 14,400. + ks_liheap_countable_income: 14_400 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_interest_dividend_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_interest_dividend_income.yaml index 0bef061387b..c9d4b6ab5c9 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_interest_dividend_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_interest_dividend_income.yaml @@ -1,6 +1,7 @@ # KEESM 13361: child interest exclusion and year-specific interest exemptions. -- name: FY2025 exactly at monthly exemption +- name: Case 1, FY2025 exactly at monthly exemption. period: 2025 + absolute_error_margin: 0.01 input: state_code: KS age: 40 @@ -8,8 +9,9 @@ dividend_income: 240 output: ks_liheap_countable_interest_dividend_income: 0 -- name: FY2025 above exemption counts the full amount +- name: Case 2, FY2025 above exemption counts the full amount. period: 2025 + absolute_error_margin: 0.01 input: state_code: KS age: 40 @@ -17,8 +19,9 @@ dividend_income: 240 output: ks_liheap_countable_interest_dividend_income: 601 -- name: FY2026 regular small interest has no blanket exemption +- name: Case 3, FY2026 regular small interest has no blanket exemption. period: 2026 + absolute_error_margin: 0.01 input: state_code: KS age: 40 @@ -26,21 +29,23 @@ dividend_income: 0 output: ks_liheap_countable_interest_dividend_income: 120 -- name: FY2026 interest of a 17-year-old is exempt but dividends count +- name: Case 4, FY2026 interest of a 17-year-old is exempt but dividends count. period: 2026 + absolute_error_margin: 0.01 input: state_code: KS age: 17 - interest_income: 1000 + interest_income: 1_000 dividend_income: 300 output: ks_liheap_countable_interest_dividend_income: 300 -- name: FY2026 interest counts at age 18 +- name: Case 5, FY2026 interest counts at age 18. period: 2026 + absolute_error_margin: 0.01 input: state_code: KS age: 18 - interest_income: 1000 + interest_income: 1_000 dividend_income: 300 output: - ks_liheap_countable_interest_dividend_income: 1300 + ks_liheap_countable_interest_dividend_income: 1_300 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/ks_liheap.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/ks_liheap.yaml index f0686076874..fe36dcbdab9 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/ks_liheap.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/ks_liheap.yaml @@ -225,8 +225,9 @@ members: [person1] state_code: KS output: - # Negative gross income is in the 0-899 band: matrix p.1 (80%) tier E, - # House, size 1-4 = 709, the same as zero income. + # The business loss is floored at zero in countable earned income, so + # countable income is 0 and the household falls in the lowest income band + # (0-899): matrix p.1 (80%) tier E, House, size 1-4 = 709. ks_liheap: 709 - name: Case 10, FY2025 season pays the 100 percent value. diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/review_regressions.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/review_regressions.yaml index c8e35532935..c46bd8dc168 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/review_regressions.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/review_regressions.yaml @@ -2,7 +2,7 @@ # KEESM 13361(29)-(30): only specified interest/dividend income is exempt. # KEESM 13340: heating equipment alone does not establish fuel responsibility. # KEESM 13362: FY2026 uses the published monthly limits, including rounding. -- name: SNAP receipt does not exempt an over-income household from the income test. +- name: Case 1, SNAP receipt does not exempt an over-income household from the income test. period: 2026 input: state_code: KS @@ -13,8 +13,9 @@ output: ks_liheap_income_eligible: false -- name: Regular adult interest and dividends count toward household income. +- name: Case 2, regular adult interest and dividends count toward household income. period: 2026 + absolute_error_margin: 0.01 input: state_code: KS age: 40 @@ -25,8 +26,9 @@ output: ks_liheap_countable_income: 25_000 -- name: A household gathering its own wood has no purchased heating costs. +- name: Case 3, a household gathering its own wood has no purchased heating costs. period: 2026 + absolute_error_margin: 0.01 input: state_code: KS age: 40 @@ -38,7 +40,7 @@ ks_liheap_eligible: false ks_liheap: 0 -- name: FY2026 one-person income above the published monthly limit is ineligible. +- name: Case 4, FY2026 one-person income above the published monthly limit is ineligible. period: 2026 input: state_code: KS @@ -51,7 +53,7 @@ output: ks_liheap_income_eligible: false -- name: FY2026 four-person household exactly at the published monthly limit qualifies. +- name: Case 5, FY2026 four-person household exactly at the published monthly limit qualifies. period: 2026 input: state_code: KS diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/vectorized.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/vectorized.yaml index 3e231aa4f51..04aaf608e62 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/vectorized.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/vectorized.yaml @@ -1,115 +1,102 @@ # Published FY2026 adjusted matrix cells (pages 1-4) and KEESM 13340/13362. # Seven SPM units evaluate mixed inputs and a non-Kansas mask together. -- name: Mixed households evaluate Kansas LIEAP in one vectorized simulation. +- name: Case 1, mixed households evaluate Kansas LIEAP in one vectorized simulation. period: 2026 + absolute_error_margin: 0.01 input: people: - gas: + person1: age: 40 - employment_income: 9600 - electric: + employment_income: 9_600 + person2: age: 40 - employment_income: 22000 - propane: + employment_income: 22_000 + person3: age: 40 - employment_income: 21600 - wood: + employment_income: 21_600 + person4: age: 40 - employment_income: 12000 - over_limit: + employment_income: 12_000 + person5: age: 40 - employment_income: 30000 - free_wood: + employment_income: 30_000 + person6: age: 40 - employment_income: 12000 - missouri: + employment_income: 12_000 + person7: age: 40 - employment_income: 9600 + employment_income: 9_600 spm_units: gas: - members: - - gas + members: [person1] heating_type: NATURAL_GAS - gas_expense: 1200 + gas_expense: 1_200 ks_liheap_utility_rate_tier: E ks_liheap_dwelling_type: HOUSE_MODULAR_MOBILE ks_tanf: 0 electric: - members: - - electric + members: [person2] heating_type: ELECTRICITY - pre_subsidy_electricity_expense: 1200 + pre_subsidy_electricity_expense: 1_200 ks_liheap_utility_rate_tier: E ks_liheap_dwelling_type: APARTMENT ks_tanf: 0 propane: - members: - - propane + members: [person3] heating_type: PROPANE - bottled_gas_expense: 1200 + bottled_gas_expense: 1_200 ks_liheap_utility_rate_tier: A ks_liheap_dwelling_type: TRAILER_OTHER ks_tanf: 0 wood: - members: - - wood + members: [person4] heating_type: WOOD - wood_expense: 1200 + wood_expense: 1_200 ks_liheap_utility_rate_tier: J ks_liheap_dwelling_type: DUPLEX ks_tanf: 0 over_limit: - members: - - over_limit + members: [person5] heating_type: NATURAL_GAS - gas_expense: 1200 + gas_expense: 1_200 ks_liheap_utility_rate_tier: B ks_liheap_dwelling_type: DUPLEX ks_tanf: 0 free_wood: - members: - - free_wood + members: [person6] heating_type: WOOD wood_expense: 0 ks_liheap_utility_rate_tier: A ks_liheap_dwelling_type: HOUSE_MODULAR_MOBILE ks_tanf: 0 missouri: - members: - - missouri + members: [person7] heating_type: NATURAL_GAS - gas_expense: 1200 + gas_expense: 1_200 ks_liheap_utility_rate_tier: E ks_liheap_dwelling_type: HOUSE_MODULAR_MOBILE ks_tanf: 0 households: gas: - members: - - gas + members: [person1] state_code: KS electric: - members: - - electric + members: [person2] state_code: KS propane: - members: - - propane + members: [person3] state_code: KS wood: - members: - - wood + members: [person4] state_code: KS over_limit: - members: - - over_limit + members: [person5] state_code: KS free_wood: - members: - - free_wood + members: [person6] state_code: KS missouri: - members: - - missouri + members: [person7] state_code: MO output: spm_units: diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_earned_income.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_earned_income.py index 950f41d50d6..bb9ccc36ee0 100644 --- a/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_earned_income.py +++ b/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_earned_income.py @@ -20,8 +20,9 @@ class ks_liheap_countable_earned_income(Variable): reference = ( "https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13360.htm", "https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13360.htm", - "https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=6", - "https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=7", + "https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm7122.htm", + "https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm7122.htm", + "https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=6,7", ) defined_for = StateCode.KS From 0ddd84ba368be94f317247af80a32b2771bb02ec Mon Sep 17 00:00:00 2001 From: Ziming Date: Wed, 30 Sep 2026 14:41:43 -0400 Subject: [PATCH 06/12] Consolidate Kansas LIEAP tests Fold the mixed-state vectorized case into ks_liheap.yaml, drop the review_regressions file and the boundary and lookup cases that duplicated coverage held elsewhere, and assert eligibility alongside the zero benefit where a case exercises an ineligibility gate. Co-Authored-By: Claude Fable 5.1 --- .../eligibility/ks_liheap_eligible.yaml | 102 ------- .../ks_liheap_income_eligible.yaml | 68 +---- .../ks_liheap_countable_earned_income.yaml | 43 +-- .../income/ks_liheap_countable_income.yaml | 45 --- .../gov/states/ks/dcf/liheap/ks_liheap.yaml | 283 +++++++----------- .../payment/ks_liheap_matrix_amount.yaml | 51 ---- .../ks/dcf/liheap/review_regressions.yaml | 67 ----- .../gov/states/ks/dcf/liheap/vectorized.yaml | 116 ------- 8 files changed, 119 insertions(+), 656 deletions(-) delete mode 100644 policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/review_regressions.yaml delete mode 100644 policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/vectorized.yaml diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_eligible.yaml index ab4ee9e7488..81d865702d2 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_eligible.yaml @@ -6,25 +6,6 @@ # (KEESM 13340; KS LIHEAP State Plan FY2026 2.3, #page=8). No asset test # (plan 2.3). -- name: Case 1, low-income Kansas household paying for natural gas is eligible. - period: 2026 - input: - people: - person1: - age: 40 - employment_income: 15_000 - spm_units: - spm_unit: - members: [person1] - heating_type: NATURAL_GAS - gas_expense: 1_200 - households: - household: - members: [person1] - state_code: KS - output: - ks_liheap_eligible: true - - name: Case 2, the same household in Missouri is not eligible. period: 2026 input: @@ -44,24 +25,6 @@ output: ks_liheap_eligible: false -- name: Case 3, a home with no heating is not energy vulnerable. - period: 2026 - input: - people: - person1: - age: 40 - employment_income: 15_000 - spm_units: - spm_unit: - members: [person1] - heating_type: NONE - households: - household: - members: [person1] - state_code: KS - output: - ks_liheap_eligible: false - - name: Case 4, household with no citizen or qualified member is not eligible. period: 2026 input: @@ -111,27 +74,6 @@ # 12,000 (the parent's income counts). ks_liheap_eligible: true -- name: Case 6, subsidized-housing renter with heat included in rent is not eligible. - period: 2026 - input: - people: - person1: - age: 40 - employment_income: 15_000 - spm_units: - spm_unit: - members: [person1] - heating_type: NATURAL_GAS - gas_expense: 1_200 - receives_housing_assistance: true - heat_expense_included_in_rent: true - households: - household: - members: [person1] - state_code: KS - output: - ks_liheap_eligible: false - - name: Case 7, subsidized-housing renter who pays heat separately is eligible. period: 2026 input: @@ -154,50 +96,6 @@ # KEESM 13340: pays heating costs directly to a utility -> vulnerable. ks_liheap_eligible: true -- name: Case 8, unsubsidized renter with heat included in rent is eligible. - period: 2026 - input: - people: - person1: - age: 40 - employment_income: 15_000 - spm_units: - spm_unit: - members: [person1] - heating_type: NATURAL_GAS - gas_expense: 1_200 - receives_housing_assistance: false - heat_expense_included_in_rent: true - households: - household: - members: [person1] - state_code: KS - output: - # KEESM 13340: paying the landlord for fuel included in rent qualifies. - ks_liheap_eligible: true - -- name: Case 9, household over the income limit is not eligible. - period: 2026 - input: - people: - person1: - age: 40 - employment_income: 30_000 - spm_units: - spm_unit: - members: [person1] - heating_type: NATURAL_GAS - gas_expense: 1_200 - snap: 0 - ks_tanf: 0 - households: - household: - members: [person1] - state_code: KS - output: - # 30,000 > 23,472 and no categorical route. - ks_liheap_eligible: false - - name: Case 10, no asset test so large savings do not disqualify. period: 2026 input: diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_eligible.yaml index 6908b8d8bb7..8aa82bbfebd 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_eligible.yaml @@ -10,6 +10,7 @@ output: ks_liheap_income_limit: 22_590 ks_liheap_income_eligible: true + - name: Case 2, 2025 household size 1, income 1 dollar above the published limit. period: 2025 absolute_error_margin: 0.01 @@ -20,26 +21,7 @@ output: ks_liheap_income_limit: 22_590 ks_liheap_income_eligible: false -- name: Case 3, 2025 household size 4, income 0 dollar above the published limit. - period: 2025 - absolute_error_margin: 0.01 - input: - state_code: KS - ks_liheap_household_size: 4 - ks_liheap_countable_income: 46_800 - output: - ks_liheap_income_limit: 46_800 - ks_liheap_income_eligible: true -- name: Case 4, 2025 household size 4, income 1 dollar above the published limit. - period: 2025 - absolute_error_margin: 0.01 - input: - state_code: KS - ks_liheap_household_size: 4 - ks_liheap_countable_income: 46_801 - output: - ks_liheap_income_limit: 46_800 - ks_liheap_income_eligible: false + - name: Case 5, 2026 household size 1, income 0 dollar above the published limit. period: 2026 absolute_error_margin: 0.01 @@ -50,6 +32,7 @@ output: ks_liheap_income_limit: 23_472 ks_liheap_income_eligible: true + - name: Case 6, 2026 household size 1, income 1 dollar above the published limit. period: 2026 absolute_error_margin: 0.01 @@ -60,26 +43,7 @@ output: ks_liheap_income_limit: 23_472 ks_liheap_income_eligible: false -- name: Case 7, 2026 household size 4, income 0 dollar above the published limit. - period: 2026 - absolute_error_margin: 0.01 - input: - state_code: KS - ks_liheap_household_size: 4 - ks_liheap_countable_income: 48_228 - output: - ks_liheap_income_limit: 48_228 - ks_liheap_income_eligible: true -- name: Case 8, 2026 household size 4, income 1 dollar above the published limit. - period: 2026 - absolute_error_margin: 0.01 - input: - state_code: KS - ks_liheap_household_size: 4 - ks_liheap_countable_income: 48_229 - output: - ks_liheap_income_limit: 48_228 - ks_liheap_income_eligible: false + - name: Case 9, 2026 household size 9, income 0 dollar above the published limit. period: 2026 absolute_error_margin: 0.01 @@ -90,6 +54,7 @@ output: ks_liheap_income_limit: 89_484 ks_liheap_income_eligible: true + - name: Case 10, 2026 household size 9, income 1 dollar above the published limit. period: 2026 absolute_error_margin: 0.01 @@ -100,26 +65,7 @@ output: ks_liheap_income_limit: 89_484 ks_liheap_income_eligible: false -- name: Case 11, 2026 household size 10, income 0 dollar above the published limit. - period: 2026 - absolute_error_margin: 0.01 - input: - state_code: KS - ks_liheap_household_size: 10 - ks_liheap_countable_income: 97_740 - output: - ks_liheap_income_limit: 97_740 - ks_liheap_income_eligible: true -- name: Case 12, 2026 household size 10, income 1 dollar above the published limit. - period: 2026 - absolute_error_margin: 0.01 - input: - state_code: KS - ks_liheap_household_size: 10 - ks_liheap_countable_income: 97_741 - output: - ks_liheap_income_limit: 97_740 - ks_liheap_income_eligible: false + - name: Case 13, snap receipt does not waive the household income limit. period: 2026 input: @@ -129,6 +75,7 @@ snap: 1_200 output: ks_liheap_income_eligible: false + - name: Case 14, ssi receipt does not waive the household income limit. period: 2026 input: @@ -138,6 +85,7 @@ ssi: 1_200 output: ks_liheap_income_eligible: false + - name: Case 15, ks_tanf receipt does not waive the household income limit. period: 2026 input: diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_earned_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_earned_income.yaml index b8e5ece3fdd..420b963547b 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_earned_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_earned_income.yaml @@ -23,48 +23,6 @@ output: ks_liheap_countable_earned_income: 24_000 -- name: Case 2, wages and self-employment income are both earned income. - period: 2026 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 40 - employment_income: 15_000 - self_employment_income: 4_000 - spm_units: - spm_unit: - members: [person1] - households: - household: - members: [person1] - state_code: KS - output: - # 15,000 + 4,000 - ks_liheap_countable_earned_income: 19_000 - -- name: Case 3, a 17-year-old's wages are excluded while the parent's count. - period: 2026 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 42 - employment_income: 18_000 - person2: - age: 17 - employment_income: 5_000 - spm_units: - spm_unit: - members: [person1, person2] - ks_tanf: 0 - households: - household: - members: [person1, person2] - state_code: KS - output: - ks_liheap_countable_earned_income: [18_000, 0] - - name: Case 4, an 18-year-old's wages are counted. period: 2026 absolute_error_margin: 0.01 @@ -85,6 +43,7 @@ state_code: KS output: ks_liheap_countable_earned_income: [18_000, 5_000] + ks_liheap_countable_income: 23_000 - name: Case 5, unearned income is not part of earned income. period: 2026 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_income.yaml index fb37ff1fabc..23ce1e1820e 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_income.yaml @@ -27,29 +27,6 @@ # 20,000 wages + 3,000 interest + 2,000 dividends (KEESM 13360). ks_liheap_countable_income: 25_000 -- name: Case 2, earned income of a child under 18 is not counted. - period: 2026 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 42 - employment_income: 18_000 - person2: - age: 16 - employment_income: 5_000 - spm_units: - spm_unit: - members: [person1, person2] - ks_tanf: 0 - households: - household: - members: [person1, person2] - state_code: KS - output: - # 18,000 parent wages; the 16-year-old's 5,000 wages are excluded. - ks_liheap_countable_income: 18_000 - - name: Case 3, Social Security and SSI are counted. period: 2026 absolute_error_margin: 0.01 @@ -70,28 +47,6 @@ # 12,000 SSA + 3,000 SSI = 15,000 (plan 1.8: SSA and SSI checked). ks_liheap_countable_income: 15_000 -- name: Case 4, an 18-year-old member's earnings are counted. - period: 2026 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 45 - employment_income: 18_000 - person2: - age: 18 - employment_income: 5_000 - spm_units: - spm_unit: - members: [person1, person2] - households: - household: - members: [person1, person2] - state_code: KS - output: - # KEESM 13320: a member who is 18 has countable income -> 18,000 + 5,000. - ks_liheap_countable_income: 23_000 - - name: Case 5, unearned income of a child under 18 is still counted. period: 2026 absolute_error_margin: 0.01 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/ks_liheap.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/ks_liheap.yaml index fe36dcbdab9..83656fab819 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/ks_liheap.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/ks_liheap.yaml @@ -5,77 +5,6 @@ # minimum is $100 (KS LIHEAP State Plan FY2025 2.6, #page=9). Zero when # ineligible. -- name: Case 1, eligible natural gas household receives the matrix cell. - period: 2026 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 40 - employment_income: 9_600 - spm_units: - spm_unit: - members: [person1] - heating_type: NATURAL_GAS - gas_expense: 1_200 - ks_liheap_utility_rate_tier: E - ks_liheap_dwelling_type: HOUSE_MODULAR_MOBILE - households: - household: - members: [person1] - state_code: KS - output: - # 800/mo -> 0-899; matrix p.1 (80%) tier E, House, size 1-4 = 709 >= 130 - ks_liheap: 709 - -- name: Case 2, propane trailer cell of 75 is raised to the 130 minimum. - period: 2026 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 40 - employment_income: 21_600 - spm_units: - spm_unit: - members: [person1] - heating_type: PROPANE - bottled_gas_expense: 1_200 - ks_liheap_utility_rate_tier: A - ks_liheap_dwelling_type: TRAILER_OTHER - households: - household: - members: [person1] - state_code: KS - output: - # 1,800/mo -> 1,700 & over; matrix p.3 (80%) tier A, Trailer/Other, - # size 1-4 = 75; max(75, 130) = 130 (plan 2.6 minimum benefit) - ks_liheap: 130 - -- name: Case 3, natural gas trailer cell of 84 is raised to the 130 minimum. - period: 2026 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 40 - employment_income: 21_600 - spm_units: - spm_unit: - members: [person1] - heating_type: NATURAL_GAS - gas_expense: 1_200 - ks_liheap_utility_rate_tier: A - ks_liheap_dwelling_type: TRAILER_OTHER - households: - household: - members: [person1] - state_code: KS - output: - # matrix p.1 (80%) 1,700 & over tier A, Trailer/Other, size 1-4 = 84; - # max(84, 130) = 130 - ks_liheap: 130 - - name: Case 4, other fuel trailer cell of 128 for a large family is raised to 130. period: 2026 absolute_error_margin: 0.01 @@ -158,51 +87,7 @@ members: [person1] state_code: KS output: - ks_liheap: 0 - -- name: Case 7, household over the income limit receives nothing. - period: 2026 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 40 - employment_income: 30_000 - spm_units: - spm_unit: - members: [person1] - heating_type: NATURAL_GAS - gas_expense: 1_200 - snap: 0 - ks_tanf: 0 - households: - household: - members: [person1] - state_code: KS - output: - # 30,000 > 1,956 x 12 = 23,472 - ks_liheap: 0 - -- name: Case 8, subsidized-housing renter with heat in rent receives nothing. - period: 2026 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 40 - employment_income: 9_600 - spm_units: - spm_unit: - members: [person1] - heating_type: NATURAL_GAS - gas_expense: 1_200 - receives_housing_assistance: true - heat_expense_included_in_rent: true - households: - household: - members: [person1] - state_code: KS - output: + ks_liheap_eligible: false ks_liheap: 0 - name: Case 9, negative self-employment income does not inflate the benefit. @@ -230,30 +115,36 @@ # (0-899): matrix p.1 (80%) tier E, House, size 1-4 = 709. ks_liheap: 709 -- name: Case 10, FY2025 season pays the 100 percent value. +- name: Case 13, FY2025 natural gas trailer cell of 112 is above the 100 minimum and unchanged. period: 2025 absolute_error_margin: 0.01 input: people: person1: age: 40 - employment_income: 9_600 + employment_income: 21_600 spm_units: spm_unit: members: [person1] heating_type: NATURAL_GAS gas_expense: 1_200 - ks_liheap_utility_rate_tier: E - ks_liheap_dwelling_type: HOUSE_MODULAR_MOBILE + ks_liheap_utility_rate_tier: A + ks_liheap_dwelling_type: TRAILER_OTHER + snap: 0 + ks_tanf: 0 households: household: members: [person1] state_code: KS output: - # KS_BenefitMatrix_2025.pdf p.1 (100%) 0-899 tier E, House, size 1-4 = 941 - ks_liheap: 941 + # KS_BenefitMatrix_2025.pdf p.1 (100%) 1,700 & over tier A, Trailer/Other, + # size 1-4 = 112; max(112, 100) = 112 (would be 130 under the FY2026 + # minimum, KS LIHEAP State Plan FY2025 2.6, #page=9 gives $100). + ks_liheap: 112 -- name: Case 11, household outside Kansas receives nothing. +# Published FY2026 adjusted matrix cells (pages 1-4) and KEESM 13340/13362. +# Seven SPM units evaluate mixed inputs and a non-Kansas mask together. +- name: Case 15, mixed households evaluate Kansas LIEAP in one vectorized simulation. period: 2026 absolute_error_margin: 0.01 input: @@ -261,70 +152,116 @@ person1: age: 40 employment_income: 9_600 - spm_units: - spm_unit: - members: [person1] - heating_type: NATURAL_GAS - gas_expense: 1_200 - households: - household: - members: [person1] - state_code: OK - output: - ks_liheap: 0 - -- name: Case 12, FY2025 propane trailer cell of 100 meets the 100 minimum and is paid as is. - period: 2025 - absolute_error_margin: 0.01 - input: - people: - person1: + person2: + age: 40 + employment_income: 22_000 + person3: age: 40 employment_income: 21_600 + person4: + age: 40 + employment_income: 12_000 + person5: + age: 40 + employment_income: 30_000 + person6: + age: 40 + employment_income: 12_000 + person7: + age: 40 + employment_income: 9_600 spm_units: - spm_unit: + gas: members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_200 + ks_liheap_utility_rate_tier: E + ks_liheap_dwelling_type: HOUSE_MODULAR_MOBILE + ks_tanf: 0 + electric: + members: [person2] + heating_type: ELECTRICITY + pre_subsidy_electricity_expense: 1_200 + ks_liheap_utility_rate_tier: E + ks_liheap_dwelling_type: APARTMENT + ks_tanf: 0 + propane: + members: [person3] heating_type: PROPANE bottled_gas_expense: 1_200 ks_liheap_utility_rate_tier: A ks_liheap_dwelling_type: TRAILER_OTHER - snap: 0 ks_tanf: 0 - households: - household: - members: [person1] - state_code: KS - output: - # 21,600 <= 1.5 x 15,060 = 22,590 -> eligible; 1,800/mo -> 1,700 & over; - # KS_BenefitMatrix_2025.pdf p.2 (100%) propane tier A, Trailer/Other, - # size 1-4 = 100; FY2025 minimum benefit is $100 (KS LIHEAP State Plan - # FY2025 2.6, #page=9): max(100, 100) = 100 (the FY2026 $130 floor does - # not apply to the FY2025 season). - ks_liheap: 100 - -- name: Case 13, FY2025 natural gas trailer cell of 112 is above the 100 minimum and unchanged. - period: 2025 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 40 - employment_income: 21_600 - spm_units: - spm_unit: - members: [person1] + wood: + members: [person4] + heating_type: WOOD + wood_expense: 1_200 + ks_liheap_utility_rate_tier: J + ks_liheap_dwelling_type: DUPLEX + ks_tanf: 0 + over_limit: + members: [person5] heating_type: NATURAL_GAS gas_expense: 1_200 + ks_liheap_utility_rate_tier: B + ks_liheap_dwelling_type: DUPLEX + ks_tanf: 0 + free_wood: + members: [person6] + heating_type: WOOD + wood_expense: 0 ks_liheap_utility_rate_tier: A - ks_liheap_dwelling_type: TRAILER_OTHER - snap: 0 + ks_liheap_dwelling_type: HOUSE_MODULAR_MOBILE + ks_tanf: 0 + missouri: + members: [person7] + heating_type: NATURAL_GAS + gas_expense: 1_200 + ks_liheap_utility_rate_tier: E + ks_liheap_dwelling_type: HOUSE_MODULAR_MOBILE ks_tanf: 0 households: - household: + gas: members: [person1] state_code: KS + electric: + members: [person2] + state_code: KS + propane: + members: [person3] + state_code: KS + wood: + members: [person4] + state_code: KS + over_limit: + members: [person5] + state_code: KS + free_wood: + members: [person6] + state_code: KS + missouri: + members: [person7] + state_code: MO output: - # KS_BenefitMatrix_2025.pdf p.1 (100%) 1,700 & over tier A, Trailer/Other, - # size 1-4 = 112; max(112, 100) = 112 (would be 130 under the FY2026 - # minimum, KS LIHEAP State Plan FY2025 2.6, #page=9 gives $100). - ks_liheap: 112 + spm_units: + gas: + ks_liheap_eligible: true + ks_liheap: 709 + electric: + ks_liheap_eligible: true + ks_liheap: 365 + propane: + ks_liheap_eligible: true + ks_liheap: 130 + wood: + ks_liheap_eligible: true + ks_liheap: 431 + over_limit: + ks_liheap_eligible: false + ks_liheap: 0 + free_wood: + ks_liheap_eligible: false + ks_liheap: 0 + missouri: + ks_liheap_eligible: false + ks_liheap: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/payment/ks_liheap_matrix_amount.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/payment/ks_liheap_matrix_amount.yaml index e494f7afbc4..efeba9b2407 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/payment/ks_liheap_matrix_amount.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/payment/ks_liheap_matrix_amount.yaml @@ -139,35 +139,6 @@ # matrix p.1 (80%) 0-899 tier J, House, size 1-4 = 1,136 ks_liheap_matrix_amount: 1_136 -- name: Case 7, natural gas, band 1, tier E, house, family of four uses the 1-4 column. - period: 2026 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 40 - employment_income: 9_600 - person2: - age: 38 - person3: - age: 10 - person4: - age: 6 - spm_units: - spm_unit: - members: [person1, person2, person3, person4] - ks_tanf: 0 - heating_type: NATURAL_GAS - ks_liheap_utility_rate_tier: E - ks_liheap_dwelling_type: HOUSE_MODULAR_MOBILE - households: - household: - members: [person1, person2, person3, person4] - state_code: KS - output: - # size 4 -> "Household Size 1-4": matrix p.1 (80%) 0-899 tier E, House = 709 - ks_liheap_matrix_amount: 709 - - name: Case 8, natural gas, band 1, tier E, house, family of five uses the 5+ column. period: 2026 absolute_error_margin: 0.01 @@ -374,28 +345,6 @@ # size 1-4 = 232 ks_liheap_matrix_amount: 232 -- name: Case 16, solar heating uses the electricity table. - period: 2026 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 40 - employment_income: 9_600 - spm_units: - spm_unit: - members: [person1] - heating_type: SOLAR - ks_liheap_utility_rate_tier: E - ks_liheap_dwelling_type: HOUSE_MODULAR_MOBILE - households: - household: - members: [person1] - state_code: KS - output: - # SOLAR -> electricity: matrix p.2 (80%) 0-899 tier E, House = 1,043 - ks_liheap_matrix_amount: 1_043 - - name: Case 17, propane, band 1, tier E, house. period: 2026 absolute_error_margin: 0.01 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/review_regressions.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/review_regressions.yaml deleted file mode 100644 index c46bd8dc168..00000000000 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/review_regressions.yaml +++ /dev/null @@ -1,67 +0,0 @@ -# KEESM 13360: verified SNAP/TANF income still enters the household test. -# KEESM 13361(29)-(30): only specified interest/dividend income is exempt. -# KEESM 13340: heating equipment alone does not establish fuel responsibility. -# KEESM 13362: FY2026 uses the published monthly limits, including rounding. -- name: Case 1, SNAP receipt does not exempt an over-income household from the income test. - period: 2026 - input: - state_code: KS - age: 40 - ks_liheap_household_size: 2 - ks_liheap_countable_income: 40_000 - snap: 1_200 - output: - ks_liheap_income_eligible: false - -- name: Case 2, regular adult interest and dividends count toward household income. - period: 2026 - absolute_error_margin: 0.01 - input: - state_code: KS - age: 40 - employment_income: 20_000 - interest_income: 3_000 - dividend_income: 2_000 - ks_tanf: 0 - output: - ks_liheap_countable_income: 25_000 - -- name: Case 3, a household gathering its own wood has no purchased heating costs. - period: 2026 - absolute_error_margin: 0.01 - input: - state_code: KS - age: 40 - employment_income: 15_000 - heating_type: WOOD - wood_expense: 0 - heat_expense_included_in_rent: false - output: - ks_liheap_eligible: false - ks_liheap: 0 - -- name: Case 4, FY2026 one-person income above the published monthly limit is ineligible. - period: 2026 - input: - state_code: KS - ks_liheap_household_size: 1 - # Published monthly limit is 1,956; 1,956.25 exceeds it. - ks_liheap_countable_income: 23_475 - snap: 0 - ssi: 0 - ks_tanf: 0 - output: - ks_liheap_income_eligible: false - -- name: Case 5, FY2026 four-person household exactly at the published monthly limit qualifies. - period: 2026 - input: - state_code: KS - ks_liheap_household_size: 4 - # Published monthly limit is 4,019. - ks_liheap_countable_income: 48_228 - snap: 0 - ssi: 0 - ks_tanf: 0 - output: - ks_liheap_income_eligible: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/vectorized.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/vectorized.yaml deleted file mode 100644 index 04aaf608e62..00000000000 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/vectorized.yaml +++ /dev/null @@ -1,116 +0,0 @@ -# Published FY2026 adjusted matrix cells (pages 1-4) and KEESM 13340/13362. -# Seven SPM units evaluate mixed inputs and a non-Kansas mask together. -- name: Case 1, mixed households evaluate Kansas LIEAP in one vectorized simulation. - period: 2026 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 40 - employment_income: 9_600 - person2: - age: 40 - employment_income: 22_000 - person3: - age: 40 - employment_income: 21_600 - person4: - age: 40 - employment_income: 12_000 - person5: - age: 40 - employment_income: 30_000 - person6: - age: 40 - employment_income: 12_000 - person7: - age: 40 - employment_income: 9_600 - spm_units: - gas: - members: [person1] - heating_type: NATURAL_GAS - gas_expense: 1_200 - ks_liheap_utility_rate_tier: E - ks_liheap_dwelling_type: HOUSE_MODULAR_MOBILE - ks_tanf: 0 - electric: - members: [person2] - heating_type: ELECTRICITY - pre_subsidy_electricity_expense: 1_200 - ks_liheap_utility_rate_tier: E - ks_liheap_dwelling_type: APARTMENT - ks_tanf: 0 - propane: - members: [person3] - heating_type: PROPANE - bottled_gas_expense: 1_200 - ks_liheap_utility_rate_tier: A - ks_liheap_dwelling_type: TRAILER_OTHER - ks_tanf: 0 - wood: - members: [person4] - heating_type: WOOD - wood_expense: 1_200 - ks_liheap_utility_rate_tier: J - ks_liheap_dwelling_type: DUPLEX - ks_tanf: 0 - over_limit: - members: [person5] - heating_type: NATURAL_GAS - gas_expense: 1_200 - ks_liheap_utility_rate_tier: B - ks_liheap_dwelling_type: DUPLEX - ks_tanf: 0 - free_wood: - members: [person6] - heating_type: WOOD - wood_expense: 0 - ks_liheap_utility_rate_tier: A - ks_liheap_dwelling_type: HOUSE_MODULAR_MOBILE - ks_tanf: 0 - missouri: - members: [person7] - heating_type: NATURAL_GAS - gas_expense: 1_200 - ks_liheap_utility_rate_tier: E - ks_liheap_dwelling_type: HOUSE_MODULAR_MOBILE - ks_tanf: 0 - households: - gas: - members: [person1] - state_code: KS - electric: - members: [person2] - state_code: KS - propane: - members: [person3] - state_code: KS - wood: - members: [person4] - state_code: KS - over_limit: - members: [person5] - state_code: KS - free_wood: - members: [person6] - state_code: KS - missouri: - members: [person7] - state_code: MO - output: - spm_units: - gas: - ks_liheap: 709 - electric: - ks_liheap: 365 - propane: - ks_liheap: 130 - wood: - ks_liheap: 431 - over_limit: - ks_liheap: 0 - free_wood: - ks_liheap: 0 - missouri: - ks_liheap: 0 From 4f4f63308f44ce82b97bef1f8111b19a5a1d2351 Mon Sep 17 00:00:00 2001 From: Ziming Date: Wed, 30 Sep 2026 14:49:48 -0400 Subject: [PATCH 07/12] Cite dated KEESM editions in Kansas LIEAP references Replace every undated keesm/current link in the Kansas LIEAP variables and parameters with the October 2024 and January 2026 editions, name the edition in parameter reference titles, and point the test-file headers at the same editions with combined page anchors. Co-Authored-By: Claude Fable 5.1 --- .../ks/dcf/liheap/income/earned_income_min_age.yaml | 6 ++++-- .../ks/dcf/liheap/payment/household_size_group.yaml | 6 ++++-- .../gov/states/ks/dcf/liheap/payment/income_band.yaml | 6 ++++-- .../states/ks/dcf/liheap/payment/matrix/electricity.yaml | 6 ++++-- .../states/ks/dcf/liheap/payment/matrix/natural_gas.yaml | 6 ++++-- .../gov/states/ks/dcf/liheap/payment/matrix/other.yaml | 6 ++++-- .../gov/states/ks/dcf/liheap/payment/matrix/propane.yaml | 6 ++++-- .../ks/dcf/liheap/eligibility/ks_liheap_eligible.yaml | 3 +++ .../liheap/eligibility/ks_liheap_energy_vulnerable.yaml | 3 +++ .../liheap/eligibility/ks_liheap_income_eligible.yaml | 4 +++- .../liheap/income/ks_liheap_countable_earned_income.yaml | 5 ++++- .../ks/dcf/liheap/income/ks_liheap_countable_income.yaml | 5 ++++- .../ks_liheap_countable_interest_dividend_income.yaml | 3 +++ .../baseline/gov/states/ks/dcf/liheap/integration.yaml | 5 ++++- .../baseline/gov/states/ks/dcf/liheap/ks_liheap.yaml | 9 +++++++-- .../states/ks/dcf/liheap/ks_liheap_fuel_category.yaml | 5 ++++- .../states/ks/dcf/liheap/ks_liheap_household_size.yaml | 3 +++ .../liheap/payment/ks_liheap_household_size_group.yaml | 3 +++ .../ks/dcf/liheap/payment/ks_liheap_income_band.yaml | 3 +++ .../ks/dcf/liheap/payment/ks_liheap_matrix_amount.yaml | 5 ++++- .../ks/dcf/liheap/eligibility/ks_liheap_eligible.py | 3 ++- .../liheap/eligibility/ks_liheap_energy_vulnerable.py | 5 ++++- .../dcf/liheap/eligibility/ks_liheap_income_eligible.py | 6 ++++-- .../ks/dcf/liheap/income/ks_liheap_countable_income.py | 6 ++++-- .../liheap/income/ks_liheap_countable_unearned_income.py | 3 ++- .../variables/gov/states/ks/dcf/liheap/ks_liheap.py | 3 ++- .../gov/states/ks/dcf/liheap/ks_liheap_fuel_category.py | 3 ++- .../gov/states/ks/dcf/liheap/ks_liheap_household_size.py | 5 ++++- .../ks/dcf/liheap/payment/ks_liheap_income_band.py | 3 ++- .../ks/dcf/liheap/payment/ks_liheap_matrix_amount.py | 3 ++- 30 files changed, 104 insertions(+), 34 deletions(-) diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/earned_income_min_age.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/earned_income_min_age.yaml index f2a90dcab62..363ccb85b86 100644 --- a/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/earned_income_min_age.yaml +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/earned_income_min_age.yaml @@ -9,5 +9,7 @@ metadata: reference: - title: Kansas LIHEAP FY2026 State Plan, Section 1.9 (earned income of a child under the age of 18 is not counted) href: https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=7 - - title: KEESM 13320 Household Definition (a member who is or turns eighteen in the month of application has countable income) - href: https://content.dcf.ks.gov/ees/keesm/current/keesm13300.htm + - title: KEESM 13320 Household Definition, October 2024 edition (a member who is or turns eighteen in the month of application has countable income) + href: https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13300.htm + - title: KEESM 13320 Household Definition, January 2026 edition (a member who is or turns eighteen in the month of application has countable income) + href: https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13300.htm diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/household_size_group.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/household_size_group.yaml index b92ea501c29..fd3a34c6b45 100644 --- a/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/household_size_group.yaml +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/household_size_group.yaml @@ -22,5 +22,7 @@ metadata: href: https://liheapch.acf.gov/docs/2026/benefits-matricies/KS_BenefitMatrix_2026.pdf#page=1 - title: Kansas LIEAP FY2025 Benefit Matrix href: https://liheapch.acf.gov/docs/2025/benefits-matricies/KS_BenefitMatrix_2025.pdf#page=1 - - title: KEESM 13330 Citizenship and Alienage Requirements (non-citizen members excluded from household size) - href: https://content.dcf.ks.gov/ees/keesm/current/keesm13300.htm + - title: KEESM 13330 Citizenship and Alienage Requirements, October 2024 edition (non-citizen members excluded from household size) + href: https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13300.htm + - title: KEESM 13330 Citizenship and Alienage Requirements, January 2026 edition (non-citizen members excluded from household size) + href: https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13300.htm diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/income_band.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/income_band.yaml index 7b6468117ff..0ab0fd3c079 100644 --- a/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/income_band.yaml +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/income_band.yaml @@ -28,5 +28,7 @@ metadata: href: https://liheapch.acf.gov/docs/2026/benefits-matricies/KS_BenefitMatrix_2026.pdf#page=1 - title: Kansas LIEAP FY2025 Benefit Matrix href: https://liheapch.acf.gov/docs/2025/benefits-matricies/KS_BenefitMatrix_2025.pdf#page=1 - - title: KEESM 13230 Proof of Information Requirement (gross income of the month of application) - href: https://content.dcf.ks.gov/ees/keesm/current/keesm13200.htm + - title: KEESM 13230 Proof of Information Requirement, October 2024 edition (gross income of the month of application) + href: https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13200.htm + - title: KEESM 13230 Proof of Information Requirement, January 2026 edition (gross income of the month of application) + href: https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13200.htm diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/electricity.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/electricity.yaml index e38679ad549..3f9eee0e2aa 100644 --- a/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/electricity.yaml +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/electricity.yaml @@ -1194,5 +1194,7 @@ metadata: href: https://liheapch.acf.gov/docs/2025/benefits-matricies/KS_BenefitMatrix_2025.pdf#page=1 - title: Kansas LIHEAP FY2026 State Plan, Section 2.5 (benefit variables) href: https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=9 - - title: KEESM 13410 Benefit Levels - href: https://content.dcf.ks.gov/ees/keesm/current/keesm13400.htm + - title: KEESM 13410 Benefit Levels, October 2024 edition + href: https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13400.htm + - title: KEESM 13410 Benefit Levels, January 2026 edition + href: https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13400.htm diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/natural_gas.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/natural_gas.yaml index 56e0da0332a..d99988067c0 100644 --- a/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/natural_gas.yaml +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/natural_gas.yaml @@ -1194,5 +1194,7 @@ metadata: href: https://liheapch.acf.gov/docs/2025/benefits-matricies/KS_BenefitMatrix_2025.pdf#page=1 - title: Kansas LIHEAP FY2026 State Plan, Section 2.5 (benefit variables) href: https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=9 - - title: KEESM 13410 Benefit Levels - href: https://content.dcf.ks.gov/ees/keesm/current/keesm13400.htm + - title: KEESM 13410 Benefit Levels, October 2024 edition + href: https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13400.htm + - title: KEESM 13410 Benefit Levels, January 2026 edition + href: https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13400.htm diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/other.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/other.yaml index fbf0e702b76..7d977bcacc6 100644 --- a/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/other.yaml +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/other.yaml @@ -144,5 +144,7 @@ metadata: href: https://liheapch.acf.gov/docs/2025/benefits-matricies/KS_BenefitMatrix_2025.pdf#page=3 - title: Kansas LIHEAP FY2026 State Plan, Section 2.5 (benefit variables) href: https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=9 - - title: KEESM 13410 Benefit Levels - href: https://content.dcf.ks.gov/ees/keesm/current/keesm13400.htm + - title: KEESM 13410 Benefit Levels, October 2024 edition + href: https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13400.htm + - title: KEESM 13410 Benefit Levels, January 2026 edition + href: https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13400.htm diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/propane.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/propane.yaml index 450a344ab2b..cfe0454961e 100644 --- a/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/propane.yaml +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/propane.yaml @@ -1194,5 +1194,7 @@ metadata: href: https://liheapch.acf.gov/docs/2025/benefits-matricies/KS_BenefitMatrix_2025.pdf#page=2 - title: Kansas LIHEAP FY2026 State Plan, Section 2.5 (benefit variables) href: https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=9 - - title: KEESM 13410 Benefit Levels - href: https://content.dcf.ks.gov/ees/keesm/current/keesm13400.htm + - title: KEESM 13410 Benefit Levels, October 2024 edition + href: https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13400.htm + - title: KEESM 13410 Benefit Levels, January 2026 edition + href: https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13400.htm diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_eligible.yaml index 81d865702d2..e2d18fa8138 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_eligible.yaml @@ -5,6 +5,9 @@ # subsidized housing whose heating fuel costs are included in the rent # (KEESM 13340; KS LIHEAP State Plan FY2026 2.3, #page=8). No asset test # (plan 2.3). +# KEESM sections refer to the October 2024 and January 2026 editions: +# https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/ and +# https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/ (keesm
.htm). - name: Case 2, the same household in Missouri is not eligible. period: 2026 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_energy_vulnerable.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_energy_vulnerable.yaml index ac9942f790f..6d6db599180 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_energy_vulnerable.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_energy_vulnerable.yaml @@ -1,4 +1,7 @@ # KEESM 13340, including facts that cannot be inferred from fuel bills. +# KEESM sections refer to the October 2024 and January 2026 editions: +# https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/ and +# https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/ (keesm
.htm). - name: Purchased wood qualifies period: 2026 input: diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_eligible.yaml index 8aa82bbfebd..94a29d02ad3 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_eligible.yaml @@ -1,4 +1,6 @@ -# KEESM 13360-13362, October 2024 and January 2026 editions. +# KEESM 13360-13362, October 2024 and January 2026 editions: +# https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13360.htm +# https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13360.htm # Values annualize the published monthly limits; FY2026 includes rounding. - name: Case 1, 2025 household size 1, income 0 dollar above the published limit. period: 2025 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_earned_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_earned_income.yaml index 420b963547b..2a4b185b27e 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_earned_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_earned_income.yaml @@ -1,9 +1,12 @@ # Kansas LIEAP countable earned income per person (KS LIHEAP State Plan FY2026 -# 1.8-1.9, #page=6-7): gross wages and self-employment income are counted, +# 1.8-1.9, #page=6,7): gross wages and self-employment income are counted, # except the earned income of a child under 18. KEESM 13320: a member who is # or turns 18 in the application month has countable income. # Modeling simplification: use existing net business income directly, without # applying KEESM 13360's gross-receipts expense deduction a second time. +# KEESM sections refer to the October 2024 and January 2026 editions: +# https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/ and +# https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/ (keesm
.htm). - name: Case 1, adult wages are counted in full. period: 2026 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_income.yaml index 23ce1e1820e..765a4f45f2b 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_income.yaml @@ -1,10 +1,13 @@ # Kansas LIEAP countable gross income (KS LIHEAP State Plan FY2026 sections -# 1.8-1.9, #page=5-6; KEESM 13320). Counted: wages, self-employment, +# 1.8-1.9, #page=5,6; KEESM 13320). Counted: wages, self-employment, # unemployment insurance, SSA benefits, SSI, retirement/pension, TANF, child # support, alimony, rental income, VA benefits and recurring adult interest. # Earned income of children under 18 is excluded. Income of other # household members counts, including non-qualified noncitizens (KEESM 13330). # All amounts are annual (YEAR variable). +# KEESM sections refer to the October 2024 and January 2026 editions: +# https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/ and +# https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/ (keesm
.htm). - name: Case 1, recurring adult interest and dividends are counted. period: 2026 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_interest_dividend_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_interest_dividend_income.yaml index c9d4b6ab5c9..f07d2cb22ba 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_interest_dividend_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_interest_dividend_income.yaml @@ -1,4 +1,7 @@ # KEESM 13361: child interest exclusion and year-specific interest exemptions. +# KEESM sections refer to the October 2024 and January 2026 editions: +# https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/ and +# https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/ (keesm
.htm). - name: Case 1, FY2025 exactly at monthly exemption. period: 2025 absolute_error_margin: 0.01 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/integration.yaml index def0a014ac6..48e77f479c9 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/integration.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/integration.yaml @@ -1,7 +1,7 @@ # Kansas LIEAP end-to-end integration tests. # Sources: KEESM 13100-13400 (eligibility, household, citizenship, energy # vulnerability, benefit levels); KS LIHEAP State Plan FY2026 (income sources -# 1.8-1.9 #page=5-6, income verification 1.4 #page=5, 150% FPG 2.1 and +# 1.8-1.9 #page=5,6, income verification 1.4 #page=5, 150% FPG 2.1 and # subsidized housing 2.3 #page=8, $130 minimum 2.6 #page=9); # KS_BenefitMatrix_2026.pdf (FY2026 season, "Benefit Adjustment @ 80%" table); # KS_BenefitMatrix_2025.pdf (FY2025 season, 100%). @@ -10,6 +10,9 @@ # 2025: 22,590 (1) / 46,800 (4). # Monthly income band = annual countable income / 12: # 1 = 0-899, 2 = 900-1,199, 3 = 1,200-1,699, 4 = 1,700+. +# KEESM sections refer to the October 2024 and January 2026 editions: +# https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/ and +# https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/ (keesm
.htm). - name: Case 1, single adult renting an apartment with natural gas heat. period: 2026 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/ks_liheap.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/ks_liheap.yaml index 83656fab819..4d8f0d8f17e 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/ks_liheap.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/ks_liheap.yaml @@ -4,6 +4,9 @@ # as a floor (KS LIHEAP State Plan FY2026 2.6, #page=9). The FY2025 season # minimum is $100 (KS LIHEAP State Plan FY2025 2.6, #page=9). Zero when # ineligible. +# KEESM sections refer to the October 2024 and January 2026 editions: +# https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/ and +# https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/ (keesm
.htm). - name: Case 4, other fuel trailer cell of 128 for a large family is raised to 130. period: 2026 @@ -142,8 +145,10 @@ # minimum, KS LIHEAP State Plan FY2025 2.6, #page=9 gives $100). ks_liheap: 112 -# Published FY2026 adjusted matrix cells (pages 1-4) and KEESM 13340/13362. -# Seven SPM units evaluate mixed inputs and a non-Kansas mask together. +# Case 15 evaluates seven SPM units in one simulation, including a Missouri +# unit that the Kansas mask must zero: FY2026 adjusted matrix cells +# (KS_BenefitMatrix_2026.pdf pages 1-4), the income limit (KEESM 13362) and +# the energy-vulnerability gate (KEESM 13340). - name: Case 15, mixed households evaluate Kansas LIEAP in one vectorized simulation. period: 2026 absolute_error_margin: 0.01 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/ks_liheap_fuel_category.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/ks_liheap_fuel_category.yaml index 8479784972b..9e80275c403 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/ks_liheap_fuel_category.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/ks_liheap_fuel_category.yaml @@ -1,8 +1,11 @@ # Kansas LIEAP primary heating fuel category (KEESM 13410; KS LIHEAP State -# Plan FY2026 2.5, #page=8-9; KS_BenefitMatrix_2026.pdf pages 1-4: Natural Gas, +# Plan FY2026 2.5, #page=8,9; KS_BenefitMatrix_2026.pdf pages 1-4: Natural Gas, # Electricity, Propane, Other). Mapping from the canonical heating_type input: # NATURAL_GAS -> natural gas; ELECTRICITY, SOLAR -> electricity; PROPANE -> # propane; FUEL_OIL, KEROSENE, WOOD, COAL, OTHER, UNSPECIFIED -> other. +# KEESM sections refer to the October 2024 and January 2026 editions: +# https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/ and +# https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/ (keesm
.htm). - name: Case 1, natural gas maps to the natural gas table. period: 2026 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/ks_liheap_household_size.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/ks_liheap_household_size.yaml index 016bf6d9ffa..8bc35678fcb 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/ks_liheap_household_size.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/ks_liheap_household_size.yaml @@ -3,6 +3,9 @@ # size, although their income still counts (see ks_liheap_countable_income.yaml). # Qualified aliens per KEESM 13330: legal permanent residents, refugees, # asylees, parolees (1+ year), deportation withheld, conditional entrants. +# KEESM sections refer to the October 2024 and January 2026 editions: +# https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/ and +# https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/ (keesm
.htm). - name: Case 1, single citizen counts as one. period: 2026 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/payment/ks_liheap_household_size_group.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/payment/ks_liheap_household_size_group.yaml index af0aa2ddd90..49594193361 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/payment/ks_liheap_household_size_group.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/payment/ks_liheap_household_size_group.yaml @@ -2,6 +2,9 @@ # (KS_BenefitMatrix_2026.pdf columns "Household Size 1-4" and "Household Size # 5 and Over"): group 1 for one to four countable members, group 2 for five # or more. Size counts only citizens and qualified aliens (KEESM 13330). +# KEESM sections refer to the October 2024 and January 2026 editions: +# https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/ and +# https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/ (keesm
.htm). - name: Case 1, single person is in the 1-4 group. period: 2026 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/payment/ks_liheap_income_band.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/payment/ks_liheap_income_band.yaml index c96c29fa3df..bf08769dfee 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/payment/ks_liheap_income_band.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/payment/ks_liheap_income_band.yaml @@ -2,6 +2,9 @@ # KEESM 13230 uses income of the application month). Monthly income = # annual countable income / 12. Bands: 1 = 0-899, 2 = 900-1,199, # 3 = 1,200-1,699, 4 = 1,700 and over. +# KEESM sections refer to the October 2024 and January 2026 editions: +# https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/ and +# https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/ (keesm
.htm). - name: Case 1, zero income is in the lowest band. period: 2026 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/payment/ks_liheap_matrix_amount.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/payment/ks_liheap_matrix_amount.yaml index efeba9b2407..cfd2ef9fcda 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/payment/ks_liheap_matrix_amount.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/payment/ks_liheap_matrix_amount.yaml @@ -1,5 +1,5 @@ # Kansas LIEAP benefit matrix lookup (KEESM 13410; KS LIHEAP State Plan FY2026 -# 2.5, #page=8-9). Dimensions: primary fuel table (natural gas p.1, +# 2.5, #page=8,9). Dimensions: primary fuel table (natural gas p.1, # electricity p.2, propane p.3, other p.4 of KS_BenefitMatrix_2026.pdf), # one-month income band, utility range tier A-J (no tier on the Other table), # dwelling type (House/Modular/Mobile, Duplex, Apt, Trailer/Other) and @@ -8,6 +8,9 @@ # KS_BenefitMatrix_2025.pdf values at 100%. Raw cell values: the $130 minimum # benefit floor is applied in ks_liheap, not here. Inputs are annual; monthly # income = annual / 12. Defaults: tier E, dwelling House/Modular/Mobile. +# KEESM sections refer to the October 2024 and January 2026 editions: +# https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/ and +# https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/ (keesm
.htm). - name: Case 1, natural gas, band 1, default tier E and house, size 1. period: 2026 diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_eligible.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_eligible.py index c3cb5b0ab20..14a8842e37e 100644 --- a/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_eligible.py +++ b/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_eligible.py @@ -8,7 +8,8 @@ class ks_liheap_eligible(Variable): label = "Eligible for Kansas LIEAP" documentation = "Kansas household that is income eligible, contains at least one citizen or qualified noncitizen, and meets the heating energy vulnerability requirement." reference = ( - "https://content.dcf.ks.gov/ees/keesm/current/keesm13300.htm", + "https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13300.htm", + "https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13300.htm", "https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=8", ) defined_for = StateCode.KS diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_energy_vulnerable.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_energy_vulnerable.py index 71144cb15c8..bd5c2c353fe 100644 --- a/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_energy_vulnerable.py +++ b/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_energy_vulnerable.py @@ -8,7 +8,10 @@ class ks_liheap_energy_vulnerable(Variable): label = "Kansas LIEAP household meets heating cost responsibility rules" documentation = "Defaults to separately paid heating costs or heat included in unsubsidized rent. Set this fact directly for shared unmetered heat, subsidized tenants paying excess heating charges, limited FHA subsidies, or homeless households owing qualifying heating debt from a prior Kansas address. The default assumes an adult household member is responsible for separately metered purchased fuel." defined_for = StateCode.KS - reference = "https://content.dcf.ks.gov/ees/keesm/current/keesm13300.htm" + reference = ( + "https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13300.htm", + "https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13300.htm", + ) def formula(spm_unit, period, parameters): pays_for_heat = spm_unit("has_heating_expense", period) diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_eligible.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_eligible.py index 017f1641309..45fa33d0c71 100644 --- a/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_eligible.py +++ b/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_eligible.py @@ -11,8 +11,10 @@ class ks_liheap_income_eligible(Variable): "https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13360.htm", "https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13360.htm", "https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=8", - "https://content.dcf.ks.gov/ees/keesm/current/keesm13000.htm", - "https://content.dcf.ks.gov/ees/keesm/current/keesm13300.htm", + "https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13000.htm", + "https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13000.htm", + "https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13300.htm", + "https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13300.htm", ) defined_for = StateCode.KS diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_income.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_income.py index 408fb6ef8fa..3b1d7127cad 100644 --- a/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_income.py +++ b/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_income.py @@ -9,8 +9,10 @@ class ks_liheap_countable_income(Variable): documentation = "Combined gross income of all persons living at the address counted under Kansas LIEAP, including the income of members who are not citizens or qualified aliens." unit = USD reference = ( - "https://content.dcf.ks.gov/ees/keesm/current/keesm13000.htm", - "https://content.dcf.ks.gov/ees/keesm/current/keesm13300.htm", + "https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13000.htm", + "https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13000.htm", + "https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13300.htm", + "https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13300.htm", ) defined_for = StateCode.KS diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_unearned_income.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_unearned_income.py index fd665d871a0..ae73b686206 100644 --- a/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_unearned_income.py +++ b/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_unearned_income.py @@ -9,7 +9,8 @@ class ks_liheap_countable_unearned_income(Variable): documentation = "Gross unearned income of all household members counted toward Kansas LIEAP household income." unit = USD reference = ( - "https://content.dcf.ks.gov/ees/keesm/current/keesm13360.htm", + "https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13360.htm", + "https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13360.htm", "https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=6", ) defined_for = StateCode.KS diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/ks_liheap.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/ks_liheap.py index a3f47049e6b..b3121b9a5b3 100644 --- a/policyengine_us/variables/gov/states/ks/dcf/liheap/ks_liheap.py +++ b/policyengine_us/variables/gov/states/ks/dcf/liheap/ks_liheap.py @@ -11,7 +11,8 @@ class ks_liheap(Variable): defined_for = "ks_liheap_eligible" reference = ( "https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=9", - "https://content.dcf.ks.gov/ees/keesm/current/keesm13400.htm", + "https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13400.htm", + "https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13400.htm", ) def formula(spm_unit, period, parameters): diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/ks_liheap_fuel_category.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/ks_liheap_fuel_category.py index 89f9a56005d..11caa383909 100644 --- a/policyengine_us/variables/gov/states/ks/dcf/liheap/ks_liheap_fuel_category.py +++ b/policyengine_us/variables/gov/states/ks/dcf/liheap/ks_liheap_fuel_category.py @@ -18,7 +18,8 @@ class ks_liheap_fuel_category(Variable): documentation = "Benefit matrix fuel table derived from the canonical heating_type input: natural gas; electricity (including solar); propane; and other for fuel oil, kerosene, wood, coal, other fuels, no heating and an unspecified fuel." reference = ( "https://liheapch.acf.gov/docs/2026/benefits-matricies/KS_BenefitMatrix_2026.pdf#page=4", - "https://content.dcf.ks.gov/ees/keesm/current/keesm13400.htm", + "https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13400.htm", + "https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13400.htm", ) defined_for = StateCode.KS diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/ks_liheap_household_size.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/ks_liheap_household_size.py index 0fbca27a8d7..b2136b80724 100644 --- a/policyengine_us/variables/gov/states/ks/dcf/liheap/ks_liheap_household_size.py +++ b/policyengine_us/variables/gov/states/ks/dcf/liheap/ks_liheap_household_size.py @@ -7,7 +7,10 @@ class ks_liheap_household_size(Variable): definition_period = YEAR label = "Kansas LIEAP household size" documentation = "Number of household members who are U.S. citizens or qualified aliens. Other members are not counted in household size, although their income counts toward household income." - reference = "https://content.dcf.ks.gov/ees/keesm/current/keesm13300.htm" + reference = ( + "https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13300.htm", + "https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13300.htm", + ) defined_for = StateCode.KS adds = ["is_citizen_or_legal_immigrant"] diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/payment/ks_liheap_income_band.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/payment/ks_liheap_income_band.py index 975a76da9fe..632ea1f2234 100644 --- a/policyengine_us/variables/gov/states/ks/dcf/liheap/payment/ks_liheap_income_band.py +++ b/policyengine_us/variables/gov/states/ks/dcf/liheap/payment/ks_liheap_income_band.py @@ -9,7 +9,8 @@ class ks_liheap_income_band(Variable): documentation = "Benefit matrix income band (1-4) from one-month gross countable income, taken as one twelfth of annual countable income." reference = ( "https://liheapch.acf.gov/docs/2026/benefits-matricies/KS_BenefitMatrix_2026.pdf#page=1", - "https://content.dcf.ks.gov/ees/keesm/current/keesm13200.htm", + "https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13200.htm", + "https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13200.htm", ) defined_for = StateCode.KS diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/payment/ks_liheap_matrix_amount.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/payment/ks_liheap_matrix_amount.py index 90dab5cd8f3..11f3eea325e 100644 --- a/policyengine_us/variables/gov/states/ks/dcf/liheap/payment/ks_liheap_matrix_amount.py +++ b/policyengine_us/variables/gov/states/ks/dcf/liheap/payment/ks_liheap_matrix_amount.py @@ -11,7 +11,8 @@ class ks_liheap_matrix_amount(Variable): reference = ( "https://liheapch.acf.gov/docs/2026/benefits-matricies/KS_BenefitMatrix_2026.pdf#page=1", "https://liheapch.acf.gov/docs/2025/benefits-matricies/KS_BenefitMatrix_2025.pdf#page=1", - "https://content.dcf.ks.gov/ees/keesm/current/keesm13400.htm", + "https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13400.htm", + "https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13400.htm", ) defined_for = StateCode.KS From 8c8b7b8e698bb389b88afc8c41f07eb2ed379a82 Mon Sep 17 00:00:00 2001 From: Ziming Date: Wed, 30 Sep 2026 20:46:40 -0400 Subject: [PATCH 08/12] Use the shared federal poverty guideline helper for the Kansas income limit Replace the Kansas-only tools/liheap.py helper with fpg(..., year_lag=...) from the shared helper merged in #9731. The 150% rate, separately rounded monthly increment and eight-person breakpoint stay in ks_liheap_income_limit, which reproduces the previous results for FY2025-FY2027 at every household size. Also records the verified-years note on ks_liheap and the KEESM 13330 household-size comment. Co-Authored-By: Claude Fable 5.1 --- policyengine_us/tools/liheap.py | 32 ------------------- .../eligibility/ks_liheap_income_limit.py | 27 ++++++++++++++-- .../gov/states/ks/dcf/liheap/ks_liheap.py | 2 +- .../ks/dcf/liheap/ks_liheap_household_size.py | 2 ++ 4 files changed, 27 insertions(+), 36 deletions(-) delete mode 100644 policyengine_us/tools/liheap.py diff --git a/policyengine_us/tools/liheap.py b/policyengine_us/tools/liheap.py deleted file mode 100644 index c2b5ab2c06c..00000000000 --- a/policyengine_us/tools/liheap.py +++ /dev/null @@ -1,32 +0,0 @@ -"""Shared calculations for state LIHEAP regular heating assistance.""" - -import numpy as np -from policyengine_core.model_api import MONTHS_IN_YEAR, clip, max_ - - -def calculate_liheap_fpg_income_limit( - household_size, state_group, period, parameters, policy -): - """Annualize a monthly FPG limit with separately rounded size increments. - - The caller supplies its policy household size, modeled period, and dated - parameters: fpg_year_lag, fpg_rate, rounding_increment, and max_table_size. - Guideline amounts come from the shared federal parameters for the modeled - year minus the guideline-year lag. Round to the nearest - increment, with ties rounded up, before adding people beyond the breakpoint. - """ - fpg_year = period.start.year - int(policy.fpg_year_lag) - fpg = parameters(f"{fpg_year}-01-01").gov.hhs.fpg - first_person = fpg.first_person[state_group] - additional_person = fpg.additional_person[state_group] - capped_size = clip(household_size, 1, policy.max_table_size) - additional_people = max_(household_size - policy.max_table_size, 0) - monthly_factor = policy.fpg_rate / MONTHS_IN_YEAR - monthly_limit = ( - first_person + additional_person * (capped_size - 1) - ) * monthly_factor - monthly_increment = additional_person * monthly_factor - rounding = policy.rounding_increment - rounded_limit = np.floor(monthly_limit / rounding + 0.5) * rounding - rounded_increment = np.floor(monthly_increment / rounding + 0.5) * rounding - return (rounded_limit + additional_people * rounded_increment) * MONTHS_IN_YEAR diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_limit.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_limit.py index ed3373ec585..e095c36b0da 100644 --- a/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_limit.py +++ b/policyengine_us/variables/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_limit.py @@ -1,5 +1,5 @@ from policyengine_us.model_api import * -from policyengine_us.tools.liheap import calculate_liheap_fpg_income_limit +from policyengine_us.variables.gov.hhs.tax_unit_fpg import fpg class ks_liheap_income_limit(Variable): @@ -18,6 +18,27 @@ def formula(spm_unit, period, parameters): p = parameters(period).gov.states.ks.dcf.liheap.eligibility size = spm_unit("ks_liheap_household_size", period) state_group = spm_unit.household("state_group_str", period) - return calculate_liheap_fpg_income_limit( - size, state_group, period, parameters, p + capped_size = clip(size, 1, p.max_table_size) + additional_people = max_(size - p.max_table_size, 0) + guideline = fpg( + capped_size, state_group, period, parameters, year_lag=p.fpg_year_lag ) + additional_guideline = ( + fpg( + capped_size + 1, + state_group, + period, + parameters, + year_lag=p.fpg_year_lag, + ) + - guideline + ) + monthly_factor = p.fpg_rate / MONTHS_IN_YEAR + monthly_limit = guideline * monthly_factor + monthly_increment = additional_guideline * monthly_factor + # Round the base limit and each additional-person increment separately, + # to the nearest policy increment with ties rounded up. + rounding = p.rounding_increment + rounded_limit = np.floor(monthly_limit / rounding + 0.5) * rounding + rounded_increment = np.floor(monthly_increment / rounding + 0.5) * rounding + return (rounded_limit + additional_people * rounded_increment) * MONTHS_IN_YEAR diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/ks_liheap.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/ks_liheap.py index b3121b9a5b3..985703b749e 100644 --- a/policyengine_us/variables/gov/states/ks/dcf/liheap/ks_liheap.py +++ b/policyengine_us/variables/gov/states/ks/dcf/liheap/ks_liheap.py @@ -5,7 +5,7 @@ class ks_liheap(Variable): value_type = float entity = SPMUnit label = "Kansas LIEAP" - documentation = "Annual Kansas Low Income Energy Assistance Program (LIEAP) heating benefit: the benefit matrix amount, subject to the minimum benefit." + documentation = "Annual Kansas Low Income Energy Assistance Program (LIEAP) heating benefit: the benefit matrix amount, subject to the minimum benefit. Verified for FY2025-2026; earlier results use model parameter backfilling and are unverified historical estimates." unit = USD definition_period = YEAR defined_for = "ks_liheap_eligible" diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/ks_liheap_household_size.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/ks_liheap_household_size.py index b2136b80724..0d3870842f8 100644 --- a/policyengine_us/variables/gov/states/ks/dcf/liheap/ks_liheap_household_size.py +++ b/policyengine_us/variables/gov/states/ks/dcf/liheap/ks_liheap_household_size.py @@ -13,4 +13,6 @@ class ks_liheap_household_size(Variable): ) defined_for = StateCode.KS + # KEESM 13330 excludes ineligible members from size but retains their income. + # It expressly includes refugees/asylees; do not substitute SNAP eligibility. adds = ["is_citizen_or_legal_immigrant"] From e82afc5dd2762e75fd5b9800c86d5039c7167ed8 Mon Sep 17 00:00:00 2001 From: Ziming Date: Wed, 30 Sep 2026 23:51:05 -0400 Subject: [PATCH 09/12] Use ordinary_dividend_income in Kansas LIEAP interest and dividend income Replace the deprecated dividend_income alias in the formula and send qualified_dividend_income in the tests that used it. Expected values are unchanged. Co-Authored-By: Claude Fable 5.1 --- .../dcf/liheap/income/ks_liheap_countable_income.yaml | 2 +- .../ks_liheap_countable_interest_dividend_income.yaml | 10 +++++----- .../ks_liheap_countable_interest_dividend_income.py | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_income.yaml index 765a4f45f2b..f400d3e49b7 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_income.yaml @@ -18,7 +18,7 @@ age: 40 employment_income: 20_000 interest_income: 3_000 - dividend_income: 2_000 + qualified_dividend_income: 2_000 spm_units: spm_unit: members: [person1] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_interest_dividend_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_interest_dividend_income.yaml index f07d2cb22ba..f5b45a7e10f 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_interest_dividend_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_interest_dividend_income.yaml @@ -9,7 +9,7 @@ state_code: KS age: 40 interest_income: 360 - dividend_income: 240 + qualified_dividend_income: 240 output: ks_liheap_countable_interest_dividend_income: 0 - name: Case 2, FY2025 above exemption counts the full amount. @@ -19,7 +19,7 @@ state_code: KS age: 40 interest_income: 361 - dividend_income: 240 + qualified_dividend_income: 240 output: ks_liheap_countable_interest_dividend_income: 601 - name: Case 3, FY2026 regular small interest has no blanket exemption. @@ -29,7 +29,7 @@ state_code: KS age: 40 interest_income: 120 - dividend_income: 0 + qualified_dividend_income: 0 output: ks_liheap_countable_interest_dividend_income: 120 - name: Case 4, FY2026 interest of a 17-year-old is exempt but dividends count. @@ -39,7 +39,7 @@ state_code: KS age: 17 interest_income: 1_000 - dividend_income: 300 + qualified_dividend_income: 300 output: ks_liheap_countable_interest_dividend_income: 300 - name: Case 5, FY2026 interest counts at age 18. @@ -49,6 +49,6 @@ state_code: KS age: 18 interest_income: 1_000 - dividend_income: 300 + qualified_dividend_income: 300 output: ks_liheap_countable_interest_dividend_income: 1_300 diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_interest_dividend_income.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_interest_dividend_income.py index 9337a01ae96..73bcde16436 100644 --- a/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_interest_dividend_income.py +++ b/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_interest_dividend_income.py @@ -21,7 +21,7 @@ def formula(spm_unit, period, parameters): adult_interest = spm_unit.sum( where(age >= p.interest_income_min_age, interest, 0) ) - dividends = add(spm_unit, period, ["dividend_income"]) + dividends = add(spm_unit, period, ["ordinary_dividend_income"]) total = adult_interest + dividends threshold = p.regular_interest_dividend_exemption * MONTHS_IN_YEAR return where(total > threshold, total, 0) From f09ef1fdd7b9834554ba56ea2bd2d047bb77ef94 Mon Sep 17 00:00:00 2001 From: Ziming Date: Thu, 1 Oct 2026 17:06:50 -0400 Subject: [PATCH 10/12] Address review nits in Kansas LIEAP: descriptions, citations, test labels and edge cases - Re-template 14 parameter descriptions and name the pages in combined reference anchors - Cite the FY2025 plan, KEESM 13361 and the July 2025 edition; fix the FY2025 matrix and plan anchors that missed pages - Drop the redundant select branch in ks_liheap_fuel_category; note the household-size interpretation and the estimated $130 minimum - Fix four test page cites and the 80 percent comment, renumber case labels, format numbers - Add cases for heat in rent with an unspecified fuel, negative countable income and strike, general assistance and workers' compensation income Co-Authored-By: Claude Fable 5.1 --- .../ks/dcf/liheap/eligibility/fpg_rate.yaml | 4 ++ .../dcf/liheap/eligibility/fpg_year_lag.yaml | 2 +- .../liheap/eligibility/max_table_size.yaml | 2 +- .../eligibility/rounding_increment.yaml | 8 +++- .../liheap/income/earned_income_min_age.yaml | 8 +++- .../income/interest_income_min_age.yaml | 6 +-- .../regular_interest_dividend_exemption.yaml | 9 ++-- .../ks/dcf/liheap/income/sources/earned.yaml | 6 ++- .../dcf/liheap/income/sources/unearned.yaml | 4 +- .../liheap/payment/household_size_group.yaml | 2 +- .../ks/dcf/liheap/payment/income_band.yaml | 2 +- .../liheap/payment/matrix/electricity.yaml | 12 ++--- .../liheap/payment/matrix/natural_gas.yaml | 8 ++-- .../ks/dcf/liheap/payment/matrix/other.yaml | 8 ++-- .../ks/dcf/liheap/payment/matrix/propane.yaml | 12 ++--- .../ks/dcf/liheap/payment/min_benefit.yaml | 2 +- policyengine_us/programs.yaml | 2 +- .../eligibility/ks_liheap_eligible.yaml | 12 ++--- .../ks_liheap_energy_vulnerable.yaml | 35 +++++++++------ .../ks_liheap_income_eligible.yaml | 14 +++--- .../ks_liheap_countable_earned_income.yaml | 14 +++--- .../income/ks_liheap_countable_income.yaml | 39 +++++++++++++--- .../gov/states/ks/dcf/liheap/integration.yaml | 6 +-- .../gov/states/ks/dcf/liheap/ks_liheap.yaml | 14 +++--- .../liheap/payment/ks_liheap_income_band.yaml | 10 +++++ .../payment/ks_liheap_matrix_amount.yaml | 44 +++++++++---------- .../ks/dcf/liheap/ks_liheap_fuel_category.py | 4 +- .../ks/dcf/liheap/ks_liheap_household_size.py | 3 ++ 28 files changed, 183 insertions(+), 109 deletions(-) diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/fpg_rate.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/fpg_rate.yaml index 9b51e52da84..590c40d06f4 100644 --- a/policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/fpg_rate.yaml +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/fpg_rate.yaml @@ -11,3 +11,7 @@ metadata: href: https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13360.htm - title: KEESM 13360 Income Eligibility, January 2026 edition href: https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13360.htm + - title: Kansas LIHEAP FY2026 State Plan, Section 2.1 (eligibility threshold 150.00% of the HHS poverty guidelines) + href: https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=8 + - title: Kansas LIHEAP FY2025 State Plan, Section 2.1 (eligibility threshold 150.00% of the HHS poverty guidelines) + href: https://liheapch.acf.gov/docs/2025/state-plans/KS_Plan_2025.pdf#page=8 diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/fpg_year_lag.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/fpg_year_lag.yaml index 8b271510508..27e77cbfbd1 100644 --- a/policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/fpg_year_lag.yaml +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/fpg_year_lag.yaml @@ -1,4 +1,4 @@ -description: Kansas uses federal poverty guidelines from this many years before the modeled heating season for the Low Income Energy Assistance Program income limit. +description: Kansas uses federal poverty guidelines from this many years before the modeled heating season for the income limit under the Low Income Energy Assistance Program. # Verified for FY2025 and FY2026: their limits use the 2024 and 2025 # guidelines, respectively. This is a relative year selection, not a fixed # guideline year. Earlier and later Kansas policy remains unverified. diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/max_table_size.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/max_table_size.yaml index 3b15c75243a..3748ff7ffb4 100644 --- a/policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/max_table_size.yaml +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/max_table_size.yaml @@ -1,4 +1,4 @@ -description: Kansas publishes Low Income Energy Assistance Program income limits through this household size, with an increment for each additional person. +description: Kansas sets income limits through this household size, with an increment for each additional person, under the Low Income Energy Assistance Program. values: 2024-10-01: 8 diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/rounding_increment.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/rounding_increment.yaml index 96e0841571f..8043d951884 100644 --- a/policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/rounding_increment.yaml +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/rounding_increment.yaml @@ -1,8 +1,12 @@ -description: Kansas expresses monthly Low Income Energy Assistance Program income limits in increments of this amount. +description: Kansas sets monthly income limits in increments of this amount under the Low Income Energy Assistance Program. # Precision inferred from the published tables, not an express rounding rule: # FY2025 retains cents and exactly matches 150% of the 2024 guidelines. # FY2026 matches nearest-dollar rounding of 150% of the 2025 guidelines, # including a separately rounded $688 increment for each person beyond eight. +# The July 2025 KEESM edition is the first to carry the FY2026 limits; the +# 2025-10-01 date matches the federal program year and the FY2026 matrix. All +# Kansas LIEAP variables are annual, so any date in the 2025 season gives the +# same result. values: 2024-10-01: 0.01 2025-10-01: 1 @@ -14,5 +18,7 @@ metadata: reference: - title: KEESM 13362 Income Guidelines, October 2024 edition href: https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13360.htm + - title: KEESM 13362 Income Guidelines, July 2025 edition (first edition with the FY2026 limits of $1,956 to $6,769 and the $688 increment) + href: https://content.dcf.ks.gov/ees/KEESM/Robo07-25/Robo_07_01_25/keesm13360.htm - title: KEESM 13362 Income Guidelines, January 2026 edition href: https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13360.htm diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/earned_income_min_age.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/earned_income_min_age.yaml index 363ccb85b86..389e078a72a 100644 --- a/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/earned_income_min_age.yaml +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/earned_income_min_age.yaml @@ -1,4 +1,4 @@ -description: Kansas counts the earned income of household members at or above this age under the Low Income Energy Assistance Program. +description: Kansas excludes the earned income of household members below this age under the Low Income Energy Assistance Program. values: 2024-10-01: 18 @@ -9,6 +9,12 @@ metadata: reference: - title: Kansas LIHEAP FY2026 State Plan, Section 1.9 (earned income of a child under the age of 18 is not counted) href: https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=7 + - title: Kansas LIHEAP FY2025 State Plan, Section 1.9 (earned income of a child under the age of 18 is not counted) + href: https://liheapch.acf.gov/docs/2025/state-plans/KS_Plan_2025.pdf#page=6 + - title: KEESM 13361 Exempt Income, October 2024 edition (earned income of child household members under age 18 is exempt) + href: https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13360.htm + - title: KEESM 13361 Exempt Income, January 2026 edition (earned income of child household members under age 18 is exempt) + href: https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13360.htm - title: KEESM 13320 Household Definition, October 2024 edition (a member who is or turns eighteen in the month of application has countable income) href: https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13300.htm - title: KEESM 13320 Household Definition, January 2026 edition (a member who is or turns eighteen in the month of application has countable income) diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/interest_income_min_age.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/interest_income_min_age.yaml index add0ea6c4e2..eefb8767ace 100644 --- a/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/interest_income_min_age.yaml +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/interest_income_min_age.yaml @@ -1,4 +1,4 @@ -description: Kansas counts interest income of household members at or above this age under the Low Income Energy Assistance Program. +description: Kansas excludes the interest income of household members below this age under the Low Income Energy Assistance Program. values: 2024-10-01: 18 @@ -7,7 +7,7 @@ metadata: period: year label: Kansas LIEAP minimum age for countable interest reference: - - title: KEESM 13360-13362, October 2024 edition + - title: KEESM 13361 Exempt Income, October 2024 edition (interest accrued from the interest-bearing accounts of children under 18 is exempt) href: https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13360.htm - - title: KEESM 13360-13362, January 2026 edition + - title: KEESM 13361 Exempt Income, January 2026 edition (interest accrued from the interest-bearing accounts of children under 18 is exempt) href: https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13360.htm diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/regular_interest_dividend_exemption.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/regular_interest_dividend_exemption.yaml index 40085af1718..b18ca35570c 100644 --- a/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/regular_interest_dividend_exemption.yaml +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/regular_interest_dividend_exemption.yaml @@ -1,4 +1,5 @@ -description: Kansas excludes recurring interest and dividends not exceeding this monthly amount under the Low Income Energy Assistance Program; above it the full amount counts. +description: Kansas excludes recurring interest and dividends not exceeding this monthly amount under the Low Income Energy Assistance Program. +# Above this amount the full amount counts. values: 2024-10-01: 50 2025-10-01: 0 @@ -8,7 +9,9 @@ metadata: period: month label: Kansas LIEAP recurring interest and dividend exemption reference: - - title: KEESM 13360-13362, October 2024 edition + - title: KEESM 13361 Exempt Income, October 2024 edition (interest and dividend income not exceeding $50 per month is exempt; if in excess the full amount is counted) href: https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13360.htm - - title: KEESM 13360-13362, January 2026 edition + - title: KEESM 13361 Exempt Income, July 2025 edition (first edition with the FY2026 rule; only irregular, unpredictable interest and dividends under $30 in a quarter are exempt) + href: https://content.dcf.ks.gov/ees/KEESM/Robo07-25/Robo_07_01_25/keesm13360.htm + - title: KEESM 13361 Exempt Income, January 2026 edition (only irregular, unpredictable interest and dividends under $30 in a quarter are exempt) href: https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13360.htm diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/earned.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/earned.yaml index 9330ded4590..c9afa36a34a 100644 --- a/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/earned.yaml +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/earned.yaml @@ -22,8 +22,10 @@ metadata: href: https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm7122.htm - title: KEESM 7122.1 Income Producing Cost Deduction, January 2026 edition (a loss from self-employment cannot be deducted from other income) href: https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm7122.htm - - title: Kansas LIHEAP FY2026 State Plan, Section 1.8-1.9 (gross income; wages, self-employment income, contract income and commissions counted) - href: https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=6 + - title: Kansas LIHEAP FY2026 State Plan, Section 1.8-1.9, pages 5-6 (gross income; wages, self-employment income, contract income and commissions counted) + href: https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=5,6 + - title: Kansas LIHEAP FY2025 State Plan, Section 1.8-1.9, pages 5-6 (gross income; wages, self-employment income, contract income and commissions counted) + href: https://liheapch.acf.gov/docs/2025/state-plans/KS_Plan_2025.pdf#page=5,6 - title: KEESM 13320 Household Definition, October 2024 edition (income of all household members living together is used) href: https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13300.htm - title: KEESM 13320 Household Definition, January 2026 edition (income of all household members living together is used) diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/unearned.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/unearned.yaml index 0644e2fb401..606eb0ebb73 100644 --- a/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/unearned.yaml +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/unearned.yaml @@ -1,4 +1,4 @@ -description: Kansas counts these unearned income sources in gross household income under the Low Income Energy Assistance Program. +description: Kansas uses these unearned income sources to determine gross household income under the Low Income Energy Assistance Program. values: 2024-10-01: - unemployment_compensation @@ -32,6 +32,8 @@ metadata: reference: - title: Kansas LIHEAP FY2026 State Plan, Section 1.9 (countable income sources) href: https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=6 + - title: Kansas LIHEAP FY2025 State Plan, Section 1.9, pages 5-6 (countable income sources) + href: https://liheapch.acf.gov/docs/2025/state-plans/KS_Plan_2025.pdf#page=5,6 - title: KEESM 13360-13361, October 2024 edition (countable income and specific exemptions) href: https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13360.htm - title: KEESM 13360-13361, January 2026 edition (countable income and specific exemptions) diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/household_size_group.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/household_size_group.yaml index fd3a34c6b45..9e6e167ea38 100644 --- a/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/household_size_group.yaml +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/household_size_group.yaml @@ -1,4 +1,4 @@ -description: Kansas assigns households to this benefit matrix size group based on the number of countable household members under the Low Income Energy Assistance Program. +description: Kansas sets this benefit matrix size group based on the number of countable household members under the Low Income Energy Assistance Program. brackets: # Household size 1-4. - threshold: diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/income_band.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/income_band.yaml index 0ab0fd3c079..aecb4d8d2f3 100644 --- a/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/income_band.yaml +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/income_band.yaml @@ -1,4 +1,4 @@ -description: Kansas assigns households to this benefit matrix income band based on one-month gross countable income under the Low Income Energy Assistance Program. +description: Kansas sets this benefit matrix income band based on one-month gross countable income under the Low Income Energy Assistance Program. brackets: - threshold: 2024-10-01: 0 diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/electricity.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/electricity.yaml index 3f9eee0e2aa..680ba4b5c95 100644 --- a/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/electricity.yaml +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/electricity.yaml @@ -1,4 +1,4 @@ -description: Kansas provides this annual benefit to households heating primarily with electricity under the Low Income Energy Assistance Program, by one-month income band, utility rate tier, dwelling type and household size group. +description: Kansas provides this annual benefit to households heating primarily with electricity, by one-month income band, utility rate tier, dwelling type and household size group, under the Low Income Energy Assistance Program. # Income band 1: one-month income $0 to $899 1: @@ -1190,10 +1190,12 @@ metadata: reference: - title: Kansas LIEAP FY2026 Benefit Matrix, Electricity (Benefit Adjustment @ 80% table) href: https://liheapch.acf.gov/docs/2026/benefits-matricies/KS_BenefitMatrix_2026.pdf#page=2 - - title: Kansas LIEAP FY2025 Benefit Matrix, Electricity (Ben Adj 100.0%) - href: https://liheapch.acf.gov/docs/2025/benefits-matricies/KS_BenefitMatrix_2025.pdf#page=1 - - title: Kansas LIHEAP FY2026 State Plan, Section 2.5 (benefit variables) - href: https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=9 + - title: Kansas LIEAP FY2025 Benefit Matrix, Electricity (Ben Adj 100.0%; pages 1-2) + href: https://liheapch.acf.gov/docs/2025/benefits-matricies/KS_BenefitMatrix_2025.pdf#page=1,2 + - title: Kansas LIHEAP FY2026 State Plan, Section 2.5, pages 8-9 (benefit variables) + href: https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=8,9 + - title: Kansas LIHEAP FY2025 State Plan, Section 2.5, pages 8-9 (benefit variables) + href: https://liheapch.acf.gov/docs/2025/state-plans/KS_Plan_2025.pdf#page=8,9 - title: KEESM 13410 Benefit Levels, October 2024 edition href: https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13400.htm - title: KEESM 13410 Benefit Levels, January 2026 edition diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/natural_gas.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/natural_gas.yaml index d99988067c0..b5dd0c7bd27 100644 --- a/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/natural_gas.yaml +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/natural_gas.yaml @@ -1,4 +1,4 @@ -description: Kansas provides this annual benefit to households heating primarily with natural gas under the Low Income Energy Assistance Program, by one-month income band, utility rate tier, dwelling type and household size group. +description: Kansas provides this annual benefit to households heating primarily with natural gas, by one-month income band, utility rate tier, dwelling type and household size group, under the Low Income Energy Assistance Program. # Income band 1: one-month income $0 to $899 1: @@ -1192,8 +1192,10 @@ metadata: href: https://liheapch.acf.gov/docs/2026/benefits-matricies/KS_BenefitMatrix_2026.pdf#page=1 - title: Kansas LIEAP FY2025 Benefit Matrix, Natural gas (Ben Adj 100.0%) href: https://liheapch.acf.gov/docs/2025/benefits-matricies/KS_BenefitMatrix_2025.pdf#page=1 - - title: Kansas LIHEAP FY2026 State Plan, Section 2.5 (benefit variables) - href: https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=9 + - title: Kansas LIHEAP FY2026 State Plan, Section 2.5, pages 8-9 (benefit variables) + href: https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=8,9 + - title: Kansas LIHEAP FY2025 State Plan, Section 2.5, pages 8-9 (benefit variables) + href: https://liheapch.acf.gov/docs/2025/state-plans/KS_Plan_2025.pdf#page=8,9 - title: KEESM 13410 Benefit Levels, October 2024 edition href: https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13400.htm - title: KEESM 13410 Benefit Levels, January 2026 edition diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/other.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/other.yaml index 7d977bcacc6..8cf1bd1b6c1 100644 --- a/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/other.yaml +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/other.yaml @@ -1,4 +1,4 @@ -description: Kansas provides this annual benefit to households heating primarily with other fuels under the Low Income Energy Assistance Program, by one-month income band, dwelling type and household size group. +description: Kansas provides this annual benefit to households heating primarily with other fuels, by one-month income band, dwelling type and household size group, under the Low Income Energy Assistance Program. # Income band 1: one-month income $0 to $899 1: @@ -142,8 +142,10 @@ metadata: href: https://liheapch.acf.gov/docs/2026/benefits-matricies/KS_BenefitMatrix_2026.pdf#page=4 - title: Kansas LIEAP FY2025 Benefit Matrix, Other fuels (Ben Adj 100.0%) href: https://liheapch.acf.gov/docs/2025/benefits-matricies/KS_BenefitMatrix_2025.pdf#page=3 - - title: Kansas LIHEAP FY2026 State Plan, Section 2.5 (benefit variables) - href: https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=9 + - title: Kansas LIHEAP FY2026 State Plan, Section 2.5, pages 8-9 (benefit variables) + href: https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=8,9 + - title: Kansas LIHEAP FY2025 State Plan, Section 2.5, pages 8-9 (benefit variables) + href: https://liheapch.acf.gov/docs/2025/state-plans/KS_Plan_2025.pdf#page=8,9 - title: KEESM 13410 Benefit Levels, October 2024 edition href: https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13400.htm - title: KEESM 13410 Benefit Levels, January 2026 edition diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/propane.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/propane.yaml index cfe0454961e..d7cc704effd 100644 --- a/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/propane.yaml +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/propane.yaml @@ -1,4 +1,4 @@ -description: Kansas provides this annual benefit to households heating primarily with propane under the Low Income Energy Assistance Program, by one-month income band, utility rate tier, dwelling type and household size group. +description: Kansas provides this annual benefit to households heating primarily with propane, by one-month income band, utility rate tier, dwelling type and household size group, under the Low Income Energy Assistance Program. # Income band 1: one-month income $0 to $899 1: @@ -1190,10 +1190,12 @@ metadata: reference: - title: Kansas LIEAP FY2026 Benefit Matrix, Propane (Benefit Adjustment @ 80% table) href: https://liheapch.acf.gov/docs/2026/benefits-matricies/KS_BenefitMatrix_2026.pdf#page=3 - - title: Kansas LIEAP FY2025 Benefit Matrix, Propane (Ben Adj 100.0%) - href: https://liheapch.acf.gov/docs/2025/benefits-matricies/KS_BenefitMatrix_2025.pdf#page=2 - - title: Kansas LIHEAP FY2026 State Plan, Section 2.5 (benefit variables) - href: https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=9 + - title: Kansas LIEAP FY2025 Benefit Matrix, Propane (Ben Adj 100.0%; pages 2-3) + href: https://liheapch.acf.gov/docs/2025/benefits-matricies/KS_BenefitMatrix_2025.pdf#page=2,3 + - title: Kansas LIHEAP FY2026 State Plan, Section 2.5, pages 8-9 (benefit variables) + href: https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=8,9 + - title: Kansas LIHEAP FY2025 State Plan, Section 2.5, pages 8-9 (benefit variables) + href: https://liheapch.acf.gov/docs/2025/state-plans/KS_Plan_2025.pdf#page=8,9 - title: KEESM 13410 Benefit Levels, October 2024 edition href: https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13400.htm - title: KEESM 13410 Benefit Levels, January 2026 edition diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/min_benefit.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/min_benefit.yaml index 2d10071815c..28c8361371e 100644 --- a/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/min_benefit.yaml +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/min_benefit.yaml @@ -1,4 +1,4 @@ -description: Kansas pays at least this annual benefit to eligible households under the Low Income Energy Assistance Program. +description: Kansas provides at least this annual benefit to eligible households under the Low Income Energy Assistance Program. # Plan Section 2.6 reports a minimum and maximum benefit of $100 and $2,232 # for FY2025 and $130 and $4,301 for FY2026. The FY2025 figures equal the # FY2025 matrix minimum and maximum. The FY2026 matrix's adjusted 80% column diff --git a/policyengine_us/programs.yaml b/policyengine_us/programs.yaml index ef4394505f3..42e444275b4 100644 --- a/policyengine_us/programs.yaml +++ b/policyengine_us/programs.yaml @@ -830,7 +830,7 @@ programs: variable: ks_liheap parameter_prefix: gov.states.ks.dcf.liheap verified_years: "2025-2026" - notes: Models regular heating assistance using FY2025 and FY2026 benefit matrices and income limits derived from 150% of the prior year's federal poverty guidelines, which reproduce the published limits. Annual income approximates the application month; the SPM unit approximates the energy household. Utility tier defaults to E and dwelling type to house/mobile. Self-employment income uses existing net income with each source floored at zero; the 25% standard expense deduction is not modeled. Special energy-vulnerability cases require a direct input. Some irregular receipts and source-specific income exemptions are not modeled. Cooling, crisis, weatherization, and equipment assistance are outside scope. + notes: Models regular heating assistance using FY2025 and FY2026 benefit matrices and income limits derived from 150% of the prior year's federal poverty guidelines, which reproduce the published limits. Annual income approximates the application month; the SPM unit approximates the energy household. Utility tier defaults to E and dwelling type to house/mobile. Self-employment income uses existing net income with each source floored at zero; the 25% standard expense deduction is not modeled. Special energy-vulnerability cases require a direct input. Some irregular receipts and source-specific income exemptions are not modeled. The FY2026 $130 minimum benefit comes from the state plan's estimated benefit levels (Section 2.6) and is applied as a floor; the benefit matrix itself prints cells below it. Cooling, crisis, weatherization, and equipment assistance are outside scope. - state: TX status: partial name: Texas CEAP diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_eligible.yaml index e2d18fa8138..c8f7afdc1a3 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_eligible.yaml @@ -9,7 +9,7 @@ # https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/ and # https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/ (keesm
.htm). -- name: Case 2, the same household in Missouri is not eligible. +- name: Case 1, the same household in Missouri is not eligible. period: 2026 input: people: @@ -28,7 +28,7 @@ output: ks_liheap_eligible: false -- name: Case 4, household with no citizen or qualified member is not eligible. +- name: Case 2, household with no citizen or qualified member is not eligible. period: 2026 input: people: @@ -51,7 +51,7 @@ output: ks_liheap_eligible: false -- name: Case 5, mixed-status household with one citizen member is eligible. +- name: Case 3, mixed-status household with one citizen member is eligible. period: 2026 input: people: @@ -77,7 +77,7 @@ # 12,000 (the parent's income counts). ks_liheap_eligible: true -- name: Case 7, subsidized-housing renter who pays heat separately is eligible. +- name: Case 4, subsidized-housing renter who pays heat separately is eligible. period: 2026 input: people: @@ -99,7 +99,7 @@ # KEESM 13340: pays heating costs directly to a utility -> vulnerable. ks_liheap_eligible: true -- name: Case 10, no asset test so large savings do not disqualify. +- name: Case 5, no asset test so large savings do not disqualify. period: 2026 input: people: @@ -120,7 +120,7 @@ # Plan 2.3: "Do you require an Assets test? No". ks_liheap_eligible: true -- name: Case 11, TANF receipt does not waive the household income limit. +- name: Case 6, TANF receipt does not waive the household income limit. period: 2025 input: people: diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_energy_vulnerable.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_energy_vulnerable.yaml index 6d6db599180..379a0fe8b99 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_energy_vulnerable.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_energy_vulnerable.yaml @@ -2,76 +2,83 @@ # KEESM sections refer to the October 2024 and January 2026 editions: # https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/ and # https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/ (keesm
.htm). -- name: Purchased wood qualifies +- name: Case 1, purchased wood qualifies. period: 2026 input: state_code: KS age: 40 - ks_liheap_countable_income: 10000 + ks_liheap_countable_income: 10_000 heating_type: WOOD wood_expense: 600 output: ks_liheap_energy_vulnerable: true ks_liheap_eligible: true -- name: An unknown heating fuel with no cost information does not establish vulnerability +- name: Case 2, an unknown heating fuel with no cost information does not establish vulnerability. period: 2026 input: state_code: KS age: 40 - ks_liheap_countable_income: 10000 + ks_liheap_countable_income: 10_000 + heating_type: UNSPECIFIED output: ks_liheap_energy_vulnerable: false ks_liheap_eligible: false -- name: Unsubsidized heat included in rent qualifies +- name: Case 3, unsubsidized heat included in rent qualifies and is paid from the other-fuel table. period: 2026 + absolute_error_margin: 0.01 input: state_code: KS age: 40 - ks_liheap_countable_income: 10000 + ks_liheap_countable_income: 10_000 heat_expense_included_in_rent: true + heating_type: UNSPECIFIED output: ks_liheap_energy_vulnerable: true ks_liheap_eligible: true -- name: Subsidized heat included in rent does not qualify by default + # An unspecified fuel uses the Other table: 10,000 / 12 = 833 -> 0-899; + # KS_BenefitMatrix_2026.pdf p.4 (80%) House, size 1-4 = 639; max(639, 130). + ks_liheap_fuel_category: OTHER + ks_liheap: 639 +- name: Case 4, subsidized heat included in rent does not qualify by default. period: 2026 input: state_code: KS age: 40 - ks_liheap_countable_income: 10000 + ks_liheap_countable_income: 10_000 heat_expense_included_in_rent: true receives_housing_assistance: true output: ks_liheap_energy_vulnerable: false ks_liheap_eligible: false -- name: Subsidized excess heating charges can establish vulnerability +- name: Case 5, subsidized excess heating charges can establish vulnerability. period: 2026 input: state_code: KS age: 40 - ks_liheap_countable_income: 10000 + ks_liheap_countable_income: 10_000 heat_expense_included_in_rent: true receives_housing_assistance: true ks_liheap_energy_vulnerable: true output: ks_liheap_energy_vulnerable: true ks_liheap_eligible: true -- name: Shared unmetered heat can be explicitly excluded +- name: Case 6, shared unmetered heat can be explicitly excluded. period: 2026 input: state_code: KS age: 40 - ks_liheap_countable_income: 10000 + ks_liheap_countable_income: 10_000 heat_expense_included_in_rent: true ks_liheap_energy_vulnerable: false output: ks_liheap_energy_vulnerable: false ks_liheap_eligible: false -- name: A homeless household with qualifying prior-address heating debt can qualify +- name: Case 7, a homeless household with qualifying prior-address heating debt can qualify. period: 2026 input: state_code: KS age: 40 - ks_liheap_countable_income: 10000 + ks_liheap_countable_income: 10_000 heating_type: NONE ks_liheap_energy_vulnerable: true output: diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_eligible.yaml index 94a29d02ad3..be6489efd0f 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/eligibility/ks_liheap_income_eligible.yaml @@ -24,7 +24,7 @@ ks_liheap_income_limit: 22_590 ks_liheap_income_eligible: false -- name: Case 5, 2026 household size 1, income 0 dollar above the published limit. +- name: Case 3, 2026 household size 1, income 0 dollar above the published limit. period: 2026 absolute_error_margin: 0.01 input: @@ -35,7 +35,7 @@ ks_liheap_income_limit: 23_472 ks_liheap_income_eligible: true -- name: Case 6, 2026 household size 1, income 1 dollar above the published limit. +- name: Case 4, 2026 household size 1, income 1 dollar above the published limit. period: 2026 absolute_error_margin: 0.01 input: @@ -46,7 +46,7 @@ ks_liheap_income_limit: 23_472 ks_liheap_income_eligible: false -- name: Case 9, 2026 household size 9, income 0 dollar above the published limit. +- name: Case 5, 2026 household size 9, income 0 dollar above the published limit. period: 2026 absolute_error_margin: 0.01 input: @@ -57,7 +57,7 @@ ks_liheap_income_limit: 89_484 ks_liheap_income_eligible: true -- name: Case 10, 2026 household size 9, income 1 dollar above the published limit. +- name: Case 6, 2026 household size 9, income 1 dollar above the published limit. period: 2026 absolute_error_margin: 0.01 input: @@ -68,7 +68,7 @@ ks_liheap_income_limit: 89_484 ks_liheap_income_eligible: false -- name: Case 13, snap receipt does not waive the household income limit. +- name: Case 7, snap receipt does not waive the household income limit. period: 2026 input: state_code: KS @@ -78,7 +78,7 @@ output: ks_liheap_income_eligible: false -- name: Case 14, ssi receipt does not waive the household income limit. +- name: Case 8, ssi receipt does not waive the household income limit. period: 2026 input: state_code: KS @@ -88,7 +88,7 @@ output: ks_liheap_income_eligible: false -- name: Case 15, ks_tanf receipt does not waive the household income limit. +- name: Case 9, ks_tanf receipt does not waive the household income limit. period: 2026 input: state_code: KS diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_earned_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_earned_income.yaml index 2a4b185b27e..f72313d566a 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_earned_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_earned_income.yaml @@ -26,7 +26,7 @@ output: ks_liheap_countable_earned_income: 24_000 -- name: Case 4, an 18-year-old's wages are counted. +- name: Case 2, an 18-year-old's wages are counted. period: 2026 absolute_error_margin: 0.01 input: @@ -48,7 +48,7 @@ ks_liheap_countable_earned_income: [18_000, 5_000] ks_liheap_countable_income: 23_000 -- name: Case 5, unearned income is not part of earned income. +- name: Case 3, unearned income is not part of earned income. period: 2026 absolute_error_margin: 0.01 input: @@ -67,7 +67,7 @@ output: ks_liheap_countable_earned_income: 0 -- name: Case 6, FY2025 reported net business income receives no additional deduction. +- name: Case 4, FY2025 reported net business income receives no additional deduction. period: 2025 absolute_error_margin: 0.01 input: @@ -77,7 +77,7 @@ output: ks_liheap_countable_earned_income: 24_000 -- name: Case 7, FY2026 includes regular, SSTB, and farm net income alongside wages. +- name: Case 5, FY2026 includes regular, SSTB, and farm net income alongside wages. period: 2026 absolute_error_margin: 0.01 input: @@ -92,7 +92,7 @@ ks_liheap_countable_earned_income: 26_000 ks_liheap_countable_income: 26_000 -- name: Case 8, a farm loss does not offset wages or other positive business income. +- name: Case 6, a farm loss does not offset wages or other positive business income. period: 2026 absolute_error_margin: 0.01 input: @@ -105,7 +105,7 @@ output: ks_liheap_countable_earned_income: 22_000 -- name: Case 9, an adult with only business losses has no countable earnings. +- name: Case 7, an adult with only business losses has no countable earnings. period: 2026 absolute_error_margin: 0.01 input: @@ -117,7 +117,7 @@ output: ks_liheap_countable_earned_income: 0 -- name: Case 10, child business income is excluded and adult losses do not affect other people. +- name: Case 8, child business income is excluded and adult losses do not affect other people. period: 2026 absolute_error_margin: 0.01 input: diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_income.yaml index f400d3e49b7..fe5bad2aab3 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_income.yaml @@ -30,7 +30,7 @@ # 20,000 wages + 3,000 interest + 2,000 dividends (KEESM 13360). ks_liheap_countable_income: 25_000 -- name: Case 3, Social Security and SSI are counted. +- name: Case 2, Social Security and SSI are counted. period: 2026 absolute_error_margin: 0.01 input: @@ -50,7 +50,7 @@ # 12,000 SSA + 3,000 SSI = 15,000 (plan 1.8: SSA and SSI checked). ks_liheap_countable_income: 15_000 -- name: Case 5, unearned income of a child under 18 is still counted. +- name: Case 3, unearned income of a child under 18 is still counted. period: 2026 absolute_error_margin: 0.01 input: @@ -75,7 +75,7 @@ # 4,000 SSA survivor benefit counts: 18,000 + 4,000 = 22,000. ks_liheap_countable_income: 22_000 -- name: Case 6, other checked income sources are summed. +- name: Case 4, other checked income sources are summed. period: 2026 absolute_error_margin: 0.01 input: @@ -102,7 +102,7 @@ # alimony, rental income, VA benefits). ks_liheap_countable_income: 38_000 -- name: Case 7, TANF cash assistance is counted. +- name: Case 5, TANF cash assistance is counted. period: 2026 absolute_error_margin: 0.01 input: @@ -124,7 +124,7 @@ # 3,000 wages + 2,400 TANF (plan 1.8: TANF checked) = 5,400. ks_liheap_countable_income: 5_400 -- name: Case 8, income of a non-qualified noncitizen member is counted. +- name: Case 6, income of a non-qualified noncitizen member is counted. period: 2026 absolute_error_margin: 0.01 input: @@ -148,7 +148,7 @@ # KEESM 13330: income from non-qualified members is counted -> 18,000. ks_liheap_countable_income: 18_000 -- name: Case 9, countable earned income supplied by the caller is used as given. +- name: Case 7, countable earned income supplied by the caller is used as given. period: 2026 absolute_error_margin: 0.01 input: @@ -170,7 +170,7 @@ # 18,000 supplied countable earned income + 0 unearned income = 18,000. ks_liheap_countable_income: 18_000 -- name: Case 10, employer disability benefits are counted as unearned income. +- name: Case 8, employer disability benefits are counted as unearned income. period: 2026 absolute_error_margin: 0.01 input: @@ -193,3 +193,28 @@ ks_liheap_countable_unearned_income: 14_400 # 0 earned income + 14,400 unearned income = 14,400. ks_liheap_countable_income: 14_400 + +- name: Case 9, strike benefits, general assistance and workers' compensation are counted. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 45 + # Example amounts: 100, 200 and 300 a month. + strike_benefits: 1_200 + general_assistance: 2_400 + workers_compensation: 3_600 + spm_units: + spm_unit: + members: [person1] + ks_tanf: 0 + households: + household: + members: [person1] + state_code: KS + output: + # All three are in the unearned source list: 1,200 + 2,400 + 3,600 = 7,200. + ks_liheap_countable_unearned_income: 7_200 + # 0 earned income + 7,200 unearned income = 7,200. + ks_liheap_countable_income: 7_200 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/integration.yaml index 48e77f479c9..58a3f3b278a 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/integration.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/integration.yaml @@ -295,8 +295,8 @@ ks_liheap_eligible: true ks_liheap_income_band: 1 ks_liheap_fuel_category: NATURAL_GAS - # matrix p.1 (80%) 0-899, tier E, House, size 1-4 = 709 (941 x 0.8 = 752.8; - # the published 80% table cell is 709) + # matrix p.1 (80%) 0-899, tier E, House, size 1-4 = 709: 80% of the + # FY2026 unadjusted cell of 886 (886 x 0.8 = 708.8, rounded to 709) ks_liheap_matrix_amount: 709 ks_liheap: 709 @@ -475,7 +475,7 @@ # 21,600 / 12 = 1,800 -> 1,700 & over ks_liheap_income_band: 4 ks_liheap_fuel_category: PROPANE - # KS_BenefitMatrix_2025.pdf p.2 (100%) propane 1,700 & over, tier A, + # KS_BenefitMatrix_2025.pdf p.3 (100%) propane 1,700 & over, tier A, # Trailer/Other, size 1-4 = 100 ks_liheap_matrix_amount: 100 # FY2025 minimum benefit $100 (KS LIHEAP State Plan FY2025 2.6, #page=9): diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/ks_liheap.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/ks_liheap.yaml index 4d8f0d8f17e..339abe0aa37 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/ks_liheap.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/ks_liheap.yaml @@ -8,7 +8,7 @@ # https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/ and # https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/ (keesm
.htm). -- name: Case 4, other fuel trailer cell of 128 for a large family is raised to 130. +- name: Case 1, other fuel trailer cell of 128 for a large family is raised to 130. period: 2026 absolute_error_margin: 0.01 input: @@ -40,7 +40,7 @@ # size 5+ = 128; max(128, 130) = 130 ks_liheap: 130 -- name: Case 5, cell just above the minimum is paid unchanged. +- name: Case 2, cell just above the minimum is paid unchanged. period: 2026 absolute_error_margin: 0.01 input: @@ -73,7 +73,7 @@ # max(138, 130) = 138 ks_liheap: 138 -- name: Case 6, home with no heating receives nothing. +- name: Case 3, home with no heating receives nothing. period: 2026 absolute_error_margin: 0.01 input: @@ -93,7 +93,7 @@ ks_liheap_eligible: false ks_liheap: 0 -- name: Case 9, negative self-employment income does not inflate the benefit. +- name: Case 4, negative self-employment income does not inflate the benefit. period: 2026 absolute_error_margin: 0.01 input: @@ -118,7 +118,7 @@ # (0-899): matrix p.1 (80%) tier E, House, size 1-4 = 709. ks_liheap: 709 -- name: Case 13, FY2025 natural gas trailer cell of 112 is above the 100 minimum and unchanged. +- name: Case 5, FY2025 natural gas trailer cell of 112 is above the 100 minimum and unchanged. period: 2025 absolute_error_margin: 0.01 input: @@ -145,11 +145,11 @@ # minimum, KS LIHEAP State Plan FY2025 2.6, #page=9 gives $100). ks_liheap: 112 -# Case 15 evaluates seven SPM units in one simulation, including a Missouri +# Case 6 evaluates seven SPM units in one simulation, including a Missouri # unit that the Kansas mask must zero: FY2026 adjusted matrix cells # (KS_BenefitMatrix_2026.pdf pages 1-4), the income limit (KEESM 13362) and # the energy-vulnerability gate (KEESM 13340). -- name: Case 15, mixed households evaluate Kansas LIEAP in one vectorized simulation. +- name: Case 6, mixed households evaluate Kansas LIEAP in one vectorized simulation. period: 2026 absolute_error_margin: 0.01 input: diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/payment/ks_liheap_income_band.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/payment/ks_liheap_income_band.yaml index bf08769dfee..3c62fcb1551 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/payment/ks_liheap_income_band.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/payment/ks_liheap_income_band.yaml @@ -199,3 +199,13 @@ output: # 14,400 / 12 = 1,200 -> "1,200 - 1,699" (KS_BenefitMatrix_2025.pdf rows) ks_liheap_income_band: 3 + +- name: Case 11, negative countable income is floored to the lowest band. + period: 2026 + absolute_error_margin: 0.01 + input: + state_code: KS + ks_liheap_countable_income: -5_000 + output: + # max(-5,000, 0) / 12 = 0 -> band 1 (0-899). + ks_liheap_income_band: 1 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/payment/ks_liheap_matrix_amount.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/payment/ks_liheap_matrix_amount.yaml index cfd2ef9fcda..cc42a2081e3 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/payment/ks_liheap_matrix_amount.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/payment/ks_liheap_matrix_amount.yaml @@ -142,7 +142,7 @@ # matrix p.1 (80%) 0-899 tier J, House, size 1-4 = 1,136 ks_liheap_matrix_amount: 1_136 -- name: Case 8, natural gas, band 1, tier E, house, family of five uses the 5+ column. +- name: Case 7, natural gas, band 1, tier E, house, family of five uses the 5+ column. period: 2026 absolute_error_margin: 0.01 input: @@ -174,7 +174,7 @@ # House = 810 ks_liheap_matrix_amount: 810 -- name: Case 9, natural gas, band 2, tier E, house. +- name: Case 8, natural gas, band 2, tier E, house. period: 2026 absolute_error_margin: 0.01 input: @@ -196,7 +196,7 @@ # 13,200 / 12 = 1,100 -> 900-1,199; matrix p.1 (80%) tier E, House = 638 ks_liheap_matrix_amount: 638 -- name: Case 10, natural gas, band 3, tier E, house. +- name: Case 9, natural gas, band 3, tier E, house. period: 2026 absolute_error_margin: 0.01 input: @@ -218,7 +218,7 @@ # 18,000 / 12 = 1,500 -> 1,200-1,699; matrix p.1 (80%) tier E, House = 567 ks_liheap_matrix_amount: 567 -- name: Case 11, natural gas, band 4, tier E, house. +- name: Case 10, natural gas, band 4, tier E, house. period: 2026 absolute_error_margin: 0.01 input: @@ -240,7 +240,7 @@ # 21,600 / 12 = 1,800 -> 1,700 & over; matrix p.1 (80%) tier E, House = 496 ks_liheap_matrix_amount: 496 -- name: Case 12, natural gas, band 2, tier G, duplex, size 5+. +- name: Case 11, natural gas, band 2, tier G, duplex, size 5+. period: 2026 absolute_error_margin: 0.01 input: @@ -271,7 +271,7 @@ # 1,100/mo -> 900-1,199; matrix p.1 (80%) tier G, Duplex, size 5+ = 585 ks_liheap_matrix_amount: 585 -- name: Case 13, electricity, band 1, tier E, house. +- name: Case 12, electricity, band 1, tier E, house. period: 2026 absolute_error_margin: 0.01 input: @@ -293,7 +293,7 @@ # matrix p.2 electricity (80%) 0-899 tier E, House, size 1-4 = 1,043 ks_liheap_matrix_amount: 1_043 -- name: Case 14, electricity, band 4, tier E, apartment, size 5+. +- name: Case 13, electricity, band 4, tier E, apartment, size 5+. period: 2026 absolute_error_margin: 0.01 input: @@ -325,7 +325,7 @@ # size 5+ = 417 ks_liheap_matrix_amount: 417 -- name: Case 15, electricity, band 3, tier H, trailer. +- name: Case 14, electricity, band 3, tier H, trailer. period: 2026 absolute_error_margin: 0.01 input: @@ -348,7 +348,7 @@ # size 1-4 = 232 ks_liheap_matrix_amount: 232 -- name: Case 17, propane, band 1, tier E, house. +- name: Case 15, propane, band 1, tier E, house. period: 2026 absolute_error_margin: 0.01 input: @@ -370,7 +370,7 @@ # matrix p.3 propane (80%) 0-899 tier E, House, size 1-4 = 553 ks_liheap_matrix_amount: 553 -- name: Case 18, propane, band 4, tier A, trailer returns the raw cell below the floor. +- name: Case 16, propane, band 4, tier A, trailer returns the raw cell below the floor. period: 2026 absolute_error_margin: 0.01 input: @@ -393,7 +393,7 @@ # size 1-4 = 75 (the $130 floor is applied in ks_liheap) ks_liheap_matrix_amount: 75 -- name: Case 19, propane, band 3, tier C, apartment, size 5+. +- name: Case 17, propane, band 3, tier C, apartment, size 5+. period: 2026 absolute_error_margin: 0.01 input: @@ -424,7 +424,7 @@ # 1,500/mo -> 1,200-1,699; matrix p.3 (80%) tier C, Apt, size 5+ = 233 ks_liheap_matrix_amount: 233 -- name: Case 20, wood heat uses the other table, band 1, house. +- name: Case 18, wood heat uses the other table, band 1, house. period: 2026 absolute_error_margin: 0.01 input: @@ -445,7 +445,7 @@ # matrix p.4 other (80%) 0-899, House, size 1-4 = 639 (no tier) ks_liheap_matrix_amount: 639 -- name: Case 21, fuel oil on the other table ignores the utility tier. +- name: Case 19, fuel oil on the other table ignores the utility tier. period: 2026 absolute_error_margin: 0.01 input: @@ -467,7 +467,7 @@ # matrix p.4 other (80%) 0-899, House, size 1-4 = 639 regardless of tier J ks_liheap_matrix_amount: 639 -- name: Case 22, other fuel, band 4, trailer, size 5+. +- name: Case 20, other fuel, band 4, trailer, size 5+. period: 2026 absolute_error_margin: 0.01 input: @@ -498,7 +498,7 @@ # size 5+ = 128 ks_liheap_matrix_amount: 128 -- name: Case 23, zero income lands in band 1. +- name: Case 21, zero income lands in band 1. period: 2026 absolute_error_margin: 0.01 input: @@ -520,7 +520,7 @@ # 0/mo -> 0-899; matrix p.1 (80%) tier E, House, size 1-4 = 709 ks_liheap_matrix_amount: 709 -- name: Case 24, FY2025 season pays the 100 percent natural gas value for the Case 1 household. +- name: Case 22, FY2025 season pays the 100 percent natural gas value for the Case 1 household. period: 2025 absolute_error_margin: 0.01 input: @@ -543,7 +543,7 @@ # (vs 709 at 80% in FY2026, Case 1) ks_liheap_matrix_amount: 941 -- name: Case 25, FY2025 electricity, band 1, tier E, house, size 5+. +- name: Case 23, FY2025 electricity, band 1, tier E, house, size 5+. period: 2025 absolute_error_margin: 0.01 input: @@ -571,10 +571,10 @@ members: [person1, person2, person3, person4, person5] state_code: KS output: - # KS_BenefitMatrix_2025.pdf p.2 (100%) 0-899 tier E, House, size 5+ = 1,584 + # KS_BenefitMatrix_2025.pdf p.1 (100%) 0-899 tier E, House, size 5+ = 1,584 ks_liheap_matrix_amount: 1_584 -- name: Case 26, FY2025 propane, band 2, tier J, duplex. +- name: Case 24, FY2025 propane, band 2, tier J, duplex. period: 2025 absolute_error_margin: 0.01 input: @@ -593,11 +593,11 @@ members: [person1] state_code: KS output: - # 1,100/mo -> 900-1,199; KS_BenefitMatrix_2025.pdf p.3 (100%) tier J, + # 1,100/mo -> 900-1,199; KS_BenefitMatrix_2025.pdf p.2 (100%) tier J, # Duplex, size 1-4 = 868 ks_liheap_matrix_amount: 868 -- name: Case 27, FY2025 other fuel, band 4, house. +- name: Case 25, FY2025 other fuel, band 4, house. period: 2025 absolute_error_margin: 0.01 input: @@ -615,6 +615,6 @@ members: [person1] state_code: KS output: - # 1,800/mo -> 1,700 & over; KS_BenefitMatrix_2025.pdf p.4 (100%) other, + # 1,800/mo -> 1,700 & over; KS_BenefitMatrix_2025.pdf p.3 (100%) other, # House, size 1-4 = 594 ks_liheap_matrix_amount: 594 diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/ks_liheap_fuel_category.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/ks_liheap_fuel_category.py index 11caa383909..bfe1084f89f 100644 --- a/policyengine_us/variables/gov/states/ks/dcf/liheap/ks_liheap_fuel_category.py +++ b/policyengine_us/variables/gov/states/ks/dcf/liheap/ks_liheap_fuel_category.py @@ -31,14 +31,12 @@ def formula(spm_unit, period, parameters): heating_type == types.SOLAR ) propane = heating_type == types.PROPANE - other = ~(natural_gas | electricity | propane) return select( - [natural_gas, electricity, propane, other], + [natural_gas, electricity, propane], [ KSLIEAPFuelCategory.NATURAL_GAS, KSLIEAPFuelCategory.ELECTRICITY, KSLIEAPFuelCategory.PROPANE, - KSLIEAPFuelCategory.OTHER, ], default=KSLIEAPFuelCategory.OTHER, ) diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/ks_liheap_household_size.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/ks_liheap_household_size.py index 0d3870842f8..5f83f198dea 100644 --- a/policyengine_us/variables/gov/states/ks/dcf/liheap/ks_liheap_household_size.py +++ b/policyengine_us/variables/gov/states/ks/dcf/liheap/ks_liheap_household_size.py @@ -15,4 +15,7 @@ class ks_liheap_household_size(Variable): # KEESM 13330 excludes ineligible members from size but retains their income. # It expressly includes refugees/asylees; do not substitute SNAP eligibility. + # Its size sentence names "citizens or lawful permanent residents", while + # its list of qualified aliens is broader. Counting every qualified status + # is an interpretation of that section, not an express instruction. adds = ["is_citizen_or_legal_immigrant"] From f0e9c030ac1957a433d0b2701e3be789bedb3cea Mon Sep 17 00:00:00 2001 From: Ziming Date: Thu, 1 Oct 2026 17:43:21 -0400 Subject: [PATCH 11/12] Shorten the Kansas LIEAP registry note Co-Authored-By: Claude Fable 5.1 --- policyengine_us/programs.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/policyengine_us/programs.yaml b/policyengine_us/programs.yaml index 42e444275b4..f1829ab2688 100644 --- a/policyengine_us/programs.yaml +++ b/policyengine_us/programs.yaml @@ -830,7 +830,7 @@ programs: variable: ks_liheap parameter_prefix: gov.states.ks.dcf.liheap verified_years: "2025-2026" - notes: Models regular heating assistance using FY2025 and FY2026 benefit matrices and income limits derived from 150% of the prior year's federal poverty guidelines, which reproduce the published limits. Annual income approximates the application month; the SPM unit approximates the energy household. Utility tier defaults to E and dwelling type to house/mobile. Self-employment income uses existing net income with each source floored at zero; the 25% standard expense deduction is not modeled. Special energy-vulnerability cases require a direct input. Some irregular receipts and source-specific income exemptions are not modeled. The FY2026 $130 minimum benefit comes from the state plan's estimated benefit levels (Section 2.6) and is applied as a floor; the benefit matrix itself prints cells below it. Cooling, crisis, weatherization, and equipment assistance are outside scope. + notes: FY2025-FY2026 regular heating only. The FY2026 $130 minimum comes from the plan's estimated benefit levels; crisis, cooling and weatherization assistance are out of scope. - state: TX status: partial name: Texas CEAP From d9a4e0870e51564af151edc599d47542b7b5fd8d Mon Sep 17 00:00:00 2001 From: Ziming Date: Fri, 2 Oct 2026 12:35:29 -0400 Subject: [PATCH 12/12] Address second Kansas LIEAP review Give every multi-page reference a single page in the link, with the pages named in the title or in a comment. Count partnership and S corporation income as earned income, floored at zero like the other business sources (KEESM 6300 and 6313), and farm rental income as unearned income (KEESM 6313). State the exact effective-date range in the rounding comment and correct two test header page cites. Co-Authored-By: Claude Fable 5.1 --- .../eligibility/rounding_increment.yaml | 6 ++-- .../ks/dcf/liheap/income/sources/earned.yaml | 13 ++++++-- .../dcf/liheap/income/sources/unearned.yaml | 9 +++++- .../liheap/payment/matrix/electricity.yaml | 6 ++-- .../liheap/payment/matrix/natural_gas.yaml | 4 +-- .../ks/dcf/liheap/payment/matrix/other.yaml | 4 +-- .../ks/dcf/liheap/payment/matrix/propane.yaml | 6 ++-- .../ks_liheap_countable_earned_income.yaml | 31 ++++++++++++++++++- .../income/ks_liheap_countable_income.yaml | 26 +++++++++++++++- .../gov/states/ks/dcf/liheap/integration.yaml | 4 +-- .../dcf/liheap/ks_liheap_fuel_category.yaml | 2 +- .../payment/ks_liheap_matrix_amount.yaml | 2 +- .../ks_liheap_countable_earned_income.py | 3 +- 13 files changed, 93 insertions(+), 23 deletions(-) diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/rounding_increment.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/rounding_increment.yaml index 8043d951884..330050af8d7 100644 --- a/policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/rounding_increment.yaml +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/eligibility/rounding_increment.yaml @@ -4,9 +4,9 @@ description: Kansas sets monthly income limits in increments of this amount unde # FY2026 matches nearest-dollar rounding of 150% of the 2025 guidelines, # including a separately rounded $688 increment for each person beyond eight. # The July 2025 KEESM edition is the first to carry the FY2026 limits; the -# 2025-10-01 date matches the federal program year and the FY2026 matrix. All -# Kansas LIEAP variables are annual, so any date in the 2025 season gives the -# same result. +# 2025-10-01 date matches the federal program year and the FY2026 matrix. +# Kansas LIEAP variables are annual and read the value in force on January 1, +# so any date from 2025-01-02 through 2026-01-01 gives the same result. values: 2024-10-01: 0.01 2025-10-01: 1 diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/earned.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/earned.yaml index c9afa36a34a..afc37e285d7 100644 --- a/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/earned.yaml +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/earned.yaml @@ -8,6 +8,11 @@ values: - self_employment_income - sstb_self_employment_income - farm_operations_income + # KEESM 6300 treats profit from performing services, including managerial + # responsibilities, as earned income, and KEESM 6313 bars deducting a loss + # from other income, so pass-through business income is floored with the + # other business sources. + - partnership_s_corp_income metadata: unit: list @@ -23,10 +28,14 @@ metadata: - title: KEESM 7122.1 Income Producing Cost Deduction, January 2026 edition (a loss from self-employment cannot be deducted from other income) href: https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm7122.htm - title: Kansas LIHEAP FY2026 State Plan, Section 1.8-1.9, pages 5-6 (gross income; wages, self-employment income, contract income and commissions counted) - href: https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=5,6 + href: https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=5 - title: Kansas LIHEAP FY2025 State Plan, Section 1.8-1.9, pages 5-6 (gross income; wages, self-employment income, contract income and commissions counted) - href: https://liheapch.acf.gov/docs/2025/state-plans/KS_Plan_2025.pdf#page=5,6 + href: https://liheapch.acf.gov/docs/2025/state-plans/KS_Plan_2025.pdf#page=5 - title: KEESM 13320 Household Definition, October 2024 edition (income of all household members living together is used) href: https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13300.htm - title: KEESM 13320 Household Definition, January 2026 edition (income of all household members living together is used) href: https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13300.htm + - title: KEESM 6313 Self-Employment, October 2024 edition (a loss from self-employment cannot be deducted from other income) + href: https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm6313.htm + - title: KEESM 6313 Self-Employment, January 2026 edition (a loss from self-employment cannot be deducted from other income) + href: https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm6313.htm diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/unearned.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/unearned.yaml index 606eb0ebb73..c31480fd362 100644 --- a/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/unearned.yaml +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/unearned.yaml @@ -10,6 +10,9 @@ values: - general_assistance - ks_tanf - rental_income + # KEESM 6313: income from rental property is unearned unless a household + # member actively manages it at least 20 hours a week. + - farm_rent_income - alimony_income - child_support_received # Plan counts "insurance payments made directly to the insured". @@ -33,7 +36,7 @@ metadata: - title: Kansas LIHEAP FY2026 State Plan, Section 1.9 (countable income sources) href: https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=6 - title: Kansas LIHEAP FY2025 State Plan, Section 1.9, pages 5-6 (countable income sources) - href: https://liheapch.acf.gov/docs/2025/state-plans/KS_Plan_2025.pdf#page=5,6 + href: https://liheapch.acf.gov/docs/2025/state-plans/KS_Plan_2025.pdf#page=5 - title: KEESM 13360-13361, October 2024 edition (countable income and specific exemptions) href: https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13360.htm - title: KEESM 13360-13361, January 2026 edition (countable income and specific exemptions) @@ -42,3 +45,7 @@ metadata: href: https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13300.htm - title: KEESM 13320 Household Definition, January 2026 edition (income of all household members living together is used) href: https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13300.htm + - title: KEESM 6313 Self-Employment, October 2024 edition (rental property income is unearned unless actively managed 20 hours a week) + href: https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm6313.htm + - title: KEESM 6313 Self-Employment, January 2026 edition (rental property income is unearned unless actively managed 20 hours a week) + href: https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm6313.htm diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/electricity.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/electricity.yaml index 680ba4b5c95..eb54672c321 100644 --- a/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/electricity.yaml +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/electricity.yaml @@ -1191,11 +1191,11 @@ metadata: - title: Kansas LIEAP FY2026 Benefit Matrix, Electricity (Benefit Adjustment @ 80% table) href: https://liheapch.acf.gov/docs/2026/benefits-matricies/KS_BenefitMatrix_2026.pdf#page=2 - title: Kansas LIEAP FY2025 Benefit Matrix, Electricity (Ben Adj 100.0%; pages 1-2) - href: https://liheapch.acf.gov/docs/2025/benefits-matricies/KS_BenefitMatrix_2025.pdf#page=1,2 + href: https://liheapch.acf.gov/docs/2025/benefits-matricies/KS_BenefitMatrix_2025.pdf#page=1 - title: Kansas LIHEAP FY2026 State Plan, Section 2.5, pages 8-9 (benefit variables) - href: https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=8,9 + href: https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=8 - title: Kansas LIHEAP FY2025 State Plan, Section 2.5, pages 8-9 (benefit variables) - href: https://liheapch.acf.gov/docs/2025/state-plans/KS_Plan_2025.pdf#page=8,9 + href: https://liheapch.acf.gov/docs/2025/state-plans/KS_Plan_2025.pdf#page=8 - title: KEESM 13410 Benefit Levels, October 2024 edition href: https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13400.htm - title: KEESM 13410 Benefit Levels, January 2026 edition diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/natural_gas.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/natural_gas.yaml index b5dd0c7bd27..e199f466019 100644 --- a/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/natural_gas.yaml +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/natural_gas.yaml @@ -1193,9 +1193,9 @@ metadata: - title: Kansas LIEAP FY2025 Benefit Matrix, Natural gas (Ben Adj 100.0%) href: https://liheapch.acf.gov/docs/2025/benefits-matricies/KS_BenefitMatrix_2025.pdf#page=1 - title: Kansas LIHEAP FY2026 State Plan, Section 2.5, pages 8-9 (benefit variables) - href: https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=8,9 + href: https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=8 - title: Kansas LIHEAP FY2025 State Plan, Section 2.5, pages 8-9 (benefit variables) - href: https://liheapch.acf.gov/docs/2025/state-plans/KS_Plan_2025.pdf#page=8,9 + href: https://liheapch.acf.gov/docs/2025/state-plans/KS_Plan_2025.pdf#page=8 - title: KEESM 13410 Benefit Levels, October 2024 edition href: https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13400.htm - title: KEESM 13410 Benefit Levels, January 2026 edition diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/other.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/other.yaml index 8cf1bd1b6c1..60d171fc3fa 100644 --- a/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/other.yaml +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/other.yaml @@ -143,9 +143,9 @@ metadata: - title: Kansas LIEAP FY2025 Benefit Matrix, Other fuels (Ben Adj 100.0%) href: https://liheapch.acf.gov/docs/2025/benefits-matricies/KS_BenefitMatrix_2025.pdf#page=3 - title: Kansas LIHEAP FY2026 State Plan, Section 2.5, pages 8-9 (benefit variables) - href: https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=8,9 + href: https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=8 - title: Kansas LIHEAP FY2025 State Plan, Section 2.5, pages 8-9 (benefit variables) - href: https://liheapch.acf.gov/docs/2025/state-plans/KS_Plan_2025.pdf#page=8,9 + href: https://liheapch.acf.gov/docs/2025/state-plans/KS_Plan_2025.pdf#page=8 - title: KEESM 13410 Benefit Levels, October 2024 edition href: https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13400.htm - title: KEESM 13410 Benefit Levels, January 2026 edition diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/propane.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/propane.yaml index d7cc704effd..a9ab2a86ff4 100644 --- a/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/propane.yaml +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/payment/matrix/propane.yaml @@ -1191,11 +1191,11 @@ metadata: - title: Kansas LIEAP FY2026 Benefit Matrix, Propane (Benefit Adjustment @ 80% table) href: https://liheapch.acf.gov/docs/2026/benefits-matricies/KS_BenefitMatrix_2026.pdf#page=3 - title: Kansas LIEAP FY2025 Benefit Matrix, Propane (Ben Adj 100.0%; pages 2-3) - href: https://liheapch.acf.gov/docs/2025/benefits-matricies/KS_BenefitMatrix_2025.pdf#page=2,3 + href: https://liheapch.acf.gov/docs/2025/benefits-matricies/KS_BenefitMatrix_2025.pdf#page=2 - title: Kansas LIHEAP FY2026 State Plan, Section 2.5, pages 8-9 (benefit variables) - href: https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=8,9 + href: https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=8 - title: Kansas LIHEAP FY2025 State Plan, Section 2.5, pages 8-9 (benefit variables) - href: https://liheapch.acf.gov/docs/2025/state-plans/KS_Plan_2025.pdf#page=8,9 + href: https://liheapch.acf.gov/docs/2025/state-plans/KS_Plan_2025.pdf#page=8 - title: KEESM 13410 Benefit Levels, October 2024 edition href: https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm13400.htm - title: KEESM 13410 Benefit Levels, January 2026 edition diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_earned_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_earned_income.yaml index f72313d566a..d26339e589c 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_earned_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_earned_income.yaml @@ -1,5 +1,5 @@ # Kansas LIEAP countable earned income per person (KS LIHEAP State Plan FY2026 -# 1.8-1.9, #page=6,7): gross wages and self-employment income are counted, +# 1.8-1.9, pages 5-7): gross wages and self-employment income are counted, # except the earned income of a child under 18. KEESM 13320: a member who is # or turns 18 in the application month has countable income. # Modeling simplification: use existing net business income directly, without @@ -146,3 +146,32 @@ output: ks_liheap_countable_earned_income: [12_000, 0, 6_000] ks_liheap_countable_income: 18_000 + +- name: Case 9, partnership and S corporation profit is counted and a loss does not offset wages. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 45 + # 10 an hour, 40 hours a week: 10 * 2,080 = 20,800. + employment_income: 20_800 + partnership_s_corp_income: 9_000 + person2: + age: 43 + employment_income: 20_800 + partnership_s_corp_income: -4_000 + spm_units: + spm_unit: + members: [person1, person2] + ks_tanf: 0 + households: + household: + members: [person1, person2] + state_code: KS + output: + # KEESM 6313: a loss cannot be deducted from other income, so each source + # is floored at zero before the sources are added. + # person1: 20,800 + 9,000 = 29,800. person2: 20,800 + max(-4,000, 0) = 20,800. + ks_liheap_countable_earned_income: [29_800, 20_800] + ks_liheap_countable_income: 50_600 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_income.yaml index fe5bad2aab3..9662fb1dd66 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_income.yaml @@ -1,5 +1,5 @@ # Kansas LIEAP countable gross income (KS LIHEAP State Plan FY2026 sections -# 1.8-1.9, #page=5,6; KEESM 13320). Counted: wages, self-employment, +# 1.8-1.9, pages 5-7; KEESM 13320). Counted: wages, self-employment, # unemployment insurance, SSA benefits, SSI, retirement/pension, TANF, child # support, alimony, rental income, VA benefits and recurring adult interest. # Earned income of children under 18 is excluded. Income of other @@ -218,3 +218,27 @@ ks_liheap_countable_unearned_income: 7_200 # 0 earned income + 7,200 unearned income = 7,200. ks_liheap_countable_income: 7_200 + +- name: Case 10, farm rental income is counted as unearned income. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 45 + # 600 a month from leased farmland. + farm_rent_income: 7_200 + spm_units: + spm_unit: + members: [person1] + ks_tanf: 0 + households: + household: + members: [person1] + state_code: KS + output: + # KEESM 6313: income from rental property is unearned unless a household + # member actively manages it at least 20 hours a week. + ks_liheap_countable_unearned_income: 7_200 + # 0 earned income + 7,200 unearned income = 7,200. + ks_liheap_countable_income: 7_200 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/integration.yaml index 58a3f3b278a..1bc6748609d 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/integration.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/integration.yaml @@ -1,8 +1,8 @@ # Kansas LIEAP end-to-end integration tests. # Sources: KEESM 13100-13400 (eligibility, household, citizenship, energy # vulnerability, benefit levels); KS LIHEAP State Plan FY2026 (income sources -# 1.8-1.9 #page=5,6, income verification 1.4 #page=5, 150% FPG 2.1 and -# subsidized housing 2.3 #page=8, $130 minimum 2.6 #page=9); +# 1.8-1.9 pages 5-7, income verification 1.4 page 5, 150% FPG 2.1 and +# subsidized housing 2.3 page 8, $130 minimum 2.6 page 9); # KS_BenefitMatrix_2026.pdf (FY2026 season, "Benefit Adjustment @ 80%" table); # KS_BenefitMatrix_2025.pdf (FY2025 season, 100%). # Annualized published monthly income limits (KEESM 13362): diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/ks_liheap_fuel_category.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/ks_liheap_fuel_category.yaml index 9e80275c403..6f697039865 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/ks_liheap_fuel_category.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/ks_liheap_fuel_category.yaml @@ -1,5 +1,5 @@ # Kansas LIEAP primary heating fuel category (KEESM 13410; KS LIHEAP State -# Plan FY2026 2.5, #page=8,9; KS_BenefitMatrix_2026.pdf pages 1-4: Natural Gas, +# Plan FY2026 2.5, pages 8-9; KS_BenefitMatrix_2026.pdf pages 1-4: Natural Gas, # Electricity, Propane, Other). Mapping from the canonical heating_type input: # NATURAL_GAS -> natural gas; ELECTRICITY, SOLAR -> electricity; PROPANE -> # propane; FUEL_OIL, KEROSENE, WOOD, COAL, OTHER, UNSPECIFIED -> other. diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/payment/ks_liheap_matrix_amount.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/payment/ks_liheap_matrix_amount.yaml index cc42a2081e3..ade8314f6fe 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/payment/ks_liheap_matrix_amount.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/payment/ks_liheap_matrix_amount.yaml @@ -1,5 +1,5 @@ # Kansas LIEAP benefit matrix lookup (KEESM 13410; KS LIHEAP State Plan FY2026 -# 2.5, #page=8,9). Dimensions: primary fuel table (natural gas p.1, +# 2.5, pages 8-9). Dimensions: primary fuel table (natural gas p.1, # electricity p.2, propane p.3, other p.4 of KS_BenefitMatrix_2026.pdf), # one-month income band, utility range tier A-J (no tier on the Other table), # dwelling type (House/Modular/Mobile, Duplex, Apt, Trailer/Other) and diff --git a/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_earned_income.py b/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_earned_income.py index bb9ccc36ee0..24a8651ff60 100644 --- a/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_earned_income.py +++ b/policyengine_us/variables/gov/states/ks/dcf/liheap/income/ks_liheap_countable_earned_income.py @@ -22,7 +22,8 @@ class ks_liheap_countable_earned_income(Variable): "https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm13360.htm", "https://content.dcf.ks.gov/ees/KEESM/Robo10-24/Robo_10_01_24/keesm7122.htm", "https://content.dcf.ks.gov/ees/KEESM/Robo01-26/Robo_01_01_26/keesm7122.htm", - "https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=6,7", + # Section 1.9 (pages 6-7). + "https://liheapch.acf.gov/docs/2026/state-plans/KS_Plan_2026.pdf#page=6", ) defined_for = StateCode.KS