diff --git a/changelog.d/medicaid-abd-noncitizen-countable-income.fixed.md b/changelog.d/medicaid-abd-noncitizen-countable-income.fixed.md new file mode 100644 index 00000000000..abfa381b4b1 --- /dev/null +++ b/changelog.d/medicaid-abd-noncitizen-countable-income.fixed.md @@ -0,0 +1 @@ +Count the own income of aged, blind, or disabled people who fail SSI's noncitizen test in SSI-methodology countable income, so Medicaid's optional aged, blind, and disabled and medically needy income tests, CAPI, and other programs no longer treat it as zero; the California state supplement no longer counts a CAPI-eligible member's income, and Maryland PAA no longer imputes SSI or deems spouse income for people SSI bars by alien status. diff --git a/policyengine_us/tests/policy/baseline/gov/hhs/medicaid/eligibility/categories/medically_needy/is_medically_needy_for_medicaid.yaml b/policyengine_us/tests/policy/baseline/gov/hhs/medicaid/eligibility/categories/medically_needy/is_medically_needy_for_medicaid.yaml index 4c889ee6e99..a9af369a172 100644 --- a/policyengine_us/tests/policy/baseline/gov/hhs/medicaid/eligibility/categories/medically_needy/is_medically_needy_for_medicaid.yaml +++ b/policyengine_us/tests/policy/baseline/gov/hhs/medicaid/eligibility/categories/medically_needy/is_medically_needy_for_medicaid.yaml @@ -50,3 +50,39 @@ state_code: MA output: is_medically_needy_for_medicaid: false + +- name: Case 3, aged permanent resident without 40 SSI quarters has pension counted. + period: 2026 + input: + age: 70 + immigration_status: LEGAL_PERMANENT_RESIDENT + years_since_us_entry: 10 + ssi_qualifying_quarters_earnings: 20 + pension_income: 60_000 + is_in_medicaid_medically_needy_category: true + is_adult_for_medicaid: false + is_optional_senior_or_disabled_for_medicaid: false + medicaid_medically_needy_medical_expenses: 6_000 + ssi_countable_resources: 1_000 + state_code: MA + output: + # 60,000 - 20 x 12 = 59,760; 59,760 - 6,000 = 53,760 > 522 x 12 = 6,264. + is_medically_needy_for_medicaid: false + +- name: Case 4, aged permanent resident without 40 SSI quarters qualifies after medical spenddown. + period: 2026 + input: + age: 70 + immigration_status: LEGAL_PERMANENT_RESIDENT + years_since_us_entry: 10 + ssi_qualifying_quarters_earnings: 20 + pension_income: 18_000 + is_in_medicaid_medically_needy_category: true + is_adult_for_medicaid: false + is_optional_senior_or_disabled_for_medicaid: false + medicaid_medically_needy_medical_expenses: 12_000 + ssi_countable_resources: 1_000 + state_code: MA + output: + # 18,000 - 20 x 12 = 17,760; 17,760 - 12,000 = 5,760 <= 522 x 12 = 6,264. + is_medically_needy_for_medicaid: true diff --git a/policyengine_us/tests/policy/baseline/gov/hhs/medicaid/eligibility/is_medicaid_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/hhs/medicaid/eligibility/is_medicaid_eligible.yaml index 2fb92c16b1e..697be6e4d9b 100644 --- a/policyengine_us/tests/policy/baseline/gov/hhs/medicaid/eligibility/is_medicaid_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/hhs/medicaid/eligibility/is_medicaid_eligible.yaml @@ -314,3 +314,48 @@ medicaid_category: SECTION_1115_MEC_ADULT is_medicaid_work_requirement_applicable_adult: true is_medicaid_eligible: true + +- name: Case 17, aged permanent resident without 40 SSI quarters is over the Massachusetts income limit. + period: 2025 + input: + age: 70 + immigration_status: LEGAL_PERMANENT_RESIDENT + years_since_us_entry: 10 + ssi_qualifying_quarters_earnings: 20 + pension_income: 60_000 + state_code: MA + output: + # The optional aged, blind, and disabled pathway counts 59,760 of + # income, above 100% of the poverty guideline, even though the person + # fails SSI's 40-quarter test. + is_medicaid_immigration_status_eligible: true + is_optional_senior_or_disabled_for_medicaid: false + is_medicaid_eligible: false + +- name: Case 18, aged permanent resident without 40 SSI quarters with a small pension is eligible. + period: 2025 + input: + age: 70 + immigration_status: LEGAL_PERMANENT_RESIDENT + years_since_us_entry: 10 + ssi_qualifying_quarters_earnings: 20 + pension_income: 12_000 + state_code: MA + output: + # 12,000 - 20 x 12 = 11,760, under 100% of the poverty guideline. + is_optional_senior_or_disabled_for_medicaid: true + is_medicaid_eligible: true + +- name: Case 19, aged undocumented resident of the District of Columbia is over the income limit. + period: 2025 + input: + age: 70 + immigration_status: UNDOCUMENTED + pension_income: 60_000 + state_code: DC + output: + # The District covers undocumented residents, but the optional aged, + # blind, and disabled pathway still counts 59,760 of income. + is_medicaid_immigration_status_eligible: true + is_optional_senior_or_disabled_for_medicaid: false + is_medicaid_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/hhs/medicaid/income/deemed/from_ineligible_spouse/medicaid_optional_senior_or_disabled_income_deemed_from_ineligible_spouse.yaml b/policyengine_us/tests/policy/baseline/gov/hhs/medicaid/income/deemed/from_ineligible_spouse/medicaid_optional_senior_or_disabled_income_deemed_from_ineligible_spouse.yaml index 1724495a64d..42218c4dfd6 100644 --- a/policyengine_us/tests/policy/baseline/gov/hhs/medicaid/income/deemed/from_ineligible_spouse/medicaid_optional_senior_or_disabled_income_deemed_from_ineligible_spouse.yaml +++ b/policyengine_us/tests/policy/baseline/gov/hhs/medicaid/income/deemed/from_ineligible_spouse/medicaid_optional_senior_or_disabled_income_deemed_from_ineligible_spouse.yaml @@ -120,3 +120,36 @@ # (17,004 - 20 * 12 - 65 * 12) / 2 = 7,992 deemed and countable. medicaid_optional_senior_or_disabled_income_deemed_from_ineligible_spouse: [7_992, 0, 0] medicaid_optional_senior_or_disabled_countable_income: [7_992, 0, 0] + +- name: Spouse income is deemed to an aged permanent resident without 40 SSI quarters. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + is_tax_unit_head: true + immigration_status: LEGAL_PERMANENT_RESIDENT + years_since_us_entry: 10 + ssi_qualifying_quarters_earnings: 20 + pension_income: 6_000 + person2: + age: 55 + is_tax_unit_spouse: true + employment_income: 40_000 + tax_units: + tax_unit: + members: [person1, person2] + marital_units: + marital_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MA + output: + # SSI's noncitizen test does not stop deeming (42 CFR 435.601). + # Spouse wages 40,000 > (1,450 - 967) x 12 = 5,796. + # Couple: (500 - 20) x 12 + (40,000 - 65 x 12) / 2 = 25,370. + # Alone: (500 - 20) x 12 = 5,760. Deemed: 25,370 - 5,760 = 19,610. + medicaid_optional_senior_or_disabled_income_deemed_from_ineligible_spouse: [19_610, 0] diff --git a/policyengine_us/tests/policy/baseline/gov/hhs/medicaid/income/medicaid_optional_senior_or_disabled_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/hhs/medicaid/income/medicaid_optional_senior_or_disabled_countable_income.yaml index 883b6e7bed9..c86e871c723 100644 --- a/policyengine_us/tests/policy/baseline/gov/hhs/medicaid/income/medicaid_optional_senior_or_disabled_countable_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/hhs/medicaid/income/medicaid_optional_senior_or_disabled_countable_income.yaml @@ -105,3 +105,54 @@ # rounding, 1,131.75 would exceed the $1,131 standard. medicaid_optional_senior_or_disabled_countable_income: 13_572 is_optional_senior_or_disabled_income_eligible: true + +- name: An aged permanent resident without 40 SSI quarters has their pension counted. + period: 2025 + absolute_error_margin: 0.01 + input: + age: 70 + immigration_status: LEGAL_PERMANENT_RESIDENT + years_since_us_entry: 10 + ssi_qualifying_quarters_earnings: 20 + pension_income: 60_000 + state_code: MA + output: + # Failing SSI's noncitizen test does not zero income under SSI + # methodology (42 CFR 435.601): 60,000 - 20 x 12 = 59,760. + medicaid_optional_senior_or_disabled_countable_income: 59_760 + is_optional_senior_or_disabled_income_eligible: false + +- name: Spouse income is deemed to an aged permanent resident without 40 SSI quarters. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + is_tax_unit_head: true + immigration_status: LEGAL_PERMANENT_RESIDENT + years_since_us_entry: 10 + ssi_qualifying_quarters_earnings: 20 + pension_income: 6_000 + person2: + age: 55 + is_tax_unit_spouse: true + employment_income: 40_000 + tax_units: + tax_unit: + members: [person1, person2] + marital_units: + marital_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MA + output: + # Own income: 6,000 - 20 x 12 = 5,760. + # Deemed from the spouse who is not aged, blind, or disabled: + # 40,000 > (1,450 - 967) x 12 = 5,796, so the couple total is + # 5,760 + (40,000 - 65 x 12) / 2 = 25,370, and 25,370 - 5,760 = 19,610. + # The spouse's own countable income stays 0 to avoid counting it twice. + medicaid_optional_senior_or_disabled_countable_income: [25_370, 0] + is_optional_senior_or_disabled_income_eligible: [false, false] diff --git a/policyengine_us/tests/policy/baseline/gov/local/ca/sf/caap/ca_sf_caap.yaml b/policyengine_us/tests/policy/baseline/gov/local/ca/sf/caap/ca_sf_caap.yaml index 3e8dcad1290..cb6ca423414 100644 --- a/policyengine_us/tests/policy/baseline/gov/local/ca/sf/caap/ca_sf_caap.yaml +++ b/policyengine_us/tests/policy/baseline/gov/local/ca/sf/caap/ca_sf_caap.yaml @@ -316,8 +316,8 @@ # size-1 grant ($714) is paid through the top-level benefit, not the GA $578. ca_sf_caap: 714 -- name: Case 15, aged TPS member with a CAPI payment is excluded from the - budget unit along with her income. +- name: Case 15, aged TPS member whose pension rules out CAPI stays in the + budget unit with her income. period: 2026-01 absolute_error_margin: 0.01 input: @@ -339,22 +339,14 @@ spm_unit_cash_assets: 0 output: # person2 is categorically CAPI-eligible (aged 68 + noncitizen + TPS is not - # an SSI-qualified status) and the model pays her unit CAPI, so the - # receipt-based bar (ca_capi > 0) drops her from the budget unit and her - # pension is masked out of countable income; the remaining member collects - # the size-1 grant. - # NOTE: in real life her 2,000/month pension is roughly double the CAPI - # payment standard, so she would receive no CAPI and would stay in the - # CAAP budget unit (size 2, max grant 1,036), where her income fails the - # strict income test: ca_sf_caap = 0. The model currently pays her CAPI - # regardless of income because ca_capi's income test reads - # ssi_countable_income, which is zeroed for anyone failing the SSI - # immigration test (CAPI's entire target population) -- an upstream CAPI - # limitation. When that is fixed upstream, this case's expectations flip - # to budget_unit_size 2, countable_income 2_000, ca_sf_caap 0. - ca_sf_caap_budget_unit_size: 1 - ca_sf_caap_countable_income: 0 - ca_sf_caap: 578 + # an SSI-qualified status), but CAPI counts her pension: her countable + # pension (2,000 - 20 = 1,980/month) exceeds CAPI's payment standard, so + # ca_capi = 0. The receipt-based bar (ca_capi > 0) does not apply, and she + # stays in the CAAP budget unit (size 2, max grant 1,036), where her + # income fails the strict income test. + ca_sf_caap_budget_unit_size: 2 + ca_sf_caap_countable_income: 2_000 + ca_sf_caap: 0 - name: Case 16, one spouse receiving SSI and only one spouse applying yields the full one-person grant against the applicant's own income. diff --git a/policyengine_us/tests/policy/baseline/gov/ssa/ssi/eligibility/income/deemed/from_ineligible_spouse/ssi_income_deemed_from_ineligible_spouse.yaml b/policyengine_us/tests/policy/baseline/gov/ssa/ssi/eligibility/income/deemed/from_ineligible_spouse/ssi_income_deemed_from_ineligible_spouse.yaml index 0b05128cf11..e1968e9c591 100644 --- a/policyengine_us/tests/policy/baseline/gov/ssa/ssi/eligibility/income/deemed/from_ineligible_spouse/ssi_income_deemed_from_ineligible_spouse.yaml +++ b/policyengine_us/tests/policy/baseline/gov/ssa/ssi/eligibility/income/deemed/from_ineligible_spouse/ssi_income_deemed_from_ineligible_spouse.yaml @@ -224,3 +224,33 @@ members: [person1, person2] output: ssi_income_deemed_from_ineligible_spouse: [0, 0] + +- name: Spouse income is deemed to an aged permanent resident without 40 SSI quarters (2025) + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + is_tax_unit_head: true + immigration_status: LEGAL_PERMANENT_RESIDENT + years_since_us_entry: 10 + ssi_qualifying_quarters_earnings: 20 + pension_income: 6_000 + person2: + age: 55 + is_tax_unit_spouse: true + employment_income: 40_000 + tax_units: + tax_unit: + members: [person1, person2] + marital_units: + marital_unit: + members: [person1, person2] + output: + # Deeming turns on aged, blind, or disabled status, not on SSI's + # noncitizen test: spouse wages 40,000 > (1,450 - 967) x 12 = 5,796. + # Couple: (500 - 20) x 12 + (40,000 - 65 x 12) / 2 = 25,370. + # Alone: (500 - 20) x 12 = 5,760. Deemed: 25,370 - 5,760 = 19,610. + is_ssi_spousal_deeming_applies: [true, false] + ssi_income_deemed_from_ineligible_spouse: [19_610, 0] diff --git a/policyengine_us/tests/policy/baseline/gov/ssa/ssi/ssi_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/ssa/ssi/ssi_countable_income.yaml index 3f66920e3c1..af96ba13287 100644 --- a/policyengine_us/tests/policy/baseline/gov/ssa/ssi/ssi_countable_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/ssa/ssi/ssi_countable_income.yaml @@ -147,3 +147,47 @@ # No earned income, so earned exclusions don't apply # Countable = 3_868 ssi_countable_income: 3_868 + +- name: An aged permanent resident without 40 SSI quarters has their pension counted. + period: 2025 + absolute_error_margin: 0.01 + input: + age: 70 + immigration_status: LEGAL_PERMANENT_RESIDENT + years_since_us_entry: 10 + ssi_qualifying_quarters_earnings: 20 + pension_income: 60_000 + output: + # The noncitizen test bars SSI itself but does not zero the income + # that Medicaid and state programs count: 60,000 - 20 x 12 = 59,760. + ssi_countable_income: 59_760 + ssi: 0 + +- name: Spouse income is deemed to an aged permanent resident without 40 SSI quarters. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + is_tax_unit_head: true + immigration_status: LEGAL_PERMANENT_RESIDENT + years_since_us_entry: 10 + ssi_qualifying_quarters_earnings: 20 + pension_income: 6_000 + person2: + age: 55 + is_tax_unit_spouse: true + employment_income: 40_000 + tax_units: + tax_unit: + members: [person1, person2] + marital_units: + marital_unit: + members: [person1, person2] + output: + # Own: (500 - 20) x 12 = 5,760. Deemed from the spouse who is not aged, + # blind, or disabled: 19,610 (20 CFR 416.1163). The spouse's own + # countable income stays 0. + ssi_countable_income: [25_370, 0] + ssi: [0, 0] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi.yaml index a613984fefd..cbae90beeae 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi.yaml @@ -98,3 +98,27 @@ ca_state_supplement_aged_blind_disabled_amount: 0 ca_state_supplement: 0 ca_capi: 11_306 + +- name: Integration test, aged permanent resident without 40 SSI quarters whose pension exceeds the CAPI standard + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + immigration_status: LEGAL_PERMANENT_RESIDENT + years_since_us_entry: 10 + ssi_qualifying_quarters_earnings: 0 + pension_income: 24_000 # 2,000 a month + households: + household: + members: [person1] + state_code: CA + output: + ssi: 0 + ca_capi_eligible_person: true + # (2,000 - 20) x 12 = 23,760 of countable income. + ssi_countable_income: 23_760 + # 1,980 a month exceeds CAPI's individual payment standard, which is at + # most the 1,335.81 SSI/SSP no-cooking standard, so CAPI pays nothing. + ca_capi: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/state_supplement/ca_state_supplement.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/state_supplement/ca_state_supplement.yaml index 12c7afb14ea..eac4ce30dd6 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/state_supplement/ca_state_supplement.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/state_supplement/ca_state_supplement.yaml @@ -355,3 +355,57 @@ # 2,098.83 - 1,491 = 607.83; 2,098.83 - 2,098.83 = 0; # 2,356.57 - 2,098.83 = 257.74; 2,356.57 - 2,356.57 = 0. ca_state_supplement: [7_293.96, 0, 3_092.88, 0] + +# A CAPI-eligible member's income does not reduce the state supplement: CAPI +# budgets its own members' income (CAPI regulations MPP 49-035), and SSI/SSP +# counts another member's income only when it is deemed (20 CFR 416.1160(a)). +# 2025: federal SSI is $967; the no-cooking individual standard is +# $1,206.94 + $128.87 = $1,335.81. +- name: Case 10, 2025 aged citizen sharing an SPM unit with a CAPI-eligible sibling keeps the supplement. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + is_tax_unit_head: true + immigration_status: CITIZEN + social_security_retirement: 6_000 # 500 a month + person2: + age: 72 + is_tax_unit_head: true + immigration_status: LEGAL_PERMANENT_RESIDENT + years_since_us_entry: 10 + ssi_qualifying_quarters_earnings: 0 + pension_income: 6_000 # 500 a month + tax_units: + tax_unit1: + members: [person1] + tax_unit2: + members: [person2] + marital_units: + marital_unit1: + members: [person1] + marital_unit2: + members: [person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: CA + output: + # person2 is an LPR with fewer than 40 quarters, so SSI and the state + # supplement bar her and she is CAPI-eligible. + ca_capi_eligible_person: [false, true] + # Each has 500 - 20 = 480 a month of countable income. + ssi_countable_income: [5_760, 5_760] + # person1's SSI is 967 - 480 = 487 a month. + ssi: [5_844, 0] # 487 * 12 + # One eligible aged member, and living_arrangements_allow_for_food_preparation + # defaults to false, so the standard is 1,206.94 + 128.87 = 1,335.81. + ca_state_supplement_payment_standard: 16_029.72 # 1,335.81 * 12 + # The supplement is 1,335.81 - 487 - 480 = 368.81 a month; person2's 480 + # is not counted. + ca_state_supplement: 4_425.72 # 368.81 * 12 diff --git a/policyengine_us/tests/policy/baseline/gov/states/md/dhs/fia/paa/md_paa.yaml b/policyengine_us/tests/policy/baseline/gov/states/md/dhs/fia/paa/md_paa.yaml index 8a57dff16ca..a5d9e9b3abf 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/md/dhs/fia/paa/md_paa.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/md/dhs/fia/paa/md_paa.yaml @@ -211,3 +211,53 @@ md_paa_countable_income: 2_480 md_paa_imputed_federal_ssi: 0 md_paa: 0 + +# SSA cannot pay SSI to an LPR with fewer than 40 quarters, so PAA imputes no +# federal SSI and counts only her own income (COMAR 07.03.07.07 has no spousal +# deeming); PAA pays allowable needs less net countable income +# (COMAR 07.03.07.09A). 2025-01: provider rate $1,376; PNA $102. +- name: Case 11, aged LPR without 40 quarters in CARE_HOME_LEVEL_D with a working spouse. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + immigration_status: LEGAL_PERMANENT_RESIDENT + years_since_us_entry: 10 + ssi_qualifying_quarters_earnings: 20 + social_security_survivors: 6_000 # 500 a month + ssi_countable_resources: 1_000 + md_paa_living_arrangement: CARE_HOME_LEVEL_D + person2: + age: 60 + employment_income: 12_000 # 1,000 a month + marital_units: + marital_unit: + members: [person1, person2] + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MD + output: + # person1 qualifies through aged Social Security receipt; person2 is not + # in a PAA facility. + md_paa_eligible: [true, false] + ssi: [0, 0] + # SSI would deem person2's wages to person1: couple countable + # 480 + (1,000 - 65) * 0.5 = 947.50 less her own 480 = 467.50 a month. + ssi_income_deemed_from_ineligible_spouse: [467.50, 0] + # PAA counts person1's own 500 - 20 = 480 a month (5,760 a year) without + # the deemed amount. person2's own countable wages are + # (1,000 - 20 - 65) * 0.5 = 457.50. + md_paa_countable_income: [480, 457.50] + md_paa_imputed_federal_ssi: [0, 0] + # combined_need = 1,376 + 102 = 1,478. PAA = 1,478 - 480 - 0 = 998. + md_paa_total_cost_of_care: [1_478, 0] + md_paa: [998, 0] diff --git a/policyengine_us/variables/gov/hhs/medicaid/income/deemed/from_ineligible_spouse/medicaid_optional_senior_or_disabled_income_deemed_from_ineligible_spouse.py b/policyengine_us/variables/gov/hhs/medicaid/income/deemed/from_ineligible_spouse/medicaid_optional_senior_or_disabled_income_deemed_from_ineligible_spouse.py index a692202dac3..b2230f74783 100644 --- a/policyengine_us/variables/gov/hhs/medicaid/income/deemed/from_ineligible_spouse/medicaid_optional_senior_or_disabled_income_deemed_from_ineligible_spouse.py +++ b/policyengine_us/variables/gov/hhs/medicaid/income/deemed/from_ineligible_spouse/medicaid_optional_senior_or_disabled_income_deemed_from_ineligible_spouse.py @@ -15,7 +15,7 @@ class medicaid_optional_senior_or_disabled_income_deemed_from_ineligible_spouse( "https://www.law.cornell.edu/cfr/text/20/416.1163", "https://dssmanuals.mo.gov/mo-healthnet-for-the-aged-blind-and-disabled/0805-000-00/0805-015-00/0805-015-05/", ) - defined_for = "is_ssi_eligible_individual" + defined_for = "is_ssi_aged_blind_disabled" unit = USD def formula(person, period, parameters): diff --git a/policyengine_us/variables/gov/hhs/medicaid/income/medicaid_optional_senior_or_disabled_countable_income.py b/policyengine_us/variables/gov/hhs/medicaid/income/medicaid_optional_senior_or_disabled_countable_income.py index 044371e7419..0d6dedba250 100644 --- a/policyengine_us/variables/gov/hhs/medicaid/income/medicaid_optional_senior_or_disabled_countable_income.py +++ b/policyengine_us/variables/gov/hhs/medicaid/income/medicaid_optional_senior_or_disabled_countable_income.py @@ -12,6 +12,7 @@ class medicaid_optional_senior_or_disabled_countable_income(Variable): definition_period = YEAR reference = ( "https://www.law.cornell.edu/uscode/text/42/1396a#m", + "https://www.law.cornell.edu/cfr/text/42/435.601", "https://www.kff.org/medicaid/medicaid-financial-eligibility-for-seniors-and-people-with-disabilities-findings-from-a-50-state-survey/", # Missouri MHABD budgeting order and rounding "https://dssmanuals.mo.gov/mo-healthnet-for-the-aged-blind-and-disabled/0805-000-00/0805-015-00/", @@ -62,12 +63,14 @@ def formula(person, period, parameters): "medicaid_optional_senior_or_disabled_income_deemed_from_ineligible_spouse", period, ) - is_eligible_individual = person("is_ssi_eligible_individual", period) - is_eligible_spouse = person("is_ssi_eligible_spouse", period) - is_eligible = is_eligible_individual | is_eligible_spouse + # SSI methodology (42 CFR 435.601) counts the applicant's own income + # whether or not they meet SSI's noncitizen rules. People who are not + # aged, blind, or disabled have no countable income here; a spouse's + # income is deemed to the applicant instead. + is_aged_blind_disabled = person("is_ssi_aged_blind_disabled", period) return where( - ~is_eligible, + ~is_aged_blind_disabled, 0, where( couple_computation, diff --git a/policyengine_us/variables/gov/ssa/ssi/eligibility/income/deemed/from_ineligible_spouse/is_ssi_spousal_deeming_applies.py b/policyengine_us/variables/gov/ssa/ssi/eligibility/income/deemed/from_ineligible_spouse/is_ssi_spousal_deeming_applies.py index 9c7348fb608..1492ba95097 100644 --- a/policyengine_us/variables/gov/ssa/ssi/eligibility/income/deemed/from_ineligible_spouse/is_ssi_spousal_deeming_applies.py +++ b/policyengine_us/variables/gov/ssa/ssi/eligibility/income/deemed/from_ineligible_spouse/is_ssi_spousal_deeming_applies.py @@ -7,12 +7,14 @@ class is_ssi_spousal_deeming_applies(Variable): label = "SSI spousal deeming applies" definition_period = YEAR reference = "https://www.law.cornell.edu/cfr/text/20/416.1163" - defined_for = "is_ssi_eligible_individual" + defined_for = "is_ssi_aged_blind_disabled" documentation = """ Returns True when spousal deeming applies according to 20 CFR ยง416.1163. Spousal deeming applies when: - 1. Person is an eligible individual (not part of an eligible couple) + 1. Person is aged, blind, or disabled (not part of an eligible couple). + SSI's noncitizen test is applied in is_ssi_eligible, so programs that + use SSI methodology also deem spouse income to noncitizens. 2. Spouse is ineligible (not aged/blind/disabled) 3. Spouse's leftover income (after child allocations) exceeds the difference between couple FBR and individual FBR diff --git a/policyengine_us/variables/gov/ssa/ssi/eligibility/income/deemed/from_ineligible_spouse/ssi_income_deemed_from_ineligible_spouse.py b/policyengine_us/variables/gov/ssa/ssi/eligibility/income/deemed/from_ineligible_spouse/ssi_income_deemed_from_ineligible_spouse.py index 8a885f8d66f..9e81894574e 100644 --- a/policyengine_us/variables/gov/ssa/ssi/eligibility/income/deemed/from_ineligible_spouse/ssi_income_deemed_from_ineligible_spouse.py +++ b/policyengine_us/variables/gov/ssa/ssi/eligibility/income/deemed/from_ineligible_spouse/ssi_income_deemed_from_ineligible_spouse.py @@ -18,7 +18,7 @@ class ssi_income_deemed_from_ineligible_spouse(Variable): 2) Otherwise, spouse's deemed = (couple combined countable) - (individual alone countable). This yields 816 for 1986 Example 3 and 12000 for the 2025 test. """ - defined_for = "is_ssi_eligible_individual" + defined_for = "is_ssi_aged_blind_disabled" unit = USD def formula(person, period, parameters): diff --git a/policyengine_us/variables/gov/ssa/ssi/eligibility/income/ssi_countable_income.py b/policyengine_us/variables/gov/ssa/ssi/eligibility/income/ssi_countable_income.py index 1d268ec5b6c..28aa7b33979 100644 --- a/policyengine_us/variables/gov/ssa/ssi/eligibility/income/ssi_countable_income.py +++ b/policyengine_us/variables/gov/ssa/ssi/eligibility/income/ssi_countable_income.py @@ -70,14 +70,16 @@ def formula(person, period, parameters): # Add spousal deemed income (only relevant when one spouse is ineligible) spousal_deemed = person("ssi_income_deemed_from_ineligible_spouse", period) - # Check if person is eligible (either as individual OR as eligible spouse) - is_eligible_individual = person("is_ssi_eligible_individual", period) - is_eligible_spouse = person("is_ssi_eligible_spouse", period) - is_eligible = is_eligible_individual | is_eligible_spouse + # People who are not aged, blind, or disabled have no countable income + # of their own; a spouse's income is deemed to the other spouse + # instead. SSI's noncitizen test is applied in is_ssi_eligible, so it + # does not zero the income that Medicaid and state programs count + # with SSI methodology. + is_aged_blind_disabled = person("is_ssi_aged_blind_disabled", period) # Calculate final countable income return where( - ~is_eligible, + ~is_aged_blind_disabled, 0, where( both_eligible, diff --git a/policyengine_us/variables/gov/states/ca/cdss/state_supplement/ca_state_supplement.py b/policyengine_us/variables/gov/states/ca/cdss/state_supplement/ca_state_supplement.py index cb5e88fe1df..275e0e084a3 100644 --- a/policyengine_us/variables/gov/states/ca/cdss/state_supplement/ca_state_supplement.py +++ b/policyengine_us/variables/gov/states/ca/cdss/state_supplement/ca_state_supplement.py @@ -8,10 +8,22 @@ class ca_state_supplement(Variable): unit = USD definition_period = MONTH defined_for = StateCode.CA - reference = "https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?lawCode=WIC§ionNum=12200" + reference = ( + "https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?lawCode=WIC§ionNum=12200", + "https://www.law.cornell.edu/cfr/text/20/416.1160", + ) def formula(spm_unit, period, parameters): payment_standard = spm_unit("ca_state_supplement_payment_standard", period) ssi = add(spm_unit, period, ["ssi"]) - countable_income = add(spm_unit, period, ["ssi_countable_income"]) + person = spm_unit.members + # CAPI budgets its own members' income (CAPI regulations MPP 49-035), + # and SSI/SSP counts another member's income only when it is deemed + # (20 CFR 416.1160(a)), so a CAPI-eligible member's income does not + # reduce the state supplement. + capi_eligible = person("ca_capi_eligible_person", period.this_year) + person_countable_income = person("ssi_countable_income", period) + countable_income = spm_unit.sum( + where(capi_eligible, 0, person_countable_income) + ) return max_(0, payment_standard - ssi - countable_income) diff --git a/policyengine_us/variables/gov/states/md/dhs/fia/paa/md_paa_countable_income.py b/policyengine_us/variables/gov/states/md/dhs/fia/paa/md_paa_countable_income.py index 22dcb53c08f..7e63fa527a4 100644 --- a/policyengine_us/variables/gov/states/md/dhs/fia/paa/md_paa_countable_income.py +++ b/policyengine_us/variables/gov/states/md/dhs/fia/paa/md_paa_countable_income.py @@ -12,6 +12,7 @@ class md_paa_countable_income(Variable): definition_period = YEAR defined_for = StateCode.MD reference = ( + "https://regs.maryland.gov/us/md/exec/comar/07.03.07.07", "https://regs.maryland.gov/us/md/exec/comar/07.03.07.08", "https://regs.maryland.gov/us/md/exec/comar/07.03.07.09", "https://dhs.maryland.gov/documents/FIA/Manuals/Public%20Assistance%20to%20Adults%20%28PAA%29%20Manual/PAA%20900%20Calculation%20of%20Benefits%20rev%2011.22.docx", @@ -44,7 +45,19 @@ def formula(person, period, parameters): ) both_eligible = person("ssi_couple_computation_applies", period.this_year) - spousal_deemed = person("ssi_income_deemed_from_ineligible_spouse", period) + # COMAR 07.03.07.07 counts the individual's own income and has no + # spousal deeming. The SSI cascade deems spouse income only to people + # SSA can pay, so people who fail SSI's citizen or qualified-noncitizen + # test count their own income alone. + immigration_status = person("immigration_status", period) + is_citizen = immigration_status == immigration_status.possible_values.CITIZEN + is_qualified_noncitizen = person("is_ssi_qualified_noncitizen", period) + meets_ssi_immigration_test = is_citizen | is_qualified_noncitizen + spousal_deemed = where( + meets_ssi_immigration_test, + person("ssi_income_deemed_from_ineligible_spouse", period), + 0, + ) return where( both_eligible, personal_countable / 2, diff --git a/policyengine_us/variables/gov/states/md/dhs/fia/paa/md_paa_imputed_federal_ssi.py b/policyengine_us/variables/gov/states/md/dhs/fia/paa/md_paa_imputed_federal_ssi.py index fed7819204f..b999e4f1c67 100644 --- a/policyengine_us/variables/gov/states/md/dhs/fia/paa/md_paa_imputed_federal_ssi.py +++ b/policyengine_us/variables/gov/states/md/dhs/fia/paa/md_paa_imputed_federal_ssi.py @@ -10,10 +10,21 @@ class md_paa_imputed_federal_ssi(Variable): defined_for = "md_paa_eligible" reference = ( "https://regs.maryland.gov/us/md/exec/comar/07.03.07.03", + "https://regs.maryland.gov/us/md/exec/comar/07.03.07.09", "https://www.law.cornell.edu/uscode/text/42/1382#e_1_A", ) def formula(person, period, parameters): amount = person("ssi_amount_if_eligible", period) countable_income = person("md_paa_countable_income", period) - return max_(amount - countable_income, 0) + imputed_ssi = max_(amount - countable_income, 0) + # SSA cannot pay SSI to people who fail its citizen or + # qualified-noncitizen test, so there is no federal SSI to impute. + # PAA then pays allowable needs less net countable income + # (COMAR 07.03.07.09A). + immigration_status = person("immigration_status", period.this_year) + is_citizen = immigration_status == immigration_status.possible_values.CITIZEN + is_qualified_noncitizen = person( + "is_ssi_qualified_noncitizen", period.this_year + ) + return where(is_citizen | is_qualified_noncitizen, imputed_ssi, 0)