From 9524da0f809c0bcc94570bdc43a53590bfffb90c Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Mon, 12 Oct 2026 06:07:24 -0400 Subject: [PATCH 1/5] Pay CO, TX and NM SSI supplements to both members of an SSI couple The Colorado AND-CS, Texas Medicaid-facility and New Mexico adult residential care supplements gated on is_ssi_eligible_individual, which is false for the tax-unit-spouse member of an SSI couple. Each state's rule pays every SSI recipient on their own (9 CCR 2503-5 3.546-3.548; HHSC MEPD H-1500 and H-6000; 8.106.400.10(C) and 8.106.500.10 NMAC), so gate on SSI receipt instead, the repo's convention for SSI-recipient programs. Co-Authored-By: Claude Opus 5.5 --- ...plement-couple-spouse-eligibility.fixed.md | 1 + .../ssa/state_supplement/grant_standard.yaml | 2 +- .../state_supplement/co_state_supplement.yaml | 93 ++++++++++++ .../co_state_supplement_eligible.yaml | 115 +++++++++++++-- .../nm/hca/ssi_supplement/integration.yaml | 111 +++++++++++--- .../nm_ssi_state_supplement.yaml | 10 +- .../nm_ssi_state_supplement_eligible.yaml | 40 ++++-- .../nm_ssi_state_supplement_historical.yaml | 8 +- .../ssi_state_supplement/integration.yaml | 136 +++++++++++++++--- .../tx_ssi_state_supplement_eligible.yaml | 32 +++-- .../edge_cases/state/co/state_supplement.yaml | 12 +- .../co_state_supplement_eligible.py | 12 +- .../nm_ssi_state_supplement_eligible.py | 9 +- .../tx_ssi_state_supplement_eligible.py | 9 +- 14 files changed, 497 insertions(+), 93 deletions(-) create mode 100644 changelog.d/ssi-supplement-couple-spouse-eligibility.fixed.md diff --git a/changelog.d/ssi-supplement-couple-spouse-eligibility.fixed.md b/changelog.d/ssi-supplement-couple-spouse-eligibility.fixed.md new file mode 100644 index 00000000000..602b88b4c35 --- /dev/null +++ b/changelog.d/ssi-supplement-couple-spouse-eligibility.fixed.md @@ -0,0 +1 @@ +Pay the Colorado AND-CS, Texas SSI facility and New Mexico residential care supplements to SSI recipients, so both members of an SSI couple qualify instead of only the one labelled the eligible individual. diff --git a/policyengine_us/parameters/gov/states/co/ssa/state_supplement/grant_standard.yaml b/policyengine_us/parameters/gov/states/co/ssa/state_supplement/grant_standard.yaml index 9d104731d97..d35eed18446 100644 --- a/policyengine_us/parameters/gov/states/co/ssa/state_supplement/grant_standard.yaml +++ b/policyengine_us/parameters/gov/states/co/ssa/state_supplement/grant_standard.yaml @@ -38,4 +38,4 @@ metadata: - title: 9 CCR 2503-5, Section 3.546, AND-CS Program (effective 2023) href: https://www.coloradosos.gov/CCR/GenerateRulePdf.do?ruleVersionId=10694#page=73 - title: 9 CCR 2503-5, Section 3.546, AND-CS Program - href: https://www.sos.state.co.us/CCR/GenerateRulePdf.do?fileName=9+CCR+2503-5&ruleVersionId=12428#page=99 + href: https://www.sos.state.co.us/CCR/GenerateRulePdf.do?fileName=9+CCR+2503-5&ruleVersionId=12428#page=91 diff --git a/policyengine_us/tests/policy/baseline/gov/states/co/ssa/state_supplement/co_state_supplement.yaml b/policyengine_us/tests/policy/baseline/gov/states/co/ssa/state_supplement/co_state_supplement.yaml index 31fd3ee0804..5a6a467da21 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/co/ssa/state_supplement/co_state_supplement.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/co/ssa/state_supplement/co_state_supplement.yaml @@ -127,3 +127,96 @@ ssi: 0 output: co_state_supplement: 11_928 + +- name: Case 14, both members of a disabled SSI couple receive the supplement in 2026. + # SSA 2026 SSI couple rate: $1,491/month, or $745.50 for each spouse of a + # joint claim. 9 CCR 2503-5 3.546, 3.548(A)-(B): each spouse is an AND-CS + # client whose grant is the $994 standard less their own countable income, + # which includes their SSI (3.549(A)(2)(d)): 994 - 745.50 = 248.50/month, + # or 2,982/year. SSA's January 2011 Colorado table pays a couple the same + # way: combined standard $1,398 (2 x $699), state supplement $387 + # (1,398 - 1,011 federal couple rate). + absolute_error_margin: 0.1 + period: 2026 + input: + people: + head: + age: 50 + is_disabled: true + meets_ssi_disability_criteria: true + is_tax_unit_head: true + spouse: + age: 52 + is_disabled: true + meets_ssi_disability_criteria: true + is_tax_unit_spouse: true + tax_units: + tax_unit: + members: [head, spouse] + marital_units: + marital_unit: + members: [head, spouse] + households: + household: + members: [head, spouse] + state_code: CO + output: + ssi: [8_946, 8_946] + co_state_supplement: [2_982, 2_982] + +- name: Case 15, a disabled SSI couple with equal pensions each receive the supplement. + # Each spouse has a $300/month pension. Federal SSI: couple unearned income + # 600 - 20 general exclusion = 580; couple payment 1,491 - 580 = 911, or + # 455.50 each. 3.549(A)(2): each client's countable unearned income is + # 300 - 10 (the $20 disregard split between spouses) + 455.50 SSI added back + # = 745.50, so each grant is 994 - 745.50 = 248.50/month, or 2,982/year. + absolute_error_margin: 0.1 + period: 2026 + input: + people: + head: + age: 50 + is_disabled: true + meets_ssi_disability_criteria: true + pension_income: 3_600 + is_tax_unit_head: true + spouse: + age: 52 + is_disabled: true + meets_ssi_disability_criteria: true + pension_income: 3_600 + is_tax_unit_spouse: true + tax_units: + tax_unit: + members: [head, spouse] + marital_units: + marital_unit: + members: [head, spouse] + households: + household: + members: [head, spouse] + state_code: CO + output: + ssi: [5_466, 5_466] + co_state_supplement: [2_982, 2_982] + +- name: Case 16, a disabled adult above the SSI resource limit receives nothing. + # $3,000 of countable resources exceeds the $2,000 SSI limit, so no SSI is + # paid. 3.546 limits AND-CS to clients receiving SSI, and 3.547(D) ends + # AND-CS when SSI ends, so the grant is 0 rather than the $994 standard. + absolute_error_margin: 0.1 + period: 2026 + input: + people: + person: + age: 45 + is_disabled: true + meets_ssi_disability_criteria: true + ssi_countable_resources: 3_000 + households: + household: + members: [person] + state_code: CO + output: + ssi: 0 + co_state_supplement: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/co/ssa/state_supplement/co_state_supplement_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/co/ssa/state_supplement/co_state_supplement_eligible.yaml index c9f2703f30f..6a42a8fd629 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/co/ssa/state_supplement/co_state_supplement_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/co/ssa/state_supplement/co_state_supplement_eligible.yaml @@ -1,7 +1,7 @@ - name: Case 1, ineligible senior over 60. period: 2023 input: - is_ssi_eligible_individual: true + ssi: 1_200 age: 60 is_blind: true is_ssi_disabled: true @@ -12,7 +12,7 @@ - name: Case 2, not blind or disabled. period: 2023 input: - is_ssi_eligible_individual: true + ssi: 1_200 age: 30 is_blind: false is_ssi_disabled: false @@ -20,10 +20,10 @@ output: co_state_supplement_eligible: false -- name: Case 3, not SSI eligible. +- name: Case 3, not receiving SSI. period: 2023 input: - is_ssi_eligible_individual: false + ssi: 0 age: 19 is_blind: true is_ssi_disabled: true @@ -31,10 +31,10 @@ output: co_state_supplement_eligible: false -- name: Case 4, SSI eligible and blind under 60. +- name: Case 4, receives SSI and blind under 60. period: 2023 input: - is_ssi_eligible_individual: true + ssi: 1_200 age: 59 is_blind: true is_ssi_disabled: false @@ -42,10 +42,10 @@ output: co_state_supplement_eligible: true -- name: Case 5, SSI eligible and disabled child. +- name: Case 5, receives SSI and disabled child. period: 2023 input: - is_ssi_eligible_individual: true + ssi: 1_200 age: 5 is_blind: false is_ssi_disabled: true @@ -56,7 +56,7 @@ - name: Case 6, historical eligibility in 2005. period: 2005 input: - is_ssi_eligible_individual: true + ssi: 1_200 age: 40 is_blind: false is_ssi_disabled: true @@ -67,10 +67,105 @@ - name: Case 7, age boundary at exactly 59. period: 2023 input: - is_ssi_eligible_individual: true + ssi: 1_200 age: 59 is_blind: false is_ssi_disabled: true state_code: CO output: co_state_supplement_eligible: true + +- name: Case 8, reported SSI receipt qualifies with zero computed SSI. + period: 2026-01 + input: + ssi: 0 + receives_ssi: true + age: 40 + is_blind: false + is_ssi_disabled: true + state_code: CO + output: + co_state_supplement_eligible: true + +- name: Case 9, both members of a disabled SSI couple are eligible. + # 9 CCR 2503-5 3.546: AND-CS is for clients "receiving SSI due to a + # disability or blindness"; 3.548(A): grants are "calculated on an + # individual basis with just one client per case". Each spouse of a joint + # SSI claim receives SSI, so each is an AND-CS client. + period: 2026-01 + input: + people: + head: + age: 50 + is_disabled: true + meets_ssi_disability_criteria: true + is_tax_unit_head: true + spouse: + age: 52 + is_disabled: true + meets_ssi_disability_criteria: true + is_tax_unit_spouse: true + tax_units: + tax_unit: + members: [head, spouse] + marital_units: + marital_unit: + members: [head, spouse] + households: + household: + members: [head, spouse] + state_code: CO + output: + co_state_supplement_eligible: [true, true] + +- name: Case 10, a disabled spouse who fails the SSI citizenship condition is not eligible. + # The tax-unit spouse is undocumented, so receives no SSI (8 USC 1611, + # 1612) and is not an AND-CS client. + period: 2026-01 + input: + people: + head: + age: 50 + is_disabled: true + meets_ssi_disability_criteria: true + is_tax_unit_head: true + spouse: + age: 52 + is_disabled: true + meets_ssi_disability_criteria: true + immigration_status_str: UNDOCUMENTED + is_tax_unit_spouse: true + tax_units: + tax_unit: + members: [head, spouse] + marital_units: + marital_unit: + members: [head, spouse] + households: + household: + members: [head, spouse] + state_code: CO + output: + people: + spouse: + ssi: 0 + co_state_supplement_eligible: false + +- name: Case 11, a disabled adult above the SSI resource limit is not eligible. + # $3,000 of countable resources exceeds the $2,000 SSI limit (20 CFR + # 416.1205), so no SSI is paid and 3.547(D) bars AND-CS. + period: 2026-01 + input: + people: + person: + age: 45 + is_disabled: true + meets_ssi_disability_criteria: true + ssi_countable_resources: 3_000 + households: + household: + members: [person] + state_code: CO + output: + ssi: 0 + co_state_supplement_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/nm/hca/ssi_supplement/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/nm/hca/ssi_supplement/integration.yaml index 387916d45ac..eba4e110bd0 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nm/hca/ssi_supplement/integration.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nm/hca/ssi_supplement/integration.yaml @@ -2,6 +2,8 @@ # Tests the full eligibility and benefit calculation pipeline # Source: 8.106.500.10 NMAC - Payments to Adults in Residential Care # Program: $100/month flat payment for SSI recipients in licensed ARSCH facilities +# 8.106.400.10(C) NMAC: two SSI recipients who would be a family at home are +# two separate benefit groups in an ARSCH facility, so each spouse is paid. - name: Case 1, elderly SSI recipient in ARSCH facility receives supplement. period: 2025 @@ -10,7 +12,6 @@ people: person1: age: 70 - is_ssi_eligible_individual: true is_in_adult_residential_care: true households: household: @@ -19,7 +20,7 @@ output: people: person1: - # Eligibility: SSI-eligible (true) AND age >= 18 (70 >= 18) AND in ARSCH (true) + # Eligibility: SSI recipient (aged) AND age >= 18 (70 >= 18) AND in ARSCH (true) nm_ssi_state_supplement_eligible: true # Benefit: $100/month * 12 = $1,200/year (flat payment) nm_ssi_state_supplement: 1_200 @@ -31,7 +32,8 @@ people: person1: age: 35 - is_ssi_eligible_individual: true + is_disabled: true + meets_ssi_disability_criteria: true is_in_adult_residential_care: true households: household: @@ -40,24 +42,35 @@ output: people: person1: - # Eligibility: SSI-eligible (true) AND age >= 18 (35 >= 18) AND in ARSCH (true) + # Eligibility: SSI recipient (disabled) AND age >= 18 (35 >= 18) AND in ARSCH (true) nm_ssi_state_supplement_eligible: true # Benefit: $100/month * 12 = $1,200/year nm_ssi_state_supplement: 1_200 -- name: Case 3, SSI couple both in ARSCH facility each receive supplement. +- name: Case 3, married SSI couple both in ARSCH facility each receive supplement. + # Both spouses of a joint SSI claim. 2025 SSI couple rate: $1,450/month, or + # $725 for each spouse. 8.106.400.10(C) NMAC: two SSI recipients who would + # be a family at home are "two separate benefit groups" in an ARSCH + # facility, and 8.106.500.10(C)(2) NMAC pays each $100/month. SSA's January + # 2011 New Mexico table shows the couple supplement as $200 (2 x $100). period: 2025 absolute_error_margin: 0.01 input: people: person1: age: 68 - is_ssi_eligible_individual: true + is_tax_unit_head: true is_in_adult_residential_care: true person2: age: 66 - is_ssi_eligible_individual: true + is_tax_unit_spouse: true is_in_adult_residential_care: true + tax_units: + tax_unit: + members: [person1, person2] + marital_units: + marital_unit: + members: [person1, person2] households: household: members: [person1, person2] @@ -65,13 +78,17 @@ output: people: person1: - # Person 1: SSI-eligible, age 68 >= 18, in ARSCH + ssi_claim_is_joint: true + # $725/month * 12 = $8,700/year + ssi: 8_700 + # Person 1: SSI recipient, age 68 >= 18, in ARSCH nm_ssi_state_supplement_eligible: true # $100/month * 12 = $1,200/year per person nm_ssi_state_supplement: 1_200 person2: - # Person 2: SSI-eligible, age 66 >= 18, in ARSCH - # Per 8.106.400.10 NMAC: couples in ARSCH are two separate benefit groups + ssi_claim_is_joint: true + ssi: 8_700 + # Person 2: SSI recipient, age 66 >= 18, in ARSCH nm_ssi_state_supplement_eligible: true # $100/month * 12 = $1,200/year per person nm_ssi_state_supplement: 1_200 @@ -83,7 +100,6 @@ people: person1: age: 72 - is_ssi_eligible_individual: true is_in_adult_residential_care: false households: household: @@ -92,7 +108,7 @@ output: people: person1: - # Not in ARSCH facility: ineligible regardless of SSI status + # Not in ARSCH facility: ineligible regardless of SSI receipt nm_ssi_state_supplement_eligible: false nm_ssi_state_supplement: 0 @@ -103,7 +119,8 @@ people: person1: age: 18 - is_ssi_eligible_individual: true + is_disabled: true + meets_ssi_disability_criteria: true is_in_adult_residential_care: true households: household: @@ -124,11 +141,11 @@ people: person1: age: 60 - is_ssi_eligible_individual: true + is_disabled: true + meets_ssi_disability_criteria: true is_in_adult_residential_care: true person2: age: 45 - is_ssi_eligible_individual: false is_in_adult_residential_care: true households: household: @@ -137,11 +154,11 @@ output: people: person1: - # Person 1: SSI-eligible, age 60 >= 18, in ARSCH = eligible + # Person 1: SSI recipient (disabled), age 60 >= 18, in ARSCH = eligible nm_ssi_state_supplement_eligible: true nm_ssi_state_supplement: 1_200 person2: - # Person 2: NOT SSI-eligible = ineligible even though in ARSCH + # Person 2: not aged, blind or disabled, so no SSI = ineligible even though in ARSCH nm_ssi_state_supplement_eligible: false nm_ssi_state_supplement: 0 @@ -152,7 +169,6 @@ people: person1: age: 65 - is_ssi_eligible_individual: true is_in_adult_residential_care: true households: household: @@ -164,3 +180,62 @@ # Wrong state: defined_for = StateCode.NM excludes non-NM residents nm_ssi_state_supplement_eligible: false nm_ssi_state_supplement: 0 + +- name: Case 8, ARSCH resident whose spouse fails the SSI citizenship condition. + # The undocumented tax-unit spouse receives no SSI (8 USC 1611, 1612), so + # is not "a recipient of supplemental security income" under + # 8.106.500.10(A) NMAC. The citizen head still receives the supplement. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 68 + is_tax_unit_head: true + is_in_adult_residential_care: true + person2: + age: 66 + immigration_status_str: UNDOCUMENTED + is_tax_unit_spouse: true + is_in_adult_residential_care: true + tax_units: + tax_unit: + members: [person1, person2] + marital_units: + marital_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NM + output: + people: + person1: + nm_ssi_state_supplement_eligible: true + nm_ssi_state_supplement: 1_200 + person2: + ssi: 0 + nm_ssi_state_supplement_eligible: false + nm_ssi_state_supplement: 0 + +- name: Case 9, ARSCH resident above the SSI resource limit receives nothing. + # $3,000 of countable resources exceeds the $2,000 SSI limit, so no SSI is + # paid and 8.106.500.10(A) NMAC bars the supplement. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + ssi_countable_resources: 3_000 + is_in_adult_residential_care: true + households: + household: + members: [person1] + state_code: NM + output: + people: + person1: + ssi: 0 + nm_ssi_state_supplement_eligible: false + nm_ssi_state_supplement: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nm/hca/ssi_supplement/nm_ssi_state_supplement.yaml b/policyengine_us/tests/policy/baseline/gov/states/nm/hca/ssi_supplement/nm_ssi_state_supplement.yaml index d101679d948..3d7d28619ee 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nm/hca/ssi_supplement/nm_ssi_state_supplement.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nm/hca/ssi_supplement/nm_ssi_state_supplement.yaml @@ -9,7 +9,7 @@ people: person1: age: 65 - is_ssi_eligible_individual: true + ssi: 9_000 is_in_adult_residential_care: true households: household: @@ -21,14 +21,14 @@ # $100/month * 12 months = $1,200/year nm_ssi_state_supplement: 1_200 -- name: Case 2, not SSI-eligible receives zero. +- name: Case 2, not an SSI recipient receives zero. period: 2025 absolute_error_margin: 0.01 input: people: person1: age: 65 - is_ssi_eligible_individual: false + ssi: 0 is_in_adult_residential_care: true households: household: @@ -46,7 +46,7 @@ people: person1: age: 65 - is_ssi_eligible_individual: true + ssi: 9_000 is_in_adult_residential_care: false households: household: @@ -64,7 +64,7 @@ people: person1: age: 17 - is_ssi_eligible_individual: true + ssi: 9_000 is_in_adult_residential_care: true households: household: diff --git a/policyengine_us/tests/policy/baseline/gov/states/nm/hca/ssi_supplement/nm_ssi_state_supplement_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/nm/hca/ssi_supplement/nm_ssi_state_supplement_eligible.yaml index 44eb3aa7c43..6a6840b34fd 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nm/hca/ssi_supplement/nm_ssi_state_supplement_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nm/hca/ssi_supplement/nm_ssi_state_supplement_eligible.yaml @@ -9,7 +9,7 @@ people: person1: age: 65 - is_ssi_eligible_individual: true + ssi: 9_000 is_in_adult_residential_care: true households: household: @@ -27,7 +27,7 @@ people: person1: age: 30 - is_ssi_eligible_individual: true + ssi: 9_000 is_in_adult_residential_care: true households: household: @@ -38,14 +38,14 @@ person1: nm_ssi_state_supplement_eligible: true -- name: Case 3, not SSI-eligible person in ARSCH facility in NM is ineligible. +- name: Case 3, person in ARSCH facility in NM who receives no SSI is ineligible. period: 2025 absolute_error_margin: 0.01 input: people: person1: age: 65 - is_ssi_eligible_individual: false + ssi: 0 is_in_adult_residential_care: true households: household: @@ -56,14 +56,14 @@ person1: nm_ssi_state_supplement_eligible: false -- name: Case 4, underage person is ineligible even if SSI-eligible and in ARSCH. +- name: Case 4, underage person is ineligible even if SSI recipient and in ARSCH. period: 2025 absolute_error_margin: 0.01 input: people: person1: age: 17 - is_ssi_eligible_individual: true + ssi: 9_000 is_in_adult_residential_care: true households: household: @@ -81,7 +81,7 @@ people: person1: age: 18 - is_ssi_eligible_individual: true + ssi: 9_000 is_in_adult_residential_care: true households: household: @@ -92,14 +92,14 @@ person1: nm_ssi_state_supplement_eligible: true -- name: Case 6, SSI-eligible adult NOT in ARSCH facility is ineligible. +- name: Case 6, SSI recipient adult NOT in ARSCH facility is ineligible. period: 2025 absolute_error_margin: 0.01 input: people: person1: age: 65 - is_ssi_eligible_individual: true + ssi: 9_000 is_in_adult_residential_care: false households: household: @@ -110,14 +110,14 @@ person1: nm_ssi_state_supplement_eligible: false -- name: Case 7, SSI-eligible adult in ARSCH but wrong state is ineligible. +- name: Case 7, SSI recipient adult in ARSCH but wrong state is ineligible. period: 2025 absolute_error_margin: 0.01 input: people: person1: age: 65 - is_ssi_eligible_individual: true + ssi: 9_000 is_in_adult_residential_care: true households: household: @@ -127,3 +127,21 @@ people: person1: nm_ssi_state_supplement_eligible: false + +- name: Case 8, reported SSI receipt qualifies a resident with zero computed SSI. + period: 2025-01 + input: + people: + person1: + age: 65 + ssi: 0 + receives_ssi: true + is_in_adult_residential_care: true + households: + household: + members: [person1] + state_code: NM + output: + people: + person1: + nm_ssi_state_supplement_eligible: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/nm/hca/ssi_supplement/nm_ssi_state_supplement_historical.yaml b/policyengine_us/tests/policy/baseline/gov/states/nm/hca/ssi_supplement/nm_ssi_state_supplement_historical.yaml index 0724d4aaa8a..99246699f84 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nm/hca/ssi_supplement/nm_ssi_state_supplement_historical.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nm/hca/ssi_supplement/nm_ssi_state_supplement_historical.yaml @@ -1,5 +1,5 @@ # Historical (2017-2019) New Mexico SSI state supplement amount. -# The optional state supplement for an SSI-eligible adult residing in a +# The optional state supplement for an SSI recipient adult residing in a # licensed adult residential care home has been a flat $100.00/month # ($1,200/year) continuously since July 2004 through at least 2025 (verified # against the SSA annual "State Assistance Programs for SSI Recipients" reports @@ -22,7 +22,7 @@ people: person1: age: 65 - is_ssi_eligible_individual: true + ssi: 9_000 is_in_adult_residential_care: true households: household: @@ -40,7 +40,7 @@ people: person1: age: 65 - is_ssi_eligible_individual: true + ssi: 9_000 is_in_adult_residential_care: true households: household: @@ -58,7 +58,7 @@ people: person1: age: 65 - is_ssi_eligible_individual: true + ssi: 9_000 is_in_adult_residential_care: true households: household: diff --git a/policyengine_us/tests/policy/baseline/gov/states/tx/hhsc/ssi_state_supplement/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/tx/hhsc/ssi_state_supplement/integration.yaml index 014f8e1eb49..358ed96957b 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/tx/hhsc/ssi_state_supplement/integration.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/tx/hhsc/ssi_state_supplement/integration.yaml @@ -7,19 +7,23 @@ # - 2024 PNA: $75/month, Federal reduced SSI: $30/month individual # - Individual supplement: $45/month = $540/year # - No additional state income rules beyond federal SSI +# - Each spouse of a couple in a facility receives the reduced benefit ($60 +# for the couple, H-6000), so each receives the supplement # # Reference: Texas Human Resources Code Section 32.024(w) +# Reference: HHSC MEPD Handbook H-1500 and H-6000 # Reference: SSA State Assistance Programs for SSI Recipients - Texas -- name: Scenario 1, SSI-eligible elderly individual in Texas Medicaid facility. +- name: Scenario 1, elderly SSI recipient in Texas Medicaid facility. # 70-year-old SSI recipient in a nursing facility receives state supplement period: 2024 input: people: person1: age: 70 - is_ssi_eligible_individual: true is_in_medicaid_facility: true + ssi_lives_in_medical_treatment_facility: true + ssi_medicaid_pays_majority_of_care: true tax_units: tax_unit: members: [person1] @@ -31,20 +35,25 @@ members: [person1] state_code: TX output: - # Eligibility: SSI eligible + in Medicaid facility + TX = eligible + # Federal reduced SSI: $30/month * 12 = $360/year + ssi: 360 + # Eligibility: SSI recipient + in Medicaid facility + TX = eligible tx_ssi_state_supplement_eligible: true # Supplement: ($75 PNA - $30 federal reduced SSI) * 12 = $540/year tx_ssi_state_supplement: 540 -- name: Scenario 2, SSI-eligible disabled individual in Texas Medicaid facility. +- name: Scenario 2, disabled SSI recipient in Texas Medicaid facility. # 45-year-old disabled SSI recipient in ICF/IID period: 2024 input: people: person1: age: 45 - is_ssi_eligible_individual: true + is_disabled: true + meets_ssi_disability_criteria: true is_in_medicaid_facility: true + ssi_lives_in_medical_treatment_facility: true + ssi_medicaid_pays_majority_of_care: true tax_units: tax_unit: members: [person1] @@ -56,19 +65,19 @@ members: [person1] state_code: TX output: - # Eligibility: SSI eligible + in Medicaid facility + TX = eligible + ssi: 360 + # Eligibility: SSI recipient + in Medicaid facility + TX = eligible tx_ssi_state_supplement_eligible: true # Supplement: ($75 - $30) * 12 = $540/year tx_ssi_state_supplement: 540 -- name: Scenario 3, SSI-eligible individual NOT in Medicaid facility. +- name: Scenario 3, SSI recipient NOT in Medicaid facility. # SSI recipient living in community - no supplement period: 2024 input: people: person1: age: 70 - is_ssi_eligible_individual: true is_in_medicaid_facility: false tax_units: tax_unit: @@ -85,15 +94,16 @@ tx_ssi_state_supplement_eligible: false tx_ssi_state_supplement: 0 -- name: Scenario 4, person in Medicaid facility but NOT SSI eligible. - # Non-SSI recipient in nursing facility - no supplement +- name: Scenario 4, person in Medicaid facility but NOT an SSI recipient. + # 50-year-old who is neither aged, blind nor disabled receives no SSI period: 2024 input: people: person1: age: 50 - is_ssi_eligible_individual: false is_in_medicaid_facility: true + ssi_lives_in_medical_treatment_facility: true + ssi_medicaid_pays_majority_of_care: true tax_units: tax_unit: members: [person1] @@ -105,19 +115,21 @@ members: [person1] state_code: TX output: - # Not SSI eligible = not eligible for supplement + # No SSI = not eligible for supplement + ssi: 0 tx_ssi_state_supplement_eligible: false tx_ssi_state_supplement: 0 -- name: Scenario 5, SSI-eligible individual in Medicaid facility in another state. +- name: Scenario 5, SSI recipient in Medicaid facility in another state. # SSI recipient in facility but not in Texas period: 2024 input: people: person1: age: 68 - is_ssi_eligible_individual: true is_in_medicaid_facility: true + ssi_lives_in_medical_treatment_facility: true + ssi_medicaid_pays_majority_of_care: true tax_units: tax_unit: members: [person1] @@ -133,22 +145,35 @@ tx_ssi_state_supplement_eligible: false tx_ssi_state_supplement: 0 -- name: Scenario 6, couple both SSI-eligible in Texas Medicaid facility. - # Both members of a couple in a nursing facility +- name: Scenario 6, married SSI couple both in a Texas Medicaid facility. + # Both spouses of a joint SSI claim live in a nursing facility. H-6000: + # "SSA lowers the SSI payment standard to the reduced standard for a couple + # ($60)", i.e. $30 for each spouse, and "HHSC supplements the reduced SSI + # payment standard by $45 per month to ensure SSI recipients also have a $75 + # personal needs allowance." SSA's January 2011 Texas table: "Couples + # residing in this living arrangement for more than 30 days are treated as + # two individuals." period: 2024 input: people: person1: age: 72 - is_ssi_eligible_individual: true + is_tax_unit_head: true is_in_medicaid_facility: true + ssi_lives_in_medical_treatment_facility: true + ssi_medicaid_pays_majority_of_care: true person2: age: 70 - is_ssi_eligible_individual: true + is_tax_unit_spouse: true is_in_medicaid_facility: true + ssi_lives_in_medical_treatment_facility: true + ssi_medicaid_pays_majority_of_care: true tax_units: tax_unit: members: [person1, person2] + marital_units: + marital_unit: + members: [person1, person2] spm_units: spm_unit: members: [person1, person2] @@ -157,7 +182,10 @@ members: [person1, person2] state_code: TX output: - # Both persons are eligible + ssi_claim_is_joint: [true, true] + # Each spouse: $30/month * 12 = $360/year + ssi: [360, 360] + # Both spouses are eligible tx_ssi_state_supplement_eligible: [true, true] # Each person: ($75 - $30) * 12 = $540/year tx_ssi_state_supplement: [540, 540] @@ -169,8 +197,9 @@ people: person1: age: 75 - is_ssi_eligible_individual: true is_in_medicaid_facility: true + ssi_lives_in_medical_treatment_facility: true + ssi_medicaid_pays_majority_of_care: true tax_units: tax_unit: members: [person1] @@ -194,8 +223,9 @@ people: person1: age: 80 - is_ssi_eligible_individual: true is_in_medicaid_facility: true + ssi_lives_in_medical_treatment_facility: true + ssi_medicaid_pays_majority_of_care: true tax_units: tax_unit: members: [person1] @@ -211,3 +241,67 @@ # 2005 PNA: $45/month (set 2003-09-01), Federal reduced SSI: $30/month # Supplement: ($45 - $30) * 12 = $180/year tx_ssi_state_supplement: 180 + +- name: Scenario 9, facility resident whose spouse fails the SSI citizenship condition. + # The undocumented tax-unit spouse receives no SSI (8 USC 1611, 1612), so + # receives no Texas supplement. The citizen head still does. + period: 2024 + input: + people: + person1: + age: 72 + is_tax_unit_head: true + is_in_medicaid_facility: true + ssi_lives_in_medical_treatment_facility: true + ssi_medicaid_pays_majority_of_care: true + person2: + age: 70 + immigration_status_str: UNDOCUMENTED + is_tax_unit_spouse: true + is_in_medicaid_facility: true + ssi_lives_in_medical_treatment_facility: true + ssi_medicaid_pays_majority_of_care: true + tax_units: + tax_unit: + members: [person1, person2] + marital_units: + marital_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: TX + output: + ssi: [360, 0] + tx_ssi_state_supplement_eligible: [true, false] + tx_ssi_state_supplement: [540, 0] + +- name: Scenario 10, facility resident above the SSI resource limit. + # $3,000 of countable resources exceeds the $2,000 SSI limit, so the + # person is not an SSI recipient and H-1500 gives no state supplement. + period: 2024 + input: + people: + person1: + age: 80 + ssi_countable_resources: 3_000 + is_in_medicaid_facility: true + ssi_lives_in_medical_treatment_facility: true + ssi_medicaid_pays_majority_of_care: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: TX + output: + ssi: 0 + tx_ssi_state_supplement_eligible: false + tx_ssi_state_supplement: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/tx/hhsc/ssi_state_supplement/tx_ssi_state_supplement_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/tx/hhsc/ssi_state_supplement/tx_ssi_state_supplement_eligible.yaml index dd95373cc66..b57d90c2f64 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/tx/hhsc/ssi_state_supplement/tx_ssi_state_supplement_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/tx/hhsc/ssi_state_supplement/tx_ssi_state_supplement_eligible.yaml @@ -1,40 +1,52 @@ # Unit tests for Texas SSI State Supplement eligibility -# Eligible if: SSI eligible individual AND residing in a Medicaid-funded facility +# Eligible if: SSI recipient AND residing in a Medicaid-funded facility # AND in Texas -# Reference: Texas Human Resources Code Section 32.024(w) +# Reference: Texas Human Resources Code Section 32.024(w); HHSC MEPD Handbook +# H-1500 ("SSI recipients who live in an institutional setting and receive the +# $30 reduced federal benefit receive a state supplement") -- name: Case 1, SSI eligible and in Medicaid facility in Texas. +- name: Case 1, SSI recipient and in Medicaid facility in Texas. period: 2024 input: - is_ssi_eligible_individual: true + ssi: 360 is_in_medicaid_facility: true state_code: TX output: tx_ssi_state_supplement_eligible: true -- name: Case 2, SSI eligible but not in Medicaid facility. +- name: Case 2, SSI recipient but not in Medicaid facility. period: 2024 input: - is_ssi_eligible_individual: true + ssi: 360 is_in_medicaid_facility: false state_code: TX output: tx_ssi_state_supplement_eligible: false -- name: Case 3, not SSI eligible but in Medicaid facility. +- name: Case 3, not SSI recipient but in Medicaid facility. period: 2024 input: - is_ssi_eligible_individual: false + ssi: 0 is_in_medicaid_facility: true state_code: TX output: tx_ssi_state_supplement_eligible: false -- name: Case 4, neither SSI eligible nor in Medicaid facility. +- name: Case 4, neither SSI recipient nor in Medicaid facility. period: 2024 input: - is_ssi_eligible_individual: false + ssi: 0 is_in_medicaid_facility: false state_code: TX output: tx_ssi_state_supplement_eligible: false + +- name: Case 5, reported SSI receipt qualifies a facility resident with zero computed SSI. + period: 2024-01 + input: + ssi: 0 + receives_ssi: true + is_in_medicaid_facility: true + state_code: TX + output: + tx_ssi_state_supplement_eligible: true diff --git a/policyengine_us/tests/policy/baseline/partners/analytics_coverage/edge_cases/state/co/state_supplement.yaml b/policyengine_us/tests/policy/baseline/partners/analytics_coverage/edge_cases/state/co/state_supplement.yaml index f5176cf680d..6ae5d8e189c 100644 --- a/policyengine_us/tests/policy/baseline/partners/analytics_coverage/edge_cases/state/co/state_supplement.yaml +++ b/policyengine_us/tests/policy/baseline/partners/analytics_coverage/edge_cases/state/co/state_supplement.yaml @@ -1,6 +1,6 @@ # YAML regression-test fixture (policyengine-us partner edge cases). # CO AND-CS state supplement (9 CCR 2503-5 Section 3.546), 2026 parameters: -# ages 0-59, blind/disabled SSI-eligible; benefit = 994/month grant standard (2026) +# ages 0-59, blind/disabled SSI recipients; benefit = 994/month grant standard (2026) # minus (SSI received + SSI-countable income). The 2026 single SSI FBR # (994/mo) exceeds 967, so singles on full SSI get 0; members of an SSI # couple (couple FBR 1,491/mo -> 745.50 each) get a positive supplement. @@ -74,16 +74,14 @@ co_family_affordability_credit: 0.0 # Each member of the SSI couple receives 1,491 / 2 = 745.50/mo SSI; # supplement = (994 - 745.50) x 12 = 248.50 x 12 = 2,982/yr. - # The model pays it only to the SSI "eligible individual" (the head): - # co_state_supplement_eligible checks is_ssi_eligible_individual, - # which is false for the designated "eligible spouse". co_state_supplement: 2_982.0 co_oap: 0.0 spouse: co_family_affordability_credit: 0.0 - # The tax-unit spouse is the SSI "eligible spouse", not an "eligible - # individual", so the current model pays them no AND-CS supplement. - co_state_supplement: 0.0 + # The tax-unit spouse also receives SSI, and 9 CCR 2503-5 3.548(A) + # calculates AND-CS for each client individually, so the spouse + # receives the same 2,982/yr. + co_state_supplement: 2_982.0 co_oap: 0.0 - name: co_state_supplement_single_disabled_fully_offset_by_ssi (co) period: 2026 diff --git a/policyengine_us/variables/gov/states/co/ssa/state_supplement/co_state_supplement_eligible.py b/policyengine_us/variables/gov/states/co/ssa/state_supplement/co_state_supplement_eligible.py index f9c624c8887..ee2c39b882b 100644 --- a/policyengine_us/variables/gov/states/co/ssa/state_supplement/co_state_supplement_eligible.py +++ b/policyengine_us/variables/gov/states/co/ssa/state_supplement/co_state_supplement_eligible.py @@ -7,13 +7,21 @@ class co_state_supplement_eligible(Variable): label = "Colorado State Supplement Eligible" definition_period = MONTH defined_for = StateCode.CO + reference = ( + "https://www.sos.state.co.us/CCR/GenerateRulePdf.do?fileName=9+CCR+2503-5&ruleVersionId=12428#page=91", + "https://www.sos.state.co.us/CCR/GenerateRulePdf.do?fileName=9+CCR+2503-5&ruleVersionId=12428#page=92", + ) def formula(person, period, parameters): - ssi_eligible = person("is_ssi_eligible_individual", period.this_year) + # 9 CCR 2503-5 3.546 and 3.547(A), (D): AND-CS is for clients + # "receiving SSI due to a disability or blindness". 3.548(A) + # calculates grants "on an individual basis with just one client per + # case", so each member of an SSI couple qualifies on their own. + receives_ssi = (person("ssi", period) > 0) | person("receives_ssi", period) is_disabled = person("is_ssi_disabled", period.this_year) is_blind = person("is_blind", period.this_year) disabled_or_blind = is_disabled | is_blind age = person("age", period.this_year) p = parameters(period).gov.states.co.ssa.state_supplement in_age_range = p.age_range.calc(age) - return disabled_or_blind & ssi_eligible & in_age_range + return disabled_or_blind & receives_ssi & in_age_range diff --git a/policyengine_us/variables/gov/states/nm/hca/ssi_supplement/nm_ssi_state_supplement_eligible.py b/policyengine_us/variables/gov/states/nm/hca/ssi_supplement/nm_ssi_state_supplement_eligible.py index 7129f51da12..3e73c285359 100644 --- a/policyengine_us/variables/gov/states/nm/hca/ssi_supplement/nm_ssi_state_supplement_eligible.py +++ b/policyengine_us/variables/gov/states/nm/hca/ssi_supplement/nm_ssi_state_supplement_eligible.py @@ -9,13 +9,18 @@ class nm_ssi_state_supplement_eligible(Variable): defined_for = StateCode.NM reference = ( "https://srca.nm.gov/parts/title08/08.106.0500.html", + "https://srca.nm.gov/parts/title08/08.106.0400.html", "https://www.ssa.gov/policy/docs/progdesc/ssi_st_asst/2011/nm.html", ) def formula(person, period, parameters): - ssi_eligible = person("is_ssi_eligible_individual", period.this_year) + # 8.106.500.10(A) NMAC: "The individual must be a recipient of + # supplemental security income (SSI)". 8.106.400.10(C) NMAC: two SSI + # recipients who would be a family at home are two separate benefit + # groups in residential care, so each spouse receives the payment. + receives_ssi = (person("ssi", period) > 0) | person("receives_ssi", period) age = person("age", period.this_year) p = parameters(period).gov.states.nm.hca.ssi_supplement meets_age = age >= p.min_age in_residential_care = person("is_in_adult_residential_care", period) - return ssi_eligible & meets_age & in_residential_care + return receives_ssi & meets_age & in_residential_care diff --git a/policyengine_us/variables/gov/states/tx/hhsc/ssi_state_supplement/tx_ssi_state_supplement_eligible.py b/policyengine_us/variables/gov/states/tx/hhsc/ssi_state_supplement/tx_ssi_state_supplement_eligible.py index 2bcbdb97b9a..32a3838768d 100644 --- a/policyengine_us/variables/gov/states/tx/hhsc/ssi_state_supplement/tx_ssi_state_supplement_eligible.py +++ b/policyengine_us/variables/gov/states/tx/hhsc/ssi_state_supplement/tx_ssi_state_supplement_eligible.py @@ -10,9 +10,14 @@ class tx_ssi_state_supplement_eligible(Variable): reference = ( "https://statutes.capitol.texas.gov/Docs/HR/htm/HR.32.htm", "https://www.hhs.texas.gov/handbooks/medicaid-elderly-people-disabilities-handbook/h-6000-co-payment-ssi-cases", + "https://www.hhs.texas.gov/handbooks/medicaid-elderly-people-disabilities-handbook/h-1500-personal-needs-allowance", ) def formula(person, period, parameters): - ssi_eligible = person("is_ssi_eligible_individual", period.this_year) + # MEPD Handbook H-1500: "SSI recipients who live in an institutional + # setting and receive the $30 reduced federal benefit receive a state + # supplement." H-6000 gives a couple in a facility the $60 couple + # standard, so each spouse receives the reduced benefit and qualifies. + receives_ssi = (person("ssi", period) > 0) | person("receives_ssi", period) in_facility = person("is_in_medicaid_facility", period) - return ssi_eligible & in_facility + return receives_ssi & in_facility From 72ca048bfeb429a43989da243fe88e651451f586 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Mon, 12 Oct 2026 06:29:22 -0400 Subject: [PATCH 2/5] Add couple invariants for the CO, TX and NM SSI supplements One vectorized simulation of 48 married couples checks that eligibility is SSI receipt, that the result does not depend on which spouse is the tax-unit head, that two citizen spouses are treated alike, and that a spouse failing the SSI citizenship condition is never eligible. main fails the first three; the is_ssi_eligible_individual | is_ssi_eligible_spouse alternative fails the fourth. Co-Authored-By: Claude Opus 5.5 --- ..._ssi_state_supplement_couple_invariants.py | 150 ++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 policyengine_us/tests/core/test_ssi_state_supplement_couple_invariants.py diff --git a/policyengine_us/tests/core/test_ssi_state_supplement_couple_invariants.py b/policyengine_us/tests/core/test_ssi_state_supplement_couple_invariants.py new file mode 100644 index 00000000000..c60f563ba96 --- /dev/null +++ b/policyengine_us/tests/core/test_ssi_state_supplement_couple_invariants.py @@ -0,0 +1,150 @@ +"""Invariants for the CO, TX and NM SSI supplements over married couples. + +Each state pays every SSI recipient on their own (9 CCR 2503-5 3.546-3.548; +HHSC MEPD Handbook H-1500 and H-6000; 8.106.400.10(C) and 8.106.500.10 NMAC), +so a spouse's supplement must not depend on which spouse holds the tax-unit +head role. The grid crosses state, role assignment, the second spouse's +citizenship, the first spouse's resources and an equal pension for both +spouses: 48 married couples (96 people) in one vectorized simulation. + +Checked for every person in the grid: + +1. Receipt: eligibility holds exactly when the person receives SSI (every + other program condition is met by construction, and no one reports SSI + receipt). +2. Role invariance: eligibility and the supplement are identical when the + head and spouse roles are swapped. +3. Couples: when both spouses are citizens, they have the same eligibility and + the same supplement. +4. Citizenship: a spouse who fails the SSI citizenship condition is never + eligible. + +YAML covers the source examples and their amounts. Python is needed here to +compare each person across role assignments in one simulation. +""" + +from itertools import product + +import numpy as np +import pytest + +from policyengine_us import Simulation + + +YEAR = 2026 +PERIOD = "2026-01" +STATES = ("CO", "TX", "NM") +ROLE_ORDERS = ("first_is_head", "second_is_head") +SECOND_CITIZENSHIP = ("CITIZEN", "UNDOCUMENTED") +FIRST_RESOURCES = (0, 4_000) +ANNUAL_PENSION = (0, 3_600) +GRID = tuple( + product(STATES, ROLE_ORDERS, SECOND_CITIZENSHIP, FIRST_RESOURCES, ANNUAL_PENSION) +) +PROGRAMS = { + "CO": ("co_state_supplement_eligible", "co_state_supplement"), + "TX": ("tx_ssi_state_supplement_eligible", "tx_ssi_state_supplement"), + "NM": ("nm_ssi_state_supplement_eligible", "nm_ssi_state_supplement"), +} +# Each state's program conditions other than SSI receipt. +STATE_INPUTS = { + # AND-CS: blind or disabled, ages 0-59. + "CO": dict( + ages=(50, 52), + is_disabled=True, + meets_ssi_disability_criteria=True, + ), + # SSI recipient in a Medicaid facility on the $30 reduced benefit. + "TX": dict( + ages=(72, 70), + is_in_medicaid_facility=True, + ssi_lives_in_medical_treatment_facility=True, + ssi_medicaid_pays_majority_of_care=True, + ), + # SSI recipient aged 18 or over in a licensed ARSCH home. + "NM": dict(ages=(68, 66), is_in_adult_residential_care=True), +} + + +def _situation(): + groups = ("tax_units", "marital_units", "spm_units", "families", "households") + situation = {"people": {}, **{group: {} for group in groups}} + for index, (state, order, citizenship, resources, pension) in enumerate(GRID): + conditions = dict(STATE_INPUTS[state]) + ages = conditions.pop("ages") + members = [f"couple{index}_first", f"couple{index}_second"] + head = 0 if order == "first_is_head" else 1 + for position, member in enumerate(members): + person = { + "age": {YEAR: ages[position]}, + "is_tax_unit_head": {YEAR: position == head}, + "is_tax_unit_spouse": {YEAR: position != head}, + "pension_income": {YEAR: pension}, + "ssi_countable_resources": {YEAR: resources if position == 0 else 0}, + "immigration_status_str": { + YEAR: citizenship if position == 1 else "CITIZEN" + }, + } + person.update({name: {YEAR: value} for name, value in conditions.items()}) + situation["people"][member] = person + for group in groups: + situation[group][f"{group}_{index}"] = {"members": members} + situation["households"][f"households_{index}"]["state_code"] = {YEAR: state} + return situation + + +@pytest.fixture(scope="module") +def results(): + simulation = Simulation(situation=_situation()) + ssi = simulation.calculate("ssi", PERIOD).reshape(len(GRID), 2) + eligible = np.zeros_like(ssi, dtype=bool) + supplement = np.zeros_like(ssi) + for index, (state, *_rest) in enumerate(GRID): + eligible_variable, amount_variable = PROGRAMS[state] + rows = slice(2 * index, 2 * index + 2) + eligible[index] = simulation.calculate(eligible_variable, PERIOD)[rows] + supplement[index] = simulation.calculate(amount_variable, PERIOD)[rows] + return ssi, eligible, supplement + + +def _case(state, order, citizenship, resources, pension): + return GRID.index((state, order, citizenship, resources, pension)) + + +def test_eligibility_is_ssi_receipt(results): + ssi, eligible, _ = results + np.testing.assert_array_equal(eligible, ssi > 0) + + +def test_supplement_does_not_depend_on_tax_unit_roles(results): + _, eligible, supplement = results + for state, citizenship, resources, pension in product( + STATES, SECOND_CITIZENSHIP, FIRST_RESOURCES, ANNUAL_PENSION + ): + first = _case(state, "first_is_head", citizenship, resources, pension) + second = _case(state, "second_is_head", citizenship, resources, pension) + np.testing.assert_array_equal(eligible[first], eligible[second]) + np.testing.assert_allclose(supplement[first], supplement[second]) + + +def test_citizen_spouses_are_treated_alike(results): + _, eligible, supplement = results + for index, (_state, _order, citizenship, _resources, _pension) in enumerate(GRID): + if citizenship == "CITIZEN": + assert eligible[index, 0] == eligible[index, 1] + assert supplement[index, 0] == pytest.approx(supplement[index, 1]) + + +def test_spouse_failing_citizenship_condition_is_never_eligible(results): + _, eligible, supplement = results + for index, (_state, _order, citizenship, _resources, _pension) in enumerate(GRID): + if citizenship == "UNDOCUMENTED": + assert not eligible[index, 1] + assert supplement[index, 1] == 0 + + +def test_grid_reaches_both_outcomes_for_each_state(results): + _, eligible, _ = results + for state in STATES: + rows = [index for index, case in enumerate(GRID) if case[0] == state] + assert eligible[rows].any() and not eligible[rows].all() From f2d650669e749016fb6d85aa40d5a8d327d16c69 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Mon, 12 Oct 2026 06:48:33 -0400 Subject: [PATCH 3/5] Count CO AND-CS spouses' own income; keep TX's $0-payment boundary Review round 1 (GPT-6.1 Sol): - Colorado: 9 CCR 2503-5 3.549(A) counts each AND-CS client's own income, with the $20 disregard split between spouses and no deeming between SSI-recipient spouses (3.549(F)). The model used ssi_countable_income, which halves a joint claim's pooled income. New co_state_supplement_countable_income does the per-client count where SSI's couple computation applies and keeps the federal amount elsewhere. - Texas: H-6000 keeps a facility resident eligible for SSI when countable income "does not exceed" the $30 reduced standard, and 42 USC 1382(a)(1)(A) agrees, so gate on SSI eligibility within the limit (a $0 payment included) plus take-up, or reported receipt. - One reference per document for the CO rule PDF. Also reverts the partner fixture edit: partner API contract tests change only after Ziming Hua approves (CLAUDE.md). Co-Authored-By: Claude Opus 5.5 --- ...plement-couple-spouse-eligibility.fixed.md | 2 +- ..._ssi_state_supplement_couple_invariants.py | 147 ++++++++++++------ .../state_supplement/co_state_supplement.yaml | 77 +++++++++ .../co_state_supplement_countable_income.yaml | 74 +++++++++ .../ssi_state_supplement/integration.yaml | 57 +++++++ .../tx_ssi_state_supplement_eligible.yaml | 59 +++++-- .../edge_cases/state/co/state_supplement.yaml | 12 +- .../state_supplement/co_state_supplement.py | 2 +- .../co_state_supplement_countable_income.py | 46 ++++++ .../co_state_supplement_eligible.py | 6 +- .../tx_ssi_state_supplement_eligible.py | 17 +- 11 files changed, 422 insertions(+), 77 deletions(-) create mode 100644 policyengine_us/tests/policy/baseline/gov/states/co/ssa/state_supplement/co_state_supplement_countable_income.yaml create mode 100644 policyengine_us/variables/gov/states/co/ssa/state_supplement/co_state_supplement_countable_income.py diff --git a/changelog.d/ssi-supplement-couple-spouse-eligibility.fixed.md b/changelog.d/ssi-supplement-couple-spouse-eligibility.fixed.md index 602b88b4c35..82a22b68683 100644 --- a/changelog.d/ssi-supplement-couple-spouse-eligibility.fixed.md +++ b/changelog.d/ssi-supplement-couple-spouse-eligibility.fixed.md @@ -1 +1 @@ -Pay the Colorado AND-CS, Texas SSI facility and New Mexico residential care supplements to SSI recipients, so both members of an SSI couple qualify instead of only the one labelled the eligible individual. +Pay the Colorado AND-CS, Texas SSI facility and New Mexico residential care supplements to SSI recipients, so both members of an SSI couple qualify instead of only the one labelled the eligible individual. Colorado AND-CS now counts each spouse's own income (9 CCR 2503-5 3.549), and Texas keeps a facility resident whose countable income equals the $30 reduced standard. diff --git a/policyengine_us/tests/core/test_ssi_state_supplement_couple_invariants.py b/policyengine_us/tests/core/test_ssi_state_supplement_couple_invariants.py index c60f563ba96..afdf7772920 100644 --- a/policyengine_us/tests/core/test_ssi_state_supplement_couple_invariants.py +++ b/policyengine_us/tests/core/test_ssi_state_supplement_couple_invariants.py @@ -1,26 +1,34 @@ """Invariants for the CO, TX and NM SSI supplements over married couples. -Each state pays every SSI recipient on their own (9 CCR 2503-5 3.546-3.548; +Each state pays every SSI recipient on their own (9 CCR 2503-5 3.546-3.549; HHSC MEPD Handbook H-1500 and H-6000; 8.106.400.10(C) and 8.106.500.10 NMAC), so a spouse's supplement must not depend on which spouse holds the tax-unit head role. The grid crosses state, role assignment, the second spouse's -citizenship, the first spouse's resources and an equal pension for both -spouses: 48 married couples (96 people) in one vectorized simulation. +citizenship, the first spouse's resources and the two spouses' monthly +pensions (none, $300 each, or $400 and $200): 72 married couples (144 people) +in one vectorized simulation. Checked for every person in the grid: -1. Receipt: eligibility holds exactly when the person receives SSI (every - other program condition is met by construction, and no one reports SSI - receipt). +1. Receipt: anyone paid SSI is eligible, and no one is eligible without being + eligible for SSI with countable income not over the payment standard (no + one in the grid reports SSI receipt, and every other program condition is + met by construction). In Colorado and New Mexico eligibility is exactly a + positive SSI payment. 2. Role invariance: eligibility and the supplement are identical when the head and spouse roles are swapped. -3. Couples: when both spouses are citizens, they have the same eligibility and - the same supplement. +3. Couples: two citizen spouses with the same income have the same + eligibility and the same supplement. 4. Citizenship: a spouse who fails the SSI citizenship condition is never eligible. +5. Colorado couple total: when both spouses of a joint SSI claim receive + AND-CS, the two grants sum to twice the grant standard less the couple's + federal SSI and pooled countable income, as in SSA's Colorado couple + payment level (1,398 = 2 x 699 in January 2011), however 3.549(A) divides + their own income between them. YAML covers the source examples and their amounts. Python is needed here to -compare each person across role assignments in one simulation. +compare each person across role assignments and spouses in one simulation. """ from itertools import product @@ -37,16 +45,17 @@ ROLE_ORDERS = ("first_is_head", "second_is_head") SECOND_CITIZENSHIP = ("CITIZEN", "UNDOCUMENTED") FIRST_RESOURCES = (0, 4_000) -ANNUAL_PENSION = (0, 3_600) +# Monthly pensions of the first and second spouse. +PENSIONS = ((0, 0), (300, 300), (400, 200)) GRID = tuple( - product(STATES, ROLE_ORDERS, SECOND_CITIZENSHIP, FIRST_RESOURCES, ANNUAL_PENSION) + product(STATES, ROLE_ORDERS, SECOND_CITIZENSHIP, FIRST_RESOURCES, PENSIONS) ) PROGRAMS = { "CO": ("co_state_supplement_eligible", "co_state_supplement"), "TX": ("tx_ssi_state_supplement_eligible", "tx_ssi_state_supplement"), "NM": ("nm_ssi_state_supplement_eligible", "nm_ssi_state_supplement"), } -# Each state's program conditions other than SSI receipt. +# Each state's program conditions other than SSI. STATE_INPUTS = { # AND-CS: blind or disabled, ages 0-59. "CO": dict( @@ -69,7 +78,7 @@ def _situation(): groups = ("tax_units", "marital_units", "spm_units", "families", "households") situation = {"people": {}, **{group: {} for group in groups}} - for index, (state, order, citizenship, resources, pension) in enumerate(GRID): + for index, (state, order, citizenship, resources, pensions) in enumerate(GRID): conditions = dict(STATE_INPUTS[state]) ages = conditions.pop("ages") members = [f"couple{index}_first", f"couple{index}_second"] @@ -79,7 +88,7 @@ def _situation(): "age": {YEAR: ages[position]}, "is_tax_unit_head": {YEAR: position == head}, "is_tax_unit_spouse": {YEAR: position != head}, - "pension_income": {YEAR: pension}, + "pension_income": {YEAR: 12 * pensions[position]}, "ssi_countable_resources": {YEAR: resources if position == 0 else 0}, "immigration_status_str": { YEAR: citizenship if position == 1 else "CITIZEN" @@ -96,55 +105,91 @@ def _situation(): @pytest.fixture(scope="module") def results(): simulation = Simulation(situation=_situation()) - ssi = simulation.calculate("ssi", PERIOD).reshape(len(GRID), 2) - eligible = np.zeros_like(ssi, dtype=bool) - supplement = np.zeros_like(ssi) - for index, (state, *_rest) in enumerate(GRID): - eligible_variable, amount_variable = PROGRAMS[state] - rows = slice(2 * index, 2 * index + 2) - eligible[index] = simulation.calculate(eligible_variable, PERIOD)[rows] - supplement[index] = simulation.calculate(amount_variable, PERIOD)[rows] - return ssi, eligible, supplement + def couples(variable, period=PERIOD): + return simulation.calculate(variable, period).reshape(len(GRID), 2) -def _case(state, order, citizenship, resources, pension): - return GRID.index((state, order, citizenship, resources, pension)) - - -def test_eligibility_is_ssi_receipt(results): - ssi, eligible, _ = results - np.testing.assert_array_equal(eligible, ssi > 0) + eligible = np.zeros((len(GRID), 2), dtype=bool) + supplement = np.zeros((len(GRID), 2)) + for state, (eligible_variable, amount_variable) in PROGRAMS.items(): + rows = [index for index, case in enumerate(GRID) if case[0] == state] + eligible[rows] = couples(eligible_variable)[rows] + supplement[rows] = couples(amount_variable)[rows] + parameters = simulation.tax_benefit_system.parameters(PERIOD) + return dict( + grant_standard=parameters.gov.states.co.ssa.state_supplement.grant_standard, + ssi=couples("ssi"), + ssi_eligible=couples("is_ssi_eligible"), + uncapped_ssi=couples("uncapped_ssi"), + joint=couples("ssi_claim_is_joint", YEAR), + federal_countable=couples("ssi_countable_income", YEAR) / 12, + eligible=eligible, + supplement=supplement, + ) + + +def _rows(**fixed): + names = ("state", "order", "citizenship", "resources", "pensions") + return [ + index + for index, case in enumerate(GRID) + if all(case[names.index(name)] == value for name, value in fixed.items()) + ] + + +def test_eligibility_follows_ssi_eligibility(results): + paid = results["ssi"] > 0 + within_limit = results["ssi_eligible"] & (results["uncapped_ssi"] >= 0) + eligible = results["eligible"] + assert not (paid & ~eligible).any() + assert not (eligible & ~within_limit).any() + for state in ("CO", "NM"): + rows = _rows(state=state) + np.testing.assert_array_equal(eligible[rows], paid[rows]) def test_supplement_does_not_depend_on_tax_unit_roles(results): - _, eligible, supplement = results - for state, citizenship, resources, pension in product( - STATES, SECOND_CITIZENSHIP, FIRST_RESOURCES, ANNUAL_PENSION + for state, citizenship, resources, pensions in product( + STATES, SECOND_CITIZENSHIP, FIRST_RESOURCES, PENSIONS ): - first = _case(state, "first_is_head", citizenship, resources, pension) - second = _case(state, "second_is_head", citizenship, resources, pension) - np.testing.assert_array_equal(eligible[first], eligible[second]) - np.testing.assert_allclose(supplement[first], supplement[second]) + first, second = ( + GRID.index((state, order, citizenship, resources, pensions)) + for order in ROLE_ORDERS + ) + for name in ("eligible", "supplement"): + np.testing.assert_allclose(results[name][first], results[name][second]) -def test_citizen_spouses_are_treated_alike(results): - _, eligible, supplement = results - for index, (_state, _order, citizenship, _resources, _pension) in enumerate(GRID): - if citizenship == "CITIZEN": - assert eligible[index, 0] == eligible[index, 1] - assert supplement[index, 0] == pytest.approx(supplement[index, 1]) +def test_citizen_spouses_with_equal_income_are_treated_alike(results): + for index, (_, _, citizenship, _, pensions) in enumerate(GRID): + if citizenship == "CITIZEN" and pensions[0] == pensions[1]: + for name in ("eligible", "supplement"): + assert results[name][index, 0] == pytest.approx(results[name][index, 1]) def test_spouse_failing_citizenship_condition_is_never_eligible(results): - _, eligible, supplement = results - for index, (_state, _order, citizenship, _resources, _pension) in enumerate(GRID): - if citizenship == "UNDOCUMENTED": - assert not eligible[index, 1] - assert supplement[index, 1] == 0 + rows = _rows(citizenship="UNDOCUMENTED") + assert not results["eligible"][rows, 1].any() + assert not results["supplement"][rows, 1].any() + + +def test_colorado_couple_total_matches_pooled_computation(results): + rows = [ + index + for index in _rows(state="CO") + if results["joint"][index].all() and results["eligible"][index].all() + ] + assert rows + pooled = ( + 2 * results["grant_standard"] + - results["ssi"][rows].sum(axis=1) + - results["federal_countable"][rows].sum(axis=1) + ) + np.testing.assert_allclose(results["supplement"][rows].sum(axis=1), pooled) def test_grid_reaches_both_outcomes_for_each_state(results): - _, eligible, _ = results for state in STATES: - rows = [index for index, case in enumerate(GRID) if case[0] == state] - assert eligible[rows].any() and not eligible[rows].all() + rows = _rows(state=state) + assert results["eligible"][rows].any() + assert not results["eligible"][rows].all() diff --git a/policyengine_us/tests/policy/baseline/gov/states/co/ssa/state_supplement/co_state_supplement.yaml b/policyengine_us/tests/policy/baseline/gov/states/co/ssa/state_supplement/co_state_supplement.yaml index 5a6a467da21..81412960d86 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/co/ssa/state_supplement/co_state_supplement.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/co/ssa/state_supplement/co_state_supplement.yaml @@ -220,3 +220,80 @@ output: ssi: 0 co_state_supplement: 0 + +- name: Case 17, a disabled SSI couple with unequal pensions each count their own income. + # Pensions of $400 and $200 a month. Federal SSI pools them: 600 - 20 = 580 + # countable, so the couple payment is 1,491 - 580 = 911, or 455.50 each. + # 3.549(A)(2) counts each client's own income with the $20 disregard split + # between the spouses: head 400 - 10 = 390, spouse 200 - 10 = 190. Grants: + # head 994 - 455.50 - 390 = 148.50/month (1,782/year); spouse + # 994 - 455.50 - 190 = 348.50/month (4,182/year). The couple total is the + # same 497/month as with equal pensions. + absolute_error_margin: 0.1 + period: 2026 + input: + people: + head: + age: 50 + is_disabled: true + meets_ssi_disability_criteria: true + pension_income: 4_800 + is_tax_unit_head: true + spouse: + age: 52 + is_disabled: true + meets_ssi_disability_criteria: true + pension_income: 2_400 + is_tax_unit_spouse: true + tax_units: + tax_unit: + members: [head, spouse] + marital_units: + marital_unit: + members: [head, spouse] + households: + household: + members: [head, spouse] + state_code: CO + output: + ssi: [5_466, 5_466] + co_state_supplement_countable_income: [4_680, 2_280] + co_state_supplement: [1_782, 4_182] + +- name: Case 18, a disabled SSI couple where only the head has earnings. + # The head earns $500/month and the spouse has no income. Federal SSI pools + # earnings: (500 - 20 - 65) / 2 = 207.50 countable, so the couple payment is + # 1,491 - 207.50 = 1,283.50, or 641.75 each. 3.549(A): the head's $10 share + # of the disregard goes to earned income (3.549(A)(2)(f)), then $65, then + # half: (500 - 10 - 65) / 2 = 212.50. Head grant 994 - 641.75 - 212.50 = + # 139.75/month (1,677/year); spouse 994 - 641.75 = 352.25/month + # (4,227/year). + absolute_error_margin: 0.1 + period: 2026 + input: + people: + head: + age: 50 + is_disabled: true + meets_ssi_disability_criteria: true + employment_income: 6_000 + is_tax_unit_head: true + spouse: + age: 52 + is_disabled: true + meets_ssi_disability_criteria: true + is_tax_unit_spouse: true + tax_units: + tax_unit: + members: [head, spouse] + marital_units: + marital_unit: + members: [head, spouse] + households: + household: + members: [head, spouse] + state_code: CO + output: + ssi: [7_701, 7_701] + co_state_supplement_countable_income: [2_550, 0] + co_state_supplement: [1_677, 4_227] diff --git a/policyengine_us/tests/policy/baseline/gov/states/co/ssa/state_supplement/co_state_supplement_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/co/ssa/state_supplement/co_state_supplement_countable_income.yaml new file mode 100644 index 00000000000..c5073147e9f --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/co/ssa/state_supplement/co_state_supplement_countable_income.yaml @@ -0,0 +1,74 @@ +- name: Case 1, a single client's countable income is their SSI countable income. + period: 2026 + input: + ssi_countable_income: 3_000 + state_code: CO + output: + co_state_supplement_countable_income: 3_000 + +- name: Case 2, spouses of a joint SSI claim each count their own income. + # 9 CCR 2503-5 3.549(A)(2): own unearned income less the client's half of + # the $20 disregard. Pensions of $400 and $200 a month give 390 and 190 + # a month, or 4,680 and 2,280 a year. Federal SSI would give each half of + # the pooled 580, or 290 a month. + period: 2026 + input: + people: + head: + age: 50 + is_disabled: true + meets_ssi_disability_criteria: true + pension_income: 4_800 + is_tax_unit_head: true + spouse: + age: 52 + is_disabled: true + meets_ssi_disability_criteria: true + pension_income: 2_400 + is_tax_unit_spouse: true + tax_units: + tax_unit: + members: [head, spouse] + marital_units: + marital_unit: + members: [head, spouse] + households: + household: + members: [head, spouse] + state_code: CO + output: + ssi_countable_income: [3_480, 3_480] + co_state_supplement_countable_income: [4_680, 2_280] + +- name: Case 3, a spouse's unused share of the disregard goes to their earnings. + # The spouse has $5/month of interest and $200/month of earnings. Their $10 + # share of the disregard covers the $5 of unearned income and the other $5 + # goes to earnings (3.549(A)(2)(f)): (200 - 5 - 65) / 2 = 65 a month, or + # 780 a year. + period: 2026 + input: + people: + head: + age: 50 + is_disabled: true + meets_ssi_disability_criteria: true + is_tax_unit_head: true + spouse: + age: 52 + is_disabled: true + meets_ssi_disability_criteria: true + interest_income: 60 + employment_income: 2_400 + is_tax_unit_spouse: true + tax_units: + tax_unit: + members: [head, spouse] + marital_units: + marital_unit: + members: [head, spouse] + households: + household: + members: [head, spouse] + state_code: CO + output: + co_state_supplement_countable_income: [0, 780] diff --git a/policyengine_us/tests/policy/baseline/gov/states/tx/hhsc/ssi_state_supplement/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/tx/hhsc/ssi_state_supplement/integration.yaml index 358ed96957b..86db34e9553 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/tx/hhsc/ssi_state_supplement/integration.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/tx/hhsc/ssi_state_supplement/integration.yaml @@ -305,3 +305,60 @@ ssi: 0 tx_ssi_state_supplement_eligible: false tx_ssi_state_supplement: 0 + +- name: Scenario 11, facility resident whose countable income equals the $30 reduced standard. + # A $50/month pension less the $20 general exclusion is $30 of countable + # income, so the federal payment is $30 - $30 = $0. H-6000: the resident + # "remains eligible for SSI if their countable income does not exceed the + # SSI reduced standard payment amount", and HHSC pays the $45 supplement. + period: 2024 + input: + people: + person1: + age: 80 + pension_income: 600 + is_in_medicaid_facility: true + ssi_lives_in_medical_treatment_facility: true + ssi_medicaid_pays_majority_of_care: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: TX + output: + ssi: 0 + tx_ssi_state_supplement_eligible: true + # ($75 - $30) * 12 = $540/year + tx_ssi_state_supplement: 540 + +- name: Scenario 12, facility resident whose countable income exceeds the $30 reduced standard. + # A $51/month pension gives $31 of countable income, above the reduced + # standard, so the resident is not eligible for SSI or the supplement. + period: 2024 + input: + people: + person1: + age: 80 + pension_income: 612 + is_in_medicaid_facility: true + ssi_lives_in_medical_treatment_facility: true + ssi_medicaid_pays_majority_of_care: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: TX + output: + ssi: 0 + tx_ssi_state_supplement_eligible: false + tx_ssi_state_supplement: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/tx/hhsc/ssi_state_supplement/tx_ssi_state_supplement_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/tx/hhsc/ssi_state_supplement/tx_ssi_state_supplement_eligible.yaml index b57d90c2f64..b98ca5a2c0c 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/tx/hhsc/ssi_state_supplement/tx_ssi_state_supplement_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/tx/hhsc/ssi_state_supplement/tx_ssi_state_supplement_eligible.yaml @@ -1,14 +1,19 @@ # Unit tests for Texas SSI State Supplement eligibility -# Eligible if: SSI recipient AND residing in a Medicaid-funded facility -# AND in Texas +# Eligible if: eligible for SSI with countable income not over the payment +# standard (a $0 federal payment at the limit included) and takes up SSI, or +# reported to receive SSI; AND residing in a Medicaid-funded facility; AND in +# Texas # Reference: Texas Human Resources Code Section 32.024(w); HHSC MEPD Handbook # H-1500 ("SSI recipients who live in an institutional setting and receive the -# $30 reduced federal benefit receive a state supplement") +# $30 reduced federal benefit receive a state supplement") and H-6000 (an SSI +# recipient in a facility "remains eligible for SSI if their countable income +# does not exceed the SSI reduced standard payment amount") - name: Case 1, SSI recipient and in Medicaid facility in Texas. period: 2024 input: - ssi: 360 + is_ssi_eligible: true + uncapped_ssi: 360 is_in_medicaid_facility: true state_code: TX output: @@ -17,36 +22,68 @@ - name: Case 2, SSI recipient but not in Medicaid facility. period: 2024 input: - ssi: 360 + is_ssi_eligible: true + uncapped_ssi: 360 is_in_medicaid_facility: false state_code: TX output: tx_ssi_state_supplement_eligible: false -- name: Case 3, not SSI recipient but in Medicaid facility. +- name: Case 3, not SSI eligible but in Medicaid facility. period: 2024 input: - ssi: 0 + is_ssi_eligible: false is_in_medicaid_facility: true state_code: TX output: tx_ssi_state_supplement_eligible: false -- name: Case 4, neither SSI recipient nor in Medicaid facility. +- name: Case 4, neither SSI eligible nor in Medicaid facility. period: 2024 input: - ssi: 0 + is_ssi_eligible: false is_in_medicaid_facility: false state_code: TX output: tx_ssi_state_supplement_eligible: false -- name: Case 5, reported SSI receipt qualifies a facility resident with zero computed SSI. +- name: Case 5, reported SSI receipt qualifies a facility resident. period: 2024-01 input: - ssi: 0 + is_ssi_eligible: false receives_ssi: true is_in_medicaid_facility: true state_code: TX output: tx_ssi_state_supplement_eligible: true + +- name: Case 6, countable income equal to the reduced standard leaves a $0 federal payment and stays eligible. + period: 2024-01 + input: + is_ssi_eligible: true + uncapped_ssi: 0 + is_in_medicaid_facility: true + state_code: TX + output: + tx_ssi_state_supplement_eligible: true + +- name: Case 7, countable income above the reduced standard is not eligible. + period: 2024-01 + input: + is_ssi_eligible: true + uncapped_ssi: -1 + is_in_medicaid_facility: true + state_code: TX + output: + tx_ssi_state_supplement_eligible: false + +- name: Case 8, a facility resident who does not take up SSI is not eligible. + period: 2024-01 + input: + is_ssi_eligible: true + uncapped_ssi: 30 + takes_up_ssi_if_eligible: false + is_in_medicaid_facility: true + state_code: TX + output: + tx_ssi_state_supplement_eligible: false diff --git a/policyengine_us/tests/policy/baseline/partners/analytics_coverage/edge_cases/state/co/state_supplement.yaml b/policyengine_us/tests/policy/baseline/partners/analytics_coverage/edge_cases/state/co/state_supplement.yaml index 6ae5d8e189c..f5176cf680d 100644 --- a/policyengine_us/tests/policy/baseline/partners/analytics_coverage/edge_cases/state/co/state_supplement.yaml +++ b/policyengine_us/tests/policy/baseline/partners/analytics_coverage/edge_cases/state/co/state_supplement.yaml @@ -1,6 +1,6 @@ # YAML regression-test fixture (policyengine-us partner edge cases). # CO AND-CS state supplement (9 CCR 2503-5 Section 3.546), 2026 parameters: -# ages 0-59, blind/disabled SSI recipients; benefit = 994/month grant standard (2026) +# ages 0-59, blind/disabled SSI-eligible; benefit = 994/month grant standard (2026) # minus (SSI received + SSI-countable income). The 2026 single SSI FBR # (994/mo) exceeds 967, so singles on full SSI get 0; members of an SSI # couple (couple FBR 1,491/mo -> 745.50 each) get a positive supplement. @@ -74,14 +74,16 @@ co_family_affordability_credit: 0.0 # Each member of the SSI couple receives 1,491 / 2 = 745.50/mo SSI; # supplement = (994 - 745.50) x 12 = 248.50 x 12 = 2,982/yr. + # The model pays it only to the SSI "eligible individual" (the head): + # co_state_supplement_eligible checks is_ssi_eligible_individual, + # which is false for the designated "eligible spouse". co_state_supplement: 2_982.0 co_oap: 0.0 spouse: co_family_affordability_credit: 0.0 - # The tax-unit spouse also receives SSI, and 9 CCR 2503-5 3.548(A) - # calculates AND-CS for each client individually, so the spouse - # receives the same 2,982/yr. - co_state_supplement: 2_982.0 + # The tax-unit spouse is the SSI "eligible spouse", not an "eligible + # individual", so the current model pays them no AND-CS supplement. + co_state_supplement: 0.0 co_oap: 0.0 - name: co_state_supplement_single_disabled_fully_offset_by_ssi (co) period: 2026 diff --git a/policyengine_us/variables/gov/states/co/ssa/state_supplement/co_state_supplement.py b/policyengine_us/variables/gov/states/co/ssa/state_supplement/co_state_supplement.py index da55e8d65e7..dac180acbd4 100644 --- a/policyengine_us/variables/gov/states/co/ssa/state_supplement/co_state_supplement.py +++ b/policyengine_us/variables/gov/states/co/ssa/state_supplement/co_state_supplement.py @@ -9,7 +9,7 @@ class co_state_supplement(Variable): defined_for = "co_state_supplement_eligible" def formula(person, period, parameters): - income = person("ssi_countable_income", period) + income = person("co_state_supplement_countable_income", period) ssi = person("ssi", period) total_countable_income = ssi + income p = parameters(period).gov.states.co.ssa.state_supplement diff --git a/policyengine_us/variables/gov/states/co/ssa/state_supplement/co_state_supplement_countable_income.py b/policyengine_us/variables/gov/states/co/ssa/state_supplement/co_state_supplement_countable_income.py new file mode 100644 index 00000000000..edb2c489e02 --- /dev/null +++ b/policyengine_us/variables/gov/states/co/ssa/state_supplement/co_state_supplement_countable_income.py @@ -0,0 +1,46 @@ +from policyengine_us.model_api import * +from policyengine_us.variables.gov.ssa.ssi.eligibility.income._apply_ssi_exclusions import ( + _apply_ssi_exclusions, +) + + +class co_state_supplement_countable_income(Variable): + value_type = float + entity = Person + label = "Colorado State Supplement countable income" + unit = USD + definition_period = YEAR + # PDF pages 93-94 + reference = "https://www.sos.state.co.us/CCR/GenerateRulePdf.do?fileName=9+CCR+2503-5&ruleVersionId=12428#page=93" + + def formula(person, period, parameters): + # 9 CCR 2503-5 3.549(A) counts each AND-CS client's own income. Where + # SSI's couple computation applies, ssi_countable_income instead gives + # each spouse half of the couple's pooled countable income. Both + # spouses then receive SSI, so 3.549(F) deems neither spouse's income + # to the other, and 3.549(A)(2)(c)(1) splits the $20 unearned income + # disregard "between the client and the spouse"; it is split equally + # here. Any part a spouse cannot use against unearned income goes to + # their earned income (3.549(A)(2)(f)), as _apply_ssi_exclusions does. + couple_computation = person("ssi_couple_computation_applies", period) + earned = max_( + person("ssi_earned_income", period) + - person("ssi_blind_or_disabled_working_student_exclusion", period), + 0, + ) + unearned = person("ssi_unearned_income", period) + person( + "ssi_in_kind_support_and_maintenance", period + ) + p = parameters(period).gov.ssa.ssi.income.exclusions + own_countable = _apply_ssi_exclusions( + earned, + unearned, + parameters, + period, + general_exclusion=p.general / 2, + ) + return where( + couple_computation, + own_countable, + person("ssi_countable_income", period), + ) diff --git a/policyengine_us/variables/gov/states/co/ssa/state_supplement/co_state_supplement_eligible.py b/policyengine_us/variables/gov/states/co/ssa/state_supplement/co_state_supplement_eligible.py index ee2c39b882b..24e9ea2c409 100644 --- a/policyengine_us/variables/gov/states/co/ssa/state_supplement/co_state_supplement_eligible.py +++ b/policyengine_us/variables/gov/states/co/ssa/state_supplement/co_state_supplement_eligible.py @@ -7,10 +7,8 @@ class co_state_supplement_eligible(Variable): label = "Colorado State Supplement Eligible" definition_period = MONTH defined_for = StateCode.CO - reference = ( - "https://www.sos.state.co.us/CCR/GenerateRulePdf.do?fileName=9+CCR+2503-5&ruleVersionId=12428#page=91", - "https://www.sos.state.co.us/CCR/GenerateRulePdf.do?fileName=9+CCR+2503-5&ruleVersionId=12428#page=92", - ) + # PDF pages 91-92 + reference = "https://www.sos.state.co.us/CCR/GenerateRulePdf.do?fileName=9+CCR+2503-5&ruleVersionId=12428#page=91" def formula(person, period, parameters): # 9 CCR 2503-5 3.546 and 3.547(A), (D): AND-CS is for clients diff --git a/policyengine_us/variables/gov/states/tx/hhsc/ssi_state_supplement/tx_ssi_state_supplement_eligible.py b/policyengine_us/variables/gov/states/tx/hhsc/ssi_state_supplement/tx_ssi_state_supplement_eligible.py index 32a3838768d..1f6849e00f5 100644 --- a/policyengine_us/variables/gov/states/tx/hhsc/ssi_state_supplement/tx_ssi_state_supplement_eligible.py +++ b/policyengine_us/variables/gov/states/tx/hhsc/ssi_state_supplement/tx_ssi_state_supplement_eligible.py @@ -16,8 +16,17 @@ class tx_ssi_state_supplement_eligible(Variable): def formula(person, period, parameters): # MEPD Handbook H-1500: "SSI recipients who live in an institutional # setting and receive the $30 reduced federal benefit receive a state - # supplement." H-6000 gives a couple in a facility the $60 couple - # standard, so each spouse receives the reduced benefit and qualifies. - receives_ssi = (person("ssi", period) > 0) | person("receives_ssi", period) + # supplement." H-6000: such a person "remains eligible for SSI if + # their countable income does not exceed the SSI reduced standard + # payment amount", including income equal to it and a $0 federal + # payment (42 USC 1382(a)(1)(A): income "not more than" the rate). + # H-6000 gives a couple in a facility the $60 couple standard, so + # each spouse is assessed on their own half. + eligible_for_ssi = ( + person("is_ssi_eligible", period) + & person("takes_up_ssi_if_eligible", period.this_year) + & (person("uncapped_ssi", period) >= 0) + ) + receives_ssi = person("receives_ssi", period) in_facility = person("is_in_medicaid_facility", period) - return receives_ssi & in_facility + return (eligible_for_ssi | receives_ssi) & in_facility From 66ddf925ca64ce90a8350472d7f498698583e08d Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Mon, 12 Oct 2026 06:55:18 -0400 Subject: [PATCH 4/5] Follow 3.549(A)(2)(f) as written: no earnings spillover for SSI recipients 3.549(A)(2)(f) applies "the difference between the gross unearned income and the $20.00 deduction" to earnings only when the client's unearned income is under $20, and (A)(2)(a) counts unearned income "from all sources", SSI included. So an AND-CS client, who always receives SSI, gets no share of the disregard on earnings unless their gross unearned income is under $20. This matches Axiom's encoding of 3.549 (us-co:regulations/9-ccr-2503-5/3.549). co_state_supplement_countable_income becomes MONTH so it can read that month's SSI. Co-Authored-By: Claude Opus 5.5 --- ..._ssi_state_supplement_couple_invariants.py | 10 +++--- .../state_supplement/co_state_supplement.yaml | 15 +++++---- .../co_state_supplement_countable_income.yaml | 17 +++++----- .../co_state_supplement_countable_income.py | 32 +++++++++---------- 4 files changed, 39 insertions(+), 35 deletions(-) diff --git a/policyengine_us/tests/core/test_ssi_state_supplement_couple_invariants.py b/policyengine_us/tests/core/test_ssi_state_supplement_couple_invariants.py index afdf7772920..cdecc40f80c 100644 --- a/policyengine_us/tests/core/test_ssi_state_supplement_couple_invariants.py +++ b/policyengine_us/tests/core/test_ssi_state_supplement_couple_invariants.py @@ -22,10 +22,12 @@ 4. Citizenship: a spouse who fails the SSI citizenship condition is never eligible. 5. Colorado couple total: when both spouses of a joint SSI claim receive - AND-CS, the two grants sum to twice the grant standard less the couple's - federal SSI and pooled countable income, as in SSA's Colorado couple - payment level (1,398 = 2 x 699 in January 2011), however 3.549(A) divides - their own income between them. + AND-CS and have only unearned income, the two grants sum to twice the + grant standard less the couple's federal SSI and pooled countable income, + as in SSA's Colorado couple payment level (1,398 = 2 x 699 in January + 2011), however 3.549(A) divides their own income between them. (Earnings + break the identity: 3.549(A)(1) deducts $65 for each client, where SSI + deducts $65 once for the couple.) YAML covers the source examples and their amounts. Python is needed here to compare each person across role assignments and spouses in one simulation. diff --git a/policyengine_us/tests/policy/baseline/gov/states/co/ssa/state_supplement/co_state_supplement.yaml b/policyengine_us/tests/policy/baseline/gov/states/co/ssa/state_supplement/co_state_supplement.yaml index 81412960d86..399832039ab 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/co/ssa/state_supplement/co_state_supplement.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/co/ssa/state_supplement/co_state_supplement.yaml @@ -263,11 +263,12 @@ - name: Case 18, a disabled SSI couple where only the head has earnings. # The head earns $500/month and the spouse has no income. Federal SSI pools # earnings: (500 - 20 - 65) / 2 = 207.50 countable, so the couple payment is - # 1,491 - 207.50 = 1,283.50, or 641.75 each. 3.549(A): the head's $10 share - # of the disregard goes to earned income (3.549(A)(2)(f)), then $65, then - # half: (500 - 10 - 65) / 2 = 212.50. Head grant 994 - 641.75 - 212.50 = - # 139.75/month (1,677/year); spouse 994 - 641.75 = 352.25/month - # (4,227/year). + # 1,491 - 207.50 = 1,283.50, or 641.75 each. 3.549(A): the head's only + # unearned income is SSI, so no unearned disregard applies (3.549(A)(2)(c)), + # and their gross unearned income is not under $20, so none reaches earned + # income (3.549(A)(2)(f)); 3.549(A)(1) gives (500 - 65) / 2 = 217.50. Head + # grant 994 - 641.75 - 217.50 = 134.75/month (1,617/year); spouse + # 994 - 641.75 = 352.25/month (4,227/year). absolute_error_margin: 0.1 period: 2026 input: @@ -295,5 +296,5 @@ state_code: CO output: ssi: [7_701, 7_701] - co_state_supplement_countable_income: [2_550, 0] - co_state_supplement: [1_677, 4_227] + co_state_supplement_countable_income: [2_610, 0] + co_state_supplement: [1_617, 4_227] diff --git a/policyengine_us/tests/policy/baseline/gov/states/co/ssa/state_supplement/co_state_supplement_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/co/ssa/state_supplement/co_state_supplement_countable_income.yaml index c5073147e9f..774f71cc0cb 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/co/ssa/state_supplement/co_state_supplement_countable_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/co/ssa/state_supplement/co_state_supplement_countable_income.yaml @@ -1,4 +1,4 @@ -- name: Case 1, a single client's countable income is their SSI countable income. +- name: Case 1, outside an SSI couple computation, countable income is SSI countable income. period: 2026 input: ssi_countable_income: 3_000 @@ -7,8 +7,8 @@ co_state_supplement_countable_income: 3_000 - name: Case 2, spouses of a joint SSI claim each count their own income. - # 9 CCR 2503-5 3.549(A)(2): own unearned income less the client's half of - # the $20 disregard. Pensions of $400 and $200 a month give 390 and 190 + # 9 CCR 2503-5 3.549(A)(2): own unearned income other than SSI, less the + # client's half of the $20 disregard. Pensions of $400 and $200 a month give 390 and 190 # a month, or 4,680 and 2,280 a year. Federal SSI would give each half of # the pooled 580, or 290 a month. period: 2026 @@ -40,11 +40,12 @@ ssi_countable_income: [3_480, 3_480] co_state_supplement_countable_income: [4_680, 2_280] -- name: Case 3, a spouse's unused share of the disregard goes to their earnings. +- name: Case 3, an SSI recipient's earnings get no share of the unearned income disregard. # The spouse has $5/month of interest and $200/month of earnings. Their $10 - # share of the disregard covers the $5 of unearned income and the other $5 - # goes to earnings (3.549(A)(2)(f)): (200 - 5 - 65) / 2 = 65 a month, or - # 780 a year. + # share of the $20 disregard covers the $5 of interest (3.549(A)(2)(c)). Their + # gross unearned income, SSI included, is not under $20, so nothing reaches + # earned income (3.549(A)(2)(f)): (200 - 65) / 2 = 67.50 a month, or 810 a + # year. period: 2026 input: people: @@ -71,4 +72,4 @@ members: [head, spouse] state_code: CO output: - co_state_supplement_countable_income: [0, 780] + co_state_supplement_countable_income: [0, 810] diff --git a/policyengine_us/variables/gov/states/co/ssa/state_supplement/co_state_supplement_countable_income.py b/policyengine_us/variables/gov/states/co/ssa/state_supplement/co_state_supplement_countable_income.py index edb2c489e02..d3f6bf311a9 100644 --- a/policyengine_us/variables/gov/states/co/ssa/state_supplement/co_state_supplement_countable_income.py +++ b/policyengine_us/variables/gov/states/co/ssa/state_supplement/co_state_supplement_countable_income.py @@ -1,15 +1,12 @@ from policyengine_us.model_api import * -from policyengine_us.variables.gov.ssa.ssi.eligibility.income._apply_ssi_exclusions import ( - _apply_ssi_exclusions, -) class co_state_supplement_countable_income(Variable): value_type = float entity = Person - label = "Colorado State Supplement countable income" + label = "Colorado State Supplement countable income other than SSI" unit = USD - definition_period = YEAR + definition_period = MONTH # PDF pages 93-94 reference = "https://www.sos.state.co.us/CCR/GenerateRulePdf.do?fileName=9+CCR+2503-5&ruleVersionId=12428#page=93" @@ -18,11 +15,9 @@ def formula(person, period, parameters): # SSI's couple computation applies, ssi_countable_income instead gives # each spouse half of the couple's pooled countable income. Both # spouses then receive SSI, so 3.549(F) deems neither spouse's income - # to the other, and 3.549(A)(2)(c)(1) splits the $20 unearned income - # disregard "between the client and the spouse"; it is split equally - # here. Any part a spouse cannot use against unearned income goes to - # their earned income (3.549(A)(2)(f)), as _apply_ssi_exclusions does. + # to the other, and the client's own income is counted as follows. couple_computation = person("ssi_couple_computation_applies", period) + p = parameters(period).gov.ssa.ssi.income.exclusions earned = max_( person("ssi_earned_income", period) - person("ssi_blind_or_disabled_working_student_exclusion", period), @@ -31,14 +26,19 @@ def formula(person, period, parameters): unearned = person("ssi_unearned_income", period) + person( "ssi_in_kind_support_and_maintenance", period ) - p = parameters(period).gov.ssa.ssi.income.exclusions - own_countable = _apply_ssi_exclusions( - earned, - unearned, - parameters, - period, - general_exclusion=p.general / 2, + ssi = person("ssi", period) + # 3.549(A)(2)(c): $20 is deducted from unearned income other than SSI, + # split between married spouses; a client whose only unearned income + # is SSI gets no unearned income disregard. + unearned_disregard = min_(p.general / 2, unearned) + # 3.549(A)(2)(f): only when the client's gross unearned income, SSI + # included, is under $20 does the difference reduce earned income. + earned_disregard = where(unearned > 0, max_(0, p.general - unearned - ssi), 0) + # 3.549(A)(1): deduct $65 from gross earned income and halve the rest. + countable_earned = max_(0, earned - p.earned - earned_disregard) * ( + 1 - p.earned_share ) + own_countable = unearned - unearned_disregard + countable_earned return where( couple_computation, own_countable, From 3d1da21317f9f0d80ca89304a3cf2734aa55a5d4 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Mon, 12 Oct 2026 07:14:13 -0400 Subject: [PATCH 5/5] Hold TX residents to the $30 reduced standard; halve a couple's ISM in CO Review round 2 (GPT-6.1 Sol): - Texas: testing uncapped_ssi admitted an SSI-abolished resident and a resident on the own-household rate whose income equalled it. Test H-6000's condition directly: countable income not over the $30 reduced standard, with SSI not abolished. - Colorado: a joint couple's in-kind support and maintenance is one presumed maximum value (ssi_pmv_amount), which SSI splits between the spouses; count half of it for each spouse, not all of it. Co-Authored-By: Claude Opus 5.5 --- .../state_supplement/co_state_supplement.yaml | 38 ++++++++++++++++++ .../ssi_state_supplement/integration.yaml | 27 +++++++++++++ .../tx_ssi_state_supplement_eligible.yaml | 39 ++++++++++++------- .../co_state_supplement_countable_income.py | 8 ++-- .../tx_ssi_state_supplement_eligible.py | 19 ++++++--- 5 files changed, 109 insertions(+), 22 deletions(-) diff --git a/policyengine_us/tests/policy/baseline/gov/states/co/ssa/state_supplement/co_state_supplement.yaml b/policyengine_us/tests/policy/baseline/gov/states/co/ssa/state_supplement/co_state_supplement.yaml index 399832039ab..dd50f2b0fc2 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/co/ssa/state_supplement/co_state_supplement.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/co/ssa/state_supplement/co_state_supplement.yaml @@ -298,3 +298,41 @@ ssi: [7_701, 7_701] co_state_supplement_countable_income: [2_610, 0] co_state_supplement: [1_617, 4_227] + +- name: Case 19, a disabled SSI couple receiving outside shelter support. + # No cash income. In-kind support and maintenance for a couple is one + # presumed maximum value: 1,491 / 3 + 20 = 517/month (20 CFR 416.1140), so + # couple countable income is 517 - 20 = 497 and the couple payment is + # 1,491 - 497 = 994, or 497 each. Each spouse counts half the couple's + # in-kind support, 258.50, less their 10 share of the disregard: 248.50. + # Grant 994 - 497 - 248.50 = 248.50/month (2,982/year) each. + absolute_error_margin: 0.1 + period: 2026 + input: + people: + head: + age: 50 + is_disabled: true + meets_ssi_disability_criteria: true + ssi_receives_outside_shelter_support: true + is_tax_unit_head: true + spouse: + age: 52 + is_disabled: true + meets_ssi_disability_criteria: true + ssi_receives_outside_shelter_support: true + is_tax_unit_spouse: true + tax_units: + tax_unit: + members: [head, spouse] + marital_units: + marital_unit: + members: [head, spouse] + households: + household: + members: [head, spouse] + state_code: CO + output: + ssi: [5_964, 5_964] + co_state_supplement_countable_income: [2_982, 2_982] + co_state_supplement: [2_982, 2_982] diff --git a/policyengine_us/tests/policy/baseline/gov/states/tx/hhsc/ssi_state_supplement/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/tx/hhsc/ssi_state_supplement/integration.yaml index 86db34e9553..5bc7929b311 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/tx/hhsc/ssi_state_supplement/integration.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/tx/hhsc/ssi_state_supplement/integration.yaml @@ -362,3 +362,30 @@ ssi: 0 tx_ssi_state_supplement_eligible: false tx_ssi_state_supplement: 0 + +- name: Scenario 13, facility resident outside the SSI facility living arrangement with income at the full federal rate. + # Only is_in_medicaid_facility is set, so SSI uses the $943 own-household + # rate. A $963/month pension gives $943 of countable income: SSI is $0, and + # the income is far above the $30 reduced standard that H-6000 applies to a + # facility resident, so there is no supplement. + period: 2024 + input: + people: + person1: + age: 80 + pension_income: 11_556 + is_in_medicaid_facility: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: TX + output: + ssi: 0 + tx_ssi_state_supplement_eligible: false + tx_ssi_state_supplement: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/tx/hhsc/ssi_state_supplement/tx_ssi_state_supplement_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/tx/hhsc/ssi_state_supplement/tx_ssi_state_supplement_eligible.yaml index b98ca5a2c0c..d5d5fb0042e 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/tx/hhsc/ssi_state_supplement/tx_ssi_state_supplement_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/tx/hhsc/ssi_state_supplement/tx_ssi_state_supplement_eligible.yaml @@ -1,5 +1,5 @@ # Unit tests for Texas SSI State Supplement eligibility -# Eligible if: eligible for SSI with countable income not over the payment +# Eligible if: eligible for SSI with countable income not over the $30 reduced # standard (a $0 federal payment at the limit included) and takes up SSI, or # reported to receive SSI; AND residing in a Medicaid-funded facility; AND in # Texas @@ -9,21 +9,21 @@ # recipient in a facility "remains eligible for SSI if their countable income # does not exceed the SSI reduced standard payment amount") -- name: Case 1, SSI recipient and in Medicaid facility in Texas. +- name: Case 1, SSI-eligible facility resident with no countable income. period: 2024 input: is_ssi_eligible: true - uncapped_ssi: 360 + ssi_countable_income: 0 is_in_medicaid_facility: true state_code: TX output: tx_ssi_state_supplement_eligible: true -- name: Case 2, SSI recipient but not in Medicaid facility. +- name: Case 2, SSI-eligible but not in Medicaid facility. period: 2024 input: is_ssi_eligible: true - uncapped_ssi: 360 + ssi_countable_income: 0 is_in_medicaid_facility: false state_code: TX output: @@ -57,33 +57,46 @@ output: tx_ssi_state_supplement_eligible: true -- name: Case 6, countable income equal to the reduced standard leaves a $0 federal payment and stays eligible. - period: 2024-01 +- name: Case 6, countable income equal to the $30 reduced standard stays eligible. + # $360/year = $30/month, so the federal payment is $0 (H-6000). + period: 2024 input: is_ssi_eligible: true - uncapped_ssi: 0 + ssi_countable_income: 360 is_in_medicaid_facility: true state_code: TX output: tx_ssi_state_supplement_eligible: true -- name: Case 7, countable income above the reduced standard is not eligible. - period: 2024-01 +- name: Case 7, countable income above the $30 reduced standard is not eligible. + # $372/year = $31/month. + period: 2024 input: is_ssi_eligible: true - uncapped_ssi: -1 + ssi_countable_income: 372 is_in_medicaid_facility: true state_code: TX output: tx_ssi_state_supplement_eligible: false - name: Case 8, a facility resident who does not take up SSI is not eligible. - period: 2024-01 + period: 2024 input: is_ssi_eligible: true - uncapped_ssi: 30 + ssi_countable_income: 0 takes_up_ssi_if_eligible: false is_in_medicaid_facility: true state_code: TX output: tx_ssi_state_supplement_eligible: false + +- name: Case 9, no supplement for SSI recipients once SSI is abolished. + period: 2024 + input: + gov.ssa.ssi.abolish_ssi: true + is_ssi_eligible: true + ssi_countable_income: 0 + is_in_medicaid_facility: true + state_code: TX + output: + tx_ssi_state_supplement_eligible: false diff --git a/policyengine_us/variables/gov/states/co/ssa/state_supplement/co_state_supplement_countable_income.py b/policyengine_us/variables/gov/states/co/ssa/state_supplement/co_state_supplement_countable_income.py index d3f6bf311a9..7c715bc5a79 100644 --- a/policyengine_us/variables/gov/states/co/ssa/state_supplement/co_state_supplement_countable_income.py +++ b/policyengine_us/variables/gov/states/co/ssa/state_supplement/co_state_supplement_countable_income.py @@ -23,9 +23,11 @@ def formula(person, period, parameters): - person("ssi_blind_or_disabled_working_student_exclusion", period), 0, ) - unearned = person("ssi_unearned_income", period) + person( - "ssi_in_kind_support_and_maintenance", period - ) + # A joint couple's in-kind support and maintenance is one presumed + # maximum value for the couple (ssi_pmv_amount), which SSI splits + # equally between the spouses. + ism_share = person("ssi_in_kind_support_and_maintenance", period) / 2 + unearned = person("ssi_unearned_income", period) + ism_share ssi = person("ssi", period) # 3.549(A)(2)(c): $20 is deducted from unearned income other than SSI, # split between married spouses; a client whose only unearned income diff --git a/policyengine_us/variables/gov/states/tx/hhsc/ssi_state_supplement/tx_ssi_state_supplement_eligible.py b/policyengine_us/variables/gov/states/tx/hhsc/ssi_state_supplement/tx_ssi_state_supplement_eligible.py index 1f6849e00f5..2dda8005e13 100644 --- a/policyengine_us/variables/gov/states/tx/hhsc/ssi_state_supplement/tx_ssi_state_supplement_eligible.py +++ b/policyengine_us/variables/gov/states/tx/hhsc/ssi_state_supplement/tx_ssi_state_supplement_eligible.py @@ -16,16 +16,23 @@ class tx_ssi_state_supplement_eligible(Variable): def formula(person, period, parameters): # MEPD Handbook H-1500: "SSI recipients who live in an institutional # setting and receive the $30 reduced federal benefit receive a state - # supplement." H-6000: such a person "remains eligible for SSI if + # supplement." H-6000: such a resident "remains eligible for SSI if # their countable income does not exceed the SSI reduced standard - # payment amount", including income equal to it and a $0 federal - # payment (42 USC 1382(a)(1)(A): income "not more than" the rate). - # H-6000 gives a couple in a facility the $60 couple standard, so - # each spouse is assessed on their own half. + # payment amount", so countable income equal to it, with a $0 federal + # payment, still qualifies. The test is against the reduced standard + # itself, since this program identifies residents through + # is_in_medicaid_facility rather than the SSI living arrangement. For + # a couple in a facility, SSI's couple computation gives each spouse + # half the couple's countable income, held to their $30 half of the + # $60 couple standard (H-6000). + p = parameters(period).gov.ssa.ssi + countable_income = person("ssi_countable_income", period) + within_reduced_standard = countable_income <= p.amount.institutional.individual eligible_for_ssi = ( person("is_ssi_eligible", period) & person("takes_up_ssi_if_eligible", period.this_year) - & (person("uncapped_ssi", period) >= 0) + & within_reduced_standard + & ~p.abolish_ssi ) receives_ssi = person("receives_ssi", period) in_facility = person("is_in_medicaid_facility", period)