From a0134a17d381e028512b2abb04d00306accea444 Mon Sep 17 00:00:00 2001 From: Ziming Date: Mon, 12 Oct 2026 14:19:31 -0400 Subject: [PATCH 01/10] Add New Hampshire state supplementation for 2026 --- changelog.d/nh-ssp-2026.added.md | 1 + .../household/household_state_benefits.yaml | 4 + .../hud/annual_income/sources/unearned.yaml | 1 + .../states/nh/dhhs/ssp/couple_disregard.yaml | 10 + .../gov/states/nh/dhhs/ssp/couple_need.yaml | 11 + .../nh/dhhs/ssp/disabled_minimum_age.yaml | 10 + .../dhhs/ssp/earned/aged_disabled_flat.yaml | 10 + .../earned/aged_disabled_fraction_cap.yaml | 11 + .../states/nh/dhhs/ssp/earned/blind_flat.yaml | 10 + .../dhhs/ssp/earned/disregard_fraction.yaml | 9 + .../earned/minimum_employment_expenses.yaml | 11 + .../nh/dhhs/ssp/grant_reduction_fraction.yaml | 9 + .../states/nh/dhhs/ssp/individual_need.yaml | 23 + .../states/nh/dhhs/ssp/minimum_payment.yaml | 10 + .../states/nh/dhhs/ssp/resource_limit.yaml | 9 + .../states/nh/dhhs/ssp/single_disregard.yaml | 10 + .../nh/dhhs/ssp/three_person_disregard.yaml | 10 + .../states/nh/dhhs/ssp/three_person_need.yaml | 16 + .../usda/snap/income/sources/unearned.yaml | 7 +- policyengine_us/programs.yaml | 16 + .../gov/states/nh/dhhs/ssp/integration.yaml | 217 ++++++ .../gov/states/nh/dhhs/ssp/nh_ssp.yaml | 621 ++++++++++++++++++ .../nh_ssp_resources_deemed_from_parents.yaml | 71 ++ .../gov/states/_ssp_parental_resources.py | 76 +++ .../gov/states/nh/dhhs/ssp/nh_ssp.py | 34 + .../nh/dhhs/ssp/nh_ssp_countable_income.py | 67 ++ .../nh/dhhs/ssp/nh_ssp_disability_eligible.py | 20 + .../gov/states/nh/dhhs/ssp/nh_ssp_eligible.py | 46 ++ .../nh/dhhs/ssp/nh_ssp_employment_expenses.py | 11 + ...h_ssp_essential_person_countable_income.py | 11 + .../ssp/nh_ssp_essential_person_resources.py | 12 + .../ssp/nh_ssp_grant_reduction_applies.py | 17 + .../dhhs/ssp/nh_ssp_has_essential_person.py | 10 + .../nh/dhhs/ssp/nh_ssp_living_arrangement.py | 32 + .../ssp/nh_ssp_other_income_deductions.py | 11 + .../nh_ssp_resources_deemed_from_parents.py | 29 + .../income/spm_unit/spm_unit_benefits.py | 1 + 37 files changed, 1480 insertions(+), 4 deletions(-) create mode 100644 changelog.d/nh-ssp-2026.added.md create mode 100644 policyengine_us/parameters/gov/states/nh/dhhs/ssp/couple_disregard.yaml create mode 100644 policyengine_us/parameters/gov/states/nh/dhhs/ssp/couple_need.yaml create mode 100644 policyengine_us/parameters/gov/states/nh/dhhs/ssp/disabled_minimum_age.yaml create mode 100644 policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/aged_disabled_flat.yaml create mode 100644 policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/aged_disabled_fraction_cap.yaml create mode 100644 policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/blind_flat.yaml create mode 100644 policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/disregard_fraction.yaml create mode 100644 policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/minimum_employment_expenses.yaml create mode 100644 policyengine_us/parameters/gov/states/nh/dhhs/ssp/grant_reduction_fraction.yaml create mode 100644 policyengine_us/parameters/gov/states/nh/dhhs/ssp/individual_need.yaml create mode 100644 policyengine_us/parameters/gov/states/nh/dhhs/ssp/minimum_payment.yaml create mode 100644 policyengine_us/parameters/gov/states/nh/dhhs/ssp/resource_limit.yaml create mode 100644 policyengine_us/parameters/gov/states/nh/dhhs/ssp/single_disregard.yaml create mode 100644 policyengine_us/parameters/gov/states/nh/dhhs/ssp/three_person_disregard.yaml create mode 100644 policyengine_us/parameters/gov/states/nh/dhhs/ssp/three_person_need.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/integration.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/nh_ssp.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/nh_ssp_resources_deemed_from_parents.yaml create mode 100644 policyengine_us/variables/gov/states/_ssp_parental_resources.py create mode 100644 policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp.py create mode 100644 policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_countable_income.py create mode 100644 policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_disability_eligible.py create mode 100644 policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_eligible.py create mode 100644 policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_employment_expenses.py create mode 100644 policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_essential_person_countable_income.py create mode 100644 policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_essential_person_resources.py create mode 100644 policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_grant_reduction_applies.py create mode 100644 policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_has_essential_person.py create mode 100644 policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_living_arrangement.py create mode 100644 policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_other_income_deductions.py create mode 100644 policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_resources_deemed_from_parents.py diff --git a/changelog.d/nh-ssp-2026.added.md b/changelog.d/nh-ssp-2026.added.md new file mode 100644 index 00000000000..7e17c2d8c60 --- /dev/null +++ b/changelog.d/nh-ssp-2026.added.md @@ -0,0 +1 @@ +Add New Hampshire essential-person assistance groups to the 2026 SSP calculation. Add New Hampshire State Supplement Program for 2026. diff --git a/policyengine_us/parameters/gov/household/household_state_benefits.yaml b/policyengine_us/parameters/gov/household/household_state_benefits.yaml index d2cbd6ba2d4..0ea7b407e22 100644 --- a/policyengine_us/parameters/gov/household/household_state_benefits.yaml +++ b/policyengine_us/parameters/gov/household/household_state_benefits.yaml @@ -78,6 +78,7 @@ values: # DC benefits - dc_ossp # Kansas benefits + - nh_ssp - ks_sspp # Hawaii benefits - hi_oss @@ -176,6 +177,7 @@ values: # DC benefits - dc_ossp # Kansas benefits + - nh_ssp - ks_sspp # Hawaii benefits - hi_oss @@ -279,6 +281,7 @@ values: - dc_ossp - dc_child_care_subsidies # Kansas benefits + - nh_ssp - ks_sspp # Hawaii benefits - hi_oss @@ -382,6 +385,7 @@ values: - dc_ossp - dc_child_care_subsidies # Kansas benefits + - nh_ssp - ks_sspp # Hawaii benefits - hi_oss diff --git a/policyengine_us/parameters/gov/hud/annual_income/sources/unearned.yaml b/policyengine_us/parameters/gov/hud/annual_income/sources/unearned.yaml index d2b2bbd8675..097fd002b1c 100644 --- a/policyengine_us/parameters/gov/hud/annual_income/sources/unearned.yaml +++ b/policyengine_us/parameters/gov/hud/annual_income/sources/unearned.yaml @@ -19,6 +19,7 @@ values: - strike_benefits - social_security - ssi + - nh_ssp - general_assistance - unemployment_compensation - child_support_received diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/couple_disregard.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/couple_disregard.yaml new file mode 100644 index 00000000000..27e1af90f9d --- /dev/null +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/couple_disregard.yaml @@ -0,0 +1,10 @@ +description: New Hampshire uses this couple disregard in its adult category cash assistance calculation. +values: + '2026-01-01': 20 +metadata: + unit: currency-USD + label: New Hampshire SSP couple disregard + reference: + - title: He-W 654.16, Adult standard disregard + href: https://gc.nh.gov/rules/state_agencies/he-w600.html + period: month diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/couple_need.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/couple_need.yaml new file mode 100644 index 00000000000..41e0f2a9143 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/couple_need.yaml @@ -0,0 +1,11 @@ +description: New Hampshire sets this monthly standard of need for an individual living independently with + a spouse. +values: + '2026-01-01': 1492 +metadata: + unit: currency-USD + label: New Hampshire SSP independent couple need standard + reference: + - title: New Hampshire 2026 approved optional state supplement income standards, Section D and E + href: https://www.medicaid.gov/medicaid/spa/downloads/NH-26-0001.pdf + period: month diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/disabled_minimum_age.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/disabled_minimum_age.yaml new file mode 100644 index 00000000000..fbfd15861d9 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/disabled_minimum_age.yaml @@ -0,0 +1,10 @@ +description: New Hampshire requires disabled applicants to have reached this age for adult category cash + assistance. +values: + '2026-01-01': 18 +metadata: + unit: year + label: New Hampshire SSP minimum disabled age + reference: + - title: RSA 167:6 VI + href: https://gc.nh.gov/rsa/html/XII/167/167-6.htm diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/aged_disabled_flat.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/aged_disabled_flat.yaml new file mode 100644 index 00000000000..e78cf5c4b76 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/aged_disabled_flat.yaml @@ -0,0 +1,10 @@ +description: New Hampshire uses this earned aged disabled flat in its adult category cash assistance calculation. +values: + '2026-01-01': 20 +metadata: + unit: currency-USD + label: New Hampshire SSP earned aged disabled flat + reference: + - title: He-W 654.15(f), Aged and disabled earned income disregard + href: https://gc.nh.gov/rules/state_agencies/he-w600.html + period: month diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/aged_disabled_fraction_cap.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/aged_disabled_fraction_cap.yaml new file mode 100644 index 00000000000..3094fcab9f9 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/aged_disabled_fraction_cap.yaml @@ -0,0 +1,11 @@ +description: New Hampshire uses this earned aged disabled fraction cap in its adult category cash assistance + calculation. +values: + '2026-01-01': 30 +metadata: + unit: currency-USD + label: New Hampshire SSP earned aged disabled fraction cap + reference: + - title: He-W 654.15(f), Aged and disabled earned income disregard + href: https://gc.nh.gov/rules/state_agencies/he-w600.html + period: month diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/blind_flat.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/blind_flat.yaml new file mode 100644 index 00000000000..689a9800ab2 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/blind_flat.yaml @@ -0,0 +1,10 @@ +description: New Hampshire uses this earned blind flat in its adult category cash assistance calculation. +values: + '2026-01-01': 85 +metadata: + unit: currency-USD + label: New Hampshire SSP earned blind flat + reference: + - title: He-W 654.15(b), Blind earned income disregard + href: https://gc.nh.gov/rules/state_agencies/he-w600.html + period: month diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/disregard_fraction.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/disregard_fraction.yaml new file mode 100644 index 00000000000..7b9117e8b6f --- /dev/null +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/disregard_fraction.yaml @@ -0,0 +1,9 @@ +description: New Hampshire uses this earned disregard fraction in its adult category cash assistance calculation. +values: + '2026-01-01': 0.5 +metadata: + unit: /1 + label: New Hampshire SSP earned disregard fraction + reference: + - title: He-W 654.15, Earned income disregards + href: https://gc.nh.gov/rules/state_agencies/he-w600.html diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/minimum_employment_expenses.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/minimum_employment_expenses.yaml new file mode 100644 index 00000000000..464729538b5 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/minimum_employment_expenses.yaml @@ -0,0 +1,11 @@ +description: New Hampshire uses this earned minimum employment expenses in its adult category cash assistance + calculation. +values: + '2026-01-01': 18 +metadata: + unit: currency-USD + label: New Hampshire SSP earned minimum employment expenses + reference: + - title: He-W 654.18, Employment expenses + href: https://gc.nh.gov/rules/state_agencies/he-w600.html + period: month diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/grant_reduction_fraction.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/grant_reduction_fraction.yaml new file mode 100644 index 00000000000..98f66dc0d39 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/grant_reduction_fraction.yaml @@ -0,0 +1,9 @@ +description: New Hampshire uses this grant reduction fraction in its adult category cash assistance calculation. +values: + '2026-01-01': 0.3333333333333333 +metadata: + unit: /1 + label: New Hampshire SSP grant reduction fraction + reference: + - title: He-W 670.03(c), Grant reduction + href: https://gc.nh.gov/rules/state_agencies/he-w600.html diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/individual_need.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/individual_need.yaml new file mode 100644 index 00000000000..1e4e6352ab8 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/individual_need.yaml @@ -0,0 +1,23 @@ +description: New Hampshire sets these monthly adult assistance standards of need for an individual in + each living arrangement. +metadata: + unit: currency-USD + period: month + label: New Hampshire SSP individual need standard + breakdown: + - nh_ssp_living_arrangement + reference: + - title: New Hampshire 2026 approved optional state supplement income standards, Section D and E + href: https://www.medicaid.gov/medicaid/spa/downloads/NH-26-0001.pdf +INDEPENDENT: + '2026-01-01': 1008 +SUBSIDIZED_COMMUNITY_RESIDENCE: + '2026-01-01': 1070 +NONSUBSIDIZED_COMMUNITY_RESIDENCE: + '2026-01-01': 1130 +ENHANCED_FAMILY_CARE: + '2026-01-01': 1188 +RESIDENTIAL_CARE: + '2026-01-01': 1188 +NONE: + '2026-01-01': 0 diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/minimum_payment.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/minimum_payment.yaml new file mode 100644 index 00000000000..ffe89f197ea --- /dev/null +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/minimum_payment.yaml @@ -0,0 +1,10 @@ +description: New Hampshire uses this minimum payment in its adult category cash assistance calculation. +values: + '2026-01-01': 2 +metadata: + unit: currency-USD + label: New Hampshire SSP minimum payment + reference: + - title: He-W 670.03(a), Determination of grant + href: https://gc.nh.gov/rules/state_agencies/he-w600.html + period: month diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/resource_limit.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/resource_limit.yaml new file mode 100644 index 00000000000..0d63ff486e8 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/resource_limit.yaml @@ -0,0 +1,9 @@ +description: New Hampshire uses this resource limit in its adult category cash assistance calculation. +values: + '2026-01-01': 1500 +metadata: + unit: currency-USD + label: New Hampshire SSP resource limit + reference: + - title: He-W 656.06(b), Adult category resource limit + href: https://gc.nh.gov/rules/state_agencies/he-w600.html diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/single_disregard.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/single_disregard.yaml new file mode 100644 index 00000000000..1b12757a24a --- /dev/null +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/single_disregard.yaml @@ -0,0 +1,10 @@ +description: New Hampshire uses this single disregard in its adult category cash assistance calculation. +values: + '2026-01-01': 13 +metadata: + unit: currency-USD + label: New Hampshire SSP single disregard + reference: + - title: He-W 654.16, Adult standard disregard + href: https://gc.nh.gov/rules/state_agencies/he-w600.html + period: month diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/three_person_disregard.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/three_person_disregard.yaml new file mode 100644 index 00000000000..aa6e203cafc --- /dev/null +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/three_person_disregard.yaml @@ -0,0 +1,10 @@ +description: New Hampshire deducts this standard amount for an adult, spouse and needy essential person. +values: + '2026-01-01': 25 +metadata: + unit: currency-USD + label: New Hampshire SSP three-person standard disregard + reference: + - title: He-W 654.16(b)(3) + href: https://gc.nh.gov/rules/state_agencies/he-w600.html + period: month diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/three_person_need.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/three_person_need.yaml new file mode 100644 index 00000000000..55b1ee1a24f --- /dev/null +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/three_person_need.yaml @@ -0,0 +1,16 @@ +description: 'New Hampshire uses this standard of need for an adult, spouse and needy essential person. + The 2026 value is calculated under He-W 658.03(e): the published 2025 standard of $1,934 plus the SSI + couple increase of $41 and essential-person increase of $14.' +values: + '2026-01-01': 1989 +metadata: + unit: currency-USD + label: New Hampshire SSP three-person standard of need + reference: + - title: He-W 658.03(e), COLA update method + href: https://gc.nh.gov/rules/state_agencies/he-w600.html + - title: DHHS Medicaid Budget Briefing Book, published 2025 standards, page 23 + href: https://gc.nh.gov/lba/budget/operating_budgets/2026-2027/HF_Division_III/DHHS_Medicaid_Briefing_Book_2-21-25.pdf#page=23 + - title: SSA 2026 federal payment amounts and COLA + href: https://www.ssa.gov/oact/cola/SSI.html + period: month diff --git a/policyengine_us/parameters/gov/usda/snap/income/sources/unearned.yaml b/policyengine_us/parameters/gov/usda/snap/income/sources/unearned.yaml index 6f94d3d09b2..f2c1e0baebe 100644 --- a/policyengine_us/parameters/gov/usda/snap/income/sources/unearned.yaml +++ b/policyengine_us/parameters/gov/usda/snap/income/sources/unearned.yaml @@ -36,6 +36,7 @@ values: - hi_oss - id_aabd - in_ssp + - nh_ssp - ks_sspp - ky_ssp - la_oss @@ -95,9 +96,7 @@ values: metadata: reference: - - title: 7 CFR 273.9(b)(2) - href: https://www.law.cornell.edu/cfr/text/7/273.9#b_2 - - title: 7 CFR 273.9(c)(1) - href: https://www.law.cornell.edu/cfr/text/7/273.9#c_1 + - title: 7 CFR 273.9(b)(2) and (c)(1), (5) + href: https://www.law.cornell.edu/cfr/text/7/273.9 - title: POMS SI 01401.001 General Information about State Supplementation href: https://secure.ssa.gov/poms.nsf/lnx/0501401001 diff --git a/policyengine_us/programs.yaml b/policyengine_us/programs.yaml index 05cb1d13747..04d51e7c2ec 100644 --- a/policyengine_us/programs.yaml +++ b/policyengine_us/programs.yaml @@ -1090,6 +1090,22 @@ programs: tracks. Unmodeled paths: grandfathered medically-needy-in-medical- institution recipients per WAC 388-478-0055(2)(b); DDA-determined / PVL track per (2)(f); and foster child in BRS per (2)(g). + - state: NH + status: partial + name: New Hampshire SSP + full_name: New Hampshire State Supplement Program + variable: nh_ssp + parameter_prefix: gov.states.nh.dhhs.ssp + verified_years: '2026' + notes: Models the 2026 individual and couple need standards, certified community care, + state income disregards, resource limit, rounding and grant reduction. State medical + decisions, specialized deductions, care placement and no-SNAP grant reductions require + explicit inputs. Blind children include full co-resident parental resource + excess; certified exceptions and eighteenth-birthday month treatment require + a deemed-resource input. Needy essential-person groups use a certified caregiver income/resource + budget. The three-person 2026 need standard is derived under He-W 658.03(e) + from the published 2025 standard and SSI COLA increases. Conditional resources, + sanctions and grandfathered benefits are not modeled. - id: social_security name: Social Security diff --git a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/integration.yaml new file mode 100644 index 00000000000..3ee2a8e1109 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/integration.yaml @@ -0,0 +1,217 @@ +- name: Case 1, eligible independent couple shares one grant. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + first: + age: 65 + second: + age: 65 + marital_units: + couple: + members: + - first + - second + tax_units: + unit: + members: + - first + - second + households: + household: + members: + - first + - second + state_code: NH + output: + nh_ssp: + - 10.5 + - 10.5 +- name: Case 2, nonapplicant spouse is included in needs. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + first: + age: 65 + second: + age: 40 + marital_units: + couple: + members: + - first + - second + tax_units: + unit: + members: + - first + - second + households: + household: + members: + - first + - second + state_code: NH + output: + nh_ssp: + - 518 + - 0 +- name: Case 3, independent couple combined resources exceed limit. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + first: + age: 65 + ssi_countable_resources: 750 + second: + age: 65 + ssi_countable_resources: 751 + marital_units: + couple: + members: + - first + - second + tax_units: + unit: + members: + - first + - second + households: + household: + members: + - first + - second + state_code: NH + output: + nh_ssp: + - 0 + - 0 +- name: Case 4, care spouses are individual assistance groups. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + first: + age: 65 + nh_ssp_living_arrangement: RESIDENTIAL_CARE + ssi_claim_is_joint: false + second: + age: 65 + nh_ssp_living_arrangement: RESIDENTIAL_CARE + ssi_claim_is_joint: false + marital_units: + couple: + members: + - first + - second + tax_units: + unit: + members: + - first + - second + households: + household: + members: + - first + - second + state_code: NH + output: + nh_ssp: + - 207 + - 207 +- name: Case 5, two aged applicants receive separate earned disregards. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + first: + age: 65 + employment_income: 1200 + second: + age: 65 + employment_income: 1200 + marital_units: + couple: + members: + - first + - second + tax_units: + unit: + members: + - first + - second + households: + household: + members: + - first + - second + state_code: NH + output: + nh_ssp: + - 7.5 + - 7.5 +- name: Case 6, annual independent grant and SNAP income. + period: '2026' + absolute_error_margin: 0.01 + input: + state_code: NH + age: 65 + output: + nh_ssp: 324 + household_state_benefits: 324 + snap_unearned_income: 12252 + hud_unearned_income: 12252 +- name: Eligible couple and essential person share a three-person grant + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + a: + age: 70 + nh_ssp_has_essential_person: true + b: + age: 70 + marital_units: + couple: + members: + - a + - b + households: + home: + members: + - a + - b + state_code: NH + output: + nh_ssp: + - 261.5 + - 261.5 + nh_ssp_countable_income: + - 1466 + - 1466 +- name: Three-person grant with a non-applicant spouse + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + a: + age: 70 + nh_ssp_has_essential_person: true + b: + age: 40 + marital_units: + couple: + members: + - a + - b + households: + home: + members: + - a + - b + state_code: NH + output: + nh_ssp: + - 1020 + - 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/nh_ssp.yaml b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/nh_ssp.yaml new file mode 100644 index 00000000000..595e3f79ac5 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/nh_ssp.yaml @@ -0,0 +1,621 @@ +- name: Case 1, independent SSI recipient. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NH + age: 65 + output: + nh_ssp: 27 +- name: Case 2, certified subsidized_community_residence. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NH + age: 65 + nh_ssp_living_arrangement: SUBSIDIZED_COMMUNITY_RESIDENCE + output: + nh_ssp: 89 +- name: Case 3, certified nonsubsidized_community_residence. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NH + age: 65 + nh_ssp_living_arrangement: NONSUBSIDIZED_COMMUNITY_RESIDENCE + output: + nh_ssp: 149 +- name: Case 4, certified enhanced_family_care. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NH + age: 65 + nh_ssp_living_arrangement: ENHANCED_FAMILY_CARE + output: + nh_ssp: 207 +- name: Case 5, certified residential_care. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NH + age: 65 + nh_ssp_living_arrangement: RESIDENTIAL_CARE + output: + nh_ssp: 207 +- name: Case 6, resources at state limit. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NH + age: 65 + ssi_countable_resources: 1500 + output: + nh_ssp: 27 +- name: Case 7, resources exceed state limit despite federal eligibility. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NH + age: 65 + ssi_countable_resources: 1501 + output: + nh_ssp: 0 +- name: Case 8, twenty dollars of Social Security reduces state grant. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NH + age: 65 + social_security_retirement: 240 + output: + nh_ssp: 7 +- name: Case 9, state only benefit. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NH + age: 65 + social_security_retirement: 12216 + output: + nh_ssp: 3 +- name: Case 10, positive dollar amount raised to state minimum. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NH + age: 65 + nh_ssp_countable_income: 1007 + output: + nh_ssp: 2 +- name: Case 11, income at standard. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NH + age: 65 + nh_ssp_countable_income: 1008 + output: + nh_ssp: 0 +- name: Case 12, aged employment rules. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NH + age: 65 + employment_income: 1200 + output: + nh_ssp: 3 +- name: Case 13, blind employment rules. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NH + age: 40 + is_blind: true + employment_income: 1200 + output: + nh_ssp: 27 +- name: Case 14, verified employment expenses above minimum. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NH + age: 65 + employment_income: 1200 + nh_ssp_employment_expenses: 50 + output: + nh_ssp: 35 +- name: Case 15, other allowed deductions. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NH + age: 65 + nh_ssp_other_income_deductions: 25 + output: + nh_ssp: 52 +- name: Case 16, independently determined one third grant reduction. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NH + age: 65 + nh_ssp_grant_reduction_applies: true + output: + nh_ssp: 18 +- name: Case 17, federal disability alone does not establish forty eight month duration. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NH + age: 40 + meets_ssi_disability_criteria: true + output: + nh_ssp: 0 +- name: Case 18, permanently disabled adult. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NH + age: 40 + meets_ssi_disability_criteria: true + is_permanently_and_totally_disabled: true + output: + nh_ssp: 27 +- name: Case 19, blind child. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NH + age: 17 + is_blind: true + output: + nh_ssp: 27 +- name: Case 20, disabled child without blindness. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NH + age: 17 + meets_ssi_disability_criteria: true + is_permanently_and_totally_disabled: true + output: + nh_ssp: 0 +- name: Case 21, nonresident. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: VT + age: 65 + output: + nh_ssp: 0 +- name: Case 22, required federal benefit application declined. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NH + age: 65 + takes_up_ssi_if_eligible: false + output: + nh_ssp: 0 +- name: Case 23, excluded living arrangement. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NH + age: 65 + nh_ssp_living_arrangement: NONE + output: + nh_ssp: 0 +- name: Single recipient and certified essential person use group size two + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NH + age: 70 + ssi: 994 + nh_ssp_has_essential_person: true + output: + nh_ssp: 518 +- name: Essential person income is added before the group disregard + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NH + age: 70 + ssi: 994 + nh_ssp_has_essential_person: true + nh_ssp_essential_person_countable_income: 100 + output: + nh_ssp: 418 +- name: Essential person resources are counted even when recipient receives SSI + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NH + age: 70 + ssi: 994 + nh_ssp_has_essential_person: true + ssi_countable_resources: 1000 + nh_ssp_essential_person_resources: 501 + output: + nh_ssp: 0 +- name: Essential person resource limit is inclusive + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NH + age: 70 + ssi: 994 + nh_ssp_has_essential_person: true + ssi_countable_resources: 1000 + nh_ssp_essential_person_resources: 500 + output: + nh_ssp: 518 +- name: Care facilities remain single-person groups + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NH + age: 70 + ssi: 994 + nh_ssp_has_essential_person: true + nh_ssp_living_arrangement: RESIDENTIAL_CARE + nh_ssp_essential_person_countable_income: 100 + output: + nh_ssp: 207 +- name: Uncertified caregiver does not increase the standard + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NH + age: 70 + ssi: 994 + nh_ssp_has_essential_person: false + output: + nh_ssp: 27 +- name: Group standard disregard does not turn excess essential-person income into + eligibility + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NH + age: 70 + ssi: 994 + nh_ssp_has_essential_person: true + nh_ssp_essential_person_countable_income: 518 + output: + nh_ssp: 0 +- name: Annual essential-person resource input stays a balance in each month + period: '2026' + absolute_error_margin: 0.01 + input: + state_code: NH + age: 70 + ssi: 994 + nh_ssp_has_essential_person: true + ssi_countable_resources: 1000 + nh_ssp_essential_person_resources: 501 + output: + nh_ssp: 0 + +# He-W 652.03(i)-(j),(q): full parental excess, NH $1500 ceiling, and adult control. +# https://gc.nh.gov/rules/state_agencies/he-w600.html +- name: Blind child is ineligible with excess co-resident parent resources + period: 2026-06 + absolute_error_margin: 0.01 + input: + people: + parent1: + age: + '2026': 40 + person_id: + '2026': 1 + bank_account_assets: + '2026': 10000 + child1: + age: + '2026': 10 + person_id: + '2026': 3 + parent_1_id: + '2026': 1 + is_blind: + '2026': true + marital_units: + parent1: + members: + - parent1 + child1: + members: + - child1 + tax_units: + parent1: + members: + - parent1 + child1: + members: + - child1 + families: + family: + members: + - parent1 + - child1 + spm_units: + unit: + members: + - parent1 + - child1 + households: + home: + members: + - parent1 + - child1 + state_code: + '2026': NH + output: + nh_ssp: + - 0 + - 0 +- name: Parental allowance plus the NH child resource ceiling is inclusive + period: 2026-06 + absolute_error_margin: 0.01 + input: + people: + parent1: + age: + '2026': 40 + person_id: + '2026': 1 + bank_account_assets: + '2026': 3500 + child1: + age: + '2026': 10 + person_id: + '2026': 3 + parent_1_id: + '2026': 1 + is_blind: + '2026': true + marital_units: + parent1: + members: + - parent1 + child1: + members: + - child1 + tax_units: + parent1: + members: + - parent1 + child1: + members: + - child1 + families: + family: + members: + - parent1 + - child1 + spm_units: + unit: + members: + - parent1 + - child1 + households: + home: + members: + - parent1 + - child1 + state_code: + '2026': NH + output: + nh_ssp: + - 0 + - 27 +- name: One cent above the parent allowance and NH resource ceiling is ineligible + period: 2026-06 + absolute_error_margin: 0.01 + input: + people: + parent1: + age: + '2026': 40 + person_id: + '2026': 1 + bank_account_assets: + '2026': 3500.01 + child1: + age: + '2026': 10 + person_id: + '2026': 3 + parent_1_id: + '2026': 1 + is_blind: + '2026': true + marital_units: + parent1: + members: + - parent1 + child1: + members: + - child1 + tax_units: + parent1: + members: + - parent1 + child1: + members: + - child1 + families: + family: + members: + - parent1 + - child1 + spm_units: + unit: + members: + - parent1 + - child1 + households: + home: + members: + - parent1 + - child1 + state_code: + '2026': NH + output: + nh_ssp: + - 0 + - 0 +- name: A blind adult does not receive deemed parental resources + period: 2026-06 + absolute_error_margin: 0.01 + input: + people: + parent1: + age: + '2026': 40 + person_id: + '2026': 1 + bank_account_assets: + '2026': 10000 + child1: + age: + '2026': 19 + person_id: + '2026': 3 + parent_1_id: + '2026': 1 + is_blind: + '2026': true + marital_units: + parent1: + members: + - parent1 + child1: + members: + - child1 + tax_units: + parent1: + members: + - parent1 + child1: + members: + - child1 + families: + family: + members: + - parent1 + - child1 + spm_units: + unit: + members: + - parent1 + - child1 + households: + home: + members: + - parent1 + - child1 + state_code: + '2026': NH + output: + nh_ssp: + - 0 + - 27 +- name: Each blind sibling receives the full excess under the NH rule + period: 2026-06 + absolute_error_margin: 0.01 + input: + people: + parent1: + age: + '2026': 40 + person_id: + '2026': 1 + bank_account_assets: + '2026': 5500 + parent2: + age: + '2026': 40 + person_id: + '2026': 2 + child1: + age: + '2026': 10 + person_id: + '2026': 3 + parent_1_id: + '2026': 1 + is_blind: + '2026': true + parent_2_id: + '2026': 2 + child2: + age: + '2026': 10 + person_id: + '2026': 4 + parent_1_id: + '2026': 1 + is_blind: + '2026': true + parent_2_id: + '2026': 2 + marital_units: + parent1: + members: + - parent1 + parent2: + members: + - parent2 + child1: + members: + - child1 + child2: + members: + - child2 + tax_units: + parent1: + members: + - parent1 + parent2: + members: + - parent2 + child1: + members: + - child1 + child2: + members: + - child2 + families: + family: + members: + - parent1 + - parent2 + - child1 + - child2 + spm_units: + unit: + members: + - parent1 + - parent2 + - child1 + - child2 + households: + home: + members: + - parent1 + - parent2 + - child1 + - child2 + state_code: + '2026': NH + output: + nh_ssp: + - 0 + - 0 + - 0 + - 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/nh_ssp_resources_deemed_from_parents.yaml b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/nh_ssp_resources_deemed_from_parents.yaml new file mode 100644 index 00000000000..c79fd3b4565 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/nh_ssp_resources_deemed_from_parents.yaml @@ -0,0 +1,71 @@ +# Resource balances and certified budgets are stocks. Annual demographic and asset inputs are explicit. +- name: Annual asset balances remain undivided in January and July + period: 2026 + absolute_error_margin: 0.01 + input: + people: + parent1: + age: + '2026': 40 + person_id: + '2026': 1 + bank_account_assets: + '2026': 10000 + child1: + age: + '2026': 10 + person_id: + '2026': 3 + parent_1_id: + '2026': 1 + is_blind: + '2026': true + marital_units: + parent1: + members: + - parent1 + child1: + members: + - child1 + tax_units: + parent1: + members: + - parent1 + child1: + members: + - child1 + families: + family: + members: + - parent1 + - child1 + spm_units: + unit: + members: + - parent1 + - child1 + households: + home: + members: + - parent1 + - child1 + state_code: + '2026': NH + output: + nh_ssp_resources_deemed_from_parents: + 2026-01: + - 0 + - 8000 + 2026-07: + - 0 + - 8000 +- name: Annual agency-certified resource budget remains a monthly stock + period: 2026 + absolute_error_margin: 0.01 + input: + state_code: NH + nh_ssp_resources_deemed_from_parents: 2500 + output: + nh_ssp_resources_deemed_from_parents: + 2026-01: 2500 + 2026-07: 2500 diff --git a/policyengine_us/variables/gov/states/_ssp_parental_resources.py b/policyengine_us/variables/gov/states/_ssp_parental_resources.py new file mode 100644 index 00000000000..b2d76b4a130 --- /dev/null +++ b/policyengine_us/variables/gov/states/_ssp_parental_resources.py @@ -0,0 +1,76 @@ +"""Co-resident parental resources shared by state supplement calculations.""" + +import numpy as np + +from policyengine_us.variables.household.demographic.person._parent_links import ( + co_resident_parent_indices, + has_parent_ids, + household_member_indices, + unlinked_parent, +) + + +def ssp_parental_resources(person, period, parameters, exclude_ssi_parents=False): + """Return the parent pair and resources above its SSI allowance. + + Explicit links identify natural, adoptive and step parents in this + household. Without a child's links, use only explicitly identified + unlinked parents in the same family and household. More than two such + candidates requires parent links or a certified deemed-resource input. + """ + year = period.this_year + first, second = co_resident_parent_indices(person, year) + unlinked = ~has_parent_ids(person, year) + parent = unlinked_parent(person, year) + family = person.family.reference_entity.members_entity_id + own_row = np.arange(person.count) + candidates = np.zeros(person.count, dtype=int) + fallback_first = np.full(person.count, -1, dtype=int) + fallback_second = np.full(person.count, -1, dtype=int) + for member in household_member_indices(person): + match = ( + (member >= 0) + & (member != own_row) + & parent[member] + & (family[member] == family) + ) + fallback_first = np.where(match & (candidates == 0), member, fallback_first) + fallback_second = np.where(match & (candidates == 1), member, fallback_second) + candidates = candidates + match + usable = unlinked & (candidates <= 2) + first = np.where(usable, fallback_first, first) + second = np.where(usable, fallback_second, second) + # Sorting makes sibling membership independent of the parent-slot order. + first, second = np.minimum(first, second), np.maximum(first, second) + resources = person("ssi_countable_resources", year).astype(np.float64) + if exclude_ssi_parents: + resources = np.where(person("ssi", period) > 0, 0, resources) + total = np.where(first >= 0, resources[first], 0) + np.where( + second >= 0, resources[second], 0 + ) + parents = (first >= 0).astype(int) + (second >= 0) + limit = parameters(period).gov.ssa.ssi.eligibility.resources.limit + allowance = np.where(parents > 1, limit.couple, limit.individual) + return first, second, np.maximum(total - allowance, 0) + + +def ssp_sibling_resource_share(person, first, second, excess, candidates, own, limit): + """Allocate to otherwise eligible children, removing resource failures. + + SI 01330.200/.280 require reallocation when a child's own resources + plus their share disqualify them. Children with different parent sets + do not reduce one another's deemed resources. + """ + eligible = candidates & (own <= limit) + share = excess.copy() + for _ in range(int(np.max(person.household.nb_persons(), initial=0)) + 1): + count = np.zeros(person.count, dtype=int) + for member in household_member_indices(person): + same_parents = (first == first[member]) & (second == second[member]) + count = count + ((member >= 0) & same_parents & eligible[member]) + share = excess / np.maximum(count, 1) + remaining = eligible & (own + share <= limit) + if np.array_equal(remaining, eligible): + break + eligible = remaining + return share diff --git a/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp.py b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp.py new file mode 100644 index 00000000000..d904dd5f616 --- /dev/null +++ b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp.py @@ -0,0 +1,34 @@ +from policyengine_us.model_api import * + + +class nh_ssp(Variable): + value_type = float + entity = Person + label = "New Hampshire State Supplement Program" + definition_period = MONTH + unit = USD + defined_for = "nh_ssp_eligible" + reference = ( + "https://www.medicaid.gov/medicaid/spa/downloads/NH-26-0001.pdf", + "https://gc.nh.gov/rules/state_agencies/he-w600.html", + ) + + def formula(person, period, parameters): + p = parameters(period).gov.states.nh.dhhs.ssp + arrangement = person("nh_ssp_living_arrangement", period) + independent = arrangement == arrangement.possible_values.INDEPENDENT + couple = independent & (person.marital_unit.sum(independent) == 2) + essential = independent & person.marital_unit.any( + person("nh_ssp_has_essential_person", period) + ) + standard = where(couple, p.couple_need, p.individual_need[arrangement]) + standard = where( + essential, where(couple, p.three_person_need, p.couple_need), standard + ) + income = person("nh_ssp_countable_income", period) + grant = np.floor(max_(standard - income, 0) + 0.5) + grant = where(grant > 0, max_(grant, p.minimum_payment), 0) + reduction = person("nh_ssp_grant_reduction_applies", period) + grant = np.floor(grant * (1 - reduction * p.grant_reduction_fraction) + 0.5) + recipients = person.marital_unit.sum(person("nh_ssp_eligible", period)) + return grant / where(couple, max_(recipients, 1), 1) diff --git a/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_countable_income.py b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_countable_income.py new file mode 100644 index 00000000000..52b9957e883 --- /dev/null +++ b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_countable_income.py @@ -0,0 +1,67 @@ +from policyengine_us.model_api import * + + +class nh_ssp_countable_income(Variable): + value_type = float + entity = Person + label = "New Hampshire adult assistance group countable income" + definition_period = MONTH + unit = USD + reference = "https://gc.nh.gov/rules/state_agencies/he-w600.html" + documentation = "Income for the whole assistance group; a couple shares one grant." + + def formula(person, period, parameters): + p = parameters(period).gov.states.nh.dhhs.ssp + arrangement = person("nh_ssp_living_arrangement", period) + independent = arrangement == arrangement.possible_values.INDEPENDENT + couple = independent & (person.marital_unit.sum(independent) == 2) + essential = independent & person.marital_unit.any( + person("nh_ssp_has_essential_person", period) + ) + both_applicants = ( + person.marital_unit.sum(person("nh_ssp_eligible", period)) == 2 + ) + earned = max_(person("ssi_earned_income", period), 0) + expenses = max_(person("nh_ssp_employment_expenses", period), 0) + # With a nonapplicant spouse, combine earnings before the applicant's + # category disregard under He-W 654.02(d)-(e). + combined = couple & ~both_applicants + earned = where(combined, person.marital_unit.sum(earned), earned) + expenses = where(combined, person.marital_unit.sum(expenses), expenses) + blind = person("is_blind", period.this_year) + blind_net = max_(earned - p.earned.blind_flat, 0) * ( + 1 - p.earned.disregard_fraction + ) + remaining = max_(earned - p.earned.aged_disabled_flat, 0) + aged_disabled_net = max_( + remaining + - min_( + remaining * p.earned.disregard_fraction, + p.earned.aged_disabled_fraction_cap, + ) + - max_(expenses, p.earned.minimum_employment_expenses), + 0, + ) + net_earned = where(blind, blind_net, aged_disabled_net) + net_earned = where( + couple & both_applicants, person.marital_unit.sum(net_earned), net_earned + ) + unearned = max_(person("ssi_unearned_income", period), 0) + person( + "ssi", period + ) + # Blind children use the parental allocation defined in He-W 641.04. + unearned = unearned + person( + "ssi_unearned_income_deemed_from_ineligible_parent", period + ) + unearned = where(couple, person.marital_unit.sum(unearned), unearned) + other = max_(person("nh_ssp_other_income_deductions", period), 0) + other = where(couple, person.marital_unit.sum(other), other) + unearned = unearned + essential * person.marital_unit.max( + max_(person("nh_ssp_essential_person_countable_income", period), 0) + ) + disregard = where( + essential & couple, + p.three_person_disregard, + where(couple | essential, p.couple_disregard, p.single_disregard), + ) + return max_(net_earned + unearned - disregard - other, 0) diff --git a/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_disability_eligible.py b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_disability_eligible.py new file mode 100644 index 00000000000..93e78ec802f --- /dev/null +++ b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_disability_eligible.py @@ -0,0 +1,20 @@ +from policyengine_us.model_api import * + + +class nh_ssp_disability_eligible(Variable): + value_type = bool + entity = Person + label = "Meets New Hampshire APTD medical criteria" + definition_period = YEAR + reference = "https://gc.nh.gov/rsa/html/XII/167/167-6.htm" + documentation = """ + State medical eligibility requires federal disability criteria and the + state's 48-month impairment-duration test. The formula identifies people + already reported permanently and totally disabled. Set the state decision + explicitly for qualifying impairments of finite duration. + """ + + def formula(person, period, parameters): + return person("meets_ssi_disability_criteria", period) & person( + "is_permanently_and_totally_disabled", period + ) diff --git a/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_eligible.py b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_eligible.py new file mode 100644 index 00000000000..1ed9d9c16e7 --- /dev/null +++ b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_eligible.py @@ -0,0 +1,46 @@ +from policyengine_us.model_api import * + + +class nh_ssp_eligible(Variable): + value_type = bool + entity = Person + label = "New Hampshire adult cash assistance non-income eligibility" + definition_period = MONTH + defined_for = StateCode.NH + reference = ( + "https://gc.nh.gov/rsa/html/XII/167/167-6.htm", + "https://gc.nh.gov/rules/state_agencies/he-w600.html", + ) + + def formula(person, period, parameters): + p = parameters(period).gov.states.nh.dhhs.ssp + age = person("age", period.this_year) + aged = age >= parameters(period).gov.ssa.ssi.eligibility.aged_threshold + blind = person("is_blind", period.this_year) + disabled = (age >= p.disabled_minimum_age) & person( + "nh_ssp_disability_eligible", period.this_year + ) + arrangement = person("nh_ssp_living_arrangement", period) + la = arrangement.possible_values + independent = arrangement == la.INDEPENDENT + couple = independent & (person.marital_unit.sum(independent) == 2) + essential = independent & person.marital_unit.any( + person("nh_ssp_has_essential_person", period) + ) + resources = person("ssi_countable_resources", period.this_year) + resources = where(couple, person.marital_unit.sum(resources), resources) + resources = resources + person("nh_ssp_resources_deemed_from_parents", period) + resources = resources + essential * person.marital_unit.max( + max_(person("nh_ssp_essential_person_resources", period), 0) + ) + immigration = person("immigration_status", period.this_year) + citizen = immigration == immigration.possible_values.CITIZEN + immigrant = person("is_ssi_qualified_noncitizen", period.this_year) + return ( + (aged | blind | disabled) + & (resources <= p.resource_limit) + & (citizen | immigrant) + & (arrangement != la.NONE) + & ~person("is_incarcerated", period) + & person("takes_up_ssi_if_eligible", period.this_year) + ) diff --git a/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_employment_expenses.py b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_employment_expenses.py new file mode 100644 index 00000000000..21ab6331248 --- /dev/null +++ b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_employment_expenses.py @@ -0,0 +1,11 @@ +from policyengine_us.model_api import * + + +class nh_ssp_employment_expenses(Variable): + value_type = float + entity = Person + label = "New Hampshire SSP verified employment expenses" + definition_period = MONTH + unit = USD + reference = "https://gc.nh.gov/rules/state_agencies/he-w600.html" + documentation = """Monthly verified employment expenses under He-W 654.18, including mandatory payroll deductions and qualifying transportation and dependent-care costs. The formula allows at least the statutory flat amount for aged and disabled workers.""" diff --git a/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_essential_person_countable_income.py b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_essential_person_countable_income.py new file mode 100644 index 00000000000..443942c5e7f --- /dev/null +++ b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_essential_person_countable_income.py @@ -0,0 +1,11 @@ +from policyengine_us.model_api import * + + +class nh_ssp_essential_person_countable_income(Variable): + value_type = float + entity = Person + label = "New Hampshire SSP essential-person countable income" + definition_period = MONTH + unit = USD + reference = "https://gc.nh.gov/rules/state_agencies/he-w600.html" + documentation = "Essential person's net earned income after He-W 654.15 and 654.18 deductions plus gross countable unearned income. Do not subtract the assistance-group standard disregard. Enter once, or the same amount on both applicant spouses." diff --git a/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_essential_person_resources.py b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_essential_person_resources.py new file mode 100644 index 00000000000..0e7a476e240 --- /dev/null +++ b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_essential_person_resources.py @@ -0,0 +1,12 @@ +from policyengine_us.model_api import * + + +class nh_ssp_essential_person_resources(Variable): + value_type = float + entity = Person + label = "New Hampshire SSP essential-person countable resources" + definition_period = MONTH + unit = USD + quantity_type = STOCK + reference = "https://gc.nh.gov/rules/state_agencies/he-w600.html" + documentation = "Countable resources of the certified co-resident essential person under adult cash-assistance rules. Enter once, or the same amount on both applicant spouses." diff --git a/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_grant_reduction_applies.py b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_grant_reduction_applies.py new file mode 100644 index 00000000000..5642e5c00ba --- /dev/null +++ b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_grant_reduction_applies.py @@ -0,0 +1,17 @@ +from policyengine_us.model_api import * + + +class nh_ssp_grant_reduction_applies(Variable): + value_type = bool + entity = Person + label = "New Hampshire SSP one-third grant reduction applies" + definition_period = MONTH + default_value = False + reference = "https://gc.nh.gov/rules/state_agencies/he-w600.html" + documentation = """ + State determination under He-W 670.03(c): the independent-living recipient + lives with others, has no food or residence expenses and receives no SNAP, + or fails the required documentation. This is a separate determination from + the federal SSI household reduction. It is explicit to avoid a cycle with + SNAP, which counts the state grant as income. + """ diff --git a/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_has_essential_person.py b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_has_essential_person.py new file mode 100644 index 00000000000..4c38251e425 --- /dev/null +++ b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_has_essential_person.py @@ -0,0 +1,10 @@ +from policyengine_us.model_api import * + + +class nh_ssp_has_essential_person(Variable): + value_type = bool + entity = Person + label = "New Hampshire SSP certified needy essential person" + definition_period = MONTH + reference = "https://gc.nh.gov/rules/state_agencies/he-w600.html" + documentation = "A co-resident person essential to the recipient's well-being who does not qualify for assistance in their own right under He-W 601.05(p). Set on the recipient, not the caregiver; one caregiver is shared by an applicant couple." diff --git a/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_living_arrangement.py b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_living_arrangement.py new file mode 100644 index 00000000000..20e8dffdc97 --- /dev/null +++ b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_living_arrangement.py @@ -0,0 +1,32 @@ +from policyengine_us.model_api import * + + +class NHSSPLivingArrangement(Enum): + INDEPENDENT = "Independent living" + SUBSIDIZED_COMMUNITY_RESIDENCE = "Certified subsidized community residence" + NONSUBSIDIZED_COMMUNITY_RESIDENCE = "Certified nonsubsidized community residence" + ENHANCED_FAMILY_CARE = "Certified enhanced family care" + RESIDENTIAL_CARE = "Certified residential care" + NONE = "No eligible adult assistance living arrangement" + + +class nh_ssp_living_arrangement(Variable): + value_type = Enum + entity = Person + label = "New Hampshire adult assistance living arrangement" + definition_period = MONTH + possible_values = NHSSPLivingArrangement + default_value = NHSSPLivingArrangement.INDEPENDENT + reference = "https://www.medicaid.gov/medicaid/spa/downloads/NH-26-0001.pdf" + documentation = """ + Care categories require state approval. Care recipients are individual + assistance groups, including married residents. Reflect separate federal + SSI claims explicitly when applicable. Use NONE for excluded facilities. + """ + + def formula(person, period, parameters): + return where( + person("ssi_lives_in_medical_treatment_facility", period), + NHSSPLivingArrangement.NONE, + NHSSPLivingArrangement.INDEPENDENT, + ) diff --git a/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_other_income_deductions.py b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_other_income_deductions.py new file mode 100644 index 00000000000..c28f1139d85 --- /dev/null +++ b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_other_income_deductions.py @@ -0,0 +1,11 @@ +from policyengine_us.model_api import * + + +class nh_ssp_other_income_deductions(Variable): + value_type = float + entity = Person + label = "New Hampshire SSP other allowable income deductions" + definition_period = MONTH + unit = USD + reference = "https://gc.nh.gov/rules/state_agencies/he-w600.html" + documentation = """Verified court-ordered payments, garnishments, qualifying training expenses and dependent allocations under He-W 654.20 and 654.21. Include any approved additional ANB employment-plan disregard under He-W 654.15(c).""" diff --git a/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_resources_deemed_from_parents.py b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_resources_deemed_from_parents.py new file mode 100644 index 00000000000..7c62456b41a --- /dev/null +++ b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_resources_deemed_from_parents.py @@ -0,0 +1,29 @@ +from policyengine_us.model_api import * +from policyengine_us.variables.gov.states._ssp_parental_resources import ( + ssp_parental_resources, +) + + +class nh_ssp_resources_deemed_from_parents(Variable): + value_type = float + entity = Person + label = "New Hampshire ANB resources deemed from parents" + definition_period = MONTH + quantity_type = STOCK + unit = USD + defined_for = StateCode.NH + reference = "https://gc.nh.gov/rules/state_agencies/he-w600.html" + # He-W 652.03(i)-(j) adds the co-resident parents' resources above the federal + # one/two-parent allowance to a blind child's own resources. It does not divide that + # excess between siblings. Parent includes a biological, adoptive or stepparent + # under He-W 601.06(b). Override with the agency-determined amount for a different + # certified budget, temporary absence, or the month of the eighteenth birthday; + # annual age cannot identify that month. + + def formula(person, period, parameters): + _, _, excess = ssp_parental_resources(person, period, parameters) + return ( + person("is_child", period.this_year) + * person("is_blind", period.this_year) + * excess + ) diff --git a/policyengine_us/variables/household/income/spm_unit/spm_unit_benefits.py b/policyengine_us/variables/household/income/spm_unit/spm_unit_benefits.py index 41ead044f46..267a95d0dc2 100644 --- a/policyengine_us/variables/household/income/spm_unit/spm_unit_benefits.py +++ b/policyengine_us/variables/household/income/spm_unit/spm_unit_benefits.py @@ -22,6 +22,7 @@ def formula(spm_unit, period, parameters): "ky_ssp", # Kentucky benefits "de_ssp", # Delaware benefits "fl_oss", + "nh_ssp", "ks_sspp", # Kansas benefits "hi_oss", "la_oss", # Louisiana benefits From 9959d541b7e6b43303737ea11ffb7cdfc94aaa3c Mon Sep 17 00:00:00 2001 From: Ziming Date: Tue, 13 Oct 2026 00:58:38 -0400 Subject: [PATCH 02/10] Normalize New Hampshire SSP parameter and test formatting --- .../household/household_state_benefits.yaml | 1 + .../hud/annual_income/sources/unearned.yaml | 1 + .../states/nh/dhhs/ssp/couple_disregard.yaml | 9 +- .../gov/states/nh/dhhs/ssp/couple_need.yaml | 12 +- .../nh/dhhs/ssp/disabled_minimum_age.yaml | 10 +- .../dhhs/ssp/earned/aged_disabled_flat.yaml | 9 +- .../earned/aged_disabled_fraction_cap.yaml | 12 +- .../states/nh/dhhs/ssp/earned/blind_flat.yaml | 9 +- .../dhhs/ssp/earned/disregard_fraction.yaml | 7 +- .../earned/minimum_employment_expenses.yaml | 12 +- .../nh/dhhs/ssp/grant_reduction_fraction.yaml | 7 +- .../states/nh/dhhs/ssp/individual_need.yaml | 28 +- .../states/nh/dhhs/ssp/minimum_payment.yaml | 9 +- .../states/nh/dhhs/ssp/resource_limit.yaml | 7 +- .../states/nh/dhhs/ssp/single_disregard.yaml | 9 +- .../nh/dhhs/ssp/three_person_disregard.yaml | 9 +- .../states/nh/dhhs/ssp/three_person_need.yaml | 21 +- .../gov/states/nh/dhhs/ssp/integration.yaml | 157 +++---- .../gov/states/nh/dhhs/ssp/nh_ssp.yaml | 385 ++++++++---------- .../nh_ssp_resources_deemed_from_parents.yaml | 67 ++- 20 files changed, 349 insertions(+), 432 deletions(-) diff --git a/policyengine_us/parameters/gov/household/household_state_benefits.yaml b/policyengine_us/parameters/gov/household/household_state_benefits.yaml index 0ea7b407e22..bb1599ac884 100644 --- a/policyengine_us/parameters/gov/household/household_state_benefits.yaml +++ b/policyengine_us/parameters/gov/household/household_state_benefits.yaml @@ -405,6 +405,7 @@ values: - nj_property_tax_relief # New York benefits - ny_child_care_subsidies + metadata: unit: list period: year diff --git a/policyengine_us/parameters/gov/hud/annual_income/sources/unearned.yaml b/policyengine_us/parameters/gov/hud/annual_income/sources/unearned.yaml index 097fd002b1c..e60fb9e12f5 100644 --- a/policyengine_us/parameters/gov/hud/annual_income/sources/unearned.yaml +++ b/policyengine_us/parameters/gov/hud/annual_income/sources/unearned.yaml @@ -30,6 +30,7 @@ values: - disability_benefits - survivor_benefits - financial_assistance + metadata: unit: list period: year diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/couple_disregard.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/couple_disregard.yaml index 27e1af90f9d..1e98bbb3e22 100644 --- a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/couple_disregard.yaml +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/couple_disregard.yaml @@ -1,10 +1,11 @@ description: New Hampshire uses this couple disregard in its adult category cash assistance calculation. values: - '2026-01-01': 20 + 2026-01-01: 20 + metadata: unit: currency-USD + period: month label: New Hampshire SSP couple disregard reference: - - title: He-W 654.16, Adult standard disregard - href: https://gc.nh.gov/rules/state_agencies/he-w600.html - period: month + - title: He-W 654.16, Adult standard disregard + href: https://gc.nh.gov/rules/state_agencies/he-w600.html diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/couple_need.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/couple_need.yaml index 41e0f2a9143..6957c3fe109 100644 --- a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/couple_need.yaml +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/couple_need.yaml @@ -1,11 +1,11 @@ -description: New Hampshire sets this monthly standard of need for an individual living independently with - a spouse. +description: New Hampshire sets this monthly standard of need for an individual living independently with a spouse. values: - '2026-01-01': 1492 + 2026-01-01: 1_492 + metadata: unit: currency-USD + period: month label: New Hampshire SSP independent couple need standard reference: - - title: New Hampshire 2026 approved optional state supplement income standards, Section D and E - href: https://www.medicaid.gov/medicaid/spa/downloads/NH-26-0001.pdf - period: month + - title: New Hampshire 2026 approved optional state supplement income standards, Section D and E + href: https://www.medicaid.gov/medicaid/spa/downloads/NH-26-0001.pdf diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/disabled_minimum_age.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/disabled_minimum_age.yaml index fbfd15861d9..ea133b87ddd 100644 --- a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/disabled_minimum_age.yaml +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/disabled_minimum_age.yaml @@ -1,10 +1,10 @@ -description: New Hampshire requires disabled applicants to have reached this age for adult category cash - assistance. +description: New Hampshire requires disabled applicants to have reached this age for adult category cash assistance. values: - '2026-01-01': 18 + 2026-01-01: 18 + metadata: unit: year label: New Hampshire SSP minimum disabled age reference: - - title: RSA 167:6 VI - href: https://gc.nh.gov/rsa/html/XII/167/167-6.htm + - title: RSA 167:6 VI + href: https://gc.nh.gov/rsa/html/XII/167/167-6.htm diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/aged_disabled_flat.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/aged_disabled_flat.yaml index e78cf5c4b76..9b285a7ff9c 100644 --- a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/aged_disabled_flat.yaml +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/aged_disabled_flat.yaml @@ -1,10 +1,11 @@ description: New Hampshire uses this earned aged disabled flat in its adult category cash assistance calculation. values: - '2026-01-01': 20 + 2026-01-01: 20 + metadata: unit: currency-USD + period: month label: New Hampshire SSP earned aged disabled flat reference: - - title: He-W 654.15(f), Aged and disabled earned income disregard - href: https://gc.nh.gov/rules/state_agencies/he-w600.html - period: month + - title: He-W 654.15(f), Aged and disabled earned income disregard + href: https://gc.nh.gov/rules/state_agencies/he-w600.html diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/aged_disabled_fraction_cap.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/aged_disabled_fraction_cap.yaml index 3094fcab9f9..c13547fc48b 100644 --- a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/aged_disabled_fraction_cap.yaml +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/aged_disabled_fraction_cap.yaml @@ -1,11 +1,11 @@ -description: New Hampshire uses this earned aged disabled fraction cap in its adult category cash assistance - calculation. +description: New Hampshire uses this earned aged disabled fraction cap in its adult category cash assistance calculation. values: - '2026-01-01': 30 + 2026-01-01: 30 + metadata: unit: currency-USD + period: month label: New Hampshire SSP earned aged disabled fraction cap reference: - - title: He-W 654.15(f), Aged and disabled earned income disregard - href: https://gc.nh.gov/rules/state_agencies/he-w600.html - period: month + - title: He-W 654.15(f), Aged and disabled earned income disregard + href: https://gc.nh.gov/rules/state_agencies/he-w600.html diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/blind_flat.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/blind_flat.yaml index 689a9800ab2..aaeffaa03ae 100644 --- a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/blind_flat.yaml +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/blind_flat.yaml @@ -1,10 +1,11 @@ description: New Hampshire uses this earned blind flat in its adult category cash assistance calculation. values: - '2026-01-01': 85 + 2026-01-01: 85 + metadata: unit: currency-USD + period: month label: New Hampshire SSP earned blind flat reference: - - title: He-W 654.15(b), Blind earned income disregard - href: https://gc.nh.gov/rules/state_agencies/he-w600.html - period: month + - title: He-W 654.15(b), Blind earned income disregard + href: https://gc.nh.gov/rules/state_agencies/he-w600.html diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/disregard_fraction.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/disregard_fraction.yaml index 7b9117e8b6f..7053aa5ea23 100644 --- a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/disregard_fraction.yaml +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/disregard_fraction.yaml @@ -1,9 +1,10 @@ description: New Hampshire uses this earned disregard fraction in its adult category cash assistance calculation. values: - '2026-01-01': 0.5 + 2026-01-01: 0.5 + metadata: unit: /1 label: New Hampshire SSP earned disregard fraction reference: - - title: He-W 654.15, Earned income disregards - href: https://gc.nh.gov/rules/state_agencies/he-w600.html + - title: He-W 654.15, Earned income disregards + href: https://gc.nh.gov/rules/state_agencies/he-w600.html diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/minimum_employment_expenses.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/minimum_employment_expenses.yaml index 464729538b5..c7a083a4bb4 100644 --- a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/minimum_employment_expenses.yaml +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/minimum_employment_expenses.yaml @@ -1,11 +1,11 @@ -description: New Hampshire uses this earned minimum employment expenses in its adult category cash assistance - calculation. +description: New Hampshire uses this earned minimum employment expenses in its adult category cash assistance calculation. values: - '2026-01-01': 18 + 2026-01-01: 18 + metadata: unit: currency-USD + period: month label: New Hampshire SSP earned minimum employment expenses reference: - - title: He-W 654.18, Employment expenses - href: https://gc.nh.gov/rules/state_agencies/he-w600.html - period: month + - title: He-W 654.18, Employment expenses + href: https://gc.nh.gov/rules/state_agencies/he-w600.html diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/grant_reduction_fraction.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/grant_reduction_fraction.yaml index 98f66dc0d39..1ef86ce3cb2 100644 --- a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/grant_reduction_fraction.yaml +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/grant_reduction_fraction.yaml @@ -1,9 +1,10 @@ description: New Hampshire uses this grant reduction fraction in its adult category cash assistance calculation. values: - '2026-01-01': 0.3333333333333333 + 2026-01-01: 0.3333333333333333 + metadata: unit: /1 label: New Hampshire SSP grant reduction fraction reference: - - title: He-W 670.03(c), Grant reduction - href: https://gc.nh.gov/rules/state_agencies/he-w600.html + - title: He-W 670.03(c), Grant reduction + href: https://gc.nh.gov/rules/state_agencies/he-w600.html diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/individual_need.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/individual_need.yaml index 1e4e6352ab8..6274fe6ec8a 100644 --- a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/individual_need.yaml +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/individual_need.yaml @@ -1,23 +1,29 @@ -description: New Hampshire sets these monthly adult assistance standards of need for an individual in - each living arrangement. +description: New Hampshire sets these monthly adult assistance standards of need for an individual in each living arrangement. + metadata: unit: currency-USD period: month label: New Hampshire SSP individual need standard breakdown: - - nh_ssp_living_arrangement + - nh_ssp_living_arrangement reference: - - title: New Hampshire 2026 approved optional state supplement income standards, Section D and E - href: https://www.medicaid.gov/medicaid/spa/downloads/NH-26-0001.pdf + - title: New Hampshire 2026 approved optional state supplement income standards, Section D and E + href: https://www.medicaid.gov/medicaid/spa/downloads/NH-26-0001.pdf + INDEPENDENT: - '2026-01-01': 1008 + 2026-01-01: 1_008 + SUBSIDIZED_COMMUNITY_RESIDENCE: - '2026-01-01': 1070 + 2026-01-01: 1_070 + NONSUBSIDIZED_COMMUNITY_RESIDENCE: - '2026-01-01': 1130 + 2026-01-01: 1_130 + ENHANCED_FAMILY_CARE: - '2026-01-01': 1188 + 2026-01-01: 1_188 + RESIDENTIAL_CARE: - '2026-01-01': 1188 + 2026-01-01: 1_188 + NONE: - '2026-01-01': 0 + 2026-01-01: 0 diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/minimum_payment.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/minimum_payment.yaml index ffe89f197ea..9c70fa7dff1 100644 --- a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/minimum_payment.yaml +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/minimum_payment.yaml @@ -1,10 +1,11 @@ description: New Hampshire uses this minimum payment in its adult category cash assistance calculation. values: - '2026-01-01': 2 + 2026-01-01: 2 + metadata: unit: currency-USD + period: month label: New Hampshire SSP minimum payment reference: - - title: He-W 670.03(a), Determination of grant - href: https://gc.nh.gov/rules/state_agencies/he-w600.html - period: month + - title: He-W 670.03(a), Determination of grant + href: https://gc.nh.gov/rules/state_agencies/he-w600.html diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/resource_limit.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/resource_limit.yaml index 0d63ff486e8..b3a7be58b4e 100644 --- a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/resource_limit.yaml +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/resource_limit.yaml @@ -1,9 +1,10 @@ description: New Hampshire uses this resource limit in its adult category cash assistance calculation. values: - '2026-01-01': 1500 + 2026-01-01: 1_500 + metadata: unit: currency-USD label: New Hampshire SSP resource limit reference: - - title: He-W 656.06(b), Adult category resource limit - href: https://gc.nh.gov/rules/state_agencies/he-w600.html + - title: He-W 656.06(b), Adult category resource limit + href: https://gc.nh.gov/rules/state_agencies/he-w600.html diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/single_disregard.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/single_disregard.yaml index 1b12757a24a..6776cee043d 100644 --- a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/single_disregard.yaml +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/single_disregard.yaml @@ -1,10 +1,11 @@ description: New Hampshire uses this single disregard in its adult category cash assistance calculation. values: - '2026-01-01': 13 + 2026-01-01: 13 + metadata: unit: currency-USD + period: month label: New Hampshire SSP single disregard reference: - - title: He-W 654.16, Adult standard disregard - href: https://gc.nh.gov/rules/state_agencies/he-w600.html - period: month + - title: He-W 654.16, Adult standard disregard + href: https://gc.nh.gov/rules/state_agencies/he-w600.html diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/three_person_disregard.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/three_person_disregard.yaml index aa6e203cafc..0a87c3b1b36 100644 --- a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/three_person_disregard.yaml +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/three_person_disregard.yaml @@ -1,10 +1,11 @@ description: New Hampshire deducts this standard amount for an adult, spouse and needy essential person. values: - '2026-01-01': 25 + 2026-01-01: 25 + metadata: unit: currency-USD + period: month label: New Hampshire SSP three-person standard disregard reference: - - title: He-W 654.16(b)(3) - href: https://gc.nh.gov/rules/state_agencies/he-w600.html - period: month + - title: He-W 654.16(b)(3) + href: https://gc.nh.gov/rules/state_agencies/he-w600.html diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/three_person_need.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/three_person_need.yaml index 55b1ee1a24f..0ccd7752cce 100644 --- a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/three_person_need.yaml +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/three_person_need.yaml @@ -1,16 +1,15 @@ -description: 'New Hampshire uses this standard of need for an adult, spouse and needy essential person. - The 2026 value is calculated under He-W 658.03(e): the published 2025 standard of $1,934 plus the SSI - couple increase of $41 and essential-person increase of $14.' +description: 'New Hampshire uses this standard of need for an adult, spouse and needy essential person. The 2026 value is calculated under He-W 658.03(e): the published 2025 standard of $1,934 plus the SSI couple increase of $41 and essential-person increase of $14.' values: - '2026-01-01': 1989 + 2026-01-01: 1_989 + metadata: unit: currency-USD + period: month label: New Hampshire SSP three-person standard of need reference: - - title: He-W 658.03(e), COLA update method - href: https://gc.nh.gov/rules/state_agencies/he-w600.html - - title: DHHS Medicaid Budget Briefing Book, published 2025 standards, page 23 - href: https://gc.nh.gov/lba/budget/operating_budgets/2026-2027/HF_Division_III/DHHS_Medicaid_Briefing_Book_2-21-25.pdf#page=23 - - title: SSA 2026 federal payment amounts and COLA - href: https://www.ssa.gov/oact/cola/SSI.html - period: month + - title: He-W 658.03(e), COLA update method + href: https://gc.nh.gov/rules/state_agencies/he-w600.html + - title: DHHS Medicaid Budget Briefing Book, published 2025 standards, page 23 + href: https://gc.nh.gov/lba/budget/operating_budgets/2026-2027/HF_Division_III/DHHS_Medicaid_Briefing_Book_2-21-25.pdf#page=23 + - title: SSA 2026 federal payment amounts and COLA + href: https://www.ssa.gov/oact/cola/SSI.html diff --git a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/integration.yaml index 3ee2a8e1109..ecb26c41a4c 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/integration.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/integration.yaml @@ -3,156 +3,121 @@ absolute_error_margin: 0.01 input: people: - first: + person1: age: 65 - second: + person2: age: 65 marital_units: couple: - members: - - first - - second + members: [person1, person2] tax_units: unit: - members: - - first - - second + members: [person1, person2] households: household: - members: - - first - - second + members: [person1, person2] state_code: NH output: - nh_ssp: - - 10.5 - - 10.5 + nh_ssp: [10.5, 10.5] + - name: Case 2, nonapplicant spouse is included in needs. period: 2026-01 absolute_error_margin: 0.01 input: people: - first: + person1: age: 65 - second: + person2: age: 40 marital_units: couple: - members: - - first - - second + members: [person1, person2] tax_units: unit: - members: - - first - - second + members: [person1, person2] households: household: - members: - - first - - second + members: [person1, person2] state_code: NH output: - nh_ssp: - - 518 - - 0 + nh_ssp: [518, 0] + - name: Case 3, independent couple combined resources exceed limit. period: 2026-01 absolute_error_margin: 0.01 input: people: - first: + person1: age: 65 ssi_countable_resources: 750 - second: + person2: age: 65 ssi_countable_resources: 751 marital_units: couple: - members: - - first - - second + members: [person1, person2] tax_units: unit: - members: - - first - - second + members: [person1, person2] households: household: - members: - - first - - second + members: [person1, person2] state_code: NH output: - nh_ssp: - - 0 - - 0 + nh_ssp: [0, 0] + - name: Case 4, care spouses are individual assistance groups. period: 2026-01 absolute_error_margin: 0.01 input: people: - first: + person1: age: 65 nh_ssp_living_arrangement: RESIDENTIAL_CARE ssi_claim_is_joint: false - second: + person2: age: 65 nh_ssp_living_arrangement: RESIDENTIAL_CARE ssi_claim_is_joint: false marital_units: couple: - members: - - first - - second + members: [person1, person2] tax_units: unit: - members: - - first - - second + members: [person1, person2] households: household: - members: - - first - - second + members: [person1, person2] state_code: NH output: - nh_ssp: - - 207 - - 207 + nh_ssp: [207, 207] + - name: Case 5, two aged applicants receive separate earned disregards. period: 2026-01 absolute_error_margin: 0.01 input: people: - first: + person1: age: 65 - employment_income: 1200 - second: + employment_income: 1_200 + person2: age: 65 - employment_income: 1200 + employment_income: 1_200 marital_units: couple: - members: - - first - - second + members: [person1, person2] tax_units: unit: - members: - - first - - second + members: [person1, person2] households: household: - members: - - first - - second + members: [person1, person2] state_code: NH output: - nh_ssp: - - 7.5 - - 7.5 + nh_ssp: [7.5, 7.5] + - name: Case 6, annual independent grant and SNAP income. - period: '2026' + period: 2026 absolute_error_margin: 0.01 input: state_code: NH @@ -160,58 +125,46 @@ output: nh_ssp: 324 household_state_benefits: 324 - snap_unearned_income: 12252 - hud_unearned_income: 12252 -- name: Eligible couple and essential person share a three-person grant + snap_unearned_income: 12_252 + hud_unearned_income: 12_252 + +- name: Case 7, Eligible couple and essential person share a three-person grant. period: 2026-01 absolute_error_margin: 0.01 input: people: - a: + person1: age: 70 nh_ssp_has_essential_person: true - b: + person2: age: 70 marital_units: couple: - members: - - a - - b + members: [person1, person2] households: home: - members: - - a - - b + members: [person1, person2] state_code: NH output: - nh_ssp: - - 261.5 - - 261.5 - nh_ssp_countable_income: - - 1466 - - 1466 -- name: Three-person grant with a non-applicant spouse + nh_ssp: [261.5, 261.5] + nh_ssp_countable_income: [1_466, 1_466] + +- name: Case 8, Three-person grant with a non-applicant spouse. period: 2026-01 absolute_error_margin: 0.01 input: people: - a: + person1: age: 70 nh_ssp_has_essential_person: true - b: + person2: age: 40 marital_units: couple: - members: - - a - - b + members: [person1, person2] households: home: - members: - - a - - b + members: [person1, person2] state_code: NH output: - nh_ssp: - - 1020 - - 0 + nh_ssp: [1_020, 0] diff --git a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/nh_ssp.yaml b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/nh_ssp.yaml index 595e3f79ac5..ca777969c29 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/nh_ssp.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/nh_ssp.yaml @@ -6,6 +6,7 @@ age: 65 output: nh_ssp: 27 + - name: Case 2, certified subsidized_community_residence. period: 2026-01 absolute_error_margin: 0.01 @@ -15,6 +16,7 @@ nh_ssp_living_arrangement: SUBSIDIZED_COMMUNITY_RESIDENCE output: nh_ssp: 89 + - name: Case 3, certified nonsubsidized_community_residence. period: 2026-01 absolute_error_margin: 0.01 @@ -24,6 +26,7 @@ nh_ssp_living_arrangement: NONSUBSIDIZED_COMMUNITY_RESIDENCE output: nh_ssp: 149 + - name: Case 4, certified enhanced_family_care. period: 2026-01 absolute_error_margin: 0.01 @@ -33,6 +36,7 @@ nh_ssp_living_arrangement: ENHANCED_FAMILY_CARE output: nh_ssp: 207 + - name: Case 5, certified residential_care. period: 2026-01 absolute_error_margin: 0.01 @@ -42,24 +46,27 @@ nh_ssp_living_arrangement: RESIDENTIAL_CARE output: nh_ssp: 207 + - name: Case 6, resources at state limit. period: 2026-01 absolute_error_margin: 0.01 input: state_code: NH age: 65 - ssi_countable_resources: 1500 + ssi_countable_resources: 1_500 output: nh_ssp: 27 + - name: Case 7, resources exceed state limit despite federal eligibility. period: 2026-01 absolute_error_margin: 0.01 input: state_code: NH age: 65 - ssi_countable_resources: 1501 + ssi_countable_resources: 1_501 output: nh_ssp: 0 + - name: Case 8, twenty dollars of Social Security reduces state grant. period: 2026-01 absolute_error_margin: 0.01 @@ -69,42 +76,47 @@ social_security_retirement: 240 output: nh_ssp: 7 + - name: Case 9, state only benefit. period: 2026-01 absolute_error_margin: 0.01 input: state_code: NH age: 65 - social_security_retirement: 12216 + social_security_retirement: 12_216 output: nh_ssp: 3 + - name: Case 10, positive dollar amount raised to state minimum. period: 2026-01 absolute_error_margin: 0.01 input: state_code: NH age: 65 - nh_ssp_countable_income: 1007 + nh_ssp_countable_income: 1_007 output: nh_ssp: 2 + - name: Case 11, income at standard. period: 2026-01 absolute_error_margin: 0.01 input: state_code: NH age: 65 - nh_ssp_countable_income: 1008 + nh_ssp_countable_income: 1_008 output: nh_ssp: 0 + - name: Case 12, aged employment rules. period: 2026-01 absolute_error_margin: 0.01 input: state_code: NH age: 65 - employment_income: 1200 + employment_income: 1_200 output: nh_ssp: 3 + - name: Case 13, blind employment rules. period: 2026-01 absolute_error_margin: 0.01 @@ -112,19 +124,21 @@ state_code: NH age: 40 is_blind: true - employment_income: 1200 + employment_income: 1_200 output: nh_ssp: 27 + - name: Case 14, verified employment expenses above minimum. period: 2026-01 absolute_error_margin: 0.01 input: state_code: NH age: 65 - employment_income: 1200 + employment_income: 1_200 nh_ssp_employment_expenses: 50 output: nh_ssp: 35 + - name: Case 15, other allowed deductions. period: 2026-01 absolute_error_margin: 0.01 @@ -134,6 +148,7 @@ nh_ssp_other_income_deductions: 25 output: nh_ssp: 52 + - name: Case 16, independently determined one third grant reduction. period: 2026-01 absolute_error_margin: 0.01 @@ -143,6 +158,7 @@ nh_ssp_grant_reduction_applies: true output: nh_ssp: 18 + - name: Case 17, federal disability alone does not establish forty eight month duration. period: 2026-01 absolute_error_margin: 0.01 @@ -152,6 +168,7 @@ meets_ssi_disability_criteria: true output: nh_ssp: 0 + - name: Case 18, permanently disabled adult. period: 2026-01 absolute_error_margin: 0.01 @@ -162,6 +179,7 @@ is_permanently_and_totally_disabled: true output: nh_ssp: 27 + - name: Case 19, blind child. period: 2026-01 absolute_error_margin: 0.01 @@ -171,6 +189,7 @@ is_blind: true output: nh_ssp: 27 + - name: Case 20, disabled child without blindness. period: 2026-01 absolute_error_margin: 0.01 @@ -181,6 +200,7 @@ is_permanently_and_totally_disabled: true output: nh_ssp: 0 + - name: Case 21, nonresident. period: 2026-01 absolute_error_margin: 0.01 @@ -189,6 +209,7 @@ age: 65 output: nh_ssp: 0 + - name: Case 22, required federal benefit application declined. period: 2026-01 absolute_error_margin: 0.01 @@ -198,6 +219,7 @@ takes_up_ssi_if_eligible: false output: nh_ssp: 0 + - name: Case 23, excluded living arrangement. period: 2026-01 absolute_error_margin: 0.01 @@ -207,7 +229,8 @@ nh_ssp_living_arrangement: NONE output: nh_ssp: 0 -- name: Single recipient and certified essential person use group size two + +- name: Case 24, Single recipient and certified essential person use group size two. period: 2026-01 absolute_error_margin: 0.01 input: @@ -217,7 +240,8 @@ nh_ssp_has_essential_person: true output: nh_ssp: 518 -- name: Essential person income is added before the group disregard + +- name: Case 25, Essential person income is added before the group disregard. period: 2026-01 absolute_error_margin: 0.01 input: @@ -228,7 +252,8 @@ nh_ssp_essential_person_countable_income: 100 output: nh_ssp: 418 -- name: Essential person resources are counted even when recipient receives SSI + +- name: Case 26, Essential person resources are counted even when recipient receives SSI. period: 2026-01 absolute_error_margin: 0.01 input: @@ -236,11 +261,12 @@ age: 70 ssi: 994 nh_ssp_has_essential_person: true - ssi_countable_resources: 1000 + ssi_countable_resources: 1_000 nh_ssp_essential_person_resources: 501 output: nh_ssp: 0 -- name: Essential person resource limit is inclusive + +- name: Case 27, Essential person resource limit is inclusive. period: 2026-01 absolute_error_margin: 0.01 input: @@ -248,11 +274,12 @@ age: 70 ssi: 994 nh_ssp_has_essential_person: true - ssi_countable_resources: 1000 + ssi_countable_resources: 1_000 nh_ssp_essential_person_resources: 500 output: nh_ssp: 518 -- name: Care facilities remain single-person groups + +- name: Case 28, Care facilities remain single-person groups. period: 2026-01 absolute_error_margin: 0.01 input: @@ -264,7 +291,8 @@ nh_ssp_essential_person_countable_income: 100 output: nh_ssp: 207 -- name: Uncertified caregiver does not increase the standard + +- name: Case 29, Uncertified caregiver does not increase the standard. period: 2026-01 absolute_error_margin: 0.01 input: @@ -274,8 +302,8 @@ nh_ssp_has_essential_person: false output: nh_ssp: 27 -- name: Group standard disregard does not turn excess essential-person income into - eligibility + +- name: Case 30, Group standard disregard does not turn excess essential-person income into eligibility. period: 2026-01 absolute_error_margin: 0.01 input: @@ -286,336 +314,269 @@ nh_ssp_essential_person_countable_income: 518 output: nh_ssp: 0 -- name: Annual essential-person resource input stays a balance in each month - period: '2026' + +- name: Case 31, Annual essential-person resource input stays a balance in each month. + period: 2026 absolute_error_margin: 0.01 input: state_code: NH age: 70 ssi: 994 nh_ssp_has_essential_person: true - ssi_countable_resources: 1000 + ssi_countable_resources: 1_000 nh_ssp_essential_person_resources: 501 output: nh_ssp: 0 # He-W 652.03(i)-(j),(q): full parental excess, NH $1500 ceiling, and adult control. # https://gc.nh.gov/rules/state_agencies/he-w600.html -- name: Blind child is ineligible with excess co-resident parent resources +- name: Case 32, Blind child is ineligible with excess co-resident parent resources. period: 2026-06 absolute_error_margin: 0.01 input: people: - parent1: + person1: age: - '2026': 40 + 2026: 40 person_id: - '2026': 1 + 2026: 1 bank_account_assets: - '2026': 10000 - child1: + 2026: 10_000 + person2: age: - '2026': 10 + 2026: 10 person_id: - '2026': 3 + 2026: 3 parent_1_id: - '2026': 1 + 2026: 1 is_blind: - '2026': true + 2026: true marital_units: parent1: - members: - - parent1 + members: [person1] child1: - members: - - child1 + members: [person2] + families: + family: + members: [person1, person2] tax_units: parent1: - members: - - parent1 + members: [person1] child1: - members: - - child1 - families: - family: - members: - - parent1 - - child1 + members: [person2] spm_units: unit: - members: - - parent1 - - child1 + members: [person1, person2] households: home: - members: - - parent1 - - child1 + members: [person1, person2] state_code: - '2026': NH + 2026: NH output: - nh_ssp: - - 0 - - 0 -- name: Parental allowance plus the NH child resource ceiling is inclusive + nh_ssp: [0, 0] + +- name: Case 33, Parental allowance plus the NH child resource ceiling is inclusive. period: 2026-06 absolute_error_margin: 0.01 input: people: - parent1: + person1: age: - '2026': 40 + 2026: 40 person_id: - '2026': 1 + 2026: 1 bank_account_assets: - '2026': 3500 - child1: + 2026: 3_500 + person2: age: - '2026': 10 + 2026: 10 person_id: - '2026': 3 + 2026: 3 parent_1_id: - '2026': 1 + 2026: 1 is_blind: - '2026': true + 2026: true marital_units: parent1: - members: - - parent1 + members: [person1] child1: - members: - - child1 + members: [person2] + families: + family: + members: [person1, person2] tax_units: parent1: - members: - - parent1 + members: [person1] child1: - members: - - child1 - families: - family: - members: - - parent1 - - child1 + members: [person2] spm_units: unit: - members: - - parent1 - - child1 + members: [person1, person2] households: home: - members: - - parent1 - - child1 + members: [person1, person2] state_code: - '2026': NH + 2026: NH output: - nh_ssp: - - 0 - - 27 -- name: One cent above the parent allowance and NH resource ceiling is ineligible + nh_ssp: [0, 27] + +- name: Case 34, One cent above the parent allowance and NH resource ceiling is ineligible. period: 2026-06 absolute_error_margin: 0.01 input: people: - parent1: + person1: age: - '2026': 40 + 2026: 40 person_id: - '2026': 1 + 2026: 1 bank_account_assets: - '2026': 3500.01 - child1: + 2026: 3_500.01 + person2: age: - '2026': 10 + 2026: 10 person_id: - '2026': 3 + 2026: 3 parent_1_id: - '2026': 1 + 2026: 1 is_blind: - '2026': true + 2026: true marital_units: parent1: - members: - - parent1 + members: [person1] child1: - members: - - child1 + members: [person2] + families: + family: + members: [person1, person2] tax_units: parent1: - members: - - parent1 + members: [person1] child1: - members: - - child1 - families: - family: - members: - - parent1 - - child1 + members: [person2] spm_units: unit: - members: - - parent1 - - child1 + members: [person1, person2] households: home: - members: - - parent1 - - child1 + members: [person1, person2] state_code: - '2026': NH + 2026: NH output: - nh_ssp: - - 0 - - 0 -- name: A blind adult does not receive deemed parental resources + nh_ssp: [0, 0] + +- name: Case 35, A blind adult does not receive deemed parental resources. period: 2026-06 absolute_error_margin: 0.01 input: people: - parent1: + person1: age: - '2026': 40 + 2026: 40 person_id: - '2026': 1 + 2026: 1 bank_account_assets: - '2026': 10000 - child1: + 2026: 10_000 + person2: age: - '2026': 19 + 2026: 19 person_id: - '2026': 3 + 2026: 3 parent_1_id: - '2026': 1 + 2026: 1 is_blind: - '2026': true + 2026: true marital_units: parent1: - members: - - parent1 + members: [person1] child1: - members: - - child1 + members: [person2] + families: + family: + members: [person1, person2] tax_units: parent1: - members: - - parent1 + members: [person1] child1: - members: - - child1 - families: - family: - members: - - parent1 - - child1 + members: [person2] spm_units: unit: - members: - - parent1 - - child1 + members: [person1, person2] households: home: - members: - - parent1 - - child1 + members: [person1, person2] state_code: - '2026': NH + 2026: NH output: - nh_ssp: - - 0 - - 27 -- name: Each blind sibling receives the full excess under the NH rule + nh_ssp: [0, 27] + +- name: Case 36, Each blind sibling receives the full excess under the NH rule. period: 2026-06 absolute_error_margin: 0.01 input: people: - parent1: + person1: age: - '2026': 40 + 2026: 40 person_id: - '2026': 1 + 2026: 1 bank_account_assets: - '2026': 5500 - parent2: + 2026: 5_500 + person2: age: - '2026': 40 + 2026: 40 person_id: - '2026': 2 - child1: + 2026: 2 + person3: age: - '2026': 10 + 2026: 10 person_id: - '2026': 3 + 2026: 3 parent_1_id: - '2026': 1 + 2026: 1 is_blind: - '2026': true + 2026: true parent_2_id: - '2026': 2 - child2: + 2026: 2 + person4: age: - '2026': 10 + 2026: 10 person_id: - '2026': 4 + 2026: 4 parent_1_id: - '2026': 1 + 2026: 1 is_blind: - '2026': true + 2026: true parent_2_id: - '2026': 2 + 2026: 2 marital_units: parent1: - members: - - parent1 + members: [person1] parent2: - members: - - parent2 + members: [person2] child1: - members: - - child1 + members: [person3] child2: - members: - - child2 + members: [person4] + families: + family: + members: [person1, person2, person3, person4] tax_units: parent1: - members: - - parent1 + members: [person1] parent2: - members: - - parent2 + members: [person2] child1: - members: - - child1 + members: [person3] child2: - members: - - child2 - families: - family: - members: - - parent1 - - parent2 - - child1 - - child2 + members: [person4] spm_units: unit: - members: - - parent1 - - parent2 - - child1 - - child2 + members: [person1, person2, person3, person4] households: home: - members: - - parent1 - - parent2 - - child1 - - child2 + members: [person1, person2, person3, person4] state_code: - '2026': NH + 2026: NH output: - nh_ssp: - - 0 - - 0 - - 0 - - 0 + nh_ssp: [0, 0, 0, 0] diff --git a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/nh_ssp_resources_deemed_from_parents.yaml b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/nh_ssp_resources_deemed_from_parents.yaml index c79fd3b4565..296b15f6335 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/nh_ssp_resources_deemed_from_parents.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/nh_ssp_resources_deemed_from_parents.yaml @@ -1,71 +1,58 @@ # Resource balances and certified budgets are stocks. Annual demographic and asset inputs are explicit. -- name: Annual asset balances remain undivided in January and July +- name: Case 1, Annual asset balances remain undivided in January and July. period: 2026 absolute_error_margin: 0.01 input: people: - parent1: + person1: age: - '2026': 40 + 2026: 40 person_id: - '2026': 1 + 2026: 1 bank_account_assets: - '2026': 10000 - child1: + 2026: 10_000 + person2: age: - '2026': 10 + 2026: 10 person_id: - '2026': 3 + 2026: 3 parent_1_id: - '2026': 1 + 2026: 1 is_blind: - '2026': true + 2026: true marital_units: parent1: - members: - - parent1 + members: [person1] child1: - members: - - child1 + members: [person2] + families: + family: + members: [person1, person2] tax_units: parent1: - members: - - parent1 + members: [person1] child1: - members: - - child1 - families: - family: - members: - - parent1 - - child1 + members: [person2] spm_units: unit: - members: - - parent1 - - child1 + members: [person1, person2] households: home: - members: - - parent1 - - child1 + members: [person1, person2] state_code: - '2026': NH + 2026: NH output: nh_ssp_resources_deemed_from_parents: - 2026-01: - - 0 - - 8000 - 2026-07: - - 0 - - 8000 -- name: Annual agency-certified resource budget remains a monthly stock + 2026-01: [0, 8_000] + 2026-07: [0, 8_000] + +- name: Case 2, Annual agency-certified resource budget remains a monthly stock. period: 2026 absolute_error_margin: 0.01 input: state_code: NH - nh_ssp_resources_deemed_from_parents: 2500 + nh_ssp_resources_deemed_from_parents: 2_500 output: nh_ssp_resources_deemed_from_parents: - 2026-01: 2500 - 2026-07: 2500 + 2026-01: 2_500 + 2026-07: 2_500 From 1ce21c3e7bc4516c091b13269dffdd3d3d57230c Mon Sep 17 00:00:00 2001 From: Ziming Date: Tue, 13 Oct 2026 02:52:35 -0400 Subject: [PATCH 03/10] Fix issues from review: New Hampshire SSP immigrant rule, minimum grant and parental resources - Apply He-W 616.02's five-year entry rule instead of SSI's 40-quarter test - Pay nothing when the grant is below the $2 minimum (He-W 670.03(a)(4)) - Deem parental resources through the federal pool, which counts stepparents; drop the shared helper - Couple status from the SSI spouse signal; couple grant reduction independent of member order - Derive employment expenses and support deductions from existing variables - Registry placement and comments, SNAP reference title, shorter programs.yaml note, reference locators - Tests for the immigrant rule, minimum grant, stepparent, spouse earnings and couple cases Co-Authored-By: Claude Opus 5.5 --- .../household/household_state_benefits.yaml | 12 +- .../states/nh/dhhs/ssp/couple_disregard.yaml | 4 +- .../gov/states/nh/dhhs/ssp/couple_need.yaml | 8 +- .../dhhs/ssp/earned/aged_disabled_flat.yaml | 4 +- .../earned/aged_disabled_fraction_cap.yaml | 11 -- ...aged_disabled_remainder_disregard_cap.yaml | 11 ++ .../states/nh/dhhs/ssp/earned/blind_flat.yaml | 4 +- .../dhhs/ssp/earned/disregard_fraction.yaml | 4 +- .../earned/minimum_employment_expenses.yaml | 4 +- .../nh/dhhs/ssp/grant_reduction_fraction.yaml | 4 +- .../dhhs/ssp/immigration/exempt_statuses.yaml | 18 ++ .../dhhs/ssp/immigration/waiting_period.yaml | 13 ++ .../states/nh/dhhs/ssp/individual_need.yaml | 4 +- .../states/nh/dhhs/ssp/minimum_payment.yaml | 4 +- .../states/nh/dhhs/ssp/resource_limit.yaml | 2 +- .../states/nh/dhhs/ssp/single_disregard.yaml | 4 +- .../states/nh/dhhs/ssp/three_person_need.yaml | 2 +- .../usda/snap/income/sources/unearned.yaml | 4 +- policyengine_us/programs.yaml | 12 +- .../gov/states/nh/dhhs/ssp/integration.yaml | 119 ++++++++++- .../gov/states/nh/dhhs/ssp/nh_ssp.yaml | 184 +++++++++++++++--- .../nh_ssp_resources_deemed_from_parents.yaml | 58 +++++- .../gov/states/_ssp_parental_resources.py | 76 -------- .../gov/states/nh/dhhs/ssp/_nh_ssp_couple.py | 26 +++ .../gov/states/nh/dhhs/ssp/nh_ssp.py | 26 ++- .../nh/dhhs/ssp/nh_ssp_countable_income.py | 39 ++-- .../gov/states/nh/dhhs/ssp/nh_ssp_eligible.py | 38 +++- .../nh/dhhs/ssp/nh_ssp_employment_expenses.py | 6 +- .../nh/dhhs/ssp/nh_ssp_living_arrangement.py | 3 +- .../ssp/nh_ssp_other_income_deductions.py | 4 +- .../nh_ssp_resources_deemed_from_parents.py | 14 +- .../income/spm_unit/spm_unit_benefits.py | 2 +- 32 files changed, 524 insertions(+), 200 deletions(-) delete mode 100644 policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/aged_disabled_fraction_cap.yaml create mode 100644 policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/aged_disabled_remainder_disregard_cap.yaml create mode 100644 policyengine_us/parameters/gov/states/nh/dhhs/ssp/immigration/exempt_statuses.yaml create mode 100644 policyengine_us/parameters/gov/states/nh/dhhs/ssp/immigration/waiting_period.yaml delete mode 100644 policyengine_us/variables/gov/states/_ssp_parental_resources.py create mode 100644 policyengine_us/variables/gov/states/nh/dhhs/ssp/_nh_ssp_couple.py diff --git a/policyengine_us/parameters/gov/household/household_state_benefits.yaml b/policyengine_us/parameters/gov/household/household_state_benefits.yaml index bb1599ac884..466af75f757 100644 --- a/policyengine_us/parameters/gov/household/household_state_benefits.yaml +++ b/policyengine_us/parameters/gov/household/household_state_benefits.yaml @@ -65,6 +65,8 @@ values: - ok_child_care_subsidies # South Carolina benefits - sc_child_care_subsidies + # New Hampshire benefits + - nh_ssp # New Mexico benefits - nm_ssi_state_supplement # South Carolina benefits @@ -78,7 +80,6 @@ values: # DC benefits - dc_ossp # Kansas benefits - - nh_ssp - ks_sspp # Hawaii benefits - hi_oss @@ -158,6 +159,8 @@ values: - nv_child_care_subsidies # Oklahoma benefits - ok_child_care_subsidies + # New Hampshire benefits + - nh_ssp # New Mexico benefits - nm_ssi_state_supplement # South Carolina benefits @@ -177,7 +180,6 @@ values: # DC benefits - dc_ossp # Kansas benefits - - nh_ssp - ks_sspp # Hawaii benefits - hi_oss @@ -261,6 +263,8 @@ values: - nv_child_care_subsidies # Oklahoma benefits - ok_child_care_subsidies + # New Hampshire benefits + - nh_ssp # New Mexico benefits - nm_ssi_state_supplement # South Carolina benefits @@ -281,7 +285,6 @@ values: - dc_ossp - dc_child_care_subsidies # Kansas benefits - - nh_ssp - ks_sspp # Hawaii benefits - hi_oss @@ -365,6 +368,8 @@ values: - nv_child_care_subsidies # Oklahoma benefits - ok_child_care_subsidies + # New Hampshire benefits + - nh_ssp # New Mexico benefits - nm_ssi_state_supplement # South Carolina benefits @@ -385,7 +390,6 @@ values: - dc_ossp - dc_child_care_subsidies # Kansas benefits - - nh_ssp - ks_sspp # Hawaii benefits - hi_oss diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/couple_disregard.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/couple_disregard.yaml index 1e98bbb3e22..db2c052f2fb 100644 --- a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/couple_disregard.yaml +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/couple_disregard.yaml @@ -1,11 +1,11 @@ -description: New Hampshire uses this couple disregard in its adult category cash assistance calculation. +description: New Hampshire deducts this amount from the income of a two-person assistance group under the adult category financial assistance program. values: 2026-01-01: 20 metadata: unit: currency-USD period: month - label: New Hampshire SSP couple disregard + label: New Hampshire SSP two-person standard disregard reference: - title: He-W 654.16, Adult standard disregard href: https://gc.nh.gov/rules/state_agencies/he-w600.html diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/couple_need.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/couple_need.yaml index 6957c3fe109..e5d4dcc3140 100644 --- a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/couple_need.yaml +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/couple_need.yaml @@ -1,11 +1,11 @@ -description: New Hampshire sets this monthly standard of need for an individual living independently with a spouse. +description: New Hampshire sets this standard of need for a two-person independent-living assistance group under the adult category financial assistance program. values: 2026-01-01: 1_492 metadata: unit: currency-USD period: month - label: New Hampshire SSP independent couple need standard + label: New Hampshire SSP independent two-person need standard reference: - - title: New Hampshire 2026 approved optional state supplement income standards, Section D and E - href: https://www.medicaid.gov/medicaid/spa/downloads/NH-26-0001.pdf + - title: New Hampshire 2026 approved optional state supplement income standards, Section D + href: https://www.medicaid.gov/medicaid/spa/downloads/NH-26-0001.pdf#page=14 diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/aged_disabled_flat.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/aged_disabled_flat.yaml index 9b285a7ff9c..291f5261d0c 100644 --- a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/aged_disabled_flat.yaml +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/aged_disabled_flat.yaml @@ -1,11 +1,11 @@ -description: New Hampshire uses this earned aged disabled flat in its adult category cash assistance calculation. +description: New Hampshire excludes this amount of monthly gross earnings under the Old Age Assistance and Aid to the Permanently and Totally Disabled programs. values: 2026-01-01: 20 metadata: unit: currency-USD period: month - label: New Hampshire SSP earned aged disabled flat + label: New Hampshire SSP aged and disabled flat earned income disregard reference: - title: He-W 654.15(f), Aged and disabled earned income disregard href: https://gc.nh.gov/rules/state_agencies/he-w600.html diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/aged_disabled_fraction_cap.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/aged_disabled_fraction_cap.yaml deleted file mode 100644 index c13547fc48b..00000000000 --- a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/aged_disabled_fraction_cap.yaml +++ /dev/null @@ -1,11 +0,0 @@ -description: New Hampshire uses this earned aged disabled fraction cap in its adult category cash assistance calculation. -values: - 2026-01-01: 30 - -metadata: - unit: currency-USD - period: month - label: New Hampshire SSP earned aged disabled fraction cap - reference: - - title: He-W 654.15(f), Aged and disabled earned income disregard - href: https://gc.nh.gov/rules/state_agencies/he-w600.html diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/aged_disabled_remainder_disregard_cap.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/aged_disabled_remainder_disregard_cap.yaml new file mode 100644 index 00000000000..03ec3ff8942 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/aged_disabled_remainder_disregard_cap.yaml @@ -0,0 +1,11 @@ +description: New Hampshire limits the disregard of remaining earnings to this amount under the Old Age Assistance and Aid to the Permanently and Totally Disabled programs. +values: + 2026-01-01: 30 + +metadata: + unit: currency-USD + period: month + label: New Hampshire SSP aged and disabled remaining earnings disregard cap + reference: + - title: He-W 654.15(f), Aged and disabled earned income disregard + href: https://gc.nh.gov/rules/state_agencies/he-w600.html diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/blind_flat.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/blind_flat.yaml index aaeffaa03ae..64f49087f5e 100644 --- a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/blind_flat.yaml +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/blind_flat.yaml @@ -1,11 +1,11 @@ -description: New Hampshire uses this earned blind flat in its adult category cash assistance calculation. +description: New Hampshire excludes this amount of monthly gross earnings under the Aid to the Needy Blind program. values: 2026-01-01: 85 metadata: unit: currency-USD period: month - label: New Hampshire SSP earned blind flat + label: New Hampshire SSP blind flat earned income disregard reference: - title: He-W 654.15(b), Blind earned income disregard href: https://gc.nh.gov/rules/state_agencies/he-w600.html diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/disregard_fraction.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/disregard_fraction.yaml index 7053aa5ea23..409f85089f7 100644 --- a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/disregard_fraction.yaml +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/disregard_fraction.yaml @@ -1,10 +1,10 @@ -description: New Hampshire uses this earned disregard fraction in its adult category cash assistance calculation. +description: New Hampshire excludes this share of earnings above the flat disregard under the adult category financial assistance program. values: 2026-01-01: 0.5 metadata: unit: /1 - label: New Hampshire SSP earned disregard fraction + label: New Hampshire SSP remaining earnings disregard rate reference: - title: He-W 654.15, Earned income disregards href: https://gc.nh.gov/rules/state_agencies/he-w600.html diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/minimum_employment_expenses.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/minimum_employment_expenses.yaml index c7a083a4bb4..2901f0b8e16 100644 --- a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/minimum_employment_expenses.yaml +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/minimum_employment_expenses.yaml @@ -1,11 +1,11 @@ -description: New Hampshire uses this earned minimum employment expenses in its adult category cash assistance calculation. +description: New Hampshire deducts at least this amount of employment expenses under the Old Age Assistance and Aid to the Permanently and Totally Disabled programs. values: 2026-01-01: 18 metadata: unit: currency-USD period: month - label: New Hampshire SSP earned minimum employment expenses + label: New Hampshire SSP minimum employment expense disregard reference: - title: He-W 654.18, Employment expenses href: https://gc.nh.gov/rules/state_agencies/he-w600.html diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/grant_reduction_fraction.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/grant_reduction_fraction.yaml index 1ef86ce3cb2..8d5a17f7749 100644 --- a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/grant_reduction_fraction.yaml +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/grant_reduction_fraction.yaml @@ -1,10 +1,10 @@ -description: New Hampshire uses this grant reduction fraction in its adult category cash assistance calculation. +description: New Hampshire deducts this share of the grant for recipients subject to the grant reduction under the adult category financial assistance program. values: 2026-01-01: 0.3333333333333333 metadata: unit: /1 - label: New Hampshire SSP grant reduction fraction + label: New Hampshire SSP grant reduction rate reference: - title: He-W 670.03(c), Grant reduction href: https://gc.nh.gov/rules/state_agencies/he-w600.html diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/immigration/exempt_statuses.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/immigration/exempt_statuses.yaml new file mode 100644 index 00000000000..ee759516115 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/immigration/exempt_statuses.yaml @@ -0,0 +1,18 @@ +description: New Hampshire excludes these immigration statuses from the qualified alien waiting period under the adult category financial assistance program. +values: + # Amerasian immigrants, COFA migrants, qualifying military noncitizens, + # certain Native Americans and trafficking victims are also eligible without + # restriction but have no immigration_status value. + 2026-01-01: + - REFUGEE + - ASYLEE + - CUBAN_HAITIAN_ENTRANT + - DEPORTATION_WITHHELD + +metadata: + unit: list + period: year + label: New Hampshire SSP immigration statuses without a waiting period + reference: + - title: NH DHHS Adult Assistance Manual 305.11, Qualified Aliens Eligible Without Restriction + href: https://dhhs.nh.gov/aam_htm/html/305_11_qualified_aliens_eligible_without_restriction_aam.htm diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/immigration/waiting_period.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/immigration/waiting_period.yaml new file mode 100644 index 00000000000..1dcf9f32474 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/immigration/waiting_period.yaml @@ -0,0 +1,13 @@ +description: New Hampshire sets this number of years after entry as the qualified alien waiting period under the adult category financial assistance program. +values: + 2026-01-01: 5 + +metadata: + unit: year + period: year + label: New Hampshire SSP qualified alien waiting period + reference: + - title: He-W 616.02(a)(2), Eligibility of Qualified Aliens + href: https://gc.nh.gov/rules/state_agencies/he-w600.html + - title: NH DHHS Adult Assistance Manual 305.13, Qualified Aliens with Restricted Eligibility Based on Date of Entry into the U.S. + href: https://dhhs.nh.gov/aam_htm/html/305_13_qualified_aliens_with_restricted_eligibility_based_on_date_of_entry_into_the_us_aam.htm diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/individual_need.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/individual_need.yaml index 6274fe6ec8a..61ac88cce24 100644 --- a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/individual_need.yaml +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/individual_need.yaml @@ -7,8 +7,8 @@ metadata: breakdown: - nh_ssp_living_arrangement reference: - - title: New Hampshire 2026 approved optional state supplement income standards, Section D and E - href: https://www.medicaid.gov/medicaid/spa/downloads/NH-26-0001.pdf + - title: "New Hampshire 2026 approved optional state supplement income standards, Section D and E #page 14-16" + href: https://www.medicaid.gov/medicaid/spa/downloads/NH-26-0001.pdf#page=14 INDEPENDENT: 2026-01-01: 1_008 diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/minimum_payment.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/minimum_payment.yaml index 9c70fa7dff1..33bfab0d73d 100644 --- a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/minimum_payment.yaml +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/minimum_payment.yaml @@ -1,11 +1,11 @@ -description: New Hampshire uses this minimum payment in its adult category cash assistance calculation. +description: New Hampshire provides no payment when the rounded grant is below this amount under the adult category financial assistance program. values: 2026-01-01: 2 metadata: unit: currency-USD period: month - label: New Hampshire SSP minimum payment + label: New Hampshire SSP minimum grant reference: - title: He-W 670.03(a), Determination of grant href: https://gc.nh.gov/rules/state_agencies/he-w600.html diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/resource_limit.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/resource_limit.yaml index b3a7be58b4e..90537813cb0 100644 --- a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/resource_limit.yaml +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/resource_limit.yaml @@ -1,4 +1,4 @@ -description: New Hampshire uses this resource limit in its adult category cash assistance calculation. +description: New Hampshire limits countable resources to this amount under the adult category financial assistance program. values: 2026-01-01: 1_500 diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/single_disregard.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/single_disregard.yaml index 6776cee043d..14bfc597507 100644 --- a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/single_disregard.yaml +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/single_disregard.yaml @@ -1,11 +1,11 @@ -description: New Hampshire uses this single disregard in its adult category cash assistance calculation. +description: New Hampshire deducts this amount from the income of a one-person assistance group under the adult category financial assistance program. values: 2026-01-01: 13 metadata: unit: currency-USD period: month - label: New Hampshire SSP single disregard + label: New Hampshire SSP one-person standard disregard reference: - title: He-W 654.16, Adult standard disregard href: https://gc.nh.gov/rules/state_agencies/he-w600.html diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/three_person_need.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/three_person_need.yaml index 0ccd7752cce..a36627d4a14 100644 --- a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/three_person_need.yaml +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/three_person_need.yaml @@ -9,7 +9,7 @@ metadata: reference: - title: He-W 658.03(e), COLA update method href: https://gc.nh.gov/rules/state_agencies/he-w600.html - - title: DHHS Medicaid Budget Briefing Book, published 2025 standards, page 23 + - title: DHHS Medicaid Budget Briefing Book, published 2025 standards href: https://gc.nh.gov/lba/budget/operating_budgets/2026-2027/HF_Division_III/DHHS_Medicaid_Briefing_Book_2-21-25.pdf#page=23 - title: SSA 2026 federal payment amounts and COLA href: https://www.ssa.gov/oact/cola/SSI.html diff --git a/policyengine_us/parameters/gov/usda/snap/income/sources/unearned.yaml b/policyengine_us/parameters/gov/usda/snap/income/sources/unearned.yaml index f2c1e0baebe..231ccac073b 100644 --- a/policyengine_us/parameters/gov/usda/snap/income/sources/unearned.yaml +++ b/policyengine_us/parameters/gov/usda/snap/income/sources/unearned.yaml @@ -36,7 +36,6 @@ values: - hi_oss - id_aabd - in_ssp - - nh_ssp - ks_sspp - ky_ssp - la_oss @@ -47,6 +46,7 @@ values: - mn_msa_person - mo_ssp - ne_aabd + - nh_ssp - nm_ssi_state_supplement - sc_ssi_state_supplement - tx_ssi_state_supplement @@ -96,7 +96,7 @@ values: metadata: reference: - - title: 7 CFR 273.9(b)(2) and (c)(1), (5) + - title: 7 CFR 273.9(b)(2) and (c)(1) href: https://www.law.cornell.edu/cfr/text/7/273.9 - title: POMS SI 01401.001 General Information about State Supplementation href: https://secure.ssa.gov/poms.nsf/lnx/0501401001 diff --git a/policyengine_us/programs.yaml b/policyengine_us/programs.yaml index 04d51e7c2ec..844bef87bdc 100644 --- a/policyengine_us/programs.yaml +++ b/policyengine_us/programs.yaml @@ -1097,15 +1097,9 @@ programs: variable: nh_ssp parameter_prefix: gov.states.nh.dhhs.ssp verified_years: '2026' - notes: Models the 2026 individual and couple need standards, certified community care, - state income disregards, resource limit, rounding and grant reduction. State medical - decisions, specialized deductions, care placement and no-SNAP grant reductions require - explicit inputs. Blind children include full co-resident parental resource - excess; certified exceptions and eighteenth-birthday month treatment require - a deemed-resource input. Needy essential-person groups use a certified caregiver income/resource - budget. The three-person 2026 need standard is derived under He-W 658.03(e) - from the published 2025 standard and SSI COLA increases. Conditional resources, - sanctions and grandfathered benefits are not modeled. + notes: Models 2026 adult category cash assistance (OAA, ANB and APTD) for independent + living, certified community care, couples and needy essential persons. Conditional + resources, sanctions and grandfathered benefits are not modeled. - id: social_security name: Social Security diff --git a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/integration.yaml index ecb26c41a4c..aa0810f29f8 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/integration.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/integration.yaml @@ -18,6 +18,12 @@ members: [person1, person2] state_code: NH output: + # Joint claim: 1,491 couple rate / 2 = 745.5 each. + ssi: [745.5, 745.5] + nh_ssp_eligible: [true, true] + # 745.5 + 745.5 - 20 two-person disregard = 1,471. + nh_ssp_countable_income: [1_471, 1_471] + # 1,492 - 1,471 = 21, split between two recipients. nh_ssp: [10.5, 10.5] - name: Case 2, nonapplicant spouse is included in needs. @@ -40,6 +46,12 @@ members: [person1, person2] state_code: NH output: + # The spouse has no income to deem, so person1 receives the individual rate. + ssi: [994, 0] + nh_ssp_eligible: [true, false] + # 994 - 20 two-person disregard = 974. + nh_ssp_countable_income: [974, 974] + # 1,492 two-person standard - 974 = 518. nh_ssp: [518, 0] - name: Case 3, independent couple combined resources exceed limit. @@ -64,6 +76,10 @@ members: [person1, person2] state_code: NH output: + # 750 + 751 = 1,501 <= 3,000 federal couple limit. + ssi: [745.5, 745.5] + # 1,501 > 1,500 state limit. + nh_ssp_eligible: [false, false] nh_ssp: [0, 0] - name: Case 4, care spouses are individual assistance groups. @@ -90,6 +106,11 @@ members: [person1, person2] state_code: NH output: + # Separate claims: individual rate each. + ssi: [994, 994] + # 994 - 13 one-person disregard = 981. + nh_ssp_countable_income: [981, 981] + # 1,188 residential care standard - 981 = 207. nh_ssp: [207, 207] - name: Case 5, two aged applicants receive separate earned disregards. @@ -114,6 +135,13 @@ members: [person1, person2] state_code: NH output: + # Couple earnings 200: (200 - 85) * 0.5 / 2 = 28.75; 745.5 - 28.75 = 716.75. + ssi: [716.75, 716.75] + # FICA 1,200 * 0.0765 / 12 = 7.65, below the $18 minimum. + nh_ssp_employment_expenses: [7.65, 7.65] + # Each 100 - 20 - 30 - 18 = 32; 32 + 32 + 716.75 + 716.75 - 20 = 1,477.5. + nh_ssp_countable_income: [1_477.5, 1_477.5] + # 1,492 - 1,477.5 = 14.5, rounded to 15 and split. nh_ssp: [7.5, 7.5] - name: Case 6, annual independent grant and SNAP income. @@ -123,12 +151,18 @@ state_code: NH age: 65 output: + # 994 * 12 = 11,928. + ssi: 11_928 + # (994 - 13) * 12 = 11,772. + nh_ssp_countable_income: 11_772 + # (1,008 - 981) * 12 = 324. nh_ssp: 324 household_state_benefits: 324 + # 11,928 SSI + 324 state supplement = 12,252. snap_unearned_income: 12_252 hud_unearned_income: 12_252 -- name: Case 7, Eligible couple and essential person share a three-person grant. +- name: Case 7, eligible couple and essential person share a three-person grant. period: 2026-01 absolute_error_margin: 0.01 input: @@ -146,10 +180,13 @@ members: [person1, person2] state_code: NH output: + ssi: [745.5, 745.5] + # 1,989 three-person standard - 1,466 = 523, split between two recipients. nh_ssp: [261.5, 261.5] + # 745.5 + 745.5 - 25 three-person disregard = 1,466. nh_ssp_countable_income: [1_466, 1_466] -- name: Case 8, Three-person grant with a non-applicant spouse. +- name: Case 8, three-person grant with a non-applicant spouse. period: 2026-01 absolute_error_margin: 0.01 input: @@ -167,4 +204,82 @@ members: [person1, person2] state_code: NH output: + ssi: [994, 0] + # 994 - 25 three-person disregard = 969. + nh_ssp_countable_income: [969, 969] + # 1,989 three-person standard - 969 = 1,020. nh_ssp: [1_020, 0] + +- name: Case 9, nonapplicant spouse's part-time earnings are combined with the applicant's. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 67 + person2: + age: 60 + # 20 hours a week at the $14.56 New Hampshire median wage for + # cashiers (BLS OEWS, May 2023): 20 * 52 * 14.56 = 15,142.40. + employment_income: 15_142.4 + marital_units: + couple: + members: [person1, person2] + tax_units: + unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NH + output: + # Spousal deeming: (1,261.87 - 85) * 0.5 = 588.43; 1,491 - 588.43 = 902.57. + ssi: [902.57, 0] + # FICA: 15,142.40 * 0.0765 / 12 = 96.53. + nh_ssp_employment_expenses: [0, 96.53] + nh_ssp_eligible: [true, false] + # He-W 654.02(d): combined earnings 1,261.87 - 20 - 30 - 96.53 = 1,115.33; + # 1,115.33 + 902.57 SSI - 20 two-person disregard = 1,997.90. + nh_ssp_countable_income: [1_997.9, 1_997.9] + # 1,997.90 exceeds the 1,492 two-person standard. + nh_ssp: [0, 0] + +- name: Case 10, parental income deemed to a blind child counts as unearned income. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 38 + person_id: 1 + # Full time at the $22.23 New Hampshire median wage for general + # office clerks (BLS OEWS, May 2023): 2,080 * 22.23 = 46,238.40. + employment_income: 46_238.4 + person2: + age: 10 + person_id: 2 + parent_1_id: 1 + is_blind: true + marital_units: + parent: + members: [person1] + child: + members: [person2] + tax_units: + unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NH + output: + # (3,853.20 - 85) * 0.5 = 1,884.10 - 994 parent allocation = 890.10. + ssi_unearned_income_deemed_from_ineligible_parent: [0, 890.1] + # 994 - (890.10 - 20) = 123.90. + ssi: [0, 123.9] + nh_ssp_eligible: [false, true] + # person1: 3,853.20 - 20 - 30 - 294.77 FICA - 13 = 3,495.43. + # person2, He-W 652.03(f)-(g): 890.10 + 123.90 - 13 = 1,001. + nh_ssp_countable_income: [3_495.43, 1_001] + # 1,008 - 1,001 = 7. + nh_ssp: [0, 7] diff --git a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/nh_ssp.yaml b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/nh_ssp.yaml index ca777969c29..99f75c6ad83 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/nh_ssp.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/nh_ssp.yaml @@ -7,7 +7,7 @@ output: nh_ssp: 27 -- name: Case 2, certified subsidized_community_residence. +- name: Case 2, certified subsidized community residence. period: 2026-01 absolute_error_margin: 0.01 input: @@ -17,7 +17,7 @@ output: nh_ssp: 89 -- name: Case 3, certified nonsubsidized_community_residence. +- name: Case 3, certified nonsubsidized community residence. period: 2026-01 absolute_error_margin: 0.01 input: @@ -27,7 +27,7 @@ output: nh_ssp: 149 -- name: Case 4, certified enhanced_family_care. +- name: Case 4, certified enhanced family care. period: 2026-01 absolute_error_margin: 0.01 input: @@ -37,7 +37,7 @@ output: nh_ssp: 207 -- name: Case 5, certified residential_care. +- name: Case 5, certified residential care. period: 2026-01 absolute_error_margin: 0.01 input: @@ -87,7 +87,7 @@ output: nh_ssp: 3 -- name: Case 10, positive dollar amount raised to state minimum. +- name: Case 10, grant below state minimum is not paid. period: 2026-01 absolute_error_margin: 0.01 input: @@ -95,7 +95,8 @@ age: 65 nh_ssp_countable_income: 1_007 output: - nh_ssp: 2 + # 1,008 - 1,007 = 1, below the $2 minimum of He-W 670.03(a)(4): no payment. + nh_ssp: 0 - name: Case 11, income at standard. period: 2026-01 @@ -128,26 +129,45 @@ output: nh_ssp: 27 -- name: Case 14, verified employment expenses above minimum. +- name: Case 14, payroll taxes above the minimum employment expense are deducted. period: 2026-01 absolute_error_margin: 0.01 input: state_code: NH - age: 65 - employment_income: 1_200 - nh_ssp_employment_expenses: 50 - output: - nh_ssp: 35 - -- name: Case 15, other allowed deductions. + age: 40 + meets_ssi_disability_criteria: true + is_permanently_and_totally_disabled: true + nh_ssp_living_arrangement: ENHANCED_FAMILY_CARE + # Supported employment, 10 hours a week at the $7.25 minimum wage + # (RSA 279:21 adopts the federal rate): 10 * 52 * 7.25 = 3,770. + employment_income: 3_770 + output: + # SSI: 994 - (3,770 / 12 - 85) * 0.5 = 994 - 114.58 = 879.42. + ssi: 879.42 + # FICA: 3,770 * 0.0765 / 12 = 24.03, above the $18 minimum. + nh_ssp_employment_expenses: 24.03 + # Earned: 314.17 - 20 - 30 - 24.03 = 240.13; 240.13 + 879.42 - 13 = 1,106.55. + nh_ssp_countable_income: 1_106.55 + # 1,188 - 1,106.55 = 81.45, rounded to 81. + nh_ssp: 81 + +- name: Case 15, court-ordered child support is deducted. period: 2026-01 absolute_error_margin: 0.01 input: state_code: NH - age: 65 - nh_ssp_other_income_deductions: 25 + age: 40 + meets_ssi_disability_criteria: true + is_permanently_and_totally_disabled: true + # The $50 monthly minimum support order of RSA 458-C:2, V: 50 * 12 = 600. + child_support_expense: 600 output: - nh_ssp: 52 + # 600 / 12 = 50 under He-W 654.20(a)(1). + nh_ssp_other_income_deductions: 50 + # 994 SSI - 13 disregard - 50 support = 931. + nh_ssp_countable_income: 931 + # 1,008 - 931 = 77. + nh_ssp: 77 - name: Case 16, independently determined one third grant reduction. period: 2026-01 @@ -230,7 +250,7 @@ output: nh_ssp: 0 -- name: Case 24, Single recipient and certified essential person use group size two. +- name: Case 24, single recipient and certified essential person use group size two. period: 2026-01 absolute_error_margin: 0.01 input: @@ -241,7 +261,7 @@ output: nh_ssp: 518 -- name: Case 25, Essential person income is added before the group disregard. +- name: Case 25, essential person income is added before the group disregard. period: 2026-01 absolute_error_margin: 0.01 input: @@ -253,7 +273,7 @@ output: nh_ssp: 418 -- name: Case 26, Essential person resources are counted even when recipient receives SSI. +- name: Case 26, essential person resources are counted even when recipient receives SSI. period: 2026-01 absolute_error_margin: 0.01 input: @@ -266,7 +286,7 @@ output: nh_ssp: 0 -- name: Case 27, Essential person resource limit is inclusive. +- name: Case 27, essential person resource limit is inclusive. period: 2026-01 absolute_error_margin: 0.01 input: @@ -279,7 +299,7 @@ output: nh_ssp: 518 -- name: Case 28, Care facilities remain single-person groups. +- name: Case 28, care facilities remain single-person groups. period: 2026-01 absolute_error_margin: 0.01 input: @@ -292,7 +312,7 @@ output: nh_ssp: 207 -- name: Case 29, Uncertified caregiver does not increase the standard. +- name: Case 29, uncertified caregiver does not increase the standard. period: 2026-01 absolute_error_margin: 0.01 input: @@ -303,7 +323,7 @@ output: nh_ssp: 27 -- name: Case 30, Group standard disregard does not turn excess essential-person income into eligibility. +- name: Case 30, group standard disregard does not turn excess essential-person income into eligibility. period: 2026-01 absolute_error_margin: 0.01 input: @@ -315,22 +335,24 @@ output: nh_ssp: 0 -- name: Case 31, Annual essential-person resource input stays a balance in each month. +- name: Case 31, annual essential-person resource input stays a balance in each month. period: 2026 absolute_error_margin: 0.01 input: state_code: NH age: 70 - ssi: 994 + # The monthly SSI of 994 summed over the year: 994 * 12 = 11,928. + ssi: 11_928 nh_ssp_has_essential_person: true ssi_countable_resources: 1_000 nh_ssp_essential_person_resources: 501 output: + # 1,000 + 501 = 1,501 > 1,500 in every month. nh_ssp: 0 # He-W 652.03(i)-(j),(q): full parental excess, NH $1500 ceiling, and adult control. # https://gc.nh.gov/rules/state_agencies/he-w600.html -- name: Case 32, Blind child is ineligible with excess co-resident parent resources. +- name: Case 32, blind child is ineligible with excess co-resident parent resources. period: 2026-06 absolute_error_margin: 0.01 input: @@ -375,7 +397,7 @@ output: nh_ssp: [0, 0] -- name: Case 33, Parental allowance plus the NH child resource ceiling is inclusive. +- name: Case 33, parental allowance plus the NH child resource ceiling is inclusive. period: 2026-06 absolute_error_margin: 0.01 input: @@ -420,7 +442,7 @@ output: nh_ssp: [0, 27] -- name: Case 34, One cent above the parent allowance and NH resource ceiling is ineligible. +- name: Case 34, one cent above the parent allowance and NH resource ceiling is ineligible. period: 2026-06 absolute_error_margin: 0.01 input: @@ -465,7 +487,7 @@ output: nh_ssp: [0, 0] -- name: Case 35, A blind adult does not receive deemed parental resources. +- name: Case 35, a blind adult does not receive deemed parental resources. period: 2026-06 absolute_error_margin: 0.01 input: @@ -510,7 +532,7 @@ output: nh_ssp: [0, 27] -- name: Case 36, Each blind sibling receives the full excess under the NH rule. +- name: Case 36, each blind sibling receives the full excess under the NH rule. period: 2026-06 absolute_error_margin: 0.01 input: @@ -580,3 +602,103 @@ 2026: NH output: nh_ssp: [0, 0, 0, 0] + +# He-W 616.02(a) and AAM 305.11-305.13: five-year rule instead of SSI's 40 quarters. +- name: Case 37, permanent resident past the five-year wait without forty quarters. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NH + age: 70 + immigration_status: LEGAL_PERMANENT_RESIDENT + years_since_us_entry: 10 + ssi_qualifying_quarters_earnings: 0 + output: + # 0 of the 40 qualifying quarters SSI requires, so no SSI. + ssi: 0 + # 10 years since entry >= 5-year waiting period. + nh_ssp_eligible: true + # max(0 + 0 - 13, 0) = 0 countable; 1,008 - 0 = 1,008. + nh_ssp: 1_008 + +- name: Case 38, permanent resident within the five-year wait is ineligible. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NH + age: 70 + immigration_status: LEGAL_PERMANENT_RESIDENT + # Default 40 qualifying quarters, which SSI's rule would accept. + years_since_us_entry: 2 + output: + # 2 years since entry < 5-year waiting period. + nh_ssp_eligible: false + nh_ssp: 0 + +- name: Case 39, refugee is eligible without a waiting period. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NH + age: 70 + immigration_status: REFUGEE + years_since_us_entry: 1 + output: + # Refugees are SSI qualified noncitizens. + ssi: 994 + # AAM 305.11 exempts refugees from the waiting period. + nh_ssp_eligible: true + # 994 - 13 = 981 countable; 1,008 - 981 = 27. + nh_ssp: 27 + +- name: Case 40, parent and adult child in a default marital unit use an individual budget. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + person_id: 1 + person2: + age: 40 + person_id: 2 + parent_1_id: 1 + households: + household: + members: [person1, person2] + state_code: NH + output: + # The omitted marital units put both people in one default unit; the + # parent link rules out a spouse, so each is a one-person group. + ssi: [994, 0] + # person1: 994 - 13 = 981; person2: max(0 - 13, 0) = 0. + nh_ssp_countable_income: [981, 0] + # 1,008 - 981 = 27; person2 is not aged, blind or disabled. + nh_ssp: [27, 0] + +- name: Case 41, grant reduction flag on either spouse reduces the couple grant. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 65 + person2: + age: 65 + nh_ssp_grant_reduction_applies: true + marital_units: + couple: + members: [person1, person2] + tax_units: + unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NH + output: + # 745.5 SSI each: 745.5 + 745.5 - 20 = 1,471 for the couple. + nh_ssp_countable_income: [1_471, 1_471] + # 1,492 - 1,471 = 21; 21 * 2 / 3 = 14 for the couple, whichever spouse has + # the flag; 14 / 2 = 7 each. + nh_ssp: [7, 7] diff --git a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/nh_ssp_resources_deemed_from_parents.yaml b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/nh_ssp_resources_deemed_from_parents.yaml index 296b15f6335..db5ff5254a6 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/nh_ssp_resources_deemed_from_parents.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/nh_ssp_resources_deemed_from_parents.yaml @@ -1,5 +1,5 @@ # Resource balances and certified budgets are stocks. Annual demographic and asset inputs are explicit. -- name: Case 1, Annual asset balances remain undivided in January and July. +- name: Case 1, annual asset balances remain undivided in January and July. period: 2026 absolute_error_margin: 0.01 input: @@ -46,7 +46,7 @@ 2026-01: [0, 8_000] 2026-07: [0, 8_000] -- name: Case 2, Annual agency-certified resource budget remains a monthly stock. +- name: Case 2, annual agency-certified resource budget remains a monthly stock. period: 2026 absolute_error_margin: 0.01 input: @@ -56,3 +56,57 @@ nh_ssp_resources_deemed_from_parents: 2026-01: 2_500 2026-07: 2_500 + +# He-W 601.06(b) counts a stepparent as a parent, so the federal pool adds the +# named mother's co-resident spouse. +- name: Case 3, stepparent resources are deemed with the named parent's resources. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: + 2026: 38 + person_id: + 2026: 1 + bank_account_assets: + 2026: 2_000 + person2: + age: + 2026: 40 + person_id: + 2026: 2 + bank_account_assets: + 2026: 2_000 + person3: + age: + 2026: 10 + person_id: + 2026: 3 + parent_1_id: + 2026: 1 + is_blind: + 2026: true + bank_account_assets: + 2026: 600 + marital_units: + parents: + members: [person1, person2] + child: + members: [person3] + tax_units: + unit: + members: [person1, person2, person3] + households: + home: + members: [person1, person2, person3] + state_code: + 2026: NH + output: + # Mother 2,000 + stepfather 2,000 = 4,000 - 3,000 two-parent allowance = 1,000. + nh_ssp_resources_deemed_from_parents: [0, 0, 1_000] + # Federal SSI: 600 + 1,000 = 1,600 <= 2,000, so the child receives 994. + ssi: [0, 0, 994] + # NH: 600 + 1,000 = 1,600 > 1,500 resource limit. + nh_ssp_eligible: [false, false, false] + nh_ssp: [0, 0, 0] diff --git a/policyengine_us/variables/gov/states/_ssp_parental_resources.py b/policyengine_us/variables/gov/states/_ssp_parental_resources.py deleted file mode 100644 index b2d76b4a130..00000000000 --- a/policyengine_us/variables/gov/states/_ssp_parental_resources.py +++ /dev/null @@ -1,76 +0,0 @@ -"""Co-resident parental resources shared by state supplement calculations.""" - -import numpy as np - -from policyengine_us.variables.household.demographic.person._parent_links import ( - co_resident_parent_indices, - has_parent_ids, - household_member_indices, - unlinked_parent, -) - - -def ssp_parental_resources(person, period, parameters, exclude_ssi_parents=False): - """Return the parent pair and resources above its SSI allowance. - - Explicit links identify natural, adoptive and step parents in this - household. Without a child's links, use only explicitly identified - unlinked parents in the same family and household. More than two such - candidates requires parent links or a certified deemed-resource input. - """ - year = period.this_year - first, second = co_resident_parent_indices(person, year) - unlinked = ~has_parent_ids(person, year) - parent = unlinked_parent(person, year) - family = person.family.reference_entity.members_entity_id - own_row = np.arange(person.count) - candidates = np.zeros(person.count, dtype=int) - fallback_first = np.full(person.count, -1, dtype=int) - fallback_second = np.full(person.count, -1, dtype=int) - for member in household_member_indices(person): - match = ( - (member >= 0) - & (member != own_row) - & parent[member] - & (family[member] == family) - ) - fallback_first = np.where(match & (candidates == 0), member, fallback_first) - fallback_second = np.where(match & (candidates == 1), member, fallback_second) - candidates = candidates + match - usable = unlinked & (candidates <= 2) - first = np.where(usable, fallback_first, first) - second = np.where(usable, fallback_second, second) - # Sorting makes sibling membership independent of the parent-slot order. - first, second = np.minimum(first, second), np.maximum(first, second) - resources = person("ssi_countable_resources", year).astype(np.float64) - if exclude_ssi_parents: - resources = np.where(person("ssi", period) > 0, 0, resources) - total = np.where(first >= 0, resources[first], 0) + np.where( - second >= 0, resources[second], 0 - ) - parents = (first >= 0).astype(int) + (second >= 0) - limit = parameters(period).gov.ssa.ssi.eligibility.resources.limit - allowance = np.where(parents > 1, limit.couple, limit.individual) - return first, second, np.maximum(total - allowance, 0) - - -def ssp_sibling_resource_share(person, first, second, excess, candidates, own, limit): - """Allocate to otherwise eligible children, removing resource failures. - - SI 01330.200/.280 require reallocation when a child's own resources - plus their share disqualify them. Children with different parent sets - do not reduce one another's deemed resources. - """ - eligible = candidates & (own <= limit) - share = excess.copy() - for _ in range(int(np.max(person.household.nb_persons(), initial=0)) + 1): - count = np.zeros(person.count, dtype=int) - for member in household_member_indices(person): - same_parents = (first == first[member]) & (second == second[member]) - count = count + ((member >= 0) & same_parents & eligible[member]) - share = excess / np.maximum(count, 1) - remaining = eligible & (own + share <= limit) - if np.array_equal(remaining, eligible): - break - eligible = remaining - return share diff --git a/policyengine_us/variables/gov/states/nh/dhhs/ssp/_nh_ssp_couple.py b/policyengine_us/variables/gov/states/nh/dhhs/ssp/_nh_ssp_couple.py new file mode 100644 index 00000000000..2b0d069ea58 --- /dev/null +++ b/policyengine_us/variables/gov/states/nh/dhhs/ssp/_nh_ssp_couple.py @@ -0,0 +1,26 @@ +"""Couples that share one New Hampshire adult category assistance group.""" + +import numpy as np + +from policyengine_us.variables.gov.ssa.ssi.eligibility.resources.deemed._ssi_spouses import ( + _ssi_spouse_index, +) + + +def nh_ssp_spouse(person, period): + """Row of each person's co-resident spouse in a shared group, or -1. + + Spouses share a group only when both live independently; care categories + are one-person groups (SPA NH-26-0001 Section E). The SSI spouse test + keeps a default marital unit from pairing a parent with their child. + """ + arrangement = person("nh_ssp_living_arrangement", period) + independent = arrangement == arrangement.possible_values.INDEPENDENT + spouse = _ssi_spouse_index(person, period) + shared = independent & (spouse >= 0) & independent[np.maximum(spouse, 0)] + return np.where(shared, spouse, -1) + + +def spouse_value(values, spouse, default=0): + """Each person's spouse's value, or the default without a spouse.""" + return np.where(spouse >= 0, values[np.maximum(spouse, 0)], default) diff --git a/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp.py b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp.py index d904dd5f616..c5c5f56063e 100644 --- a/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp.py +++ b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp.py @@ -1,4 +1,8 @@ from policyengine_us.model_api import * +from policyengine_us.variables.gov.states.nh.dhhs.ssp._nh_ssp_couple import ( + nh_ssp_spouse, + spouse_value, +) class nh_ssp(Variable): @@ -9,7 +13,8 @@ class nh_ssp(Variable): unit = USD defined_for = "nh_ssp_eligible" reference = ( - "https://www.medicaid.gov/medicaid/spa/downloads/NH-26-0001.pdf", + # PDF pages 14-16 + "https://www.medicaid.gov/medicaid/spa/downloads/NH-26-0001.pdf#page=14", "https://gc.nh.gov/rules/state_agencies/he-w600.html", ) @@ -17,9 +22,11 @@ def formula(person, period, parameters): p = parameters(period).gov.states.nh.dhhs.ssp arrangement = person("nh_ssp_living_arrangement", period) independent = arrangement == arrangement.possible_values.INDEPENDENT - couple = independent & (person.marital_unit.sum(independent) == 2) - essential = independent & person.marital_unit.any( - person("nh_ssp_has_essential_person", period) + spouse = nh_ssp_spouse(person, period) + couple = spouse >= 0 + has_essential_person = person("nh_ssp_has_essential_person", period) + essential = independent & ( + has_essential_person | spouse_value(has_essential_person, spouse, False) ) standard = where(couple, p.couple_need, p.individual_need[arrangement]) standard = where( @@ -27,8 +34,13 @@ def formula(person, period, parameters): ) income = person("nh_ssp_countable_income", period) grant = np.floor(max_(standard - income, 0) + 0.5) - grant = where(grant > 0, max_(grant, p.minimum_payment), 0) + # He-W 670.03(a)(4): no payment when the rounded grant is below the minimum. + grant = where(grant >= p.minimum_payment, grant, 0) + # He-W 670.03(c) reduces the group grant, so either spouse's flag applies. reduction = person("nh_ssp_grant_reduction_applies", period) + reduction = reduction | spouse_value(reduction, spouse, False) grant = np.floor(grant * (1 - reduction * p.grant_reduction_fraction) + 0.5) - recipients = person.marital_unit.sum(person("nh_ssp_eligible", period)) - return grant / where(couple, max_(recipients, 1), 1) + # Applicant spouses split the couple's grant. + eligible = person("nh_ssp_eligible", period) + recipients = eligible.astype(int) + spouse_value(eligible, spouse, False) + return grant / max_(recipients, 1) diff --git a/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_countable_income.py b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_countable_income.py index 52b9957e883..fa57ef3eae1 100644 --- a/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_countable_income.py +++ b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_countable_income.py @@ -1,4 +1,8 @@ from policyengine_us.model_api import * +from policyengine_us.variables.gov.states.nh.dhhs.ssp._nh_ssp_couple import ( + nh_ssp_spouse, + spouse_value, +) class nh_ssp_countable_income(Variable): @@ -7,6 +11,7 @@ class nh_ssp_countable_income(Variable): label = "New Hampshire adult assistance group countable income" definition_period = MONTH unit = USD + defined_for = StateCode.NH reference = "https://gc.nh.gov/rules/state_agencies/he-w600.html" documentation = "Income for the whole assistance group; a couple shares one grant." @@ -14,20 +19,21 @@ def formula(person, period, parameters): p = parameters(period).gov.states.nh.dhhs.ssp arrangement = person("nh_ssp_living_arrangement", period) independent = arrangement == arrangement.possible_values.INDEPENDENT - couple = independent & (person.marital_unit.sum(independent) == 2) - essential = independent & person.marital_unit.any( - person("nh_ssp_has_essential_person", period) - ) - both_applicants = ( - person.marital_unit.sum(person("nh_ssp_eligible", period)) == 2 + spouse = nh_ssp_spouse(person, period) + couple = spouse >= 0 + has_essential_person = person("nh_ssp_has_essential_person", period) + essential = independent & ( + has_essential_person | spouse_value(has_essential_person, spouse, False) ) + eligible = person("nh_ssp_eligible", period) + both_applicants = eligible & spouse_value(eligible, spouse, False) earned = max_(person("ssi_earned_income", period), 0) expenses = max_(person("nh_ssp_employment_expenses", period), 0) # With a nonapplicant spouse, combine earnings before the applicant's # category disregard under He-W 654.02(d)-(e). combined = couple & ~both_applicants - earned = where(combined, person.marital_unit.sum(earned), earned) - expenses = where(combined, person.marital_unit.sum(expenses), expenses) + earned = where(combined, earned + spouse_value(earned, spouse), earned) + expenses = where(combined, expenses + spouse_value(expenses, spouse), expenses) blind = person("is_blind", period.this_year) blind_net = max_(earned - p.earned.blind_flat, 0) * ( 1 - p.earned.disregard_fraction @@ -37,27 +43,30 @@ def formula(person, period, parameters): remaining - min_( remaining * p.earned.disregard_fraction, - p.earned.aged_disabled_fraction_cap, + p.earned.aged_disabled_remainder_disregard_cap, ) - max_(expenses, p.earned.minimum_employment_expenses), 0, ) net_earned = where(blind, blind_net, aged_disabled_net) net_earned = where( - couple & both_applicants, person.marital_unit.sum(net_earned), net_earned + both_applicants, net_earned + spouse_value(net_earned, spouse), net_earned ) unearned = max_(person("ssi_unearned_income", period), 0) + person( "ssi", period ) - # Blind children use the parental allocation defined in He-W 641.04. + # Blind children use the parental allocation in He-W 652.03(f)-(g). unearned = unearned + person( "ssi_unearned_income_deemed_from_ineligible_parent", period ) - unearned = where(couple, person.marital_unit.sum(unearned), unearned) + unearned = unearned + spouse_value(unearned, spouse) other = max_(person("nh_ssp_other_income_deductions", period), 0) - other = where(couple, person.marital_unit.sum(other), other) - unearned = unearned + essential * person.marital_unit.max( - max_(person("nh_ssp_essential_person_countable_income", period), 0) + other = other + spouse_value(other, spouse) + essential_income = max_( + person("nh_ssp_essential_person_countable_income", period), 0 + ) + unearned = unearned + essential * max_( + essential_income, spouse_value(essential_income, spouse) ) disregard = where( essential & couple, diff --git a/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_eligible.py b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_eligible.py index 1ed9d9c16e7..75e72a552c7 100644 --- a/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_eligible.py +++ b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_eligible.py @@ -1,4 +1,8 @@ from policyengine_us.model_api import * +from policyengine_us.variables.gov.states.nh.dhhs.ssp._nh_ssp_couple import ( + nh_ssp_spouse, + spouse_value, +) class nh_ssp_eligible(Variable): @@ -10,6 +14,8 @@ class nh_ssp_eligible(Variable): reference = ( "https://gc.nh.gov/rsa/html/XII/167/167-6.htm", "https://gc.nh.gov/rules/state_agencies/he-w600.html", + "https://dhhs.nh.gov/aam_htm/html/305_11_qualified_aliens_eligible_without_restriction_aam.htm", + "https://dhhs.nh.gov/aam_htm/html/305_13_qualified_aliens_with_restricted_eligibility_based_on_date_of_entry_into_the_us_aam.htm", ) def formula(person, period, parameters): @@ -23,23 +29,39 @@ def formula(person, period, parameters): arrangement = person("nh_ssp_living_arrangement", period) la = arrangement.possible_values independent = arrangement == la.INDEPENDENT - couple = independent & (person.marital_unit.sum(independent) == 2) - essential = independent & person.marital_unit.any( - person("nh_ssp_has_essential_person", period) + spouse = nh_ssp_spouse(person, period) + has_essential_person = person("nh_ssp_has_essential_person", period) + essential = independent & ( + has_essential_person | spouse_value(has_essential_person, spouse, False) ) resources = person("ssi_countable_resources", period.this_year) - resources = where(couple, person.marital_unit.sum(resources), resources) + resources = resources + spouse_value(resources, spouse) resources = resources + person("nh_ssp_resources_deemed_from_parents", period) - resources = resources + essential * person.marital_unit.max( - max_(person("nh_ssp_essential_person_resources", period), 0) + essential_resources = max_( + person("nh_ssp_essential_person_resources", period), 0 ) + resources = resources + essential * max_( + essential_resources, spouse_value(essential_resources, spouse) + ) + # He-W 616.02(a): qualified aliens under 8 USC 1641(b) are eligible once + # the waiting period since entry has elapsed, which also covers entry + # before August 22, 1996. AAM 305.11 exempts the listed statuses; AAM + # 305.13 applies the wait to permanent residents regardless of work + # history, so SSI's 40-quarter rule does not apply. immigration = person("immigration_status", period.this_year) citizen = immigration == immigration.possible_values.CITIZEN - immigrant = person("is_ssi_qualified_noncitizen", period.this_year) + exempt = np.isin(immigration.decode_to_str(), p.immigration.exempt_statuses) + waited = ( + person("years_since_us_entry", period.this_year) + >= p.immigration.waiting_period + ) + immigration_eligible = person( + "is_citizen_or_legal_immigrant", period.this_year + ) & (citizen | exempt | waited) return ( (aged | blind | disabled) & (resources <= p.resource_limit) - & (citizen | immigrant) + & immigration_eligible & (arrangement != la.NONE) & ~person("is_incarcerated", period) & person("takes_up_ssi_if_eligible", period.this_year) diff --git a/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_employment_expenses.py b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_employment_expenses.py index 21ab6331248..4c2cca26186 100644 --- a/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_employment_expenses.py +++ b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_employment_expenses.py @@ -4,8 +4,10 @@ class nh_ssp_employment_expenses(Variable): value_type = float entity = Person - label = "New Hampshire SSP verified employment expenses" + label = "New Hampshire SSP employment expenses" definition_period = MONTH unit = USD reference = "https://gc.nh.gov/rules/state_agencies/he-w600.html" - documentation = """Monthly verified employment expenses under He-W 654.18, including mandatory payroll deductions and qualifying transportation and dependent-care costs. The formula allows at least the statutory flat amount for aged and disabled workers.""" + documentation = """Employment expenses under He-W 654.18(c)(1): the employee's Federal Insurance Contributions Act taxes. The countable income formula allows at least the regulatory flat amount of He-W 654.18(b) for aged and disabled workers.""" + # NOTE: Expenses in He-W 654.18(c)(2)-(9), such as withholding, are not derived. + adds = ["employee_social_security_tax", "employee_medicare_tax"] diff --git a/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_living_arrangement.py b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_living_arrangement.py index 20e8dffdc97..c2d5f55f531 100644 --- a/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_living_arrangement.py +++ b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_living_arrangement.py @@ -17,7 +17,8 @@ class nh_ssp_living_arrangement(Variable): definition_period = MONTH possible_values = NHSSPLivingArrangement default_value = NHSSPLivingArrangement.INDEPENDENT - reference = "https://www.medicaid.gov/medicaid/spa/downloads/NH-26-0001.pdf" + # PDF pages 14-16 + reference = "https://www.medicaid.gov/medicaid/spa/downloads/NH-26-0001.pdf#page=14" documentation = """ Care categories require state approval. Care recipients are individual assistance groups, including married residents. Reflect separate federal diff --git a/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_other_income_deductions.py b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_other_income_deductions.py index c28f1139d85..5c1b7841b7b 100644 --- a/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_other_income_deductions.py +++ b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_other_income_deductions.py @@ -8,4 +8,6 @@ class nh_ssp_other_income_deductions(Variable): definition_period = MONTH unit = USD reference = "https://gc.nh.gov/rules/state_agencies/he-w600.html" - documentation = """Verified court-ordered payments, garnishments, qualifying training expenses and dependent allocations under He-W 654.20 and 654.21. Include any approved additional ANB employment-plan disregard under He-W 654.15(c).""" + documentation = """Court-ordered child support and alimony payments deducted under He-W 654.20(a)(1).""" + # NOTE: Other He-W 654.20-654.21 and 654.15(c) deductions are not derived. + adds = ["child_support_expense", "alimony_expense"] diff --git a/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_resources_deemed_from_parents.py b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_resources_deemed_from_parents.py index 7c62456b41a..36651c708c2 100644 --- a/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_resources_deemed_from_parents.py +++ b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_resources_deemed_from_parents.py @@ -1,6 +1,6 @@ from policyengine_us.model_api import * -from policyengine_us.variables.gov.states._ssp_parental_resources import ( - ssp_parental_resources, +from policyengine_us.variables.gov.ssa.ssi.eligibility.resources.deemed.ssi_resources_deemed_from_ineligible_parent import ( + _ssi_parental_resource_pool, ) @@ -16,12 +16,18 @@ class nh_ssp_resources_deemed_from_parents(Variable): # He-W 652.03(i)-(j) adds the co-resident parents' resources above the federal # one/two-parent allowance to a blind child's own resources. It does not divide that # excess between siblings. Parent includes a biological, adoptive or stepparent - # under He-W 601.06(b). Override with the agency-determined amount for a different + # under He-W 601.06(b); the federal pool also counts a named parent's + # co-resident spouse. Override with the agency-determined amount for a different # certified budget, temporary absence, or the month of the eighteenth birthday; # annual age cannot identify that month. def formula(person, period, parameters): - _, _, excess = ssp_parental_resources(person, period, parameters) + p = parameters(period).gov.ssa.ssi.eligibility.resources.limit + parental_resources, parent_count, _ = _ssi_parental_resource_pool( + person, period, person("ssi_resources_for_deeming", period) + ) + allowance = where(parent_count > 1, p.couple, p.individual) + excess = max_(0, parental_resources - allowance) return ( person("is_child", period.this_year) * person("is_blind", period.this_year) diff --git a/policyengine_us/variables/household/income/spm_unit/spm_unit_benefits.py b/policyengine_us/variables/household/income/spm_unit/spm_unit_benefits.py index 267a95d0dc2..ba5fe19620a 100644 --- a/policyengine_us/variables/household/income/spm_unit/spm_unit_benefits.py +++ b/policyengine_us/variables/household/income/spm_unit/spm_unit_benefits.py @@ -22,7 +22,7 @@ def formula(spm_unit, period, parameters): "ky_ssp", # Kentucky benefits "de_ssp", # Delaware benefits "fl_oss", - "nh_ssp", + "nh_ssp", # New Hampshire benefits "ks_sspp", # Kansas benefits "hi_oss", "la_oss", # Louisiana benefits From 3972ca11f9cc2f5d978491481bc492a0287dc2f3 Mon Sep 17 00:00:00 2001 From: Ziming Date: Wed, 14 Oct 2026 15:35:54 -0400 Subject: [PATCH 04/10] Address review: New Hampshire SSP 40-quarter exception, COLA-linked standards and tests - Follow 8 U.S.C. 1622(b)(2): a permanent resident credited with 40 qualifying quarters is exempt from the 5-year wait; document the conflict with AAM 305.13. - Compute the standards of need as the SSI maximum plus the minimum payment level less the standard disregard (He-W 658.03(e), 648.04(b)), so they follow each SSI COLA; correct the three-person standard to the published $1,976. - Add nh_ssp_assistance_group_size and key the standard disregard by group size. - Add cases for untested branches, the one-third reduction, boundaries, mixed and nonapplicant-spouse couples, and the 2027 COLA pass-through; fix descriptions, references, defined_for gates and the changelog. Co-Authored-By: Claude Opus 5.5 --- changelog.d/nh-ssp-2026.added.md | 2 +- .../states/nh/dhhs/ssp/couple_disregard.yaml | 11 - .../gov/states/nh/dhhs/ssp/couple_need.yaml | 11 - .../nh/dhhs/ssp/disabled_minimum_age.yaml | 2 +- .../dhhs/ssp/earned/disregard_fraction.yaml | 2 +- .../earned/minimum_employment_expenses.yaml | 2 +- .../dhhs/ssp/immigration/exempt_statuses.yaml | 2 + ...ermanent_resident_qualifying_quarters.yaml | 13 + .../states/nh/dhhs/ssp/individual_need.yaml | 29 --- .../states/nh/dhhs/ssp/minimum_payment.yaml | 2 +- .../ssp/minimum_payment_level/one_person.yaml | 45 ++++ .../ssp/minimum_payment_level/two_person.yaml | 21 ++ .../states/nh/dhhs/ssp/single_disregard.yaml | 11 - .../nh/dhhs/ssp/standard_disregard.yaml | 23 ++ .../nh/dhhs/ssp/three_person_disregard.yaml | 11 - .../states/nh/dhhs/ssp/three_person_need.yaml | 19 +- .../gov/states/nh/dhhs/ssp/integration.yaml | 11 +- .../gov/states/nh/dhhs/ssp/nh_ssp.yaml | 225 +++++++++++++++++- .../ssp/nh_ssp_assistance_group_size.yaml | 87 +++++++ .../gov/states/nh/dhhs/ssp/nh_ssp.py | 27 ++- .../dhhs/ssp/nh_ssp_assistance_group_size.py | 26 ++ .../nh/dhhs/ssp/nh_ssp_countable_income.py | 15 +- .../nh/dhhs/ssp/nh_ssp_disability_eligible.py | 5 + .../gov/states/nh/dhhs/ssp/nh_ssp_eligible.py | 31 ++- .../nh/dhhs/ssp/nh_ssp_employment_expenses.py | 1 + .../nh/dhhs/ssp/nh_ssp_living_arrangement.py | 1 + .../nh_ssp_resources_deemed_from_parents.py | 3 +- .../snap_alien_qualifying_quarters.py | 5 +- 28 files changed, 519 insertions(+), 124 deletions(-) delete mode 100644 policyengine_us/parameters/gov/states/nh/dhhs/ssp/couple_disregard.yaml delete mode 100644 policyengine_us/parameters/gov/states/nh/dhhs/ssp/couple_need.yaml create mode 100644 policyengine_us/parameters/gov/states/nh/dhhs/ssp/immigration/permanent_resident_qualifying_quarters.yaml delete mode 100644 policyengine_us/parameters/gov/states/nh/dhhs/ssp/individual_need.yaml create mode 100644 policyengine_us/parameters/gov/states/nh/dhhs/ssp/minimum_payment_level/one_person.yaml create mode 100644 policyengine_us/parameters/gov/states/nh/dhhs/ssp/minimum_payment_level/two_person.yaml delete mode 100644 policyengine_us/parameters/gov/states/nh/dhhs/ssp/single_disregard.yaml create mode 100644 policyengine_us/parameters/gov/states/nh/dhhs/ssp/standard_disregard.yaml delete mode 100644 policyengine_us/parameters/gov/states/nh/dhhs/ssp/three_person_disregard.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/nh_ssp_assistance_group_size.yaml create mode 100644 policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_assistance_group_size.py diff --git a/changelog.d/nh-ssp-2026.added.md b/changelog.d/nh-ssp-2026.added.md index 7e17c2d8c60..01909548a32 100644 --- a/changelog.d/nh-ssp-2026.added.md +++ b/changelog.d/nh-ssp-2026.added.md @@ -1 +1 @@ -Add New Hampshire essential-person assistance groups to the 2026 SSP calculation. Add New Hampshire State Supplement Program for 2026. +Add New Hampshire's adult category state supplement (Old Age Assistance, Aid to the Needy Blind and Aid to the Permanently and Totally Disabled) for 2026. diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/couple_disregard.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/couple_disregard.yaml deleted file mode 100644 index db2c052f2fb..00000000000 --- a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/couple_disregard.yaml +++ /dev/null @@ -1,11 +0,0 @@ -description: New Hampshire deducts this amount from the income of a two-person assistance group under the adult category financial assistance program. -values: - 2026-01-01: 20 - -metadata: - unit: currency-USD - period: month - label: New Hampshire SSP two-person standard disregard - reference: - - title: He-W 654.16, Adult standard disregard - href: https://gc.nh.gov/rules/state_agencies/he-w600.html diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/couple_need.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/couple_need.yaml deleted file mode 100644 index e5d4dcc3140..00000000000 --- a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/couple_need.yaml +++ /dev/null @@ -1,11 +0,0 @@ -description: New Hampshire sets this standard of need for a two-person independent-living assistance group under the adult category financial assistance program. -values: - 2026-01-01: 1_492 - -metadata: - unit: currency-USD - period: month - label: New Hampshire SSP independent two-person need standard - reference: - - title: New Hampshire 2026 approved optional state supplement income standards, Section D - href: https://www.medicaid.gov/medicaid/spa/downloads/NH-26-0001.pdf#page=14 diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/disabled_minimum_age.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/disabled_minimum_age.yaml index ea133b87ddd..157ec1bb974 100644 --- a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/disabled_minimum_age.yaml +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/disabled_minimum_age.yaml @@ -1,4 +1,4 @@ -description: New Hampshire requires disabled applicants to have reached this age for adult category cash assistance. +description: New Hampshire sets this age as the minimum for disabled applicants under the adult category financial assistance program. values: 2026-01-01: 18 diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/disregard_fraction.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/disregard_fraction.yaml index 409f85089f7..7adfa5e757a 100644 --- a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/disregard_fraction.yaml +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/disregard_fraction.yaml @@ -6,5 +6,5 @@ metadata: unit: /1 label: New Hampshire SSP remaining earnings disregard rate reference: - - title: He-W 654.15, Earned income disregards + - title: He-W 654.15(b) and (f)(2), Earned income disregards href: https://gc.nh.gov/rules/state_agencies/he-w600.html diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/minimum_employment_expenses.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/minimum_employment_expenses.yaml index 2901f0b8e16..03120ed5a53 100644 --- a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/minimum_employment_expenses.yaml +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/earned/minimum_employment_expenses.yaml @@ -7,5 +7,5 @@ metadata: period: month label: New Hampshire SSP minimum employment expense disregard reference: - - title: He-W 654.18, Employment expenses + - title: He-W 654.18(b), Employment expenses href: https://gc.nh.gov/rules/state_agencies/he-w600.html diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/immigration/exempt_statuses.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/immigration/exempt_statuses.yaml index ee759516115..e1587973f2d 100644 --- a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/immigration/exempt_statuses.yaml +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/immigration/exempt_statuses.yaml @@ -16,3 +16,5 @@ metadata: reference: - title: NH DHHS Adult Assistance Manual 305.11, Qualified Aliens Eligible Without Restriction href: https://dhhs.nh.gov/aam_htm/html/305_11_qualified_aliens_eligible_without_restriction_aam.htm + - title: 8 U.S.C. 1622(b)(1), Time-limited exception for refugees and asylees + href: https://www.law.cornell.edu/uscode/text/8/1622#b_1 diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/immigration/permanent_resident_qualifying_quarters.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/immigration/permanent_resident_qualifying_quarters.yaml new file mode 100644 index 00000000000..0d309ecf207 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/immigration/permanent_resident_qualifying_quarters.yaml @@ -0,0 +1,13 @@ +description: New Hampshire treats a lawful permanent resident credited with at least this many qualifying quarters as exempt from the qualified alien waiting period under the adult category financial assistance program. +values: + 2026-01-01: 40 + +metadata: + unit: int + period: year + label: New Hampshire SSP permanent resident qualifying quarters exception + reference: + - title: 8 U.S.C. 1622(b)(2), Certain permanent resident aliens + href: https://www.law.cornell.edu/uscode/text/8/1622#b_2 + - title: 8 U.S.C. 1645, Qualifying quarters + href: https://www.law.cornell.edu/uscode/text/8/1645 diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/individual_need.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/individual_need.yaml deleted file mode 100644 index 61ac88cce24..00000000000 --- a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/individual_need.yaml +++ /dev/null @@ -1,29 +0,0 @@ -description: New Hampshire sets these monthly adult assistance standards of need for an individual in each living arrangement. - -metadata: - unit: currency-USD - period: month - label: New Hampshire SSP individual need standard - breakdown: - - nh_ssp_living_arrangement - reference: - - title: "New Hampshire 2026 approved optional state supplement income standards, Section D and E #page 14-16" - href: https://www.medicaid.gov/medicaid/spa/downloads/NH-26-0001.pdf#page=14 - -INDEPENDENT: - 2026-01-01: 1_008 - -SUBSIDIZED_COMMUNITY_RESIDENCE: - 2026-01-01: 1_070 - -NONSUBSIDIZED_COMMUNITY_RESIDENCE: - 2026-01-01: 1_130 - -ENHANCED_FAMILY_CARE: - 2026-01-01: 1_188 - -RESIDENTIAL_CARE: - 2026-01-01: 1_188 - -NONE: - 2026-01-01: 0 diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/minimum_payment.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/minimum_payment.yaml index 33bfab0d73d..e313986fcd7 100644 --- a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/minimum_payment.yaml +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/minimum_payment.yaml @@ -7,5 +7,5 @@ metadata: period: month label: New Hampshire SSP minimum grant reference: - - title: He-W 670.03(a), Determination of grant + - title: He-W 670.03(a)(4), Determination of grant href: https://gc.nh.gov/rules/state_agencies/he-w600.html diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/minimum_payment_level/one_person.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/minimum_payment_level/one_person.yaml new file mode 100644 index 00000000000..8153b240604 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/minimum_payment_level/one_person.yaml @@ -0,0 +1,45 @@ +description: New Hampshire maintains this minimum supplemental payment level for a one-person assistance group in each living arrangement under the adult category financial assistance program. + +metadata: + propagate_metadata_to_children: true + unit: currency-USD + period: month + label: New Hampshire SSP one-person minimum payment level + breakdown: + - nh_ssp_living_arrangement + reference: + - title: He-W 658.03(c) and (e), and He-W 648.04, Adult category standard of need + href: https://gc.nh.gov/rules/state_agencies/he-w600.html + - title: SSA, State Assistance Programs for SSI Recipients, January 1998, New Hampshire, payment levels + href: https://www.ssa.gov/policy/docs/progdesc/ssi_st_asst/1998/nh.pdf#page=3 + - title: SSA, State Assistance Programs for SSI Recipients, January 2011, New Hampshire, Table 1 + href: https://www.ssa.gov/policy/docs/progdesc/ssi_st_asst/2011/nh.pdf#page=2 + - title: NH DHHS Supervisory Release SR 26-01, January 2026 COLA + href: https://www.dhhs.nh.gov/sr_htm/html/sr_26-01_dated_01_26.htm + +# The standard of need is the SSI maximum plus this level less the $13 +# standard disregard, so each level is the grant to an SSI-only recipient. +# SR 26-01 standards: $1,008, $1,070, $1,130, $1,188 and $1,188 less the +# $994 SSI maximum plus $13 give 27, 89, 149, 207 and 207. SSA's January 1998 +# and January 2011 tables print the same state supplementation amounts, and +# NH's January releases give matching standards for every year from 1999 to +# 2026. SSA's 2004 and 2008 to 2010 tables print other amounts, but NH's +# releases for those years do not. +INDEPENDENT: + 1998-01-01: 27 + +SUBSIDIZED_COMMUNITY_RESIDENCE: + 1998-01-01: 89 + +NONSUBSIDIZED_COMMUNITY_RESIDENCE: + 1998-01-01: 149 + +ENHANCED_FAMILY_CARE: + 1998-01-01: 207 + +RESIDENTIAL_CARE: + 1998-01-01: 207 + +# No adult category grant in excluded arrangements. +NONE: + 1998-01-01: 0 diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/minimum_payment_level/two_person.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/minimum_payment_level/two_person.yaml new file mode 100644 index 00000000000..59eb6e7d759 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/minimum_payment_level/two_person.yaml @@ -0,0 +1,21 @@ +description: New Hampshire maintains this minimum supplemental payment level for a two-person independent-living assistance group under the adult category financial assistance program. +values: + # SR 26-01: the $1,492 standard less the $1,491 SSI maximum for an individual + # and either a spouse or needy essential person, plus the $20 standard + # disregard. SSA's January 1998 and January 2011 tables print the same $21 + # couple supplement, and NH's January releases match it from 1999 to 2026. + 1998-01-01: 21 + +metadata: + unit: currency-USD + period: month + label: New Hampshire SSP two-person minimum payment level + reference: + - title: He-W 658.03(c) and (e), Adult category standard of need + href: https://gc.nh.gov/rules/state_agencies/he-w600.html + - title: SSA, State Assistance Programs for SSI Recipients, January 1998, New Hampshire, payment levels + href: https://www.ssa.gov/policy/docs/progdesc/ssi_st_asst/1998/nh.pdf#page=3 + - title: SSA, State Assistance Programs for SSI Recipients, January 2011, New Hampshire, Table 1 + href: https://www.ssa.gov/policy/docs/progdesc/ssi_st_asst/2011/nh.pdf#page=2 + - title: NH DHHS Supervisory Release SR 26-01, January 2026 COLA + href: https://www.dhhs.nh.gov/sr_htm/html/sr_26-01_dated_01_26.htm diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/single_disregard.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/single_disregard.yaml deleted file mode 100644 index 14bfc597507..00000000000 --- a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/single_disregard.yaml +++ /dev/null @@ -1,11 +0,0 @@ -description: New Hampshire deducts this amount from the income of a one-person assistance group under the adult category financial assistance program. -values: - 2026-01-01: 13 - -metadata: - unit: currency-USD - period: month - label: New Hampshire SSP one-person standard disregard - reference: - - title: He-W 654.16, Adult standard disregard - href: https://gc.nh.gov/rules/state_agencies/he-w600.html diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/standard_disregard.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/standard_disregard.yaml new file mode 100644 index 00000000000..22bc43271bd --- /dev/null +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/standard_disregard.yaml @@ -0,0 +1,23 @@ +description: New Hampshire deducts this amount from the income of an assistance group of each size under the adult category financial assistance program. + +metadata: + propagate_metadata_to_children: true + unit: currency-USD + period: month + breakdown: + - range(1, 4) + breakdown_label: + - Assistance group size + label: New Hampshire SSP standard disregard + reference: + - title: He-W 654.16(b), Adult standard disregard + href: https://gc.nh.gov/rules/state_agencies/he-w600.html + +1: + 2026-01-01: 13 + +2: + 2026-01-01: 20 + +3: + 2026-01-01: 25 diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/three_person_disregard.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/three_person_disregard.yaml deleted file mode 100644 index 0a87c3b1b36..00000000000 --- a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/three_person_disregard.yaml +++ /dev/null @@ -1,11 +0,0 @@ -description: New Hampshire deducts this standard amount for an adult, spouse and needy essential person. -values: - 2026-01-01: 25 - -metadata: - unit: currency-USD - period: month - label: New Hampshire SSP three-person standard disregard - reference: - - title: He-W 654.16(b)(3) - href: https://gc.nh.gov/rules/state_agencies/he-w600.html diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/three_person_need.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/three_person_need.yaml index a36627d4a14..cb3e318aa6e 100644 --- a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/three_person_need.yaml +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/three_person_need.yaml @@ -1,15 +1,20 @@ -description: 'New Hampshire uses this standard of need for an adult, spouse and needy essential person. The 2026 value is calculated under He-W 658.03(e): the published 2025 standard of $1,934 plus the SSI couple increase of $41 and essential-person increase of $14.' +description: New Hampshire sets this standard of need for a three-person independent-living assistance group under the adult category financial assistance program. values: - 2026-01-01: 1_989 + # NOTE: NH's three-person standard is DHHS's stated SSI maximum for a couple + # and needy essential person less $12 ($1,988 - $12 = $1,976 in 2026). That + # maximum usually equals the couple rate plus the SSI essential person + # increment, but not in 2026 ($1,491 + $498 = $1,989), so the published + # standard is kept and needs a new value each January. + 2026-01-01: 1_976 metadata: unit: currency-USD period: month label: New Hampshire SSP three-person standard of need reference: - - title: He-W 658.03(e), COLA update method + - title: NH DHHS Supervisory Release SR 26-01, January 2026 COLA + href: https://www.dhhs.nh.gov/sr_htm/html/sr_26-01_dated_01_26.htm + - title: NH DHHS Adult Assistance Manual 601, Table A + href: https://www.dhhs.nh.gov/aam_htm/html/601_table_a_income_limits_aam.htm + - title: He-W 658.03(e), Adult category standard of need href: https://gc.nh.gov/rules/state_agencies/he-w600.html - - title: DHHS Medicaid Budget Briefing Book, published 2025 standards - href: https://gc.nh.gov/lba/budget/operating_budgets/2026-2027/HF_Division_III/DHHS_Medicaid_Briefing_Book_2-21-25.pdf#page=23 - - title: SSA 2026 federal payment amounts and COLA - href: https://www.ssa.gov/oact/cola/SSI.html diff --git a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/integration.yaml index aa0810f29f8..138650b3af4 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/integration.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/integration.yaml @@ -161,6 +161,8 @@ # 11,928 SSI + 324 state supplement = 12,252. snap_unearned_income: 12_252 hud_unearned_income: 12_252 + # $11,928 SSI + $324 state supplement + $678 SNAP = $12,930. + spm_unit_benefits: 12_930 - name: Case 7, eligible couple and essential person share a three-person grant. period: 2026-01 @@ -181,8 +183,9 @@ state_code: NH output: ssi: [745.5, 745.5] - # 1,989 three-person standard - 1,466 = 523, split between two recipients. - nh_ssp: [261.5, 261.5] + # 1,976 three-person standard (SR 26-01) - 1,466 = 510, split between two + # recipients. + nh_ssp: [255, 255] # 745.5 + 745.5 - 25 three-person disregard = 1,466. nh_ssp_countable_income: [1_466, 1_466] @@ -207,8 +210,8 @@ ssi: [994, 0] # 994 - 25 three-person disregard = 969. nh_ssp_countable_income: [969, 969] - # 1,989 three-person standard - 969 = 1,020. - nh_ssp: [1_020, 0] + # 1,976 three-person standard (SR 26-01) - 969 = 1,007. + nh_ssp: [1_007, 0] - name: Case 9, nonapplicant spouse's part-time earnings are combined with the applicant's. period: 2026-01 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/nh_ssp.yaml b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/nh_ssp.yaml index 99f75c6ad83..c5cd4776f6e 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/nh_ssp.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/nh_ssp.yaml @@ -628,7 +628,8 @@ state_code: NH age: 70 immigration_status: LEGAL_PERMANENT_RESIDENT - # Default 40 qualifying quarters, which SSI's rule would accept. + # No credited quarters are supplied (snap_alien_qualifying_quarters + # defaults to 0), so the 8 USC 1622(b)(2) exception does not apply. years_since_us_entry: 2 output: # 2 years since entry < 5-year waiting period. @@ -702,3 +703,225 @@ # 1,492 - 1,471 = 21; 21 * 2 / 3 = 14 for the couple, whichever spouse has # the flag; 14 / 2 = 7 each. nh_ssp: [7, 7] + +- name: Case 42, a resident of a medical facility where Medicaid pays most of the cost has no grant. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NH + age: 70 + ssi_lives_in_medical_treatment_facility: true + ssi_medicaid_pays_majority_of_care: true + output: + nh_ssp_living_arrangement: NONE + # Federal living arrangement D: the $30 reduced SSI payment. + ssi: 30 + nh_ssp_eligible: false + nh_ssp: 0 + +- name: Case 43, an incarcerated person is ineligible. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NH + age: 70 + is_incarcerated: true + output: + nh_ssp_eligible: false + nh_ssp: 0 + +- name: Case 44, an undocumented immigrant is ineligible. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NH + age: 70 + immigration_status: UNDOCUMENTED + output: + ssi: 0 + nh_ssp_eligible: false + nh_ssp: 0 + +- name: Case 45, the federal one-third reduction alone does not reduce the state grant. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NH + age: 70 + ssi_lives_in_another_persons_household: true + ssi_receives_shelter_from_others_in_household: true + ssi_others_pay_all_meals: true + output: + # $994 * 2/3 = $662.67 federal payment in another person's household. + ssi: 662.67 + # $662.67 - $13 = $649.67 countable; $1,008 - $649.67 = $358.33, rounded to + # $358. He-W 670.03(c) also requires no SNAP receipt, so the state reduction + # is the separate nh_ssp_grant_reduction_applies input (a SNAP recipient keeps $358). + nh_ssp: 358 + +- name: Case 46, the same household without SNAP takes the state one-third reduction. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NH + age: 70 + ssi_lives_in_another_persons_household: true + ssi_receives_shelter_from_others_in_household: true + ssi_others_pay_all_meals: true + nh_ssp_grant_reduction_applies: true + output: + ssi: 662.67 + # $358 * (1 - 1/3) = $238.67, rounded to $239. + nh_ssp: 239 + +- name: Case 47, a permanently and totally disabled applicant qualifies at exactly 18. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NH + age: 18 + meets_ssi_disability_criteria: true + is_permanently_and_totally_disabled: true + output: + nh_ssp_eligible: true + # $1,008 - ($994 - $13) = $27. + nh_ssp: 27 + +- name: Case 48, a permanent resident qualifies exactly five years after entry. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NH + age: 70 + immigration_status: LEGAL_PERMANENT_RESIDENT + years_since_us_entry: 5 + ssi_qualifying_quarters_earnings: 0 + output: + # 0 of the 40 qualifying quarters SSI requires, so no SSI. + ssi: 0 + # 5 years since entry >= 5-year waiting period. + nh_ssp_eligible: true + # max(0 - 13, 0) = 0 countable; $1,008 - $0 = $1,008. + nh_ssp: 1_008 + +- name: Case 49, a mixed blind and aged applicant couple uses each member's own earned income disregard. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + person2: + age: 40 + is_blind: true + # 10 hours a week as a cashier at the New Hampshire median wage of + # $16.27 (BLS OEWS May 2025): $16.27 * 10 * 52 = $8,460.40 a year. + employment_income: 8_460.4 + marital_units: + couple: + members: [person1, person2] + households: + home: + members: [person1, person2] + state_code: NH + output: + # $8,460.40 / 12 = $705.03 a month; ($705.03 - $20 - $65) * 0.5 = $310.02 + # countable; ($1,491 - $310.02) / 2 = $590.49 each. + ssi: [590.49, 590.49] + # He-W 654.15(b), blind: ($705.03 - $85) * 0.5 = $310.02 net earnings; the + # aged member has none. $310.02 + $1,180.98 SSI - $20 = $1,471. + nh_ssp_countable_income: [1_471, 1_471] + # $1,492 two-person standard - $1,471 = $21, split between two recipients. + nh_ssp: [10.5, 10.5] + +- name: Case 50, a blind applicant's nonapplicant spouse's earnings get the blind disregard. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + is_blind: true + person2: + age: 40 + # 20 hours a week as a cashier at the New Hampshire median wage of + # $16.27 (BLS OEWS May 2025): $16.27 * 20 * 52 = $16,920.80 a year. + employment_income: 16_920.8 + marital_units: + couple: + members: [person1, person2] + households: + home: + members: [person1, person2] + state_code: NH + output: + # $16,920.80 / 12 = $1,410.07 a month, above the $497 difference, so SSI + # deems ($1,410.07 - $20 - $65) * 0.5 = $662.53; $1,491 - $662.53 = $828.47. + ssi: [828.47, 0] + nh_ssp_eligible: [true, false] + # He-W 654.02(e) combines the spouse's earnings before the blind disregard: + # ($1,410.07 - $85) * 0.5 = $662.53; $662.53 + $828.47 - $20 = $1,471. + # $1,492 two-person standard - $1,471 = $21. + nh_ssp: [21, 0] + +- name: Case 51, a permanent resident with 40 credited quarters is eligible within the five-year wait. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NH + age: 70 + immigration_status: LEGAL_PERMANENT_RESIDENT + years_since_us_entry: 2 + # 8 USC 1622(b)(2): 40 qualifying quarters credited under 8 USC 1645. + snap_alien_qualifying_quarters: 40 + # 8 USC 1613(a) bars federal SSI for 5 years after entry; the federal SSI + # model does not apply that bar, so SSI is set to the $0 it would pay. + ssi: 0 + output: + nh_ssp_eligible: true + # max(0 - 13, 0) = 0 countable; $1,008 - $0 = $1,008. + nh_ssp: 1_008 + +- name: Case 52, the independent-living standard moves with the SSI cost-of-living increase. + period: 2027-01 + absolute_error_margin: 0.01 + input: + state_code: NH + age: 70 + output: + # He-W 658.03(e): standard = SSI individual rate + $27 - $13, and countable + # income = SSI - $13, so the grant stays $27 whatever the 2027 rate is. + nh_ssp: 27 + +- name: Case 53, the residential care standard moves with the SSI cost-of-living increase. + period: 2027-01 + absolute_error_margin: 0.01 + input: + state_code: NH + age: 70 + nh_ssp_living_arrangement: RESIDENTIAL_CARE + output: + # He-W 648.04(b): standard = SSI individual rate - $13 + $207, so the grant + # stays $207. + nh_ssp: 207 + +- name: Case 54, the two-person standard moves with the SSI cost-of-living increase. + period: 2027-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + person2: + age: 70 + marital_units: + couple: + members: [person1, person2] + households: + home: + members: [person1, person2] + state_code: NH + output: + # Standard = SSI couple rate + $21 - $20 and countable income = SSI - $20, + # so the group grant stays $21, split between two recipients. + nh_ssp: [10.5, 10.5] diff --git a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/nh_ssp_assistance_group_size.yaml b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/nh_ssp_assistance_group_size.yaml new file mode 100644 index 00000000000..2b5b7b4a859 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/nh_ssp_assistance_group_size.yaml @@ -0,0 +1,87 @@ +# He-W 658.03(b): one person, plus a spouse or a needy essential person in an +# independent living arrangement (2), or both (3). +- name: Case 1, a single person living independently is a group of one. + period: 2026-01 + input: + state_code: NH + age: 70 + output: + nh_ssp_assistance_group_size: 1 + +- name: Case 2, a single person with a needy essential person is a group of two. + period: 2026-01 + input: + state_code: NH + age: 70 + nh_ssp_has_essential_person: true + output: + nh_ssp_assistance_group_size: 2 + +- name: Case 3, an independent couple is a group of two. + period: 2026-01 + input: + people: + person1: + age: 70 + person2: + age: 70 + marital_units: + couple: + members: [person1, person2] + households: + home: + members: [person1, person2] + state_code: NH + output: + nh_ssp_assistance_group_size: [2, 2] + +- name: Case 4, an independent couple with a needy essential person is a group of three. + period: 2026-01 + input: + people: + person1: + age: 70 + nh_ssp_has_essential_person: true + person2: + age: 70 + marital_units: + couple: + members: [person1, person2] + households: + home: + members: [person1, person2] + state_code: NH + output: + nh_ssp_assistance_group_size: [3, 3] + +- name: Case 5, spouses in residential care are separate groups of one. + period: 2026-01 + input: + people: + person1: + age: 65 + nh_ssp_living_arrangement: RESIDENTIAL_CARE + ssi_claim_is_joint: false + person2: + age: 65 + nh_ssp_living_arrangement: RESIDENTIAL_CARE + ssi_claim_is_joint: false + marital_units: + couple: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NH + output: + nh_ssp_assistance_group_size: [1, 1] + +- name: Case 6, an essential person does not enlarge a residential care group. + period: 2026-01 + input: + state_code: NH + age: 70 + nh_ssp_living_arrangement: RESIDENTIAL_CARE + nh_ssp_has_essential_person: true + output: + nh_ssp_assistance_group_size: 1 diff --git a/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp.py b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp.py index c5c5f56063e..1f5e3adfa3a 100644 --- a/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp.py +++ b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp.py @@ -16,27 +16,34 @@ class nh_ssp(Variable): # PDF pages 14-16 "https://www.medicaid.gov/medicaid/spa/downloads/NH-26-0001.pdf#page=14", "https://gc.nh.gov/rules/state_agencies/he-w600.html", + "https://www.dhhs.nh.gov/sr_htm/html/sr_26-01_dated_01_26.htm", ) def formula(person, period, parameters): p = parameters(period).gov.states.nh.dhhs.ssp arrangement = person("nh_ssp_living_arrangement", period) - independent = arrangement == arrangement.possible_values.INDEPENDENT spouse = nh_ssp_spouse(person, period) - couple = spouse >= 0 - has_essential_person = person("nh_ssp_has_essential_person", period) - essential = independent & ( - has_essential_person | spouse_value(has_essential_person, spouse, False) - ) - standard = where(couple, p.couple_need, p.individual_need[arrangement]) - standard = where( - essential, where(couple, p.three_person_need, p.couple_need), standard + size = person("nh_ssp_assistance_group_size", period) + # He-W 658.03(e) and 648.04(b): the standard of need is the SSI maximum + # for the group plus the minimum payment level less the standard + # disregard, so it moves with each SSI cost-of-living increase. + ssi = parameters(period).gov.ssa.ssi.amount + disregard = p.standard_disregard[size] + level = p.minimum_payment_level + one_person = ssi.individual + level.one_person[arrangement] - disregard + two_person = ssi.couple + level.two_person - disregard + standard = select( + [size == 3, size == 2], + [p.three_person_need, two_person], + default=one_person, ) income = person("nh_ssp_countable_income", period) grant = np.floor(max_(standard - income, 0) + 0.5) # He-W 670.03(a)(4): no payment when the rounded grant is below the minimum. grant = where(grant >= p.minimum_payment, grant, 0) - # He-W 670.03(c) reduces the group grant, so either spouse's flag applies. + # He-W 670.03(c) reduces "the adult category grant pursuant to (a)", and + # the rule does not apply the minimum again afterwards, so a reduced $2 + # grant pays $1. Either spouse's flag reduces the group grant. reduction = person("nh_ssp_grant_reduction_applies", period) reduction = reduction | spouse_value(reduction, spouse, False) grant = np.floor(grant * (1 - reduction * p.grant_reduction_fraction) + 0.5) diff --git a/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_assistance_group_size.py b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_assistance_group_size.py new file mode 100644 index 00000000000..7d9fc1bdfb0 --- /dev/null +++ b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_assistance_group_size.py @@ -0,0 +1,26 @@ +from policyengine_us.model_api import * +from policyengine_us.variables.gov.states.nh.dhhs.ssp._nh_ssp_couple import ( + nh_ssp_spouse, + spouse_value, +) + + +class nh_ssp_assistance_group_size(Variable): + value_type = int + entity = Person + label = "New Hampshire adult category assistance group size" + definition_period = MONTH + defined_for = StateCode.NH + reference = "https://gc.nh.gov/rules/state_agencies/he-w600.html" + + def formula(person, period, parameters): + # He-W 658.03(b): one person, plus a spouse or a needy essential person + # in an independent living arrangement (2), or both (3). + arrangement = person("nh_ssp_living_arrangement", period) + independent = arrangement == arrangement.possible_values.INDEPENDENT + spouse = nh_ssp_spouse(person, period) + has_essential_person = person("nh_ssp_has_essential_person", period) + essential = independent & ( + has_essential_person | spouse_value(has_essential_person, spouse, False) + ) + return 1 + (spouse >= 0) + essential diff --git a/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_countable_income.py b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_countable_income.py index fa57ef3eae1..a7db9c30456 100644 --- a/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_countable_income.py +++ b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_countable_income.py @@ -17,14 +17,11 @@ class nh_ssp_countable_income(Variable): def formula(person, period, parameters): p = parameters(period).gov.states.nh.dhhs.ssp - arrangement = person("nh_ssp_living_arrangement", period) - independent = arrangement == arrangement.possible_values.INDEPENDENT spouse = nh_ssp_spouse(person, period) couple = spouse >= 0 - has_essential_person = person("nh_ssp_has_essential_person", period) - essential = independent & ( - has_essential_person | spouse_value(has_essential_person, spouse, False) - ) + size = person("nh_ssp_assistance_group_size", period) + # A group larger than the person and any spouse includes an essential person. + essential = size > 1 + couple eligible = person("nh_ssp_eligible", period) both_applicants = eligible & spouse_value(eligible, spouse, False) earned = max_(person("ssi_earned_income", period), 0) @@ -68,9 +65,5 @@ def formula(person, period, parameters): unearned = unearned + essential * max_( essential_income, spouse_value(essential_income, spouse) ) - disregard = where( - essential & couple, - p.three_person_disregard, - where(couple | essential, p.couple_disregard, p.single_disregard), - ) + disregard = p.standard_disregard[size] return max_(net_earned + unearned - disregard - other, 0) diff --git a/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_disability_eligible.py b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_disability_eligible.py index 93e78ec802f..1e18dc64b86 100644 --- a/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_disability_eligible.py +++ b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_disability_eligible.py @@ -6,6 +6,7 @@ class nh_ssp_disability_eligible(Variable): entity = Person label = "Meets New Hampshire APTD medical criteria" definition_period = YEAR + defined_for = StateCode.NH reference = "https://gc.nh.gov/rsa/html/XII/167/167-6.htm" documentation = """ State medical eligibility requires federal disability criteria and the @@ -13,6 +14,10 @@ class nh_ssp_disability_eligible(Variable): already reported permanently and totally disabled. Set the state decision explicitly for qualifying impairments of finite duration. """ + # NOTE: is_permanently_and_totally_disabled is an input that defaults to + # false, so microsimulation pays Aid to the Permanently and Totally Disabled + # only where the dataset sets it; Old Age Assistance and Aid to the Needy + # Blind do not depend on it. def formula(person, period, parameters): return person("meets_ssi_disability_criteria", period) & person( diff --git a/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_eligible.py b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_eligible.py index 75e72a552c7..1e54977b753 100644 --- a/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_eligible.py +++ b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_eligible.py @@ -16,6 +16,7 @@ class nh_ssp_eligible(Variable): "https://gc.nh.gov/rules/state_agencies/he-w600.html", "https://dhhs.nh.gov/aam_htm/html/305_11_qualified_aliens_eligible_without_restriction_aam.htm", "https://dhhs.nh.gov/aam_htm/html/305_13_qualified_aliens_with_restricted_eligibility_based_on_date_of_entry_into_the_us_aam.htm", + "https://www.law.cornell.edu/uscode/text/8/1622#b", ) def formula(person, period, parameters): @@ -28,12 +29,10 @@ def formula(person, period, parameters): ) arrangement = person("nh_ssp_living_arrangement", period) la = arrangement.possible_values - independent = arrangement == la.INDEPENDENT spouse = nh_ssp_spouse(person, period) - has_essential_person = person("nh_ssp_has_essential_person", period) - essential = independent & ( - has_essential_person | spouse_value(has_essential_person, spouse, False) - ) + size = person("nh_ssp_assistance_group_size", period) + # A group larger than the person and any spouse includes an essential person. + essential = size > 1 + (spouse >= 0) resources = person("ssi_countable_resources", period.this_year) resources = resources + spouse_value(resources, spouse) resources = resources + person("nh_ssp_resources_deemed_from_parents", period) @@ -45,19 +44,31 @@ def formula(person, period, parameters): ) # He-W 616.02(a): qualified aliens under 8 USC 1641(b) are eligible once # the waiting period since entry has elapsed, which also covers entry - # before August 22, 1996. AAM 305.11 exempts the listed statuses; AAM - # 305.13 applies the wait to permanent residents regardless of work - # history, so SSI's 40-quarter rule does not apply. + # before August 22, 1996. AAM 305.11 exempts the listed statuses, as + # 8 USC 1622(b)(1) requires. + # NOTE: source conflict. AAM 305.13 keeps "lawfully admitted permanent + # residents regardless of work history" out for the 5 years. 8 USC + # 1622(b)(2) instead makes a permanent resident credited with 40 + # qualifying quarters (8 USC 1645) "eligible for any State public + # benefits", and He-W 616.02 does not address it. The model follows + # the federal statute. The quarters come from + # snap_alien_qualifying_quarters, the same legal count, which defaults + # to 0, so the exception applies only when quarters are supplied. immigration = person("immigration_status", period.this_year) - citizen = immigration == immigration.possible_values.CITIZEN + statuses = immigration.possible_values + citizen = immigration == statuses.CITIZEN exempt = np.isin(immigration.decode_to_str(), p.immigration.exempt_statuses) + quarters = person("snap_alien_qualifying_quarters", period.this_year) + credited_permanent_resident = ( + immigration == statuses.LEGAL_PERMANENT_RESIDENT + ) & (quarters >= p.immigration.permanent_resident_qualifying_quarters) waited = ( person("years_since_us_entry", period.this_year) >= p.immigration.waiting_period ) immigration_eligible = person( "is_citizen_or_legal_immigrant", period.this_year - ) & (citizen | exempt | waited) + ) & (citizen | exempt | credited_permanent_resident | waited) return ( (aged | blind | disabled) & (resources <= p.resource_limit) diff --git a/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_employment_expenses.py b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_employment_expenses.py index 4c2cca26186..0972c88d9c4 100644 --- a/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_employment_expenses.py +++ b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_employment_expenses.py @@ -7,6 +7,7 @@ class nh_ssp_employment_expenses(Variable): label = "New Hampshire SSP employment expenses" definition_period = MONTH unit = USD + defined_for = StateCode.NH reference = "https://gc.nh.gov/rules/state_agencies/he-w600.html" documentation = """Employment expenses under He-W 654.18(c)(1): the employee's Federal Insurance Contributions Act taxes. The countable income formula allows at least the regulatory flat amount of He-W 654.18(b) for aged and disabled workers.""" # NOTE: Expenses in He-W 654.18(c)(2)-(9), such as withholding, are not derived. diff --git a/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_living_arrangement.py b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_living_arrangement.py index c2d5f55f531..81aabe2b084 100644 --- a/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_living_arrangement.py +++ b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_living_arrangement.py @@ -17,6 +17,7 @@ class nh_ssp_living_arrangement(Variable): definition_period = MONTH possible_values = NHSSPLivingArrangement default_value = NHSSPLivingArrangement.INDEPENDENT + defined_for = StateCode.NH # PDF pages 14-16 reference = "https://www.medicaid.gov/medicaid/spa/downloads/NH-26-0001.pdf#page=14" documentation = """ diff --git a/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_resources_deemed_from_parents.py b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_resources_deemed_from_parents.py index 36651c708c2..074bef3c182 100644 --- a/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_resources_deemed_from_parents.py +++ b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_resources_deemed_from_parents.py @@ -19,7 +19,8 @@ class nh_ssp_resources_deemed_from_parents(Variable): # under He-W 601.06(b); the federal pool also counts a named parent's # co-resident spouse. Override with the agency-determined amount for a different # certified budget, temporary absence, or the month of the eighteenth birthday; - # annual age cannot identify that month. + # annual age cannot identify that month. He-W 652.03(j) cites "He-W 656.06(c)", + # which does not exist; the adult category resource limit is He-W 656.06(b). def formula(person, period, parameters): p = parameters(period).gov.ssa.ssi.eligibility.resources.limit diff --git a/policyengine_us/variables/gov/usda/snap/eligibility/waiting_period/snap_alien_qualifying_quarters.py b/policyengine_us/variables/gov/usda/snap/eligibility/waiting_period/snap_alien_qualifying_quarters.py index ec087ae9bf4..b7c56144201 100644 --- a/policyengine_us/variables/gov/usda/snap/eligibility/waiting_period/snap_alien_qualifying_quarters.py +++ b/policyengine_us/variables/gov/usda/snap/eligibility/waiting_period/snap_alien_qualifying_quarters.py @@ -18,8 +18,9 @@ class snap_alien_qualifying_quarters(Variable): "total net of quarters after December 31, 1996, in which the person, " "parent or spouse actually received any Federal means-tested public " "benefit or SNAP benefits, which are not creditable " - "(273.4(a)(6)(ii)(A)(2)). Consulted only for lawful permanent " - "residents inside the SNAP qualified alien waiting period. Defaults " + "(273.4(a)(6)(ii)(A)(2)). Consulted for lawful permanent residents " + "inside the SNAP qualified alien waiting period, and for New " + "Hampshire's adult category assistance under 8 USC 1622(b)(2). Defaults " "to 0, so the 40-quarter exception applies only when this input is " "supplied. This is the same legal count as " "ssi_qualifying_quarters_earnings. 8 USC 1612(a)(2)(B) is one " From a71c7cde73861f8fbab50ceb43d9e2ed5273abfd Mon Sep 17 00:00:00 2001 From: Ziming Date: Wed, 14 Oct 2026 15:49:21 -0400 Subject: [PATCH 05/10] Cite New Hampshire's January 1998 release for the minimum payment levels Co-Authored-By: Claude Opus 5.5 --- .../nh/dhhs/ssp/minimum_payment_level/one_person.yaml | 8 +++++--- .../nh/dhhs/ssp/minimum_payment_level/two_person.yaml | 5 ++++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/minimum_payment_level/one_person.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/minimum_payment_level/one_person.yaml index 8153b240604..d572a3c0aad 100644 --- a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/minimum_payment_level/one_person.yaml +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/minimum_payment_level/one_person.yaml @@ -14,6 +14,8 @@ metadata: href: https://www.ssa.gov/policy/docs/progdesc/ssi_st_asst/1998/nh.pdf#page=3 - title: SSA, State Assistance Programs for SSI Recipients, January 2011, New Hampshire, Table 1 href: https://www.ssa.gov/policy/docs/progdesc/ssi_st_asst/2011/nh.pdf#page=2 + - title: NH DHHS Supervisory Release SR 97-44, January 1998 COLA + href: https://web.archive.org/web/20210808185249/https://www.dhhs.nh.gov/sr_htm/html/sr_97-44_dated_01_98.htm - title: NH DHHS Supervisory Release SR 26-01, January 2026 COLA href: https://www.dhhs.nh.gov/sr_htm/html/sr_26-01_dated_01_26.htm @@ -22,9 +24,9 @@ metadata: # SR 26-01 standards: $1,008, $1,070, $1,130, $1,188 and $1,188 less the # $994 SSI maximum plus $13 give 27, 89, 149, 207 and 207. SSA's January 1998 # and January 2011 tables print the same state supplementation amounts, and -# NH's January releases give matching standards for every year from 1999 to -# 2026. SSA's 2004 and 2008 to 2010 tables print other amounts, but NH's -# releases for those years do not. +# NH's January releases give matching standards for every year from 1998 +# (SR 97-44) to 2026. The care levels differed in 1996. SSA's 2004 and 2008 to +# 2010 tables print other amounts, but NH's releases for those years do not. INDEPENDENT: 1998-01-01: 27 diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/minimum_payment_level/two_person.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/minimum_payment_level/two_person.yaml index 59eb6e7d759..b7d9a7656a0 100644 --- a/policyengine_us/parameters/gov/states/nh/dhhs/ssp/minimum_payment_level/two_person.yaml +++ b/policyengine_us/parameters/gov/states/nh/dhhs/ssp/minimum_payment_level/two_person.yaml @@ -3,7 +3,8 @@ values: # SR 26-01: the $1,492 standard less the $1,491 SSI maximum for an individual # and either a spouse or needy essential person, plus the $20 standard # disregard. SSA's January 1998 and January 2011 tables print the same $21 - # couple supplement, and NH's January releases match it from 1999 to 2026. + # couple supplement, and NH's January releases match it from 1998 (SR 97-44) + # to 2026. 1998-01-01: 21 metadata: @@ -17,5 +18,7 @@ metadata: href: https://www.ssa.gov/policy/docs/progdesc/ssi_st_asst/1998/nh.pdf#page=3 - title: SSA, State Assistance Programs for SSI Recipients, January 2011, New Hampshire, Table 1 href: https://www.ssa.gov/policy/docs/progdesc/ssi_st_asst/2011/nh.pdf#page=2 + - title: NH DHHS Supervisory Release SR 97-44, January 1998 COLA + href: https://web.archive.org/web/20210808185249/https://www.dhhs.nh.gov/sr_htm/html/sr_97-44_dated_01_98.htm - title: NH DHHS Supervisory Release SR 26-01, January 2026 COLA href: https://www.dhhs.nh.gov/sr_htm/html/sr_26-01_dated_01_26.htm From 20e94605f695e622ef20cd1df28728c5d3d38538 Mon Sep 17 00:00:00 2001 From: Ziming Date: Tue, 20 Oct 2026 01:36:58 -0400 Subject: [PATCH 06/10] Fix New Hampshire SSP crash in mixed-state simulations Default nh_ssp_assistance_group_size to 1 so people outside New Hampshire still find a standard_disregard key. Add a two-state case, four boundary cases and a note on 8 U.S.C. 1624. Co-Authored-By: Claude Opus 5.5 --- .../gov/states/nh/dhhs/ssp/nh_ssp.yaml | 95 +++++++++++++++++++ .../dhhs/ssp/nh_ssp_assistance_group_size.py | 4 + .../gov/states/nh/dhhs/ssp/nh_ssp_eligible.py | 7 +- 3 files changed, 105 insertions(+), 1 deletion(-) diff --git a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/nh_ssp.yaml b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/nh_ssp.yaml index c5cd4776f6e..74091a1caf6 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/nh_ssp.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/nh_ssp.yaml @@ -925,3 +925,98 @@ # Standard = SSI couple rate + $21 - $20 and countable income = SSI - $20, # so the group grant stays $21, split between two recipients. nh_ssp: [10.5, 10.5] + +- name: Case 55, a New Hampshire resident and a Massachusetts resident in one simulation. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + person2: + age: 70 + # Separate units, so default units don't pair the two as spouses. + tax_units: + tax_unit1: + members: [person1] + tax_unit2: + members: [person2] + spm_units: + spm_unit1: + members: [person1] + spm_unit2: + members: [person2] + families: + family1: + members: [person1] + family2: + members: [person2] + marital_units: + marital_unit1: + members: [person1] + marital_unit2: + members: [person2] + households: + nh_home: + members: [person1] + state_code: NH + ma_home: + members: [person2] + state_code: MA + output: + # person1: $994 SSI - $13 = $981 countable; $1,008 - $981 = $27. person2 is + # outside New Hampshire. + nh_ssp_countable_income: [981, 0] + nh_ssp: [27, 0] + +- name: Case 56, a rounded grant of exactly the $2 minimum is paid. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NH + age: 65 + nh_ssp_countable_income: 1_006 + output: + # 1,008 - 1,006 = 2, the He-W 670.03(a)(4) minimum: paid. + nh_ssp: 2 + +- name: Case 57, the one-third reduction applies after the minimum grant test. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NH + age: 65 + nh_ssp_countable_income: 1_006 + nh_ssp_grant_reduction_applies: true + output: + # The $2 grant passes the minimum, then He-W 670.03(c) reduces it: + # 2 * 2/3 = 1.33, rounded to 1. + nh_ssp: 1 + +- name: Case 58, a grant of $2.49 rounds down to the $2 minimum. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NH + age: 65 + nh_ssp_countable_income: 1_005.51 + output: + # 1,008 - 1,005.51 = 2.49, rounded down to 2 under He-W 670.03(a)(3)a.: paid. + nh_ssp: 2 + +- name: Case 59, a permanent resident with 39 credited quarters stays in the five-year wait. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NH + age: 70 + immigration_status: LEGAL_PERMANENT_RESIDENT + years_since_us_entry: 2 + # One quarter short of the 40 in 8 USC 1622(b)(2). + snap_alien_qualifying_quarters: 39 + # As in Case 51, 8 USC 1613(a) bars federal SSI for 5 years after entry. + ssi: 0 + output: + # 2 < 5 years, not exempt, and 39 < 40 quarters: ineligible. + nh_ssp_eligible: false + nh_ssp: 0 diff --git a/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_assistance_group_size.py b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_assistance_group_size.py index 7d9fc1bdfb0..a4a3c528aee 100644 --- a/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_assistance_group_size.py +++ b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_assistance_group_size.py @@ -10,6 +10,10 @@ class nh_ssp_assistance_group_size(Variable): entity = Person label = "New Hampshire adult category assistance group size" definition_period = MONTH + # Core runs nh_ssp and nh_ssp_countable_income for everyone once anyone + # qualifies, so people outside New Hampshire still need a valid + # standard_disregard key. + default_value = 1 defined_for = StateCode.NH reference = "https://gc.nh.gov/rules/state_agencies/he-w600.html" diff --git a/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_eligible.py b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_eligible.py index 1e54977b753..779b506a8b6 100644 --- a/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_eligible.py +++ b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_eligible.py @@ -51,7 +51,12 @@ def formula(person, period, parameters): # 1622(b)(2) instead makes a permanent resident credited with 40 # qualifying quarters (8 USC 1645) "eligible for any State public # benefits", and He-W 616.02 does not address it. The model follows - # the federal statute. The quarters come from + # 8 USC 1622(b)(2). AAM 305.13 may instead rest on 8 USC 1624, which + # lets a State restrict aliens' eligibility for "programs of general + # cash public assistance" if no more restrictive than comparable + # Federal programs; SSI bars these residents for the 5 years (8 USC + # 1613(a)). Whether the adult categories are general cash public + # assistance is unsettled. The quarters come from # snap_alien_qualifying_quarters, the same legal count, which defaults # to 0, so the exception applies only when quarters are supplied. immigration = person("immigration_status", period.this_year) From 893f54b2d2708479a9a48c631efa60c4871b5b1f Mon Sep 17 00:00:00 2001 From: Ziming Date: Tue, 20 Oct 2026 16:07:53 -0400 Subject: [PATCH 07/10] Count gross wages in New Hampshire's SSP income test He-W 601.04(m) and 654.02 count wages before payroll deductions, so the state test no longer nets out pre-tax health premiums; federal SSI keeps SSA's exclusion. Note that blind-child parental deeming still uses SSI's wage count. Co-Authored-By: Claude Opus 5.5 --- .../gov/states/nh/dhhs/ssp/nh_ssp.yaml | 54 +++++++++++++++++++ .../nh/dhhs/ssp/nh_ssp_countable_income.py | 9 +++- 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/nh_ssp.yaml b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/nh_ssp.yaml index 74091a1caf6..20c0afb96ab 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/nh_ssp.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/ssp/nh_ssp.yaml @@ -1020,3 +1020,57 @@ # 2 < 5 years, not exempt, and 39 < 40 quarters: ineligible. nh_ssp_eligible: false nh_ssp: 0 + +- name: Case 60, pre-tax health premiums still count as New Hampshire wages. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NH + age: 40 + is_blind: true + # $1,000 a month, about 14 hours a week at the New Hampshire cashier + # median of $16.27 (BLS OEWS May 2025). + employment_income: 12_000 + # $100 a month for self-only coverage through a cafeteria plan, below the + # 2025 average worker contribution of $1,440 (KFF Employer Health + # Benefits Survey). + pre_tax_health_insurance_premiums: 1_200 + output: + # SSI excludes the premiums (POMS SI 00820.102 C.2): 1,000 - 100 = 900; + # 994 - (900 - 20 - 65) * 0.5 = 994 - 407.50 = 586.50. + ssi: 586.5 + # He-W 601.04(m) counts the 1,000 before payroll deductions. He-W + # 654.15(b): (1,000 - 85) * 0.5 = 457.50; 457.50 + 586.50 - 13 = 1,031. + nh_ssp_countable_income: 1_031 + # 1,031 is above the 1,008 standard (994 + 27 - 13): no grant. + nh_ssp: 0 + +- name: Case 61, a nonapplicant spouse's pre-tax health premiums still count as New Hampshire wages. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + is_blind: true + person2: + age: 40 + # As in Case 50: 20 hours a week at $16.27, $16,920.80 a year. + employment_income: 16_920.8 + # $100 a month through a cafeteria plan, as in Case 60. + pre_tax_health_insurance_premiums: 1_200 + marital_units: + couple: + members: [person1, person2] + households: + home: + members: [person1, person2] + state_code: NH + output: + # SSI deems the spouse's wages net of premiums: 1,410.07 - 100 = 1,310.07; + # (1,310.07 - 20 - 65) * 0.5 = 612.53; 1,491 - 612.53 = 878.47. + ssi: [878.47, 0] + nh_ssp_eligible: [true, false] + # He-W 654.02(e)(1) combines gross earnings: (1,410.07 - 85) * 0.5 = 662.53; + # 662.53 + 878.47 - 20 = 1,521, above the 1,492 two-person standard. + nh_ssp: [0, 0] diff --git a/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_countable_income.py b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_countable_income.py index a7db9c30456..3df789f2c0c 100644 --- a/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_countable_income.py +++ b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_countable_income.py @@ -24,7 +24,12 @@ def formula(person, period, parameters): essential = size > 1 + couple eligible = person("nh_ssp_eligible", period) both_applicants = eligible & spouse_value(eligible, spouse, False) - earned = max_(person("ssi_earned_income", period), 0) + # NOTE: He-W 654.02(c)(1) and 601.04(m) count wages "prior to payroll + # deductions", and He-W 600 excludes no cafeteria-plan salary reduction, + # so pre-tax health premiums stay in the state's wage count. Federal SSI + # excludes them (POMS SI 00820.102 C.2), and the ssi term keeps that. + sources = parameters(period).gov.ssa.ssi.income.sources.earned + earned = max_(add(person, period, sources), 0) expenses = max_(person("nh_ssp_employment_expenses", period), 0) # With a nonapplicant spouse, combine earnings before the applicant's # category disregard under He-W 654.02(d)-(e). @@ -53,6 +58,8 @@ def formula(person, period, parameters): "ssi", period ) # Blind children use the parental allocation in He-W 652.03(f)-(g). + # NOTE: that term uses SSI's earned income, so the parents' pre-tax + # health premiums are excluded there; 652.03(f)(2) names no such exclusion. unearned = unearned + person( "ssi_unearned_income_deemed_from_ineligible_parent", period ) From 1fcfdad32ac738a030ba4e1c70cb08b4f4dfb4bb Mon Sep 17 00:00:00 2001 From: Ziming Date: Tue, 20 Oct 2026 18:33:24 -0400 Subject: [PATCH 08/10] Drop the source-conflict label from a NOTE until the conflict is registered The new guard (#10287) reserves the phrase for registered markers. The NOTE's content is unchanged; the conflict goes to source_conflicts/candidates.yaml when main is merged. Co-Authored-By: Claude Opus 5.5 --- .../variables/gov/states/nh/dhhs/ssp/nh_ssp_eligible.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_eligible.py b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_eligible.py index 779b506a8b6..4ba8532fe3f 100644 --- a/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_eligible.py +++ b/policyengine_us/variables/gov/states/nh/dhhs/ssp/nh_ssp_eligible.py @@ -46,8 +46,8 @@ def formula(person, period, parameters): # the waiting period since entry has elapsed, which also covers entry # before August 22, 1996. AAM 305.11 exempts the listed statuses, as # 8 USC 1622(b)(1) requires. - # NOTE: source conflict. AAM 305.13 keeps "lawfully admitted permanent - # residents regardless of work history" out for the 5 years. 8 USC + # NOTE: AAM 305.13 keeps "lawfully admitted permanent residents + # regardless of work history" out for the 5 years. 8 USC # 1622(b)(2) instead makes a permanent resident credited with 40 # qualifying quarters (8 USC 1645) "eligible for any State public # benefits", and He-W 616.02 does not address it. The model follows From b57e225b9740c275182fcb34f5a8edb0d95bfd2b Mon Sep 17 00:00:00 2001 From: Ziming Date: Wed, 21 Oct 2026 00:48:58 -0400 Subject: [PATCH 09/10] List New Hampshire's 8 U.S.C. 1622(b)(2) conflict as a source-conflict candidate The model follows the statute over Adult Assistance Manual 305.13; the entry waits in source_conflicts/candidates.yaml until it is registered. Co-Authored-By: Claude Opus 5.5 --- source_conflicts/candidates.yaml | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/source_conflicts/candidates.yaml b/source_conflicts/candidates.yaml index 7d8c41658c6..cea0e7bcead 100644 --- a/source_conflicts/candidates.yaml +++ b/source_conflicts/candidates.yaml @@ -3732,6 +3732,38 @@ candidates: prs: [] state: unreviewed note: Verify whether the still-listed ruling applies during these years despite its obsolete tax base. +- id: us-nh:ssp-permanent-resident-forty-quarters + program: ssi-state-supplement + years: + from: 2026 + to: 2026 + type: calendar + question: Can a lawful permanent resident credited with 40 qualifying quarters receive New Hampshire's state + supplement during the five years after entry? + sources: + - kind: statute + citation: 8 U.S.C. 1622(b)(2) + url: https://www.law.cornell.edu/uscode/text/8/1622 + - kind: manual + citation: NH DHHS Adult Assistance Manual 305.13 + url: https://dhhs.nh.gov/aam_htm/html/305_13_qualified_aliens_with_restricted_eligibility_based_on_date_of_entry_into_the_us_aam.htm + - kind: regulation + citation: N.H. Admin. Rules He-W 616.02 + url: https://gc.nh.gov/rules/state_agencies/he-w600.html + readings: + statute: A permanent resident credited with 40 qualifying quarters is "eligible for any State public benefits", + so the five-year wait does not apply. + other: The manual keeps "lawfully admitted permanent residents regardless of work history" out for five years. + example: A permanent resident within five years of entry with 40 credited quarters is eligible under the statute + and ineligible under the manual; with 39 quarters both readings bar them. + pe_us: + follows: statute + code: [] + prs: + - https://github.com/PolicyEngine/policyengine-us/pull/10156 + state: ruled + note: 'The manual may rest on 8 U.S.C. 1624, which lets a State restrict general cash public assistance; whether + the adult categories are that is unsettled. Code not yet on main: nh_ssp_eligible.' - id: us-nj:claim-of-right-same-category-offset program: income-tax years: From d10c6fbfa9a190aefba10fabd8fe337df9a597f6 Mon Sep 17 00:00:00 2001 From: Ziming Date: Wed, 21 Oct 2026 21:19:28 -0400 Subject: [PATCH 10/10] Place shared-list entries apart from sibling SSP pull requests Each sibling SSP PR adds its line to the same unsorted lists, so the entries now sit at different anchors and the PRs merge without conflicts. Co-Authored-By: Claude Opus 5.5 --- .../household/household_state_benefits.yaml | 12 +++++------ .../hud/annual_income/sources/unearned.yaml | 2 +- policyengine_us/programs.yaml | 20 +++++++++---------- .../income/spm_unit/spm_unit_benefits.py | 2 +- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/policyengine_us/parameters/gov/household/household_state_benefits.yaml b/policyengine_us/parameters/gov/household/household_state_benefits.yaml index 024b4c38e60..1b0c24e0188 100644 --- a/policyengine_us/parameters/gov/household/household_state_benefits.yaml +++ b/policyengine_us/parameters/gov/household/household_state_benefits.yaml @@ -176,11 +176,11 @@ values: # Nevada benefits - nv_oss - nv_child_care_subsidies + # New Hampshire benefits + - nh_ssp # Oklahoma benefits - ok_child_care_subsidies - ok_ssp - # New Hampshire benefits - - nh_ssp # New Jersey benefits - nj_ssp # New Mexico benefits @@ -296,11 +296,11 @@ values: # Nevada benefits - nv_oss - nv_child_care_subsidies + # New Hampshire benefits + - nh_ssp # Oklahoma benefits - ok_child_care_subsidies - ok_ssp - # New Hampshire benefits - - nh_ssp # New Jersey benefits - nj_ssp # New Mexico benefits @@ -417,11 +417,11 @@ values: # Nevada benefits - nv_oss - nv_child_care_subsidies + # New Hampshire benefits + - nh_ssp # Oklahoma benefits - ok_child_care_subsidies - ok_ssp - # New Hampshire benefits - - nh_ssp # New Jersey benefits - nj_ssp # New Mexico benefits diff --git a/policyengine_us/parameters/gov/hud/annual_income/sources/unearned.yaml b/policyengine_us/parameters/gov/hud/annual_income/sources/unearned.yaml index 0cd5f24f517..7abfaa978f7 100644 --- a/policyengine_us/parameters/gov/hud/annual_income/sources/unearned.yaml +++ b/policyengine_us/parameters/gov/hud/annual_income/sources/unearned.yaml @@ -20,6 +20,7 @@ values: - social_security - ssi - nj_ssp + - nh_ssp - pa_ssp - wy_ssp - nc_sa_countable_for_hud @@ -30,7 +31,6 @@ values: - ri_ssp - sd_ssp - va_ag - - nh_ssp - general_assistance - total_unemployment_compensation - child_support_received diff --git a/policyengine_us/programs.yaml b/policyengine_us/programs.yaml index d7ea544cd2e..1c912744177 100644 --- a/policyengine_us/programs.yaml +++ b/policyengine_us/programs.yaml @@ -1161,6 +1161,16 @@ programs: Models 2026 New Jersey optional supplement rates by living arrangement, including the ineligible-spouse variation. Mandatory grandfathered supplementation is not modeled. + - state: NH + status: partial + name: New Hampshire SSP + full_name: New Hampshire State Supplement Program + variable: nh_ssp + parameter_prefix: gov.states.nh.dhhs.ssp + verified_years: '2026' + notes: Models 2026 adult category cash assistance (OAA, ANB and APTD) for independent + living, certified community care, couples and needy essential persons. Conditional + resources, sanctions and grandfathered benefits are not modeled. - state: PA status: partial name: Pennsylvania SSP @@ -1257,16 +1267,6 @@ programs: notes: Models 2026 locality rates and SSI and non-SSI budgets for certified assisted living, adult foster care and supportive housing residents. Conditional resource benefits and historical grandfathering are not modeled. - - state: NH - status: partial - name: New Hampshire SSP - full_name: New Hampshire State Supplement Program - variable: nh_ssp - parameter_prefix: gov.states.nh.dhhs.ssp - verified_years: '2026' - notes: Models 2026 adult category cash assistance (OAA, ANB and APTD) for independent - living, certified community care, couples and needy essential persons. Conditional - resources, sanctions and grandfathered benefits are not modeled. - id: social_security name: Social Security diff --git a/policyengine_us/variables/household/income/spm_unit/spm_unit_benefits.py b/policyengine_us/variables/household/income/spm_unit/spm_unit_benefits.py index 6f461a30abb..c22156af086 100644 --- a/policyengine_us/variables/household/income/spm_unit/spm_unit_benefits.py +++ b/policyengine_us/variables/household/income/spm_unit/spm_unit_benefits.py @@ -23,6 +23,7 @@ def formula(spm_unit, period, parameters): "de_ssp", # Delaware benefits "fl_oss", "nj_ssp", # New Jersey benefits + "nh_ssp", # New Hampshire benefits "pa_ssp", # Pennsylvania benefits "wy_ssp", # Wyoming benefits "nc_sa", # North Carolina benefits @@ -32,7 +33,6 @@ def formula(spm_unit, period, parameters): "ri_ssp", # Rhode Island benefits "sd_ssp", # South Dakota benefits "va_ag", # Virginia benefits - "nh_ssp", # New Hampshire benefits "ks_sspp", # Kansas benefits "hi_oss", "la_oss", # Louisiana benefits