From 27350c703583cf9c05b6d03238f4a595c32fdd04 Mon Sep 17 00:00:00 2001 From: Ziming Date: Sat, 3 Oct 2026 19:28:51 -0400 Subject: [PATCH 01/10] Add Idaho LIHEAP household and income components --- changelog.d/id-liheap-wave2c.added.md | 1 + .../id/dhw/liheap/eligibility/fpg_rate.yaml | 11 ++ .../dhw/liheap/eligibility/fpg_year_lag.yaml | 11 ++ .../eligibility/smi_max_household_size.yaml | 11 ++ .../id/dhw/liheap/eligibility/smi_rate.yaml | 11 ++ .../liheap/income/earned_income_min_age.yaml | 11 ++ .../id/dhw/liheap/income/sources/earned.yaml | 16 ++ .../dhw/liheap/income/sources/unearned.yaml | 26 +++ policyengine_us/programs.yaml | 9 +- .../eligibility/id_liheap_household_size.yaml | 63 +++++++ .../eligibility/id_liheap_income_limit.yaml | 154 ++++++++++++++++++ .../income/id_liheap_countable_income.yaml | 150 +++++++++++++++++ .../eligibility/id_liheap_household_size.py | 12 ++ .../eligibility/id_liheap_income_limit.py | 45 +++++ .../income/id_liheap_countable_income.py | 29 ++++ 15 files changed, 559 insertions(+), 1 deletion(-) create mode 100644 changelog.d/id-liheap-wave2c.added.md create mode 100644 policyengine_us/parameters/gov/states/id/dhw/liheap/eligibility/fpg_rate.yaml create mode 100644 policyengine_us/parameters/gov/states/id/dhw/liheap/eligibility/fpg_year_lag.yaml create mode 100644 policyengine_us/parameters/gov/states/id/dhw/liheap/eligibility/smi_max_household_size.yaml create mode 100644 policyengine_us/parameters/gov/states/id/dhw/liheap/eligibility/smi_rate.yaml create mode 100644 policyengine_us/parameters/gov/states/id/dhw/liheap/income/earned_income_min_age.yaml create mode 100644 policyengine_us/parameters/gov/states/id/dhw/liheap/income/sources/earned.yaml create mode 100644 policyengine_us/parameters/gov/states/id/dhw/liheap/income/sources/unearned.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/eligibility/id_liheap_household_size.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/eligibility/id_liheap_income_limit.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/income/id_liheap_countable_income.yaml create mode 100644 policyengine_us/variables/gov/states/id/dhw/liheap/eligibility/id_liheap_household_size.py create mode 100644 policyengine_us/variables/gov/states/id/dhw/liheap/eligibility/id_liheap_income_limit.py create mode 100644 policyengine_us/variables/gov/states/id/dhw/liheap/income/id_liheap_countable_income.py diff --git a/changelog.d/id-liheap-wave2c.added.md b/changelog.d/id-liheap-wave2c.added.md new file mode 100644 index 00000000000..b7a8a6f6eac --- /dev/null +++ b/changelog.d/id-liheap-wave2c.added.md @@ -0,0 +1 @@ +Add Idaho LIHEAP countable income, qualified household size and income-limit calculations; the heating benefit calculation remains incomplete. diff --git a/policyengine_us/parameters/gov/states/id/dhw/liheap/eligibility/fpg_rate.yaml b/policyengine_us/parameters/gov/states/id/dhw/liheap/eligibility/fpg_rate.yaml new file mode 100644 index 00000000000..2b110f55bb0 --- /dev/null +++ b/policyengine_us/parameters/gov/states/id/dhw/liheap/eligibility/fpg_rate.yaml @@ -0,0 +1,11 @@ +description: Idaho limits household income to this multiple of federal poverty guidelines for larger households under the Low Income Home Energy Assistance Program. +values: + 2025-10-01: 1.5 + +metadata: + unit: /1 + period: year + label: Idaho LIHEAP FPG rate + reference: + - title: Idaho FY2026 LIHEAP State Plan + href: https://liheapch.acf.gov/docs/2026/state-plans/ID_Plan_2026.pdf#page=8 diff --git a/policyengine_us/parameters/gov/states/id/dhw/liheap/eligibility/fpg_year_lag.yaml b/policyengine_us/parameters/gov/states/id/dhw/liheap/eligibility/fpg_year_lag.yaml new file mode 100644 index 00000000000..74a2efb431d --- /dev/null +++ b/policyengine_us/parameters/gov/states/id/dhw/liheap/eligibility/fpg_year_lag.yaml @@ -0,0 +1,11 @@ +description: Idaho uses federal poverty guidelines from this many years before the benefit fiscal year under the Low Income Home Energy Assistance Program. +values: + 2025-10-01: 1 + +metadata: + unit: year + period: year + label: Idaho LIHEAP FPG year lag + reference: + - title: Idaho FY2026 LIHEAP State Plan + href: https://liheapch.acf.gov/docs/2026/state-plans/ID_Plan_2026.pdf#page=8 diff --git a/policyengine_us/parameters/gov/states/id/dhw/liheap/eligibility/smi_max_household_size.yaml b/policyengine_us/parameters/gov/states/id/dhw/liheap/eligibility/smi_max_household_size.yaml new file mode 100644 index 00000000000..83501dcb915 --- /dev/null +++ b/policyengine_us/parameters/gov/states/id/dhw/liheap/eligibility/smi_max_household_size.yaml @@ -0,0 +1,11 @@ +description: Idaho uses state median income limits for households up to this size under the Low Income Home Energy Assistance Program. +values: + 2025-10-01: 7 + +metadata: + unit: person + period: year + label: Idaho LIHEAP maximum household size for SMI limits + reference: + - title: Idaho FY2026 LIHEAP State Plan + href: https://liheapch.acf.gov/docs/2026/state-plans/ID_Plan_2026.pdf#page=8 diff --git a/policyengine_us/parameters/gov/states/id/dhw/liheap/eligibility/smi_rate.yaml b/policyengine_us/parameters/gov/states/id/dhw/liheap/eligibility/smi_rate.yaml new file mode 100644 index 00000000000..bd0f65e6a8e --- /dev/null +++ b/policyengine_us/parameters/gov/states/id/dhw/liheap/eligibility/smi_rate.yaml @@ -0,0 +1,11 @@ +description: Idaho limits household income to this share of state median income for smaller households under the Low Income Home Energy Assistance Program. +values: + 2025-10-01: 0.6 + +metadata: + unit: /1 + period: year + label: Idaho LIHEAP SMI rate + reference: + - title: Idaho FY2026 LIHEAP State Plan + href: https://liheapch.acf.gov/docs/2026/state-plans/ID_Plan_2026.pdf#page=8 diff --git a/policyengine_us/parameters/gov/states/id/dhw/liheap/income/earned_income_min_age.yaml b/policyengine_us/parameters/gov/states/id/dhw/liheap/income/earned_income_min_age.yaml new file mode 100644 index 00000000000..a6965e9e8a1 --- /dev/null +++ b/policyengine_us/parameters/gov/states/id/dhw/liheap/income/earned_income_min_age.yaml @@ -0,0 +1,11 @@ +description: Idaho counts earned income of members this age or older under the Low Income Home Energy Assistance Program. +values: + 2025-10-01: 18 + +metadata: + unit: year + period: year + label: Idaho LIHEAP minimum age for earned income + reference: + - title: Idaho FY2026 LIHEAP State Plan + href: https://liheapch.acf.gov/docs/2026/state-plans/ID_Plan_2026.pdf#page=6 diff --git a/policyengine_us/parameters/gov/states/id/dhw/liheap/income/sources/earned.yaml b/policyengine_us/parameters/gov/states/id/dhw/liheap/income/sources/earned.yaml new file mode 100644 index 00000000000..86bc47876e6 --- /dev/null +++ b/policyengine_us/parameters/gov/states/id/dhw/liheap/income/sources/earned.yaml @@ -0,0 +1,16 @@ +description: Idaho counts these earned income sources under the Low Income Home Energy Assistance Program. +values: + 2025-10-01: + - employment_income + - self_employment_income + - sstb_self_employment_income + - farm_operations_income + - partnership_s_corp_income + +metadata: + unit: list + period: year + label: Idaho LIHEAP countable earned income sources + reference: + - title: Idaho FY2026 LIHEAP State Plan + href: https://liheapch.acf.gov/docs/2026/state-plans/ID_Plan_2026.pdf#page=5,6,7 diff --git a/policyengine_us/parameters/gov/states/id/dhw/liheap/income/sources/unearned.yaml b/policyengine_us/parameters/gov/states/id/dhw/liheap/income/sources/unearned.yaml new file mode 100644 index 00000000000..92a7af57293 --- /dev/null +++ b/policyengine_us/parameters/gov/states/id/dhw/liheap/income/sources/unearned.yaml @@ -0,0 +1,26 @@ +description: Idaho counts these unearned income sources under the Low Income Home Energy Assistance Program. +values: + 2025-10-01: + - social_security + - ssi + - pension_income + - survivor_benefits + - unemployment_compensation + - strike_benefits + - rental_income + - farm_rent_income + - alimony_income + - interest_income + - ordinary_dividend_income + - estate_income + - disability_benefits + - workers_compensation + - id_tafi + +metadata: + unit: list + period: year + label: Idaho LIHEAP countable unearned income sources + reference: + - title: Idaho FY2026 LIHEAP State Plan + href: https://liheapch.acf.gov/docs/2026/state-plans/ID_Plan_2026.pdf#page=5,6,7 diff --git a/policyengine_us/programs.yaml b/policyengine_us/programs.yaml index 756dc2c4988..2817b23b426 100644 --- a/policyengine_us/programs.yaml +++ b/policyengine_us/programs.yaml @@ -802,7 +802,7 @@ programs: category: Benefits agency: HHS status: partial - coverage: OR, DC, Riverside County, MA, IL, KS, MS, TX + coverage: OR, DC, Riverside County, MA, IL, KS, MS, TX, ID state_implementations: - state: OR status: in_progress @@ -839,6 +839,13 @@ programs: parameter_prefix: gov.states.ms.mdhs.liheap verified_years: "2026" notes: FY2026 regular assistance for heating fuel and electric bills, using the published matrix as printed. Crisis assistance and energy equipment are out of scope. + - state: ID + status: in_progress + name: Idaho LIHEAP + full_name: Idaho Low Income Home Energy Assistance Program + parameter_prefix: gov.states.id.dhw.liheap + verified_years: "2026" + notes: FY2026 household size, countable income and income-limit components only. No final eligibility or benefit award; provider and area heating-cost mapping and categorical-income treatment remain unresolved. Annual flows approximate prior-month income. Earlier backfilled results are unverified historical estimates. - state: TX status: partial name: Texas CEAP diff --git a/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/eligibility/id_liheap_household_size.yaml b/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/eligibility/id_liheap_household_size.yaml new file mode 100644 index 00000000000..f026288cf1a --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/eligibility/id_liheap_household_size.yaml @@ -0,0 +1,63 @@ +# Idaho FY2026 LIHEAP plan, qualified household membership (page9). +# https://liheapch.acf.gov/docs/2026/state-plans/ID_Plan_2026.pdf#page=9 +# IDAPA16.03.08 sections201-202, shared economic household (pages5-6). +# https://adminrules.idaho.gov/rules/current/16/160308.pdf#page=5,6 + +- name: Case 1, citizen child counts while nonqualified parent does not. + period: 2026 + # REQ002: one qualified child; the adult status cannot erase the child. + input: + people: + person1: {age: 35, is_citizen_or_legal_immigrant: false, employment_income: 20_000, ssi: 0} + person2: {age: 8, is_citizen_or_legal_immigrant: true, ssi: 0} + spm_units: + spm_unit: {members: [person1, person2], heating_type: NATURAL_GAS, gas_expense: 1_000} + households: + household: {members: [person1, person2], state_code: ID} + output: + id_liheap_household_size: 1 + +- name: Case 2, all nonqualified members give zero eligible size. + period: 2026 + # REQ002: neither member satisfies the citizenship or qualified-status rule. + input: + people: + person1: {age: 35, is_citizen_or_legal_immigrant: false, ssi: 0} + person2: {age: 8, is_citizen_or_legal_immigrant: false, ssi: 0} + spm_units: + spm_unit: {members: [person1, person2], heating_type: NATURAL_GAS, gas_expense: 1_000} + households: + household: {members: [person1, person2], state_code: ID} + output: + id_liheap_household_size: 0 + +- name: Case 3, qualified foster child remains a household member. + period: 2026 + # REQ002: no Idaho source excludes a qualified foster member from size. + input: + people: + person1: {age: 35, is_citizen_or_legal_immigrant: true, ssi: 0} + person2: {age: 8, is_citizen_or_legal_immigrant: true, ssi: 0, is_in_foster_care: {2026-01: true}} + spm_units: + spm_unit: {members: [person1, person2], heating_type: NATURAL_GAS, gas_expense: 1_000} + households: + household: {members: [person1, person2], state_code: ID} + output: + id_liheap_household_size: 2 + +- name: Case 4, mixed states keep Idaho size separate. + period: 2026 + # REQ002/state scope: qualified Idaho pair counts; Colorado is outside this component. + input: + people: + person1: {age: 35, is_citizen_or_legal_immigrant: true, ssi: 0} + person2: {age: 8, is_citizen_or_legal_immigrant: true, ssi: 0} + person3: {age: 40, is_citizen_or_legal_immigrant: true, ssi: 0} + spm_units: + spm_unit1: {members: [person1, person2], heating_type: NATURAL_GAS, gas_expense: 1_000} + spm_unit2: {members: [person3], heating_type: NATURAL_GAS, gas_expense: 1_000} + households: + household1: {members: [person1, person2], state_code: ID} + household2: {members: [person3], state_code: CO} + output: + id_liheap_household_size: [2, 0] diff --git a/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/eligibility/id_liheap_income_limit.yaml b/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/eligibility/id_liheap_income_limit.yaml new file mode 100644 index 00000000000..b11d90778a6 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/eligibility/id_liheap_income_limit.yaml @@ -0,0 +1,154 @@ +# Idaho FY2026 LIHEAP plan, 60%SMI for sizes1-7 and150%FPG for8+ (page8). +# https://liheapch.acf.gov/docs/2026/state-plans/ID_Plan_2026.pdf#page=8 +# DHW published monthly limits effective2025-10-01; retrieved2026-10-03. +# https://healthandwelfare.idaho.gov/services-programs/financial-assistance/home-heating-and-utility-assistance/apply-heating-assistance + +- name: Case 1, all published monthly limits and additional person amounts annualize exactly. + period: 2026 + absolute_error_margin: 0.01 + # REQ005: sizes1-10 use published monthly [2736.25,3578.17,4420.08,5262.08, + # 6104,6945.92,7103.75,6768.75,7456.25,8143.75] times12. + # Size11 = (8143.75 +687.50)*12 =105975; size15 = (8143.75 +5*687.50)*12 =138975. + # Size7 annual85245 exceeds size8 annual81225: the explicit SMI-to-FPG switch is not max(). + input: + people: + person1: {age: 40, is_citizen_or_legal_immigrant: true} + person2: {age: 40, is_citizen_or_legal_immigrant: true} + person3: {age: 38, is_citizen_or_legal_immigrant: true} + person4: {age: 40, is_citizen_or_legal_immigrant: true} + person5: {age: 38, is_citizen_or_legal_immigrant: true} + person6: {age: 17, is_citizen_or_legal_immigrant: true} + person7: {age: 40, is_citizen_or_legal_immigrant: true} + person8: {age: 38, is_citizen_or_legal_immigrant: true} + person9: {age: 17, is_citizen_or_legal_immigrant: true} + person10: {age: 16, is_citizen_or_legal_immigrant: true} + person11: {age: 40, is_citizen_or_legal_immigrant: true} + person12: {age: 38, is_citizen_or_legal_immigrant: true} + person13: {age: 17, is_citizen_or_legal_immigrant: true} + person14: {age: 16, is_citizen_or_legal_immigrant: true} + person15: {age: 15, is_citizen_or_legal_immigrant: true} + person16: {age: 40, is_citizen_or_legal_immigrant: true} + person17: {age: 38, is_citizen_or_legal_immigrant: true} + person18: {age: 17, is_citizen_or_legal_immigrant: true} + person19: {age: 16, is_citizen_or_legal_immigrant: true} + person20: {age: 15, is_citizen_or_legal_immigrant: true} + person21: {age: 14, is_citizen_or_legal_immigrant: true} + person22: {age: 40, is_citizen_or_legal_immigrant: true} + person23: {age: 38, is_citizen_or_legal_immigrant: true} + person24: {age: 17, is_citizen_or_legal_immigrant: true} + person25: {age: 16, is_citizen_or_legal_immigrant: true} + person26: {age: 15, is_citizen_or_legal_immigrant: true} + person27: {age: 14, is_citizen_or_legal_immigrant: true} + person28: {age: 13, is_citizen_or_legal_immigrant: true} + person29: {age: 40, is_citizen_or_legal_immigrant: true} + person30: {age: 38, is_citizen_or_legal_immigrant: true} + person31: {age: 17, is_citizen_or_legal_immigrant: true} + person32: {age: 16, is_citizen_or_legal_immigrant: true} + person33: {age: 15, is_citizen_or_legal_immigrant: true} + person34: {age: 14, is_citizen_or_legal_immigrant: true} + person35: {age: 13, is_citizen_or_legal_immigrant: true} + person36: {age: 12, is_citizen_or_legal_immigrant: true} + person37: {age: 40, is_citizen_or_legal_immigrant: true} + person38: {age: 38, is_citizen_or_legal_immigrant: true} + person39: {age: 17, is_citizen_or_legal_immigrant: true} + person40: {age: 16, is_citizen_or_legal_immigrant: true} + person41: {age: 15, is_citizen_or_legal_immigrant: true} + person42: {age: 14, is_citizen_or_legal_immigrant: true} + person43: {age: 13, is_citizen_or_legal_immigrant: true} + person44: {age: 12, is_citizen_or_legal_immigrant: true} + person45: {age: 11, is_citizen_or_legal_immigrant: true} + person46: {age: 40, is_citizen_or_legal_immigrant: true} + person47: {age: 38, is_citizen_or_legal_immigrant: true} + person48: {age: 17, is_citizen_or_legal_immigrant: true} + person49: {age: 16, is_citizen_or_legal_immigrant: true} + person50: {age: 15, is_citizen_or_legal_immigrant: true} + person51: {age: 14, is_citizen_or_legal_immigrant: true} + person52: {age: 13, is_citizen_or_legal_immigrant: true} + person53: {age: 12, is_citizen_or_legal_immigrant: true} + person54: {age: 11, is_citizen_or_legal_immigrant: true} + person55: {age: 10, is_citizen_or_legal_immigrant: true} + person56: {age: 40, is_citizen_or_legal_immigrant: true} + person57: {age: 38, is_citizen_or_legal_immigrant: true} + person58: {age: 17, is_citizen_or_legal_immigrant: true} + person59: {age: 16, is_citizen_or_legal_immigrant: true} + person60: {age: 15, is_citizen_or_legal_immigrant: true} + person61: {age: 14, is_citizen_or_legal_immigrant: true} + person62: {age: 13, is_citizen_or_legal_immigrant: true} + person63: {age: 12, is_citizen_or_legal_immigrant: true} + person64: {age: 11, is_citizen_or_legal_immigrant: true} + person65: {age: 10, is_citizen_or_legal_immigrant: true} + person66: {age: 9, is_citizen_or_legal_immigrant: true} + person67: {age: 40, is_citizen_or_legal_immigrant: true} + person68: {age: 38, is_citizen_or_legal_immigrant: true} + person69: {age: 17, is_citizen_or_legal_immigrant: true} + person70: {age: 16, is_citizen_or_legal_immigrant: true} + person71: {age: 15, is_citizen_or_legal_immigrant: true} + person72: {age: 14, is_citizen_or_legal_immigrant: true} + person73: {age: 13, is_citizen_or_legal_immigrant: true} + person74: {age: 12, is_citizen_or_legal_immigrant: true} + person75: {age: 11, is_citizen_or_legal_immigrant: true} + person76: {age: 10, is_citizen_or_legal_immigrant: true} + person77: {age: 9, is_citizen_or_legal_immigrant: true} + person78: {age: 8, is_citizen_or_legal_immigrant: true} + person79: {age: 7, is_citizen_or_legal_immigrant: true} + person80: {age: 6, is_citizen_or_legal_immigrant: true} + person81: {age: 5, is_citizen_or_legal_immigrant: true} + spm_units: + spm_unit1: {members: [person1], heating_type: NATURAL_GAS, gas_expense: 1_000} + spm_unit2: {members: [person2, person3], heating_type: NATURAL_GAS, gas_expense: 1_000} + spm_unit3: {members: [person4, person5, person6], heating_type: NATURAL_GAS, gas_expense: 1_000} + spm_unit4: {members: [person7, person8, person9, person10], heating_type: NATURAL_GAS, gas_expense: 1_000} + spm_unit5: {members: [person11, person12, person13, person14, person15], heating_type: NATURAL_GAS, gas_expense: 1_000} + spm_unit6: {members: [person16, person17, person18, person19, person20, person21], heating_type: NATURAL_GAS, gas_expense: 1_000} + spm_unit7: {members: [person22, person23, person24, person25, person26, person27, person28], heating_type: NATURAL_GAS, gas_expense: 1_000} + spm_unit8: {members: [person29, person30, person31, person32, person33, person34, person35, person36], heating_type: NATURAL_GAS, gas_expense: 1_000} + spm_unit9: {members: [person37, person38, person39, person40, person41, person42, person43, person44, person45], heating_type: NATURAL_GAS, gas_expense: 1_000} + spm_unit10: {members: [person46, person47, person48, person49, person50, person51, person52, person53, person54, person55], heating_type: NATURAL_GAS, gas_expense: 1_000} + spm_unit11: {members: [person56, person57, person58, person59, person60, person61, person62, person63, person64, person65, person66], heating_type: NATURAL_GAS, gas_expense: 1_000} + spm_unit12: {members: [person67, person68, person69, person70, person71, person72, person73, person74, person75, person76, person77, person78, person79, person80, person81], heating_type: NATURAL_GAS, gas_expense: 1_000} + households: + household1: {members: [person1], state_code: ID} + household2: {members: [person2, person3], state_code: ID} + household3: {members: [person4, person5, person6], state_code: ID} + household4: {members: [person7, person8, person9, person10], state_code: ID} + household5: {members: [person11, person12, person13, person14, person15], state_code: ID} + household6: {members: [person16, person17, person18, person19, person20, person21], state_code: ID} + household7: {members: [person22, person23, person24, person25, person26, person27, person28], state_code: ID} + household8: {members: [person29, person30, person31, person32, person33, person34, person35, person36], state_code: ID} + household9: {members: [person37, person38, person39, person40, person41, person42, person43, person44, person45], state_code: ID} + household10: {members: [person46, person47, person48, person49, person50, person51, person52, person53, person54, person55], state_code: ID} + household11: {members: [person56, person57, person58, person59, person60, person61, person62, person63, person64, person65, person66], state_code: ID} + household12: {members: [person67, person68, person69, person70, person71, person72, person73, person74, person75, person76, person77, person78, person79, person80, person81], state_code: ID} + output: + id_liheap_income_limit: [32_835.0, 42_938.04, 53_040.96, 63_144.96, 73_248.0, 83_351.04, 85_245.0, 81_225.0, 89_475.0, 97_725.0, 105_975.0, 138_975.0] + +- name: Case 2, no qualified member has zero income limit. + period: 2026 + absolute_error_margin: 0.01 + # REQ002/005: no eligible household member means no applicable income ceiling. + input: + people: + person1: {age: 40, is_citizen_or_legal_immigrant: false} + spm_units: + spm_unit: {members: [person1], heating_type: NATURAL_GAS, gas_expense: 1_000} + households: + household: {members: [person1], state_code: ID} + output: + id_liheap_income_limit: 0 + +- name: Case 3, mixed state vector preserves the Idaho limit and masks another state. + period: 2026 + absolute_error_margin: 0.01 + # REQ005/state scope: Idaho one-person monthly2736.25*12=32835; California0. + input: + people: + person1: {age: 40, is_citizen_or_legal_immigrant: true} + person2: {age: 40, is_citizen_or_legal_immigrant: true} + spm_units: + spm_unit1: {members: [person1], heating_type: NATURAL_GAS, gas_expense: 1_000} + spm_unit2: {members: [person2], heating_type: NATURAL_GAS, gas_expense: 1_000} + households: + household1: {members: [person1], state_code: ID} + household2: {members: [person2], state_code: CA} + output: + id_liheap_income_limit: [32_835, 0] diff --git a/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/income/id_liheap_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/income/id_liheap_countable_income.yaml new file mode 100644 index 00000000000..cdeef01f68f --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/income/id_liheap_countable_income.yaml @@ -0,0 +1,150 @@ +# Idaho FY2026 LIHEAP plan, gross income checkboxes and other-income text (pages5-7). +# https://liheapch.acf.gov/docs/2026/state-plans/ID_Plan_2026.pdf#page=5,6,7 +# IDAPA16.03.08 section202 includes income of nonqualified household members (page6). +# https://adminrules.idaho.gov/rules/current/16/160308.pdf#page=6 + +- name: Case 1, minor earnings are excluded but child SSI is included. + period: 2026 + absolute_error_margin: 0.01 + # REQ003-004: adult12000 + childSSI(100/month*12)=13200; child wages, support, VA and GA excluded. + # SSI input1200 is the annual amount for a MONTH variable in a YEAR test. + input: + people: + person1: {age: 35, is_citizen_or_legal_immigrant: true, ssi: 0, employment_income: 12_000} + person2: {age: 17, is_citizen_or_legal_immigrant: true, employment_income: 6_000, ssi: 1_200, child_support_received: 6_000, veterans_benefits: 3_000, general_assistance: 900} + spm_units: + spm_unit: {members: [person1, person2], heating_type: NATURAL_GAS, gas_expense: 1_000, id_tafi: 0} + households: + household: {members: [person1, person2], state_code: ID} + output: + id_liheap_countable_income: 13_200 + +- name: Case 2, earnings count at the eighteenth birthday. + period: 2026 + absolute_error_margin: 0.01 + # REQ003: child is now18, so both12000 adult wages and6000 earnings count. + input: + people: + person1: {age: 35, is_citizen_or_legal_immigrant: true, ssi: 0, employment_income: 12_000} + person2: {age: 18, is_citizen_or_legal_immigrant: true, ssi: 0, employment_income: 6_000} + spm_units: + spm_unit: {members: [person1, person2], heating_type: NATURAL_GAS, gas_expense: 1_000, id_tafi: 0} + households: + household: {members: [person1, person2], state_code: ID} + output: + id_liheap_countable_income: 18_000 + +- name: Case 3, nonqualified parent income still counts for citizen child. + period: 2026 + absolute_error_margin: 0.01 + # REQ002-004: parent is excluded from eligible size but their20000 wages remain countable. + input: + people: + person1: {age: 35, is_citizen_or_legal_immigrant: false, employment_income: 20_000, ssi: 0} + person2: {age: 8, is_citizen_or_legal_immigrant: true, ssi: 0} + spm_units: + spm_unit: {members: [person1, person2], heating_type: NATURAL_GAS, gas_expense: 1_000, id_tafi: 0} + households: + household: {members: [person1, person2], state_code: ID} + output: + id_liheap_countable_income: 20_000 + +- name: Case 4, all represented unearned sources count without pension double counting. + period: 2026 + absolute_error_margin: 0.01 + # REQ004: SSA12000 + SSI1200 + pension(1000+2000+300+400)=3700 + survivor500 + # + unemployment2400 + strike300 + rent600 + farmrent700 + alimony400 + # + interest200 + dividends250 + estate800 + disability900 + workerscomp1000 =24950. + # Pension and SSA subcomponents each enter their aggregates exactly once. + input: + people: + person1: {age: 40, is_citizen_or_legal_immigrant: true, ssi: 0, social_security_disability: 12_000, taxable_public_pension_income: 1_000, taxable_private_pension_income: 2_000, tax_exempt_public_pension_income: 300, tax_exempt_private_pension_income: 400, survivor_benefits: 500, unemployment_compensation: 2_400, strike_benefits: 300, rental_income: 600, farm_rent_income: 700, alimony_income: 400, interest_income: 200, ordinary_dividend_income: 250, estate_income: 800, disability_benefits: 900, workers_compensation: 1_000} + person2: {age: 8, is_citizen_or_legal_immigrant: true, ssi: 1_200} + spm_units: + spm_unit: {members: [person1, person2], heating_type: NATURAL_GAS, gas_expense: 1_000, id_tafi: 0} + households: + household: {members: [person1, person2], state_code: ID} + output: + id_liheap_countable_income: 24_950 + +- name: Case 5, all supported earned business streams count. + period: 2026 + absolute_error_margin: 0.01 + # REQ003: gross wages10000 + net business streams2000+3000+4000+5000=24000. + input: + people: + person1: {age: 40, is_citizen_or_legal_immigrant: true, ssi: 0, employment_income: 10_000, self_employment_income: 2_000, sstb_self_employment_income: 3_000, farm_operations_income: 4_000, partnership_s_corp_income: 5_000} + spm_units: + spm_unit: {members: [person1], heating_type: NATURAL_GAS, gas_expense: 1_000, id_tafi: 0} + households: + household: {members: [person1], state_code: ID} + output: + id_liheap_countable_income: 24_000 + +- name: Case 6, negative business sources do not offset positive earnings. + period: 2026 + absolute_error_margin: 0.01 + # REQ003 documented net-business approximation:10000 +max(-9000,0)+2000+max(-7000,0)+3000=15000. + input: + people: + person1: {age: 40, is_citizen_or_legal_immigrant: true, ssi: 0, employment_income: 10_000, self_employment_income: -9_000, sstb_self_employment_income: 2_000, farm_operations_income: -7_000, partnership_s_corp_income: 3_000} + spm_units: + spm_unit: {members: [person1], heating_type: NATURAL_GAS, gas_expense: 1_000, id_tafi: 0} + households: + household: {members: [person1], state_code: ID} + output: + id_liheap_countable_income: 15_000 + +- name: Case 7, monthly SSI and TAFI aggregate once over the year. + period: 2026 + absolute_error_margin: 0.01 + # REQ004 period coverage: childSSI100+200=300; SPM TAFI300+200+100=600; total900. + # All other months are explicitly0, and TAFI must not be multiplied by household size. + input: + people: + person1: {age: 35, is_citizen_or_legal_immigrant: true, ssi: {2026-01: 0, 2026-02: 0, 2026-03: 0, 2026-04: 0, 2026-05: 0, 2026-06: 0, 2026-07: 0, 2026-08: 0, 2026-09: 0, 2026-10: 0, 2026-11: 0, 2026-12: 0}} + person2: {age: 8, is_citizen_or_legal_immigrant: true, ssi: {2026-01: 100, 2026-02: 200, 2026-03: 0, 2026-04: 0, 2026-05: 0, 2026-06: 0, 2026-07: 0, 2026-08: 0, 2026-09: 0, 2026-10: 0, 2026-11: 0, 2026-12: 0}} + spm_units: + spm_unit: {members: [person1, person2], heating_type: NATURAL_GAS, gas_expense: 1_000, id_tafi: {2026-01: 300, 2026-02: 200, 2026-03: 100, 2026-04: 0, 2026-05: 0, 2026-06: 0, 2026-07: 0, 2026-08: 0, 2026-09: 0, 2026-10: 0, 2026-11: 0, 2026-12: 0}} + households: + household: {members: [person1, person2], state_code: ID} + output: + id_liheap_countable_income: 900 + +- name: Case 8, child support veterans benefits and general assistance are excluded. + period: 2026 + absolute_error_margin: 0.01 + # REQ004 unchecked source boxes: childsupport9000, VA5000 and GA2000 do not count. + input: + people: + person1: {age: 35, is_citizen_or_legal_immigrant: true, ssi: 0, child_support_received: 9_000, veterans_benefits: 5_000, general_assistance: 2_000} + person2: {age: 8, is_citizen_or_legal_immigrant: true, ssi: 0} + spm_units: + spm_unit: {members: [person1, person2], heating_type: NATURAL_GAS, gas_expense: 1_000, id_tafi: 0} + households: + household: {members: [person1, person2], state_code: ID} + output: + id_liheap_countable_income: 0 + +- name: Case 9, mixed states and unequal memberships retain separate income totals. + period: 2026 + absolute_error_margin: 0.01 + # REQ002-004/state scope: first Idaho unit6000+6000=12000, Colorado0, + # second Idaho unit adult1800+childSSI1800=3600; minor wages10000 excluded. + input: + people: + person1: {age: 35, is_citizen_or_legal_immigrant: true, ssi: 0, employment_income: 6_000} + person2: {age: 34, is_citizen_or_legal_immigrant: false, employment_income: 6_000, ssi: 0} + person3: {age: 40, is_citizen_or_legal_immigrant: true, ssi: 0, employment_income: 12_000} + person4: {age: 35, is_citizen_or_legal_immigrant: true, ssi: 0, employment_income: 1_800} + person5: {age: 12, is_citizen_or_legal_immigrant: true, employment_income: 10_000, ssi: 1_800} + spm_units: + spm_unit1: {members: [person1, person2], heating_type: NATURAL_GAS, gas_expense: 1_000, id_tafi: 0} + spm_unit2: {members: [person3], heating_type: NATURAL_GAS, gas_expense: 1_000, id_tafi: 0} + spm_unit3: {members: [person4, person5], heating_type: NATURAL_GAS, gas_expense: 1_000, id_tafi: 0} + households: + household1: {members: [person1, person2], state_code: ID} + household2: {members: [person3], state_code: CO} + household3: {members: [person4, person5], state_code: ID} + output: + id_liheap_countable_income: [12_000, 0, 3_600] diff --git a/policyengine_us/variables/gov/states/id/dhw/liheap/eligibility/id_liheap_household_size.py b/policyengine_us/variables/gov/states/id/dhw/liheap/eligibility/id_liheap_household_size.py new file mode 100644 index 00000000000..8389296e807 --- /dev/null +++ b/policyengine_us/variables/gov/states/id/dhw/liheap/eligibility/id_liheap_household_size.py @@ -0,0 +1,12 @@ +from policyengine_us.model_api import * + + +class id_liheap_household_size(Variable): + value_type = int + entity = SPMUnit + label = "Idaho LIHEAP eligible household size" + definition_period = YEAR + defined_for = StateCode.ID + reference = "https://liheapch.acf.gov/docs/2026/state-plans/ID_Plan_2026.pdf#page=9" + # The SPM unit approximates the economic unit sharing heating costs. + adds = ["is_citizen_or_legal_immigrant"] diff --git a/policyengine_us/variables/gov/states/id/dhw/liheap/eligibility/id_liheap_income_limit.py b/policyengine_us/variables/gov/states/id/dhw/liheap/eligibility/id_liheap_income_limit.py new file mode 100644 index 00000000000..ef2f21f7866 --- /dev/null +++ b/policyengine_us/variables/gov/states/id/dhw/liheap/eligibility/id_liheap_income_limit.py @@ -0,0 +1,45 @@ +from policyengine_us.model_api import * +from policyengine_us.variables.gov.hhs.hhs_smi import smi +from policyengine_us.variables.gov.hhs.tax_unit_fpg import fpg + + +class id_liheap_income_limit(Variable): + value_type = float + entity = SPMUnit + label = "Idaho LIHEAP annual income limit" + unit = USD + definition_period = YEAR + defined_for = StateCode.ID + reference = ( + "https://liheapch.acf.gov/docs/2026/state-plans/ID_Plan_2026.pdf#page=8", + "https://healthandwelfare.idaho.gov/services-programs/financial-assistance/home-heating-and-utility-assistance/apply-heating-assistance", + ) + + def formula(spm_unit, period, parameters): + size = spm_unit("id_liheap_household_size", period) + state = spm_unit.household("state_code_str", period) + group = spm_unit.household("state_group_str", period) + p = parameters(period) + eligibility = p.gov.states.id.dhw.liheap.eligibility + base = p.gov.hhs.smi.amount[state] + factor = smi(size, state, period, parameters) / base + # Flooring the four-person base before applying the size factor matches + # all seven published FY2026 SMI limits. The source specifies the dollar + # amounts, not this inferred rounding order. Preserve monthly cents. + annual_smi = np.floor(np.floor(base * eligibility.smi_rate) * factor) + monthly_smi = np.round(annual_smi / MONTHS_IN_YEAR, 2) + annual_fpg = eligibility.fpg_rate * fpg( + max_(size, 1), + group, + period, + parameters, + year_lag=eligibility.fpg_year_lag, + ) + # The plan explicitly switches to FPG at size eight, even though this + # lowers the limit; using max(SMI, FPG) would contradict its table. + annual_limit = where( + size <= eligibility.smi_max_household_size, + monthly_smi * MONTHS_IN_YEAR, + annual_fpg, + ) + return where(size > 0, annual_limit, 0) diff --git a/policyengine_us/variables/gov/states/id/dhw/liheap/income/id_liheap_countable_income.py b/policyengine_us/variables/gov/states/id/dhw/liheap/income/id_liheap_countable_income.py new file mode 100644 index 00000000000..0a48cca3078 --- /dev/null +++ b/policyengine_us/variables/gov/states/id/dhw/liheap/income/id_liheap_countable_income.py @@ -0,0 +1,29 @@ +from policyengine_us.model_api import * + + +class id_liheap_countable_income(Variable): + value_type = float + entity = SPMUnit + label = "Idaho LIHEAP countable annual income" + unit = USD + definition_period = YEAR + defined_for = StateCode.ID + reference = ( + "https://liheapch.acf.gov/docs/2026/state-plans/ID_Plan_2026.pdf#page=5,6,7" + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.id.dhw.liheap.income + person = spm_unit.members + # Annual income approximates a stable prior-month assessment. Existing + # net business inputs are used without another expense deduction; losses + # do not offset other income under this common modeling approximation. + earned = sum(max_(person(source, period), 0) for source in p.sources.earned) + adult = person("age", period) >= p.earned_income_min_age + earned = spm_unit.sum(where(adult, earned, 0)) + unearned = add(spm_unit, period, p.sources.unearned) + # Income of nonqualified members counts. The plan excludes child support, + # VA and general assistance. Jury duty, WIA, mortgage/royalty receipts and + # irregular gifts/lottery winnings over $30 in the prior month lack + # separately identified inputs; they are unmodeled, not legal exclusions. + return max_(earned + unearned, 0) From b9ff96a147329ecc87a897514605dca5c675290d Mon Sep 17 00:00:00 2001 From: Ziming Date: Sat, 3 Oct 2026 20:18:38 -0400 Subject: [PATCH 02/10] Count recurring retirement-account income in Idaho LIHEAP --- .../dhw/liheap/income/sources/unearned.yaml | 3 +++ .../income/id_liheap_countable_income.yaml | 27 +++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/policyengine_us/parameters/gov/states/id/dhw/liheap/income/sources/unearned.yaml b/policyengine_us/parameters/gov/states/id/dhw/liheap/income/sources/unearned.yaml index 92a7af57293..22f6d62608c 100644 --- a/policyengine_us/parameters/gov/states/id/dhw/liheap/income/sources/unearned.yaml +++ b/policyengine_us/parameters/gov/states/id/dhw/liheap/income/sources/unearned.yaml @@ -4,6 +4,9 @@ values: - social_security - ssi - pension_income + # Ongoing IRA/401k distributions are separate from pension_income. + # Existing annual inputs do not identify an excluded one-time lump sum. + - retirement_distributions - survivor_benefits - unemployment_compensation - strike_benefits diff --git a/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/income/id_liheap_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/income/id_liheap_countable_income.yaml index cdeef01f68f..fc7081564fe 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/income/id_liheap_countable_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/income/id_liheap_countable_income.yaml @@ -148,3 +148,30 @@ household3: {members: [person4, person5], state_code: ID} output: id_liheap_countable_income: [12_000, 0, 3_600] + +# Ongoing retirement receipts: pension 1,000 + taxable IRA 12,000 + exempt IRA 3,000. +# Count the two aggregates once; one-time lump sums are not represented here. +- name: Recurring taxable and exempt retirement distributions count beside pensions. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person: + age: 70 + immigration_status: CITIZEN + ssi: 0 + pension_income: 1_000 + taxable_ira_distributions: 12_000 + tax_exempt_ira_distributions: 3_000 + spm_units: + spm_unit: + members: [person] + heating_type: NATURAL_GAS + gas_expense: 1_000 + id_tafi: 0 + households: + household: + members: [person] + state_code: ID + output: + id_liheap_countable_income: 16_000 From 038a74025267ac426e8b1967f912caccf6f5696e Mon Sep 17 00:00:00 2001 From: Ziming Date: Sat, 3 Oct 2026 21:24:57 -0400 Subject: [PATCH 03/10] Add supported Idaho LIHEAP financial eligibility routes --- changelog.d/id-liheap-wave2c.added.md | 2 +- .../gov/states/id/dhw/liheap/README.md | 36 + .../eligibility/program_year_start_month.yaml | 10 + policyengine_us/programs.yaml | 2 +- .../id_liheap_income_eligible.yaml | 1764 +++++++++++++++++ .../eligibility/id_liheap_income_eligible.py | 29 + 6 files changed, 1841 insertions(+), 2 deletions(-) create mode 100644 policyengine_us/parameters/gov/states/id/dhw/liheap/README.md create mode 100644 policyengine_us/parameters/gov/states/id/dhw/liheap/eligibility/program_year_start_month.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/eligibility/id_liheap_income_eligible.yaml create mode 100644 policyengine_us/variables/gov/states/id/dhw/liheap/eligibility/id_liheap_income_eligible.py diff --git a/changelog.d/id-liheap-wave2c.added.md b/changelog.d/id-liheap-wave2c.added.md index b7a8a6f6eac..98a2dfd00ab 100644 --- a/changelog.d/id-liheap-wave2c.added.md +++ b/changelog.d/id-liheap-wave2c.added.md @@ -1 +1 @@ -Add Idaho LIHEAP countable income, qualified household size and income-limit calculations; the heating benefit calculation remains incomplete. +Add Idaho LIHEAP countable income, qualified household size, income limits and modeled financial eligibility, including SNAP and SSI categorical routes; the heating benefit calculation remains incomplete. diff --git a/policyengine_us/parameters/gov/states/id/dhw/liheap/README.md b/policyengine_us/parameters/gov/states/id/dhw/liheap/README.md new file mode 100644 index 00000000000..ff443df23ad --- /dev/null +++ b/policyengine_us/parameters/gov/states/id/dhw/liheap/README.md @@ -0,0 +1,36 @@ +# Idaho regular heating components + +The FY2026 components calculate qualified household size, countable income, +income limits and modeled financial eligibility. The ordinary income test is +inclusive. A household with a SNAP recipient during the October-September +program year, or a current SSI recipient, is categorically income eligible. +Income still determines the eventual award. Any household member can establish +that categorical route; the model does not require every member to receive aid. +A household with no qualified members cannot qualify. + +SNAP uses the actual twelve-month program-year window: FY2026 reads October 2025 +through September 2026. SSI uses annual positive benefits as a stable-current- +receipt approximation because application month is not an input. The model's +annual income flows likewise approximate the prior-month assessment. Existing +net business inputs receive no second expense deduction. SPM membership +approximates the household sharing home heating costs. + +Means-tested veterans benefits also establish categorical eligibility, but the +existing aggregate veterans_benefits input does not distinguish them from other +VA benefits. That route remains unobserved; a false modeled financial predicate +is not a definitive legal denial for such a household. No new input or blanket +VA qualification is introduced. Housing, heating-cost responsibility and +administrative requirements are separate from this financial component. +The predecessor rule's discretionary catastrophic-illness exception also needs +an administrative determination that existing inputs cannot establish. + +Final eligibility and awards remain incomplete. The current estimated annual +heating-cost chart and current provider/region mapping +have not been established. The recovered historical county map and 2007 heating +costs are not promoted to FY2026 policy, and actual household bills do not replace +the state's estimated costs. The current methodology's exactly-11-percent burden +boundary is also unresolved; a superseded rule does not settle it. + +Only researched and tested FY2026 components are verified. Earlier parameter +backfills are unverified historical estimates. Crisis, cooling, weatherization +and equipment are outside scope. diff --git a/policyengine_us/parameters/gov/states/id/dhw/liheap/eligibility/program_year_start_month.yaml b/policyengine_us/parameters/gov/states/id/dhw/liheap/eligibility/program_year_start_month.yaml new file mode 100644 index 00000000000..7e5788b20bf --- /dev/null +++ b/policyengine_us/parameters/gov/states/id/dhw/liheap/eligibility/program_year_start_month.yaml @@ -0,0 +1,10 @@ +description: Idaho begins the Low Income Home Energy Assistance Program year, used to establish categorical SNAP receipt, in this month of the preceding calendar year. +values: + 2025-10-01: 10 +metadata: + unit: month + period: year + label: Idaho LIHEAP program year start month + reference: + - title: Idaho FY2026 LIHEAP State Plan, categorical eligibility + href: https://liheapch.acf.gov/docs/2026/state-plans/ID_Plan_2026.pdf#page=5 diff --git a/policyengine_us/programs.yaml b/policyengine_us/programs.yaml index 2817b23b426..47fbdd29b11 100644 --- a/policyengine_us/programs.yaml +++ b/policyengine_us/programs.yaml @@ -845,7 +845,7 @@ programs: full_name: Idaho Low Income Home Energy Assistance Program parameter_prefix: gov.states.id.dhw.liheap verified_years: "2026" - notes: FY2026 household size, countable income and income-limit components only. No final eligibility or benefit award; provider and area heating-cost mapping and categorical-income treatment remain unresolved. Annual flows approximate prior-month income. Earlier backfilled results are unverified historical estimates. + notes: FY2026 household size, countable income, income limits and modeled financial eligibility. SNAP during the October-September program year or current SSI receipt bypasses the ordinary income test; annual SSI assumes stable current receipt. Means-tested VA categorical status is unobserved by existing inputs. No final eligibility or benefit award; current estimated heating costs, provider/area mapping and an energy-burden boundary remain unresolved. Annual flows approximate prior-month income. Earlier backfilled results are unverified historical estimates. - state: TX status: partial name: Texas CEAP diff --git a/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/eligibility/id_liheap_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/eligibility/id_liheap_income_eligible.yaml new file mode 100644 index 00000000000..e3501f46157 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/eligibility/id_liheap_income_eligible.yaml @@ -0,0 +1,1764 @@ +# Source-derived financial-component tests; no final eligibility or award claim. +# Accepted FY2026 plan, categorical rules and income thresholds (pages 5, 8). +# https://liheapch.acf.gov/docs/2026/state-plans/ID_Plan_2026.pdf#page=5,8 +# Pre-consolidation IDAPA 16.04.14 section 151.01 (physical pages 4-5). +# https://web.archive.org/web/20250910171431id_/https://adminrules.idaho.gov/rules/current/16/160414.pdf#page=4,5 +# DHW monthly limits effective October 1, 2025. +# https://healthandwelfare.idaho.gov/services-programs/financial-assistance/home-heating-and-utility-assistance/apply-heating-assistance +# Means-tested VA and discretionary medical determinations are unobserved routes. +# False means no modeled route is established, not exhaustive legal denial. + +- name: Case 1, ordinary income qualifies through the inclusive published ceiling. + # DHW one-person monthly limit 2_736.25 * 12 = 32_835. + # No SNAP or SSI; one cent below, exactly at, and one cent above. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + is_citizen_or_legal_immigrant: true + employment_income: 32834.99 + ssi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + person2: + age: 40 + is_citizen_or_legal_immigrant: true + employment_income: 32835 + ssi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + person3: + age: 40 + is_citizen_or_legal_immigrant: true + employment_income: 32835.01 + ssi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: NATURAL_GAS + gas_expense: 1200 + pre_subsidy_electricity_expense: 0 + id_tafi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + snap: + 2025-09: 0 + 2025-10: 0 + 2025-11: 0 + 2025-12: 0 + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + spm_unit2: + members: + - person2 + heating_type: NATURAL_GAS + gas_expense: 1200 + pre_subsidy_electricity_expense: 0 + id_tafi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + snap: + 2025-09: 0 + 2025-10: 0 + 2025-11: 0 + 2025-12: 0 + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + spm_unit3: + members: + - person3 + heating_type: NATURAL_GAS + gas_expense: 1200 + pre_subsidy_electricity_expense: 0 + id_tafi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + snap: + 2025-09: 0 + 2025-10: 0 + 2025-11: 0 + 2025-12: 0 + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + households: + household1: + members: + - person1 + state_code: ID + household2: + members: + - person2 + state_code: ID + household3: + members: + - person3 + state_code: ID + output: + id_liheap_income_eligible: + - true + - true + - false + id_liheap_household_size: + - 1 + - 1 + - 1 + id_liheap_countable_income: + - 32834.99 + - 32835 + - 32835.01 + id_liheap_income_limit: + - 32835 + - 32835 + - 32835 + +- name: Case 2, SNAP receipt follows the October through September program year. + # Plan section 1.4a specifies October 1-September 30. + # First/last included months qualify; adjacent outside months do not. + # All other months September 2025-December 2026 are explicitly zero. + # SNAP establishes a route without erasing 40_000 of countable earnings. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + is_citizen_or_legal_immigrant: true + employment_income: 40000 + ssi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + person2: + age: 40 + is_citizen_or_legal_immigrant: true + employment_income: 40000 + ssi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + person3: + age: 40 + is_citizen_or_legal_immigrant: true + employment_income: 40000 + ssi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + person4: + age: 40 + is_citizen_or_legal_immigrant: true + employment_income: 40000 + ssi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: NATURAL_GAS + gas_expense: 1200 + pre_subsidy_electricity_expense: 0 + id_tafi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + snap: + 2025-09: 0 + 2025-10: 1 + 2025-11: 0 + 2025-12: 0 + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + spm_unit2: + members: + - person2 + heating_type: NATURAL_GAS + gas_expense: 1200 + pre_subsidy_electricity_expense: 0 + id_tafi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + snap: + 2025-09: 0 + 2025-10: 0 + 2025-11: 0 + 2025-12: 0 + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 1 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + spm_unit3: + members: + - person3 + heating_type: NATURAL_GAS + gas_expense: 1200 + pre_subsidy_electricity_expense: 0 + id_tafi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + snap: + 2025-09: 1 + 2025-10: 0 + 2025-11: 0 + 2025-12: 0 + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + spm_unit4: + members: + - person4 + heating_type: NATURAL_GAS + gas_expense: 1200 + pre_subsidy_electricity_expense: 0 + id_tafi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + snap: + 2025-09: 0 + 2025-10: 0 + 2025-11: 0 + 2025-12: 0 + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 1 + 2026-11: 0 + 2026-12: 0 + households: + household1: + members: + - person1 + state_code: ID + household2: + members: + - person2 + state_code: ID + household3: + members: + - person3 + state_code: ID + household4: + members: + - person4 + state_code: ID + output: + id_liheap_income_eligible: + - true + - true + - false + - false + id_liheap_household_size: + - 1 + - 1 + - 1 + - 1 + id_liheap_countable_income: + - 40000 + - 40000 + - 40000 + - 40000 + +- name: Case 3, one member receiving SSI establishes the modeled categorical route. + # Positive requested-year SSI is the documented stable-receipt approximation. + # Income: 40_000 + 1 * 12; 60_000 + 100 * 12; 40_000 + 100 * 12. + # Child earnings are excluded; SSI is counted once. + # The third unit has a nonqualified SSI recipient and a qualified child. + # The parent income counts; SSI is not restricted to qualified members. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + is_citizen_or_legal_immigrant: true + employment_income: 40000 + ssi: + 2026-01: 1 + 2026-02: 1 + 2026-03: 1 + 2026-04: 1 + 2026-05: 1 + 2026-06: 1 + 2026-07: 1 + 2026-08: 1 + 2026-09: 1 + 2026-10: 1 + 2026-11: 1 + 2026-12: 1 + person2: + age: 40 + is_citizen_or_legal_immigrant: true + employment_income: 60000 + ssi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + person3: + age: 10 + is_citizen_or_legal_immigrant: true + employment_income: 6000 + ssi: + 2026-01: 100 + 2026-02: 100 + 2026-03: 100 + 2026-04: 100 + 2026-05: 100 + 2026-06: 100 + 2026-07: 100 + 2026-08: 100 + 2026-09: 100 + 2026-10: 100 + 2026-11: 100 + 2026-12: 100 + person4: + age: 40 + is_citizen_or_legal_immigrant: false + employment_income: 40000 + ssi: + 2026-01: 100 + 2026-02: 100 + 2026-03: 100 + 2026-04: 100 + 2026-05: 100 + 2026-06: 100 + 2026-07: 100 + 2026-08: 100 + 2026-09: 100 + 2026-10: 100 + 2026-11: 100 + 2026-12: 100 + person5: + age: 10 + is_citizen_or_legal_immigrant: true + employment_income: 0 + ssi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: NATURAL_GAS + gas_expense: 1200 + pre_subsidy_electricity_expense: 0 + id_tafi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + snap: + 2025-09: 0 + 2025-10: 0 + 2025-11: 0 + 2025-12: 0 + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + spm_unit2: + members: + - person2 + - person3 + heating_type: NATURAL_GAS + gas_expense: 1200 + pre_subsidy_electricity_expense: 0 + id_tafi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + snap: + 2025-09: 0 + 2025-10: 0 + 2025-11: 0 + 2025-12: 0 + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + spm_unit3: + members: + - person4 + - person5 + heating_type: NATURAL_GAS + gas_expense: 1200 + pre_subsidy_electricity_expense: 0 + id_tafi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + snap: + 2025-09: 0 + 2025-10: 0 + 2025-11: 0 + 2025-12: 0 + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + households: + household1: + members: + - person1 + state_code: ID + household2: + members: + - person2 + - person3 + state_code: ID + household3: + members: + - person4 + - person5 + state_code: ID + output: + id_liheap_income_eligible: + - true + - true + - true + id_liheap_household_size: + - 1 + - 2 + - 1 + id_liheap_countable_income: + - 40012 + - 61200 + - 41200 + id_liheap_income_limit: + - 32835 + - 42938.04 + - 32835 + +- name: Case 4, qualified size is required with zero income or categorical receipt. + # All-nonqualified units fail without benefits, with SNAP, and with SSI. + # Mixed status retains parent income one cent above the one-person ceiling. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + is_citizen_or_legal_immigrant: false + employment_income: 0 + ssi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + person2: + age: 40 + is_citizen_or_legal_immigrant: false + employment_income: 0 + ssi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + person3: + age: 40 + is_citizen_or_legal_immigrant: false + employment_income: 0 + ssi: + 2026-01: 100 + 2026-02: 100 + 2026-03: 100 + 2026-04: 100 + 2026-05: 100 + 2026-06: 100 + 2026-07: 100 + 2026-08: 100 + 2026-09: 100 + 2026-10: 100 + 2026-11: 100 + 2026-12: 100 + person4: + age: 40 + is_citizen_or_legal_immigrant: false + employment_income: 32835.01 + ssi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + person5: + age: 10 + is_citizen_or_legal_immigrant: true + employment_income: 0 + ssi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: NATURAL_GAS + gas_expense: 1200 + pre_subsidy_electricity_expense: 0 + id_tafi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + snap: + 2025-09: 0 + 2025-10: 0 + 2025-11: 0 + 2025-12: 0 + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + spm_unit2: + members: + - person2 + heating_type: NATURAL_GAS + gas_expense: 1200 + pre_subsidy_electricity_expense: 0 + id_tafi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + snap: + 2025-09: 0 + 2025-10: 1 + 2025-11: 0 + 2025-12: 0 + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + spm_unit3: + members: + - person3 + heating_type: NATURAL_GAS + gas_expense: 1200 + pre_subsidy_electricity_expense: 0 + id_tafi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + snap: + 2025-09: 0 + 2025-10: 0 + 2025-11: 0 + 2025-12: 0 + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + spm_unit4: + members: + - person4 + - person5 + heating_type: NATURAL_GAS + gas_expense: 1200 + pre_subsidy_electricity_expense: 0 + id_tafi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + snap: + 2025-09: 0 + 2025-10: 0 + 2025-11: 0 + 2025-12: 0 + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + households: + household1: + members: + - person1 + state_code: ID + household2: + members: + - person2 + state_code: ID + household3: + members: + - person3 + state_code: ID + household4: + members: + - person4 + - person5 + state_code: ID + output: + id_liheap_income_eligible: + - false + - false + - false + - false + id_liheap_household_size: + - 0 + - 0 + - 0 + - 1 + id_liheap_countable_income: + - 0 + - 0 + - 1200 + - 32835.01 + +- name: Case 5, TANF alone is not categorical and SNAP retains actual income. + # Plan page 5 marks TANF no and SNAP yes for heating categorical eligibility. + # TAFI 100 monthly = 1_200 annual countable income, without a categorical route. + # SNAP opens the modeled route without imputing or erasing other income. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + is_citizen_or_legal_immigrant: true + employment_income: 40000 + ssi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + person2: + age: 40 + is_citizen_or_legal_immigrant: true + employment_income: 40000 + ssi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: NATURAL_GAS + gas_expense: 1200 + pre_subsidy_electricity_expense: 0 + id_tafi: + 2026-01: 100 + 2026-02: 100 + 2026-03: 100 + 2026-04: 100 + 2026-05: 100 + 2026-06: 100 + 2026-07: 100 + 2026-08: 100 + 2026-09: 100 + 2026-10: 100 + 2026-11: 100 + 2026-12: 100 + snap: + 2025-09: 0 + 2025-10: 0 + 2025-11: 0 + 2025-12: 0 + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + spm_unit2: + members: + - person2 + heating_type: NATURAL_GAS + gas_expense: 1200 + pre_subsidy_electricity_expense: 0 + id_tafi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + snap: + 2025-09: 0 + 2025-10: 0 + 2025-11: 0 + 2025-12: 0 + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 1 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + households: + household1: + members: + - person1 + state_code: ID + household2: + members: + - person2 + state_code: ID + output: + id_liheap_income_eligible: + - false + - true + id_liheap_household_size: + - 1 + - 1 + id_liheap_countable_income: + - 41200 + - 40000 + +- name: Case 6, the seven to eight member switch affects ordinary eligibility. + # Published size-7 monthly 7_103.75 * 12 = 85_245. + # Published size-8 monthly 6_768.75 * 12 = 81_225. + # The explicit SMI/FPG switch does not take the larger guideline. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + is_citizen_or_legal_immigrant: true + employment_income: 84000 + ssi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + person2: + age: 40 + is_citizen_or_legal_immigrant: true + employment_income: 0 + ssi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + person3: + age: 40 + is_citizen_or_legal_immigrant: true + employment_income: 0 + ssi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + person4: + age: 40 + is_citizen_or_legal_immigrant: true + employment_income: 0 + ssi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + person5: + age: 40 + is_citizen_or_legal_immigrant: true + employment_income: 0 + ssi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + person6: + age: 40 + is_citizen_or_legal_immigrant: true + employment_income: 0 + ssi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + person7: + age: 40 + is_citizen_or_legal_immigrant: true + employment_income: 0 + ssi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + person8: + age: 40 + is_citizen_or_legal_immigrant: true + employment_income: 84000 + ssi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + person9: + age: 40 + is_citizen_or_legal_immigrant: true + employment_income: 0 + ssi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + person10: + age: 40 + is_citizen_or_legal_immigrant: true + employment_income: 0 + ssi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + person11: + age: 40 + is_citizen_or_legal_immigrant: true + employment_income: 0 + ssi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + person12: + age: 40 + is_citizen_or_legal_immigrant: true + employment_income: 0 + ssi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + person13: + age: 40 + is_citizen_or_legal_immigrant: true + employment_income: 0 + ssi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + person14: + age: 40 + is_citizen_or_legal_immigrant: true + employment_income: 0 + ssi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + person15: + age: 40 + is_citizen_or_legal_immigrant: true + employment_income: 0 + ssi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + spm_units: + spm_unit1: + members: + - person1 + - person2 + - person3 + - person4 + - person5 + - person6 + - person7 + heating_type: NATURAL_GAS + gas_expense: 1200 + pre_subsidy_electricity_expense: 0 + id_tafi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + snap: + 2025-09: 0 + 2025-10: 0 + 2025-11: 0 + 2025-12: 0 + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + spm_unit2: + members: + - person8 + - person9 + - person10 + - person11 + - person12 + - person13 + - person14 + - person15 + heating_type: NATURAL_GAS + gas_expense: 1200 + pre_subsidy_electricity_expense: 0 + id_tafi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + snap: + 2025-09: 0 + 2025-10: 0 + 2025-11: 0 + 2025-12: 0 + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + households: + household1: + members: + - person1 + - person2 + - person3 + - person4 + - person5 + - person6 + - person7 + state_code: ID + household2: + members: + - person8 + - person9 + - person10 + - person11 + - person12 + - person13 + - person14 + - person15 + state_code: ID + output: + id_liheap_income_eligible: + - true + - false + id_liheap_household_size: + - 7 + - 8 + id_liheap_countable_income: + - 84000 + - 84000 + id_liheap_income_limit: + - 85245 + - 81225 + +- name: Case 7, financial eligibility does not decide heating responsibility. + # Zero income meets this financial component despite no heat bill. + # This is not a finding of full program eligibility or a heating award. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + is_citizen_or_legal_immigrant: true + employment_income: 0 + ssi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: NONE + gas_expense: 0 + pre_subsidy_electricity_expense: 0 + id_tafi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + snap: + 2025-09: 0 + 2025-10: 0 + 2025-11: 0 + 2025-12: 0 + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + households: + household1: + members: + - person1 + state_code: ID + output: + id_liheap_income_eligible: + - true + id_liheap_household_size: + - 1 + id_liheap_countable_income: + - 0 + +- name: Case 8, mixed states isolate ordinary and categorical financial routes. + # Idaho meets ordinary income; Washington cannot use this state component. + # The last unit receives SSI, testing the state guard on that route. + # Existing Idaho size/income helpers are zero outside Idaho. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + is_citizen_or_legal_immigrant: true + employment_income: 0 + ssi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + person2: + age: 40 + is_citizen_or_legal_immigrant: true + employment_income: 0 + ssi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + person3: + age: 40 + is_citizen_or_legal_immigrant: true + employment_income: 40000 + ssi: + 2026-01: 1 + 2026-02: 1 + 2026-03: 1 + 2026-04: 1 + 2026-05: 1 + 2026-06: 1 + 2026-07: 1 + 2026-08: 1 + 2026-09: 1 + 2026-10: 1 + 2026-11: 1 + 2026-12: 1 + spm_units: + spm_unit1: + members: + - person1 + heating_type: NATURAL_GAS + gas_expense: 1200 + pre_subsidy_electricity_expense: 0 + id_tafi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + snap: + 2025-09: 0 + 2025-10: 0 + 2025-11: 0 + 2025-12: 0 + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + spm_unit2: + members: + - person2 + heating_type: NATURAL_GAS + gas_expense: 1200 + pre_subsidy_electricity_expense: 0 + id_tafi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + snap: + 2025-09: 0 + 2025-10: 0 + 2025-11: 0 + 2025-12: 0 + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + spm_unit3: + members: + - person3 + heating_type: NATURAL_GAS + gas_expense: 1200 + pre_subsidy_electricity_expense: 0 + id_tafi: + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + snap: + 2025-09: 0 + 2025-10: 0 + 2025-11: 0 + 2025-12: 0 + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + households: + household1: + members: + - person1 + state_code: ID + household2: + members: + - person2 + state_code: WA + household3: + members: + - person3 + state_code: WA + output: + id_liheap_income_eligible: + - true + - false + - false + id_liheap_household_size: + - 1 + - 0 + - 0 + id_liheap_countable_income: + - 0 + - 0 + - 0 diff --git a/policyengine_us/variables/gov/states/id/dhw/liheap/eligibility/id_liheap_income_eligible.py b/policyengine_us/variables/gov/states/id/dhw/liheap/eligibility/id_liheap_income_eligible.py new file mode 100644 index 00000000000..2a017095514 --- /dev/null +++ b/policyengine_us/variables/gov/states/id/dhw/liheap/eligibility/id_liheap_income_eligible.py @@ -0,0 +1,29 @@ +from policyengine_us.model_api import * + + +class id_liheap_income_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Idaho LIHEAP modeled income eligibility" + definition_period = YEAR + defined_for = StateCode.ID + reference = ( + "https://liheapch.acf.gov/docs/2026/state-plans/ID_Plan_2026.pdf#page=5", + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.id.dhw.liheap.eligibility + size = spm_unit("id_liheap_household_size", period) + income = spm_unit("id_liheap_countable_income", period) + limit = spm_unit("id_liheap_income_limit", period) + # SNAP receipt can occur anywhere in the October-September program year. + snap_period = period.offset( + p.program_year_start_month - 1 - MONTHS_IN_YEAR, "month" + ) + receives_snap = spm_unit("snap", snap_period, options=[ADD]) > 0 + # Annual SSI is a stable-current-receipt proxy because the application + # month is not an input. Any member may establish categorical eligibility. + receives_ssi = spm_unit.any(spm_unit.members("ssi", period, options=[ADD]) > 0) + # Means-tested VA receipt also qualifies, but veterans_benefits does not + # identify that category. This unmodeled route is not a legal exclusion. + return (size > 0) & ((income <= limit) | receives_snap | receives_ssi) From bd9eff048644caf266d901fe9ab08e9b2076ef6d Mon Sep 17 00:00:00 2001 From: Ziming Date: Sat, 3 Oct 2026 22:26:25 -0400 Subject: [PATCH 04/10] Add Idaho LIHEAP electric benefit table with provider assumption --- changelog.d/id-liheap-wave2c.added.md | 2 +- .../gov/states/id/dhw/liheap/README.md | 14 +++++- .../liheap/payment/matrix/electricity.yaml | 44 +++++++++++++++++++ policyengine_us/programs.yaml | 2 +- 4 files changed, 58 insertions(+), 4 deletions(-) create mode 100644 policyengine_us/parameters/gov/states/id/dhw/liheap/payment/matrix/electricity.yaml diff --git a/changelog.d/id-liheap-wave2c.added.md b/changelog.d/id-liheap-wave2c.added.md index 98a2dfd00ab..872800f870d 100644 --- a/changelog.d/id-liheap-wave2c.added.md +++ b/changelog.d/id-liheap-wave2c.added.md @@ -1 +1 @@ -Add Idaho LIHEAP countable income, qualified household size, income limits and modeled financial eligibility, including SNAP and SSI categorical routes; the heating benefit calculation remains incomplete. +Add Idaho LIHEAP countable income, qualified household size, income limits, modeled financial eligibility and the Idaho Power & Southern Utilities electric-benefit table without electric-provider distinctions; the heating benefit calculation remains incomplete. diff --git a/policyengine_us/parameters/gov/states/id/dhw/liheap/README.md b/policyengine_us/parameters/gov/states/id/dhw/liheap/README.md index ff443df23ad..58d4ee08841 100644 --- a/policyengine_us/parameters/gov/states/id/dhw/liheap/README.md +++ b/policyengine_us/parameters/gov/states/id/dhw/liheap/README.md @@ -24,9 +24,19 @@ administrative requirements are separate from this financial component. The predecessor rule's discretionary catastrophic-illness exception also needs an administrative determination that existing inputs cannot establish. +The electric-benefit parameter table uses the Idaho Power & Southern Utilities +column for all three heating areas. Electric utility-provider groups are not +distinguished for now; the Avista & Northern Utilities and Rocky Mountain Power +columns are omitted. This is an explicit modeling simplification, not a claim +that providers pay identical benefits. No utility-provider input is added. +The table contains the base amounts before the vulnerable-household supplement. +It is not yet connected to a household award because the area and burden +calculations remain unresolved. Natural-gas provider selection is a separate +unresolved issue; this electric-column choice does not resolve it. + Final eligibility and awards remain incomplete. The current estimated annual -heating-cost chart and current provider/region mapping -have not been established. The recovered historical county map and 2007 heating +heating-cost chart and current heating-area mapping have not been established. +The recovered historical county map and 2007 heating costs are not promoted to FY2026 policy, and actual household bills do not replace the state's estimated costs. The current methodology's exactly-11-percent burden boundary is also unresolved; a superseded rule does not settle it. diff --git a/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/matrix/electricity.yaml b/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/matrix/electricity.yaml new file mode 100644 index 00000000000..bf267090d5f --- /dev/null +++ b/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/matrix/electricity.yaml @@ -0,0 +1,44 @@ +description: Idaho provides this base electric-heating benefit by heating area and energy-burden group under the Low Income Home Energy Assistance Program. + +# Electric utility-provider groups are not distinguished in the model for now. +# Use only the Idaho Power & Southern Utilities column; omit the Avista & +# Northern Utilities and Rocky Mountain Power columns. +# Heating areas 1-3 correspond to Areas I-III in the published chart. +# Energy-burden groups: 1 = low, 2 = medium, 3 = high. +# Amounts exclude the separate vulnerable-household supplement. +1: + 1: + 2025-10-01: 328 + 2: + 2025-10-01: 342 + 3: + 2025-10-01: 355 +2: + 1: + 2025-10-01: 378 + 2: + 2025-10-01: 394 + 3: + 2025-10-01: 410 +3: + 1: + 2025-10-01: 429 + 2: + 2025-10-01: 447 + 3: + 2025-10-01: 464 + +metadata: + propagate_metadata_to_children: true + unit: currency-USD + period: year + label: Idaho LIHEAP base electric-heating benefit + breakdown: + - range(1, 4) + - range(1, 4) + breakdown_labels: + - Heating area + - Energy-burden group + reference: + - title: Idaho PY26 LIHEAP Benefit Determination Chart + href: https://liheapch.acf.gov/docs/2026/benefits-matricies/ID_BenefitMatrix_Heating_2026.pdf#page=1 diff --git a/policyengine_us/programs.yaml b/policyengine_us/programs.yaml index 47fbdd29b11..1391defadcd 100644 --- a/policyengine_us/programs.yaml +++ b/policyengine_us/programs.yaml @@ -845,7 +845,7 @@ programs: full_name: Idaho Low Income Home Energy Assistance Program parameter_prefix: gov.states.id.dhw.liheap verified_years: "2026" - notes: FY2026 household size, countable income, income limits and modeled financial eligibility. SNAP during the October-September program year or current SSI receipt bypasses the ordinary income test; annual SSI assumes stable current receipt. Means-tested VA categorical status is unobserved by existing inputs. No final eligibility or benefit award; current estimated heating costs, provider/area mapping and an energy-burden boundary remain unresolved. Annual flows approximate prior-month income. Earlier backfilled results are unverified historical estimates. + notes: FY2026 household size, countable income, income limits and modeled financial eligibility. SNAP during the October-September program year or current SSI receipt bypasses the ordinary income test; annual SSI assumes stable current receipt. Means-tested VA categorical status is unobserved by existing inputs. The electric-benefit parameter table uses Idaho Power & Southern Utilities amounts without distinguishing electric-provider groups; it is not yet connected to household awards. No final eligibility or benefit award; current estimated heating costs, heating-area mapping, natural-gas provider selection and an energy-burden boundary remain unresolved. Annual flows approximate prior-month income. Earlier backfilled results are unverified historical estimates. - state: TX status: partial name: Texas CEAP From 20c99201d177ef050e0e9a0c37ae7711f4c27284 Mon Sep 17 00:00:00 2001 From: Ziming Date: Tue, 20 Oct 2026 20:56:57 -0400 Subject: [PATCH 05/10] Document Idaho high burden at 11 percent or greater --- changelog.d/id-liheap-wave2c.added.md | 2 +- .../parameters/gov/states/id/dhw/liheap/README.md | 13 +++++++++++-- .../id/dhw/liheap/payment/matrix/electricity.yaml | 2 ++ policyengine_us/programs.yaml | 2 +- 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/changelog.d/id-liheap-wave2c.added.md b/changelog.d/id-liheap-wave2c.added.md index 0eb86638b97..c64f0478199 100644 --- a/changelog.d/id-liheap-wave2c.added.md +++ b/changelog.d/id-liheap-wave2c.added.md @@ -1 +1 @@ -Add Idaho LIHEAP income, household and financial-eligibility components with net Social Security, receipt-based income and the Idaho Power & Southern Utilities electric table; the full heating award remains incomplete. +Add Idaho LIHEAP income, household and financial-eligibility components with net Social Security, receipt-based income and the Idaho Power & Southern Utilities electric table. Document the approved high-burden convention of 11% or greater; the full heating award remains incomplete. diff --git a/policyengine_us/parameters/gov/states/id/dhw/liheap/README.md b/policyengine_us/parameters/gov/states/id/dhw/liheap/README.md index 57ebac8cfd9..f99380f8837 100644 --- a/policyengine_us/parameters/gov/states/id/dhw/liheap/README.md +++ b/policyengine_us/parameters/gov/states/id/dhw/liheap/README.md @@ -41,12 +41,21 @@ It is not yet connected to a household award because the area and burden calculations remain unresolved. Provider/company and administering-agency distinctions are outside this implementation scope. +The approved energy-burden convention is low below 6%, medium from 6% up to +but excluding 11%, and high at 11% or greater (`burden >= 0.11`). This includes +exactly 11% in the high group. The user approved this interpretation on +October 20, 2026: the [FY2026 matrix methodology](https://liheapch.acf.gov/docs/2026/benefits-matricies/ID_BenefitMatrix_Heating_2026.pdf#page=2) +prints medium below 11% and high above 11%, leaving exactly 11% unassigned. +The [historical 2011 rule, section 204.03](https://adminrules.idaho.gov/rules/2011/16/0414.pdf#page=8) +explicitly included 11% in high. This is an approved modeling convention; +the current source omission remains documented. + Final eligibility and awards remain incomplete. The current estimated annual heating-cost chart and current heating-area mapping have not been established. The recovered historical county map and 2007 heating costs are not promoted to FY2026 policy, and actual household bills do not replace -the state's estimated costs. The current methodology's exactly-11-percent burden -boundary is also unresolved; a superseded rule does not settle it. +the state's estimated costs. The exactly-11-percent boundary is resolved by the +approved convention above. FY2026 components and the selected electric table are researched and tested; the incomplete state has no fully verified policy year. Earlier parameter diff --git a/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/matrix/electricity.yaml b/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/matrix/electricity.yaml index bf267090d5f..78612d38ef8 100644 --- a/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/matrix/electricity.yaml +++ b/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/matrix/electricity.yaml @@ -5,6 +5,8 @@ description: Idaho provides this base electric-heating benefit by heating area a # Northern Utilities and Rocky Mountain Power columns. # Heating areas 1-3 correspond to Areas I-III in the published chart. # Energy-burden groups: 1 = low, 2 = medium, 3 = high. +# Approved convention: low < 6%; medium >= 6% and < 11%; high >= 11%. +# Exactly 11% is high by the user's October 20, 2026 decision; see README.md. # Amounts exclude the separate vulnerable-household supplement. 1: 1: diff --git a/policyengine_us/programs.yaml b/policyengine_us/programs.yaml index 9272ced330b..b98e5e126b5 100644 --- a/policyengine_us/programs.yaml +++ b/policyengine_us/programs.yaml @@ -965,7 +965,7 @@ programs: name: Idaho LIHEAP full_name: Idaho Low Income Home Energy Assistance Program parameter_prefix: gov.states.id.dhw.liheap - notes: FY2026 household size, countable income, income limits and modeled financial eligibility. SNAP during the October-September program year or current SSI receipt bypasses the ordinary income test; annual SSI assumes stable current receipt. Means-tested VA categorical status is unobserved by existing inputs. The electric-benefit parameter table uses Idaho Power & Southern Utilities amounts without distinguishing electric-provider groups; it is not yet connected to household awards. No final eligibility or benefit award; current estimated heating costs, heating-area mapping, housing treatment and an energy-burden boundary remain unresolved. Annual flows approximate prior-month income. Earlier backfilled results are unverified historical estimates. + notes: FY2026 household size, countable income, income limits and modeled financial eligibility. SNAP during the October-September program year or current SSI receipt bypasses the ordinary income test; annual SSI assumes stable current receipt. Means-tested VA categorical status is unobserved by existing inputs. The electric-benefit parameter table uses Idaho Power & Southern Utilities amounts without distinguishing electric-provider groups; it is not yet connected to household awards. High energy burden includes exactly 11% under the user-approved modeling convention. No final eligibility or benefit award; current estimated heating costs, heating-area mapping and housing treatment remain unresolved. Annual flows approximate prior-month income. Earlier backfilled results are unverified historical estimates. # --- SSA programs --- - id: ssi From 137e64241d7727e203e767076f1a0ab225a8161b Mon Sep 17 00:00:00 2001 From: Ziming Date: Tue, 20 Oct 2026 21:10:35 -0400 Subject: [PATCH 06/10] Add approved Idaho heating areas and dated rent schedule --- changelog.d/id-liheap-wave2c.added.md | 2 +- .../gov/states/id/dhw/liheap/README.md | 54 +++++++++--- .../id/dhw/liheap/payment/heating_areas.yaml | 65 ++++++++++++++ .../states/id/dhw/liheap/payment/rent.yaml | 20 +++++ policyengine_us/programs.yaml | 2 +- .../id/dhw/liheap/id_liheap_heating_area.yaml | 87 +++++++++++++++++++ .../id/dhw/liheap/id_liheap_heating_area.py | 25 ++++++ 7 files changed, 243 insertions(+), 12 deletions(-) create mode 100644 policyengine_us/parameters/gov/states/id/dhw/liheap/payment/heating_areas.yaml create mode 100644 policyengine_us/parameters/gov/states/id/dhw/liheap/payment/rent.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/id_liheap_heating_area.yaml create mode 100644 policyengine_us/variables/gov/states/id/dhw/liheap/id_liheap_heating_area.py diff --git a/changelog.d/id-liheap-wave2c.added.md b/changelog.d/id-liheap-wave2c.added.md index c64f0478199..e6a996449ff 100644 --- a/changelog.d/id-liheap-wave2c.added.md +++ b/changelog.d/id-liheap-wave2c.added.md @@ -1 +1 @@ -Add Idaho LIHEAP income, household and financial-eligibility components with net Social Security, receipt-based income and the Idaho Power & Southern Utilities electric table. Document the approved high-burden convention of 11% or greater; the full heating award remains incomplete. +Add Idaho LIHEAP income, household, financial-eligibility and county-based heating-area components with net Social Security, receipt-based income and the Idaho Power & Southern Utilities electric table. Continue the historical county map under a user-approved assumption, with high burden at 11% or greater, and preserve the FY2025 $75 no-obligation rent base while following its FY2026 exclusion; the full heating award remains incomplete. diff --git a/policyengine_us/parameters/gov/states/id/dhw/liheap/README.md b/policyengine_us/parameters/gov/states/id/dhw/liheap/README.md index f99380f8837..b9fc9e0c0e7 100644 --- a/policyengine_us/parameters/gov/states/id/dhw/liheap/README.md +++ b/policyengine_us/parameters/gov/states/id/dhw/liheap/README.md @@ -1,8 +1,8 @@ # Idaho regular heating components The FY2026 components calculate qualified household size, countable income, -income limits and modeled financial eligibility. The ordinary income test is -inclusive. A household with a SNAP recipient during the October-September +income limits, modeled financial eligibility and the heating area. The ordinary +income test is inclusive. A household with a SNAP recipient during the October-September program year, or a current SSI recipient, is categorically income eligible. Income still determines the eventual award. Any household member can establish that categorical route; the model does not require every member to receive aid. @@ -37,9 +37,31 @@ distinguished for now; the Avista & Northern Utilities and Rocky Mountain Power columns are omitted. This is an explicit modeling simplification, not a claim that providers pay identical benefits. No utility-provider input is added. The table contains the base amounts before the vulnerable-household supplement. -It is not yet connected to a household award because the area and burden -calculations remain unresolved. Provider/company and administering-agency distinctions are outside this -implementation scope. +It is not yet connected to a household award because current estimated heating +costs are missing and existing inputs do not identify every heating-cost obligation. Provider/company and +administering-agency distinctions are outside this implementation scope. + +The user approved continuing the recovered 44-county heating-area map on +October 20, 2026. `id_liheap_heating_area` derives Areas I-III from the existing +county input using the complete left-hand county table in historical Appendix A. +The right-hand table duplicates Power County and omits Elmore County. The PDF +has no printed effective year; its metadata says last modified October 18, 2006, +and the archived copy was captured January 24, 2017. These dates do not establish +FY2026 applicability. The FY2026 parameter anchor records the approved modeling +continuation. Explicit unknown or unmatched counties return area zero; an omitted +county retains the shared geography fallback to Ada County, Area I. + +The FY2025 rent column pays a $75 base amount in every area and burden band, +before the separately determined target supplement. The accepted FY2025 plan +assigns that minimum to households with no specific heat-cost obligation. The +accepted FY2026 plan explicitly makes that category ineligible and the FY2026 +matrix drops its rent column. The user initially approved reusing the FY2025 +amount, then chose to follow the confirmed FY2026 rule on October 20, 2026. +The conditional rent parameter is therefore $75 for FY2025 and zero from +FY2026 for households without a specific heating-cost obligation. No rent +amount is connected to household awards. +The PY2008 subsidized-housing low-burden rule is excluded. Current housing +responsibility rules are described below. The approved energy-burden convention is low below 6%, medium from 6% up to but excluding 11%, and high at 11% or greater (`burden >= 0.11`). This includes @@ -51,11 +73,23 @@ explicitly included 11% in high. This is an approved modeling convention; the current source omission remains documented. Final eligibility and awards remain incomplete. The current estimated annual -heating-cost chart and current heating-area mapping have not been established. -The recovered historical county map and 2007 heating -costs are not promoted to FY2026 policy, and actual household bills do not replace -the state's estimated costs. The exactly-11-percent boundary is resolved by the -approved convention above. +heating-cost chart has not been established, and the PY2007 costs are excluded. +Actual household bills do not replace the state's estimated costs. The +exactly-11-percent boundary is resolved by the approved convention above. + +The accepted [FY2025 plan](https://liheapch.acf.gov/docs/2025/state-plans/ID_Plan_2025.pdf#page=9) +establishes the earlier $75 minimum for households without a specific heating +obligation. The accepted [FY2026 plan #page 8-9](https://liheapch.acf.gov/docs/2026/state-plans/ID_Plan_2026.pdf#page=8) +requires renters, including subsidized renters, to establish financial heating +responsibility and excludes households with no specific heating-cost obligation. +[IDAPA 16.03.08, sections 200.07 and 201](https://adminrules.idaho.gov/rules/current/16/160308.pdf#page=5), +effective July 1, 2026, likewise requires direct costs or a designated rent +portion. Applying the general fuel/area/burden matrix to otherwise eligible +subsidized households with a heating obligation is an interpretation supported +by these current rules. No current source specifies the old automatic low band. +The existing heat-in-rent flag does not distinguish free bundled heat from a +designated tenant heating charge, so it cannot determine every responsibility +case. No new responsibility input or blanket subsidy exclusion is added. FY2026 components and the selected electric table are researched and tested; the incomplete state has no fully verified policy year. Earlier parameter diff --git a/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/heating_areas.yaml b/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/heating_areas.yaml new file mode 100644 index 00000000000..d1d95bb4a7d --- /dev/null +++ b/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/heating_areas.yaml @@ -0,0 +1,65 @@ +description: Idaho groups counties into these heating areas under the Low Income Home Energy Assistance Program. + +# The user approved continuing the recovered county map on October 20, 2026. +# The FY2026 anchor is a modeling assumption, not a verified effective date. +# Use the complete left-hand county table on page 2; the right-hand table +# duplicates Power County and omits Elmore County. +area_1: + 2025-10-01: + - ADA_COUNTY_ID + - CANYON_COUNTY_ID + - ELMORE_COUNTY_ID + - GEM_COUNTY_ID + - GOODING_COUNTY_ID + - LATAH_COUNTY_ID + - NEZ_PERCE_COUNTY_ID + - OWYHEE_COUNTY_ID + - PAYETTE_COUNTY_ID + - WASHINGTON_COUNTY_ID +area_2: + 2025-10-01: + - ADAMS_COUNTY_ID + - BANNOCK_COUNTY_ID + - BENEWAH_COUNTY_ID + - BINGHAM_COUNTY_ID + - BOISE_COUNTY_ID + - BONNER_COUNTY_ID + - BOUNDARY_COUNTY_ID + - CASSIA_COUNTY_ID + - CLEARWATER_COUNTY_ID + - FRANKLIN_COUNTY_ID + - IDAHO_COUNTY_ID + - JEROME_COUNTY_ID + - KOOTENAI_COUNTY_ID + - LEWIS_COUNTY_ID + - LINCOLN_COUNTY_ID + - MINIDOKA_COUNTY_ID + - ONEIDA_COUNTY_ID + - POWER_COUNTY_ID + - SHOSHONE_COUNTY_ID + - TWIN_FALLS_COUNTY_ID +area_3: + 2025-10-01: + - BEAR_LAKE_COUNTY_ID + - BLAINE_COUNTY_ID + - BONNEVILLE_COUNTY_ID + - BUTTE_COUNTY_ID + - CAMAS_COUNTY_ID + - CARIBOU_COUNTY_ID + - CLARK_COUNTY_ID + - CUSTER_COUNTY_ID + - FREMONT_COUNTY_ID + - JEFFERSON_COUNTY_ID + - LEMHI_COUNTY_ID + - MADISON_COUNTY_ID + - TETON_COUNTY_ID + - VALLEY_COUNTY_ID + +metadata: + propagate_metadata_to_children: true + unit: list + period: year + label: Idaho LIHEAP heating-area counties + reference: + - title: Historical Idaho LIHEAP Intake Manual, Appendix A, county codes + href: https://web.archive.org/web/20170124204651id_/http://healthandwelfare.idaho.gov/portals/_rainbow/manuals/liheap/Appendices/a_codes_all.pdf#page=2 diff --git a/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/rent.yaml b/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/rent.yaml new file mode 100644 index 00000000000..3eae0a98b74 --- /dev/null +++ b/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/rent.yaml @@ -0,0 +1,20 @@ +description: Idaho provides this base benefit to households without a specific heating-cost obligation under the Low Income Home Energy Assistance Program. + +# FY2025 paid the minimum rent benefit before any target supplement. +# This category became ineligible in FY2026; zero is not an unknown amount. +# This rule does not exclude all renters or all subsidized households. +values: + 2024-10-01: 75 + 2025-10-01: 0 + +metadata: + unit: currency-USD + period: year + label: Idaho LIHEAP base benefit without a specific heating-cost obligation + reference: + - title: FY2025 Idaho LIHEAP State Plan, sections 2.5 and 2.6 + href: https://liheapch.acf.gov/docs/2025/state-plans/ID_Plan_2025.pdf#page=9 + - title: Idaho PY25 Benefit Determination Chart + href: https://liheapch.acf.gov/docs/2025/benefits-matricies/ID_BenefitMatrix_2025.pdf#page=1 + - title: FY2026 Idaho LIHEAP State Plan, sections 2.5 and 2.6 + href: https://liheapch.acf.gov/docs/2026/state-plans/ID_Plan_2026.pdf#page=9 diff --git a/policyengine_us/programs.yaml b/policyengine_us/programs.yaml index b98e5e126b5..7bfbb619175 100644 --- a/policyengine_us/programs.yaml +++ b/policyengine_us/programs.yaml @@ -965,7 +965,7 @@ programs: name: Idaho LIHEAP full_name: Idaho Low Income Home Energy Assistance Program parameter_prefix: gov.states.id.dhw.liheap - notes: FY2026 household size, countable income, income limits and modeled financial eligibility. SNAP during the October-September program year or current SSI receipt bypasses the ordinary income test; annual SSI assumes stable current receipt. Means-tested VA categorical status is unobserved by existing inputs. The electric-benefit parameter table uses Idaho Power & Southern Utilities amounts without distinguishing electric-provider groups; it is not yet connected to household awards. High energy burden includes exactly 11% under the user-approved modeling convention. No final eligibility or benefit award; current estimated heating costs, heating-area mapping and housing treatment remain unresolved. Annual flows approximate prior-month income. Earlier backfilled results are unverified historical estimates. + notes: FY2026 household size, countable income, income limits, modeled financial eligibility and derived heating area. SNAP during the October-September program year or current SSI receipt bypasses the ordinary income test; annual SSI assumes stable current receipt. Means-tested VA categorical status is unobserved by existing inputs. The electric-benefit parameter table uses Idaho Power & Southern Utilities amounts without distinguishing electric-provider groups. The recovered county map is continued by a user-approved modeling assumption. FY2026 excludes households without a specific heating-cost obligation; the conditional no-obligation rent parameter is $75 in FY2025 and zero from FY2026, following the accepted plans. High energy burden includes exactly 11% under the approved convention. No final eligibility or benefit award; current estimated heating costs are missing and existing inputs do not identify every heating-cost obligation. PY2007 costs and the PY2008 subsidized low-burden rule are excluded. Annual flows approximate prior-month income. Earlier backfilled results are unverified historical estimates. # --- SSA programs --- - id: ssi diff --git a/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/id_liheap_heating_area.yaml b/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/id_liheap_heating_area.yaml new file mode 100644 index 00000000000..8b9b307d169 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/id_liheap_heating_area.yaml @@ -0,0 +1,87 @@ +# Historical Idaho LIHEAP Intake Manual, Appendix A, physical page 2. +# https://web.archive.org/web/20170124204651id_/http://healthandwelfare.idaho.gov/portals/_rainbow/manuals/liheap/Appendices/a_codes_all.pdf#page=2 +# The user approved continuing this undated map in the current draft. +# Expected areas follow the complete left table in county-code order 1-44. +# The right table duplicates Power and omits Elmore; Elmore is in Area I. + +- name: Case 1, all forty-four counties follow the recovered county table. + period: 2026 + input: + state_code: [ID, ID, ID, ID, ID, ID, ID, ID, ID, ID, ID, + ID, ID, ID, ID, ID, ID, ID, ID, ID, ID, ID, + ID, ID, ID, ID, ID, ID, ID, ID, ID, ID, ID, + ID, ID, ID, ID, ID, ID, ID, ID, ID, ID, ID] + county: + - ADA_COUNTY_ID + - ADAMS_COUNTY_ID + - BANNOCK_COUNTY_ID + - BEAR_LAKE_COUNTY_ID + - BENEWAH_COUNTY_ID + - BINGHAM_COUNTY_ID + - BLAINE_COUNTY_ID + - BOISE_COUNTY_ID + - BONNER_COUNTY_ID + - BONNEVILLE_COUNTY_ID + - BOUNDARY_COUNTY_ID + - BUTTE_COUNTY_ID + - CAMAS_COUNTY_ID + - CANYON_COUNTY_ID + - CARIBOU_COUNTY_ID + - CASSIA_COUNTY_ID + - CLARK_COUNTY_ID + - CLEARWATER_COUNTY_ID + - CUSTER_COUNTY_ID + - ELMORE_COUNTY_ID + - FRANKLIN_COUNTY_ID + - FREMONT_COUNTY_ID + - GEM_COUNTY_ID + - GOODING_COUNTY_ID + - IDAHO_COUNTY_ID + - JEFFERSON_COUNTY_ID + - JEROME_COUNTY_ID + - KOOTENAI_COUNTY_ID + - LATAH_COUNTY_ID + - LEMHI_COUNTY_ID + - LEWIS_COUNTY_ID + - LINCOLN_COUNTY_ID + - MADISON_COUNTY_ID + - MINIDOKA_COUNTY_ID + - NEZ_PERCE_COUNTY_ID + - ONEIDA_COUNTY_ID + - OWYHEE_COUNTY_ID + - PAYETTE_COUNTY_ID + - POWER_COUNTY_ID + - SHOSHONE_COUNTY_ID + - TETON_COUNTY_ID + - TWIN_FALLS_COUNTY_ID + - VALLEY_COUNTY_ID + - WASHINGTON_COUNTY_ID + output: + id_liheap_heating_area: [1, 2, 2, 3, 2, 2, 3, 2, 2, 3, 2, + 3, 3, 1, 3, 2, 3, 2, 3, 1, 2, 3, + 1, 1, 2, 3, 2, 2, 1, 3, 2, 2, 3, + 2, 1, 2, 1, 1, 2, 2, 3, 2, 3, 1] + +- name: Case 2, unknown and out-of-state county strings remain unassigned. + period: 2026 + input: + state_code: [ID, ID] + county: [UNKNOWN, BAKER_COUNTY_OR] + output: + id_liheap_heating_area: [0, 0] + +- name: Case 3, omitted county inherits the shared Ada County fallback. + period: 2026 + input: + state_code: ID + output: + county_str: ADA_COUNTY_ID + id_liheap_heating_area: 1 + +- name: Case 4, mixed-state households only assign an Idaho heating area. + period: 2026 + input: + state_code: [ID, OR, OR] + county: [ADA_COUNTY_ID, ADA_COUNTY_ID, BAKER_COUNTY_OR] + output: + id_liheap_heating_area: [1, 0, 0] diff --git a/policyengine_us/variables/gov/states/id/dhw/liheap/id_liheap_heating_area.py b/policyengine_us/variables/gov/states/id/dhw/liheap/id_liheap_heating_area.py new file mode 100644 index 00000000000..08e7d3ce41d --- /dev/null +++ b/policyengine_us/variables/gov/states/id/dhw/liheap/id_liheap_heating_area.py @@ -0,0 +1,25 @@ +from policyengine_us.model_api import * + + +class id_liheap_heating_area(Variable): + value_type = int + entity = SPMUnit + label = "Idaho LIHEAP heating area" + definition_period = YEAR + defined_for = StateCode.ID + reference = "https://web.archive.org/web/20170124204651id_/http://healthandwelfare.idaho.gov/portals/_rainbow/manuals/liheap/Appendices/a_codes_all.pdf#page=2" + + def formula(spm_unit, period, parameters): + county = spm_unit.household("county_str", period) + p = parameters(period).gov.states.id.dhw.liheap.payment.heating_areas + # Area codes match the benefit matrix; zero leaves unmatched counties + # unassigned. The recovered map's continuation is user-approved. + return select( + [ + np.isin(county, p.area_1), + np.isin(county, p.area_2), + np.isin(county, p.area_3), + ], + [1, 2, 3], + default=0, + ) From 98302d04bf6015979c4e8a0fb750639dabf6cd38 Mon Sep 17 00:00:00 2001 From: Ziming Date: Tue, 20 Oct 2026 21:18:23 -0400 Subject: [PATCH 07/10] Use approved historical Idaho heating-cost assumptions --- changelog.d/id-liheap-wave2c.added.md | 2 +- .../gov/states/id/dhw/liheap/README.md | 33 ++++++++-- .../payment/estimated_heating_costs.yaml | 48 ++++++++++++++ policyengine_us/programs.yaml | 2 +- .../id_liheap_estimated_heating_cost.yaml | 66 +++++++++++++++++++ .../id_liheap_estimated_heating_cost.py | 38 +++++++++++ 6 files changed, 180 insertions(+), 9 deletions(-) create mode 100644 policyengine_us/parameters/gov/states/id/dhw/liheap/payment/estimated_heating_costs.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/id_liheap_estimated_heating_cost.yaml create mode 100644 policyengine_us/variables/gov/states/id/dhw/liheap/id_liheap_estimated_heating_cost.py diff --git a/changelog.d/id-liheap-wave2c.added.md b/changelog.d/id-liheap-wave2c.added.md index e6a996449ff..308e2f84851 100644 --- a/changelog.d/id-liheap-wave2c.added.md +++ b/changelog.d/id-liheap-wave2c.added.md @@ -1 +1 @@ -Add Idaho LIHEAP income, household, financial-eligibility and county-based heating-area components with net Social Security, receipt-based income and the Idaho Power & Southern Utilities electric table. Continue the historical county map under a user-approved assumption, with high burden at 11% or greater, and preserve the FY2025 $75 no-obligation rent base while following its FY2026 exclusion; the full heating award remains incomplete. +Add Idaho LIHEAP income, household, financial-eligibility and county-based heating-area and estimated heating-cost components with net Social Security, receipt-based income and the Idaho Power & Southern Utilities electric table. Continue the historical county map and PY2007 nine-month cost table under user-approved assumptions with unconfirmed FY2026 cost applicability, with high burden at 11% or greater, and preserve the FY2025 $75 no-obligation rent base while following its FY2026 exclusion; the full heating award remains incomplete. diff --git a/policyengine_us/parameters/gov/states/id/dhw/liheap/README.md b/policyengine_us/parameters/gov/states/id/dhw/liheap/README.md index b9fc9e0c0e7..4b9e31592ed 100644 --- a/policyengine_us/parameters/gov/states/id/dhw/liheap/README.md +++ b/policyengine_us/parameters/gov/states/id/dhw/liheap/README.md @@ -1,7 +1,8 @@ # Idaho regular heating components The FY2026 components calculate qualified household size, countable income, -income limits, modeled financial eligibility and the heating area. The ordinary +income limits, modeled financial eligibility, heating area and estimated heating +cost. The ordinary income test is inclusive. A household with a SNAP recipient during the October-September program year, or a current SSI recipient, is categorically income eligible. Income still determines the eventual award. Any household member can establish @@ -37,8 +38,9 @@ distinguished for now; the Avista & Northern Utilities and Rocky Mountain Power columns are omitted. This is an explicit modeling simplification, not a claim that providers pay identical benefits. No utility-provider input is added. The table contains the base amounts before the vulnerable-household supplement. -It is not yet connected to a household award because current estimated heating -costs are missing and existing inputs do not identify every heating-cost obligation. Provider/company and +The approved historical cost table is now available as a derived component. +These components are not yet connected to a final household award, and existing +inputs do not identify every heating-cost obligation. Provider/company and administering-agency distinctions are outside this implementation scope. The user approved continuing the recovered 44-county heating-area map on @@ -72,10 +74,27 @@ The [historical 2011 rule, section 204.03](https://adminrules.idaho.gov/rules/20 explicitly included 11% in high. This is an approved modeling convention; the current source omission remains documented. -Final eligibility and awards remain incomplete. The current estimated annual -heating-cost chart has not been established, and the PY2007 costs are excluded. -Actual household bills do not replace the state's estimated costs. The -exactly-11-percent boundary is resolved by the approved convention above. +The user approved using the PY2007 heating-cost table on October 20, 2026. +**We have not confirmed that it is still current for FY2026.** The parameter +comments and `id_liheap_estimated_heating_cost` preserve that limitation. The +source estimates nine months of heating costs; its nominal amounts are used +directly, without inflation or a twelve-month uplift. The FY2026 date anchor +records this approved modeling assumption. It does not establish a policy update. +The old Appendix C benefit percentages are not adopted. + +Electric costs use the same Idaho Power & Southern Utilities assumption as the +existing electric-benefit parameter. Natural gas uses Intermountain Gas as one +representative column because it contains nonzero values in all three areas; +this is a documented implementation simplification rather than a provider +selector. Oil/propane and coal/wood retain their shared source rows. The old +rent-cost column is not used: FY2025 has a flat no-obligation benefit and +FY2026 excludes that category. Unknown areas and unsupported fuels return zero +modeled estimated cost, not a finding of legal ineligibility or zero actual +heating expenses. + +Final eligibility and awards remain incomplete. Actual household bills do not +replace the assumed state cost table. The exactly-11-percent boundary is +resolved by the approved convention above. The accepted [FY2025 plan](https://liheapch.acf.gov/docs/2025/state-plans/ID_Plan_2025.pdf#page=9) establishes the earlier $75 minimum for households without a specific heating diff --git a/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/estimated_heating_costs.yaml b/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/estimated_heating_costs.yaml new file mode 100644 index 00000000000..5e55553df83 --- /dev/null +++ b/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/estimated_heating_costs.yaml @@ -0,0 +1,48 @@ +description: Idaho uses these estimated heating-season costs by fuel and heating area under the Low Income Home Energy Assistance Program. + +# User-approved assumption: use the PY2007 estimated nine-month heating costs. +# We have not confirmed that this table is still current for FY2026. +# The FY2026 anchor records this modeling assumption, not a verified update. +# Preserve the published amounts without inflation or a twelve-month uplift. +# Provider groups are not distinguished. Electricity uses Idaho Power & +# Southern Utilities; natural gas uses the complete Intermountain Gas column. +# The old rent-cost column and old benefit percentages are not used. +oil_or_propane: + 1: + 2025-10-01: 1_625 + 2: + 2025-10-01: 1_845 + 3: + 2025-10-01: 2_145 +natural_gas: + 1: + 2025-10-01: 977 + 2: + 2025-10-01: 1_100 + 3: + 2025-10-01: 1_207 +electricity: + 1: + 2025-10-01: 1_335 + 2: + 2025-10-01: 1_455 + 3: + 2025-10-01: 1_605 +coal_or_wood: + 1: + 2025-10-01: 1_200 + 2: + 2025-10-01: 1_600 + 3: + 2025-10-01: 1_800 + +metadata: + propagate_metadata_to_children: true + unit: currency-USD + period: year + label: Idaho LIHEAP estimated nine-month heating costs + reference: + - title: Historical Idaho LIHEAP Intake Manual, Appendix C, average heating-cost matrix + href: https://web.archive.org/web/20170127123014id_/http://www.healthandwelfare.idaho.gov/Portals/_Rainbow/Manuals/LIHEAP/Appendices/c_htgcost_matrix_PY07.pdf#page=1 + - title: Historical Idaho LIHEAP Intake Manual, Heating Cost Estimation, PY2007 nine-month matrix + href: https://web.archive.org/web/20080512165351id_/http://www.healthandwelfare.idaho.gov:80/Portals/_Rainbow/Manuals/LIHEAP/Benefit_Calculation/Heating_Cost_Estimation.htm diff --git a/policyengine_us/programs.yaml b/policyengine_us/programs.yaml index 7bfbb619175..5ffcda91c4f 100644 --- a/policyengine_us/programs.yaml +++ b/policyengine_us/programs.yaml @@ -965,7 +965,7 @@ programs: name: Idaho LIHEAP full_name: Idaho Low Income Home Energy Assistance Program parameter_prefix: gov.states.id.dhw.liheap - notes: FY2026 household size, countable income, income limits, modeled financial eligibility and derived heating area. SNAP during the October-September program year or current SSI receipt bypasses the ordinary income test; annual SSI assumes stable current receipt. Means-tested VA categorical status is unobserved by existing inputs. The electric-benefit parameter table uses Idaho Power & Southern Utilities amounts without distinguishing electric-provider groups. The recovered county map is continued by a user-approved modeling assumption. FY2026 excludes households without a specific heating-cost obligation; the conditional no-obligation rent parameter is $75 in FY2025 and zero from FY2026, following the accepted plans. High energy burden includes exactly 11% under the approved convention. No final eligibility or benefit award; current estimated heating costs are missing and existing inputs do not identify every heating-cost obligation. PY2007 costs and the PY2008 subsidized low-burden rule are excluded. Annual flows approximate prior-month income. Earlier backfilled results are unverified historical estimates. + notes: FY2026 household size, countable income, income limits, modeled financial eligibility and derived heating area. SNAP during the October-September program year or current SSI receipt bypasses the ordinary income test; annual SSI assumes stable current receipt. Means-tested VA categorical status is unobserved by existing inputs. The electric-benefit parameter table uses Idaho Power & Southern Utilities amounts without distinguishing electric-provider groups. The recovered county map and PY2007 nine-month estimated heating costs are continued by user-approved modeling assumptions; FY2026 cost applicability is unconfirmed. Electric costs use Idaho Power & Southern Utilities and gas costs use one representative Intermountain column, without provider selectors. FY2026 excludes households without a specific heating-cost obligation; the conditional no-obligation rent parameter is $75 in FY2025 and zero from FY2026, following the accepted plans. High energy burden includes exactly 11% under the approved convention. No final eligibility or benefit award; existing inputs do not identify every heating-cost obligation. The PY2008 subsidized low-burden rule remains excluded. Annual flows approximate prior-month income. Earlier backfilled results are unverified historical estimates. # --- SSA programs --- - id: ssi diff --git a/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/id_liheap_estimated_heating_cost.yaml b/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/id_liheap_estimated_heating_cost.yaml new file mode 100644 index 00000000000..a480cc62b24 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/id_liheap_estimated_heating_cost.yaml @@ -0,0 +1,66 @@ +# Historical Idaho LIHEAP Intake Manual, Appendix C, physical page 1. +# https://web.archive.org/web/20170127123014id_/http://www.healthandwelfare.idaho.gov/Portals/_Rainbow/Manuals/LIHEAP/Appendices/c_htgcost_matrix_PY07.pdf#page=1 +# PY2007 estimated nine-month costs are used provisionally by user approval; +# their current FY2026 applicability is unconfirmed. No inflation or 12/9 scaling. +# Electricity uses Idaho Power & Southern Utilities. Natural gas uses the +# Intermountain column as a modeling simplification, without a provider input. + +- name: Case 1, six supported fuels use the historical costs in all three areas. + period: 2026 + absolute_error_margin: 0.01 + input: + state_code: [ID, ID, ID, ID, ID, ID, ID, ID, ID, + ID, ID, ID, ID, ID, ID, ID, ID, ID] + county: [ADA_COUNTY_ID, BANNOCK_COUNTY_ID, BEAR_LAKE_COUNTY_ID, + ADA_COUNTY_ID, BANNOCK_COUNTY_ID, BEAR_LAKE_COUNTY_ID, + ADA_COUNTY_ID, BANNOCK_COUNTY_ID, BEAR_LAKE_COUNTY_ID, + ADA_COUNTY_ID, BANNOCK_COUNTY_ID, BEAR_LAKE_COUNTY_ID, + ADA_COUNTY_ID, BANNOCK_COUNTY_ID, BEAR_LAKE_COUNTY_ID, + ADA_COUNTY_ID, BANNOCK_COUNTY_ID, BEAR_LAKE_COUNTY_ID] + heating_type: [ELECTRICITY, ELECTRICITY, ELECTRICITY, + NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, + FUEL_OIL, FUEL_OIL, FUEL_OIL, + PROPANE, PROPANE, PROPANE, + WOOD, WOOD, WOOD, + COAL, COAL, COAL] + output: + id_liheap_estimated_heating_cost: [1_335, 1_455, 1_605, + 977, 1_100, 1_207, + 1_625, 1_845, 2_145, + 1_625, 1_845, 2_145, + 1_200, 1_600, 1_800, + 1_200, 1_600, 1_800] + +- name: Case 2, unknown areas and unsupported fuels have no modeled cost. + period: 2026 + absolute_error_margin: 0.01 + # Zero denotes an unmodeled cost, not a legal eligibility determination. + input: + state_code: [ID, ID, ID, ID, ID, ID, ID] + county: [UNKNOWN, BAKER_COUNTY_OR, ADA_COUNTY_ID, ADA_COUNTY_ID, + ADA_COUNTY_ID, ADA_COUNTY_ID, ADA_COUNTY_ID] + heating_type: [ELECTRICITY, ELECTRICITY, UNSPECIFIED, NONE, + OTHER, SOLAR, KEROSENE] + output: + id_liheap_estimated_heating_cost: [0, 0, 0, 0, 0, 0, 0] + +- name: Case 3, omitted county uses the shared Ada fallback and its electric cost. + period: 2026 + absolute_error_margin: 0.01 + input: + state_code: ID + heating_type: ELECTRICITY + output: + county_str: ADA_COUNTY_ID + id_liheap_estimated_heating_cost: 1_335 + +- name: Case 4, mixed-state households isolate Idaho estimated heating costs. + period: 2026 + absolute_error_margin: 0.01 + input: + state_code: [ID, OR, ID, OR] + county: [BEAR_LAKE_COUNTY_ID, BEAR_LAKE_COUNTY_ID, + ADA_COUNTY_ID, BAKER_COUNTY_OR] + heating_type: [NATURAL_GAS, NATURAL_GAS, COAL, ELECTRICITY] + output: + id_liheap_estimated_heating_cost: [1_207, 0, 1_200, 0] diff --git a/policyengine_us/variables/gov/states/id/dhw/liheap/id_liheap_estimated_heating_cost.py b/policyengine_us/variables/gov/states/id/dhw/liheap/id_liheap_estimated_heating_cost.py new file mode 100644 index 00000000000..3fd5df576ff --- /dev/null +++ b/policyengine_us/variables/gov/states/id/dhw/liheap/id_liheap_estimated_heating_cost.py @@ -0,0 +1,38 @@ +from policyengine_us.model_api import * + + +class id_liheap_estimated_heating_cost(Variable): + value_type = float + entity = SPMUnit + label = "Idaho LIHEAP estimated heating cost" + unit = USD + definition_period = YEAR + defined_for = StateCode.ID + reference = "https://web.archive.org/web/20170127123014id_/http://www.healthandwelfare.idaho.gov/Portals/_Rainbow/Manuals/LIHEAP/Appendices/c_htgcost_matrix_PY07.pdf#page=1" + + def formula(spm_unit, period, parameters): + area = spm_unit("id_liheap_heating_area", period) + heating = spm_unit("heating_type", period) + types = heating.possible_values + p = parameters(period).gov.states.id.dhw.liheap.payment.estimated_heating_costs + # PY2007 nine-month cost proxy; FY2026 applicability is unconfirmed. + # Safe lookup leaves unknown areas unassigned after fuel selection. + lookup_area = clip(area, 1, 3) + cost = select( + [ + heating == types.ELECTRICITY, + heating == types.NATURAL_GAS, + (heating == types.FUEL_OIL) | (heating == types.PROPANE), + (heating == types.COAL) | (heating == types.WOOD), + ], + [ + p.electricity[lookup_area], + p.natural_gas[lookup_area], + p.oil_or_propane[lookup_area], + p.coal_or_wood[lookup_area], + ], + default=0, + ) + # Zero for unknown area or unsupported fuel is no modeled cost, + # not a determination of legal ineligibility or actual heating costs. + return where((area >= 1) & (area <= 3), cost, 0) From 9414e8557f667cc4fb0501c9583c5467c2814f17 Mon Sep 17 00:00:00 2001 From: Ziming Date: Mon, 2 Nov 2026 11:53:52 -0500 Subject: [PATCH 08/10] Apply Wave 2C sweep and review fixes Co-Authored-By: Claude Opus 5.5 --- changelog.d/id-liheap-wave2c.added.md | 2 +- .../gov/states/id/dhw/liheap/README.md | 116 -------- .../dhw/liheap/eligibility/fpg_year_lag.yaml | 4 +- .../dhw/liheap/income/sources/unearned.yaml | 11 +- .../payment/energy_burden/high_rate.yaml | 13 + .../payment/energy_burden/medium_rate.yaml | 11 + .../payment/estimated_heating_costs.yaml | 4 +- .../id/dhw/liheap/payment/heating_areas.yaml | 4 +- .../liheap/payment/matrix/coal_or_wood.yaml | 40 +++ .../liheap/payment/matrix/electricity.yaml | 3 - .../liheap/payment/matrix/natural_gas.yaml | 43 +++ .../liheap/payment/matrix/oil_or_propane.yaml | 40 +++ .../states/id/dhw/liheap/payment/rent.yaml | 2 +- .../liheap/payment/target_bonus/amount.yaml | 13 + .../payment/target_bonus/child_age_limit.yaml | 11 + .../payment/target_bonus/elderly_age.yaml | 11 + policyengine_us/programs.yaml | 5 +- .../eligibility/id_liheap_eligible.yaml | 58 ++++ .../eligibility/id_liheap_household_size.yaml | 22 +- .../id_liheap_income_eligible.yaml | 88 +++--- .../eligibility/id_liheap_income_limit.yaml | 46 ++-- .../gov/states/id/dhw/liheap/id_liheap.yaml | 254 ++++++++++++++++++ .../id_liheap_estimated_heating_cost.yaml | 22 +- .../id/dhw/liheap/id_liheap_heating_area.yaml | 2 +- .../income/id_liheap_countable_income.yaml | 170 +++++++----- .../liheap/eligibility/id_liheap_eligible.py | 31 +++ .../eligibility/id_liheap_income_eligible.py | 6 +- .../eligibility/id_liheap_income_limit.py | 13 +- .../gov/states/id/dhw/liheap/id_liheap.py | 64 +++++ .../id_liheap_estimated_heating_cost.py | 8 +- .../id/dhw/liheap/id_liheap_heating_area.py | 2 +- .../income/id_liheap_countable_income.py | 16 +- 32 files changed, 837 insertions(+), 298 deletions(-) delete mode 100644 policyengine_us/parameters/gov/states/id/dhw/liheap/README.md create mode 100644 policyengine_us/parameters/gov/states/id/dhw/liheap/payment/energy_burden/high_rate.yaml create mode 100644 policyengine_us/parameters/gov/states/id/dhw/liheap/payment/energy_burden/medium_rate.yaml create mode 100644 policyengine_us/parameters/gov/states/id/dhw/liheap/payment/matrix/coal_or_wood.yaml create mode 100644 policyengine_us/parameters/gov/states/id/dhw/liheap/payment/matrix/natural_gas.yaml create mode 100644 policyengine_us/parameters/gov/states/id/dhw/liheap/payment/matrix/oil_or_propane.yaml create mode 100644 policyengine_us/parameters/gov/states/id/dhw/liheap/payment/target_bonus/amount.yaml create mode 100644 policyengine_us/parameters/gov/states/id/dhw/liheap/payment/target_bonus/child_age_limit.yaml create mode 100644 policyengine_us/parameters/gov/states/id/dhw/liheap/payment/target_bonus/elderly_age.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/eligibility/id_liheap_eligible.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/id_liheap.yaml create mode 100644 policyengine_us/variables/gov/states/id/dhw/liheap/eligibility/id_liheap_eligible.py create mode 100644 policyengine_us/variables/gov/states/id/dhw/liheap/id_liheap.py diff --git a/changelog.d/id-liheap-wave2c.added.md b/changelog.d/id-liheap-wave2c.added.md index 308e2f84851..d16ab73d290 100644 --- a/changelog.d/id-liheap-wave2c.added.md +++ b/changelog.d/id-liheap-wave2c.added.md @@ -1 +1 @@ -Add Idaho LIHEAP income, household, financial-eligibility and county-based heating-area and estimated heating-cost components with net Social Security, receipt-based income and the Idaho Power & Southern Utilities electric table. Continue the historical county map and PY2007 nine-month cost table under user-approved assumptions with unconfirmed FY2026 cost applicability, with high burden at 11% or greater, and preserve the FY2025 $75 no-obligation rent base while following its FY2026 exclusion; the full heating award remains incomplete. +Add Idaho LIHEAP regular heating assistance for FY2026. diff --git a/policyengine_us/parameters/gov/states/id/dhw/liheap/README.md b/policyengine_us/parameters/gov/states/id/dhw/liheap/README.md deleted file mode 100644 index 4b9e31592ed..00000000000 --- a/policyengine_us/parameters/gov/states/id/dhw/liheap/README.md +++ /dev/null @@ -1,116 +0,0 @@ -# Idaho regular heating components - -The FY2026 components calculate qualified household size, countable income, -income limits, modeled financial eligibility, heating area and estimated heating -cost. The ordinary -income test is inclusive. A household with a SNAP recipient during the October-September -program year, or a current SSI recipient, is categorically income eligible. -Income still determines the eventual award. Any household member can establish -that categorical route; the model does not require every member to receive aid. -A household with no qualified members cannot qualify. - -SNAP uses the actual twelve-month program-year window: FY2026 reads October 2025 -through September 2026. SSI uses annual positive benefits as a stable-current- -receipt approximation because application month is not an input. The model's -annual income flows likewise approximate the prior-month assessment. Existing -net business inputs receive no second expense deduction. Received sources are -floored separately per person so losses do not cancel other receipts. Social -Security is counted net of the existing Part B premium, floored at zero for -each person; excess premiums cannot reduce pensions or another member's income. -Military retirement pay is counted separately from pension and retirement-account -aggregates. UI uses reported compensation or the shared modeled-state fallback. -TANF is take-up gated and counted once per household, without adding a TANF -categorical route. SPM membership -approximates the household sharing home heating costs. - -Means-tested veterans benefits also establish categorical eligibility, but the -existing aggregate veterans_benefits input does not distinguish them from other -VA benefits. That route remains unobserved; a false modeled financial predicate -is not a definitive legal denial for such a household. No new input or blanket -VA qualification is introduced. Housing, heating-cost responsibility and -administrative requirements are separate from this financial component. -The predecessor rule's discretionary catastrophic-illness exception also needs -an administrative determination that existing inputs cannot establish. - -The electric-benefit parameter table uses the Idaho Power & Southern Utilities -column for all three heating areas. Electric utility-provider groups are not -distinguished for now; the Avista & Northern Utilities and Rocky Mountain Power -columns are omitted. This is an explicit modeling simplification, not a claim -that providers pay identical benefits. No utility-provider input is added. -The table contains the base amounts before the vulnerable-household supplement. -The approved historical cost table is now available as a derived component. -These components are not yet connected to a final household award, and existing -inputs do not identify every heating-cost obligation. Provider/company and -administering-agency distinctions are outside this implementation scope. - -The user approved continuing the recovered 44-county heating-area map on -October 20, 2026. `id_liheap_heating_area` derives Areas I-III from the existing -county input using the complete left-hand county table in historical Appendix A. -The right-hand table duplicates Power County and omits Elmore County. The PDF -has no printed effective year; its metadata says last modified October 18, 2006, -and the archived copy was captured January 24, 2017. These dates do not establish -FY2026 applicability. The FY2026 parameter anchor records the approved modeling -continuation. Explicit unknown or unmatched counties return area zero; an omitted -county retains the shared geography fallback to Ada County, Area I. - -The FY2025 rent column pays a $75 base amount in every area and burden band, -before the separately determined target supplement. The accepted FY2025 plan -assigns that minimum to households with no specific heat-cost obligation. The -accepted FY2026 plan explicitly makes that category ineligible and the FY2026 -matrix drops its rent column. The user initially approved reusing the FY2025 -amount, then chose to follow the confirmed FY2026 rule on October 20, 2026. -The conditional rent parameter is therefore $75 for FY2025 and zero from -FY2026 for households without a specific heating-cost obligation. No rent -amount is connected to household awards. -The PY2008 subsidized-housing low-burden rule is excluded. Current housing -responsibility rules are described below. - -The approved energy-burden convention is low below 6%, medium from 6% up to -but excluding 11%, and high at 11% or greater (`burden >= 0.11`). This includes -exactly 11% in the high group. The user approved this interpretation on -October 20, 2026: the [FY2026 matrix methodology](https://liheapch.acf.gov/docs/2026/benefits-matricies/ID_BenefitMatrix_Heating_2026.pdf#page=2) -prints medium below 11% and high above 11%, leaving exactly 11% unassigned. -The [historical 2011 rule, section 204.03](https://adminrules.idaho.gov/rules/2011/16/0414.pdf#page=8) -explicitly included 11% in high. This is an approved modeling convention; -the current source omission remains documented. - -The user approved using the PY2007 heating-cost table on October 20, 2026. -**We have not confirmed that it is still current for FY2026.** The parameter -comments and `id_liheap_estimated_heating_cost` preserve that limitation. The -source estimates nine months of heating costs; its nominal amounts are used -directly, without inflation or a twelve-month uplift. The FY2026 date anchor -records this approved modeling assumption. It does not establish a policy update. -The old Appendix C benefit percentages are not adopted. - -Electric costs use the same Idaho Power & Southern Utilities assumption as the -existing electric-benefit parameter. Natural gas uses Intermountain Gas as one -representative column because it contains nonzero values in all three areas; -this is a documented implementation simplification rather than a provider -selector. Oil/propane and coal/wood retain their shared source rows. The old -rent-cost column is not used: FY2025 has a flat no-obligation benefit and -FY2026 excludes that category. Unknown areas and unsupported fuels return zero -modeled estimated cost, not a finding of legal ineligibility or zero actual -heating expenses. - -Final eligibility and awards remain incomplete. Actual household bills do not -replace the assumed state cost table. The exactly-11-percent boundary is -resolved by the approved convention above. - -The accepted [FY2025 plan](https://liheapch.acf.gov/docs/2025/state-plans/ID_Plan_2025.pdf#page=9) -establishes the earlier $75 minimum for households without a specific heating -obligation. The accepted [FY2026 plan #page 8-9](https://liheapch.acf.gov/docs/2026/state-plans/ID_Plan_2026.pdf#page=8) -requires renters, including subsidized renters, to establish financial heating -responsibility and excludes households with no specific heating-cost obligation. -[IDAPA 16.03.08, sections 200.07 and 201](https://adminrules.idaho.gov/rules/current/16/160308.pdf#page=5), -effective July 1, 2026, likewise requires direct costs or a designated rent -portion. Applying the general fuel/area/burden matrix to otherwise eligible -subsidized households with a heating obligation is an interpretation supported -by these current rules. No current source specifies the old automatic low band. -The existing heat-in-rent flag does not distinguish free bundled heat from a -designated tenant heating charge, so it cannot determine every responsibility -case. No new responsibility input or blanket subsidy exclusion is added. - -FY2026 components and the selected electric table are researched and tested; the -incomplete state has no fully verified policy year. Earlier parameter -backfills are unverified historical estimates. Crisis, cooling, weatherization -and equipment are outside scope. diff --git a/policyengine_us/parameters/gov/states/id/dhw/liheap/eligibility/fpg_year_lag.yaml b/policyengine_us/parameters/gov/states/id/dhw/liheap/eligibility/fpg_year_lag.yaml index 74a2efb431d..cc6e6cadd72 100644 --- a/policyengine_us/parameters/gov/states/id/dhw/liheap/eligibility/fpg_year_lag.yaml +++ b/policyengine_us/parameters/gov/states/id/dhw/liheap/eligibility/fpg_year_lag.yaml @@ -7,5 +7,7 @@ metadata: period: year label: Idaho LIHEAP FPG year lag reference: - - title: Idaho FY2026 LIHEAP State Plan + - title: Idaho FY2026 LIHEAP State Plan, section 2.1 href: https://liheapch.acf.gov/docs/2026/state-plans/ID_Plan_2026.pdf#page=8 + - title: Idaho Department of Health and Welfare, monthly limits effective October 1, 2025 + href: https://healthandwelfare.idaho.gov/services-programs/financial-assistance/home-heating-and-utility-assistance/apply-heating-assistance diff --git a/policyengine_us/parameters/gov/states/id/dhw/liheap/income/sources/unearned.yaml b/policyengine_us/parameters/gov/states/id/dhw/liheap/income/sources/unearned.yaml index 205941e023f..e784e31fb92 100644 --- a/policyengine_us/parameters/gov/states/id/dhw/liheap/income/sources/unearned.yaml +++ b/policyengine_us/parameters/gov/states/id/dhw/liheap/income/sources/unearned.yaml @@ -4,7 +4,9 @@ values: 2025-10-01: - ssi - pension_income - - military_retirement_pay + # Military retirement includes Survivor Benefit Plan annuities. + - military_retirement_income + - railroad_benefits # Ongoing IRA/401k distributions are separate from pension_income. # Existing annual inputs do not identify an excluded one-time lump sum. - retirement_distributions @@ -19,6 +21,11 @@ values: - estate_income - disability_benefits - workers_compensation + # Plan 1.9's checked Other line and IDAPA 16.04.14.151.02.f count gifts and + # lottery winnings over $30, although its lump-sum line is unchecked. The + # specific line is followed. The $30 test has no input: annual amounts count. + - gambling_winnings + - financial_assistance metadata: unit: list @@ -27,3 +34,5 @@ metadata: reference: - title: "Idaho FY2026 LIHEAP State Plan #page 5-7" href: https://liheapch.acf.gov/docs/2026/state-plans/ID_Plan_2026.pdf#page=5 + - title: IDAPA 16.04.14.151.02 as of September 10, 2025 + href: https://web.archive.org/web/20250910171431id_/https://adminrules.idaho.gov/rules/current/16/160414.pdf#page=5 diff --git a/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/energy_burden/high_rate.yaml b/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/energy_burden/high_rate.yaml new file mode 100644 index 00000000000..8bcfd4b36fe --- /dev/null +++ b/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/energy_burden/high_rate.yaml @@ -0,0 +1,13 @@ +description: Idaho places households in the high energy-burden group when estimated annual heating costs reach this share of annual income under the Low Income Home Energy Assistance Program. + +# Modeling convention: exactly 11% is high; the published chart omits that boundary. +values: + 2025-10-01: 0.11 + +metadata: + unit: /1 + period: year + label: Idaho LIHEAP high energy-burden rate + reference: + - title: Idaho PY26 LIHEAP Benefit Determination Chart PDF, PY23 LIHEAP Benefit Matrix Summary + href: https://liheapch.acf.gov/docs/2026/benefits-matricies/ID_BenefitMatrix_Heating_2026.pdf#page=2 diff --git a/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/energy_burden/medium_rate.yaml b/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/energy_burden/medium_rate.yaml new file mode 100644 index 00000000000..ee528f29786 --- /dev/null +++ b/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/energy_burden/medium_rate.yaml @@ -0,0 +1,11 @@ +description: Idaho places households in the medium energy-burden group when estimated annual heating costs reach this share of annual income under the Low Income Home Energy Assistance Program. +values: + 2025-10-01: 0.06 + +metadata: + unit: /1 + period: year + label: Idaho LIHEAP medium energy-burden rate + reference: + - title: Idaho PY26 LIHEAP Benefit Determination Chart PDF, PY23 LIHEAP Benefit Matrix Summary + href: https://liheapch.acf.gov/docs/2026/benefits-matricies/ID_BenefitMatrix_Heating_2026.pdf#page=2 diff --git a/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/estimated_heating_costs.yaml b/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/estimated_heating_costs.yaml index 5e55553df83..e27544cf740 100644 --- a/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/estimated_heating_costs.yaml +++ b/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/estimated_heating_costs.yaml @@ -1,7 +1,7 @@ description: Idaho uses these estimated heating-season costs by fuel and heating area under the Low Income Home Energy Assistance Program. -# User-approved assumption: use the PY2007 estimated nine-month heating costs. -# We have not confirmed that this table is still current for FY2026. +# Modeling assumption: the PY2007 estimated nine-month heating costs continue. +# This table is not confirmed as current for FY2026. # The FY2026 anchor records this modeling assumption, not a verified update. # Preserve the published amounts without inflation or a twelve-month uplift. # Provider groups are not distinguished. Electricity uses Idaho Power & diff --git a/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/heating_areas.yaml b/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/heating_areas.yaml index d1d95bb4a7d..dd69c03a048 100644 --- a/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/heating_areas.yaml +++ b/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/heating_areas.yaml @@ -1,7 +1,7 @@ description: Idaho groups counties into these heating areas under the Low Income Home Energy Assistance Program. -# The user approved continuing the recovered county map on October 20, 2026. -# The FY2026 anchor is a modeling assumption, not a verified effective date. +# The recovered historical county map continues as a modeling assumption. +# The FY2026 anchor is not a verified effective date. # Use the complete left-hand county table on page 2; the right-hand table # duplicates Power County and omits Elmore County. area_1: diff --git a/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/matrix/coal_or_wood.yaml b/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/matrix/coal_or_wood.yaml new file mode 100644 index 00000000000..799a66ed79c --- /dev/null +++ b/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/matrix/coal_or_wood.yaml @@ -0,0 +1,40 @@ +description: Idaho provides this base coal or wood heating benefit by heating area and energy-burden group under the Low Income Home Energy Assistance Program. + +# Heating areas 1-3 correspond to Areas I-III in the published chart. +# Energy-burden groups: 1 = low, 2 = medium, 3 = high. +1: + 1: + 2025-10-01: 467 + 2: + 2025-10-01: 486 + 3: + 2025-10-01: 505 +2: + 1: + 2025-10-01: 544 + 2: + 2025-10-01: 567 + 3: + 2025-10-01: 590 +3: + 1: + 2025-10-01: 622 + 2: + 2025-10-01: 648 + 3: + 2025-10-01: 674 + +metadata: + propagate_metadata_to_children: true + unit: currency-USD + period: year + label: Idaho LIHEAP base coal or wood heating benefit + breakdown: + - range(1, 4) + - range(1, 4) + breakdown_labels: + - Heating area + - Energy-burden group + reference: + - title: Idaho PY26 LIHEAP Benefit Determination Chart + href: https://liheapch.acf.gov/docs/2026/benefits-matricies/ID_BenefitMatrix_Heating_2026.pdf#page=1 diff --git a/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/matrix/electricity.yaml b/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/matrix/electricity.yaml index 78612d38ef8..bb42cb0876e 100644 --- a/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/matrix/electricity.yaml +++ b/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/matrix/electricity.yaml @@ -5,9 +5,6 @@ description: Idaho provides this base electric-heating benefit by heating area a # Northern Utilities and Rocky Mountain Power columns. # Heating areas 1-3 correspond to Areas I-III in the published chart. # Energy-burden groups: 1 = low, 2 = medium, 3 = high. -# Approved convention: low < 6%; medium >= 6% and < 11%; high >= 11%. -# Exactly 11% is high by the user's October 20, 2026 decision; see README.md. -# Amounts exclude the separate vulnerable-household supplement. 1: 1: 2025-10-01: 328 diff --git a/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/matrix/natural_gas.yaml b/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/matrix/natural_gas.yaml new file mode 100644 index 00000000000..616f0b94cde --- /dev/null +++ b/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/matrix/natural_gas.yaml @@ -0,0 +1,43 @@ +description: Idaho provides this base natural gas heating benefit by heating area and energy-burden group under the Low Income Home Energy Assistance Program. + +# Natural gas provider groups are not distinguished in the model for now. +# Use the Intermountain Gas column, the only one filled in all three areas; +# omit the Avista column. Matches estimated_heating_costs. +# Heating areas 1-3 correspond to Areas I-III in the published chart. +# Energy-burden groups: 1 = low, 2 = medium, 3 = high. +1: + 1: + 2025-10-01: 122 + 2: + 2025-10-01: 127 + 3: + 2025-10-01: 132 +2: + 1: + 2025-10-01: 141 + 2: + 2025-10-01: 147 + 3: + 2025-10-01: 152 +3: + 1: + 2025-10-01: 159 + 2: + 2025-10-01: 166 + 3: + 2025-10-01: 173 + +metadata: + propagate_metadata_to_children: true + unit: currency-USD + period: year + label: Idaho LIHEAP base natural gas heating benefit + breakdown: + - range(1, 4) + - range(1, 4) + breakdown_labels: + - Heating area + - Energy-burden group + reference: + - title: Idaho PY26 LIHEAP Benefit Determination Chart + href: https://liheapch.acf.gov/docs/2026/benefits-matricies/ID_BenefitMatrix_Heating_2026.pdf#page=1 diff --git a/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/matrix/oil_or_propane.yaml b/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/matrix/oil_or_propane.yaml new file mode 100644 index 00000000000..209c7a4e556 --- /dev/null +++ b/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/matrix/oil_or_propane.yaml @@ -0,0 +1,40 @@ +description: Idaho provides this base oil or propane heating benefit by heating area and energy-burden group under the Low Income Home Energy Assistance Program. + +# Heating areas 1-3 correspond to Areas I-III in the published chart. +# Energy-burden groups: 1 = low, 2 = medium, 3 = high. +1: + 1: + 2025-10-01: 776 + 2: + 2025-10-01: 808 + 3: + 2025-10-01: 840 +2: + 1: + 2025-10-01: 970 + 2: + 2025-10-01: 1_010 + 3: + 2025-10-01: 1_050 +3: + 1: + 2025-10-01: 1_164 + 2: + 2025-10-01: 1_212 + 3: + 2025-10-01: 1_260 + +metadata: + propagate_metadata_to_children: true + unit: currency-USD + period: year + label: Idaho LIHEAP base oil or propane heating benefit + breakdown: + - range(1, 4) + - range(1, 4) + breakdown_labels: + - Heating area + - Energy-burden group + reference: + - title: Idaho PY26 LIHEAP Benefit Determination Chart + href: https://liheapch.acf.gov/docs/2026/benefits-matricies/ID_BenefitMatrix_Heating_2026.pdf#page=1 diff --git a/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/rent.yaml b/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/rent.yaml index 3eae0a98b74..0a61e7dc099 100644 --- a/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/rent.yaml +++ b/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/rent.yaml @@ -15,6 +15,6 @@ metadata: - title: FY2025 Idaho LIHEAP State Plan, sections 2.5 and 2.6 href: https://liheapch.acf.gov/docs/2025/state-plans/ID_Plan_2025.pdf#page=9 - title: Idaho PY25 Benefit Determination Chart - href: https://liheapch.acf.gov/docs/2025/benefits-matricies/ID_BenefitMatrix_2025.pdf#page=1 + href: https://liheapch.acf.gov/docs/2025/benefits-matricies/ID_BenefitMatrix_2025.pdf - title: FY2026 Idaho LIHEAP State Plan, sections 2.5 and 2.6 href: https://liheapch.acf.gov/docs/2026/state-plans/ID_Plan_2026.pdf#page=9 diff --git a/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/target_bonus/amount.yaml b/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/target_bonus/amount.yaml new file mode 100644 index 00000000000..d2ef920d5f0 --- /dev/null +++ b/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/target_bonus/amount.yaml @@ -0,0 +1,13 @@ +description: Idaho adds this target benefit for households with a vulnerable member under the Low Income Home Energy Assistance Program. +values: + 2025-10-01: 25 + +metadata: + unit: currency-USD + period: year + label: Idaho LIHEAP target bonus amount + reference: + - title: Idaho FY2026 LIHEAP State Plan, section 2.4 + href: https://liheapch.acf.gov/docs/2026/state-plans/ID_Plan_2026.pdf#page=9 + - title: Idaho PY26 LIHEAP Benefit Determination Chart PDF, PY23 LIHEAP Benefit Matrix Summary + href: https://liheapch.acf.gov/docs/2026/benefits-matricies/ID_BenefitMatrix_Heating_2026.pdf#page=2 diff --git a/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/target_bonus/child_age_limit.yaml b/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/target_bonus/child_age_limit.yaml new file mode 100644 index 00000000000..c011b400cca --- /dev/null +++ b/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/target_bonus/child_age_limit.yaml @@ -0,0 +1,11 @@ +description: Idaho treats children younger than this age as vulnerable under the Low Income Home Energy Assistance Program. +values: + 2025-10-01: 6 + +metadata: + unit: year + period: year + label: Idaho LIHEAP target bonus child age limit + reference: + - title: Idaho PY26 LIHEAP Benefit Determination Chart PDF, PY23 LIHEAP Benefit Matrix Summary + href: https://liheapch.acf.gov/docs/2026/benefits-matricies/ID_BenefitMatrix_Heating_2026.pdf#page=2 diff --git a/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/target_bonus/elderly_age.yaml b/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/target_bonus/elderly_age.yaml new file mode 100644 index 00000000000..4e4f4503ae8 --- /dev/null +++ b/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/target_bonus/elderly_age.yaml @@ -0,0 +1,11 @@ +description: Idaho treats adults reaching this age before the program year ends as vulnerable under the Low Income Home Energy Assistance Program. +values: + 2025-10-01: 60 + +metadata: + unit: year + period: year + label: Idaho LIHEAP target bonus elderly age + reference: + - title: Idaho PY26 LIHEAP Benefit Determination Chart PDF, PY23 LIHEAP Benefit Matrix Summary + href: https://liheapch.acf.gov/docs/2026/benefits-matricies/ID_BenefitMatrix_Heating_2026.pdf#page=2 diff --git a/policyengine_us/programs.yaml b/policyengine_us/programs.yaml index 5ffcda91c4f..92a45491eec 100644 --- a/policyengine_us/programs.yaml +++ b/policyengine_us/programs.yaml @@ -961,11 +961,12 @@ programs: parameter_prefix: gov.states.tx.tdhca.ceap notes: Models the 150% FPG income limit, the alternative 60% SMI limit from the FY2024 state plan (applied through 2024), benefit amounts, and categorical eligibility through TANF enrollment, SNAP eligibility, and SSI receipt. Not modeled - net rather than gross gambling winnings, the Medicare premium deduction from counted Social Security, and the exclusion of means-tested veterans' pensions from counted income (10 TAC 6.4(c)) - state: ID - status: in_progress + status: partial name: Idaho LIHEAP full_name: Idaho Low Income Home Energy Assistance Program + variable: id_liheap parameter_prefix: gov.states.id.dhw.liheap - notes: FY2026 household size, countable income, income limits, modeled financial eligibility and derived heating area. SNAP during the October-September program year or current SSI receipt bypasses the ordinary income test; annual SSI assumes stable current receipt. Means-tested VA categorical status is unobserved by existing inputs. The electric-benefit parameter table uses Idaho Power & Southern Utilities amounts without distinguishing electric-provider groups. The recovered county map and PY2007 nine-month estimated heating costs are continued by user-approved modeling assumptions; FY2026 cost applicability is unconfirmed. Electric costs use Idaho Power & Southern Utilities and gas costs use one representative Intermountain column, without provider selectors. FY2026 excludes households without a specific heating-cost obligation; the conditional no-obligation rent parameter is $75 in FY2025 and zero from FY2026, following the accepted plans. High energy burden includes exactly 11% under the approved convention. No final eligibility or benefit award; existing inputs do not identify every heating-cost obligation. The PY2008 subsidized low-burden rule remains excluded. Annual flows approximate prior-month income. Earlier backfilled results are unverified historical estimates. + notes: FY2026 regular heating; burden bands use the PY2007 heating-cost table, whose FY2026 currency is unconfirmed, so no year is verified. Crisis, cooling, weatherization and equipment assistance are out of scope. # --- SSA programs --- - id: ssi diff --git a/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/eligibility/id_liheap_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/eligibility/id_liheap_eligible.yaml new file mode 100644 index 00000000000..91b65eafc16 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/eligibility/id_liheap_eligible.yaml @@ -0,0 +1,58 @@ +# Accepted FY2026 plan, sections 2.3 and 2.5 (pages 8-9); FY2025 plan, section 2.5 (page 9). +# https://liheapch.acf.gov/docs/2026/state-plans/ID_Plan_2026.pdf#page=8 +# https://liheapch.acf.gov/docs/2025/state-plans/ID_Plan_2025.pdf#page=9 +# IDAPA 16.03.08.200.07: costs incurred directly or as a designated portion of rent. +# https://adminrules.idaho.gov/rules/current/16/160308.pdf#page=5 + +- name: Case 1, income eligibility and a modeled heating cost are both required. + period: 2026 + # Ada County is Area I. OTHER, NONE and UNSPECIFIED have no chart column. No Idaho + # source names solar or kerosene; solar reads as electric and kerosene as oil. + input: + state_code: [ID, ID, ID, ID, ID, ID, ID, ID, OR] + county: [ADA_COUNTY_ID, ADA_COUNTY_ID, ADA_COUNTY_ID, ADA_COUNTY_ID, ADA_COUNTY_ID, + ADA_COUNTY_ID, ADA_COUNTY_ID, UNKNOWN, BAKER_COUNTY_OR] + heating_type: [NATURAL_GAS, NATURAL_GAS, SOLAR, KEROSENE, OTHER, NONE, UNSPECIFIED, + NATURAL_GAS, NATURAL_GAS] + has_heating_expense: [true, true, true, true, true, true, true, true, true] + id_liheap_income_eligible: [true, false, true, true, true, true, true, true, true] + output: + id_liheap_eligible: [true, false, true, true, false, false, false, false, false] + +- name: Case 2, heat in rent has no specific obligation from FY2026 while subsidized tenants paying directly qualify. + period: 2026 + input: + state_code: [ID, ID, ID] + county: [ADA_COUNTY_ID, ADA_COUNTY_ID, ADA_COUNTY_ID] + heating_type: [NATURAL_GAS, NATURAL_GAS, NATURAL_GAS] + heat_expense_included_in_rent: [true, true, false] + receives_housing_assistance: [false, true, true] + gas_expense: [0, 0, 900] + id_liheap_income_eligible: [true, true, true] + output: + id_liheap_eligible: [false, false, true] + +- name: Case 3, FY2025 paid households with heat in rent, whatever the fuel. + period: 2025 + input: + state_code: [ID, ID] + county: [ADA_COUNTY_ID, ADA_COUNTY_ID] + heating_type: [NATURAL_GAS, OTHER] + heat_expense_included_in_rent: [true, true] + id_liheap_income_eligible: [true, true] + output: + id_liheap_eligible: [true, true] + +- name: Case 4, a direct fuel household needs a heating cost obligation. + period: 2026 + # Plan 2.3: "The household must pay for home heating costs". Free gathered wood and a + # subsidized tenant with no gas bill have none; a wood bill establishes one. + input: + state_code: [ID, ID, ID] + county: [ADA_COUNTY_ID, ADA_COUNTY_ID, ADA_COUNTY_ID] + heating_type: [WOOD, NATURAL_GAS, WOOD] + wood_expense: [0, 0, 300] + receives_housing_assistance: [false, true, false] + id_liheap_income_eligible: [true, true, true] + output: + id_liheap_eligible: [false, false, true] diff --git a/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/eligibility/id_liheap_household_size.yaml b/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/eligibility/id_liheap_household_size.yaml index 98366c4c564..7ea7f75fcfb 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/eligibility/id_liheap_household_size.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/eligibility/id_liheap_household_size.yaml @@ -1,17 +1,17 @@ -# Idaho FY2026 LIHEAP plan, qualified household membership (page9). +# Idaho FY2026 LIHEAP plan, qualified household membership (page 9). # https://liheapch.acf.gov/docs/2026/state-plans/ID_Plan_2026.pdf#page=9 -# IDAPA16.03.08 sections201-202, shared economic household (pages5-6). +# IDAPA 16.03.08 sections 201-202, shared economic household (pages 5-6). # https://adminrules.idaho.gov/rules/current/16/160308.pdf#page=5 - name: Case 1, citizen child counts while nonqualified parent does not. period: 2026 - # REQ002: one qualified child; the adult status cannot erase the child. + # One qualified child; the adult status cannot erase the child. input: people: person1: {age: 35, is_citizen_or_legal_immigrant: false, employment_income: 20_000, ssi: 0} person2: {age: 8, is_citizen_or_legal_immigrant: true, ssi: 0} spm_units: - spm_unit: {members: [person1, person2], heating_type: NATURAL_GAS, gas_expense: 1_000} + spm_unit: {members: [person1, person2], heating_type: NATURAL_GAS} households: household: {members: [person1, person2], state_code: ID} output: @@ -19,13 +19,13 @@ - name: Case 2, all nonqualified members give zero eligible size. period: 2026 - # REQ002: neither member satisfies the citizenship or qualified-status rule. + # Neither member satisfies the citizenship or qualified-status rule. input: people: person1: {age: 35, is_citizen_or_legal_immigrant: false, ssi: 0} person2: {age: 8, is_citizen_or_legal_immigrant: false, ssi: 0} spm_units: - spm_unit: {members: [person1, person2], heating_type: NATURAL_GAS, gas_expense: 1_000} + spm_unit: {members: [person1, person2], heating_type: NATURAL_GAS} households: household: {members: [person1, person2], state_code: ID} output: @@ -33,13 +33,13 @@ - name: Case 3, qualified foster child remains a household member. period: 2026 - # REQ002: no Idaho source excludes a qualified foster member from size. + # No Idaho source excludes a qualified foster member from size. input: people: person1: {age: 35, is_citizen_or_legal_immigrant: true, ssi: 0} person2: {age: 8, is_citizen_or_legal_immigrant: true, ssi: 0, is_in_foster_care: {2026-01: true}} spm_units: - spm_unit: {members: [person1, person2], heating_type: NATURAL_GAS, gas_expense: 1_000} + spm_unit: {members: [person1, person2], heating_type: NATURAL_GAS} households: household: {members: [person1, person2], state_code: ID} output: @@ -47,15 +47,15 @@ - name: Case 4, mixed states keep Idaho size separate. period: 2026 - # REQ002/state scope: qualified Idaho pair counts; Colorado is outside this component. + # The qualified Idaho pair counts; Colorado is outside this component. input: people: person1: {age: 35, is_citizen_or_legal_immigrant: true, ssi: 0} person2: {age: 8, is_citizen_or_legal_immigrant: true, ssi: 0} person3: {age: 40, is_citizen_or_legal_immigrant: true, ssi: 0} spm_units: - spm_unit1: {members: [person1, person2], heating_type: NATURAL_GAS, gas_expense: 1_000} - spm_unit2: {members: [person3], heating_type: NATURAL_GAS, gas_expense: 1_000} + spm_unit1: {members: [person1, person2], heating_type: NATURAL_GAS} + spm_unit2: {members: [person3], heating_type: NATURAL_GAS} households: household1: {members: [person1, person2], state_code: ID} household2: {members: [person3], state_code: CO} diff --git a/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/eligibility/id_liheap_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/eligibility/id_liheap_income_eligible.yaml index b4ada0b06f3..eb309da3bae 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/eligibility/id_liheap_income_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/eligibility/id_liheap_income_eligible.yaml @@ -1,4 +1,4 @@ -# Source-derived financial-component tests; no final eligibility or award claim. +# Source-derived financial eligibility tests. # Accepted FY2026 plan, categorical rules and income thresholds (pages 5, 8). # https://liheapch.acf.gov/docs/2026/state-plans/ID_Plan_2026.pdf#page=5 # Pre-consolidation IDAPA 16.04.14 section 151.01 (physical pages 4-5). @@ -71,8 +71,6 @@ members: - person1 heating_type: NATURAL_GAS - gas_expense: 1200 - pre_subsidy_electricity_expense: 0 id_tafi: 2026-01: 0 2026-02: 0 @@ -107,8 +105,6 @@ members: - person2 heating_type: NATURAL_GAS - gas_expense: 1200 - pre_subsidy_electricity_expense: 0 id_tafi: 2026-01: 0 2026-02: 0 @@ -143,8 +139,6 @@ members: - person3 heating_type: NATURAL_GAS - gas_expense: 1200 - pre_subsidy_electricity_expense: 0 id_tafi: 2026-01: 0 2026-02: 0 @@ -288,8 +282,6 @@ members: - person1 heating_type: NATURAL_GAS - gas_expense: 1200 - pre_subsidy_electricity_expense: 0 id_tafi: 2026-01: 0 2026-02: 0 @@ -324,8 +316,6 @@ members: - person2 heating_type: NATURAL_GAS - gas_expense: 1200 - pre_subsidy_electricity_expense: 0 id_tafi: 2026-01: 0 2026-02: 0 @@ -360,8 +350,6 @@ members: - person3 heating_type: NATURAL_GAS - gas_expense: 1200 - pre_subsidy_electricity_expense: 0 id_tafi: 2026-01: 0 2026-02: 0 @@ -396,8 +384,6 @@ members: - person4 heating_type: NATURAL_GAS - gas_expense: 1200 - pre_subsidy_electricity_expense: 0 id_tafi: 2026-01: 0 2026-02: 0 @@ -562,8 +548,6 @@ members: - person1 heating_type: NATURAL_GAS - gas_expense: 1200 - pre_subsidy_electricity_expense: 0 id_tafi: 2026-01: 0 2026-02: 0 @@ -599,8 +583,6 @@ - person2 - person3 heating_type: NATURAL_GAS - gas_expense: 1200 - pre_subsidy_electricity_expense: 0 id_tafi: 2026-01: 0 2026-02: 0 @@ -636,8 +618,6 @@ - person4 - person5 heating_type: NATURAL_GAS - gas_expense: 1200 - pre_subsidy_electricity_expense: 0 id_tafi: 2026-01: 0 2026-02: 0 @@ -798,8 +778,6 @@ members: - person1 heating_type: NATURAL_GAS - gas_expense: 1200 - pre_subsidy_electricity_expense: 0 id_tafi: 2026-01: 0 2026-02: 0 @@ -834,8 +812,6 @@ members: - person2 heating_type: NATURAL_GAS - gas_expense: 1200 - pre_subsidy_electricity_expense: 0 id_tafi: 2026-01: 0 2026-02: 0 @@ -870,8 +846,6 @@ members: - person3 heating_type: NATURAL_GAS - gas_expense: 1200 - pre_subsidy_electricity_expense: 0 id_tafi: 2026-01: 0 2026-02: 0 @@ -907,8 +881,6 @@ - person4 - person5 heating_type: NATURAL_GAS - gas_expense: 1200 - pre_subsidy_electricity_expense: 0 id_tafi: 2026-01: 0 2026-02: 0 @@ -1021,8 +993,6 @@ members: - person1 heating_type: NATURAL_GAS - gas_expense: 1200 - pre_subsidy_electricity_expense: 0 id_tafi: 2026-01: 100 2026-02: 100 @@ -1057,8 +1027,6 @@ members: - person2 heating_type: NATURAL_GAS - gas_expense: 1200 - pre_subsidy_electricity_expense: 0 id_tafi: 2026-01: 0 2026-02: 0 @@ -1383,8 +1351,6 @@ - person6 - person7 heating_type: NATURAL_GAS - gas_expense: 1200 - pre_subsidy_electricity_expense: 0 id_tafi: 2026-01: 0 2026-02: 0 @@ -1426,8 +1392,6 @@ - person14 - person15 heating_type: NATURAL_GAS - gas_expense: 1200 - pre_subsidy_electricity_expense: 0 id_tafi: 2026-01: 0 2026-02: 0 @@ -1523,8 +1487,6 @@ members: - person1 heating_type: NONE - gas_expense: 0 - pre_subsidy_electricity_expense: 0 id_tafi: 2026-01: 0 2026-02: 0 @@ -1632,8 +1594,6 @@ members: - person1 heating_type: NATURAL_GAS - gas_expense: 1200 - pre_subsidy_electricity_expense: 0 id_tafi: 2026-01: 0 2026-02: 0 @@ -1668,8 +1628,6 @@ members: - person2 heating_type: NATURAL_GAS - gas_expense: 1200 - pre_subsidy_electricity_expense: 0 id_tafi: 2026-01: 0 2026-02: 0 @@ -1704,8 +1662,6 @@ members: - person3 heating_type: NATURAL_GAS - gas_expense: 1200 - pre_subsidy_electricity_expense: 0 id_tafi: 2026-01: 0 2026-02: 0 @@ -1762,3 +1718,45 @@ - 0 - 0 - 0 + +- name: Case 9, reported SSI receipt establishes the categorical route. + # Modeled SSI is zero, but the member reports receiving SSI. Income of 100,000 + # is far above the size-one ceiling and SNAP is zero across the program year, + # so only the SSI route qualifies. + period: 2026 + input: + people: + person1: + age: 70 + is_citizen_or_legal_immigrant: true + employment_income: 100_000 + ssi: 0 + receives_ssi: + 2026-01: true + spm_units: + spm_unit: + members: [person1] + snap: + 2025-09: 0 + 2025-10: 0 + 2025-11: 0 + 2025-12: 0 + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + households: + household: + members: [person1] + state_code: ID + output: + id_liheap_income_eligible: true + diff --git a/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/eligibility/id_liheap_income_limit.yaml b/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/eligibility/id_liheap_income_limit.yaml index b11d90778a6..813820ab539 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/eligibility/id_liheap_income_limit.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/eligibility/id_liheap_income_limit.yaml @@ -1,15 +1,15 @@ -# Idaho FY2026 LIHEAP plan, 60%SMI for sizes1-7 and150%FPG for8+ (page8). +# Idaho FY2026 LIHEAP plan, 60% of SMI for sizes 1-7 and 150% of the guideline for 8 and up (page 8). # https://liheapch.acf.gov/docs/2026/state-plans/ID_Plan_2026.pdf#page=8 -# DHW published monthly limits effective2025-10-01; retrieved2026-10-03. +# DHW published monthly limits effective 2025-10-01; retrieved 2026-10-03. # https://healthandwelfare.idaho.gov/services-programs/financial-assistance/home-heating-and-utility-assistance/apply-heating-assistance - name: Case 1, all published monthly limits and additional person amounts annualize exactly. period: 2026 absolute_error_margin: 0.01 - # REQ005: sizes1-10 use published monthly [2736.25,3578.17,4420.08,5262.08, - # 6104,6945.92,7103.75,6768.75,7456.25,8143.75] times12. - # Size11 = (8143.75 +687.50)*12 =105975; size15 = (8143.75 +5*687.50)*12 =138975. - # Size7 annual85245 exceeds size8 annual81225: the explicit SMI-to-FPG switch is not max(). + # Sizes 1-10 use published monthly [2736.25,3578.17,4420.08,5262.08, + # 6104,6945.92,7103.75,6768.75,7456.25,8143.75] times 12. + # Size 11 = (8,143.75 + 687.50) x 12 = 105,975; size 15 = (8,143.75 + 5 x 687.50) x 12 = 138,975. + # Size 7 annual 85,245 exceeds size 8 annual 81,225: the explicit SMI-to-FPG switch is not max(). input: people: person1: {age: 40, is_citizen_or_legal_immigrant: true} @@ -94,18 +94,18 @@ person80: {age: 6, is_citizen_or_legal_immigrant: true} person81: {age: 5, is_citizen_or_legal_immigrant: true} spm_units: - spm_unit1: {members: [person1], heating_type: NATURAL_GAS, gas_expense: 1_000} - spm_unit2: {members: [person2, person3], heating_type: NATURAL_GAS, gas_expense: 1_000} - spm_unit3: {members: [person4, person5, person6], heating_type: NATURAL_GAS, gas_expense: 1_000} - spm_unit4: {members: [person7, person8, person9, person10], heating_type: NATURAL_GAS, gas_expense: 1_000} - spm_unit5: {members: [person11, person12, person13, person14, person15], heating_type: NATURAL_GAS, gas_expense: 1_000} - spm_unit6: {members: [person16, person17, person18, person19, person20, person21], heating_type: NATURAL_GAS, gas_expense: 1_000} - spm_unit7: {members: [person22, person23, person24, person25, person26, person27, person28], heating_type: NATURAL_GAS, gas_expense: 1_000} - spm_unit8: {members: [person29, person30, person31, person32, person33, person34, person35, person36], heating_type: NATURAL_GAS, gas_expense: 1_000} - spm_unit9: {members: [person37, person38, person39, person40, person41, person42, person43, person44, person45], heating_type: NATURAL_GAS, gas_expense: 1_000} - spm_unit10: {members: [person46, person47, person48, person49, person50, person51, person52, person53, person54, person55], heating_type: NATURAL_GAS, gas_expense: 1_000} - spm_unit11: {members: [person56, person57, person58, person59, person60, person61, person62, person63, person64, person65, person66], heating_type: NATURAL_GAS, gas_expense: 1_000} - spm_unit12: {members: [person67, person68, person69, person70, person71, person72, person73, person74, person75, person76, person77, person78, person79, person80, person81], heating_type: NATURAL_GAS, gas_expense: 1_000} + spm_unit1: {members: [person1], heating_type: NATURAL_GAS} + spm_unit2: {members: [person2, person3], heating_type: NATURAL_GAS} + spm_unit3: {members: [person4, person5, person6], heating_type: NATURAL_GAS} + spm_unit4: {members: [person7, person8, person9, person10], heating_type: NATURAL_GAS} + spm_unit5: {members: [person11, person12, person13, person14, person15], heating_type: NATURAL_GAS} + spm_unit6: {members: [person16, person17, person18, person19, person20, person21], heating_type: NATURAL_GAS} + spm_unit7: {members: [person22, person23, person24, person25, person26, person27, person28], heating_type: NATURAL_GAS} + spm_unit8: {members: [person29, person30, person31, person32, person33, person34, person35, person36], heating_type: NATURAL_GAS} + spm_unit9: {members: [person37, person38, person39, person40, person41, person42, person43, person44, person45], heating_type: NATURAL_GAS} + spm_unit10: {members: [person46, person47, person48, person49, person50, person51, person52, person53, person54, person55], heating_type: NATURAL_GAS} + spm_unit11: {members: [person56, person57, person58, person59, person60, person61, person62, person63, person64, person65, person66], heating_type: NATURAL_GAS} + spm_unit12: {members: [person67, person68, person69, person70, person71, person72, person73, person74, person75, person76, person77, person78, person79, person80, person81], heating_type: NATURAL_GAS} households: household1: {members: [person1], state_code: ID} household2: {members: [person2, person3], state_code: ID} @@ -125,12 +125,12 @@ - name: Case 2, no qualified member has zero income limit. period: 2026 absolute_error_margin: 0.01 - # REQ002/005: no eligible household member means no applicable income ceiling. + # No eligible household member means no applicable income ceiling. input: people: person1: {age: 40, is_citizen_or_legal_immigrant: false} spm_units: - spm_unit: {members: [person1], heating_type: NATURAL_GAS, gas_expense: 1_000} + spm_unit: {members: [person1], heating_type: NATURAL_GAS} households: household: {members: [person1], state_code: ID} output: @@ -139,14 +139,14 @@ - name: Case 3, mixed state vector preserves the Idaho limit and masks another state. period: 2026 absolute_error_margin: 0.01 - # REQ005/state scope: Idaho one-person monthly2736.25*12=32835; California0. + # Idaho one-person monthly 2,736.25 x 12 = 32,835; California 0. input: people: person1: {age: 40, is_citizen_or_legal_immigrant: true} person2: {age: 40, is_citizen_or_legal_immigrant: true} spm_units: - spm_unit1: {members: [person1], heating_type: NATURAL_GAS, gas_expense: 1_000} - spm_unit2: {members: [person2], heating_type: NATURAL_GAS, gas_expense: 1_000} + spm_unit1: {members: [person1], heating_type: NATURAL_GAS} + spm_unit2: {members: [person2], heating_type: NATURAL_GAS} households: household1: {members: [person1], state_code: ID} household2: {members: [person2], state_code: CA} diff --git a/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/id_liheap.yaml b/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/id_liheap.yaml new file mode 100644 index 00000000000..540e2237cc1 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/id_liheap.yaml @@ -0,0 +1,254 @@ +# Expected amounts come from the PY26 Benefit Determination Chart and its summary (pages 1-2). +# https://liheapch.acf.gov/docs/2026/benefits-matricies/ID_BenefitMatrix_Heating_2026.pdf#page=1 +# Burden = estimated annual heating cost / annual income, with the PY2007 costs: +# electricity 1_335, 1_455, 1_605; natural gas 977, 1_100, 1_207; +# oil or propane 1_625, 1_845, 2_145; coal or wood 1_200, 1_600, 1_800 (Areas I, II, III). +# Ada County is Area I, Bannock County Area II, Bear Lake County Area III. +# Low burden is under 6%, medium 6% to under 11%, high 11% or more. +# Income 40_000 is low and 8_000 high for every fuel and area. +# Cases 1 to 8 set has_heating_expense directly; a bill would not change the amount. + +- name: Case 1, electric heat pays the Idaho Power and Southern Utilities column in every cell. + period: 2026 + absolute_error_margin: 0.01 + # Income 16_000 is medium: 8.34%, 9.09%, 10.03%. + input: + state_code: [ID, ID, ID, ID, ID, ID, ID, ID, ID] + county: [ADA_COUNTY_ID, ADA_COUNTY_ID, ADA_COUNTY_ID, + BANNOCK_COUNTY_ID, BANNOCK_COUNTY_ID, BANNOCK_COUNTY_ID, + BEAR_LAKE_COUNTY_ID, BEAR_LAKE_COUNTY_ID, BEAR_LAKE_COUNTY_ID] + heating_type: [ELECTRICITY, ELECTRICITY, ELECTRICITY, + ELECTRICITY, ELECTRICITY, ELECTRICITY, + ELECTRICITY, ELECTRICITY, ELECTRICITY] + id_liheap_countable_income: [40_000, 16_000, 8_000, + 40_000, 16_000, 8_000, + 40_000, 16_000, 8_000] + id_liheap_income_eligible: [true, true, true, true, true, true, true, true, true] + has_heating_expense: [true, true, true, true, true, true, true, true, true] + output: + id_liheap: [328, 342, 355, + 378, 394, 410, + 429, 447, 464] + +- name: Case 2, natural gas pays the Intermountain Gas column in every cell. + period: 2026 + absolute_error_margin: 0.01 + # Income 12_000 is medium: 8.14%, 9.17%, 10.06%. + input: + state_code: [ID, ID, ID, ID, ID, ID, ID, ID, ID] + county: [ADA_COUNTY_ID, ADA_COUNTY_ID, ADA_COUNTY_ID, + BANNOCK_COUNTY_ID, BANNOCK_COUNTY_ID, BANNOCK_COUNTY_ID, + BEAR_LAKE_COUNTY_ID, BEAR_LAKE_COUNTY_ID, BEAR_LAKE_COUNTY_ID] + heating_type: [NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, + NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, + NATURAL_GAS, NATURAL_GAS, NATURAL_GAS] + id_liheap_countable_income: [40_000, 12_000, 8_000, + 40_000, 12_000, 8_000, + 40_000, 12_000, 8_000] + id_liheap_income_eligible: [true, true, true, true, true, true, true, true, true] + has_heating_expense: [true, true, true, true, true, true, true, true, true] + output: + id_liheap: [122, 127, 132, + 141, 147, 152, + 159, 166, 173] + +- name: Case 3, fuel oil and propane share the oil or propane column in every cell. + period: 2026 + absolute_error_margin: 0.01 + # Income 20_000 is medium: 8.13%, 9.23%, 10.73%. + input: + state_code: [ID, ID, ID, ID, ID, ID, ID, ID, ID] + county: [ADA_COUNTY_ID, ADA_COUNTY_ID, ADA_COUNTY_ID, + BANNOCK_COUNTY_ID, BANNOCK_COUNTY_ID, BANNOCK_COUNTY_ID, + BEAR_LAKE_COUNTY_ID, BEAR_LAKE_COUNTY_ID, BEAR_LAKE_COUNTY_ID] + heating_type: [FUEL_OIL, FUEL_OIL, FUEL_OIL, + PROPANE, PROPANE, PROPANE, + FUEL_OIL, FUEL_OIL, FUEL_OIL] + id_liheap_countable_income: [40_000, 20_000, 8_000, + 40_000, 20_000, 8_000, + 40_000, 20_000, 8_000] + id_liheap_income_eligible: [true, true, true, true, true, true, true, true, true] + has_heating_expense: [true, true, true, true, true, true, true, true, true] + output: + id_liheap: [776, 808, 840, + 970, 1_010, 1_050, + 1_164, 1_212, 1_260] + +- name: Case 4, coal and wood share the coal or wood column in every cell. + period: 2026 + absolute_error_margin: 0.01 + # Income 18_000 is medium: 6.67%, 8.89%, 10%. + input: + state_code: [ID, ID, ID, ID, ID, ID, ID, ID, ID] + county: [ADA_COUNTY_ID, ADA_COUNTY_ID, ADA_COUNTY_ID, + BANNOCK_COUNTY_ID, BANNOCK_COUNTY_ID, BANNOCK_COUNTY_ID, + BEAR_LAKE_COUNTY_ID, BEAR_LAKE_COUNTY_ID, BEAR_LAKE_COUNTY_ID] + heating_type: [WOOD, WOOD, WOOD, + COAL, COAL, COAL, + WOOD, WOOD, WOOD] + id_liheap_countable_income: [40_000, 18_000, 8_000, + 40_000, 18_000, 8_000, + 40_000, 18_000, 8_000] + id_liheap_income_eligible: [true, true, true, true, true, true, true, true, true] + has_heating_expense: [true, true, true, true, true, true, true, true, true] + output: + id_liheap: [467, 486, 505, + 544, 567, 590, + 622, 648, 674] + +- name: Case 5, burden bands turn at exactly 6 percent and 11 percent, and zero income is high. + period: 2026 + absolute_error_margin: 0.01 + # Bannock electricity 1_455: 1_455 / 24_250 = 6% is medium; 24_251 is low. + # Bannock gas 1_100: 1_100 / 10_000 = 11% is high; 10_001 is medium; zero income is high. + input: + state_code: [ID, ID, ID, ID, ID] + county: [BANNOCK_COUNTY_ID, BANNOCK_COUNTY_ID, BANNOCK_COUNTY_ID, + BANNOCK_COUNTY_ID, BANNOCK_COUNTY_ID] + heating_type: [ELECTRICITY, ELECTRICITY, NATURAL_GAS, NATURAL_GAS, NATURAL_GAS] + id_liheap_countable_income: [24_250, 24_251, 10_000, 10_001, 0] + id_liheap_income_eligible: [true, true, true, true, true] + has_heating_expense: [true, true, true, true, true] + output: + id_liheap: [394, 378, 152, 147, 152] + +- name: Case 6, a child under six, an adult of 60 and a disabled adult add the target bonus. + period: 2026 + absolute_error_margin: 0.01 + # Ada gas at low burden is 122, and 122 + 25 = 147, the chart's lowest bonus amount. + # The last row is Bear Lake oil at high burden: 1_260 + 25 = 1_285, the chart's highest. + input: + state_code: [ID, ID, ID, ID, ID, ID] + county: [ADA_COUNTY_ID, ADA_COUNTY_ID, ADA_COUNTY_ID, ADA_COUNTY_ID, ADA_COUNTY_ID, + BEAR_LAKE_COUNTY_ID] + heating_type: [NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, FUEL_OIL] + age: [5, 6, 59, 60, 40, 60] + is_disabled: [false, false, false, false, true, false] + id_liheap_countable_income: [40_000, 40_000, 40_000, 40_000, 40_000, 8_000] + id_liheap_income_eligible: [true, true, true, true, true, true] + has_heating_expense: [true, true, true, true, true, true] + output: + id_liheap: [147, 122, 122, 147, 147, 1_285] + +- name: Case 7, several vulnerable members earn one target bonus. + period: 2026 + absolute_error_margin: 0.01 + # Ada gas at low burden: 122 + 25 = 147. + input: + people: + person1: + age: 65 + person2: + age: 3 + spm_units: + spm_unit: + members: [person1, person2] + heating_type: NATURAL_GAS + id_liheap_countable_income: 40_000 + id_liheap_income_eligible: true + has_heating_expense: true + households: + household: + members: [person1, person2] + state_code: ID + county: ADA_COUNTY_ID + output: + id_liheap: 147 + +- name: Case 8, a vulnerable member who is not a qualified member earns no target bonus. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + person2: + age: 65 + is_citizen_or_legal_immigrant: false + spm_units: + spm_unit: + members: [person1, person2] + heating_type: NATURAL_GAS + id_liheap_countable_income: 40_000 + id_liheap_income_eligible: true + has_heating_expense: true + households: + household: + members: [person1, person2] + state_code: ID + county: ADA_COUNTY_ID + output: + id_liheap: 122 + +- name: Case 9, heat in rent paid 75 in FY2025 with the target bonus on top. + period: 2025 + absolute_error_margin: 0.01 + # PY25 chart Rent column and its 75 and 100 low amounts. + input: + state_code: [ID, ID] + county: [ADA_COUNTY_ID, ADA_COUNTY_ID] + heating_type: [NATURAL_GAS, NATURAL_GAS] + heat_expense_included_in_rent: [true, true] + age: [40, 60] + id_liheap_income_eligible: [true, true] + output: + id_liheap: [75, 100] + +- name: Case 10, ineligible households, fuels with no chart column and heat in rent from FY2026 receive nothing. + period: 2026 + absolute_error_margin: 0.01 + input: + state_code: [ID, ID, ID] + county: [ADA_COUNTY_ID, ADA_COUNTY_ID, ADA_COUNTY_ID] + heating_type: [NATURAL_GAS, OTHER, NATURAL_GAS] + heat_expense_included_in_rent: [false, false, true] + has_heating_expense: [true, true, false] + age: [60, 60, 60] + id_liheap_income_eligible: [false, true, true] + output: + id_liheap: [0, 0, 0] + +- name: Case 11, a parent and child in Bannock County at the medium burden. + period: 2026 + absolute_error_margin: 0.01 + # Wages 18_000 and no other income; 1_100 / 18_000 = 6.11% is medium; the child is eight. + # The 900 gas bill shows the obligation; the PY2007 table sets the burden. + input: + people: + person1: + age: 35 + employment_income_before_lsr: 18_000 + person2: + age: 8 + spm_units: + spm_unit: + members: [person1, person2] + heating_type: NATURAL_GAS + gas_expense: 900 + takes_up_tanf_if_eligible: false + households: + household: + members: [person1, person2] + state_code: ID + county: BANNOCK_COUNTY_ID + output: + id_liheap_countable_income: 18_000 + id_liheap_estimated_heating_cost: 1_100 + id_liheap_eligible: true + id_liheap: 147 + +- name: Case 12, solar with an electric bill pays the electric column and kerosene with a bill the oil column. + period: 2026 + absolute_error_margin: 0.01 + # Ada County. Solar: 1_335 / 16_000 = 8.34% is medium, 342. + # Kerosene: 1_625 / 20_000 = 8.13% is medium, 808. + input: + state_code: [ID, ID] + county: [ADA_COUNTY_ID, ADA_COUNTY_ID] + heating_type: [SOLAR, KEROSENE] + pre_subsidy_electricity_expense: [1_000, 0] + fuel_oil_expense: [0, 800] + id_liheap_countable_income: [16_000, 20_000] + id_liheap_income_eligible: [true, true] + output: + id_liheap: [342, 808] diff --git a/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/id_liheap_estimated_heating_cost.yaml b/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/id_liheap_estimated_heating_cost.yaml index a480cc62b24..a71cdf164e0 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/id_liheap_estimated_heating_cost.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/id_liheap_estimated_heating_cost.yaml @@ -1,6 +1,6 @@ # Historical Idaho LIHEAP Intake Manual, Appendix C, physical page 1. # https://web.archive.org/web/20170127123014id_/http://www.healthandwelfare.idaho.gov/Portals/_Rainbow/Manuals/LIHEAP/Appendices/c_htgcost_matrix_PY07.pdf#page=1 -# PY2007 estimated nine-month costs are used provisionally by user approval; +# PY2007 estimated nine-month costs are used as a modeling assumption; # their current FY2026 applicability is unconfirmed. No inflation or 12/9 scaling. # Electricity uses Idaho Power & Southern Utilities. Natural gas uses the # Intermountain column as a modeling simplification, without a provider input. @@ -36,13 +36,11 @@ absolute_error_margin: 0.01 # Zero denotes an unmodeled cost, not a legal eligibility determination. input: - state_code: [ID, ID, ID, ID, ID, ID, ID] - county: [UNKNOWN, BAKER_COUNTY_OR, ADA_COUNTY_ID, ADA_COUNTY_ID, - ADA_COUNTY_ID, ADA_COUNTY_ID, ADA_COUNTY_ID] - heating_type: [ELECTRICITY, ELECTRICITY, UNSPECIFIED, NONE, - OTHER, SOLAR, KEROSENE] + state_code: [ID, ID, ID, ID, ID] + county: [UNKNOWN, BAKER_COUNTY_OR, ADA_COUNTY_ID, ADA_COUNTY_ID, ADA_COUNTY_ID] + heating_type: [ELECTRICITY, ELECTRICITY, UNSPECIFIED, NONE, OTHER] output: - id_liheap_estimated_heating_cost: [0, 0, 0, 0, 0, 0, 0] + id_liheap_estimated_heating_cost: [0, 0, 0, 0, 0] - name: Case 3, omitted county uses the shared Ada fallback and its electric cost. period: 2026 @@ -64,3 +62,13 @@ heating_type: [NATURAL_GAS, NATURAL_GAS, COAL, ELECTRICITY] output: id_liheap_estimated_heating_cost: [1_207, 0, 1_200, 0] + +- name: Case 5, solar uses the electric cost and kerosene the oil cost. + period: 2026 + absolute_error_margin: 0.01 + input: + state_code: [ID, ID] + county: [ADA_COUNTY_ID, ADA_COUNTY_ID] + heating_type: [SOLAR, KEROSENE] + output: + id_liheap_estimated_heating_cost: [1_335, 1_625] diff --git a/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/id_liheap_heating_area.yaml b/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/id_liheap_heating_area.yaml index 8b9b307d169..504edb4660b 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/id_liheap_heating_area.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/id_liheap_heating_area.yaml @@ -1,6 +1,6 @@ # Historical Idaho LIHEAP Intake Manual, Appendix A, physical page 2. # https://web.archive.org/web/20170124204651id_/http://healthandwelfare.idaho.gov/portals/_rainbow/manuals/liheap/Appendices/a_codes_all.pdf#page=2 -# The user approved continuing this undated map in the current draft. +# This undated map continues as a modeling assumption. # Expected areas follow the complete left table in county-code order 1-44. # The right table duplicates Power and omits Elmore; Elmore is in Area I. diff --git a/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/income/id_liheap_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/income/id_liheap_countable_income.yaml index 1c7610ddcf3..1cd1f762803 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/income/id_liheap_countable_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/income/id_liheap_countable_income.yaml @@ -1,19 +1,19 @@ -# Idaho FY2026 LIHEAP plan, gross income checkboxes and other-income text (pages5-7). +# Idaho FY2026 LIHEAP plan, gross income checkboxes and other-income text (pages 5-7). # https://liheapch.acf.gov/docs/2026/state-plans/ID_Plan_2026.pdf#page=5 -# IDAPA16.03.08 section202 includes income of nonqualified household members (page6). +# IDAPA 16.03.08 section 202 includes income of nonqualified household members (page 6). # https://adminrules.idaho.gov/rules/current/16/160308.pdf#page=6 - name: Case 1, minor earnings are excluded but child SSI is included. period: 2026 absolute_error_margin: 0.01 - # REQ003-004: adult12000 + childSSI(100/month*12)=13200; child wages, support, VA and GA excluded. - # SSI input1200 is the annual amount for a MONTH variable in a YEAR test. + # Adult 12,000 + child SSI (100 a month x 12) = 13,200; child wages, support, VA and GA are excluded. + # The SSI input of 1,200 is the annual amount for a MONTH variable in a YEAR test. input: people: person1: {age: 35, is_citizen_or_legal_immigrant: true, ssi: 0, employment_income: 12_000} person2: {age: 17, is_citizen_or_legal_immigrant: true, employment_income: 6_000, ssi: 1_200, child_support_received: 6_000, veterans_benefits: 3_000, general_assistance: 900} spm_units: - spm_unit: {members: [person1, person2], heating_type: NATURAL_GAS, gas_expense: 1_000, id_tafi: 0} + spm_unit: {members: [person1, person2], heating_type: NATURAL_GAS, id_tafi: 0} households: household: {members: [person1, person2], state_code: ID} output: @@ -22,13 +22,13 @@ - name: Case 2, earnings count at the eighteenth birthday. period: 2026 absolute_error_margin: 0.01 - # REQ003: child is now18, so both12000 adult wages and6000 earnings count. + # The child is now 18, so both the 12,000 of adult wages and the 6,000 of earnings count. input: people: person1: {age: 35, is_citizen_or_legal_immigrant: true, ssi: 0, employment_income: 12_000} person2: {age: 18, is_citizen_or_legal_immigrant: true, ssi: 0, employment_income: 6_000} spm_units: - spm_unit: {members: [person1, person2], heating_type: NATURAL_GAS, gas_expense: 1_000, id_tafi: 0} + spm_unit: {members: [person1, person2], heating_type: NATURAL_GAS, id_tafi: 0} households: household: {members: [person1, person2], state_code: ID} output: @@ -37,13 +37,13 @@ - name: Case 3, nonqualified parent income still counts for citizen child. period: 2026 absolute_error_margin: 0.01 - # REQ002-004: parent is excluded from eligible size but their20000 wages remain countable. + # The parent is excluded from eligible size but their 20,000 of wages remain countable. input: people: person1: {age: 35, is_citizen_or_legal_immigrant: false, employment_income: 20_000, ssi: 0} person2: {age: 8, is_citizen_or_legal_immigrant: true, ssi: 0} spm_units: - spm_unit: {members: [person1, person2], heating_type: NATURAL_GAS, gas_expense: 1_000, id_tafi: 0} + spm_unit: {members: [person1, person2], heating_type: NATURAL_GAS, id_tafi: 0} households: household: {members: [person1, person2], state_code: ID} output: @@ -52,16 +52,16 @@ - name: Case 4, all represented unearned sources count without pension double counting. period: 2026 absolute_error_margin: 0.01 - # REQ004: SSA12000 + SSI1200 + pension(1000+2000+300+400)=3700 + survivor500 - # + unemployment2400 + strike300 + rent600 + farmrent700 + alimony400 - # + interest200 + dividends250 + estate800 + disability900 + workerscomp1000 =24950. + # Social Security 12,000 + SSI 1,200 + pension (1,000 + 2,000 + 300 + 400) 3,700 + survivor 500 + # + unemployment 2,400 + strike 300 + rent 600 + farm rent 700 + alimony 400 + # + interest 200 + dividends 250 + estate 800 + disability 900 + workers' compensation 1,000 = 24,950. # Pension and SSA subcomponents each enter their aggregates exactly once. input: people: person1: {age: 40, is_citizen_or_legal_immigrant: true, ssi: 0, social_security_disability: 12_000, taxable_public_pension_income: 1_000, taxable_private_pension_income: 2_000, tax_exempt_public_pension_income: 300, tax_exempt_private_pension_income: 400, survivor_benefits: 500, unemployment_compensation: 2_400, strike_benefits: 300, rental_income: 600, farm_rent_income: 700, alimony_income: 400, interest_income: 200, ordinary_dividend_income: 250, estate_income: 800, disability_benefits: 900, workers_compensation: 1_000} person2: {age: 8, is_citizen_or_legal_immigrant: true, ssi: 1_200} spm_units: - spm_unit: {members: [person1, person2], heating_type: NATURAL_GAS, gas_expense: 1_000, id_tafi: 0} + spm_unit: {members: [person1, person2], heating_type: NATURAL_GAS, id_tafi: 0} households: household: {members: [person1, person2], state_code: ID} output: @@ -70,12 +70,12 @@ - name: Case 5, all supported earned business streams count. period: 2026 absolute_error_margin: 0.01 - # REQ003: gross wages10000 + net business streams2000+3000+4000+5000=24000. + # Gross wages 10,000 + net business streams 2,000 + 3,000 + 4,000 + 5,000 = 24,000. input: people: person1: {age: 40, is_citizen_or_legal_immigrant: true, ssi: 0, employment_income: 10_000, self_employment_income: 2_000, sstb_self_employment_income: 3_000, farm_operations_income: 4_000, partnership_s_corp_income: 5_000} spm_units: - spm_unit: {members: [person1], heating_type: NATURAL_GAS, gas_expense: 1_000, id_tafi: 0} + spm_unit: {members: [person1], heating_type: NATURAL_GAS, id_tafi: 0} households: household: {members: [person1], state_code: ID} output: @@ -84,12 +84,12 @@ - name: Case 6, negative business sources do not offset positive earnings. period: 2026 absolute_error_margin: 0.01 - # REQ003 documented net-business approximation:10000 +max(-9000,0)+2000+max(-7000,0)+3000=15000. + # Net-business approximation: 10,000 + max(-9,000, 0) + 2,000 + max(-7,000, 0) + 3,000 = 15,000. input: people: person1: {age: 40, is_citizen_or_legal_immigrant: true, ssi: 0, employment_income: 10_000, self_employment_income: -9_000, sstb_self_employment_income: 2_000, farm_operations_income: -7_000, partnership_s_corp_income: 3_000} spm_units: - spm_unit: {members: [person1], heating_type: NATURAL_GAS, gas_expense: 1_000, id_tafi: 0} + spm_unit: {members: [person1], heating_type: NATURAL_GAS, id_tafi: 0} households: household: {members: [person1], state_code: ID} output: @@ -98,14 +98,14 @@ - name: Case 7, monthly SSI and TAFI aggregate once over the year. period: 2026 absolute_error_margin: 0.01 - # REQ004 period coverage: childSSI100+200=300; SPM TAFI300+200+100=600; total900. - # All other months are explicitly0, and TAFI must not be multiplied by household size. + # Child SSI 100 + 200 = 300; SPM TAFI 300 + 200 + 100 = 600; total 900. + # All other months are explicitly 0, and TAFI must not be multiplied by household size. input: people: person1: {age: 35, is_citizen_or_legal_immigrant: true, ssi: {2026-01: 0, 2026-02: 0, 2026-03: 0, 2026-04: 0, 2026-05: 0, 2026-06: 0, 2026-07: 0, 2026-08: 0, 2026-09: 0, 2026-10: 0, 2026-11: 0, 2026-12: 0}} person2: {age: 8, is_citizen_or_legal_immigrant: true, ssi: {2026-01: 100, 2026-02: 200, 2026-03: 0, 2026-04: 0, 2026-05: 0, 2026-06: 0, 2026-07: 0, 2026-08: 0, 2026-09: 0, 2026-10: 0, 2026-11: 0, 2026-12: 0}} spm_units: - spm_unit: {members: [person1, person2], heating_type: NATURAL_GAS, gas_expense: 1_000, id_tafi: {2026-01: 300, 2026-02: 200, 2026-03: 100, 2026-04: 0, 2026-05: 0, 2026-06: 0, 2026-07: 0, 2026-08: 0, 2026-09: 0, 2026-10: 0, 2026-11: 0, 2026-12: 0}} + spm_unit: {members: [person1, person2], heating_type: NATURAL_GAS, id_tafi: {2026-01: 300, 2026-02: 200, 2026-03: 100, 2026-04: 0, 2026-05: 0, 2026-06: 0, 2026-07: 0, 2026-08: 0, 2026-09: 0, 2026-10: 0, 2026-11: 0, 2026-12: 0}} households: household: {members: [person1, person2], state_code: ID} output: @@ -114,13 +114,13 @@ - name: Case 8, child support veterans benefits and general assistance are excluded. period: 2026 absolute_error_margin: 0.01 - # REQ004 unchecked source boxes: childsupport9000, VA5000 and GA2000 do not count. + # Unchecked source boxes: child support 9,000, VA 5,000 and GA 2,000 do not count. input: people: person1: {age: 35, is_citizen_or_legal_immigrant: true, ssi: 0, child_support_received: 9_000, veterans_benefits: 5_000, general_assistance: 2_000} person2: {age: 8, is_citizen_or_legal_immigrant: true, ssi: 0} spm_units: - spm_unit: {members: [person1, person2], heating_type: NATURAL_GAS, gas_expense: 1_000, id_tafi: 0} + spm_unit: {members: [person1, person2], heating_type: NATURAL_GAS, id_tafi: 0} households: household: {members: [person1, person2], state_code: ID} output: @@ -129,8 +129,8 @@ - name: Case 9, mixed states and unequal memberships retain separate income totals. period: 2026 absolute_error_margin: 0.01 - # REQ002-004/state scope: first Idaho unit6000+6000=12000, Colorado0, - # second Idaho unit adult1800+childSSI1800=3600; minor wages10000 excluded. + # First Idaho unit 6,000 + 6,000 = 12,000; Colorado 0; + # second Idaho unit adult 1,800 + child SSI 1,800 = 3,600; minor wages of 10,000 are excluded. input: people: person1: {age: 35, is_citizen_or_legal_immigrant: true, ssi: 0, employment_income: 6_000} @@ -139,9 +139,9 @@ person4: {age: 35, is_citizen_or_legal_immigrant: true, ssi: 0, employment_income: 1_800} person5: {age: 12, is_citizen_or_legal_immigrant: true, employment_income: 10_000, ssi: 1_800} spm_units: - spm_unit1: {members: [person1, person2], heating_type: NATURAL_GAS, gas_expense: 1_000, id_tafi: 0} - spm_unit2: {members: [person3], heating_type: NATURAL_GAS, gas_expense: 1_000, id_tafi: 0} - spm_unit3: {members: [person4, person5], heating_type: NATURAL_GAS, gas_expense: 1_000, id_tafi: 0} + spm_unit1: {members: [person1, person2], heating_type: NATURAL_GAS, id_tafi: 0} + spm_unit2: {members: [person3], heating_type: NATURAL_GAS, id_tafi: 0} + spm_unit3: {members: [person4, person5], heating_type: NATURAL_GAS, id_tafi: 0} households: household1: {members: [person1, person2], state_code: ID} household2: {members: [person3], state_code: CO} @@ -151,7 +151,7 @@ # Ongoing retirement receipts: pension 1,000 + taxable IRA 12,000 + exempt IRA 3,000. # Count the two aggregates once; one-time lump sums are not represented here. -- name: Recurring taxable and exempt retirement distributions count beside pensions. +- name: Case 10, recurring taxable and exempt retirement distributions count beside pensions. period: 2026 absolute_error_margin: 0.01 input: @@ -167,7 +167,6 @@ spm_unit: members: [person] heating_type: NATURAL_GAS - gas_expense: 1_000 id_tafi: 0 households: household: @@ -176,13 +175,13 @@ output: id_liheap_countable_income: 16_000 -# FY2026 one-person limit32_835. GrossSSA34_000 minus actualPartB2_400=31_600. -# Military40_000 and pension34_000 exceed the limit. Rental losses are not deductions. -# UI36_000 fails; reportedUI gives31_200; a negative receipt leaves30_000. -# TANF receipt controls use the two-person limit42_938.04, with no TANF categorical bypass. +# FY2026 one-person limit 32,835. Gross Social Security 34,000 minus actual Part B 2,400 = 31,600. +# Military 40,000 and pension 34,000 exceed the limit. Rental losses are not deductions. +# UI 36,000 fails; reported UI gives 31,200; a negative receipt leaves 30,000. +# TANF receipt controls use the two-person limit 42,938.04, with no TANF categorical bypass. - name: Case 11, military retirement net Social Security and rental loss affect financial eligibility. - period: 2_026 + period: 2026 absolute_error_margin: 0.01 input: people: @@ -212,29 +211,26 @@ members: - person1 heating_type: NATURAL_GAS - gas_expense: 1_200 id_tafi: 0 snap: - 2_025: 0 - 2_026: 0 + 2025: 0 + 2026: 0 spm_unit2: members: - person2 heating_type: NATURAL_GAS - gas_expense: 1_200 id_tafi: 0 snap: - 2_025: 0 - 2_026: 0 + 2025: 0 + 2026: 0 spm_unit3: members: - person3 heating_type: NATURAL_GAS - gas_expense: 1_200 id_tafi: 0 snap: - 2_025: 0 - 2_026: 0 + 2025: 0 + 2026: 0 households: household1: members: @@ -262,7 +258,7 @@ - true - false - name: Case 12, excess Medicare premiums cannot reduce another income source. - period: 2_026 + period: 2026 absolute_error_margin: 0.01 input: people: @@ -278,11 +274,10 @@ members: - person1 heating_type: NATURAL_GAS - gas_expense: 1_200 id_tafi: 0 snap: - 2_025: 0 - 2_026: 0 + 2025: 0 + 2026: 0 households: household1: members: @@ -292,7 +287,7 @@ id_liheap_countable_income: 34_000 id_liheap_income_eligible: false - name: Case 13, UI uses the receipt helper and cannot offset positive wages. - period: 2_026 + period: 2026 absolute_error_margin: 0.01 input: people: @@ -328,29 +323,26 @@ members: - person1 heating_type: NATURAL_GAS - gas_expense: 1_200 id_tafi: 0 snap: - 2_025: 0 - 2_026: 0 + 2025: 0 + 2026: 0 spm_unit2: members: - person2 heating_type: NATURAL_GAS - gas_expense: 1_200 id_tafi: 0 snap: - 2_025: 0 - 2_026: 0 + 2025: 0 + 2026: 0 spm_unit3: members: - person3 heating_type: NATURAL_GAS - gas_expense: 1_200 id_tafi: 0 snap: - 2_025: 0 - 2_026: 0 + 2025: 0 + 2026: 0 households: household1: members: @@ -378,7 +370,7 @@ - true - true - name: Case 14, received TANF counts once without creating a categorical route. - period: 2_026 + period: 2026 absolute_error_margin: 0.01 input: people: @@ -414,22 +406,20 @@ - person1 - person2 heating_type: NATURAL_GAS - gas_expense: 1_200 id_tafi: 6_000 snap: - 2_025: 0 - 2_026: 0 + 2025: 0 + 2026: 0 takes_up_tanf_if_eligible: true spm_unit2: members: - person3 - person4 heating_type: NATURAL_GAS - gas_expense: 1_200 id_tafi: 6_000 snap: - 2_025: 0 - 2_026: 0 + 2025: 0 + 2026: 0 takes_up_tanf_if_eligible: false households: household1: @@ -452,3 +442,55 @@ id_liheap_income_eligible: - false - true + +# Plan item 1.9 counts retirement and pension benefits: railroad retirement 6,000. +- name: Case 15, railroad retirement counts as a retirement benefit. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 60 + is_citizen_or_legal_immigrant: true + ssi: 0 + social_security: 0 + medicare_part_b_premium: 0 + railroad_benefits: 6_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + id_tafi: 0 + households: + household: + members: [person1] + state_code: ID + output: + id_liheap_countable_income: 6_000 + +# Plan 1.9's Other line and IDAPA 16.04.14.151.02.f count gifts and lottery winnings +# over $30. The $30 test has no input, so annual amounts count in full: +# wages 25,000 + winnings 1,000 + gifts 500. +- name: Case 16, gifts and lottery winnings count. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + is_citizen_or_legal_immigrant: true + ssi: 0 + employment_income: 25_000 + gambling_winnings: 1_000 + financial_assistance: 500 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + id_tafi: 0 + households: + household: + members: [person1] + state_code: ID + output: + id_liheap_countable_income: 26_500 diff --git a/policyengine_us/variables/gov/states/id/dhw/liheap/eligibility/id_liheap_eligible.py b/policyengine_us/variables/gov/states/id/dhw/liheap/eligibility/id_liheap_eligible.py new file mode 100644 index 00000000000..d98009931b2 --- /dev/null +++ b/policyengine_us/variables/gov/states/id/dhw/liheap/eligibility/id_liheap_eligible.py @@ -0,0 +1,31 @@ +from policyengine_us.model_api import * + + +class id_liheap_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Eligible for Idaho LIHEAP regular heating assistance" + definition_period = YEAR + defined_for = StateCode.ID + reference = ( + # PDF pages 8-9 + "https://liheapch.acf.gov/docs/2026/state-plans/ID_Plan_2026.pdf#page=8", + "https://adminrules.idaho.gov/rules/current/16/160308.pdf#page=5", + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.id.dhw.liheap.payment + income_eligible = spm_unit("id_liheap_income_eligible", period) + cost = spm_unit("id_liheap_estimated_heating_cost", period) + heat_in_rent = spm_unit("heat_expense_included_in_rent", period) + # Plan 2.3 requires the household to pay for heat. has_heating_expense + # reads the primary fuel's bill, or can be set directly; the bill does + # not set the amount. + pays_for_heat = spm_unit("has_heating_expense", period) + # Heat in rent stands for no specific heating-cost obligation; a + # designated heat charge within the rent has no input. That base is + # zero from FY2026, when plan 2.5 makes these households ineligible. + # Other subsidized tenants paying for heat follow the general chart. + return income_eligible & where( + heat_in_rent, p.rent > 0, (cost > 0) & pays_for_heat + ) diff --git a/policyengine_us/variables/gov/states/id/dhw/liheap/eligibility/id_liheap_income_eligible.py b/policyengine_us/variables/gov/states/id/dhw/liheap/eligibility/id_liheap_income_eligible.py index 2a017095514..10ac696b5c2 100644 --- a/policyengine_us/variables/gov/states/id/dhw/liheap/eligibility/id_liheap_income_eligible.py +++ b/policyengine_us/variables/gov/states/id/dhw/liheap/eligibility/id_liheap_income_eligible.py @@ -23,7 +23,11 @@ def formula(spm_unit, period, parameters): receives_snap = spm_unit("snap", snap_period, options=[ADD]) > 0 # Annual SSI is a stable-current-receipt proxy because the application # month is not an input. Any member may establish categorical eligibility. - receives_ssi = spm_unit.any(spm_unit.members("ssi", period, options=[ADD]) > 0) + person = spm_unit.members + receives_ssi = spm_unit.any( + (person("ssi", period, options=[ADD]) > 0) + | (add(person, period, ["receives_ssi"]) > 0) + ) # Means-tested VA receipt also qualifies, but veterans_benefits does not # identify that category. This unmodeled route is not a legal exclusion. return (size > 0) & ((income <= limit) | receives_snap | receives_ssi) diff --git a/policyengine_us/variables/gov/states/id/dhw/liheap/eligibility/id_liheap_income_limit.py b/policyengine_us/variables/gov/states/id/dhw/liheap/eligibility/id_liheap_income_limit.py index ef2f21f7866..81e62903d6b 100644 --- a/policyengine_us/variables/gov/states/id/dhw/liheap/eligibility/id_liheap_income_limit.py +++ b/policyengine_us/variables/gov/states/id/dhw/liheap/eligibility/id_liheap_income_limit.py @@ -1,5 +1,5 @@ from policyengine_us.model_api import * -from policyengine_us.variables.gov.hhs.hhs_smi import smi +from policyengine_us.variables.gov.hhs.hhs_smi import liheap_smi_limit from policyengine_us.variables.gov.hhs.tax_unit_fpg import fpg @@ -21,12 +21,11 @@ def formula(spm_unit, period, parameters): group = spm_unit.household("state_group_str", period) p = parameters(period) eligibility = p.gov.states.id.dhw.liheap.eligibility - base = p.gov.hhs.smi.amount[state] - factor = smi(size, state, period, parameters) / base - # Flooring the four-person base before applying the size factor matches - # all seven published FY2026 SMI limits. The source specifies the dollar - # amounts, not this inferred rounding order. Preserve monthly cents. - annual_smi = np.floor(np.floor(base * eligibility.smi_rate) * factor) + # The shared helper's flooring order matches all seven published FY2026 + # SMI limits. Preserve monthly cents. + annual_smi = liheap_smi_limit( + size, state, eligibility.smi_rate, period, parameters + ) monthly_smi = np.round(annual_smi / MONTHS_IN_YEAR, 2) annual_fpg = eligibility.fpg_rate * fpg( max_(size, 1), diff --git a/policyengine_us/variables/gov/states/id/dhw/liheap/id_liheap.py b/policyengine_us/variables/gov/states/id/dhw/liheap/id_liheap.py new file mode 100644 index 00000000000..06e83a89f2c --- /dev/null +++ b/policyengine_us/variables/gov/states/id/dhw/liheap/id_liheap.py @@ -0,0 +1,64 @@ +from policyengine_us.model_api import * + + +class id_liheap(Variable): + value_type = float + entity = SPMUnit + label = "Idaho LIHEAP regular heating assistance" + unit = USD + definition_period = YEAR + defined_for = "id_liheap_eligible" + reference = ( + # PDF pages 1-2 + "https://liheapch.acf.gov/docs/2026/benefits-matricies/ID_BenefitMatrix_Heating_2026.pdf#page=1", + "https://liheapch.acf.gov/docs/2026/state-plans/ID_Plan_2026.pdf#page=9", + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.id.dhw.liheap.payment + cost = spm_unit("id_liheap_estimated_heating_cost", period) + income = spm_unit("id_liheap_countable_income", period) + # Zero income has the highest burden. + burden_group = select( + [ + cost >= income * p.energy_burden.high_rate, + cost >= income * p.energy_burden.medium_rate, + ], + [3, 2], + default=1, + ) + # Safe lookup; eligibility already requires a known area. + area = clip(spm_unit("id_liheap_heating_area", period), 1, 3) + heating = spm_unit("heating_type", period) + types = heating.possible_values + chart_amount = select( + [ + (heating == types.ELECTRICITY) | (heating == types.SOLAR), + heating == types.NATURAL_GAS, + (heating == types.FUEL_OIL) + | (heating == types.KEROSENE) + | (heating == types.PROPANE), + (heating == types.COAL) | (heating == types.WOOD), + ], + [ + p.matrix.electricity[area][burden_group], + p.matrix.natural_gas[area][burden_group], + p.matrix.oil_or_propane[area][burden_group], + p.matrix.coal_or_wood[area][burden_group], + ], + default=0, + ) + heat_in_rent = spm_unit("heat_expense_included_in_rent", period) + person = spm_unit.members + # Annual age stands in for age by the end of the program year. + age = person("age", period) + vulnerable = ( + (age < p.target_bonus.child_age_limit) + | (age >= p.target_bonus.elderly_age) + | person("is_disabled", period) + ) + qualified = person("is_citizen_or_legal_immigrant", period) + target_bonus = spm_unit.any(vulnerable & qualified) * p.target_bonus.amount + # The chart's $122 minimum and $1,285 maximum are its own lowest and + # highest amounts, so no separate limits apply. + return where(heat_in_rent, p.rent, chart_amount) + target_bonus diff --git a/policyengine_us/variables/gov/states/id/dhw/liheap/id_liheap_estimated_heating_cost.py b/policyengine_us/variables/gov/states/id/dhw/liheap/id_liheap_estimated_heating_cost.py index 3fd5df576ff..5e3443a285a 100644 --- a/policyengine_us/variables/gov/states/id/dhw/liheap/id_liheap_estimated_heating_cost.py +++ b/policyengine_us/variables/gov/states/id/dhw/liheap/id_liheap_estimated_heating_cost.py @@ -17,12 +17,16 @@ def formula(spm_unit, period, parameters): p = parameters(period).gov.states.id.dhw.liheap.payment.estimated_heating_costs # PY2007 nine-month cost proxy; FY2026 applicability is unconfirmed. # Safe lookup leaves unknown areas unassigned after fuel selection. + # No Idaho source names solar or kerosene. As in heating_expense, solar + # reads as electric and kerosene as the chart's oil. lookup_area = clip(area, 1, 3) cost = select( [ - heating == types.ELECTRICITY, + (heating == types.ELECTRICITY) | (heating == types.SOLAR), heating == types.NATURAL_GAS, - (heating == types.FUEL_OIL) | (heating == types.PROPANE), + (heating == types.FUEL_OIL) + | (heating == types.KEROSENE) + | (heating == types.PROPANE), (heating == types.COAL) | (heating == types.WOOD), ], [ diff --git a/policyengine_us/variables/gov/states/id/dhw/liheap/id_liheap_heating_area.py b/policyengine_us/variables/gov/states/id/dhw/liheap/id_liheap_heating_area.py index 08e7d3ce41d..3edd6ee3225 100644 --- a/policyengine_us/variables/gov/states/id/dhw/liheap/id_liheap_heating_area.py +++ b/policyengine_us/variables/gov/states/id/dhw/liheap/id_liheap_heating_area.py @@ -13,7 +13,7 @@ def formula(spm_unit, period, parameters): county = spm_unit.household("county_str", period) p = parameters(period).gov.states.id.dhw.liheap.payment.heating_areas # Area codes match the benefit matrix; zero leaves unmatched counties - # unassigned. The recovered map's continuation is user-approved. + # unassigned. The recovered map continues as a modeling assumption. return select( [ np.isin(county, p.area_1), diff --git a/policyengine_us/variables/gov/states/id/dhw/liheap/income/id_liheap_countable_income.py b/policyengine_us/variables/gov/states/id/dhw/liheap/income/id_liheap_countable_income.py index 99ee583a00f..8d644cfe492 100644 --- a/policyengine_us/variables/gov/states/id/dhw/liheap/income/id_liheap_countable_income.py +++ b/policyengine_us/variables/gov/states/id/dhw/liheap/income/id_liheap_countable_income.py @@ -18,20 +18,22 @@ def formula(spm_unit, period, parameters): person = spm_unit.members # Annual flows approximate prior-month receipts. Source losses do not # offset other receipts; existing net business inputs need no deduction. - earned = sum( - max_(add(person, period, [source]), 0) for source in p.sources.earned - ) + earned = 0 + for source in p.sources.earned: + earned = earned + max_(add(person, period, [source]), 0) adult = person("age", period) >= p.earned_income_min_age - unearned = sum( - max_(add(person, period, [source]), 0) for source in p.sources.unearned - ) + unearned = 0 + for source in p.sources.unearned: + unearned = unearned + max_(add(person, period, [source]), 0) social_security = max_( person("social_security", period) - max_(person("medicare_part_b_premium", period), 0), 0, ) # Nonqualified members' income counts. Child support, VA and general - # assistance remain excluded under the accepted plan's checklist. + # assistance remain excluded under the accepted plan's checklist; IDAPA + # 16.04.14.151.02 lists no exclusion for VA, general assistance or minors' + # earnings, and the plan is followed. return spm_unit.sum( where(adult, earned, 0) + unearned + social_security ) + max_(spm_unit("tanf", period), 0) From acf4d762455ecf958538ac188fbefe2f68ef7005 Mon Sep 17 00:00:00 2001 From: Ziming Date: Tue, 3 Nov 2026 16:44:03 -0500 Subject: [PATCH 09/10] Apply review fixes to Idaho LIHEAP Cap the annualized monthly limit at HHS's mandatory amount, which DHW's cents exceed by 4 cents at sizes 2 and 6. Count military basic pay, remove three floors that cannot bind, and fix one description. Record the federal cap, heat in rent and the plan's income checklist as candidates. Co-Authored-By: Claude Opus 5.5 --- .../eligibility/program_year_start_month.yaml | 2 +- .../id/dhw/liheap/income/sources/earned.yaml | 3 + .../states/id/dhw/liheap/payment/rent.yaml | 2 +- .../id_liheap_income_eligible.yaml | 37 +++++- .../eligibility/id_liheap_income_limit.yaml | 8 +- .../income/id_liheap_countable_income.yaml | 8 +- .../eligibility/id_liheap_income_limit.py | 11 +- .../income/id_liheap_countable_income.py | 4 +- source_conflicts/candidates.yaml | 106 ++++++++++++++++++ 9 files changed, 166 insertions(+), 15 deletions(-) diff --git a/policyengine_us/parameters/gov/states/id/dhw/liheap/eligibility/program_year_start_month.yaml b/policyengine_us/parameters/gov/states/id/dhw/liheap/eligibility/program_year_start_month.yaml index 7e5788b20bf..8f3c766e948 100644 --- a/policyengine_us/parameters/gov/states/id/dhw/liheap/eligibility/program_year_start_month.yaml +++ b/policyengine_us/parameters/gov/states/id/dhw/liheap/eligibility/program_year_start_month.yaml @@ -1,4 +1,4 @@ -description: Idaho begins the Low Income Home Energy Assistance Program year, used to establish categorical SNAP receipt, in this month of the preceding calendar year. +description: Idaho starts the program year, used to test SNAP receipt, in this month of the preceding calendar year under the Low Income Home Energy Assistance Program. values: 2025-10-01: 10 metadata: diff --git a/policyengine_us/parameters/gov/states/id/dhw/liheap/income/sources/earned.yaml b/policyengine_us/parameters/gov/states/id/dhw/liheap/income/sources/earned.yaml index e37a2a1309e..a98a4f83d0b 100644 --- a/policyengine_us/parameters/gov/states/id/dhw/liheap/income/sources/earned.yaml +++ b/policyengine_us/parameters/gov/states/id/dhw/liheap/income/sources/earned.yaml @@ -2,6 +2,9 @@ description: Idaho counts these earned income sources under the Low Income Home values: 2025-10-01: - employment_income + # Plan 1.9 checks "Wages". Basic pay is an input apart from employment_income; + # enter it in one of the two. + - military_basic_pay - self_employment_income - sstb_self_employment_income - farm_operations_income diff --git a/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/rent.yaml b/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/rent.yaml index 0a61e7dc099..3eae0a98b74 100644 --- a/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/rent.yaml +++ b/policyengine_us/parameters/gov/states/id/dhw/liheap/payment/rent.yaml @@ -15,6 +15,6 @@ metadata: - title: FY2025 Idaho LIHEAP State Plan, sections 2.5 and 2.6 href: https://liheapch.acf.gov/docs/2025/state-plans/ID_Plan_2025.pdf#page=9 - title: Idaho PY25 Benefit Determination Chart - href: https://liheapch.acf.gov/docs/2025/benefits-matricies/ID_BenefitMatrix_2025.pdf + href: https://liheapch.acf.gov/docs/2025/benefits-matricies/ID_BenefitMatrix_2025.pdf#page=1 - title: FY2026 Idaho LIHEAP State Plan, sections 2.5 and 2.6 href: https://liheapch.acf.gov/docs/2026/state-plans/ID_Plan_2026.pdf#page=9 diff --git a/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/eligibility/id_liheap_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/eligibility/id_liheap_income_eligible.yaml index eb309da3bae..9b4889cdbd1 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/eligibility/id_liheap_income_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/eligibility/id_liheap_income_eligible.yaml @@ -678,7 +678,7 @@ - 41200 id_liheap_income_limit: - 32835 - - 42938.04 + - 42938 - 32835 - name: Case 4, qualified size is required with zero income or categorical receipt. @@ -1760,3 +1760,38 @@ output: id_liheap_income_eligible: true +- name: Case 10, two cents over the federal maximum for two fails. + # HHS's mandatory FY2026 amount for two people is 42,938. DHW's monthly $3,578.17 would annualize to 42,938.04. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: {age: 40, is_citizen_or_legal_immigrant: true, ssi: 0} + person2: {age: 40, is_citizen_or_legal_immigrant: true, ssi: 0} + spm_units: + spm_unit: + members: [person1, person2] + heating_type: NATURAL_GAS + id_liheap_countable_income: 42_938.02 + snap: + 2025-09: 0 + 2025-10: 0 + 2025-11: 0 + 2025-12: 0 + 2026-01: 0 + 2026-02: 0 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + households: + household: {members: [person1, person2], state_code: ID} + output: + id_liheap_income_limit: 42_938 + id_liheap_income_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/eligibility/id_liheap_income_limit.yaml b/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/eligibility/id_liheap_income_limit.yaml index 813820ab539..5ebb4e499dc 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/eligibility/id_liheap_income_limit.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/eligibility/id_liheap_income_limit.yaml @@ -1,13 +1,17 @@ # Idaho FY2026 LIHEAP plan, 60% of SMI for sizes 1-7 and 150% of the guideline for 8 and up (page 8). # https://liheapch.acf.gov/docs/2026/state-plans/ID_Plan_2026.pdf#page=8 # DHW published monthly limits effective 2025-10-01; retrieved 2026-10-03. +# 42 U.S.C. 8624(b)(2)(B) and HHS Attachment 4 set the federal maximum. +# https://acf.gov/sites/default/files/documents/ocs/COMM_LIHEAP_IM2025-02_SMIStateTable_Att4.pdf#page=1 # https://healthandwelfare.idaho.gov/services-programs/financial-assistance/home-heating-and-utility-assistance/apply-heating-assistance -- name: Case 1, all published monthly limits and additional person amounts annualize exactly. +- name: Case 1, published monthly limits annualize under the federal maximum. period: 2026 absolute_error_margin: 0.01 # Sizes 1-10 use published monthly [2736.25,3578.17,4420.08,5262.08, # 6104,6945.92,7103.75,6768.75,7456.25,8143.75] times 12. + # Sizes 2 and 6 would be 42,938.04 and 83,351.04, so they cap at HHS's 42,938 and 83,351. + # Sizes 3 and 4 stay at DHW's lower 53,040.96 and 63,144.96. # Size 11 = (8,143.75 + 687.50) x 12 = 105,975; size 15 = (8,143.75 + 5 x 687.50) x 12 = 138,975. # Size 7 annual 85,245 exceeds size 8 annual 81,225: the explicit SMI-to-FPG switch is not max(). input: @@ -120,7 +124,7 @@ household11: {members: [person56, person57, person58, person59, person60, person61, person62, person63, person64, person65, person66], state_code: ID} household12: {members: [person67, person68, person69, person70, person71, person72, person73, person74, person75, person76, person77, person78, person79, person80, person81], state_code: ID} output: - id_liheap_income_limit: [32_835.0, 42_938.04, 53_040.96, 63_144.96, 73_248.0, 83_351.04, 85_245.0, 81_225.0, 89_475.0, 97_725.0, 105_975.0, 138_975.0] + id_liheap_income_limit: [32_835.0, 42_938.0, 53_040.96, 63_144.96, 73_248.0, 83_351.0, 85_245.0, 81_225.0, 89_475.0, 97_725.0, 105_975.0, 138_975.0] - name: Case 2, no qualified member has zero income limit. period: 2026 diff --git a/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/income/id_liheap_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/income/id_liheap_countable_income.yaml index 1cd1f762803..92a7ea716d4 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/income/id_liheap_countable_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/income/id_liheap_countable_income.yaml @@ -70,16 +70,16 @@ - name: Case 5, all supported earned business streams count. period: 2026 absolute_error_margin: 0.01 - # Gross wages 10,000 + net business streams 2,000 + 3,000 + 4,000 + 5,000 = 24,000. + # Gross wages 10,000 + basic pay 500 + net business streams 2,000 + 3,000 + 4,000 + 5,000 = 24,500. input: people: - person1: {age: 40, is_citizen_or_legal_immigrant: true, ssi: 0, employment_income: 10_000, self_employment_income: 2_000, sstb_self_employment_income: 3_000, farm_operations_income: 4_000, partnership_s_corp_income: 5_000} + person1: {age: 40, is_citizen_or_legal_immigrant: true, ssi: 0, employment_income: 10_000, military_basic_pay: 500, self_employment_income: 2_000, sstb_self_employment_income: 3_000, farm_operations_income: 4_000, partnership_s_corp_income: 5_000} spm_units: spm_unit: {members: [person1], heating_type: NATURAL_GAS, id_tafi: 0} households: household: {members: [person1], state_code: ID} output: - id_liheap_countable_income: 24_000 + id_liheap_countable_income: 24_500 - name: Case 6, negative business sources do not offset positive earnings. period: 2026 @@ -178,7 +178,7 @@ # FY2026 one-person limit 32,835. Gross Social Security 34,000 minus actual Part B 2,400 = 31,600. # Military 40,000 and pension 34,000 exceed the limit. Rental losses are not deductions. # UI 36,000 fails; reported UI gives 31,200; a negative receipt leaves 30,000. -# TANF receipt controls use the two-person limit 42,938.04, with no TANF categorical bypass. +# TANF receipt controls use the two-person limit 42,938, with no TANF categorical bypass. - name: Case 11, military retirement net Social Security and rental loss affect financial eligibility. period: 2026 diff --git a/policyengine_us/variables/gov/states/id/dhw/liheap/eligibility/id_liheap_income_limit.py b/policyengine_us/variables/gov/states/id/dhw/liheap/eligibility/id_liheap_income_limit.py index 81e62903d6b..0e813b1b196 100644 --- a/policyengine_us/variables/gov/states/id/dhw/liheap/eligibility/id_liheap_income_limit.py +++ b/policyengine_us/variables/gov/states/id/dhw/liheap/eligibility/id_liheap_income_limit.py @@ -11,7 +11,9 @@ class id_liheap_income_limit(Variable): definition_period = YEAR defined_for = StateCode.ID reference = ( + "https://www.law.cornell.edu/uscode/text/42/8624#b_2_B", "https://liheapch.acf.gov/docs/2026/state-plans/ID_Plan_2026.pdf#page=8", + "https://acf.gov/sites/default/files/documents/ocs/COMM_LIHEAP_IM2025-02_SMIStateTable_Att4.pdf#page=1", "https://healthandwelfare.idaho.gov/services-programs/financial-assistance/home-heating-and-utility-assistance/apply-heating-assistance", ) @@ -21,14 +23,15 @@ def formula(spm_unit, period, parameters): group = spm_unit.household("state_group_str", period) p = parameters(period) eligibility = p.gov.states.id.dhw.liheap.eligibility - # The shared helper's flooring order matches all seven published FY2026 - # SMI limits. Preserve monthly cents. + # The shared helper's flooring order matches all seven HHS FY2026 amounts. + # DHW prints monthly limits in cents. At sizes 2 and 6 they annualize 4 cents + # above those amounts, the federal maximum, so the cap applies there. annual_smi = liheap_smi_limit( size, state, eligibility.smi_rate, period, parameters ) monthly_smi = np.round(annual_smi / MONTHS_IN_YEAR, 2) annual_fpg = eligibility.fpg_rate * fpg( - max_(size, 1), + size, group, period, parameters, @@ -38,7 +41,7 @@ def formula(spm_unit, period, parameters): # lowers the limit; using max(SMI, FPG) would contradict its table. annual_limit = where( size <= eligibility.smi_max_household_size, - monthly_smi * MONTHS_IN_YEAR, + min_(monthly_smi * MONTHS_IN_YEAR, annual_smi), annual_fpg, ) return where(size > 0, annual_limit, 0) diff --git a/policyengine_us/variables/gov/states/id/dhw/liheap/income/id_liheap_countable_income.py b/policyengine_us/variables/gov/states/id/dhw/liheap/income/id_liheap_countable_income.py index 8d644cfe492..5a1359ddb86 100644 --- a/policyengine_us/variables/gov/states/id/dhw/liheap/income/id_liheap_countable_income.py +++ b/policyengine_us/variables/gov/states/id/dhw/liheap/income/id_liheap_countable_income.py @@ -27,7 +27,7 @@ def formula(spm_unit, period, parameters): unearned = unearned + max_(add(person, period, [source]), 0) social_security = max_( person("social_security", period) - - max_(person("medicare_part_b_premium", period), 0), + - person("medicare_part_b_premium", period), 0, ) # Nonqualified members' income counts. Child support, VA and general @@ -36,4 +36,4 @@ def formula(spm_unit, period, parameters): # earnings, and the plan is followed. return spm_unit.sum( where(adult, earned, 0) + unearned + social_security - ) + max_(spm_unit("tanf", period), 0) + ) + spm_unit("tanf", period) diff --git a/source_conflicts/candidates.yaml b/source_conflicts/candidates.yaml index 1cea80fc061..57e3094882c 100644 --- a/source_conflicts/candidates.yaml +++ b/source_conflicts/candidates.yaml @@ -2652,6 +2652,112 @@ candidates: state: ruled note: 'Ruled statute-first in October 2026; confirm line 12(c)''s scope against the per-person statute and worksheet. Code not yet on main: id_grocery_credit.' +- id: us-id:liheap-heat-in-rent-fy2026 + program: liheap + years: + from: 2026 + to: 2026 + type: federal-fiscal + question: Is an Idaho household that pays for heat through its rent eligible for FY2026 regular heating, as the rule in + force until June 2026 provides, or ineligible, as the FY2026 plan provides? + sources: + - kind: regulation + citation: IDAPA 16.04.14.152.02 and 16.04.14.010.08.b, effective April 6, 2023 + url: https://www.law.cornell.edu/regulations/idaho/IDAPA-16.04.14.152 + - kind: plan + citation: Idaho FY2026 LIHEAP State Plan, items 2.3 and 2.5, PDF pages 8-9 + url: https://liheapch.acf.gov/docs/2026/state-plans/ID_Plan_2026.pdf#page=8 + - kind: regulation + citation: IDAPA 16.03.08.200.07, effective July 1, 2026 + url: https://adminrules.idaho.gov/rules/current/16/160308.pdf#page=5 + readings: + statute: No statute is supplied; 16.04.14.152.02 covers households that incur home energy costs "either directly or as + an undesignated portion of their rent". From July 1, 2026, 16.03.08.200.07 says "designated portion". + other: Plan 2.5 says "Household with no specific heat cost obligation (included in rent, rent subsidized) will not be + eligible to a LIHEAP benefit", and the PY26 chart has no rent amount. + example: One person aged 65 with $15,000 of Social Security and natural gas heat included in rent in Ada County receives + $0 under the plan. Under 16.04.14.152.02 the household is eligible, and no FY2026 amount is printed for it. + pe_us: + follows: conflicting-source + code: + - policyengine_us/variables/gov/states/id/dhw/liheap/eligibility/id_liheap_eligible.py + - policyengine_us/parameters/gov/states/id/dhw/liheap/payment/rent.yaml + prs: + - https://github.com/PolicyEngine/policyengine-us/pull/10613 + state: ruled + note: 'Ruled 2026-11-02 and confirmed 2026-11-03: heat in rent is read as no specific obligation and is ineligible from + FY2026, although plan 1.1 runs heating assistance from October 2025 to March 2026, all under 16.04.14. A designated heat charge within rent has no + input.' +- id: us-id:liheap-monthly-limit-above-federal-ceiling + program: liheap + years: + from: 2026 + to: 2026 + type: federal-fiscal + question: Can Idaho's monthly income limits in cents pay a household whose annual income exceeds HHS's 60% state median + income amount? + sources: + - kind: statute + citation: 42 U.S.C. 8624(b)(2)(B) + url: https://www.law.cornell.edu/uscode/text/42/8624#b_2_B + - kind: guidance + citation: HHS LIHEAP IM 2025-02 Attachment 4, Mandatory Use in LIHEAP for FY26, Idaho, pages 1 and 4 + url: https://acf.gov/sites/default/files/documents/ocs/COMM_LIHEAP_IM2025-02_SMIStateTable_Att4.pdf#page=1 + - kind: guidance + citation: Idaho DHW Apply for Heating Assistance, monthly income limits effective October 1, 2025 + url: https://healthandwelfare.idaho.gov/services-programs/financial-assistance/home-heating-and-utility-assistance/apply-heating-assistance + readings: + statute: Payments go only to households whose income does not exceed the greater of 150% of the poverty guideline and + 60% of the state median income, which HHS publishes as $42,938 for two people and $83,351 for six. + other: DHW prints $3,578.17 and $6,945.92 a month, which annualize to $42,938.04 and $83,351.04. + example: Two adults with $42,938.02 of wages and natural gas heat in Ada County exceed the $42,938 federal maximum and + receive $0. The annualized monthly limit would pay $122. + pe_us: + follows: statute + code: + - policyengine_us/variables/gov/states/id/dhw/liheap/eligibility/id_liheap_income_limit.py + prs: + - https://github.com/PolicyEngine/policyengine-us/pull/10613 + state: unreviewed + note: The PR caps the annualized monthly limit at HHS's amount. DHW's lower annualized figures at sizes 3 and 4 ($53,040.96 + and $63,144.96) stay, since a lower limit is allowed. +- id: us-id:liheap-plan-income-checklist + program: liheap + years: + from: 2026 + to: 2026 + type: federal-fiscal + question: Do VA benefits, general assistance and minors' earnings count for Idaho LIHEAP under the income rule in force + until June 2026, or stay out under the FY2026 plan checklist? + sources: + - kind: regulation + citation: IDAPA 16.04.14.010.06 and 16.04.14.151.02, effective April 6, 2023 + url: https://www.law.cornell.edu/regulations/idaho/IDAPA-16.04.14.010 + - kind: plan + citation: Idaho FY2026 LIHEAP State Plan, section 1.9, PDF pages 5-7 + url: https://liheapch.acf.gov/docs/2026/state-plans/ID_Plan_2026.pdf#page=5 + - kind: regulation + citation: IDAPA 16.03.08.202, effective July 1, 2026 + url: https://adminrules.idaho.gov/rules/current/16/160308.pdf#page=6 + readings: + statute: No statute is supplied; 16.04.14.010.06 counts moneys "from all sources", and the closed exclusion list at + 151.02 names only GI Bill education money among VA payments and no general assistance or minors' earnings. + other: Plan 1.9 leaves "General Assistance benefits", "Veterans Administration (VA) benefits" and "Earned income of a + child under the age of 18" unchecked. From July 1, 2026, 16.03.08.202 counts gross income as the Department determines. + example: A veteran aged 45 with $35,000 of VA disability compensation and natural gas heat in Ada County counts $0 and + receives $132 under the plan. Under 16.04.14.010.06 the $35,000 is above the $32,835 limit and the household receives + $0. + pe_us: + follows: conflicting-source + code: + - policyengine_us/parameters/gov/states/id/dhw/liheap/income/sources/earned.yaml + - policyengine_us/parameters/gov/states/id/dhw/liheap/income/sources/unearned.yaml + - policyengine_us/variables/gov/states/id/dhw/liheap/income/id_liheap_countable_income.py + prs: + - https://github.com/PolicyEngine/policyengine-us/pull/10613 + state: ruled + note: 'Ruled 2026-11-02: follow the plan over IDAPA 16.04.14. The Idaho AABD supplement (id_aabd) is also not counted, + as plan 1.9 does not name it, although 151.02 does not exclude it; it can only move an SSI recipient''s burden band.' - id: us-il:2022-rebate-claimed-vs-claimable program: income-tax years: From b1cdb6e1c4002c2062adabdd03fe2ae8252d3761 Mon Sep 17 00:00:00 2001 From: Ziming Date: Thu, 5 Nov 2026 13:25:12 -0500 Subject: [PATCH 10/10] Follow IDAPA 16.04.14 on Idaho LIHEAP income for FY2026 Count VA benefits, general assistance, the Idaho AABD supplement and the earnings of members under 18, as ruled on 2026-11-05: 010.06 counts moneys from all sources and the 151.02 exclusion list is closed. Remove the unused earned_income_min_age parameter. Part B netting and the unlisted sources are unchanged. Cite 16.04.14 in eligibility and record the heat-in-rent basis. Co-Authored-By: Claude Opus 5.5 --- .../liheap/income/earned_income_min_age.yaml | 11 --- .../id/dhw/liheap/income/sources/earned.yaml | 5 ++ .../dhw/liheap/income/sources/unearned.yaml | 9 ++- .../id_liheap_income_eligible.yaml | 6 +- .../gov/states/id/dhw/liheap/id_liheap.yaml | 71 +++++++++++++++++++ .../income/id_liheap_countable_income.yaml | 23 +++--- .../liheap/eligibility/id_liheap_eligible.py | 3 + .../income/id_liheap_countable_income.py | 17 +++-- source_conflicts/candidates.yaml | 25 ++++--- 9 files changed, 126 insertions(+), 44 deletions(-) delete mode 100644 policyengine_us/parameters/gov/states/id/dhw/liheap/income/earned_income_min_age.yaml diff --git a/policyengine_us/parameters/gov/states/id/dhw/liheap/income/earned_income_min_age.yaml b/policyengine_us/parameters/gov/states/id/dhw/liheap/income/earned_income_min_age.yaml deleted file mode 100644 index a6965e9e8a1..00000000000 --- a/policyengine_us/parameters/gov/states/id/dhw/liheap/income/earned_income_min_age.yaml +++ /dev/null @@ -1,11 +0,0 @@ -description: Idaho counts earned income of members this age or older under the Low Income Home Energy Assistance Program. -values: - 2025-10-01: 18 - -metadata: - unit: year - period: year - label: Idaho LIHEAP minimum age for earned income - reference: - - title: Idaho FY2026 LIHEAP State Plan - href: https://liheapch.acf.gov/docs/2026/state-plans/ID_Plan_2026.pdf#page=6 diff --git a/policyengine_us/parameters/gov/states/id/dhw/liheap/income/sources/earned.yaml b/policyengine_us/parameters/gov/states/id/dhw/liheap/income/sources/earned.yaml index a98a4f83d0b..12b33bbcc40 100644 --- a/policyengine_us/parameters/gov/states/id/dhw/liheap/income/sources/earned.yaml +++ b/policyengine_us/parameters/gov/states/id/dhw/liheap/income/sources/earned.yaml @@ -1,4 +1,7 @@ description: Idaho counts these earned income sources under the Low Income Home Energy Assistance Program. +# Every member's earnings count: IDAPA 16.04.14.010.06 counts moneys "from all +# sources" and 151.02 does not exclude a minor's, although plan 1.9 leaves them +# unchecked. values: 2025-10-01: - employment_income @@ -17,3 +20,5 @@ metadata: reference: - title: "Idaho FY2026 LIHEAP State Plan #page 5-7" href: https://liheapch.acf.gov/docs/2026/state-plans/ID_Plan_2026.pdf#page=5 + - title: IDAPA 16.04.14.010.06 as of September 10, 2025 + href: https://web.archive.org/web/20250910171431id_/https://adminrules.idaho.gov/rules/current/16/160414.pdf#page=3 diff --git a/policyengine_us/parameters/gov/states/id/dhw/liheap/income/sources/unearned.yaml b/policyengine_us/parameters/gov/states/id/dhw/liheap/income/sources/unearned.yaml index e784e31fb92..aa98119cf35 100644 --- a/policyengine_us/parameters/gov/states/id/dhw/liheap/income/sources/unearned.yaml +++ b/policyengine_us/parameters/gov/states/id/dhw/liheap/income/sources/unearned.yaml @@ -21,6 +21,11 @@ values: - estate_income - disability_benefits - workers_compensation + # IDAPA 16.04.14.010.06 counts moneys "from all sources", and 151.02 excludes + # none of these, although plan 1.9 leaves VA and general assistance unchecked. + - veterans_benefits + - general_assistance + - id_aabd # Plan 1.9's checked Other line and IDAPA 16.04.14.151.02.f count gifts and # lottery winnings over $30, although its lump-sum line is unchecked. The # specific line is followed. The $30 test has no input: annual amounts count. @@ -34,5 +39,5 @@ metadata: reference: - title: "Idaho FY2026 LIHEAP State Plan #page 5-7" href: https://liheapch.acf.gov/docs/2026/state-plans/ID_Plan_2026.pdf#page=5 - - title: IDAPA 16.04.14.151.02 as of September 10, 2025 - href: https://web.archive.org/web/20250910171431id_/https://adminrules.idaho.gov/rules/current/16/160414.pdf#page=5 + - title: "IDAPA 16.04.14.010.06 and 151.02 as of September 10, 2025 #page 3,5" + href: https://web.archive.org/web/20250910171431id_/https://adminrules.idaho.gov/rules/current/16/160414.pdf#page=3 diff --git a/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/eligibility/id_liheap_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/eligibility/id_liheap_income_eligible.yaml index 9b4889cdbd1..baf729024f6 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/eligibility/id_liheap_income_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/eligibility/id_liheap_income_eligible.yaml @@ -450,8 +450,8 @@ - name: Case 3, one member receiving SSI establishes the modeled categorical route. # Positive requested-year SSI is the documented stable-receipt approximation. - # Income: 40_000 + 1 * 12; 60_000 + 100 * 12; 40_000 + 100 * 12. - # Child earnings are excluded; SSI is counted once. + # Income: 40_000 + 1 * 12; 60_000 + 6_000 + 100 * 12; 40_000 + 100 * 12. + # Child earnings count; SSI is counted once. # The third unit has a nonqualified SSI recipient and a qualified child. # The parent income counts; SSI is not restricted to qualified members. period: 2026 @@ -674,7 +674,7 @@ - 1 id_liheap_countable_income: - 40012 - - 61200 + - 67200 - 41200 id_liheap_income_limit: - 32835 diff --git a/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/id_liheap.yaml b/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/id_liheap.yaml index 540e2237cc1..122e2536bc4 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/id_liheap.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/id_liheap.yaml @@ -252,3 +252,74 @@ id_liheap_income_eligible: [true, true] output: id_liheap: [342, 808] + +- name: Case 13, VA benefits and a minor's earnings can put a household over the limit. + period: 2026 + absolute_error_margin: 0.01 + # IDAPA 16.04.14.010.06 counts them. Ada County, gas with a bill, SNAP zero over the program year. + # VA 35_000 is over the one-person 32_835. Wages 36_000 + 8_000 = 44_000 are over the two-person 42_938. + input: + people: + person1: + age: 45 + veterans_benefits: 35_000 + person2: + age: 40 + employment_income_before_lsr: 36_000 + person3: + age: 17 + employment_income_before_lsr: 8_000 + spm_units: + spm_unit1: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 900 + takes_up_tanf_if_eligible: false + snap: {2025-10: 0, 2025-11: 0, 2025-12: 0, 2026-01: 0, 2026-02: 0, 2026-03: 0, 2026-04: 0, 2026-05: 0, 2026-06: 0, 2026-07: 0, 2026-08: 0, 2026-09: 0} + spm_unit2: + members: [person2, person3] + heating_type: NATURAL_GAS + gas_expense: 900 + takes_up_tanf_if_eligible: false + snap: {2025-10: 0, 2025-11: 0, 2025-12: 0, 2026-01: 0, 2026-02: 0, 2026-03: 0, 2026-04: 0, 2026-05: 0, 2026-06: 0, 2026-07: 0, 2026-08: 0, 2026-09: 0} + households: + household1: + members: [person1] + state_code: ID + county: ADA_COUNTY_ID + household2: + members: [person2, person3] + state_code: ID + county: ADA_COUNTY_ID + output: + id_liheap_countable_income: [35_000, 44_000] + id_liheap_income_limit: [32_835, 42_938] + id_liheap_eligible: [false, false] + id_liheap: [0, 0] + +- name: Case 14, the Idaho AABD supplement counts and can move the burden band. + period: 2026 + absolute_error_margin: 0.01 + # SSI (994 a month x 12) 11_928 + AABD (53 a month x 12) 636 = 12_564. Ada County electric 1_335 / 12_564 + # = 10.63% is medium, 342, plus the 25 bonus at age 65. Without AABD, 1_335 / 11_928 = 11.19% would be high. + input: + people: + person1: + age: 65 + ssi: 11_928 + id_aabd_living_arrangement: SINGLE + spm_units: + spm_unit: + members: [person1] + heating_type: ELECTRICITY + pre_subsidy_electricity_expense: 1_000 + takes_up_tanf_if_eligible: false + households: + household: + members: [person1] + state_code: ID + county: ADA_COUNTY_ID + output: + id_aabd: 636 + id_liheap_countable_income: 12_564 + id_liheap: 367 diff --git a/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/income/id_liheap_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/income/id_liheap_countable_income.yaml index 92a7ea716d4..75172af05ee 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/income/id_liheap_countable_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/id/dhw/liheap/income/id_liheap_countable_income.yaml @@ -2,11 +2,14 @@ # https://liheapch.acf.gov/docs/2026/state-plans/ID_Plan_2026.pdf#page=5 # IDAPA 16.03.08 section 202 includes income of nonqualified household members (page 6). # https://adminrules.idaho.gov/rules/current/16/160308.pdf#page=6 +# IDAPA 16.04.14.010.06 and 151.02 define income for FY2026 heating (pages 3, 5). +# https://web.archive.org/web/20250910171431id_/https://adminrules.idaho.gov/rules/current/16/160414.pdf#page=3 -- name: Case 1, minor earnings are excluded but child SSI is included. +- name: Case 1, a minor's earnings, VA benefits and general assistance count and child support does not. period: 2026 absolute_error_margin: 0.01 - # Adult 12,000 + child SSI (100 a month x 12) = 13,200; child wages, support, VA and GA are excluded. + # Adult 12,000 + child wages 6,000 + SSI (100 a month x 12) 1,200 + VA 3,000 + GA 900 = 23,100. + # IDAPA 16.04.14.151.02.t excludes the child support. # The SSI input of 1,200 is the annual amount for a MONTH variable in a YEAR test. input: people: @@ -17,12 +20,12 @@ households: household: {members: [person1, person2], state_code: ID} output: - id_liheap_countable_income: 13_200 + id_liheap_countable_income: 23_100 -- name: Case 2, earnings count at the eighteenth birthday. +- name: Case 2, an eighteen-year-old's earnings count. period: 2026 absolute_error_margin: 0.01 - # The child is now 18, so both the 12,000 of adult wages and the 6,000 of earnings count. + # The 12,000 of adult wages and the 18-year-old's 6,000 of earnings both count. input: people: person1: {age: 35, is_citizen_or_legal_immigrant: true, ssi: 0, employment_income: 12_000} @@ -111,10 +114,10 @@ output: id_liheap_countable_income: 900 -- name: Case 8, child support veterans benefits and general assistance are excluded. +- name: Case 8, child support is excluded and VA benefits and general assistance count. period: 2026 absolute_error_margin: 0.01 - # Unchecked source boxes: child support 9,000, VA 5,000 and GA 2,000 do not count. + # IDAPA 16.04.14.151.02.t excludes child support 9,000; VA 5,000 + GA 2,000 = 7,000 count. input: people: person1: {age: 35, is_citizen_or_legal_immigrant: true, ssi: 0, child_support_received: 9_000, veterans_benefits: 5_000, general_assistance: 2_000} @@ -124,13 +127,13 @@ households: household: {members: [person1, person2], state_code: ID} output: - id_liheap_countable_income: 0 + id_liheap_countable_income: 7_000 - name: Case 9, mixed states and unequal memberships retain separate income totals. period: 2026 absolute_error_margin: 0.01 # First Idaho unit 6,000 + 6,000 = 12,000; Colorado 0; - # second Idaho unit adult 1,800 + child SSI 1,800 = 3,600; minor wages of 10,000 are excluded. + # second Idaho unit adult 1,800 + minor wages 10,000 + child SSI 1,800 = 13,600. input: people: person1: {age: 35, is_citizen_or_legal_immigrant: true, ssi: 0, employment_income: 6_000} @@ -147,7 +150,7 @@ household2: {members: [person3], state_code: CO} household3: {members: [person4, person5], state_code: ID} output: - id_liheap_countable_income: [12_000, 0, 3_600] + id_liheap_countable_income: [12_000, 0, 13_600] # Ongoing retirement receipts: pension 1,000 + taxable IRA 12,000 + exempt IRA 3,000. # Count the two aggregates once; one-time lump sums are not represented here. diff --git a/policyengine_us/variables/gov/states/id/dhw/liheap/eligibility/id_liheap_eligible.py b/policyengine_us/variables/gov/states/id/dhw/liheap/eligibility/id_liheap_eligible.py index d98009931b2..580521fea16 100644 --- a/policyengine_us/variables/gov/states/id/dhw/liheap/eligibility/id_liheap_eligible.py +++ b/policyengine_us/variables/gov/states/id/dhw/liheap/eligibility/id_liheap_eligible.py @@ -11,6 +11,9 @@ class id_liheap_eligible(Variable): # PDF pages 8-9 "https://liheapch.acf.gov/docs/2026/state-plans/ID_Plan_2026.pdf#page=8", "https://adminrules.idaho.gov/rules/current/16/160308.pdf#page=5", + # IDAPA 16.04.14.001.02 and 152.02, in force for all of FY2026 heating. + # PDF pages 3, 6 + "https://web.archive.org/web/20250910171431id_/https://adminrules.idaho.gov/rules/current/16/160414.pdf#page=3", ) def formula(spm_unit, period, parameters): diff --git a/policyengine_us/variables/gov/states/id/dhw/liheap/income/id_liheap_countable_income.py b/policyengine_us/variables/gov/states/id/dhw/liheap/income/id_liheap_countable_income.py index 5a1359ddb86..5d693f0e49e 100644 --- a/policyengine_us/variables/gov/states/id/dhw/liheap/income/id_liheap_countable_income.py +++ b/policyengine_us/variables/gov/states/id/dhw/liheap/income/id_liheap_countable_income.py @@ -10,7 +10,9 @@ class id_liheap_countable_income(Variable): defined_for = StateCode.ID reference = ( # PDF pages 5-7 - "https://liheapch.acf.gov/docs/2026/state-plans/ID_Plan_2026.pdf#page=5" + "https://liheapch.acf.gov/docs/2026/state-plans/ID_Plan_2026.pdf#page=5", + # IDAPA 16.04.14.010.06 and 151.02. PDF pages 3, 5 + "https://web.archive.org/web/20250910171431id_/https://adminrules.idaho.gov/rules/current/16/160414.pdf#page=3", ) def formula(spm_unit, period, parameters): @@ -21,7 +23,6 @@ def formula(spm_unit, period, parameters): earned = 0 for source in p.sources.earned: earned = earned + max_(add(person, period, [source]), 0) - adult = person("age", period) >= p.earned_income_min_age unearned = 0 for source in p.sources.unearned: unearned = unearned + max_(add(person, period, [source]), 0) @@ -30,10 +31,8 @@ def formula(spm_unit, period, parameters): - person("medicare_part_b_premium", period), 0, ) - # Nonqualified members' income counts. Child support, VA and general - # assistance remain excluded under the accepted plan's checklist; IDAPA - # 16.04.14.151.02 lists no exclusion for VA, general assistance or minors' - # earnings, and the plan is followed. - return spm_unit.sum( - where(adult, earned, 0) + unearned + social_security - ) + spm_unit("tanf", period) + # Every member's income counts, nonqualified members' and minors' included. + # IDAPA 16.04.14.151.02.t leaves out child support, which is in neither list. + return spm_unit.sum(earned + unearned + social_security) + spm_unit( + "tanf", period + ) diff --git a/source_conflicts/candidates.yaml b/source_conflicts/candidates.yaml index 10d3c8327c5..a03b6314f6f 100644 --- a/source_conflicts/candidates.yaml +++ b/source_conflicts/candidates.yaml @@ -3272,7 +3272,9 @@ candidates: - https://github.com/PolicyEngine/policyengine-us/pull/10613 state: ruled note: 'Ruled 2026-11-02 and confirmed 2026-11-03: heat in rent is read as no specific obligation and is ineligible from - FY2026, although plan 1.1 runs heating assistance from October 2025 to March 2026, all under 16.04.14. A designated heat charge within rent has no + FY2026, although plan 1.1 runs heating assistance from October 2025 to March 2026, all under 16.04.14. Basis: 16.04.14 + sets no amount (001.02: "does not entitle any household to a certain amount or form of assistance"), and the PY26 + chart, the only FY2026 amount instrument, drops the Rent column PY25 had. A designated heat charge within rent has no input.' - id: us-id:liheap-monthly-limit-above-federal-ceiling program: liheap @@ -3313,8 +3315,8 @@ candidates: from: 2026 to: 2026 type: federal-fiscal - question: Do VA benefits, general assistance and minors' earnings count for Idaho LIHEAP under the income rule in force - until June 2026, or stay out under the FY2026 plan checklist? + question: Do VA benefits, general assistance and minors' earnings count for Idaho LIHEAP in FY2026, as IDAPA 16.04.14 + provides, or stay out under the FY2026 plan checklist? sources: - kind: regulation citation: IDAPA 16.04.14.010.06 and 16.04.14.151.02, effective April 6, 2023 @@ -3330,11 +3332,10 @@ candidates: 151.02 names only GI Bill education money among VA payments and no general assistance or minors' earnings. other: Plan 1.9 leaves "General Assistance benefits", "Veterans Administration (VA) benefits" and "Earned income of a child under the age of 18" unchecked. From July 1, 2026, 16.03.08.202 counts gross income as the Department determines. - example: A veteran aged 45 with $35,000 of VA disability compensation and natural gas heat in Ada County counts $0 and - receives $132 under the plan. Under 16.04.14.010.06 the $35,000 is above the $32,835 limit and the household receives - $0. + example: A veteran aged 45 with $35,000 of VA disability compensation and natural gas heat in Ada County counts $35,000 + under the rule, above the $32,835 limit, and receives $0. Under the plan the household counts $0 and receives $132. pe_us: - follows: conflicting-source + follows: statute code: - policyengine_us/parameters/gov/states/id/dhw/liheap/income/sources/earned.yaml - policyengine_us/parameters/gov/states/id/dhw/liheap/income/sources/unearned.yaml @@ -3342,8 +3343,14 @@ candidates: prs: - https://github.com/PolicyEngine/policyengine-us/pull/10613 state: ruled - note: 'Ruled 2026-11-02: follow the plan over IDAPA 16.04.14. The Idaho AABD supplement (id_aabd) is also not counted, - as plan 1.9 does not name it, although 151.02 does not exclude it; it can only move an SSI recipient''s burden band.' + note: 'Ruled 2026-11-05 for the regulation by the project lead; the ruling record is + https://github.com/PolicyEngine/policyengine-us/pull/10613#issuecomment-6665844738. 16.04.14.010.06 defines income as moneys "from all sources", the + 151.02 exclusion list is closed, and 16.04.14 does not delegate countable income to the department or adopt the state + plan. The rule was in force April 6, 2023 to June 30, 2026, and plan 1.1 runs FY2026 heating October 1, 2025 to March + 31, 2026, so it governed every heating determination. us-nm:liheap-plan-income-checklist followed its regulation over + the same checklist. The ruling covers VA benefits, general assistance, minors'' earnings and id_aabd; Part B netting + under plan 1.9 and miscellaneous_income, pfml_benefits, life_insurance_benefits, gi_cash_assistance and capital_gains, + which stay uncounted, are unchanged and outside it.' - id: us-il:2022-rebate-claimed-vs-claimable program: income-tax years: