From f3006dca8bc072c16793cd3efb69dd0bdbece96a Mon Sep 17 00:00:00 2001 From: Ziming Date: Thu, 15 Oct 2026 13:14:10 -0400 Subject: [PATCH 01/18] Count income of ABD people who fail SSI's noncitizen test medicaid_optional_senior_or_disabled_countable_income and ssi_countable_income zeroed income for anyone who was not an SSI-eligible individual or spouse, and that status includes SSI's citizen and qualified-noncitizen test. Aged, blind, or disabled people who fail only that test (for example, LPRs with fewer than 40 quarters, or undocumented residents of states that cover them) therefore passed the optional ABD and medically needy Medicaid income tests, and CAPI, regardless of income. Gate the zero, and the spousal-deeming variables, on aged, blind, or disabled status instead. The zero still applies to a spouse who is not aged, blind, or disabled, whose income is deemed to the other spouse. SSI benefits are unchanged because is_ssi_eligible still applies the noncitizen test. Co-Authored-By: Claude Opus 5.5 --- ...d-abd-noncitizen-countable-income.fixed.md | 1 + .../is_medically_needy_for_medicaid.yaml | 36 +++++++++++++ .../eligibility/is_medicaid_eligible.yaml | 45 ++++++++++++++++ ..._income_deemed_from_ineligible_spouse.yaml | 33 ++++++++++++ ...l_senior_or_disabled_countable_income.yaml | 51 +++++++++++++++++++ .../gov/local/ca/sf/caap/ca_sf_caap.yaml | 26 ++++------ ..._income_deemed_from_ineligible_spouse.yaml | 30 +++++++++++ .../gov/ssa/ssi/ssi_countable_income.yaml | 44 ++++++++++++++++ .../gov/states/ca/cdss/capi/ca_capi.yaml | 24 +++++++++ ...ed_income_deemed_from_ineligible_spouse.py | 2 +- ...nal_senior_or_disabled_countable_income.py | 11 ++-- .../is_ssi_spousal_deeming_applies.py | 6 ++- ...si_income_deemed_from_ineligible_spouse.py | 2 +- .../income/ssi_countable_income.py | 12 +++-- 14 files changed, 293 insertions(+), 30 deletions(-) create mode 100644 changelog.d/medicaid-abd-noncitizen-countable-income.fixed.md 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..e52eaa35d0c --- /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. 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..b7d0dc449bd 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 + # an SSI-qualified status), but CAPI counts her pension: 2,000 - 20 = + # 1,980/month exceeds the 994/month 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 = 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 + # 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..b34926450ce 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 has pension counted + period: 2024 + 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: 6_000 + households: + household: + members: [person1] + state_code: CA + output: + ssi: 0 + ca_capi_eligible_person: true + # (500 - 20) x 12 = 5,760 of countable income. + ssi_countable_income: 5_760 + ca_state_supplement: 0 + # 943 x 12 = 11,316 payment standard, less the 10 offset and 5,760. + ca_capi: 5_546 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, From 56dc11f8dbd440c1adf96d27064b41f3f499e0ef Mon Sep 17 00:00:00 2001 From: Ziming Date: Wed, 21 Oct 2026 18:22:15 -0400 Subject: [PATCH 02/18] Fix issues from review: CA SSP and MD PAA for people SSI bars by alien status Counting the own income of aged, blind or disabled people who fail SSI's noncitizen test exposed two downstream defects found in the 2026-10-19 review: - The California state supplement summed ssi_countable_income over the whole SPM unit, so a CAPI-eligible relative's income reduced an SSI recipient's supplement. CAPI budgets its own members' income (MPP 49-035), and SSI/SSP counts another member's income only when it is deemed (20 CFR 416.1160(a)), so CAPI-eligible members are left out of the sum. - Maryland PAA deemed spouse income and imputed federal SSI to people SSA cannot pay. For people who fail SSI's citizen or qualified-noncitizen test, PAA now counts only their own income and imputes no SSI (COMAR 07.03.07.07 and 07.03.07.09A). The CAPI test that encoded the federal-benefit-only standard is replaced with an over-income case that holds before and after the CAPI rework. Co-Authored-By: Claude Opus 5.5 --- ...d-abd-noncitizen-countable-income.fixed.md | 2 +- .../gov/local/ca/sf/caap/ca_sf_caap.yaml | 10 ++-- .../gov/states/ca/cdss/capi/ca_capi.yaml | 16 +++--- .../state_supplement/ca_state_supplement.yaml | 54 +++++++++++++++++++ .../gov/states/md/dhs/fia/paa/md_paa.yaml | 50 +++++++++++++++++ .../state_supplement/ca_state_supplement.py | 16 +++++- .../md/dhs/fia/paa/md_paa_countable_income.py | 15 +++++- .../dhs/fia/paa/md_paa_imputed_federal_ssi.py | 13 ++++- 8 files changed, 158 insertions(+), 18 deletions(-) diff --git a/changelog.d/medicaid-abd-noncitizen-countable-income.fixed.md b/changelog.d/medicaid-abd-noncitizen-countable-income.fixed.md index e52eaa35d0c..abfa381b4b1 100644 --- a/changelog.d/medicaid-abd-noncitizen-countable-income.fixed.md +++ b/changelog.d/medicaid-abd-noncitizen-countable-income.fixed.md @@ -1 +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. +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/local/ca/sf/caap/ca_sf_caap.yaml b/policyengine_us/tests/policy/baseline/gov/local/ca/sf/caap/ca_sf_caap.yaml index b7d0dc449bd..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 @@ -339,11 +339,11 @@ spm_unit_cash_assets: 0 output: # person2 is categorically CAPI-eligible (aged 68 + noncitizen + TPS is not - # an SSI-qualified status), but CAPI counts her pension: 2,000 - 20 = - # 1,980/month exceeds the 994/month 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. + # 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 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 b34926450ce..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 @@ -99,8 +99,8 @@ ca_state_supplement: 0 ca_capi: 11_306 -- name: Integration test, aged permanent resident without 40 SSI quarters has pension counted - period: 2024 +- 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: @@ -109,7 +109,7 @@ immigration_status: LEGAL_PERMANENT_RESIDENT years_since_us_entry: 10 ssi_qualifying_quarters_earnings: 0 - pension_income: 6_000 + pension_income: 24_000 # 2,000 a month households: household: members: [person1] @@ -117,8 +117,8 @@ output: ssi: 0 ca_capi_eligible_person: true - # (500 - 20) x 12 = 5,760 of countable income. - ssi_countable_income: 5_760 - ca_state_supplement: 0 - # 943 x 12 = 11,316 payment standard, less the 10 offset and 5,760. - ca_capi: 5_546 + # (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/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) From e126f9fa303e7ab8de648bb07d21a9e87c8b508c Mon Sep 17 00:00:00 2001 From: Ziming Date: Wed, 21 Oct 2026 18:22:29 -0400 Subject: [PATCH 03/18] Pay California CAPI from the SSI/SSP standard per person, with deeming CAPI payment standards equal the SSI/SSP payment standards less $10 for an individual and $20 for a couple (MPP 49-050.1, .11-.13). The model instead used the federal benefit rate plus the SPM unit's state supplement payment, pooled every CAPI-eligible member's income against one unit standard, applied the $10/$20 offset once a year, and left the tax-unit spouse of a noncitizen couple out. - ca_capi_payment_standard: the SSI/SSP standard for an individual, or half the couple standard, built from the state supplement parameters, less the monthly offset. - ca_capi_person: the standard less the person's own countable income (MPP 49-055.3), with spouse-to-spouse deeming computed as POMS SI 01320.430 D prescribes (federal and state parts each the lesser of the individual and deeming amounts). - ca_capi sums ca_capi_person; ca_capi_income_eligible asks whether any member's income is below their standard (MPP 49-035.1). - Both members of a noncitizen couple, and the noncitizen spouse of a citizen, are CAPI-eligible (MPP 49-055.4, 49-050.13). Co-Authored-By: Claude Opus 5.5 --- changelog.d/ca-capi-ssi-ssp-standard.fixed.md | 1 + .../capi/payment_standard_offset/couple.yaml | 6 +- .../capi/payment_standard_offset/single.yaml | 6 +- .../gov/states/ca/cdss/capi/ca_capi.yaml | 136 ++++++++++++--- .../cdss/capi/ca_capi_payment_standard.yaml | 155 ++++++++++++++++++ .../states/ca/cdss/capi/ca_capi_person.yaml | 142 ++++++++++++++++ .../eligibility/ca_capi_eligible_person.yaml | 26 ++- .../eligibility/ca_capi_income_eligible.yaml | 63 +++++-- .../ca/cdss/capi/_ca_capi_ssi_ssp_standard.py | 75 +++++++++ .../gov/states/ca/cdss/capi/ca_capi.py | 21 +-- .../ca/cdss/capi/ca_capi_payment_standard.py | 27 +++ .../gov/states/ca/cdss/capi/ca_capi_person.py | 51 ++++++ .../eligibility/ca_capi_eligible_person.py | 14 +- .../eligibility/ca_capi_income_eligible.py | 18 +- 14 files changed, 660 insertions(+), 81 deletions(-) create mode 100644 changelog.d/ca-capi-ssi-ssp-standard.fixed.md create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi_payment_standard.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi_person.yaml create mode 100644 policyengine_us/variables/gov/states/ca/cdss/capi/_ca_capi_ssi_ssp_standard.py create mode 100644 policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_payment_standard.py create mode 100644 policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_person.py diff --git a/changelog.d/ca-capi-ssi-ssp-standard.fixed.md b/changelog.d/ca-capi-ssi-ssp-standard.fixed.md new file mode 100644 index 00000000000..40040d59dbd --- /dev/null +++ b/changelog.d/ca-capi-ssi-ssp-standard.fixed.md @@ -0,0 +1 @@ +Base California CAPI on the full SSI/SSP payment standard less the monthly $10 individual or $20 couple offset, pay each eligible person (including both spouses of a noncitizen couple) on their own income, and apply spouse-to-spouse deeming. diff --git a/policyengine_us/parameters/gov/states/ca/cdss/capi/payment_standard_offset/couple.yaml b/policyengine_us/parameters/gov/states/ca/cdss/capi/payment_standard_offset/couple.yaml index 8c9c77fc547..27eeb894489 100644 --- a/policyengine_us/parameters/gov/states/ca/cdss/capi/payment_standard_offset/couple.yaml +++ b/policyengine_us/parameters/gov/states/ca/cdss/capi/payment_standard_offset/couple.yaml @@ -1,8 +1,8 @@ -description: California reduces the Supplemental Security Income / State Supplemental Payment payment standard by this amount for couples when calculating the Cash Assistance Program for Immigrants. +description: California deducts this amount from the Supplemental Security Income and State Supplementary Payment couple standard under the Cash Assistance Program for Immigrants. metadata: unit: currency-USD - period: year - label: California CAPI couple payment standard offset + period: month + label: California CAPI couple payment standard offset reference: - title: California Eligibility and Assistance Standards Chapter 49-050 (.1) href: https://www.cdss.ca.gov/Portals/9/CAPI/CAPI_Regulations-Accessible.pdf#page=44 diff --git a/policyengine_us/parameters/gov/states/ca/cdss/capi/payment_standard_offset/single.yaml b/policyengine_us/parameters/gov/states/ca/cdss/capi/payment_standard_offset/single.yaml index 8ea02f39e03..cf2c05cff3d 100644 --- a/policyengine_us/parameters/gov/states/ca/cdss/capi/payment_standard_offset/single.yaml +++ b/policyengine_us/parameters/gov/states/ca/cdss/capi/payment_standard_offset/single.yaml @@ -1,8 +1,8 @@ -description: California reduces the Supplemental Security Income / State Supplemental Payment payment standard by this amount for single filers when calculating the Cash Assistance Program for Immigrants. +description: California deducts this amount from the Supplemental Security Income and State Supplementary Payment individual standard under the Cash Assistance Program for Immigrants. metadata: unit: currency-USD - period: year - label: California CAPI single payment standard offset + period: month + label: California CAPI single payment standard offset reference: - title: California Eligibility and Assistance Standards Chapter 49-050 (.1) href: https://www.cdss.ca.gov/Portals/9/CAPI/CAPI_Regulations-Accessible.pdf#page=44 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..4ec8615ae66 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 @@ -1,38 +1,53 @@ - name: Single eligible person - period: 2024 + period: 2026 + absolute_error_margin: 0.01 input: people: person1: - ssi_amount_if_eligible: 1_000 - ca_capi_eligible_person: true - ssi_countable_income: 500 - spm_units: - spm_unit: + age: 70 + immigration_status: UNDOCUMENTED + # 520 per month foreign pension. + pension_income: 6_240 + # SSI zeroes countable income for people who fail its immigration + # test, so the case supplies it: 520 - 20 general exclusion = 500 per + # month (6,000 per year). + ssi_countable_income: 6_000 + households: + household: members: [person1] - ca_capi_eligible: true - ca_state_supplement: 2_000 + state_code: CA + living_arrangements_allow_for_food_preparation: true output: - ca_capi: 2_490 + # Individual standard 1,233.94 - 10 = 1,223.94 (MPP 49-050.11), less + # countable income 500 = 723.94 per month (MPP 49-055.32). + # 723.94 x 12 = 8,687.28. + ca_capi: 8_687.28 - name: Couple, both people eligible - period: 2024 + period: 2026 + absolute_error_margin: 0.01 input: people: person1: - ssi_amount_if_eligible: 1_000 - ca_capi_eligible_person: true - ssi_countable_income: 500 + age: 72 + immigration_status: UNDOCUMENTED person2: - ssi_amount_if_eligible: 1_000 - ca_capi_eligible_person: true - ssi_countable_income: 4_000 - spm_units: - spm_unit: + age: 68 + immigration_status: UNDOCUMENTED + marital_units: + marital_unit: members: [person1, person2] - ca_capi_eligible: true - ca_state_supplement: 4_000 + households: + household: + members: [person1, person2] + state_code: CA + living_arrangements_allow_for_food_preparation: true output: - ca_capi: 1_480 + # Couple standard 2,098.83 - 20 = 2,078.83 (MPP 49-050.12); each member + # receives one-half (MPP 49-055.4): 1,039.415 per month, 12,472.98 per + # year. The unit total is 2 x 12,472.98 = 24,945.96. + ca_capi_person: [12_472.98, 12_472.98] + ca_capi: 24_945.96 - name: Integration test, ineligible period: 2024 @@ -74,7 +89,8 @@ ca_capi: 0 - name: Integration test, undocumented - period: 2024 + period: 2026 + absolute_error_margin: 0.01 input: people: person1: @@ -97,4 +113,78 @@ ca_state_supplement_blind_amount: 0 ca_state_supplement_aged_blind_disabled_amount: 0 ca_state_supplement: 0 - ca_capi: 11_306 + # Disabled individual standard 1,233.94 + no-cooking food allowance + # 128.87 (living arrangements default to no food preparation) = + # 1,362.81; less $10 = 1,352.81 per month. Earnings of 83.33 per month + # fall within the $20 + $65 exclusions, so countable income is 0. + # 1,352.81 x 12 = 16,233.72. + ca_capi: 16_233.72 + +- name: Mixed couple, only the noncitizen spouse receives CAPI + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 72 + immigration_status: CITIZEN + person2: + age: 68 + immigration_status: UNDOCUMENTED + marital_units: + marital_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: CA + living_arrangements_allow_for_food_preparation: true + output: + # The citizen receives SSI/SSP, which CAPI does not add. The noncitizen + # spouse's standard is 2,098.83 / 2 - 10 = 1,039.415 per month + # (MPP 49-050.13); 1,039.415 x 12 = 12,472.98. + ca_capi_person: [0, 12_472.98] + ca_capi: 12_472.98 + +- name: Two unrelated eligible people in one unit, income is not pooled + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 72 + immigration_status: UNDOCUMENTED + # 1,520 per month foreign pension. + pension_income: 18_240 + # SSI zeroes countable income for people who fail its immigration + # test, so the case supplies it: 1,520 - 20 = 1,500 per month + # (18,000 per year). + ssi_countable_income: 18_000 + person2: + age: 68 + immigration_status: UNDOCUMENTED + 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 + living_arrangements_allow_for_food_preparation: true + output: + # Each person is assessed on their own income (MPP 49-035.1, 49-055.32). + # person1: 1,500 is not lower than the 1,223.94 standard, so 0. + # person2: no income, so 1,223.94 per month; x 12 = 14,687.28. Pooling + # person1's excess income with person2's standard would lower this. + ca_capi_person: [0, 14_687.28] + ca_capi: 14_687.28 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi_payment_standard.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi_payment_standard.yaml new file mode 100644 index 00000000000..9e277d6c34f --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi_payment_standard.yaml @@ -0,0 +1,155 @@ +- name: Case 1, aged individual with cooking facilities. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + immigration_status: UNDOCUMENTED + households: + household: + members: [person1] + state_code: CA + living_arrangements_allow_for_food_preparation: true + output: + # MPP 49-050.11: the SSI/SSP aged or disabled individual standard + # 1,233.94 less $10 = 1,223.94. + ca_capi_payment_standard: 1_223.94 + +- name: Case 2, aged individual without cooking facilities in 2025. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + immigration_status: UNDOCUMENTED + households: + household: + members: [person1] + state_code: CA + living_arrangements_allow_for_food_preparation: false + output: + # 2025 aged or disabled individual standard 1,206.94 + no-cooking food + # allowance 128.87 (WIC 12200(e)) = 1,335.81; less $10 = 1,325.81. + ca_capi_payment_standard: 1_325.81 + +- name: Case 3, blind individual without cooking facilities gets no food allowance. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + is_blind: true + immigration_status: UNDOCUMENTED + households: + household: + members: [person1] + state_code: CA + living_arrangements_allow_for_food_preparation: false + output: + # Blind individual standard 1,318.32. The no-cooking allowance applies + # only to aged or disabled people (WIC 12200(e)), so 1,318.32 - 10 = + # 1,308.32. + ca_capi_payment_standard: 1_308.32 + +- name: Case 4, aged noncitizen couple with cooking facilities splits the couple standard. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 72 + immigration_status: UNDOCUMENTED + person2: + age: 68 + immigration_status: UNDOCUMENTED + marital_units: + marital_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: CA + living_arrangements_allow_for_food_preparation: true + output: + # Both spouses are aged, so the SSI couple computation applies. + # Couple standard 2,098.83 less $20 (MPP 49-050.12) = 2,078.83; each + # member receives one-half (MPP 49-055.4): 1,039.415. + ca_capi_payment_standard: [1_039.415, 1_039.415] + +- name: Case 5, aged noncitizen couple without cooking facilities adds the couple food allowance. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 72 + immigration_status: UNDOCUMENTED + person2: + age: 68 + immigration_status: UNDOCUMENTED + marital_units: + marital_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: CA + living_arrangements_allow_for_food_preparation: false + output: + # Couple standard 2,098.83 + couple no-cooking allowance 257.74 = + # 2,356.57; less $20 = 2,336.57; one-half each = 1,168.285. + ca_capi_payment_standard: [1_168.285, 1_168.285] + +- name: Case 6, noncitizen couple with one blind member uses the one-blind couple standard. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + immigration_status: UNDOCUMENTED + person2: + age: 60 + is_blind: true + immigration_status: UNDOCUMENTED + marital_units: + marital_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: CA + living_arrangements_allow_for_food_preparation: true + output: + # The one-blind couple standard 2,238.44 (WIC 12200(b)) exceeds the + # aged couple standard 2,098.83 and applies (MPP 49-050.27). Less $20 = + # 2,218.44; one-half each = 1,109.22. + ca_capi_payment_standard: [1_109.22, 1_109.22] + +- name: Case 7, noncitizen spouse of an aged citizen gets half the couple standard less $10. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 72 + immigration_status: CITIZEN + person2: + age: 68 + immigration_status: UNDOCUMENTED + marital_units: + marital_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: CA + living_arrangements_allow_for_food_preparation: true + output: + # The citizen receives SSI/SSP, not CAPI. MPP 49-050.13 sets the couple + # standard $10 below the SSI/SSP couple standard, so the CAPI member's + # half is 2,098.83 / 2 - 10 = 1,039.415. + ca_capi_payment_standard: [0, 1_039.415] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi_person.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi_person.yaml new file mode 100644 index 00000000000..80cb66deb4f --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi_person.yaml @@ -0,0 +1,142 @@ +- name: Case 1, aged noncitizen couple splits the couple's countable income. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 72 + immigration_status: UNDOCUMENTED + # 420 per month foreign pension. + pension_income: 5_040 + # SSI zeroes countable income for people who fail its immigration + # test, so the case supplies it. The couple's countable income is + # 420 - 20 general exclusion = 400 per month, split equally as SSI + # does for a couple: 200 per month (2,400 per year) each. + ssi_countable_income: 2_400 + person2: + age: 68 + immigration_status: UNDOCUMENTED + ssi_countable_income: 2_400 + marital_units: + marital_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: CA + living_arrangements_allow_for_food_preparation: true + output: + # Couple standard 2,098.83 - 20 = 2,078.83, less the couple's countable + # income 400 = 1,678.83 (MPP 49-055.32); each member receives one-half + # (MPP 49-055.4): 839.415. + ca_capi_person: [839.415, 839.415] + +- name: Case 2, deemed income from an ineligible spouse below the couple FBR. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + immigration_status: UNDOCUMENTED + # SSI does not compute these for people who fail its immigration + # test, so the case supplies them. The spouse earns 500 per month, + # above the 497 gap between the couple and individual FBRs + # (1,491 - 994), so deeming applies. Couple countable income is + # (500 - 20 - 65) / 2 = 207.50 per month (2,490 per year), all of it + # deemed because person1 has no income of her own. + is_ssi_spousal_deeming_applies: true + ssi_income_deemed_from_ineligible_spouse: 2_490 + ssi_countable_income: 2_490 + person2: + age: 50 + employment_income: 6_000 + marital_units: + marital_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: CA + living_arrangements_allow_for_food_preparation: true + output: + # POMS SI 01320.430 D. + # As an individual: federal 994 - 0 = 994; a federal benefit is due, so + # the state supplement is the full individual OSS 1,233.94 - 994 = 239.94. + # Under deeming: federal 1,491 - 207.50 = 1,283.50; a federal benefit is + # due, so the state supplement is the couple OSS 2,098.83 - 1,491 = 607.83. + # Federal = min(994, 1,283.50) = 994; state = min(239.94, 607.83) = 239.94. + # CAPI = 994 + 239.94 - 10 = 1,223.94. + ca_capi_person: [1_223.94, 0] + +- name: Case 3, deemed income above the couple FBR reduces the couple state supplement. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + immigration_status: UNDOCUMENTED + # Supplied for the reason in Case 2. The spouse earns 3,867 per + # month; couple countable income is (3,867 - 85) / 2 = 1,891 per + # month (22,692 per year), all deemed. + is_ssi_spousal_deeming_applies: true + ssi_income_deemed_from_ineligible_spouse: 22_692 + ssi_countable_income: 22_692 + person2: + age: 50 + employment_income: 46_404 + marital_units: + marital_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: CA + living_arrangements_allow_for_food_preparation: true + output: + # POMS SI 01320.430 D. + # As an individual: federal 994; state supplement 239.94. + # Under deeming: 1,891 exceeds the couple FBR 1,491 by 400, so no federal + # benefit; state supplement = couple OSS 607.83 - 400 = 207.83. + # Federal = min(994, 0) = 0; state = min(239.94, 207.83) = 207.83. + # CAPI = 0 + 207.83 - 10 = 197.83. + ca_capi_person: [197.83, 0] + +- name: Case 4, blind noncitizen with an ineligible spouse uses the two-blind couple rate under deeming. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 45 + is_blind: true + immigration_status: UNDOCUMENTED + # Supplied for the reason in Case 2. The spouse earns 4,267 per + # month; couple countable income is (4,267 - 85) / 2 = 2,091 per + # month (25,092 per year), all deemed. + is_ssi_spousal_deeming_applies: true + ssi_income_deemed_from_ineligible_spouse: 25_092 + ssi_countable_income: 25_092 + person2: + age: 42 + employment_income: 51_204 + marital_units: + marital_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: CA + living_arrangements_allow_for_food_preparation: true + output: + # POMS SI 01320.430 C.7 and D. + # As an individual: federal 994; state supplement = blind individual + # OSS 1,318.32 - 994 = 324.32. + # Under deeming the ineligible spouse is treated as blind too, so the + # couple OSS is the two-blind rate 2,324.35 - 1,491 = 833.35. 2,091 + # exceeds the couple FBR by 600, so no federal benefit; state supplement + # = 833.35 - 600 = 233.35. + # Federal = 0; state = min(324.32, 233.35) = 233.35. + # CAPI = 0 + 233.35 - 10 = 223.35. + ca_capi_person: [223.35, 0] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/eligibility/ca_capi_eligible_person.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/eligibility/ca_capi_eligible_person.yaml index 4991ca5f673..287beb1cab9 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/eligibility/ca_capi_eligible_person.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/eligibility/ca_capi_eligible_person.yaml @@ -2,7 +2,6 @@ period: 2023 input: is_ssi_aged_blind_disabled: true - is_ssi_eligible_spouse: false immigration_status: UNDOCUMENTED state_code: CA output: @@ -12,7 +11,6 @@ period: 2023 input: is_ssi_aged_blind_disabled: true - is_ssi_eligible_spouse: false immigration_status: CITIZEN state_code: CA output: @@ -22,9 +20,31 @@ period: 2023 input: is_ssi_aged_blind_disabled: true - is_ssi_eligible_spouse: false immigration_status: LEGAL_PERMANENT_RESIDENT ssi_qualifying_quarters_earnings: 39 state_code: CA output: ca_capi_eligible_person: true + +- name: Eligible couple - both spouses aged and undocumented + period: 2026 + input: + people: + person1: + age: 72 + immigration_status: UNDOCUMENTED + person2: + age: 68 + immigration_status: UNDOCUMENTED + marital_units: + marital_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: CA + output: + # person2 is the tax-unit spouse of an aged couple. Each member of an + # eligible couple receives CAPI (MPP 49-055.4), so the spouse is eligible + # too. + ca_capi_eligible_person: [true, true] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/eligibility/ca_capi_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/eligibility/ca_capi_income_eligible.yaml index a33d38fa225..accef876957 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/eligibility/ca_capi_income_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/eligibility/ca_capi_income_eligible.yaml @@ -1,21 +1,60 @@ -- name: Ineligible - period: 2024 +- name: Ineligible, countable income one dollar above the payment standard + period: 2026 input: - ssi_amount_if_eligible: 2_000 - ca_state_supplement_payment_standard: 1_000 - ssi_countable_income: 3_001 - ca_capi_eligible_person: true + age: 70 + immigration_status: UNDOCUMENTED + # SSI zeroes countable income for people who fail its immigration test, + # so the case supplies it: 1,224.94 per month (14,699.28 per year). + ssi_countable_income: 14_699.28 + living_arrangements_allow_for_food_preparation: true state_code: CA output: + # Standard 1,233.94 - 10 = 1,223.94. Countable income must be lower than + # the standard (MPP 49-035.1); 1,224.94 is not, so there is no CAPI. ca_capi_income_eligible: false -- name: Eligible - period: 2024 +- name: Eligible, countable income one dollar below the payment standard + period: 2026 input: - ssi_amount_if_eligible: 2_000 - ca_state_supplement_payment_standard: 1_000 - ssi_countable_income: 2_999 - ca_capi_eligible_person: true + age: 70 + immigration_status: UNDOCUMENTED + # Supplied as above: 1,222.94 per month (14,675.28 per year). + ssi_countable_income: 14_675.28 + living_arrangements_allow_for_food_preparation: true state_code: CA output: + # 1,222.94 is lower than the 1,223.94 standard: 1 per month of CAPI. ca_capi_income_eligible: true + +- name: Ineligible, income deemed from a high-earning spouse exhausts the couple state supplement + period: 2026 + input: + people: + person1: + age: 70 + immigration_status: UNDOCUMENTED + # SSI does not compute these for people who fail its immigration + # test, so the case supplies them. The spouse earns 5,000 per month; + # couple countable income is (5,000 - 20 - 65) / 2 = 2,457.50 per + # month (29,490 per year), all deemed. + is_ssi_spousal_deeming_applies: true + ssi_income_deemed_from_ineligible_spouse: 29_490 + ssi_countable_income: 29_490 + person2: + age: 50 + employment_income: 60_000 + marital_units: + marital_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: CA + living_arrangements_allow_for_food_preparation: true + output: + # POMS SI 01320.430 D. As an individual: federal 994, state 239.94. + # Under deeming: 2,457.50 exceeds the couple FBR 1,491 by 966.50, which + # exceeds the couple OSS 607.83, so neither a federal benefit nor a + # state supplement is due. Federal = 0, state = min(239.94, 0) = 0, and + # CAPI = max(0, 0 - 10) = 0 in every month. + ca_capi_income_eligible: false diff --git a/policyengine_us/variables/gov/states/ca/cdss/capi/_ca_capi_ssi_ssp_standard.py b/policyengine_us/variables/gov/states/ca/cdss/capi/_ca_capi_ssi_ssp_standard.py new file mode 100644 index 00000000000..28bec390276 --- /dev/null +++ b/policyengine_us/variables/gov/states/ca/cdss/capi/_ca_capi_ssi_ssp_standard.py @@ -0,0 +1,75 @@ +from policyengine_us.model_api import * + + +def ca_capi_ssi_ssp_standard(person, period, parameters): + """Return a person's monthly SSI/SSP individual and couple standards. + + CAPI payment standards equal the SSI/SSP standards less an offset (MPP + 49-050.1). These follow ca_state_supplement_payment_standard, whose amounts + include the federal benefit rate: the higher of the blind amount and the + aged or disabled amount (the disabled child amount for a dependent child, + MPP 49-050.25; blind children take the blind amount, MPP 49-050.253), the + food allowance for an aged or disabled adult who cannot prepare meals, and + the out-of-home-care and medical-care-facility allowances per person. + In an SSI couple computation the couple standard uses both members; + otherwise it treats the ineligible spouse as the person's category (POMS + SI 01320.430 C.7) and adds only the person's own allowances. + """ + p = parameters(period).gov.states.ca.cdss.state_supplement.payment_standard + age = person("monthly_age", period) + child = person("is_tax_unit_dependent", period.this_year) & ( + age < p.dependent.age_limit + ) + blind = person("is_blind", period.this_year) + aged_or_disabled = (age >= p.aged_or_disabled.age_threshold) | person( + "is_ssi_disabled", period.this_year + ) + no_cooking = ~person.household( + "living_arrangements_allow_for_food_preparation", period.this_year + ) + allowance = ( + person("in_out_of_home_care_facility", period.this_year) + * p.allowance.out_of_home_care + + person("ca_in_medical_care_facility", period.this_year) + * p.allowance.medical_care_facility + ) + individual = ( + max_( + blind * p.blind.single, + aged_or_disabled + * where(child, p.dependent.amount, p.aged_or_disabled.amount.single), + ) + + aged_or_disabled * ~child * no_cooking * p.allowance.food.single + + allowance + ) + + joint = person("ssi_couple_computation_applies", period) + blind_count = where(joint, person.marital_unit.sum(blind), 2 * blind) + aged_or_disabled_count = where( + joint, person.marital_unit.sum(aged_or_disabled), 2 * aged_or_disabled + ) + blind_amount = select( + [blind_count > 1, blind_count == 1], + [p.blind.married.two_blind, p.blind.married.one_blind], + default=0, + ) + aged_or_disabled_amount = select( + [aged_or_disabled_count > 1, aged_or_disabled_count == 1], + [p.aged_or_disabled.amount.married, p.aged_or_disabled.amount.single], + default=0, + ) + food = ( + (aged_or_disabled_count > 0) + * no_cooking + * where( + aged_or_disabled_count > 1, + p.allowance.food.married, + p.allowance.food.single, + ) + ) + couple = ( + max_(blind_amount, aged_or_disabled_amount) + + food + + where(joint, person.marital_unit.sum(allowance), allowance) + ) + return individual, couple diff --git a/policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi.py b/policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi.py index c7d975049b2..ddf4a41ed0c 100644 --- a/policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi.py +++ b/policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi.py @@ -8,21 +8,8 @@ class ca_capi(Variable): label = "California CAPI" definition_period = YEAR defined_for = "ca_capi_eligible" - reference = "https://www.cdss.ca.gov/Portals/9/CAPI/CAPI_Regulations-Accessible.pdf" + reference = ( + "https://www.cdss.ca.gov/Portals/9/CAPI/CAPI_Regulations-Accessible.pdf#page=47" + ) - def formula(spm_unit, period, parameters): - state_supplement_payment_standard = spm_unit("ca_state_supplement", period) - person = spm_unit.members - ssi_amount_if_eligible = person("ssi_amount_if_eligible", period) - eligible_person = person("ca_capi_eligible_person", period) - total_ssi_amount = spm_unit.sum(ssi_amount_if_eligible * eligible_person) - payment_standard = state_supplement_payment_standard + total_ssi_amount - p = parameters(period).gov.states.ca.cdss.capi.payment_standard_offset - married = spm_unit("spm_unit_is_married", period) - offset = where(married, p.couple, p.single) - total_payment_standard = max_(payment_standard - offset, 0) - person = spm_unit.members - countable_income = spm_unit.sum( - (person("ssi_countable_income", period) * eligible_person) - ) - return max_(0, total_payment_standard - countable_income) + adds = ["ca_capi_person"] diff --git a/policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_payment_standard.py b/policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_payment_standard.py new file mode 100644 index 00000000000..3f9b820804c --- /dev/null +++ b/policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_payment_standard.py @@ -0,0 +1,27 @@ +from policyengine_us.model_api import * +from policyengine_us.variables.gov.states.ca.cdss.capi._ca_capi_ssi_ssp_standard import ( + ca_capi_ssi_ssp_standard, +) + + +class ca_capi_payment_standard(Variable): + value_type = float + entity = Person + label = "California CAPI payment standard" + unit = USD + definition_period = MONTH + defined_for = "ca_capi_eligible_person" + reference = ( + # PDF pages 44-46 + "https://www.cdss.ca.gov/Portals/9/CAPI/CAPI_Regulations-Accessible.pdf#page=44", + "https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?lawCode=WIC§ionNum=12200", + ) + + def formula(person, period, parameters): + individual, couple = ca_capi_ssi_ssp_standard(person, period, parameters) + p = parameters(period).gov.states.ca.cdss.capi.payment_standard_offset + joint = person("ssi_couple_computation_applies", period) + # Each member of a couple takes half the couple standard less half the + # couple offset, so a couple with one SSI/SSP member is one half-offset + # below the SSI/SSP couple standard (MPP 49-050.12-.13). + return where(joint, (couple - p.couple) / 2, individual - p.single) diff --git a/policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_person.py b/policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_person.py new file mode 100644 index 00000000000..888aba48190 --- /dev/null +++ b/policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_person.py @@ -0,0 +1,51 @@ +from policyengine_us.model_api import * +from policyengine_us.variables.gov.states.ca.cdss.capi._ca_capi_ssi_ssp_standard import ( + ca_capi_ssi_ssp_standard, +) + + +class ca_capi_person(Variable): + value_type = float + entity = Person + label = "California CAPI amount per person" + unit = USD + definition_period = MONTH + defined_for = "ca_capi_eligible_person" + reference = ( + # PDF pages 25, 30, 47 + "https://www.cdss.ca.gov/Portals/9/CAPI/CAPI_Regulations-Accessible.pdf#page=25", + "https://secure.ssa.gov/poms.nsf/lnx/0501320430", + ) + + def formula(person, period, parameters): + countable_income = person("ssi_countable_income", period) + payment_standard = person("ca_capi_payment_standard", period) + benefit = max_(payment_standard - countable_income, 0) + + # MPP 49-035.71 follows the SSI spouse-to-spouse deeming steps: compute + # the federal and state parts as an individual and under deeming, then + # take the lesser of each (POMS SI 01320.430 D). + # NOTE: the federal parts use the independent-living benefit rates, + # matching the independent-living SSI/SSP standards. + individual_standard, couple_standard = ca_capi_ssi_ssp_standard( + person, period, parameters + ) + fbr = parameters(period).gov.ssa.ssi.amount + deemed_income = person("ssi_income_deemed_from_ineligible_spouse", period) + own_income = max_(countable_income - deemed_income, 0) + individual_federal = fbr.individual - own_income + couple_federal = fbr.couple - countable_income + federal = max_(min_(individual_federal, couple_federal), 0) + individual_supplement = individual_standard - fbr.individual + couple_supplement = max_(couple_standard - fbr.couple, individual_supplement) + # Income above a federal rate reduces the matching state supplement. + supplement = min_( + individual_supplement + min_(individual_federal, 0), + couple_supplement + min_(couple_federal, 0), + ) + p = parameters(period).gov.states.ca.cdss.capi.payment_standard_offset + deemed_benefit = max_(federal + supplement - p.single, 0) + deeming = person("is_ssi_spousal_deeming_applies", period.this_year) & ~person( + "ssi_couple_computation_applies", period + ) + return where(deeming, deemed_benefit, benefit) diff --git a/policyengine_us/variables/gov/states/ca/cdss/capi/eligibility/ca_capi_eligible_person.py b/policyengine_us/variables/gov/states/ca/cdss/capi/eligibility/ca_capi_eligible_person.py index 6309ee13c10..ea946c5b4ea 100644 --- a/policyengine_us/variables/gov/states/ca/cdss/capi/eligibility/ca_capi_eligible_person.py +++ b/policyengine_us/variables/gov/states/ca/cdss/capi/eligibility/ca_capi_eligible_person.py @@ -7,18 +7,16 @@ class ca_capi_eligible_person(Variable): label = "California CAPI eligible person" definition_period = YEAR defined_for = StateCode.CA - reference = "https://www.cdss.ca.gov/Portals/9/CAPI/CAPI_Regulations-Accessible.pdf" + # PDF pages 10, 47 + reference = ( + "https://www.cdss.ca.gov/Portals/9/CAPI/CAPI_Regulations-Accessible.pdf#page=10" + ) def formula(person, period, parameters): + # Both members of a couple can be eligible (MPP 49-055.4). aged_blind_disabled = person("is_ssi_aged_blind_disabled", period) - is_ssi_eligible_spouse = person("is_ssi_eligible_spouse", period) immigration_status = person("immigration_status", period) is_citizen = immigration_status == immigration_status.possible_values.CITIZEN is_qualified_noncitizen = person("is_ssi_qualified_noncitizen", period) - return ( - aged_blind_disabled - & ~is_ssi_eligible_spouse - & ~is_citizen - & ~is_qualified_noncitizen - ) + return aged_blind_disabled & ~is_citizen & ~is_qualified_noncitizen diff --git a/policyengine_us/variables/gov/states/ca/cdss/capi/eligibility/ca_capi_income_eligible.py b/policyengine_us/variables/gov/states/ca/cdss/capi/eligibility/ca_capi_income_eligible.py index ed3148b592d..a3351201fbf 100644 --- a/policyengine_us/variables/gov/states/ca/cdss/capi/eligibility/ca_capi_income_eligible.py +++ b/policyengine_us/variables/gov/states/ca/cdss/capi/eligibility/ca_capi_income_eligible.py @@ -7,17 +7,11 @@ class ca_capi_income_eligible(Variable): label = "California CAPI income eligible" definition_period = YEAR defined_for = StateCode.CA - reference = "https://www.cdss.ca.gov/Portals/9/CAPI/CAPI_Regulations-Accessible.pdf" + reference = ( + "https://www.cdss.ca.gov/Portals/9/CAPI/CAPI_Regulations-Accessible.pdf#page=25" + ) def formula(spm_unit, period, parameters): - payment_standard = add( - spm_unit, - period, - ["ssi_amount_if_eligible", "ca_state_supplement_payment_standard"], - ) - person = spm_unit.members - eligible_person = person("ca_capi_eligible_person", period) - countable_income = spm_unit.sum( - (person("ssi_countable_income", period) * eligible_person) - ) - return payment_standard > countable_income + # MPP 49-035.1 compares each individual's or couple's countable income + # with the CAPI payment standard; a payment remains only when it is lower. + return add(spm_unit, period, ["ca_capi_person"]) > 0 From 9e39da393d57d12291349b34a1a8b90fd8e8fde7 Mon Sep 17 00:00:00 2001 From: Ziming Date: Mon, 26 Oct 2026 21:04:51 -0400 Subject: [PATCH 04/18] Fix issues from review: CAPI equals SSI/SSP since June 2019, mixed couples, one standard per arrangement - Offsets are $0 from June 1, 2019 (WIC 18941; ACIN I-23-19); new mixed-couple offset (MPP 49-050.13) before then - Mixed couple: couple standard less the couple's countable income and the spouse's SSI/SSP (MPP 49-005(e)(3), 49-035.221) - Title XIX facility $62 and non-medical out-of-home care $1,626.07 replace the community standard; no-cooking allowance only on the aged or disabled amount - Floor the standards at the federal benefit rate while the CA SSP parameters hold 1991 totals (issue 7787) - No deeming for a Title XIX facility resident (20 CFR 416.1160(a)(1)) - candidates.yaml: us-ca:capi-payment-standard-offset (open, Pavel's sign-off) and us-ca:capi-spousal-deeming-method (unreviewed) Co-Authored-By: Claude Opus 5.5 --- changelog.d/ca-capi-ssi-ssp-standard.fixed.md | 2 +- .../capi/payment_standard_offset/couple.yaml | 15 +- .../payment_standard_offset/mixed_couple.yaml | 17 ++ .../capi/payment_standard_offset/single.yaml | 15 +- .../gov/states/ca/cdss/capi/ca_capi.yaml | 68 ++++-- .../cdss/capi/ca_capi_payment_standard.yaml | 230 ++++++++++++++++-- .../states/ca/cdss/capi/ca_capi_person.yaml | 142 ++++++++++- .../eligibility/ca_capi_income_eligible.yaml | 19 +- .../ca/cdss/capi/_ca_capi_ssi_ssp_standard.py | 107 ++++---- .../ca/cdss/capi/ca_capi_payment_standard.py | 26 +- .../gov/states/ca/cdss/capi/ca_capi_person.py | 63 ++++- source_conflicts/candidates.yaml | 77 ++++++ 12 files changed, 653 insertions(+), 128 deletions(-) create mode 100644 policyengine_us/parameters/gov/states/ca/cdss/capi/payment_standard_offset/mixed_couple.yaml diff --git a/changelog.d/ca-capi-ssi-ssp-standard.fixed.md b/changelog.d/ca-capi-ssi-ssp-standard.fixed.md index 40040d59dbd..beb3dba5fdd 100644 --- a/changelog.d/ca-capi-ssi-ssp-standard.fixed.md +++ b/changelog.d/ca-capi-ssi-ssp-standard.fixed.md @@ -1 +1 @@ -Base California CAPI on the full SSI/SSP payment standard less the monthly $10 individual or $20 couple offset, pay each eligible person (including both spouses of a noncitizen couple) on their own income, and apply spouse-to-spouse deeming. +Pay California CAPI at the SSI/SSP payment standard (with no offset since June 2019) using one standard per living arrangement, compute each eligible person's benefit on their own income, count the SSI/SSP of a spouse who receives it, and apply spouse-to-spouse deeming. diff --git a/policyengine_us/parameters/gov/states/ca/cdss/capi/payment_standard_offset/couple.yaml b/policyengine_us/parameters/gov/states/ca/cdss/capi/payment_standard_offset/couple.yaml index 27eeb894489..3e76e4ce95c 100644 --- a/policyengine_us/parameters/gov/states/ca/cdss/capi/payment_standard_offset/couple.yaml +++ b/policyengine_us/parameters/gov/states/ca/cdss/capi/payment_standard_offset/couple.yaml @@ -1,10 +1,17 @@ -description: California deducts this amount from the Supplemental Security Income and State Supplementary Payment couple standard under the Cash Assistance Program for Immigrants. +description: California deducts this amount from the Supplemental Security Income and State Supplementary Payment couple standard under the Cash Assistance Program for Immigrants until June 2019. +values: + 1991-01-01: 20 + 2019-06-01: 0 metadata: unit: currency-USD period: month label: California CAPI couple payment standard offset reference: - - title: California Eligibility and Assistance Standards Chapter 49-050 (.1) + - title: California Eligibility and Assistance Standards Chapter 49-050 (.12) href: https://www.cdss.ca.gov/Portals/9/CAPI/CAPI_Regulations-Accessible.pdf#page=44 -values: - 1991-01-01: 20 + - title: California Welfare and Institutions Code Section 18941 + href: https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?lawCode=WIC§ionNum=18941 + - title: California Department of Social Services, All County Information Notice I-23-19, CAPI payment standards effective June 1, 2019 + href: https://www.cdss.ca.gov/Portals/9/ACIN/2019/I-23_19.pdf#page=2 + - title: California Department of Social Services, All County Information Notice I-59-25, CAPI payment standards for January 2026 + href: https://cdss.ca.gov/Portals/9/Additional-Resources/Letters-and-Notices/ACINs/2025/I-59_25.pdf#page=5 diff --git a/policyengine_us/parameters/gov/states/ca/cdss/capi/payment_standard_offset/mixed_couple.yaml b/policyengine_us/parameters/gov/states/ca/cdss/capi/payment_standard_offset/mixed_couple.yaml new file mode 100644 index 00000000000..050c39241ed --- /dev/null +++ b/policyengine_us/parameters/gov/states/ca/cdss/capi/payment_standard_offset/mixed_couple.yaml @@ -0,0 +1,17 @@ +description: California deducts this amount from the Supplemental Security Income and State Supplementary Payment couple standard for mixed couples under the Cash Assistance Program for Immigrants until June 2019. +values: + 1991-01-01: 10 + 2019-06-01: 0 +metadata: + unit: currency-USD + period: month + label: California CAPI mixed couple payment standard offset + reference: + - title: California Eligibility and Assistance Standards Chapter 49-050 (.13) + href: https://www.cdss.ca.gov/Portals/9/CAPI/CAPI_Regulations-Accessible.pdf#page=44 + - title: California Welfare and Institutions Code Section 18941 + href: https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?lawCode=WIC§ionNum=18941 + - title: California Department of Social Services, All County Information Notice I-23-19, CAPI payment standards effective June 1, 2019 + href: https://www.cdss.ca.gov/Portals/9/ACIN/2019/I-23_19.pdf#page=2 + - title: California Department of Social Services, All County Information Notice I-59-25, CAPI payment standards for January 2026 + href: https://cdss.ca.gov/Portals/9/Additional-Resources/Letters-and-Notices/ACINs/2025/I-59_25.pdf#page=5 diff --git a/policyengine_us/parameters/gov/states/ca/cdss/capi/payment_standard_offset/single.yaml b/policyengine_us/parameters/gov/states/ca/cdss/capi/payment_standard_offset/single.yaml index cf2c05cff3d..db5ece35f70 100644 --- a/policyengine_us/parameters/gov/states/ca/cdss/capi/payment_standard_offset/single.yaml +++ b/policyengine_us/parameters/gov/states/ca/cdss/capi/payment_standard_offset/single.yaml @@ -1,10 +1,17 @@ -description: California deducts this amount from the Supplemental Security Income and State Supplementary Payment individual standard under the Cash Assistance Program for Immigrants. +description: California deducts this amount from the Supplemental Security Income and State Supplementary Payment individual standard under the Cash Assistance Program for Immigrants until June 2019. +values: + 1991-01-01: 10 + 2019-06-01: 0 metadata: unit: currency-USD period: month label: California CAPI single payment standard offset reference: - - title: California Eligibility and Assistance Standards Chapter 49-050 (.1) + - title: California Eligibility and Assistance Standards Chapter 49-050 (.11) href: https://www.cdss.ca.gov/Portals/9/CAPI/CAPI_Regulations-Accessible.pdf#page=44 -values: - 1991-01-01: 10 + - title: California Welfare and Institutions Code Section 18941 + href: https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?lawCode=WIC§ionNum=18941 + - title: California Department of Social Services, All County Information Notice I-23-19, CAPI payment standards effective June 1, 2019 + href: https://www.cdss.ca.gov/Portals/9/ACIN/2019/I-23_19.pdf#page=2 + - title: California Department of Social Services, All County Information Notice I-59-25, CAPI payment standards for January 2026 + href: https://cdss.ca.gov/Portals/9/Additional-Resources/Letters-and-Notices/ACINs/2025/I-59_25.pdf#page=5 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 4ec8615ae66..7ddbe20a697 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 @@ -18,10 +18,10 @@ state_code: CA living_arrangements_allow_for_food_preparation: true output: - # Individual standard 1,233.94 - 10 = 1,223.94 (MPP 49-050.11), less - # countable income 500 = 723.94 per month (MPP 49-055.32). - # 723.94 x 12 = 8,687.28. - ca_capi: 8_687.28 + # Individual standard 1,233.94 (no offset since June 2019, WIC 18941), + # less countable income 500 = 733.94 per month (MPP 49-055.32). + # 733.94 x 12 = 8,807.28. + ca_capi: 8_807.28 - name: Couple, both people eligible period: 2026 @@ -43,11 +43,11 @@ state_code: CA living_arrangements_allow_for_food_preparation: true output: - # Couple standard 2,098.83 - 20 = 2,078.83 (MPP 49-050.12); each member - # receives one-half (MPP 49-055.4): 1,039.415 per month, 12,472.98 per - # year. The unit total is 2 x 12,472.98 = 24,945.96. - ca_capi_person: [12_472.98, 12_472.98] - ca_capi: 24_945.96 + # Couple standard 2,098.83 with no offset; each member receives one-half + # (MPP 49-055.4): 1,049.415 per month, 12,592.98 per year. The unit + # total is 2 x 12,592.98 = 25,185.96. + ca_capi_person: [12_592.98, 12_592.98] + ca_capi: 25_185.96 - name: Integration test, ineligible period: 2024 @@ -115,10 +115,10 @@ ca_state_supplement: 0 # Disabled individual standard 1,233.94 + no-cooking food allowance # 128.87 (living arrangements default to no food preparation) = - # 1,362.81; less $10 = 1,352.81 per month. Earnings of 83.33 per month - # fall within the $20 + $65 exclusions, so countable income is 0. - # 1,352.81 x 12 = 16,233.72. - ca_capi: 16_233.72 + # 1,362.81 per month with no offset. Earnings of 83.33 per month fall + # within the $20 + $65 exclusions, so countable income is 0. + # 1,362.81 x 12 = 16,353.72. + ca_capi: 16_353.72 - name: Mixed couple, only the noncitizen spouse receives CAPI period: 2026 @@ -140,11 +140,14 @@ state_code: CA living_arrangements_allow_for_food_preparation: true output: - # The citizen receives SSI/SSP, which CAPI does not add. The noncitizen - # spouse's standard is 2,098.83 / 2 - 10 = 1,039.415 per month - # (MPP 49-050.13); 1,039.415 x 12 = 12,472.98. - ca_capi_person: [0, 12_472.98] - ca_capi: 12_472.98 + # The citizen receives SSI/SSP, which counts as the CAPI member's + # unearned income (MPP 49-035.221). The model pays the citizen SSI of + # 1,491 / 2 = 745.50 and a state supplement of 1,233.94 - 745.50 = + # 488.44 per month; SSA pays 994 + 239.94, the same 1,233.94 total. + # CAPI = couple standard 2,098.83 (MPP 49-050.13, no offset) - 0 income + # - 745.50 - 488.44 = 864.89 per month; 864.89 x 12 = 10,378.68. + ca_capi_person: [0, 10_378.68] + ca_capi: 10_378.68 - name: Two unrelated eligible people in one unit, income is not pooled period: 2026 @@ -183,8 +186,29 @@ living_arrangements_allow_for_food_preparation: true output: # Each person is assessed on their own income (MPP 49-035.1, 49-055.32). - # person1: 1,500 is not lower than the 1,223.94 standard, so 0. - # person2: no income, so 1,223.94 per month; x 12 = 14,687.28. Pooling + # person1: 1,500 is not lower than the 1,233.94 standard, so 0. + # person2: no income, so 1,233.94 per month; x 12 = 14,807.28. Pooling # person1's excess income with person2's standard would lower this. - ca_capi_person: [0, 14_687.28] - ca_capi: 14_687.28 + ca_capi_person: [0, 14_807.28] + ca_capi: 14_807.28 + +- name: Aged person in 2024, the independent-living standard is floored at the federal benefit rate + period: 2024 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + immigration_status: UNDOCUMENTED + households: + household: + members: [person1] + state_code: CA + living_arrangements_allow_for_food_preparation: true + output: + # The state supplement parameters hold the 1991 aged amount of 630 until + # 2025 (issue 7787). CAPI equals SSI/SSP (WIC 18941), so the standard is + # floored at the 2024 federal benefit rate: max(630, 943) = 943 per + # month with no offset and no income; 943 x 12 = 11,316. + ca_capi_person: 11_316 + ca_capi: 11_316 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi_payment_standard.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi_payment_standard.yaml index 9e277d6c34f..14389061408 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi_payment_standard.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi_payment_standard.yaml @@ -12,9 +12,10 @@ state_code: CA living_arrangements_allow_for_food_preparation: true output: - # MPP 49-050.11: the SSI/SSP aged or disabled individual standard - # 1,233.94 less $10 = 1,223.94. - ca_capi_payment_standard: 1_223.94 + # WIC 18941: the CAPI standard equals the SSI/SSP aged or disabled + # individual standard, with no offset since June 2019 (ACIN I-59-25): + # 994 + 239.94 = 1,233.94. + ca_capi_payment_standard: 1_233.94 - name: Case 2, aged individual without cooking facilities in 2025. period: 2025-01 @@ -31,8 +32,9 @@ living_arrangements_allow_for_food_preparation: false output: # 2025 aged or disabled individual standard 1,206.94 + no-cooking food - # allowance 128.87 (WIC 12200(e)) = 1,335.81; less $10 = 1,325.81. - ca_capi_payment_standard: 1_325.81 + # allowance 128.87 (WIC 12200(e)) = 1,335.81, above the 967 federal + # benefit rate; no offset. + ca_capi_payment_standard: 1_335.81 - name: Case 3, blind individual without cooking facilities gets no food allowance. period: 2026-01 @@ -50,9 +52,9 @@ living_arrangements_allow_for_food_preparation: false output: # Blind individual standard 1,318.32. The no-cooking allowance applies - # only to aged or disabled people (WIC 12200(e)), so 1,318.32 - 10 = - # 1,308.32. - ca_capi_payment_standard: 1_308.32 + # only to aged or disabled people (WIC 12200(e)), so the standard stays + # 1,318.32. + ca_capi_payment_standard: 1_318.32 - name: Case 4, aged noncitizen couple with cooking facilities splits the couple standard. period: 2026-01 @@ -75,9 +77,9 @@ living_arrangements_allow_for_food_preparation: true output: # Both spouses are aged, so the SSI couple computation applies. - # Couple standard 2,098.83 less $20 (MPP 49-050.12) = 2,078.83; each - # member receives one-half (MPP 49-055.4): 1,039.415. - ca_capi_payment_standard: [1_039.415, 1_039.415] + # Couple standard 2,098.83 with no offset; each member receives one-half + # (MPP 49-055.4): 2,098.83 / 2 = 1,049.415. + ca_capi_payment_standard: [1_049.415, 1_049.415] - name: Case 5, aged noncitizen couple without cooking facilities adds the couple food allowance. period: 2026-01 @@ -100,8 +102,8 @@ living_arrangements_allow_for_food_preparation: false output: # Couple standard 2,098.83 + couple no-cooking allowance 257.74 = - # 2,356.57; less $20 = 2,336.57; one-half each = 1,168.285. - ca_capi_payment_standard: [1_168.285, 1_168.285] + # 2,356.57; one-half each = 1,178.285. + ca_capi_payment_standard: [1_178.285, 1_178.285] - name: Case 6, noncitizen couple with one blind member uses the one-blind couple standard. period: 2026-01 @@ -125,11 +127,11 @@ living_arrangements_allow_for_food_preparation: true output: # The one-blind couple standard 2,238.44 (WIC 12200(b)) exceeds the - # aged couple standard 2,098.83 and applies (MPP 49-050.27). Less $20 = - # 2,218.44; one-half each = 1,109.22. - ca_capi_payment_standard: [1_109.22, 1_109.22] + # aged couple standard 2,098.83 and applies (MPP 49-050.27); one-half + # each = 1,119.22. + ca_capi_payment_standard: [1_119.22, 1_119.22] -- name: Case 7, noncitizen spouse of an aged citizen gets half the couple standard less $10. +- name: Case 7, noncitizen spouse of an aged SSI/SSP recipient takes the whole couple standard. period: 2026-01 absolute_error_margin: 0.01 input: @@ -149,7 +151,193 @@ state_code: CA living_arrangements_allow_for_food_preparation: true output: - # The citizen receives SSI/SSP, not CAPI. MPP 49-050.13 sets the couple - # standard $10 below the SSI/SSP couple standard, so the CAPI member's - # half is 2,098.83 / 2 - 10 = 1,039.415. - ca_capi_payment_standard: [0, 1_039.415] + # The citizen receives SSI/SSP, not CAPI, and counts as an eligible + # spouse (MPP 49-005(e)(3)). The CAPI member takes the whole couple + # standard (MPP 49-050.13), whose offset is 0 since June 2019 (WIC + # 18941): 2,098.83. ca_capi_person subtracts the citizen's SSI/SSP. + ca_capi_payment_standard: [0, 2_098.83] + +- name: Case 8, Title XIX medical facility resident takes the facility standard alone. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 75 + immigration_status: UNDOCUMENTED + ca_in_medical_care_facility: true + households: + household: + members: [person1] + state_code: CA + living_arrangements_allow_for_food_preparation: false + output: + # ACIN I-59-25 and POMS SI 01415.058 code J: the Title XIX medical + # facility standard is 30 + 32 = 62 (MPP 49-050.26). It replaces the + # independent-living standard, adds no food allowance and is not floored + # at the federal benefit rate. + ca_capi_payment_standard: 62 + +- name: Case 9, nonmedical out-of-home care uses one standard for every category. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 75 + immigration_status: UNDOCUMENTED + in_out_of_home_care_facility: true + households: + household: + members: [person1] + state_code: CA + living_arrangements_allow_for_food_preparation: false + output: + # ACIN I-59-25 and POMS SI 01415.058 code B: half the couple + # out-of-home care standard, (2,098.83 + 1,153.31) / 2 = 3,252.14 / 2 = + # 1,626.07 (MPP 49-050.24). No food allowance is added. + ca_capi_payment_standard: 1_626.07 + +- name: Case 10, aged and blind individual without cooking takes the higher aged amount with food. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + is_blind: true + immigration_status: UNDOCUMENTED + households: + household: + members: [person1] + state_code: CA + living_arrangements_allow_for_food_preparation: false + output: + # California pays the highest category (POMS SI 01415.058 B.2): + # max(blind 1,318.32, aged 1,233.94 + food 128.87 = 1,362.81) = + # 1,362.81. The food allowance does not stack on the blind amount. + ca_capi_payment_standard: 1_362.81 + +- name: Case 11, disabled dependent child takes the disabled minor standard. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: UNDOCUMENTED + person2: + age: 10 + is_disabled: true + meets_ssi_disability_criteria: true + immigration_status: UNDOCUMENTED + marital_units: + marital_unit1: + members: [person1] + marital_unit2: + members: [person2] + households: + household: + members: [person1, person2] + state_code: CA + living_arrangements_allow_for_food_preparation: false + output: + # ACIN I-59-25 disabled minor 994 + 97.27 = 1,091.27 (MPP 49-050.25), + # with no food allowance. The parent is not aged, blind or disabled. + ca_capi_payment_standard: [0, 1_091.27] + +- name: Case 12, blind dependent child takes the blind standard. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: UNDOCUMENTED + person2: + age: 10 + is_blind: true + immigration_status: UNDOCUMENTED + marital_units: + marital_unit1: + members: [person1] + marital_unit2: + members: [person2] + households: + household: + members: [person1, person2] + state_code: CA + living_arrangements_allow_for_food_preparation: true + output: + # A blind child takes the blind amount, 1,318.32 (MPP 49-050.253). + ca_capi_payment_standard: [0, 1_318.32] + +- name: Case 13, aged couple with one blind member without cooking adds the individual food allowance. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 72 + immigration_status: UNDOCUMENTED + person2: + age: 70 + is_blind: true + immigration_status: UNDOCUMENTED + marital_units: + marital_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: CA + living_arrangements_allow_for_food_preparation: false + output: + # POMS SI 01415.058 code C note: the blind/aged couple level plus the + # individual restaurant allowance, 2,238.44 + 128.87 = 2,367.31. This + # beats the aged couple without cooking, 2,098.83 + 257.74 = 2,356.57. + # One-half each: 2,367.31 / 2 = 1,183.655. + ca_capi_payment_standard: [1_183.655, 1_183.655] + +- name: Case 14, 2024 independent-living standard is floored at the federal benefit rate. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + immigration_status: UNDOCUMENTED + households: + household: + members: [person1] + state_code: CA + living_arrangements_allow_for_food_preparation: true + output: + # The state supplement parameters hold the 1991 aged amount of 630 until + # 2025 (issue 7787), below the 2024 federal benefit rate of 943. CAPI + # equals SSI/SSP (WIC 18941), so the standard is max(630, 943) = 943. + ca_capi_payment_standard: 943 + +- name: Case 15, the 10 individual offset applies through May 2019 and ends in June 2019. + period: 2019 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + immigration_status: UNDOCUMENTED + households: + household: + members: [person1] + state_code: CA + living_arrangements_allow_for_food_preparation: true + output: + # The state supplement parameters hold the 1991 aged amount of 630 until + # 2025 (issue 7787), so the model floors the standard at the 2019 federal + # benefit rate: max(630, 771) = 771. The actual 2019 SSI/SSP standard was + # 931.72 (ACIN I-23-19). This case pins only the offset boundary: + # 771 - 10 = 761 through May 2019 (MPP 49-050.11) and 771 - 0 = 771 from + # June 1, 2019 (WIC 18941). + ca_capi_payment_standard: + 2019-05: 761 + 2019-06: 771 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi_person.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi_person.yaml index 80cb66deb4f..00789c189c0 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi_person.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi_person.yaml @@ -26,10 +26,10 @@ state_code: CA living_arrangements_allow_for_food_preparation: true output: - # Couple standard 2,098.83 - 20 = 2,078.83, less the couple's countable - # income 400 = 1,678.83 (MPP 49-055.32); each member receives one-half - # (MPP 49-055.4): 839.415. - ca_capi_person: [839.415, 839.415] + # Couple standard 2,098.83 (no offset since June 2019, WIC 18941), less + # the couple's countable income 400 = 1,698.83 (MPP 49-055.32); each + # member receives one-half (MPP 49-055.4): 849.415. + ca_capi_person: [849.415, 849.415] - name: Case 2, deemed income from an ineligible spouse below the couple FBR. period: 2026-01 @@ -66,8 +66,8 @@ # Under deeming: federal 1,491 - 207.50 = 1,283.50; a federal benefit is # due, so the state supplement is the couple OSS 2,098.83 - 1,491 = 607.83. # Federal = min(994, 1,283.50) = 994; state = min(239.94, 607.83) = 239.94. - # CAPI = 994 + 239.94 - 10 = 1,223.94. - ca_capi_person: [1_223.94, 0] + # CAPI = 994 + 239.94 = 1,233.94 (no offset since June 2019). + ca_capi_person: [1_233.94, 0] - name: Case 3, deemed income above the couple FBR reduces the couple state supplement. period: 2026-01 @@ -100,8 +100,8 @@ # Under deeming: 1,891 exceeds the couple FBR 1,491 by 400, so no federal # benefit; state supplement = couple OSS 607.83 - 400 = 207.83. # Federal = min(994, 0) = 0; state = min(239.94, 207.83) = 207.83. - # CAPI = 0 + 207.83 - 10 = 197.83. - ca_capi_person: [197.83, 0] + # CAPI = 0 + 207.83 = 207.83. + ca_capi_person: [207.83, 0] - name: Case 4, blind noncitizen with an ineligible spouse uses the two-blind couple rate under deeming. period: 2026-01 @@ -138,5 +138,127 @@ # exceeds the couple FBR by 600, so no federal benefit; state supplement # = 833.35 - 600 = 233.35. # Federal = 0; state = min(324.32, 233.35) = 233.35. - # CAPI = 0 + 233.35 - 10 = 223.35. - ca_capi_person: [223.35, 0] + # CAPI = 0 + 233.35 = 233.35. + ca_capi_person: [233.35, 0] + +- name: Case 5, deeming with the CAPI person's own income uses the couple federal amount. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + immigration_status: UNDOCUMENTED + # 320 per month foreign pension; own countable income is 320 - 20 = + # 300 per month. + pension_income: 3_840 + # Supplied for the reason in Case 2. The spouse earns 2,000 per + # month, so (2,000 - 65) / 2 = 967.50 per month (11,610 per year) is + # deemed, and countable income is 300 + 967.50 = 1,267.50 per month + # (15,210 per year). + is_ssi_spousal_deeming_applies: true + ssi_income_deemed_from_ineligible_spouse: 11_610 + ssi_countable_income: 15_210 + person2: + age: 50 + employment_income: 24_000 + marital_units: + marital_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: CA + living_arrangements_allow_for_food_preparation: true + output: + # POMS SI 01320.430 D. + # As an individual: federal 994 - 300 = 694; a federal benefit is due, + # so the state supplement is the full individual OSS 239.94. + # Under deeming: federal 1,491 - 1,267.50 = 223.50; a federal benefit is + # due, so the state supplement is the couple OSS 607.83. + # Federal = min(694, 223.50) = 223.50; state = min(239.94, 607.83) = + # 239.94. CAPI = 223.50 + 239.94 = 463.44. + ca_capi_person: [463.44, 0] + +- name: Case 6, mixed couple subtracts the couple's income and the spouse's SSI/SSP from the couple standard. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 72 + immigration_status: CITIZEN + # SSA treats the noncitizen as an ineligible spouse whose 420 pension + # is below the 497 deeming threshold (1,491 - 994), so the citizen + # receives the individual rate with no countable income: SSI 994 + # plus state supplement 239.94 (POMS SI 01415.058). The case supplies + # these, since the model's split of the couple's SSI and income is + # being reworked separately. + ssi: 994 + ssi_countable_income: 0 + person2: + age: 68 + immigration_status: UNDOCUMENTED + # 420 per month foreign pension; countable income is 420 - 20 = 400 + # per month (4,800 per year), supplied as in Case 1. + pension_income: 5_040 + ssi_countable_income: 4_800 + marital_units: + marital_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + ca_state_supplement: 239.94 + households: + household: + members: [person1, person2] + state_code: CA + living_arrangements_allow_for_food_preparation: true + output: + # The CAPI member takes the couple standard 2,098.83 (MPP 49-050.13, no + # offset since June 2019). The couple's countable income 0 + 400 (MPP + # 49-055.32) and the citizen's SSI/SSP 994 + 239.94, counted as unearned + # income based on need (MPP 49-035.221), are subtracted: + # 2,098.83 - 400 - 994 - 239.94 = 464.89. + ca_capi_payment_standard: [0, 2_098.83] + ca_capi_person: [0, 464.89] + +- name: Case 7, Title XIX facility resident is paid on own income without deeming. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 75 + immigration_status: UNDOCUMENTED + ca_in_medical_care_facility: true + # 40 per month foreign pension; own countable income is 40 - 20 = 20 + # per month. + pension_income: 480 + # Supplied as SSI deeming would compute them at home. The spouse + # earns 1,200 per month, so (1,200 - 65) / 2 = 567.50 per month + # (6,810 per year) is deemed, and countable income is 20 + 567.50 = + # 587.50 per month (7,050 per year). + is_ssi_spousal_deeming_applies: true + ssi_income_deemed_from_ineligible_spouse: 6_810 + ssi_countable_income: 7_050 + person2: + age: 50 + employment_income: 14_400 + marital_units: + marital_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: CA + living_arrangements_allow_for_food_preparation: true + output: + # Deeming needs an ineligible spouse living in the same household (20 + # CFR 416.1160(a)(1)), so the resident is paid the Title XIX standard 62 + # less own income 20 = 42. Deeming would give + # max(min(994 - 20, 1,491 - 587.50) + (62 - 994), 0) = 0, and subtracting + # the deemed income would give max(62 - 587.50, 0) = 0. + ca_capi_payment_standard: [62, 0] + ca_capi_person: [42, 0] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/eligibility/ca_capi_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/eligibility/ca_capi_income_eligible.yaml index accef876957..f57268bfd93 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/eligibility/ca_capi_income_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/eligibility/ca_capi_income_eligible.yaml @@ -4,13 +4,14 @@ age: 70 immigration_status: UNDOCUMENTED # SSI zeroes countable income for people who fail its immigration test, - # so the case supplies it: 1,224.94 per month (14,699.28 per year). - ssi_countable_income: 14_699.28 + # so the case supplies it: 1,234.94 per month (14,819.28 per year). + ssi_countable_income: 14_819.28 living_arrangements_allow_for_food_preparation: true state_code: CA output: - # Standard 1,233.94 - 10 = 1,223.94. Countable income must be lower than - # the standard (MPP 49-035.1); 1,224.94 is not, so there is no CAPI. + # Standard 1,233.94 with no offset since June 2019 (WIC 18941). + # Countable income must be lower than the standard (MPP 49-035.1); + # 1,234.94 is not, so there is no CAPI. ca_capi_income_eligible: false - name: Eligible, countable income one dollar below the payment standard @@ -18,12 +19,12 @@ input: age: 70 immigration_status: UNDOCUMENTED - # Supplied as above: 1,222.94 per month (14,675.28 per year). - ssi_countable_income: 14_675.28 + # Supplied as above: 1,232.94 per month (14,795.28 per year). + ssi_countable_income: 14_795.28 living_arrangements_allow_for_food_preparation: true state_code: CA output: - # 1,222.94 is lower than the 1,223.94 standard: 1 per month of CAPI. + # 1,232.94 is lower than the 1,233.94 standard: 1 per month of CAPI. ca_capi_income_eligible: true - name: Ineligible, income deemed from a high-earning spouse exhausts the couple state supplement @@ -55,6 +56,6 @@ # POMS SI 01320.430 D. As an individual: federal 994, state 239.94. # Under deeming: 2,457.50 exceeds the couple FBR 1,491 by 966.50, which # exceeds the couple OSS 607.83, so neither a federal benefit nor a - # state supplement is due. Federal = 0, state = min(239.94, 0) = 0, and - # CAPI = max(0, 0 - 10) = 0 in every month. + # state supplement is due. Federal = 0, state = min(239.94, 607.83 - + # 966.50) = -358.67, and CAPI = max(0 - 358.67, 0) = 0 in every month. ca_capi_income_eligible: false diff --git a/policyengine_us/variables/gov/states/ca/cdss/capi/_ca_capi_ssi_ssp_standard.py b/policyengine_us/variables/gov/states/ca/cdss/capi/_ca_capi_ssi_ssp_standard.py index 28bec390276..0be284f8a9f 100644 --- a/policyengine_us/variables/gov/states/ca/cdss/capi/_ca_capi_ssi_ssp_standard.py +++ b/policyengine_us/variables/gov/states/ca/cdss/capi/_ca_capi_ssi_ssp_standard.py @@ -4,18 +4,30 @@ def ca_capi_ssi_ssp_standard(person, period, parameters): """Return a person's monthly SSI/SSP individual and couple standards. - CAPI payment standards equal the SSI/SSP standards less an offset (MPP - 49-050.1). These follow ca_state_supplement_payment_standard, whose amounts - include the federal benefit rate: the higher of the blind amount and the - aged or disabled amount (the disabled child amount for a dependent child, - MPP 49-050.25; blind children take the blind amount, MPP 49-050.253), the - food allowance for an aged or disabled adult who cannot prepare meals, and - the out-of-home-care and medical-care-facility allowances per person. - In an SSI couple computation the couple standard uses both members; - otherwise it treats the ineligible spouse as the person's category (POMS - SI 01320.430 C.7) and adds only the person's own allowances. + CAPI payment standards equal the SSI/SSP standards (WIC 18941), and the + living arrangement selects one standard (MPP 49-050.2; POMS SI 01415.058 + B). These follow ca_state_supplement_payment_standard, whose amounts + include the federal benefit rate: + - Title XIX medical facility: the facility standard alone (MPP 49-050.26). + - Nonmedical out-of-home care: one standard for every category, half the + couple out-of-home care standard per person (MPP 49-050.24). + - Independent living: the higher of the blind amount and the aged or + disabled amount (the disabled child amount for a dependent child, MPP + 49-050.25; blind children take the blind amount, MPP 49-050.253). Only + the aged or disabled amount adds the food allowance for people who + cannot prepare meals (WIC 12200(e)); a couple with one blind member + adds the individual food allowance for the other member (POMS SI + 01415.058 B.1 code C). California pays the highest category a person or + couple qualifies for. + In an SSI couple computation the couple standard sums both members' + shares; otherwise it treats the ineligible spouse as the person's + category (POMS SI 01320.430 C.7). + NOTE: the reduced-needs standards for people living in another person's + household (POMS SI 01415.058 code D) are not modeled; they need their own + state supplement amounts (issue 7892). """ p = parameters(period).gov.states.ca.cdss.state_supplement.payment_standard + fbr = parameters(period).gov.ssa.ssi.amount age = person("monthly_age", period) child = person("is_tax_unit_dependent", period.this_year) & ( age < p.dependent.age_limit @@ -27,20 +39,20 @@ def ca_capi_ssi_ssp_standard(person, period, parameters): no_cooking = ~person.household( "living_arrangements_allow_for_food_preparation", period.this_year ) - allowance = ( - person("in_out_of_home_care_facility", period.this_year) - * p.allowance.out_of_home_care - + person("ca_in_medical_care_facility", period.this_year) - * p.allowance.medical_care_facility - ) - individual = ( - max_( - blind * p.blind.single, - aged_or_disabled - * where(child, p.dependent.amount, p.aged_or_disabled.amount.single), - ) - + aged_or_disabled * ~child * no_cooking * p.allowance.food.single - + allowance + medical_facility = person("ca_in_medical_care_facility", period.this_year) + out_of_home_care = person("in_out_of_home_care_facility", period.this_year) + out_of_home_care_share = ( + p.aged_or_disabled.amount.married + p.allowance.out_of_home_care + ) / 2 + + community_individual = max_( + blind * p.blind.single, + aged_or_disabled + * where( + child, + p.dependent.amount, + p.aged_or_disabled.amount.single + no_cooking * p.allowance.food.single, + ), ) joint = person("ssi_couple_computation_applies", period) @@ -48,28 +60,39 @@ def ca_capi_ssi_ssp_standard(person, period, parameters): aged_or_disabled_count = where( joint, person.marital_unit.sum(aged_or_disabled), 2 * aged_or_disabled ) - blind_amount = select( - [blind_count > 1, blind_count == 1], - [p.blind.married.two_blind, p.blind.married.one_blind], - default=0, + two_blind = (blind_count > 1) * p.blind.married.two_blind + one_blind = (blind_count == 1) * ( + p.blind.married.one_blind + no_cooking * p.allowance.food.single ) - aged_or_disabled_amount = select( + aged_or_disabled_couple = select( [aged_or_disabled_count > 1, aged_or_disabled_count == 1], - [p.aged_or_disabled.amount.married, p.aged_or_disabled.amount.single], + [ + p.aged_or_disabled.amount.married + no_cooking * p.allowance.food.married, + p.aged_or_disabled.amount.single + no_cooking * p.allowance.food.single, + ], default=0, ) - food = ( - (aged_or_disabled_count > 0) - * no_cooking - * where( - aged_or_disabled_count > 1, - p.allowance.food.married, - p.allowance.food.single, - ) + community_couple = max_(max_(two_blind, one_blind), aged_or_disabled_couple) + + # The state supplement amounts hold 1991 totals until 2025 (issue 7787), + # below the federal benefit rate from 2008. CAPI equals SSI/SSP (WIC + # 18941), and SSI alone pays at least the federal rate, so the + # independent-living and out-of-home care standards are floored at it. + individual = select( + [medical_facility, out_of_home_care], + [ + p.allowance.medical_care_facility, + max_(out_of_home_care_share, fbr.individual), + ], + default=max_(community_individual, fbr.individual), ) - couple = ( - max_(blind_amount, aged_or_disabled_amount) - + food - + where(joint, person.marital_unit.sum(allowance), allowance) + couple_share = select( + [medical_facility, out_of_home_care], + [ + p.allowance.medical_care_facility, + max_(out_of_home_care_share, fbr.couple / 2), + ], + default=max_(community_couple / 2, fbr.couple / 2), ) + couple = where(joint, person.marital_unit.sum(couple_share), 2 * couple_share) return individual, couple diff --git a/policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_payment_standard.py b/policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_payment_standard.py index 3f9b820804c..78318db3cbb 100644 --- a/policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_payment_standard.py +++ b/policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_payment_standard.py @@ -12,16 +12,30 @@ class ca_capi_payment_standard(Variable): definition_period = MONTH defined_for = "ca_capi_eligible_person" reference = ( - # PDF pages 44-46 - "https://www.cdss.ca.gov/Portals/9/CAPI/CAPI_Regulations-Accessible.pdf#page=44", + # PDF pages 3, 44-47 + "https://www.cdss.ca.gov/Portals/9/CAPI/CAPI_Regulations-Accessible.pdf#page=3", "https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?lawCode=WIC§ionNum=12200", + "https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?lawCode=WIC§ionNum=18941", + "https://secure.ssa.gov/apps10/poms.nsf/lnx/0501415058", + "https://cdss.ca.gov/Portals/9/Additional-Resources/Letters-and-Notices/ACINs/2025/I-59_25.pdf#page=5", ) def formula(person, period, parameters): individual, couple = ca_capi_ssi_ssp_standard(person, period, parameters) p = parameters(period).gov.states.ca.cdss.capi.payment_standard_offset joint = person("ssi_couple_computation_applies", period) - # Each member of a couple takes half the couple standard less half the - # couple offset, so a couple with one SSI/SSP member is one half-offset - # below the SSI/SSP couple standard (MPP 49-050.12-.13). - return where(joint, (couple - p.couple) / 2, individual - p.single) + capi_members = person.marital_unit.sum( + person("ca_capi_eligible_person", period.this_year) + ) + # Each member of a CAPI couple takes one-half (MPP 49-050.12, 49-055.4). + both_capi = joint & (capi_members > 1) + # A spouse receiving SSI/SSP counts as an eligible spouse (MPP + # 49-005(e)(3)), so the CAPI member of a mixed couple takes the whole + # couple standard (MPP 49-050.13) and ca_capi_person subtracts that + # spouse's SSI/SSP. + mixed = joint & ~both_capi + return select( + [both_capi, mixed], + [(couple - p.couple) / 2, couple - p.mixed_couple], + default=individual - p.single, + ) diff --git a/policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_person.py b/policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_person.py index 888aba48190..780c4c50c6d 100644 --- a/policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_person.py +++ b/policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_person.py @@ -12,27 +12,66 @@ class ca_capi_person(Variable): definition_period = MONTH defined_for = "ca_capi_eligible_person" reference = ( - # PDF pages 25, 30, 47 - "https://www.cdss.ca.gov/Portals/9/CAPI/CAPI_Regulations-Accessible.pdf#page=25", + # PDF pages 3-4, 25, 30, 47 + "https://www.cdss.ca.gov/Portals/9/CAPI/CAPI_Regulations-Accessible.pdf#page=3", + "https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?lawCode=WIC§ionNum=18940", + "https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?lawCode=WIC§ionNum=18941", "https://secure.ssa.gov/poms.nsf/lnx/0501320430", + "https://www.law.cornell.edu/cfr/text/20/416.1160", ) def formula(person, period, parameters): countable_income = person("ssi_countable_income", period) payment_standard = person("ca_capi_payment_standard", period) - benefit = max_(payment_standard - countable_income, 0) + deemed_income = person("ssi_income_deemed_from_ineligible_spouse", period) + own_income = max_(countable_income - deemed_income, 0) + # Deeming needs an ineligible spouse living in the same household + # (20 CFR 416.1160(a)(1)), so a Title XIX facility resident counts + # only their own income. + medical_facility = person("ca_in_medical_care_facility", period.this_year) + income = where(medical_facility, own_income, countable_income) + # NOTE: the reduced-needs standards for another person's household are + # not modeled (issue 7892), so those recipients get the + # independent-living standard. + benefit = max_(payment_standard - income, 0) + + # Mixed couple: the spouse's SSI/SSP counts as unearned income based on + # need (MPP 49-035.221), subtracted with the couple's countable income + # from the couple standard (MPP 49-055.32). + # NOTE: an aged, blind or disabled spouse who receives neither SSI/SSP + # nor CAPI is an ineligible spouse (MPP 49-005(i)(2)), but the model has + # no spouse-to-spouse deeming for such a spouse, so this computation + # applies. That spouse's SSI/SSP is zero mainly when the couple's income + # exceeds the couple standard, which already leaves no CAPI. + capi_eligible = person("ca_capi_eligible_person", period.this_year) + joint = person("ssi_couple_computation_applies", period) + mixed = joint & ~(person.marital_unit.sum(capi_eligible) > 1) + spouse = ~capi_eligible + spouse_ssi = person.marital_unit.sum(person("ssi", period) * spouse) + # NOTE: ca_state_supplement is an SPM-unit amount; as a simplification, + # the spouse's share is pro rata among the unit's SSP-eligible members. + ssp_eligible = person("ca_state_supplement_eligible_person", period) + spouse_ssp_share = person.marital_unit.sum(ssp_eligible * spouse) / max_( + person.spm_unit.sum(ssp_eligible), 1 + ) + spouse_ssp = spouse_ssp_share * person.spm_unit("ca_state_supplement", period) + couple_income = person.marital_unit.sum(countable_income) + mixed_benefit = max_( + payment_standard - couple_income - spouse_ssi - spouse_ssp, 0 + ) # MPP 49-035.71 follows the SSI spouse-to-spouse deeming steps: compute # the federal and state parts as an individual and under deeming, then - # take the lesser of each (POMS SI 01320.430 D). + # take the lesser of each (POMS SI 01320.430 D). WIC 18940(b) applies + # the federal deeming rules and WIC 18941 makes CAPI equal SSI/SSP, + # which SSA computes this way; the 1999 CAPI form SOC 452 takes the + # lesser of the two totals instead. # NOTE: the federal parts use the independent-living benefit rates, # matching the independent-living SSI/SSP standards. individual_standard, couple_standard = ca_capi_ssi_ssp_standard( person, period, parameters ) fbr = parameters(period).gov.ssa.ssi.amount - deemed_income = person("ssi_income_deemed_from_ineligible_spouse", period) - own_income = max_(countable_income - deemed_income, 0) individual_federal = fbr.individual - own_income couple_federal = fbr.couple - countable_income federal = max_(min_(individual_federal, couple_federal), 0) @@ -45,7 +84,13 @@ def formula(person, period, parameters): ) p = parameters(period).gov.states.ca.cdss.capi.payment_standard_offset deemed_benefit = max_(federal + supplement - p.single, 0) - deeming = person("is_ssi_spousal_deeming_applies", period.this_year) & ~person( - "ssi_couple_computation_applies", period + deeming = ( + person("is_ssi_spousal_deeming_applies", period.this_year) + & ~joint + & ~medical_facility + ) + return select( + [mixed, deeming], + [mixed_benefit, deemed_benefit], + default=benefit, ) - return where(deeming, deemed_benefit, benefit) diff --git a/source_conflicts/candidates.yaml b/source_conflicts/candidates.yaml index ab0faa5b4ec..578a4062247 100644 --- a/source_conflicts/candidates.yaml +++ b/source_conflicts/candidates.yaml @@ -628,6 +628,83 @@ candidates: prs: [] state: unreviewed note: Verify the legal basis for the amended-return remedy and treatment of exactly $3,000. +- id: us-ca:capi-payment-standard-offset + program: capi + years: + from: 2019 + type: calendar + question: From June 1, 2019, do CAPI payment standards equal the SSI/SSP standards, or remain $10 (individual), + $20 (CAPI couple) or $10 (couple with one SSI/SSP member) below them as the regulations state? + sources: + - kind: statute + citation: Cal. WIC ยง18941 + url: https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?lawCode=WIC§ionNum=18941 + - kind: regulation + citation: CDSS MPP ยง49-050.11-.13 (Manual Letter EAS-03-09, effective 10/16/03) + url: https://www.cdss.ca.gov/Portals/9/CAPI/CAPI_Regulations-Accessible.pdf#page=44 + - kind: guidance + citation: CDSS ACIN I-59-25, Attachment A + url: https://cdss.ca.gov/Portals/9/Additional-Resources/Letters-and-Notices/ACINs/2025/I-59_25.pdf#page=5 + readings: + statute: CAPI benefits equal SSI/SSP benefits, retroactive to June 1, 2019. + other: CAPI standards are $10 below the SSI/SSP individual standard, $20 below the couple standard for a CAPI + couple and $10 below the couple standard when the other spouse receives SSI/SSP. + example: In January 2026, an aged CAPI recipient living independently with cooking facilities and no income receives + $1,233.94 a month under the statute, which PE-US follows, and $1,223.94 under the regulation. + pe_us: + follows: statute + code: + - policyengine_us/parameters/gov/states/ca/cdss/capi/payment_standard_offset/couple.yaml + - policyengine_us/parameters/gov/states/ca/cdss/capi/payment_standard_offset/mixed_couple.yaml + - policyengine_us/parameters/gov/states/ca/cdss/capi/payment_standard_offset/single.yaml + - policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_payment_standard.py + prs: + - https://github.com/PolicyEngine/policyengine-us/pull/10379 + state: open + note: 'Pavel''s sign-off requested (statute against regulation). PE-US follows the statute: the three offsets are + $0 from 2019-06-01 and keep the regulation amounts before then (payment_standard_offset/*.yaml, read by + ca_capi_payment_standard.py). The 2003 regulation predates the 2019 statute; CDSS applies the statute in ACIN + I-23-19 (June 1, 2019 increase of $10 per individual and $20 per couple) and ACIN I-59-25.' +- id: us-ca:capi-spousal-deeming-method + program: capi + years: + from: 1999 + type: calendar + question: When income is deemed from an ineligible spouse, does CAPI take the lesser federal and lesser state amounts + separately, as SSA computes SSI/SSP, or the smaller of the two totals on form SOC 452? + sources: + - kind: statute + citation: Cal. WIC ยง18940(b) + url: https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?lawCode=WIC§ionNum=18940 + - kind: statute + citation: Cal. WIC ยง18941 + url: https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?lawCode=WIC§ionNum=18941 + - kind: regulation + citation: CDSS MPP ยง49-035.71 + url: https://www.cdss.ca.gov/Portals/9/CAPI/CAPI_Regulations-Accessible.pdf#page=30 + - kind: manual + citation: SSA POMS SI 01320.430 D + url: https://secure.ssa.gov/apps10/poms.nsf/lnx/0501320430 + - kind: form + citation: CDSS SOC 452 (4/99), CAPI Income Eligibility - Adult, line C + url: https://www.cdss.ca.gov/cdssweb/entres/forms/English/SOC452.pdf + readings: + statute: Federal deeming rules govern CAPI and CAPI benefits equal SSI/SSP benefits, which SSA computes by taking + the lesser federal amount and the lesser state supplement separately (POMS SI 01320.430 D). + other: SOC 452 pays the smaller of the couple standard less the couple's countable income and the individual standard + less the recipient's own countable income. + example: In January 2026, a CAPI recipient with no income whose ineligible spouse earns $1,200 a month receives $1,173.44 + under the statute and the POMS method, which PE-US follows, and $1,233.94 under SOC 452. + pe_us: + follows: statute + code: + - policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_person.py + prs: + - https://github.com/PolicyEngine/policyengine-us/pull/10379 + state: unreviewed + note: 'PE-US follows the statute: ca_capi_person.py takes the lesser of the federal parts and the lesser of the + state parts (POMS SI 01320.430 D). MPP 49-035.71 points to both 20 CFR 416.1160 et seq. and SOC 452. Verify + whether CDSS still uses the 1999 form''s line C rule and the years affected.' - id: us-ca:care-fera-housing-subsidies program: care-fera years: From 771f1d850287871ef06b23d66928c86fe804278a Mon Sep 17 00:00:00 2001 From: Ziming Date: Mon, 26 Oct 2026 21:39:30 -0400 Subject: [PATCH 05/18] Fix issues from review round 2: MD PAA receipt gate, CA mixed-couple tests, CAPI test pins - Maryland PAA keeps imputed SSI and spouse deeming for people who report SSI receipt - CA state supplement: mixed-couple case and the matching computed CAPI case; comment and reference fixes - CAPI tests from #10379: drop pins this PR now computes, keep the rest with accurate comments Co-Authored-By: Claude Opus 5.5 --- ...d-abd-noncitizen-countable-income.fixed.md | 2 +- .../gov/states/ca/cdss/capi/ca_capi.yaml | 72 ++++++++++++-- .../states/ca/cdss/capi/ca_capi_person.yaml | 80 +++++++-------- .../eligibility/ca_capi_income_eligible.yaml | 17 ++-- .../state_supplement/ca_state_supplement.yaml | 59 +++++++++++ .../gov/states/md/dhs/fia/paa/md_paa.yaml | 97 +++++++++++++++++++ .../state_supplement/ca_state_supplement.py | 11 ++- .../md/dhs/fia/paa/md_paa_countable_income.py | 10 +- .../dhs/fia/paa/md_paa_imputed_federal_ssi.py | 10 +- 9 files changed, 288 insertions(+), 70 deletions(-) diff --git a/changelog.d/medicaid-abd-noncitizen-countable-income.fixed.md b/changelog.d/medicaid-abd-noncitizen-countable-income.fixed.md index abfa381b4b1..cf078370c11 100644 --- a/changelog.d/medicaid-abd-noncitizen-countable-income.fixed.md +++ b/changelog.d/medicaid-abd-noncitizen-countable-income.fixed.md @@ -1 +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. +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 unless they report SSI receipt. 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 3bfcfe79c07..da240a267e9 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 @@ -8,16 +8,14 @@ immigration_status: UNDOCUMENTED # 520 per month foreign pension. pension_income: 6_240 - # SSI zeroes countable income for people who fail its immigration - # test, so the case supplies it: 520 - 20 general exclusion = 500 per - # month (6,000 per year). - ssi_countable_income: 6_000 households: household: members: [person1] state_code: CA living_arrangements_allow_for_food_preparation: true output: + # 520 - 20 general exclusion = 500 per month (6,000 per year). + ssi_countable_income: 6_000 # Individual standard 1,233.94 (no offset since June 2019, WIC 18941), # less countable income 500 = 733.94 per month (MPP 49-055.32). # 733.94 x 12 = 8,807.28. @@ -159,10 +157,6 @@ immigration_status: UNDOCUMENTED # 1,520 per month foreign pension. pension_income: 18_240 - # SSI zeroes countable income for people who fail its immigration - # test, so the case supplies it: 1,520 - 20 = 1,500 per month - # (18,000 per year). - ssi_countable_income: 18_000 person2: age: 68 immigration_status: UNDOCUMENTED @@ -185,6 +179,8 @@ state_code: CA living_arrangements_allow_for_food_preparation: true output: + # person1: 1,520 - 20 = 1,500 per month (18,000 per year). + ssi_countable_income: [18_000, 0] # Each person is assessed on their own income (MPP 49-035.1, 49-055.32). # person1: 1,500 is not lower than the 1,233.94 standard, so 0. # person2: no income, so 1,233.94 per month; x 12 = 14,807.28. Pooling @@ -236,3 +232,63 @@ # 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 + +- name: Integration test, mixed couple with income, the noncitizen spouse receives CAPI + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 72 + is_tax_unit_head: true + immigration_status: CITIZEN + social_security_retirement: 6_000 # 500 a month + person2: + age: 68 + is_tax_unit_spouse: true + immigration_status: UNDOCUMENTED + pension_income: 6_000 # 500 a month foreign pension + 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: CA + output: + # Both spouses are aged, so the model applies the SSI couple computation: + # (500 + 500 - 20) / 2 = 490 a month each (5,880 a year). + ssi_countable_income: [5_880, 5_880] + # The citizen's SSI is 1,450 / 2 - 490 = 235 a month. + # NOTE: SSA treats the undocumented spouse as an ineligible spouse + # (20 CFR 416.1160(d)). Her 500 exceeds the 1,450 - 967 = 483 gap, so SSA + # deems her income and pays SSI of min(967 - 480, 1,450 - 980) = 470 and + # a state supplement of min(1,335.81 - 967, 2,315.57 - 1,450) = 368.81, + # 838.81 in all (POMS SI 01320.430 D; 20 CFR 416.1163(e)(2)). CAPI would + # then be 2,315.57 - 980 - 838.81 = 496.76 a month (5,961.12 a year). The + # model's couple computation for a mixed-status couple pays + # 235 + 610.81 = 845.81, so CAPI is 489.76 instead of 496.76. This is a + # pre-existing ssi_claim_is_joint limitation: it counts aged, blind or + # disabled head/spouse status rather than SSI eligibility. The expected + # values below are the model's. + ssi: [2_820, 0] # 235 * 12 + # The citizen's state supplement is the 1,206.94 + 128.87 = 1,335.81 + # no-cooking individual standard less SSI 235 and his own 490: + # 610.81 a month. The CAPI member's 490 is not counted. + ca_state_supplement: 7_329.72 # 610.81 * 12 + # The CAPI member takes the whole couple standard (MPP 49-050.13), the + # 2,057.83 + 257.74 = 2,315.57 no-cooking aged couple standard, with no + # offset since June 2019 (WIC 18941). + ca_capi_payment_standard: [0, 27_786.84] # 2,315.57 * 12 + # The couple's countable income 490 + 490 = 980 (MPP 49-055.32) and the + # citizen's SSI/SSP 235 + 610.81, counted as unearned income based on + # need (MPP 49-035.221), are subtracted: + # 2,315.57 - 980 - 235 - 610.81 = 489.76 a month. + ca_capi_person: [0, 5_877.12] # 489.76 * 12 + ca_capi: 5_877.12 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi_person.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi_person.yaml index 00789c189c0..f0f2032f5f6 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi_person.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi_person.yaml @@ -8,15 +8,9 @@ immigration_status: UNDOCUMENTED # 420 per month foreign pension. pension_income: 5_040 - # SSI zeroes countable income for people who fail its immigration - # test, so the case supplies it. The couple's countable income is - # 420 - 20 general exclusion = 400 per month, split equally as SSI - # does for a couple: 200 per month (2,400 per year) each. - ssi_countable_income: 2_400 person2: age: 68 immigration_status: UNDOCUMENTED - ssi_countable_income: 2_400 marital_units: marital_unit: members: [person1, person2] @@ -26,6 +20,9 @@ state_code: CA living_arrangements_allow_for_food_preparation: true output: + # The couple's countable income is 420 - 20 general exclusion = 400 per + # month, split equally as SSI does for a couple: 200 per month each. + ssi_countable_income: [200, 200] # Couple standard 2,098.83 (no offset since June 2019, WIC 18941), less # the couple's countable income 400 = 1,698.83 (MPP 49-055.32); each # member receives one-half (MPP 49-055.4): 849.415. @@ -39,15 +36,6 @@ person1: age: 70 immigration_status: UNDOCUMENTED - # SSI does not compute these for people who fail its immigration - # test, so the case supplies them. The spouse earns 500 per month, - # above the 497 gap between the couple and individual FBRs - # (1,491 - 994), so deeming applies. Couple countable income is - # (500 - 20 - 65) / 2 = 207.50 per month (2,490 per year), all of it - # deemed because person1 has no income of her own. - is_ssi_spousal_deeming_applies: true - ssi_income_deemed_from_ineligible_spouse: 2_490 - ssi_countable_income: 2_490 person2: age: 50 employment_income: 6_000 @@ -60,6 +48,13 @@ state_code: CA living_arrangements_allow_for_food_preparation: true output: + # The spouse earns 500 per month, above the 497 gap between the couple + # and individual FBRs (1,491 - 994), so deeming applies. Couple countable + # income is (500 - 20 - 65) / 2 = 207.50 per month, all of it deemed + # because person1 has no income of her own. + is_ssi_spousal_deeming_applies: [true, false] + ssi_income_deemed_from_ineligible_spouse: [207.50, 0] + ssi_countable_income: [207.50, 0] # POMS SI 01320.430 D. # As an individual: federal 994 - 0 = 994; a federal benefit is due, so # the state supplement is the full individual OSS 1,233.94 - 994 = 239.94. @@ -77,12 +72,6 @@ person1: age: 70 immigration_status: UNDOCUMENTED - # Supplied for the reason in Case 2. The spouse earns 3,867 per - # month; couple countable income is (3,867 - 85) / 2 = 1,891 per - # month (22,692 per year), all deemed. - is_ssi_spousal_deeming_applies: true - ssi_income_deemed_from_ineligible_spouse: 22_692 - ssi_countable_income: 22_692 person2: age: 50 employment_income: 46_404 @@ -95,6 +84,11 @@ state_code: CA living_arrangements_allow_for_food_preparation: true output: + # The spouse earns 3,867 per month; couple countable income is + # (3,867 - 85) / 2 = 1,891 per month, all deemed. + is_ssi_spousal_deeming_applies: [true, false] + ssi_income_deemed_from_ineligible_spouse: [1_891, 0] + ssi_countable_income: [1_891, 0] # POMS SI 01320.430 D. # As an individual: federal 994; state supplement 239.94. # Under deeming: 1,891 exceeds the couple FBR 1,491 by 400, so no federal @@ -112,12 +106,6 @@ age: 45 is_blind: true immigration_status: UNDOCUMENTED - # Supplied for the reason in Case 2. The spouse earns 4,267 per - # month; couple countable income is (4,267 - 85) / 2 = 2,091 per - # month (25,092 per year), all deemed. - is_ssi_spousal_deeming_applies: true - ssi_income_deemed_from_ineligible_spouse: 25_092 - ssi_countable_income: 25_092 person2: age: 42 employment_income: 51_204 @@ -130,6 +118,11 @@ state_code: CA living_arrangements_allow_for_food_preparation: true output: + # The spouse earns 4,267 per month; couple countable income is + # (4,267 - 85) / 2 = 2,091 per month, all deemed. + is_ssi_spousal_deeming_applies: [true, false] + ssi_income_deemed_from_ineligible_spouse: [2_091, 0] + ssi_countable_income: [2_091, 0] # POMS SI 01320.430 C.7 and D. # As an individual: federal 994; state supplement = blind individual # OSS 1,318.32 - 994 = 324.32. @@ -152,13 +145,6 @@ # 320 per month foreign pension; own countable income is 320 - 20 = # 300 per month. pension_income: 3_840 - # Supplied for the reason in Case 2. The spouse earns 2,000 per - # month, so (2,000 - 65) / 2 = 967.50 per month (11,610 per year) is - # deemed, and countable income is 300 + 967.50 = 1,267.50 per month - # (15,210 per year). - is_ssi_spousal_deeming_applies: true - ssi_income_deemed_from_ineligible_spouse: 11_610 - ssi_countable_income: 15_210 person2: age: 50 employment_income: 24_000 @@ -171,6 +157,12 @@ state_code: CA living_arrangements_allow_for_food_preparation: true output: + # The spouse earns 2,000 per month, so (2,000 - 65) / 2 = 967.50 per + # month is deemed, and countable income is 300 + 967.50 = 1,267.50 per + # month. + is_ssi_spousal_deeming_applies: [true, false] + ssi_income_deemed_from_ineligible_spouse: [967.50, 0] + ssi_countable_income: [1_267.50, 0] # POMS SI 01320.430 D. # As an individual: federal 994 - 300 = 694; a federal benefit is due, # so the state supplement is the full individual OSS 239.94. @@ -199,8 +191,11 @@ person2: age: 68 immigration_status: UNDOCUMENTED - # 420 per month foreign pension; countable income is 420 - 20 = 400 - # per month (4,800 per year), supplied as in Case 1. + # 420 per month foreign pension; her own countable income is + # 420 - 20 = 400 per month (4,800 per year). The model's SSI couple + # computation would split the couple's income, so the case supplies + # her own income, as it does the citizen's values, to isolate the + # CAPI mixed-couple formula. pension_income: 5_040 ssi_countable_income: 4_800 marital_units: @@ -236,13 +231,6 @@ # 40 per month foreign pension; own countable income is 40 - 20 = 20 # per month. pension_income: 480 - # Supplied as SSI deeming would compute them at home. The spouse - # earns 1,200 per month, so (1,200 - 65) / 2 = 567.50 per month - # (6,810 per year) is deemed, and countable income is 20 + 567.50 = - # 587.50 per month (7,050 per year). - is_ssi_spousal_deeming_applies: true - ssi_income_deemed_from_ineligible_spouse: 6_810 - ssi_countable_income: 7_050 person2: age: 50 employment_income: 14_400 @@ -255,6 +243,12 @@ state_code: CA living_arrangements_allow_for_food_preparation: true output: + # SSI deeming computes these as if the couple lived together at home. The + # spouse earns 1,200 per month, so (1,200 - 65) / 2 = 567.50 per month is + # deemed, and countable income is 20 + 567.50 = 587.50 per month. + is_ssi_spousal_deeming_applies: [true, false] + ssi_income_deemed_from_ineligible_spouse: [567.50, 0] + ssi_countable_income: [587.50, 0] # Deeming needs an ineligible spouse living in the same household (20 # CFR 416.1160(a)(1)), so the resident is paid the Title XIX standard 62 # less own income 20 = 42. Deeming would give diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/eligibility/ca_capi_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/eligibility/ca_capi_income_eligible.yaml index f57268bfd93..1c32531ffba 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/eligibility/ca_capi_income_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/eligibility/ca_capi_income_eligible.yaml @@ -3,8 +3,8 @@ input: age: 70 immigration_status: UNDOCUMENTED - # SSI zeroes countable income for people who fail its immigration test, - # so the case supplies it: 1,234.94 per month (14,819.28 per year). + # The case supplies countable income directly to isolate the CAPI income + # test: 1,234.94 per month (14,819.28 per year). ssi_countable_income: 14_819.28 living_arrangements_allow_for_food_preparation: true state_code: CA @@ -34,13 +34,6 @@ person1: age: 70 immigration_status: UNDOCUMENTED - # SSI does not compute these for people who fail its immigration - # test, so the case supplies them. The spouse earns 5,000 per month; - # couple countable income is (5,000 - 20 - 65) / 2 = 2,457.50 per - # month (29,490 per year), all deemed. - is_ssi_spousal_deeming_applies: true - ssi_income_deemed_from_ineligible_spouse: 29_490 - ssi_countable_income: 29_490 person2: age: 50 employment_income: 60_000 @@ -53,6 +46,12 @@ state_code: CA living_arrangements_allow_for_food_preparation: true output: + # The spouse earns 5,000 per month; couple countable income is + # (5,000 - 20 - 65) / 2 = 2,457.50 per month (29,490 per year), all + # deemed. + is_ssi_spousal_deeming_applies: [true, false] + ssi_income_deemed_from_ineligible_spouse: [29_490, 0] + ssi_countable_income: [29_490, 0] # POMS SI 01320.430 D. As an individual: federal 994, state 239.94. # Under deeming: 2,457.50 exceeds the couple FBR 1,491 by 966.50, which # exceeds the couple OSS 607.83, so neither a federal benefit nor a 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 eac4ce30dd6..18063ca4609 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 @@ -409,3 +409,62 @@ # 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 + +# Under the model's SSI couple computation each aged spouse carries half of +# the couple's countable income. The model leaves the CAPI member's half out +# of the citizen's state supplement because CAPI budgets the couple's income +# (MPP 49-055.32), and the citizen's own half is already in his countable +# income. 2025: the couple federal benefit rate is $1,450; the no-cooking +# individual standard is $1,206.94 + $128.87 = $1,335.81. +# NOTE: SSA treats the undocumented spouse as an ineligible spouse (20 CFR +# 416.1160(d)). Her 500 exceeds the 1,450 - 967 = 483 gap, so SSA deems her +# income and pays SSI of min(967 - 480, 1,450 - 980) = 470 and a state +# supplement of min(1,335.81 - 967, 2,315.57 - 1,450) = 368.81, 838.81 in +# all (POMS SI 01320.430 D; 20 CFR 416.1163(e)(2)). The model's couple +# computation for a mixed-status couple pays 235 + 610.81 = 845.81, so CAPI +# is 489.76 instead of 496.76. This is a pre-existing ssi_claim_is_joint +# limitation: it counts aged, blind or disabled head/spouse status rather +# than SSI eligibility. The expected values below are the model's. +- name: Case 11, 2025 aged citizen married to a CAPI-eligible spouse, whose half of the couple's income is not counted. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 72 + is_tax_unit_head: true + immigration_status: CITIZEN + social_security_retirement: 6_000 # 500 a month + person2: + age: 68 + is_tax_unit_spouse: true + immigration_status: UNDOCUMENTED + pension_income: 6_000 # 500 a month foreign pension + 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: CA + output: + # SSI and the state supplement bar person2 for immigration status, so she + # is CAPI-eligible. + ca_capi_eligible_person: [false, true] + # Both spouses are aged, so the model applies the SSI couple computation: + # (500 + 500 - 20) / 2 = 490 a month each (5,880 a year). + ssi_countable_income: [5_880, 5_880] + # person1's SSI is 1,450 / 2 - 490 = 235 a month. + ssi: [2_820, 0] # 235 * 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 - 235 - 490 = 610.81 a month; person2's 490 + # is not counted. + ca_state_supplement: 7_329.72 # 610.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 a5d9e9b3abf..563dc032b89 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 @@ -261,3 +261,100 @@ # 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] + +# A person who reports SSI receipt keeps the imputed federal SSI even though +# the model's alien test bars her, for example someone SSA still pays under 8 +# U.S.C. 1612(a)(2)(E) because she was receiving SSI on August 22, 1996. PAA +# counts federally funded assistance payments (COMAR 07.03.07.07B(3)) and pays +# allowable needs less net countable income (COMAR 07.03.07.09A). 2025-01: +# federal SSI individual rate $967; provider rate $1,376; PNA $102. +- name: Case 12, aged LPR without 40 quarters who reports SSI receipt keeps the imputed SSI. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + immigration_status: LEGAL_PERMANENT_RESIDENT + years_since_us_entry: 30 # entered in 1995 + ssi_qualifying_quarters_earnings: 20 + receives_ssi: true + social_security_survivors: 6_000 # 500 a month + ssi_countable_resources: 1_000 + md_paa_living_arrangement: CARE_HOME_LEVEL_D + households: + household: + members: [person1] + state_code: MD + output: + md_paa_eligible: true + # The model's SSI fails her on the 40-quarter test, so it computes no SSI. + ssi: 0 + # 500 - 20 general exclusion = 480 a month (5,760 a year). + md_paa_countable_income: 480 + # Reported SSI receipt keeps the imputation: 967 - 480 = 487. + md_paa_imputed_federal_ssi: 487 + # combined_need = 1,376 + 102 = 1,478. + md_paa_total_cost_of_care: 1_478 + # PAA = 1,478 - 480 - 487 = 511. + md_paa: 511 + +# Case 11's household when person1 reports SSI receipt: PAA keeps the SSI +# treatment, so person2's wages are deemed to her and the imputed federal SSI +# uses the couple rate, the same cascade as for a citizen. 2025-01: federal +# SSI couple rate $1,450 and individual rate $967; provider rate $1,376; +# PNA $102. +# NOTE: SSI under deeming cannot exceed the amount computed on her own income +# alone, so SSA would pay min(967 - 480, 1,450 - 947.50) = 487 (20 CFR +# 416.1163(e)(2)), and COMAR 07.03.07.09A would give 1,478 - 480 - 487 = 511. +# The 28 below reflects the existing uncapped couple-rate imputation and +# spousal deeming, which also apply to citizens. +- name: Case 13, aged LPR without 40 quarters who reports SSI receipt and has 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: 30 # entered in 1995 + ssi_qualifying_quarters_earnings: 20 + receives_ssi: true + 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: + md_paa_eligible: [true, false] + # The model's SSI fails person1 on the 40-quarter test. + ssi: [0, 0] + # person2's 12,000 a year exceeds the (1,450 - 967) x 12 = 5,796 gap, so + # deeming applies: couple countable 480 + (1,000 - 65) x 0.5 = 947.50 + # less person1's own 480 = 467.50 a month. + ssi_income_deemed_from_ineligible_spouse: [467.50, 0] + # Reported SSI receipt keeps the deemed amount: 480 + 467.50 = 947.50. + # person2's own countable wages are (1,000 - 20 - 65) x 0.5 = 457.50. + md_paa_countable_income: [947.50, 457.50] + # Deeming applies, so person1's federal amount is the couple rate. + ssi_amount_if_eligible: [1_450, 967] + # 1,450 - 947.50 = 502.50. + md_paa_imputed_federal_ssi: [502.50, 0] + # combined_need = 1,376 + 102 = 1,478. + md_paa_total_cost_of_care: [1_478, 0] + # PAA = 1,478 - 947.50 - 502.50 = 28. + md_paa: [28, 0] 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 275e0e084a3..e9cda34fda1 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 @@ -11,16 +11,19 @@ class ca_state_supplement(Variable): reference = ( "https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?lawCode=WIC§ionNum=12200", "https://www.law.cornell.edu/cfr/text/20/416.1160", + "https://www.cdss.ca.gov/Portals/9/CAPI/CAPI_Regulations-Accessible.pdf#page=25", ) def formula(spm_unit, period, parameters): payment_standard = spm_unit("ca_state_supplement_payment_standard", period) ssi = add(spm_unit, period, ["ssi"]) 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. + # SSI/SSP counts another member's income only when it is deemed + # (20 CFR 416.1160(a)), and CAPI budgets its own members' income (CAPI + # regulations MPP 49-035). A spouse's income already reaches the SSI + # recipient's own countable income through the couple computation or + # deeming, so a CAPI-eligible member's countable income is not added + # again. capi_eligible = person("ca_capi_eligible_person", period.this_year) person_countable_income = person("ssi_countable_income", period) countable_income = spm_unit.sum( 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 7e63fa527a4..7a8f5f18697 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 @@ -48,13 +48,17 @@ def formula(person, period, parameters): # 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. + # test count their own income alone. A person who reports SSI receipt + # (for example one SSA pays under an exception the model does not + # encode such as 8 U.S.C. 1612(a)(2)(E)) keeps the SSI treatment, + # matching md_paa_imputed_federal_ssi. 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 + reports_ssi = add(person, period, ["receives_ssi"]) > 0 + not_barred_from_ssi = is_citizen | is_qualified_noncitizen | reports_ssi spousal_deemed = where( - meets_ssi_immigration_test, + not_barred_from_ssi, person("ssi_income_deemed_from_ineligible_spouse", period), 0, ) 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 b999e4f1c67..ec202c4fb81 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 @@ -21,10 +21,16 @@ def formula(person, period, parameters): # 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). + # (COMAR 07.03.07.09A). A person who reports SSI receipt, for example + # one SSA pays under an exception the model does not encode such as + # 8 U.S.C. 1612(a)(2)(E), keeps the imputed SSI. The repository's SSI + # receipt convention is (ssi > 0) | receives_ssi, and ssi > 0 already + # implies the citizen or qualified-noncitizen test. 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) + reports_ssi = person("receives_ssi", period) + not_barred_from_ssi = is_citizen | is_qualified_noncitizen | reports_ssi + return where(not_barred_from_ssi, imputed_ssi, 0) From a7def30d37de14b83b047112e0640766dc6ba67b Mon Sep 17 00:00:00 2001 From: Ziming Date: Mon, 26 Oct 2026 22:15:51 -0400 Subject: [PATCH 06/18] Keep Maryland PAA free of spouse deeming for SSI reporters barred by alien status COMAR 07.03.07.07 counts the individual's own income; only the imputed SSI keeps the receipt exception. Drop md_paa.yaml Case 13, which codified the deeming. Co-Authored-By: Claude Opus 5.5 --- ...d-abd-noncitizen-countable-income.fixed.md | 2 +- .../gov/states/md/dhs/fia/paa/md_paa.yaml | 60 ------------------- .../md/dhs/fia/paa/md_paa_countable_income.py | 11 ++-- 3 files changed, 5 insertions(+), 68 deletions(-) diff --git a/changelog.d/medicaid-abd-noncitizen-countable-income.fixed.md b/changelog.d/medicaid-abd-noncitizen-countable-income.fixed.md index cf078370c11..646ff7ccf9a 100644 --- a/changelog.d/medicaid-abd-noncitizen-countable-income.fixed.md +++ b/changelog.d/medicaid-abd-noncitizen-countable-income.fixed.md @@ -1 +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 unless they report SSI receipt. +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 deems spouse income to people SSI bars by alien status and imputes SSI to them only if they report SSI receipt. 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 563dc032b89..a93510da563 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 @@ -298,63 +298,3 @@ md_paa_total_cost_of_care: 1_478 # PAA = 1,478 - 480 - 487 = 511. md_paa: 511 - -# Case 11's household when person1 reports SSI receipt: PAA keeps the SSI -# treatment, so person2's wages are deemed to her and the imputed federal SSI -# uses the couple rate, the same cascade as for a citizen. 2025-01: federal -# SSI couple rate $1,450 and individual rate $967; provider rate $1,376; -# PNA $102. -# NOTE: SSI under deeming cannot exceed the amount computed on her own income -# alone, so SSA would pay min(967 - 480, 1,450 - 947.50) = 487 (20 CFR -# 416.1163(e)(2)), and COMAR 07.03.07.09A would give 1,478 - 480 - 487 = 511. -# The 28 below reflects the existing uncapped couple-rate imputation and -# spousal deeming, which also apply to citizens. -- name: Case 13, aged LPR without 40 quarters who reports SSI receipt and has 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: 30 # entered in 1995 - ssi_qualifying_quarters_earnings: 20 - receives_ssi: true - 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: - md_paa_eligible: [true, false] - # The model's SSI fails person1 on the 40-quarter test. - ssi: [0, 0] - # person2's 12,000 a year exceeds the (1,450 - 967) x 12 = 5,796 gap, so - # deeming applies: couple countable 480 + (1,000 - 65) x 0.5 = 947.50 - # less person1's own 480 = 467.50 a month. - ssi_income_deemed_from_ineligible_spouse: [467.50, 0] - # Reported SSI receipt keeps the deemed amount: 480 + 467.50 = 947.50. - # person2's own countable wages are (1,000 - 20 - 65) x 0.5 = 457.50. - md_paa_countable_income: [947.50, 457.50] - # Deeming applies, so person1's federal amount is the couple rate. - ssi_amount_if_eligible: [1_450, 967] - # 1,450 - 947.50 = 502.50. - md_paa_imputed_federal_ssi: [502.50, 0] - # combined_need = 1,376 + 102 = 1,478. - md_paa_total_cost_of_care: [1_478, 0] - # PAA = 1,478 - 947.50 - 502.50 = 28. - md_paa: [28, 0] 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 7a8f5f18697..37e2e23bcdf 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 @@ -48,17 +48,14 @@ def formula(person, period, parameters): # 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. A person who reports SSI receipt - # (for example one SSA pays under an exception the model does not - # encode such as 8 U.S.C. 1612(a)(2)(E)) keeps the SSI treatment, - # matching md_paa_imputed_federal_ssi. + # test count their own income alone, including those who report SSI + # receipt: PAA itself has no spousal deeming. immigration_status = person("immigration_status", period) is_citizen = immigration_status == immigration_status.possible_values.CITIZEN is_qualified_noncitizen = person("is_ssi_qualified_noncitizen", period) - reports_ssi = add(person, period, ["receives_ssi"]) > 0 - not_barred_from_ssi = is_citizen | is_qualified_noncitizen | reports_ssi + meets_ssi_immigration_test = is_citizen | is_qualified_noncitizen spousal_deemed = where( - not_barred_from_ssi, + meets_ssi_immigration_test, person("ssi_income_deemed_from_ineligible_spouse", period), 0, ) From 31fb952c291dce8c18f0317c43aa34060d79b0f4 Mon Sep 17 00:00:00 2001 From: Ziming Date: Mon, 26 Oct 2026 22:52:04 -0400 Subject: [PATCH 07/18] Follow WIC 12200(e) for the blind-couple food allowance; mark the pre-2025 floor a stopgap; LPR test personas - One-blind couple rate adds no food allowance (WIC 12200(b), (e)); candidates item us-ca:ssp-blind-couple-food-allowance (unreviewed) - Floor comment and pinned pre-2025 cases say the values are known-low; issue 10480 backfills the totals - Mixed-couple note gives the ineligible-spouse example (issue 10481) - CAPI test personas are aged permanent residents with 39 quarters (issue 10482) - PDF page comments without spaces Co-Authored-By: Claude Opus 5.5 --- .../gov/states/ca/cdss/capi/ca_capi.yaml | 30 ++++--- .../cdss/capi/ca_capi_payment_standard.yaml | 85 ++++++++++++------- .../states/ca/cdss/capi/ca_capi_person.yaml | 24 ++++-- .../eligibility/ca_capi_eligible_person.yaml | 8 +- .../eligibility/ca_capi_income_eligible.yaml | 9 +- .../ca/cdss/capi/_ca_capi_ssi_ssp_standard.py | 27 +++--- .../ca/cdss/capi/ca_capi_payment_standard.py | 2 +- .../gov/states/ca/cdss/capi/ca_capi_person.py | 14 +-- .../eligibility/ca_capi_eligible_person.py | 2 +- source_conflicts/candidates.yaml | 35 ++++++++ 10 files changed, 165 insertions(+), 71 deletions(-) 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 7ddbe20a697..f95d3d4c450 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 @@ -5,7 +5,8 @@ people: person1: age: 70 - immigration_status: UNDOCUMENTED + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 # 520 per month foreign pension. pension_income: 6_240 # SSI zeroes countable income for people who fail its immigration @@ -30,10 +31,12 @@ people: person1: age: 72 - immigration_status: UNDOCUMENTED + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 person2: age: 68 - immigration_status: UNDOCUMENTED + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 marital_units: marital_unit: members: [person1, person2] @@ -88,7 +91,7 @@ ca_state_supplement: 0 ca_capi: 0 -- name: Integration test, undocumented +- name: Integration test, permanent resident without 40 SSI quarters period: 2026 absolute_error_margin: 0.01 input: @@ -98,7 +101,8 @@ employment_income: 1_000 is_disabled: true meets_ssi_disability_criteria: true - immigration_status: UNDOCUMENTED + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 person2: age: 10 employment_income: 0 @@ -130,7 +134,8 @@ immigration_status: CITIZEN person2: age: 68 - immigration_status: UNDOCUMENTED + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 marital_units: marital_unit: members: [person1, person2] @@ -156,7 +161,8 @@ people: person1: age: 72 - immigration_status: UNDOCUMENTED + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 # 1,520 per month foreign pension. pension_income: 18_240 # SSI zeroes countable income for people who fail its immigration @@ -165,7 +171,8 @@ ssi_countable_income: 18_000 person2: age: 68 - immigration_status: UNDOCUMENTED + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 tax_units: tax_unit1: members: [person1] @@ -199,7 +206,8 @@ people: person1: age: 70 - immigration_status: UNDOCUMENTED + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 households: household: members: [person1] @@ -209,6 +217,8 @@ # The state supplement parameters hold the 1991 aged amount of 630 until # 2025 (issue 7787). CAPI equals SSI/SSP (WIC 18941), so the standard is # floored at the 2024 federal benefit rate: max(630, 943) = 943 per - # month with no offset and no income; 943 x 12 = 11,316. + # month with no offset and no income; 943 x 12 = 11,316. This pins a + # known-low value from the stopgap floor: the published aged standard was + # 1,182.94 (POMS SI 01415.056); issue 10480 removes the floor. ca_capi_person: 11_316 ca_capi: 11_316 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi_payment_standard.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi_payment_standard.yaml index 14389061408..17de1047ca5 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi_payment_standard.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi_payment_standard.yaml @@ -5,7 +5,8 @@ people: person1: age: 70 - immigration_status: UNDOCUMENTED + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 households: household: members: [person1] @@ -24,7 +25,8 @@ people: person1: age: 70 - immigration_status: UNDOCUMENTED + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 households: household: members: [person1] @@ -44,7 +46,8 @@ person1: age: 40 is_blind: true - immigration_status: UNDOCUMENTED + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 households: household: members: [person1] @@ -63,10 +66,12 @@ people: person1: age: 72 - immigration_status: UNDOCUMENTED + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 person2: age: 68 - immigration_status: UNDOCUMENTED + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 marital_units: marital_unit: members: [person1, person2] @@ -88,10 +93,12 @@ people: person1: age: 72 - immigration_status: UNDOCUMENTED + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 person2: age: 68 - immigration_status: UNDOCUMENTED + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 marital_units: marital_unit: members: [person1, person2] @@ -112,11 +119,13 @@ people: person1: age: 70 - immigration_status: UNDOCUMENTED + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 person2: age: 60 is_blind: true - immigration_status: UNDOCUMENTED + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 marital_units: marital_unit: members: [person1, person2] @@ -141,7 +150,8 @@ immigration_status: CITIZEN person2: age: 68 - immigration_status: UNDOCUMENTED + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 marital_units: marital_unit: members: [person1, person2] @@ -164,7 +174,8 @@ people: person1: age: 75 - immigration_status: UNDOCUMENTED + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 ca_in_medical_care_facility: true households: household: @@ -185,7 +196,8 @@ people: person1: age: 75 - immigration_status: UNDOCUMENTED + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 in_out_of_home_care_facility: true households: household: @@ -206,7 +218,8 @@ person1: age: 70 is_blind: true - immigration_status: UNDOCUMENTED + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 households: household: members: [person1] @@ -225,12 +238,14 @@ people: person1: age: 40 - immigration_status: UNDOCUMENTED + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 person2: age: 10 is_disabled: true meets_ssi_disability_criteria: true - immigration_status: UNDOCUMENTED + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 marital_units: marital_unit1: members: [person1] @@ -253,11 +268,13 @@ people: person1: age: 40 - immigration_status: UNDOCUMENTED + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 person2: age: 10 is_blind: true - immigration_status: UNDOCUMENTED + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 marital_units: marital_unit1: members: [person1] @@ -272,18 +289,20 @@ # A blind child takes the blind amount, 1,318.32 (MPP 49-050.253). ca_capi_payment_standard: [0, 1_318.32] -- name: Case 13, aged couple with one blind member without cooking adds the individual food allowance. +- name: Case 13, aged couple with one blind member without cooking takes the aged couple rate with the food allowance. period: 2026-01 absolute_error_margin: 0.01 input: people: person1: age: 72 - immigration_status: UNDOCUMENTED + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 person2: age: 70 is_blind: true - immigration_status: UNDOCUMENTED + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 marital_units: marital_unit: members: [person1, person2] @@ -293,11 +312,13 @@ state_code: CA living_arrangements_allow_for_food_preparation: false output: - # POMS SI 01415.058 code C note: the blind/aged couple level plus the - # individual restaurant allowance, 2,238.44 + 128.87 = 2,367.31. This - # beats the aged couple without cooking, 2,098.83 + 257.74 = 2,356.57. - # One-half each: 2,367.31 / 2 = 1,183.655. - ca_capi_payment_standard: [1_183.655, 1_183.655] + # WIC 12200(e) gives the food allowance only to an aged or disabled + # individual or couple (12200(c), (d)), so the one-blind couple rate + # (12200(b)) adds none: 2,238.44. Both spouses are aged, so the aged + # couple rate without cooking also applies: 2,098.83 + 257.74 = 2,356.57, + # the higher. One-half each: 2,356.57 / 2 = 1,178.285. POMS SI 01415.058 + # code C would add 128.87 to the one-blind rate instead (2,367.31). + ca_capi_payment_standard: [1_178.285, 1_178.285] - name: Case 14, 2024 independent-living standard is floored at the federal benefit rate. period: 2024-01 @@ -306,7 +327,8 @@ people: person1: age: 70 - immigration_status: UNDOCUMENTED + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 households: household: members: [person1] @@ -315,7 +337,10 @@ output: # The state supplement parameters hold the 1991 aged amount of 630 until # 2025 (issue 7787), below the 2024 federal benefit rate of 943. CAPI - # equals SSI/SSP (WIC 18941), so the standard is max(630, 943) = 943. + # equals SSI/SSP (WIC 18941), so the stopgap floor gives max(630, 943) = + # 943. This pins a known-low value: the published January 2024 aged + # standard is 943 + 239.94 = 1,182.94 (POMS SI 01415.056); issue 10480 + # backfills the totals and removes the floor. ca_capi_payment_standard: 943 - name: Case 15, the 10 individual offset applies through May 2019 and ends in June 2019. @@ -325,7 +350,8 @@ people: person1: age: 70 - immigration_status: UNDOCUMENTED + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 households: household: members: [person1] @@ -335,7 +361,8 @@ # The state supplement parameters hold the 1991 aged amount of 630 until # 2025 (issue 7787), so the model floors the standard at the 2019 federal # benefit rate: max(630, 771) = 771. The actual 2019 SSI/SSP standard was - # 931.72 (ACIN I-23-19). This case pins only the offset boundary: + # 931.72 (ACIN I-23-19), so these are known-low values from the stopgap + # floor (issue 10480). This case pins only the offset boundary: # 771 - 10 = 761 through May 2019 (MPP 49-050.11) and 771 - 0 = 771 from # June 1, 2019 (WIC 18941). ca_capi_payment_standard: diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi_person.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi_person.yaml index 00789c189c0..07d06ea9b8e 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi_person.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi_person.yaml @@ -5,7 +5,8 @@ people: person1: age: 72 - immigration_status: UNDOCUMENTED + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 # 420 per month foreign pension. pension_income: 5_040 # SSI zeroes countable income for people who fail its immigration @@ -15,7 +16,8 @@ ssi_countable_income: 2_400 person2: age: 68 - immigration_status: UNDOCUMENTED + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 ssi_countable_income: 2_400 marital_units: marital_unit: @@ -38,7 +40,8 @@ people: person1: age: 70 - immigration_status: UNDOCUMENTED + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 # SSI does not compute these for people who fail its immigration # test, so the case supplies them. The spouse earns 500 per month, # above the 497 gap between the couple and individual FBRs @@ -76,7 +79,8 @@ people: person1: age: 70 - immigration_status: UNDOCUMENTED + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 # Supplied for the reason in Case 2. The spouse earns 3,867 per # month; couple countable income is (3,867 - 85) / 2 = 1,891 per # month (22,692 per year), all deemed. @@ -111,7 +115,8 @@ person1: age: 45 is_blind: true - immigration_status: UNDOCUMENTED + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 # Supplied for the reason in Case 2. The spouse earns 4,267 per # month; couple countable income is (4,267 - 85) / 2 = 2,091 per # month (25,092 per year), all deemed. @@ -148,7 +153,8 @@ people: person1: age: 70 - immigration_status: UNDOCUMENTED + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 # 320 per month foreign pension; own countable income is 320 - 20 = # 300 per month. pension_income: 3_840 @@ -198,7 +204,8 @@ ssi_countable_income: 0 person2: age: 68 - immigration_status: UNDOCUMENTED + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 # 420 per month foreign pension; countable income is 420 - 20 = 400 # per month (4,800 per year), supplied as in Case 1. pension_income: 5_040 @@ -231,7 +238,8 @@ people: person1: age: 75 - immigration_status: UNDOCUMENTED + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 ca_in_medical_care_facility: true # 40 per month foreign pension; own countable income is 40 - 20 = 20 # per month. diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/eligibility/ca_capi_eligible_person.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/eligibility/ca_capi_eligible_person.yaml index 287beb1cab9..cfde31c565e 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/eligibility/ca_capi_eligible_person.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/eligibility/ca_capi_eligible_person.yaml @@ -26,16 +26,18 @@ output: ca_capi_eligible_person: true -- name: Eligible couple - both spouses aged and undocumented +- name: Eligible couple - both spouses aged permanent residents without 40 SSI quarters period: 2026 input: people: person1: age: 72 - immigration_status: UNDOCUMENTED + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 person2: age: 68 - immigration_status: UNDOCUMENTED + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 marital_units: marital_unit: members: [person1, person2] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/eligibility/ca_capi_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/eligibility/ca_capi_income_eligible.yaml index f57268bfd93..909d90394e9 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/eligibility/ca_capi_income_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/eligibility/ca_capi_income_eligible.yaml @@ -2,7 +2,8 @@ period: 2026 input: age: 70 - immigration_status: UNDOCUMENTED + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 # SSI zeroes countable income for people who fail its immigration test, # so the case supplies it: 1,234.94 per month (14,819.28 per year). ssi_countable_income: 14_819.28 @@ -18,7 +19,8 @@ period: 2026 input: age: 70 - immigration_status: UNDOCUMENTED + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 # Supplied as above: 1,232.94 per month (14,795.28 per year). ssi_countable_income: 14_795.28 living_arrangements_allow_for_food_preparation: true @@ -33,7 +35,8 @@ people: person1: age: 70 - immigration_status: UNDOCUMENTED + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 # SSI does not compute these for people who fail its immigration # test, so the case supplies them. The spouse earns 5,000 per month; # couple countable income is (5,000 - 20 - 65) / 2 = 2,457.50 per diff --git a/policyengine_us/variables/gov/states/ca/cdss/capi/_ca_capi_ssi_ssp_standard.py b/policyengine_us/variables/gov/states/ca/cdss/capi/_ca_capi_ssi_ssp_standard.py index 0be284f8a9f..33ea748fdf3 100644 --- a/policyengine_us/variables/gov/states/ca/cdss/capi/_ca_capi_ssi_ssp_standard.py +++ b/policyengine_us/variables/gov/states/ca/cdss/capi/_ca_capi_ssi_ssp_standard.py @@ -15,9 +15,11 @@ def ca_capi_ssi_ssp_standard(person, period, parameters): disabled amount (the disabled child amount for a dependent child, MPP 49-050.25; blind children take the blind amount, MPP 49-050.253). Only the aged or disabled amount adds the food allowance for people who - cannot prepare meals (WIC 12200(e)); a couple with one blind member - adds the individual food allowance for the other member (POMS SI - 01415.058 B.1 code C). California pays the highest category a person or + cannot prepare meals, for an individual under WIC 12200(c) or a couple + under 12200(d) (WIC 12200(e)), so the one-blind couple rate under + 12200(b) adds none. POMS SI 01415.058 B.1 code C adds the individual + allowance for the aged or disabled member of such a couple; the code + follows the statute. California pays the highest category a person or couple qualifies for. In an SSI couple computation the couple standard sums both members' shares; otherwise it treats the ineligible spouse as the person's @@ -36,9 +38,14 @@ def ca_capi_ssi_ssp_standard(person, period, parameters): aged_or_disabled = (age >= p.aged_or_disabled.age_threshold) | person( "is_ssi_disabled", period.this_year ) + # NOTE: living_arrangements_allow_for_food_preparation has no default + # value, so unless it is set every aged or disabled person gets the + # no-cooking allowance. no_cooking = ~person.household( "living_arrangements_allow_for_food_preparation", period.this_year ) + # NOTE: the Title XIX standard reads ca_in_medical_care_facility, while + # SSI reads ssi_federal_living_arrangement; the two inputs can disagree. medical_facility = person("ca_in_medical_care_facility", period.this_year) out_of_home_care = person("in_out_of_home_care_facility", period.this_year) out_of_home_care_share = ( @@ -61,9 +68,7 @@ def ca_capi_ssi_ssp_standard(person, period, parameters): joint, person.marital_unit.sum(aged_or_disabled), 2 * aged_or_disabled ) two_blind = (blind_count > 1) * p.blind.married.two_blind - one_blind = (blind_count == 1) * ( - p.blind.married.one_blind + no_cooking * p.allowance.food.single - ) + one_blind = (blind_count == 1) * p.blind.married.one_blind aged_or_disabled_couple = select( [aged_or_disabled_count > 1, aged_or_disabled_count == 1], [ @@ -74,10 +79,12 @@ def ca_capi_ssi_ssp_standard(person, period, parameters): ) community_couple = max_(max_(two_blind, one_blind), aged_or_disabled_couple) - # The state supplement amounts hold 1991 totals until 2025 (issue 7787), - # below the federal benefit rate from 2008. CAPI equals SSI/SSP (WIC - # 18941), and SSI alone pays at least the federal rate, so the - # independent-living and out-of-home care standards are floored at it. + # Stopgap: the state supplement amounts hold 1991 totals until 2025, + # below the federal benefit rate from 2008, so the independent-living and + # out-of-home care standards are floored at that rate (SSI alone pays at + # least it, and CAPI equals SSI/SSP under WIC 18941). This still leaves + # out the whole state supplement before 2025; issue 10480 backfills the + # totals and removes the floor. individual = select( [medical_facility, out_of_home_care], [ diff --git a/policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_payment_standard.py b/policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_payment_standard.py index 78318db3cbb..7ec5a717150 100644 --- a/policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_payment_standard.py +++ b/policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_payment_standard.py @@ -12,7 +12,7 @@ class ca_capi_payment_standard(Variable): definition_period = MONTH defined_for = "ca_capi_eligible_person" reference = ( - # PDF pages 3, 44-47 + # PDF pages 3,44-47 "https://www.cdss.ca.gov/Portals/9/CAPI/CAPI_Regulations-Accessible.pdf#page=3", "https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?lawCode=WIC§ionNum=12200", "https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?lawCode=WIC§ionNum=18941", diff --git a/policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_person.py b/policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_person.py index 780c4c50c6d..e2fc0094e39 100644 --- a/policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_person.py +++ b/policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_person.py @@ -12,7 +12,7 @@ class ca_capi_person(Variable): definition_period = MONTH defined_for = "ca_capi_eligible_person" reference = ( - # PDF pages 3-4, 25, 30, 47 + # PDF pages 3-4,25,30,47 "https://www.cdss.ca.gov/Portals/9/CAPI/CAPI_Regulations-Accessible.pdf#page=3", "https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?lawCode=WIC§ionNum=18940", "https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?lawCode=WIC§ionNum=18941", @@ -38,11 +38,13 @@ def formula(person, period, parameters): # Mixed couple: the spouse's SSI/SSP counts as unearned income based on # need (MPP 49-035.221), subtracted with the couple's countable income # from the couple standard (MPP 49-055.32). - # NOTE: an aged, blind or disabled spouse who receives neither SSI/SSP - # nor CAPI is an ineligible spouse (MPP 49-005(i)(2)), but the model has - # no spouse-to-spouse deeming for such a spouse, so this computation - # applies. That spouse's SSI/SSP is zero mainly when the couple's income - # exceeds the couple standard, which already leaves no CAPI. + # NOTE: the model applies this computation whenever both spouses are + # aged, blind or disabled (ssi_couple_computation_applies ignores SSI's + # noncitizen test), even when SSA would pay the spouse nothing. Such a + # spouse is an ineligible spouse (MPP 49-005(i)(2); 20 CFR 416.1160(d)) + # and deeming applies. Example, January 2026: a citizen with $1,300 of + # Social Security and a CAPI spouse with no income get $818.83 a month + # in the model; the law gives $450.94 of CAPI alone (issue 10481). capi_eligible = person("ca_capi_eligible_person", period.this_year) joint = person("ssi_couple_computation_applies", period) mixed = joint & ~(person.marital_unit.sum(capi_eligible) > 1) diff --git a/policyengine_us/variables/gov/states/ca/cdss/capi/eligibility/ca_capi_eligible_person.py b/policyengine_us/variables/gov/states/ca/cdss/capi/eligibility/ca_capi_eligible_person.py index ea946c5b4ea..7cb73540e17 100644 --- a/policyengine_us/variables/gov/states/ca/cdss/capi/eligibility/ca_capi_eligible_person.py +++ b/policyengine_us/variables/gov/states/ca/cdss/capi/eligibility/ca_capi_eligible_person.py @@ -7,7 +7,7 @@ class ca_capi_eligible_person(Variable): label = "California CAPI eligible person" definition_period = YEAR defined_for = StateCode.CA - # PDF pages 10, 47 + # PDF pages 10,47 reference = ( "https://www.cdss.ca.gov/Portals/9/CAPI/CAPI_Regulations-Accessible.pdf#page=10" ) diff --git a/source_conflicts/candidates.yaml b/source_conflicts/candidates.yaml index 578a4062247..358057a2e75 100644 --- a/source_conflicts/candidates.yaml +++ b/source_conflicts/candidates.yaml @@ -1114,6 +1114,41 @@ candidates: state: unreviewed note: 'The rule requires statutory timing rather than the model''s 2025-11-01 proxy; verify commencement and authorized transitions before changing it. Code not yet on main: is_snap_sua_hr1_in_effect, snap_utility_allowance_type.' +- id: us-ca:ssp-blind-couple-food-allowance + program: ssi-ssp + years: + from: 2025 + type: calendar + question: Does a California couple paid the one-blind couple rate get the no-cooking food allowance for its aged + or disabled member? + sources: + - kind: statute + citation: Cal. WIC ยง12200(b), (e) + url: https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?lawCode=WIC§ionNum=12200 + - kind: manual + citation: SSA POMS SI 01415.058 B.1, code C note + url: https://secure.ssa.gov/apps10/poms.nsf/lnx/0501415058 + - kind: guidance + citation: CDSS ACIN I-59-25, Attachment A + url: https://cdss.ca.gov/Portals/9/Additional-Resources/Letters-and-Notices/ACINs/2025/I-59_25.pdf#page=5 + readings: + statute: The allowance goes only to an aged or disabled individual (12200(c)) or a couple both aged or disabled + (12200(d)), so a couple under the one-blind rate (12200(b)) gets none. + other: POMS adds the individual restaurant meals allowance for the aged or disabled member of a couple with one + blind member whose living arrangement lacks cooking facilities. + example: In January 2026, a couple of an aged person and a blind person aged 50 without cooking facilities has a + $2,238.44 standard under the statute, which PE-US follows for CAPI, and $2,367.31 under POMS. + pe_us: + follows: statute + code: + - policyengine_us/variables/gov/states/ca/cdss/capi/_ca_capi_ssi_ssp_standard.py + prs: + - https://github.com/PolicyEngine/policyengine-us/pull/10379 + state: unreviewed + note: 'PE-US follows the statute for CAPI: _ca_capi_ssi_ssp_standard.py adds no food allowance to the one-blind + couple rate, and a couple both aged or disabled takes the aged or disabled rate with the couple allowance when + that is higher. The ACIN I-59-25 table lists no such combination. Check how ca_state_supplement_food_allowance + treats these couples.' - id: us-ca:ssp-nmohc-couple-standard program: ssi-ssp years: From a13747ee8cd5a4c83f0c6404c3fd82f6b9927506 Mon Sep 17 00:00:00 2001 From: Ziming Date: Tue, 27 Oct 2026 15:17:50 -0400 Subject: [PATCH 08/18] Record the ruling on us-ca:capi-payment-standard-offset: statute Co-Authored-By: Claude Opus 5.5 --- source_conflicts/candidates.yaml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/source_conflicts/candidates.yaml b/source_conflicts/candidates.yaml index 358057a2e75..c332ecb1775 100644 --- a/source_conflicts/candidates.yaml +++ b/source_conflicts/candidates.yaml @@ -660,11 +660,13 @@ candidates: - policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_payment_standard.py prs: - https://github.com/PolicyEngine/policyengine-us/pull/10379 - state: open - note: 'Pavel''s sign-off requested (statute against regulation). PE-US follows the statute: the three offsets are - $0 from 2019-06-01 and keep the regulation amounts before then (payment_standard_offset/*.yaml, read by - ca_capi_payment_standard.py). The 2003 regulation predates the 2019 statute; CDSS applies the statute in ACIN - I-23-19 (June 1, 2019 increase of $10 per individual and $20 per couple) and ACIN I-59-25.' + state: ruled + note: 'Ruled 2026-10-27 for the statute by the project lead for the Medicaid fixes; the ruling record is + https://github.com/PolicyEngine/policyengine-us/pull/10379#issuecomment-6451310006. WIC 18941 (2019) makes CAPI + benefits "equivalent to the benefits provided under the SSI/SSP program" from June 1, 2019, so it governs over + MPP 49-050.11-.13 (2003); CDSS notices ACIN I-23-19 and I-59-25 agree. PE-US follows the statute: the three + offsets are $0 from 2019-06-01 and keep the regulation amounts before then (payment_standard_offset/*.yaml, read + by ca_capi_payment_standard.py).' - id: us-ca:capi-spousal-deeming-method program: capi years: From 2b9d5f7c3d77e705247026c02684ca89a5e3e565 Mon Sep 17 00:00:00 2001 From: Ziming Date: Thu, 29 Oct 2026 13:44:35 -0400 Subject: [PATCH 09/18] Apply Pavel's review: mixed couple only with a paid spouse, child SSP gate, offset and floor cases - C1: the mixed-couple computation needs a spouse paid SSI/SSP (MPP 49-005(e)(3), 49-050.13); otherwise the spouse is an ineligible spouse and CAPI deems the couple's income (49-005(i)(2)); the payment standard follows the same gate; ca_capi_person Cases 8-9 - SA1: no-cooking default NOTE with amounts and issue 10296 - SA2: the state supplement's dependent amount needs the child to meet SSI's immigration and resource conditions; three cases - SA3/SA4: couple, mixed-couple, floor and 2019 deeming offset cases; mixed couple with the citizen's income - G1/G5: candidates entries list both programs; WIC 12200(g) cited - G3/G4/G7/G9: notes, Title XIX reads both inputs, shorter docstring, Case N names Co-Authored-By: Claude Opus 5.5 --- .../gov/states/ca/cdss/capi/ca_capi.yaml | 21 +- .../cdss/capi/ca_capi_payment_standard.yaml | 104 ++++++++++ .../states/ca/cdss/capi/ca_capi_person.yaml | 189 ++++++++++++++++++ .../eligibility/ca_capi_eligible_person.yaml | 8 +- .../eligibility/ca_capi_income_eligible.yaml | 6 +- .../ca_state_supplement_dependent_amount.yaml | 52 +++++ .../ca/cdss/capi/_ca_capi_ssi_ssp_standard.py | 75 ++++--- .../ca/cdss/capi/ca_capi_payment_standard.py | 7 +- .../gov/states/ca/cdss/capi/ca_capi_person.py | 63 +++--- .../ca_state_supplement_dependent_amount.py | 12 +- source_conflicts/candidates.yaml | 16 +- 11 files changed, 468 insertions(+), 85 deletions(-) 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 f95d3d4c450..3d9df8abdac 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 @@ -1,4 +1,4 @@ -- name: Single eligible person +- name: Case 1, single eligible person. period: 2026 absolute_error_margin: 0.01 input: @@ -24,7 +24,7 @@ # 733.94 x 12 = 8,807.28. ca_capi: 8_807.28 -- name: Couple, both people eligible +- name: Case 2, couple, both people eligible. period: 2026 absolute_error_margin: 0.01 input: @@ -52,7 +52,7 @@ ca_capi_person: [12_592.98, 12_592.98] ca_capi: 25_185.96 -- name: Integration test, ineligible +- name: Case 3, integration test, ineligible. period: 2024 input: people: @@ -69,7 +69,7 @@ output: ca_capi: 0 -- name: Integration test, SSI eligible +- name: Case 4, integration test, SSI eligible. period: 2024 input: people: @@ -91,7 +91,7 @@ ca_state_supplement: 0 ca_capi: 0 -- name: Integration test, permanent resident without 40 SSI quarters +- name: Case 5, integration test, permanent resident without 40 SSI quarters. period: 2026 absolute_error_margin: 0.01 input: @@ -120,11 +120,12 @@ # Disabled individual standard 1,233.94 + no-cooking food allowance # 128.87 (living arrangements default to no food preparation) = # 1,362.81 per month with no offset. Earnings of 83.33 per month fall - # within the $20 + $65 exclusions, so countable income is 0. - # 1,362.81 x 12 = 16,353.72. + # within the $20 + $65 exclusions, so countable income is 0 (until PR + # 10240, SSI also zeroes this income for people who fail its noncitizen + # test). 1,362.81 x 12 = 16,353.72. ca_capi: 16_353.72 -- name: Mixed couple, only the noncitizen spouse receives CAPI +- name: Case 6, mixed couple, only the noncitizen spouse receives CAPI. period: 2026 absolute_error_margin: 0.01 input: @@ -154,7 +155,7 @@ ca_capi_person: [0, 10_378.68] ca_capi: 10_378.68 -- name: Two unrelated eligible people in one unit, income is not pooled +- name: Case 7, two unrelated eligible people in one unit, income is not pooled. period: 2026 absolute_error_margin: 0.01 input: @@ -199,7 +200,7 @@ ca_capi_person: [0, 14_807.28] ca_capi: 14_807.28 -- name: Aged person in 2024, the independent-living standard is floored at the federal benefit rate +- name: Case 8, aged person in 2024, the independent-living standard is floored at the federal benefit rate. period: 2024 absolute_error_margin: 0.01 input: diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi_payment_standard.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi_payment_standard.yaml index 17de1047ca5..dbbec260c3f 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi_payment_standard.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi_payment_standard.yaml @@ -368,3 +368,107 @@ ca_capi_payment_standard: 2019-05: 761 2019-06: 771 + +- name: Case 16, CAPI couple, the 20 couple offset applies through May 2019 and ends in June 2019. + period: 2019 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 72 + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 + person2: + age: 68 + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 + marital_units: + marital_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: CA + living_arrangements_allow_for_food_preparation: true + output: + # Couple standard max(1,167, 2019 couple FBR 1,157) = 1,167 (known-low, + # issue 10480). May: (1,167 - 20) / 2 = 573.50 each (MPP 49-050.12). + # June: 1,167 / 2 = 583.50 each (WIC 18941). + ca_capi_payment_standard: + 2019-05: [573.5, 573.5] + 2019-06: [583.5, 583.5] + +- name: Case 17, mixed couple, the 10 mixed-couple offset applies through May 2019 and ends in June 2019. + period: 2019 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 72 + immigration_status: CITIZEN + person2: + age: 68 + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 + marital_units: + marital_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: CA + living_arrangements_allow_for_food_preparation: true + output: + # The citizen is paid SSI, so the CAPI member takes the couple standard + # 1,167 (known-low, issue 10480). May: 1,167 - 10 = 1,157 (MPP + # 49-050.13). June: 1,167 (WIC 18941). + ca_capi_payment_standard: + 2019-05: [0, 1_157] + 2019-06: [0, 1_167] + +- name: Case 18, 2024 CAPI couple standard is floored at the couple federal benefit rate. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 72 + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 + person2: + age: 68 + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 + marital_units: + marital_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: CA + living_arrangements_allow_for_food_preparation: true + output: + # Stopgap floor: max(1,167, 2024 couple FBR 1,415) / 2 = 707.50 each. A + # known-low value: the published 2024 couple standard is higher (issue + # 10480). + ca_capi_payment_standard: [707.5, 707.5] + +- name: Case 19, 2024 out-of-home care standard is floored at the federal benefit rate. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 + in_out_of_home_care_facility: true + households: + household: + members: [person1] + state_code: CA + living_arrangements_allow_for_food_preparation: true + output: + # Stopgap floor: (1,167 + 709) / 2 = 938, floored at the 943 FBR. A + # known-low value: POMS SI 01415.056 gives 1,575.07 (issue 10480). + ca_capi_payment_standard: 943 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi_person.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi_person.yaml index 07d06ea9b8e..58616267e6d 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi_person.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi_person.yaml @@ -270,3 +270,192 @@ # the deemed income would give max(62 - 587.50, 0) = 0. ca_capi_payment_standard: [62, 0] ca_capi_person: [42, 0] + +- name: Case 8, aged citizen spouse with income too high for SSI/SSP is an ineligible spouse, so CAPI deems the spouse's income. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 72 + immigration_status: CITIZEN + # 1,600 a month; countable 1,580 after the $20 exclusion. + social_security: 19_200 + person2: + age: 68 + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 + marital_units: + marital_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: CA + living_arrangements_allow_for_food_preparation: true + output: + # The spouse is paid no SSI/SSP, so is an ineligible spouse (MPP + # 49-005(i)(2)). POMS SI 01320.430 D: federal min(994, 1,491 - 1,580) -> 0; + # state min(239.94, 607.83 - (1,580 - 1,491)) = 239.94. + ssi: [0, 0] + ca_state_supplement: 0 + # The CAPI member is an eligible individual, so the individual standard. + ca_capi_payment_standard: [0, 1_233.94] + ca_capi_person: [0, 239.94] + +- name: Case 9, spouse income above the couple state supplement leaves the couple state part. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 72 + immigration_status: CITIZEN + # 2,000 a month; countable 1,980 after the $20 exclusion. + social_security: 24_000 + person2: + age: 68 + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 + marital_units: + marital_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: CA + living_arrangements_allow_for_food_preparation: true + output: + # POMS SI 01320.430 D: federal 0; state min(239.94, 607.83 - (1,980 - + # 1,491)) = min(239.94, 118.83) = 118.83. + ca_capi_person: [0, 118.83] + +- name: Case 10, deeming keeps the 10 individual offset through May 2019. + period: 2019 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 + # Supplied as in Case 2. The spouse earns 500 per month; couple + # countable income (500 - 20 - 65) / 2 = 207.50 per month, all deemed. + is_ssi_spousal_deeming_applies: true + ssi_income_deemed_from_ineligible_spouse: 2_490 + ssi_countable_income: 2_490 + person2: + age: 50 + employment_income: 6_000 + marital_units: + marital_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: CA + living_arrangements_allow_for_food_preparation: true + output: + # Standards max(630, 771) = 771 and max(1,167, 1,157) = 1,167 (known-low, + # issue 10480). Federal min(771, 1,157 - 207.50) = 771; state 0. + # May: 771 - 10 = 761 (MPP 49-050.11); June: 771 (WIC 18941). + ca_capi_person: + 2019-05: [761, 0] + 2019-06: [771, 0] + +- name: Case 11, mixed couple where the SSI/SSP spouse has the income subtracts the couple's income. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 72 + immigration_status: CITIZEN + # 420 per month pension; countable 400 per month (4,800 per year). + # Supplied as SSA would pay: SSI 994 - 400 = 594 and the state + # supplement 239.94. + pension_income: 5_040 + ssi: 594 + ssi_countable_income: 4_800 + person2: + age: 68 + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 + ssi_countable_income: 0 + marital_units: + marital_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + ca_state_supplement: 239.94 + households: + household: + members: [person1, person2] + state_code: CA + living_arrangements_allow_for_food_preparation: true + output: + # The couple's countable income counts, whichever spouse has it (MPP + # 49-055.32): 2,098.83 - 400 - 594 - 239.94 = 864.89. + ca_capi_person: [0, 864.89] + +- name: Case 12, mixed couple with a disabled noncitizen child, the child's standard does not reduce the CAPI spouse. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 72 + immigration_status: CITIZEN + person2: + age: 68 + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 + person3: + age: 10 + is_disabled: true + meets_ssi_disability_criteria: true + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 + marital_units: + marital_unit1: + members: [person1, person2] + marital_unit2: + members: [person3] + households: + household: + members: [person1, person2, person3] + state_code: CA + living_arrangements_allow_for_food_preparation: true + output: + # The child fails SSI's noncitizen test, so the state supplement leaves + # out the child's standard and CAPI pays it: 994 + 97.27 = 1,091.27. The + # citizen gets 745.50 SSI and 1,233.94 - 745.50 = 488.44 supplement, so + # the CAPI spouse gets 2,098.83 - 745.50 - 488.44 = 864.89. + ca_capi_person: [0, 864.89, 1_091.27] + +- name: Case 13, one CAPI person with a spouse who is not aged, blind or disabled and earns below the deeming threshold. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 + person2: + age: 50 + employment_income: 3_600 # 300 a month + marital_units: + marital_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: CA + living_arrangements_allow_for_food_preparation: true + output: + # 300 a month is below the 1,491 - 994 = 497 deeming threshold, so + # nothing is deemed and the individual standard applies: 1,233.94. + ca_capi_payment_standard: [1_233.94, 0] + ca_capi_person: [1_233.94, 0] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/eligibility/ca_capi_eligible_person.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/eligibility/ca_capi_eligible_person.yaml index cfde31c565e..4fb7e48ac51 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/eligibility/ca_capi_eligible_person.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/eligibility/ca_capi_eligible_person.yaml @@ -1,4 +1,4 @@ -- name: Eligible person - undocumented +- name: Case 1, eligible person, undocumented. period: 2023 input: is_ssi_aged_blind_disabled: true @@ -7,7 +7,7 @@ output: ca_capi_eligible_person: true -- name: Citizens are not eligible +- name: Case 2, citizens are not eligible. period: 2023 input: is_ssi_aged_blind_disabled: true @@ -16,7 +16,7 @@ output: ca_capi_eligible_person: false -- name: Eligible person - legal permanent resident - not enough qualifying quarters for ssi +- name: Case 3, eligible person, permanent resident without enough qualifying quarters for SSI. period: 2023 input: is_ssi_aged_blind_disabled: true @@ -26,7 +26,7 @@ output: ca_capi_eligible_person: true -- name: Eligible couple - both spouses aged permanent residents without 40 SSI quarters +- name: Case 4, eligible couple, both spouses aged permanent residents without 40 SSI quarters. period: 2026 input: people: diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/eligibility/ca_capi_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/eligibility/ca_capi_income_eligible.yaml index 909d90394e9..cbcbbc8e195 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/eligibility/ca_capi_income_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/eligibility/ca_capi_income_eligible.yaml @@ -1,4 +1,4 @@ -- name: Ineligible, countable income one dollar above the payment standard +- name: Case 1, ineligible, countable income one dollar above the payment standard. period: 2026 input: age: 70 @@ -15,7 +15,7 @@ # 1,234.94 is not, so there is no CAPI. ca_capi_income_eligible: false -- name: Eligible, countable income one dollar below the payment standard +- name: Case 2, eligible, countable income one dollar below the payment standard. period: 2026 input: age: 70 @@ -29,7 +29,7 @@ # 1,232.94 is lower than the 1,233.94 standard: 1 per month of CAPI. ca_capi_income_eligible: true -- name: Ineligible, income deemed from a high-earning spouse exhausts the couple state supplement +- name: Case 3, ineligible, income deemed from a high-earning spouse exhausts the couple state supplement. period: 2026 input: people: diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/state_supplement/ca_state_supplement_dependent_amount.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/state_supplement/ca_state_supplement_dependent_amount.yaml index dad1e1563fa..d5812a3800c 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/state_supplement/ca_state_supplement_dependent_amount.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/state_supplement/ca_state_supplement_dependent_amount.yaml @@ -68,3 +68,55 @@ state_code: CA output: ca_state_supplement_dependent_amount: 5_988 + +- name: Disabled noncitizen child who fails SSI's noncitizen test gets CAPI, not the state supplement. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 + person2: + age: 10 + is_disabled: true + meets_ssi_disability_criteria: true + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 + households: + household: + members: [person1, person2] + state_code: CA + living_arrangements_allow_for_food_preparation: true + output: + # The child fails SSI's 40-quarter test, so the state supplement leaves + # out the child's standard (WIC 18938, 18941) and CAPI pays the disabled + # minor standard 994 + 97.27 = 1,091.27. + ca_capi_person: [0, 1_091.27] + ca_state_supplement_dependent_amount: 0 + ca_state_supplement: 0 + +- name: Disabled citizen child keeps the state supplement above SSI. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + person2: + age: 10 + is_disabled: true + meets_ssi_disability_criteria: true + immigration_status: CITIZEN + households: + household: + members: [person1, person2] + state_code: CA + living_arrangements_allow_for_food_preparation: true + output: + # SSI 994; the state supplement tops the child up to the disabled minor + # standard: 1,091.27 - 994 = 97.27. + ssi: [0, 994] + ca_state_supplement: 97.27 diff --git a/policyengine_us/variables/gov/states/ca/cdss/capi/_ca_capi_ssi_ssp_standard.py b/policyengine_us/variables/gov/states/ca/cdss/capi/_ca_capi_ssi_ssp_standard.py index 33ea748fdf3..b34133cb500 100644 --- a/policyengine_us/variables/gov/states/ca/cdss/capi/_ca_capi_ssi_ssp_standard.py +++ b/policyengine_us/variables/gov/states/ca/cdss/capi/_ca_capi_ssi_ssp_standard.py @@ -1,32 +1,54 @@ from policyengine_us.model_api import * +from policyengine_us.variables.gov.ssa.ssi.eligibility.status.ssi_federal_living_arrangement import ( + SSIFederalLivingArrangement, +) + + +def ca_capi_in_title_xix_facility(person, period): + """Whether a person lives in a Title XIX medical facility (MPP 49-050.26). + + Reads both the California input and SSI's living arrangement, so the CAPI + standard and SSI's couple test agree. + """ + arrangement = person("ssi_federal_living_arrangement", period) + return person("ca_in_medical_care_facility", period.this_year) | ( + arrangement == SSIFederalLivingArrangement.MEDICAL_TREATMENT_FACILITY + ) + + +def ca_capi_spouse_ssi_ssp(person, period): + """Return the SSI and state supplement paid to the person's spouse. + + Only a spouse who is not CAPI-eligible counts. ca_state_supplement is an + SPM-unit amount, so as a simplification the spouse's share is pro rata + among the unit's members eligible for it; a citizen disabled child's + supplement in the unit is then attributed to the spouse. + """ + spouse = ~person("ca_capi_eligible_person", period.this_year) + spouse_ssi = person.marital_unit.sum(person("ssi", period) * spouse) + ssp_eligible = person("ca_state_supplement_eligible_person", period) + spouse_ssp_share = person.marital_unit.sum(ssp_eligible * spouse) / max_( + person.spm_unit.sum(ssp_eligible), 1 + ) + spouse_ssp = spouse_ssp_share * person.spm_unit("ca_state_supplement", period) + return spouse_ssi + spouse_ssp def ca_capi_ssi_ssp_standard(person, period, parameters): """Return a person's monthly SSI/SSP individual and couple standards. - CAPI payment standards equal the SSI/SSP standards (WIC 18941), and the - living arrangement selects one standard (MPP 49-050.2; POMS SI 01415.058 - B). These follow ca_state_supplement_payment_standard, whose amounts - include the federal benefit rate: + CAPI equals SSI/SSP (WIC 18941), and the living arrangement selects one + standard (MPP 49-050.2; POMS SI 01415.058 B): - Title XIX medical facility: the facility standard alone (MPP 49-050.26). - - Nonmedical out-of-home care: one standard for every category, half the - couple out-of-home care standard per person (MPP 49-050.24). - - Independent living: the higher of the blind amount and the aged or - disabled amount (the disabled child amount for a dependent child, MPP - 49-050.25; blind children take the blind amount, MPP 49-050.253). Only - the aged or disabled amount adds the food allowance for people who - cannot prepare meals, for an individual under WIC 12200(c) or a couple - under 12200(d) (WIC 12200(e)), so the one-blind couple rate under - 12200(b) adds none. POMS SI 01415.058 B.1 code C adds the individual - allowance for the aged or disabled member of such a couple; the code - follows the statute. California pays the highest category a person or - couple qualifies for. - In an SSI couple computation the couple standard sums both members' - shares; otherwise it treats the ineligible spouse as the person's + - Non-medical out-of-home care: one standard for every category, half the + couple amount per person (WIC 12200(g); MPP 49-050.24). + - Independent living: the highest category the person or couple qualifies + for; the no-cooking allowance goes only with the aged or disabled amount + (WIC 12200(e)), not the one-blind couple rate (12200(b)). + Outside an SSI couple computation the ineligible spouse takes the person's category (POMS SI 01320.430 C.7). - NOTE: the reduced-needs standards for people living in another person's - household (POMS SI 01415.058 code D) are not modeled; they need their own - state supplement amounts (issue 7892). + NOTE: reduced-needs standards (POMS SI 01415.058 code D) are not modeled + (issue 7892). """ p = parameters(period).gov.states.ca.cdss.state_supplement.payment_standard fbr = parameters(period).gov.ssa.ssi.amount @@ -39,14 +61,13 @@ def ca_capi_ssi_ssp_standard(person, period, parameters): "is_ssi_disabled", period.this_year ) # NOTE: living_arrangements_allow_for_food_preparation has no default - # value, so unless it is set every aged or disabled person gets the - # no-cooking allowance. + # value and the microdata do not set it, so every aged or disabled + # person gets the no-cooking allowance (+$128.87 a month in 2026, +$257.74 + # for a couple) unless it is set (issue 10296). no_cooking = ~person.household( "living_arrangements_allow_for_food_preparation", period.this_year ) - # NOTE: the Title XIX standard reads ca_in_medical_care_facility, while - # SSI reads ssi_federal_living_arrangement; the two inputs can disagree. - medical_facility = person("ca_in_medical_care_facility", period.this_year) + medical_facility = ca_capi_in_title_xix_facility(person, period) out_of_home_care = person("in_out_of_home_care_facility", period.this_year) out_of_home_care_share = ( p.aged_or_disabled.amount.married + p.allowance.out_of_home_care @@ -69,6 +90,8 @@ def ca_capi_ssi_ssp_standard(person, period, parameters): ) two_blind = (blind_count > 1) * p.blind.married.two_blind one_blind = (blind_count == 1) * p.blind.married.one_blind + # NOTE: a couple with one aged or disabled member always has a blind + # member, whose rate is higher, so the second branch is only a guard. aged_or_disabled_couple = select( [aged_or_disabled_count > 1, aged_or_disabled_count == 1], [ diff --git a/policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_payment_standard.py b/policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_payment_standard.py index 7ec5a717150..d84fe108016 100644 --- a/policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_payment_standard.py +++ b/policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_payment_standard.py @@ -1,5 +1,6 @@ from policyengine_us.model_api import * from policyengine_us.variables.gov.states.ca.cdss.capi._ca_capi_ssi_ssp_standard import ( + ca_capi_spouse_ssi_ssp, ca_capi_ssi_ssp_standard, ) @@ -32,8 +33,10 @@ def formula(person, period, parameters): # A spouse receiving SSI/SSP counts as an eligible spouse (MPP # 49-005(e)(3)), so the CAPI member of a mixed couple takes the whole # couple standard (MPP 49-050.13) and ca_capi_person subtracts that - # spouse's SSI/SSP. - mixed = joint & ~both_capi + # spouse's SSI/SSP. A spouse paid neither is an ineligible spouse (MPP + # 49-005(i)(2)), so the CAPI member takes the individual standard. + spouse_paid = ca_capi_spouse_ssi_ssp(person, period) > 0 + mixed = joint & ~both_capi & spouse_paid return select( [both_capi, mixed], [(couple - p.couple) / 2, couple - p.mixed_couple], diff --git a/policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_person.py b/policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_person.py index e2fc0094e39..05f1d00a394 100644 --- a/policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_person.py +++ b/policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_person.py @@ -1,5 +1,7 @@ from policyengine_us.model_api import * from policyengine_us.variables.gov.states.ca.cdss.capi._ca_capi_ssi_ssp_standard import ( + ca_capi_in_title_xix_facility, + ca_capi_spouse_ssi_ssp, ca_capi_ssi_ssp_standard, ) @@ -28,7 +30,7 @@ def formula(person, period, parameters): # Deeming needs an ineligible spouse living in the same household # (20 CFR 416.1160(a)(1)), so a Title XIX facility resident counts # only their own income. - medical_facility = person("ca_in_medical_care_facility", period.this_year) + medical_facility = ca_capi_in_title_xix_facility(person, period) income = where(medical_facility, own_income, countable_income) # NOTE: the reduced-needs standards for another person's household are # not modeled (issue 7892), so those recipients get the @@ -38,46 +40,37 @@ def formula(person, period, parameters): # Mixed couple: the spouse's SSI/SSP counts as unearned income based on # need (MPP 49-035.221), subtracted with the couple's countable income # from the couple standard (MPP 49-055.32). - # NOTE: the model applies this computation whenever both spouses are - # aged, blind or disabled (ssi_couple_computation_applies ignores SSI's - # noncitizen test), even when SSA would pay the spouse nothing. Such a - # spouse is an ineligible spouse (MPP 49-005(i)(2); 20 CFR 416.1160(d)) - # and deeming applies. Example, January 2026: a citizen with $1,300 of - # Social Security and a CAPI spouse with no income get $818.83 a month - # in the model; the law gives $450.94 of CAPI alone (issue 10481). + # NOTE: SSI couple status ignores SSI's noncitizen test, so the model + # can still pay such a spouse SSI that SSA would not (issue 10481). capi_eligible = person("ca_capi_eligible_person", period.this_year) joint = person("ssi_couple_computation_applies", period) - mixed = joint & ~(person.marital_unit.sum(capi_eligible) > 1) - spouse = ~capi_eligible - spouse_ssi = person.marital_unit.sum(person("ssi", period) * spouse) - # NOTE: ca_state_supplement is an SPM-unit amount; as a simplification, - # the spouse's share is pro rata among the unit's SSP-eligible members. - ssp_eligible = person("ca_state_supplement_eligible_person", period) - spouse_ssp_share = person.marital_unit.sum(ssp_eligible * spouse) / max_( - person.spm_unit.sum(ssp_eligible), 1 - ) - spouse_ssp = spouse_ssp_share * person.spm_unit("ca_state_supplement", period) + couple_with_spouse = joint & ~(person.marital_unit.sum(capi_eligible) > 1) + spouse_ssi_ssp = ca_capi_spouse_ssi_ssp(person, period) couple_income = person.marital_unit.sum(countable_income) - mixed_benefit = max_( - payment_standard - couple_income - spouse_ssi - spouse_ssp, 0 - ) + # A spouse counts as an eligible spouse only while receiving SSI/SSP + # (MPP 49-005(e)(3), 49-050.13). A spouse paid neither is an + # ineligible spouse (MPP 49-005(i)(2)), whose income is deemed. + spouse_paid = spouse_ssi_ssp > 0 + mixed = couple_with_spouse & spouse_paid + unpaid_spouse = couple_with_spouse & ~spouse_paid + mixed_benefit = max_(payment_standard - couple_income - spouse_ssi_ssp, 0) - # MPP 49-035.71 follows the SSI spouse-to-spouse deeming steps: compute - # the federal and state parts as an individual and under deeming, then - # take the lesser of each (POMS SI 01320.430 D). WIC 18940(b) applies - # the federal deeming rules and WIC 18941 makes CAPI equal SSI/SSP, - # which SSA computes this way; the 1999 CAPI form SOC 452 takes the - # lesser of the two totals instead. - # NOTE: the federal parts use the independent-living benefit rates, - # matching the independent-living SSI/SSP standards. + # MPP 49-035.71 follows the SSI spouse-to-spouse deeming steps: the + # federal and state parts are each the lesser of the individual and the + # deeming computation (POMS SI 01320.430 D; WIC 18940(b), 18941). The + # 1999 CAPI form SOC 452 takes the lesser of the two totals instead. + # NOTE: the federal parts use the independent-living benefit rates. individual_standard, couple_standard = ca_capi_ssi_ssp_standard( person, period, parameters ) fbr = parameters(period).gov.ssa.ssi.amount individual_federal = fbr.individual - own_income - couple_federal = fbr.couple - countable_income + deeming_income = where(unpaid_spouse, couple_income, countable_income) + couple_federal = fbr.couple - deeming_income federal = max_(min_(individual_federal, couple_federal), 0) individual_supplement = individual_standard - fbr.individual + # NOTE: a guard (POMS SI 01320.430 C.4.c); the couple state part exceeds + # the individual part in every modeled year. couple_supplement = max_(couple_standard - fbr.couple, individual_supplement) # Income above a federal rate reduces the matching state supplement. supplement = min_( @@ -86,11 +79,13 @@ def formula(person, period, parameters): ) p = parameters(period).gov.states.ca.cdss.capi.payment_standard_offset deemed_benefit = max_(federal + supplement - p.single, 0) + # NOTE: until PR 10240 counts the income of people who fail SSI's + # noncitizen test, deeming from a spouse who is not aged, blind or + # disabled runs only with supplied inputs. deeming = ( - person("is_ssi_spousal_deeming_applies", period.this_year) - & ~joint - & ~medical_facility - ) + (person("is_ssi_spousal_deeming_applies", period.this_year) & ~joint) + | unpaid_spouse + ) & ~medical_facility return select( [mixed, deeming], [mixed_benefit, deemed_benefit], diff --git a/policyengine_us/variables/gov/states/ca/cdss/state_supplement/payment_standard/ca_state_supplement_dependent_amount.py b/policyengine_us/variables/gov/states/ca/cdss/state_supplement/payment_standard/ca_state_supplement_dependent_amount.py index fd35064bcfd..aa37b9ab887 100644 --- a/policyengine_us/variables/gov/states/ca/cdss/state_supplement/payment_standard/ca_state_supplement_dependent_amount.py +++ b/policyengine_us/variables/gov/states/ca/cdss/state_supplement/payment_standard/ca_state_supplement_dependent_amount.py @@ -20,7 +20,17 @@ def formula(spm_unit, period, parameters): # Dependent amount dependent = person("is_tax_unit_dependent", period) dependent_age_eligible = age < p.dependent.age_limit + # The child must meet the SSI/SSP conditions that + # ca_state_supplement_eligible_person applies to adults; a child who + # fails SSI's noncitizen test gets CAPI instead (WIC 18938, 18941). + 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 + ) + meets_resource_test = person("meets_ssi_resource_test", period) + eligible = meets_resource_test & (is_citizen | is_qualified_noncitizen) dependent_count = spm_unit.sum( - dependent & dependent_age_eligible & (is_ssi_disabled | blind) + dependent & dependent_age_eligible & (is_ssi_disabled | blind) & eligible ) return dependent_count * p.dependent.amount diff --git a/source_conflicts/candidates.yaml b/source_conflicts/candidates.yaml index 55d971f42f4..de437417982 100644 --- a/source_conflicts/candidates.yaml +++ b/source_conflicts/candidates.yaml @@ -1141,16 +1141,20 @@ candidates: example: In January 2026, a couple of an aged person and a blind person aged 50 without cooking facilities has a $2,238.44 standard under the statute, which PE-US follows for CAPI, and $2,367.31 under POMS. pe_us: - follows: statute + follows: conflicting-source code: - policyengine_us/variables/gov/states/ca/cdss/capi/_ca_capi_ssi_ssp_standard.py + - policyengine_us/variables/gov/states/ca/cdss/state_supplement/payment_standard/ca_state_supplement_food_allowance.py + - policyengine_us/variables/gov/states/ca/cdss/state_supplement/payment_standard/ca_state_supplement_payment_standard.py prs: - https://github.com/PolicyEngine/policyengine-us/pull/10379 state: unreviewed - note: 'PE-US follows the statute for CAPI: _ca_capi_ssi_ssp_standard.py adds no food allowance to the one-blind - couple rate, and a couple both aged or disabled takes the aged or disabled rate with the couple allowance when - that is higher. The ACIN I-59-25 table lists no such combination. Check how ca_state_supplement_food_allowance - treats these couples.' + note: 'PE-US is split, although WIC 18941 makes CAPI equal SSI/SSP. CAPI follows the statute: + _ca_capi_ssi_ssp_standard.py adds no food allowance to the one-blind couple rate, and a couple both aged or + disabled takes the aged or disabled rate with the couple allowance when that is higher. The state supplement + follows POMS: ca_state_supplement_food_allowance.py adds the individual allowance for the aged or disabled member, + so in January 2026 the same couple has a $2,367.31 standard as citizens and $2,238.44 as CAPI recipients. The + ACIN I-59-25 table lists no such combination. The ruling should set both programs.' - id: us-ca:ssp-nmohc-couple-standard program: ssi-ssp years: @@ -1186,8 +1190,10 @@ candidates: follows: statute code: - policyengine_us/parameters/gov/states/ca/cdss/state_supplement/payment_standard/allowance/out_of_home_care.yaml + - policyengine_us/variables/gov/states/ca/cdss/capi/_ca_capi_ssi_ssp_standard.py prs: - https://github.com/PolicyEngine/policyengine-us/pull/9709 + - https://github.com/PolicyEngine/policyengine-us/pull/10379 state: unreviewed note: 'PE-US follows the statute: the 2026 allowance is $1,153.31, from a $3,252.14 couple standard, twice the $1,626.07 individual rate (allowance/out_of_home_care.yaml), and the file''s comment lists the sources on each From 91898a065953501ec4519efa18cf95b07566b2ba Mon Sep 17 00:00:00 2001 From: Ziming Date: Thu, 29 Oct 2026 13:48:43 -0400 Subject: [PATCH 10/18] Apply Pavel's review: MD PAA one-third reduction on the couple rate, SSP immigration mask, new cases - C1: md_paa_imputed_federal_ssi reduces the couple rate by one third in another person's household (20 CFR 416.1131; POMS SI 01320.400 B.1.e); md_paa Cases 14-16 - SA1: medically needy Case 13 (a noncitizen dependent parent's pension does not count against the head), now that #10370 is on main - SA2: the CA state supplement leaves out a member who fails SSI's noncitizen test, except a spouse in an SSI couple computation; Case 12; Case 11 and the CAPI mixed-couple case restated - SA3: MSP Case 6 and SC OSS Case 8 - G1/G2/G7: MD PAA comment, Case 11 note on the public income-maintenance exclusion, KY SSP gate aligned Co-Authored-By: Claude Opus 5.5 --- ...d-abd-noncitizen-countable-income.fixed.md | 2 +- .../income/msp_countable_income.yaml | 29 +++++ .../gov/states/ca/cdss/capi/ca_capi.yaml | 36 +++--- .../state_supplement/ca_state_supplement.yaml | 78 ++++++++++--- .../gov/states/md/dhs/fia/paa/md_paa.yaml | 109 ++++++++++++++++++ .../ssi_state_supplement/integration.yaml | 22 ++++ .../state_supplement/ca_state_supplement.py | 23 ++-- .../ky/dcbs/ssp/ky_ssp_countable_income.py | 9 +- .../md/dhs/fia/paa/md_paa_countable_income.py | 10 +- .../dhs/fia/paa/md_paa_imputed_federal_ssi.py | 20 ++-- 10 files changed, 276 insertions(+), 62 deletions(-) diff --git a/changelog.d/medicaid-abd-noncitizen-countable-income.fixed.md b/changelog.d/medicaid-abd-noncitizen-countable-income.fixed.md index b1ee78caba6..55f2c685ab7 100644 --- a/changelog.d/medicaid-abd-noncitizen-countable-income.fixed.md +++ b/changelog.d/medicaid-abd-noncitizen-countable-income.fixed.md @@ -1 +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 deems spouse income to people SSI bars by alien status and imputes to them only the SSI that SSA pays when they report SSI receipt. +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 the income of a member who fails SSI's noncitizen test unless that member is in an SSI couple computation, and Maryland PAA no longer deems spouse income to people SSI bars by alien status and imputes to them only the SSI that SSA pays when they report SSI receipt, with the one-third reduction on the couple rate under deeming. diff --git a/policyengine_us/tests/policy/baseline/gov/hhs/medicare/savings_programs/income/msp_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/hhs/medicare/savings_programs/income/msp_countable_income.yaml index 1c823197a3b..dd0b3efecbd 100644 --- a/policyengine_us/tests/policy/baseline/gov/hhs/medicare/savings_programs/income/msp_countable_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/hhs/medicare/savings_programs/income/msp_countable_income.yaml @@ -113,3 +113,32 @@ # (12,000 - 2,400 + 24,000 - 3,600) / 12 = 2,500 monthly. # Apply the couple's exclusions once: (2,500 - 20 - 65) / 2 = 1,207.50. msp_countable_income: [1_207.50, 1_207.50] + +- name: Case 6, spouse income is deemed to an aged permanent resident without 40 SSI quarters. + period: 2025-01 + 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 + ssi_unearned_income: 12_000 + person2: + age: 55 + is_tax_unit_spouse: true + ssi_earned_income: 20_000 + tax_units: + tax_unit: + members: [person1, person2] + marital_units: + marital_unit: + members: [person1, person2] + output: + # SSI methodology deems the spouse's wages whether or not the person + # meets SSI's noncitizen test: 20,000 > (1,450 - 967) x 12 = 5,796. + # (1,000 - 20) + (1,666.67 - 65) / 2 = 980 + 800.83 = 1,780.83. + is_ssi_spousal_deeming_applies: [true, false] + msp_countable_income: [1_780.83, 790.83] 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 c336bdf346c..eded052ce07 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 @@ -220,7 +220,7 @@ ca_capi_person: 11_316 ca_capi: 11_316 -- name: Integration test, aged permanent resident without 40 SSI quarters whose pension exceeds the CAPI standard +- name: Case 9, integration test, aged permanent resident without 40 SSI quarters whose pension exceeds the CAPI standard. period: 2025 absolute_error_margin: 0.01 input: @@ -244,7 +244,7 @@ # most the 1,335.81 SSI/SSP no-cooking standard, so CAPI pays nothing. ca_capi: 0 -- name: Integration test, mixed couple with income, the noncitizen spouse receives CAPI +- name: Case 10, integration test, mixed couple with income, the noncitizen spouse receives CAPI. period: 2025 absolute_error_margin: 0.01 input: @@ -278,29 +278,25 @@ # (500 + 500 - 20) / 2 = 490 a month each (5,880 a year). ssi_countable_income: [5_880, 5_880] # The citizen's SSI is 1,450 / 2 - 490 = 235 a month. - # NOTE: SSA treats the noncitizen spouse as an ineligible spouse - # (20 CFR 416.1160(d)). Her 500 exceeds the 1,450 - 967 = 483 gap, so SSA - # deems her income and pays SSI of min(967 - 480, 1,450 - 980) = 470 and - # a state supplement of min(1,335.81 - 967, 2,315.57 - 1,450) = 368.81, - # 838.81 in all (POMS SI 01320.430 D; 20 CFR 416.1163(e)(2)). CAPI would - # then be 2,315.57 - 980 - 838.81 = 496.76 a month (5,961.12 a year). The - # model's couple computation for a mixed-status couple pays - # 235 + 610.81 = 845.81, so CAPI is 489.76 instead of 496.76. This is a - # pre-existing ssi_claim_is_joint limitation: it counts aged, blind or - # disabled head/spouse status rather than SSI eligibility. The expected - # values below are the model's. + # NOTE: SSA deems none of the CAPI member's income, because income + # counted in figuring CAPI is excluded from deeming (20 CFR + # 416.1161(a)(2)-(3); POMS SI 01320.141 A), so it pays the citizen 487 + + # 368.81 = 855.81, and CAPI would be 2,315.57 - 980 - 855.81 = 479.76 a + # month. The model's couple computation for a mixed-status couple pays the + # citizen 235 + 120.81 = 355.81 and CAPI 979.76; the couple's total is the + # same (#10481). The expected values below are the model's. ssi: [2_820, 0] # 235 * 12 # The citizen's state supplement is the 1,206.94 + 128.87 = 1,335.81 - # no-cooking individual standard less SSI 235 and his own 490: - # 610.81 a month. The CAPI member's 490 is not counted. - ca_state_supplement: 7_329.72 # 610.81 * 12 + # no-cooking individual standard less SSI 235 and both halves of the + # couple's income: 1,335.81 - 235 - 980 = 120.81 a month. + ca_state_supplement: 1_449.72 # 120.81 * 12 # The CAPI member takes the whole couple standard (MPP 49-050.13), the # 2,057.83 + 257.74 = 2,315.57 no-cooking aged couple standard, with no # offset since June 2019 (WIC 18941). ca_capi_payment_standard: [0, 27_786.84] # 2,315.57 * 12 # The couple's countable income 490 + 490 = 980 (MPP 49-055.32) and the - # citizen's SSI/SSP 235 + 610.81, counted as unearned income based on + # citizen's SSI/SSP 235 + 120.81, counted as unearned income based on # need (MPP 49-035.221), are subtracted: - # 2,315.57 - 980 - 235 - 610.81 = 489.76 a month. - ca_capi_person: [0, 5_877.12] # 489.76 * 12 - ca_capi: 5_877.12 + # 2,315.57 - 980 - 235 - 120.81 = 979.76 a month. + ca_capi_person: [0, 11_757.12] # 979.76 * 12 + ca_capi: 11_757.12 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 9f923ace80f..fefd802ba85 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 @@ -411,21 +411,22 @@ ca_state_supplement: 4_425.72 # 368.81 * 12 # Under the model's SSI couple computation each aged spouse carries half of -# the couple's countable income. The model leaves the CAPI member's half out -# of the citizen's state supplement because CAPI budgets the couple's income -# (MPP 49-055.32), and the citizen's own half is already in his countable -# income. 2025: the couple federal benefit rate is $1,450; the no-cooking -# individual standard is $1,206.94 + $128.87 = $1,335.81. +# the couple's countable income, and both halves count against the citizen's +# state supplement. 2025: the couple federal benefit rate is $1,450; the +# no-cooking individual standard is $1,206.94 + $128.87 = $1,335.81. # NOTE: SSA treats the noncitizen spouse as an ineligible spouse (20 CFR -# 416.1160(d)). Her 500 exceeds the 1,450 - 967 = 483 gap, so SSA deems her -# income and pays SSI of min(967 - 480, 1,450 - 980) = 470 and a state -# supplement of min(1,335.81 - 967, 2,315.57 - 1,450) = 368.81, 838.81 in -# all (POMS SI 01320.430 D; 20 CFR 416.1163(e)(2)). The model's couple -# computation for a mixed-status couple pays 235 + 610.81 = 845.81, so CAPI -# is 489.76 instead of 496.76. This is a pre-existing ssi_claim_is_joint -# limitation: it counts aged, blind or disabled head/spouse status rather -# than SSI eligibility. The expected values below are the model's. -- name: Case 11, 2025 aged citizen married to a CAPI-eligible spouse, whose half of the couple's income is not counted. +# 416.1160(d)), but it deems none of the spouse's income. CAPI is state-funded +# assistance based on need, a public income-maintenance payment (20 CFR +# 416.1142(a)(6); POMS SI 00830.175), and income counted in figuring such a +# payment is not deemed, whoever receives it (20 CFR 416.1161(a)(2)-(3); +# POMS SI 01320.141 A). SSA pays SSI of 967 - 480 = 487 and a state +# supplement of 1,335.81 - 967 = 368.81, 855.81 in all. The model's couple +# computation for a mixed-status couple pays 235 + 120.81 = 355.81, and CAPI +# then pays 500 more than the law gives, so the couple's total is the same. +# This is a pre-existing ssi_claim_is_joint limitation (#10481): it counts +# aged, blind or disabled head/spouse status rather than SSI eligibility. The +# expected values below are the model's. +- name: Case 11, 2025 aged citizen married to a CAPI-eligible spouse, the couple computation counts both halves of the couple's income. period: 2025 absolute_error_margin: 0.01 input: @@ -466,6 +467,49 @@ # 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 - 235 - 490 = 610.81 a month; person2's 490 - # is not counted. - ca_state_supplement: 7_329.72 # 610.81 * 12 + # The supplement is 1,335.81 - 235 - (490 + 490) = 120.81 a month. + ca_state_supplement: 1_449.72 # 120.81 * 12 + +- name: Case 12, 2025 aged citizen sharing an SPM unit with an undocumented sibling who is not CAPI-eligible 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: UNDOCUMENTED + pension_income: 6_000 # 500 a month + # WIC 18938 and MPP 49-020 bar undocumented people from CAPI (#10482). + ca_capi_eligible_person: false + 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: + # Each has 500 - 20 = 480 a month of countable income. + ssi_countable_income: [5_760, 5_760] + ssi: [5_844, 0] # 487 * 12 + ca_state_supplement_payment_standard: 16_029.72 # 1,335.81 * 12 + # A sibling's income is never deemed to an SSI/SSP recipient + # (20 CFR 416.1160(a)), so the supplement stays 1,335.81 - 487 - 480 = + # 368.81 a month. + 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 eb6e1753172..194f834dc69 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 @@ -352,3 +352,112 @@ md_paa_total_cost_of_care: [1_478, 0] # PAA = 1,478 - 480 - 487 = 511, the same as with no spouse (Case 12). md_paa: [511, 0] + +- name: Case 14, SSI reporter without 40 quarters whose deemed spouse wages make the couple computation lower. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + immigration_status: LEGAL_PERMANENT_RESIDENT + years_since_us_entry: 30 + ssi_qualifying_quarters_earnings: 20 + receives_ssi: true + 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: 24_000 # 2,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: + # Couple countable 480 + (2,000 - 65) x 0.5 = 1,447.50; deemed + # 1,447.50 - 480 = 967.50 a month. + ssi_income_deemed_from_ineligible_spouse: [967.50, 0] + md_paa_countable_income: [480, 957.50] + # SSA pays min(1,450 - 1,447.50, 967 - 480) = min(2.50, 487) = 2.50 + # (20 CFR 416.1163(d)-(e)). + md_paa_imputed_federal_ssi: [2.50, 0] + # PAA = 1,478 - 480 - 2.50 = 995.50. + md_paa: [995.50, 0] + +- name: Case 15, SSI reporter without 40 quarters under the one-third reduction 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: 30 + ssi_qualifying_quarters_earnings: 20 + receives_ssi: true + ssi_countable_resources: 1_000 + md_paa_living_arrangement: CARE_HOME_LEVEL_D + ssi_lives_in_another_persons_household: true + ssi_receives_shelter_from_others_in_household: true + ssi_others_pay_all_meals: true + 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: + # No own income, so the $20 general exclusion goes to the wages: + # (1,000 - 20 - 65) x 0.5 = 457.50 deemed a month. + ssi_income_deemed_from_ineligible_spouse: [457.50, 0] + md_paa_countable_income: [0, 457.50] + # The one-third reduction applies to the couple rate under deeming + # (POMS SI 01320.400 B.1.e): min(1,450 x 2/3 - 457.50, 967 x 2/3 - 0) = 509.17. + md_paa_imputed_federal_ssi: [509.17, 0] + # PAA = 1,478 - 0 - 509.17 = 968.83. + md_paa: [968.83, 0] + +- name: Case 16, SSI reporter without 40 quarters in an MDH Rehabilitative Residence gets the $30 medical-facility rate. + period: 2025-01 + absolute_error_margin: 0.01 + input: + age: 70 + immigration_status: LEGAL_PERMANENT_RESIDENT + years_since_us_entry: 30 + ssi_qualifying_quarters_earnings: 20 + receives_ssi: true + social_security_survivors: 120 # 10 a month + ssi_countable_resources: 1_000 + md_paa_living_arrangement: REHAB_RESIDENCE + ssi_lives_in_medical_treatment_facility: true + ssi_medicaid_pays_majority_of_care: true + state_code: MD + output: + md_paa_eligible: true + # 10 - 20 general exclusion leaves no countable income. + md_paa_countable_income: 0 + # The federal rate in a medical treatment facility is 30 a month + # (42 U.S.C. 1382(e)(1)(B)). + md_paa_imputed_federal_ssi: 30 + # PAA = the 102 personal needs allowance less 30 = 72. + md_paa: 72 diff --git a/policyengine_us/tests/policy/baseline/gov/states/sc/scdhhs/ssi_state_supplement/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/sc/scdhhs/ssi_state_supplement/integration.yaml index 9097949051a..0c630d509a8 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/sc/scdhhs/ssi_state_supplement/integration.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/sc/scdhhs/ssi_state_supplement/integration.yaml @@ -199,3 +199,25 @@ # Not eligible so OSS = $0 sc_ssi_state_supplement: [0] + +- name: Case 8, aged permanent resident without 40 SSI quarters in a CRCF has a pension above the NIL. + period: 2026 + input: + people: + person1: + age: 70 + immigration_status: LEGAL_PERMANENT_RESIDENT + years_since_us_entry: 10 + ssi_qualifying_quarters_earnings: 20 + pension_income: 24_000 + is_in_residential_care_facility: true + households: + household: + members: [person1] + state_code: SC + output: + # The pension now counts: 24,000 - 240 = 23,760, above the 21,648 net + # income limit, so the person is not eligible. + ssi_countable_income: [23_760] + sc_ssi_state_supplement_eligible: [false] + sc_ssi_state_supplement: [0] 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 e9cda34fda1..b81067831f6 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 @@ -20,13 +20,20 @@ def formula(spm_unit, period, parameters): person = spm_unit.members # SSI/SSP counts another member's income only when it is deemed # (20 CFR 416.1160(a)), and CAPI budgets its own members' income (CAPI - # regulations MPP 49-035). A spouse's income already reaches the SSI - # recipient's own countable income through the couple computation or - # deeming, so a CAPI-eligible member's countable income is not added - # again. - 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) + # regulations MPP 49-035). So the countable income of a member who + # fails SSI's citizen or qualified-noncitizen test, whether or not + # CAPI-eligible, is not added, unless that member is in an SSI couple + # computation: it splits the couple's income between the spouses, so + # both halves count against the couple's SSI/SSP. + # NOTE: SSI couple status ignores SSI's noncitizen test (issue 10481). + 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 ) + meets_ssi_immigration_test = is_citizen | is_qualified_noncitizen + in_couple_computation = person("ssi_couple_computation_applies", period) + counted = meets_ssi_immigration_test | in_couple_computation + person_countable_income = person("ssi_countable_income", period) + countable_income = spm_unit.sum(where(counted, person_countable_income, 0)) return max_(0, payment_standard - ssi - countable_income) diff --git a/policyengine_us/variables/gov/states/ky/dcbs/ssp/ky_ssp_countable_income.py b/policyengine_us/variables/gov/states/ky/dcbs/ssp/ky_ssp_countable_income.py index ed143bb9dfd..33f871585ba 100644 --- a/policyengine_us/variables/gov/states/ky/dcbs/ssp/ky_ssp_countable_income.py +++ b/policyengine_us/variables/gov/states/ky/dcbs/ssp/ky_ssp_countable_income.py @@ -37,11 +37,12 @@ def formula(person, period, parameters): both_eligible = person("ssi_couple_computation_applies", period) spousal_deemed = person("ssi_income_deemed_from_ineligible_spouse", period) - is_eligible = person("is_ssi_eligible_individual", period.this_year) | person( - "is_ssi_eligible_spouse", period.this_year - ) + # Same gate as ssi_countable_income: people who are not aged, blind or + # disabled have no countable income of their own. KY SSP requires + # is_ssi_eligible, so this does not change any payment. + is_aged_blind_disabled = person("is_ssi_aged_blind_disabled", period.this_year) return where( - ~is_eligible, + ~is_aged_blind_disabled, 0, where( both_eligible, 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 37e2e23bcdf..b32ee9f66b5 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 @@ -46,10 +46,12 @@ def formula(person, period, parameters): both_eligible = person("ssi_couple_computation_applies", period.this_year) # 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, including those who report SSI - # receipt: PAA itself has no spousal deeming. + # spousal deeming, so people who fail SSI's citizen or + # qualified-noncitizen test count their own income alone, including + # those who report SSI receipt. + # NOTE: for citizens and qualified noncitizens the SSI deemed amount is + # still added, although their imputed SSI already reflects it. This + # predates the noncitizen change and is a known limitation. immigration_status = person("immigration_status", period) is_citizen = immigration_status == immigration_status.possible_values.CITIZEN is_qualified_noncitizen = person("is_ssi_qualified_noncitizen", period) 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 4b939eacbfe..dae9a715beb 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 @@ -16,6 +16,7 @@ class md_paa_imputed_federal_ssi(Variable): "https://regs.maryland.gov/us/md/exec/comar/07.03.07.09", "https://www.law.cornell.edu/uscode/text/42/1382#e_1_A", "https://www.law.cornell.edu/cfr/text/20/416.1163", + "https://secure.ssa.gov/poms.nsf/lnx/0501320400", ) def formula(person, period, parameters): @@ -43,17 +44,20 @@ def formula(person, period, parameters): arrangement = person("ssi_federal_living_arrangement", period) arrangements = SSIFederalLivingArrangement in_medical_facility = arrangement == arrangements.MEDICAL_TREATMENT_FACILITY - individual_rate = select( - [ - in_medical_facility, - arrangement == arrangements.ANOTHER_PERSONS_HOUSEHOLD, - ], - [p.medical_facility, p.individual * (1 - p.one_third_reduction_rate)], - default=p.individual, + # The one-third reduction applies to the Federal benefit rate in use: + # the individual rate, or the couple rate under spouse deeming + # (20 CFR 416.1131; POMS SI 01320.400 B.1.e). + vtr_factor = where( + arrangement == arrangements.ANOTHER_PERSONS_HOUSEHOLD, + 1 - p.one_third_reduction_rate, + 1, + ) + individual_rate = where( + in_medical_facility, p.medical_facility, p.individual * vtr_factor ) individual_ssi = individual_rate - countable_income deemed_income = person("ssi_income_deemed_from_ineligible_spouse", period) - couple_ssi = p.couple - (countable_income + deemed_income) + couple_ssi = p.couple * vtr_factor - (countable_income + deemed_income) deeming = ( person("is_ssi_spousal_deeming_applies", period.this_year) & ~in_medical_facility From 7df48bb65e5757893f339518fe25451b1394bc26 Mon Sep 17 00:00:00 2001 From: Ziming Date: Thu, 29 Oct 2026 14:54:07 -0400 Subject: [PATCH 11/18] Compute a CAPI couple with one spouse in a Title XIX facility as two individuals; Case N names - ca_capi_couple_computation: SSI's couple computation, except when exactly one spouse is in a Title XIX facility by either input (20 CFR 416.414(b)(3)); used by the helper, the payment standard and ca_capi_person; Case 20 - ca_state_supplement_dependent_amount.yaml Cases 4 and 5 named Co-Authored-By: Claude Opus 5.5 --- .../cdss/capi/ca_capi_payment_standard.yaml | 29 +++++++++++++++++++ .../ca_state_supplement_dependent_amount.yaml | 4 +-- .../ca/cdss/capi/_ca_capi_ssi_ssp_standard.py | 17 +++++++++-- .../ca/cdss/capi/ca_capi_payment_standard.py | 3 +- .../gov/states/ca/cdss/capi/ca_capi_person.py | 3 +- 5 files changed, 49 insertions(+), 7 deletions(-) diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi_payment_standard.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi_payment_standard.yaml index dbbec260c3f..f7fc100280d 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi_payment_standard.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi_payment_standard.yaml @@ -472,3 +472,32 @@ # Stopgap floor: (1,167 + 709) / 2 = 938, floored at the 943 FBR. A # known-low value: POMS SI 01415.056 gives 1,575.07 (issue 10480). ca_capi_payment_standard: 943 + +- name: Case 20, CAPI couple with one spouse in a Title XIX facility is computed as two individuals. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 72 + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 + ca_in_medical_care_facility: true + person2: + age: 68 + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 + marital_units: + marital_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: CA + living_arrangements_allow_for_food_preparation: true + output: + # With one spouse in a Title XIX facility, each is computed separately + # (20 CFR 416.414(b)(3)): the facility standard 62 (MPP 49-050.26) and + # the aged individual standard 994 + 239.94 = 1,233.94. + ca_capi_payment_standard: [62, 1_233.94] + ca_capi_person: [62, 1_233.94] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/state_supplement/ca_state_supplement_dependent_amount.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/state_supplement/ca_state_supplement_dependent_amount.yaml index d5812a3800c..9ab4f1dad94 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/state_supplement/ca_state_supplement_dependent_amount.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/state_supplement/ca_state_supplement_dependent_amount.yaml @@ -69,7 +69,7 @@ output: ca_state_supplement_dependent_amount: 5_988 -- name: Disabled noncitizen child who fails SSI's noncitizen test gets CAPI, not the state supplement. +- name: Case 4, disabled noncitizen child who fails SSI's noncitizen test gets CAPI, not the state supplement. period: 2026-01 absolute_error_margin: 0.01 input: @@ -97,7 +97,7 @@ ca_state_supplement_dependent_amount: 0 ca_state_supplement: 0 -- name: Disabled citizen child keeps the state supplement above SSI. +- name: Case 5, disabled citizen child keeps the state supplement above SSI. period: 2026-01 absolute_error_margin: 0.01 input: diff --git a/policyengine_us/variables/gov/states/ca/cdss/capi/_ca_capi_ssi_ssp_standard.py b/policyengine_us/variables/gov/states/ca/cdss/capi/_ca_capi_ssi_ssp_standard.py index b34133cb500..1461cb59c89 100644 --- a/policyengine_us/variables/gov/states/ca/cdss/capi/_ca_capi_ssi_ssp_standard.py +++ b/policyengine_us/variables/gov/states/ca/cdss/capi/_ca_capi_ssi_ssp_standard.py @@ -7,8 +7,7 @@ def ca_capi_in_title_xix_facility(person, period): """Whether a person lives in a Title XIX medical facility (MPP 49-050.26). - Reads both the California input and SSI's living arrangement, so the CAPI - standard and SSI's couple test agree. + Reads both the California input and SSI's living arrangement. """ arrangement = person("ssi_federal_living_arrangement", period) return person("ca_in_medical_care_facility", period.this_year) | ( @@ -16,6 +15,18 @@ def ca_capi_in_title_xix_facility(person, period): ) +def ca_capi_couple_computation(person, period): + """Whether CAPI computes the person with their spouse as a couple. + + SSI's couple computation, except that a couple with exactly one spouse in + a Title XIX facility is computed separately (20 CFR 416.414(b)(3)), when + only the California facility input marks it. + """ + in_facility = ca_capi_in_title_xix_facility(person, period) + one_in_facility = person.marital_unit.sum(in_facility) == 1 + return person("ssi_couple_computation_applies", period) & ~one_in_facility + + def ca_capi_spouse_ssi_ssp(person, period): """Return the SSI and state supplement paid to the person's spouse. @@ -83,7 +94,7 @@ def ca_capi_ssi_ssp_standard(person, period, parameters): ), ) - joint = person("ssi_couple_computation_applies", period) + joint = ca_capi_couple_computation(person, period) blind_count = where(joint, person.marital_unit.sum(blind), 2 * blind) aged_or_disabled_count = where( joint, person.marital_unit.sum(aged_or_disabled), 2 * aged_or_disabled diff --git a/policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_payment_standard.py b/policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_payment_standard.py index d84fe108016..a7a86fb37f2 100644 --- a/policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_payment_standard.py +++ b/policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_payment_standard.py @@ -1,5 +1,6 @@ from policyengine_us.model_api import * from policyengine_us.variables.gov.states.ca.cdss.capi._ca_capi_ssi_ssp_standard import ( + ca_capi_couple_computation, ca_capi_spouse_ssi_ssp, ca_capi_ssi_ssp_standard, ) @@ -24,7 +25,7 @@ class ca_capi_payment_standard(Variable): def formula(person, period, parameters): individual, couple = ca_capi_ssi_ssp_standard(person, period, parameters) p = parameters(period).gov.states.ca.cdss.capi.payment_standard_offset - joint = person("ssi_couple_computation_applies", period) + joint = ca_capi_couple_computation(person, period) capi_members = person.marital_unit.sum( person("ca_capi_eligible_person", period.this_year) ) diff --git a/policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_person.py b/policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_person.py index 05f1d00a394..211bdca5d10 100644 --- a/policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_person.py +++ b/policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_person.py @@ -1,5 +1,6 @@ from policyengine_us.model_api import * from policyengine_us.variables.gov.states.ca.cdss.capi._ca_capi_ssi_ssp_standard import ( + ca_capi_couple_computation, ca_capi_in_title_xix_facility, ca_capi_spouse_ssi_ssp, ca_capi_ssi_ssp_standard, @@ -43,7 +44,7 @@ def formula(person, period, parameters): # NOTE: SSI couple status ignores SSI's noncitizen test, so the model # can still pay such a spouse SSI that SSA would not (issue 10481). capi_eligible = person("ca_capi_eligible_person", period.this_year) - joint = person("ssi_couple_computation_applies", period) + joint = ca_capi_couple_computation(person, period) couple_with_spouse = joint & ~(person.marital_unit.sum(capi_eligible) > 1) spouse_ssi_ssp = ca_capi_spouse_ssi_ssp(person, period) couple_income = person.marital_unit.sum(countable_income) From 59a97d8c962e11ffe4c24bdd6f68fea26a2219a6 Mon Sep 17 00:00:00 2001 From: Ziming Date: Thu, 29 Oct 2026 15:05:15 -0400 Subject: [PATCH 12/18] Count a mixed couple citizen's own income in the CA supplement; keep the KY gate with a NOTE; drop stale comments - ca_state_supplement: members who fail SSI's noncitizen test are left out; in an SSI couple computation with such a spouse, the citizen's own countable income counts, since SSA deems none of the CAPI-counted income (20 CFR 416.1160(d), 416.1161(a)(2)-(3)); Cases 11 and 13-14, CAPI Case 10 restated to the law's totals - ky_ssp_countable_income: SSI's eligibility gate kept, with a NOTE (an aligned gate broke KY Case 5) - Removed "until PR 10240" comments that this PR makes false Co-Authored-By: Claude Opus 5.5 --- ...ional_senior_or_disabled_for_medicaid.yaml | 5 +- .../gov/states/ca/cdss/capi/ca_capi.yaml | 25 ++-- .../state_supplement/ca_state_supplement.yaml | 113 +++++++++++++++--- .../gov/states/ca/cdss/capi/ca_capi_person.py | 3 - .../state_supplement/ca_state_supplement.py | 48 ++++++-- .../ky/dcbs/ssp/ky_ssp_countable_income.py | 12 +- 6 files changed, 154 insertions(+), 52 deletions(-) diff --git a/policyengine_us/tests/policy/baseline/gov/hhs/medicaid/eligibility/categories/is_optional_senior_or_disabled_for_medicaid.yaml b/policyengine_us/tests/policy/baseline/gov/hhs/medicaid/eligibility/categories/is_optional_senior_or_disabled_for_medicaid.yaml index 9f7afb5c3a5..16472e89f6c 100644 --- a/policyengine_us/tests/policy/baseline/gov/hhs/medicaid/eligibility/categories/is_optional_senior_or_disabled_for_medicaid.yaml +++ b/policyengine_us/tests/policy/baseline/gov/hhs/medicaid/eligibility/categories/is_optional_senior_or_disabled_for_medicaid.yaml @@ -61,8 +61,9 @@ # Emergency Medicaid covers noncitizens who meet the state plan's requirements # other than the receipt of SSI (42 U.S.C. 1396b(v)(2)(B); 42 CFR 435.406(b)). # In Alabama that leaves SSI's income test. Wages of $800 a month ($9,600 a -# year) are under the SSI rate ($11,928) before any disregard. Until #10240 -# merges, the pathway counts no income for this person; Cases 7 and 8 test it. +# year) are under the SSI rate ($11,928) before any disregard; the pathway +# counts that income (at most 4,290 a year after exclusions). Cases 7 and 8 +# test the income limit. - name: Case 6, undocumented aged Alabaman keeps the pathway, unlike the citizen in Case 3, and qualifies for emergency Medicaid. period: 2026 input: 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 eded052ce07..914f4a1c41d 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 @@ -118,9 +118,8 @@ # Disabled individual standard 1,233.94 + no-cooking food allowance # 128.87 (living arrangements default to no food preparation) = # 1,362.81 per month with no offset. Earnings of 83.33 per month fall - # within the $20 + $65 exclusions, so countable income is 0 (until PR - # 10240, SSI also zeroes this income for people who fail its noncitizen - # test). 1,362.81 x 12 = 16,353.72. + # within the $20 + $65 exclusions, so countable income is 0. + # 1,362.81 x 12 = 16,353.72. ca_capi: 16_353.72 - name: Case 6, mixed couple, only the noncitizen spouse receives CAPI. @@ -281,22 +280,20 @@ # NOTE: SSA deems none of the CAPI member's income, because income # counted in figuring CAPI is excluded from deeming (20 CFR # 416.1161(a)(2)-(3); POMS SI 01320.141 A), so it pays the citizen 487 + - # 368.81 = 855.81, and CAPI would be 2,315.57 - 980 - 855.81 = 479.76 a - # month. The model's couple computation for a mixed-status couple pays the - # citizen 235 + 120.81 = 355.81 and CAPI 979.76; the couple's total is the - # same (#10481). The expected values below are the model's. + # 368.81 = 855.81. The model's SSI is still the couple computation + # (#10481), so it pays 235 + 620.81, the same 855.81. ssi: [2_820, 0] # 235 * 12 # The citizen's state supplement is the 1,206.94 + 128.87 = 1,335.81 - # no-cooking individual standard less SSI 235 and both halves of the - # couple's income: 1,335.81 - 235 - 980 = 120.81 a month. - ca_state_supplement: 1_449.72 # 120.81 * 12 + # no-cooking individual standard less SSI 235 and the citizen's own + # 500 - 20 = 480: 620.81 a month. + ca_state_supplement: 7_449.72 # 620.81 * 12 # The CAPI member takes the whole couple standard (MPP 49-050.13), the # 2,057.83 + 257.74 = 2,315.57 no-cooking aged couple standard, with no # offset since June 2019 (WIC 18941). ca_capi_payment_standard: [0, 27_786.84] # 2,315.57 * 12 # The couple's countable income 490 + 490 = 980 (MPP 49-055.32) and the - # citizen's SSI/SSP 235 + 120.81, counted as unearned income based on + # citizen's SSI/SSP 235 + 620.81, counted as unearned income based on # need (MPP 49-035.221), are subtracted: - # 2,315.57 - 980 - 235 - 120.81 = 979.76 a month. - ca_capi_person: [0, 11_757.12] # 979.76 * 12 - ca_capi: 11_757.12 + # 2,315.57 - 980 - 235 - 620.81 = 479.76 a month. + ca_capi_person: [0, 5_757.12] # 479.76 * 12 + ca_capi: 5_757.12 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 fefd802ba85..e4af8cf6b72 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 @@ -411,22 +411,17 @@ ca_state_supplement: 4_425.72 # 368.81 * 12 # Under the model's SSI couple computation each aged spouse carries half of -# the couple's countable income, and both halves count against the citizen's -# state supplement. 2025: the couple federal benefit rate is $1,450; the -# no-cooking individual standard is $1,206.94 + $128.87 = $1,335.81. -# NOTE: SSA treats the noncitizen spouse as an ineligible spouse (20 CFR -# 416.1160(d)), but it deems none of the spouse's income. CAPI is state-funded -# assistance based on need, a public income-maintenance payment (20 CFR -# 416.1142(a)(6); POMS SI 00830.175), and income counted in figuring such a -# payment is not deemed, whoever receives it (20 CFR 416.1161(a)(2)-(3); -# POMS SI 01320.141 A). SSA pays SSI of 967 - 480 = 487 and a state -# supplement of 1,335.81 - 967 = 368.81, 855.81 in all. The model's couple -# computation for a mixed-status couple pays 235 + 120.81 = 355.81, and CAPI -# then pays 500 more than the law gives, so the couple's total is the same. -# This is a pre-existing ssi_claim_is_joint limitation (#10481): it counts -# aged, blind or disabled head/spouse status rather than SSI eligibility. The -# expected values below are the model's. -- name: Case 11, 2025 aged citizen married to a CAPI-eligible spouse, the couple computation counts both halves of the couple's income. +# the couple's countable income for SSI. SSA treats the noncitizen spouse as +# an ineligible spouse (20 CFR 416.1160(d)) but deems none of the spouse's +# income: CAPI is a public income-maintenance payment (20 CFR 416.1142(a)(6); +# POMS SI 00830.175), and income counted in figuring it is not deemed +# (20 CFR 416.1161(a)(2)-(3); POMS SI 01320.141 A). So the supplement counts +# the citizen's own income. 2025: the couple federal benefit rate is $1,450; +# the no-cooking individual standard is $1,206.94 + $128.87 = $1,335.81. +# NOTE: SSA pays SSI of 967 - 480 = 487 and a supplement of 368.81. The +# model's SSI is still the couple computation, 235 (#10481), so its +# supplement is 620.81; the citizen's total, 855.81, is the same. +- name: Case 11, 2025 aged citizen married to a CAPI-eligible spouse, the supplement counts the citizen's own income. period: 2025 absolute_error_margin: 0.01 input: @@ -467,8 +462,9 @@ # 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 - 235 - (490 + 490) = 120.81 a month. - ca_state_supplement: 1_449.72 # 120.81 * 12 + # The supplement counts the citizen's own 500 - 20 = 480: + # 1,335.81 - 235 - 480 = 620.81 a month. + ca_state_supplement: 7_449.72 # 620.81 * 12 - name: Case 12, 2025 aged citizen sharing an SPM unit with an undocumented sibling who is not CAPI-eligible keeps the supplement. period: 2025 @@ -513,3 +509,84 @@ # (20 CFR 416.1160(a)), so the supplement stays 1,335.81 - 487 - 480 = # 368.81 a month. ca_state_supplement: 4_425.72 # 368.81 * 12 + +- name: Case 13, 2025 aged citizen sharing an SPM unit with a married CAPI couple 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 + ssi_qualifying_quarters_earnings: 0 + pension_income: 6_000 # 500 a month + person3: + age: 70 + is_tax_unit_spouse: true + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 0 + pension_income: 6_000 # 500 a month + tax_units: + tax_unit1: + members: [person1] + tax_unit2: + members: [person2, person3] + marital_units: + marital_unit1: + members: [person1] + marital_unit2: + members: [person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: CA + output: + # Neither member of the couple meets SSI's noncitizen test, so neither + # one's income is deemed to the citizen (20 CFR 416.1160(a)). The citizen + # has 480 a month of countable income and SSI of 967 - 480 = 487, so the + # supplement is 1,335.81 - 487 - 480 = 368.81 a month. + ssi: [5_844, 0, 0] # 487 * 12 + ca_state_supplement: 4_425.72 # 368.81 * 12 + +- name: Case 14, 2026 mixed couple where both spouses have income, the supplement counts the citizen's own income. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 72 + immigration_status: CITIZEN + social_security_retirement: 9_600 # 800 a month + person2: + age: 68 + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 + pension_income: 9_600 # 800 a month + marital_units: + marital_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: CA + living_arrangements_allow_for_food_preparation: true + output: + # The model's SSI couple computation gives each spouse (1,600 - 20) / 2 + # = 790, so the citizen's SSI is max(745.50 - 790, 0) = 0. The supplement + # counts the citizen's own 800 - 20 = 780: 1,233.94 - 0 - 780 = 453.94. + # SSA pays the citizen 994 - 780 = 214 of SSI and 239.94 of supplement, + # the same 453.94 in all (#10481). + ssi: [0, 0] + ca_state_supplement: 453.94 + # The spouse is paid, so CAPI is the mixed-couple amount: + # 2,098.83 - 1,580 - 0 - 453.94 = 64.89. + ca_capi_person: [0, 64.89] diff --git a/policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_person.py b/policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_person.py index 211bdca5d10..b78c30b73a8 100644 --- a/policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_person.py +++ b/policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_person.py @@ -80,9 +80,6 @@ def formula(person, period, parameters): ) p = parameters(period).gov.states.ca.cdss.capi.payment_standard_offset deemed_benefit = max_(federal + supplement - p.single, 0) - # NOTE: until PR 10240 counts the income of people who fail SSI's - # noncitizen test, deeming from a spouse who is not aged, blind or - # disabled runs only with supplied inputs. deeming = ( (person("is_ssi_spousal_deeming_applies", period.this_year) & ~joint) | unpaid_spouse 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 b81067831f6..b94435c6591 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 @@ -1,4 +1,7 @@ from policyengine_us.model_api import * +from policyengine_us.variables.gov.ssa.ssi.eligibility.income._apply_ssi_exclusions import ( + _apply_ssi_exclusions, +) class ca_state_supplement(Variable): @@ -20,20 +23,45 @@ def formula(spm_unit, period, parameters): person = spm_unit.members # SSI/SSP counts another member's income only when it is deemed # (20 CFR 416.1160(a)), and CAPI budgets its own members' income (CAPI - # regulations MPP 49-035). So the countable income of a member who - # fails SSI's citizen or qualified-noncitizen test, whether or not - # CAPI-eligible, is not added, unless that member is in an SSI couple - # computation: it splits the couple's income between the spouses, so - # both halves count against the couple's SSI/SSP. - # NOTE: SSI couple status ignores SSI's noncitizen test (issue 10481). + # regulations MPP 49-035), so the income of a member who fails SSI's + # citizen or qualified-noncitizen test is not counted. 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 ) meets_ssi_immigration_test = is_citizen | is_qualified_noncitizen - in_couple_computation = person("ssi_couple_computation_applies", period) - counted = meets_ssi_immigration_test | in_couple_computation - person_countable_income = person("ssi_countable_income", period) - countable_income = spm_unit.sum(where(counted, person_countable_income, 0)) + # SSA treats a spouse who fails that test as an ineligible spouse (20 + # CFR 416.1160(d)) and deems none of the spouse's income counted for + # CAPI (20 CFR 416.1161(a)(2)-(3)), so in such a couple the recipient's + # own income counts, not half of the couple's. + # NOTE: SSI couple status ignores SSI's noncitizen test, so the + # model's SSI is still the couple computation (issue 10481). + in_mixed_couple = ( + person("ssi_couple_computation_applies", period) + & meets_ssi_immigration_test + & (person.marital_unit.sum(~meets_ssi_immigration_test) > 0) + ) + earned = max_( + person("ssi_earned_income", period.this_year) + - person( + "ssi_blind_or_disabled_working_student_exclusion", period.this_year + ), + 0, + ) + unearned = person("ssi_unearned_income", period.this_year) + person( + "ssi_in_kind_support_and_maintenance", period.this_year + ) + # _apply_ssi_exclusions takes and returns annual amounts. + own_countable_income = ( + _apply_ssi_exclusions(earned, unearned, parameters, period) / MONTHS_IN_YEAR + ) + person_countable_income = where( + in_mixed_couple, + own_countable_income, + person("ssi_countable_income", period), + ) + countable_income = spm_unit.sum( + where(meets_ssi_immigration_test, person_countable_income, 0) + ) return max_(0, payment_standard - ssi - countable_income) diff --git a/policyengine_us/variables/gov/states/ky/dcbs/ssp/ky_ssp_countable_income.py b/policyengine_us/variables/gov/states/ky/dcbs/ssp/ky_ssp_countable_income.py index 33f871585ba..217e8fe4deb 100644 --- a/policyengine_us/variables/gov/states/ky/dcbs/ssp/ky_ssp_countable_income.py +++ b/policyengine_us/variables/gov/states/ky/dcbs/ssp/ky_ssp_countable_income.py @@ -37,12 +37,14 @@ def formula(person, period, parameters): both_eligible = person("ssi_couple_computation_applies", period) spousal_deemed = person("ssi_income_deemed_from_ineligible_spouse", period) - # Same gate as ssi_countable_income: people who are not aged, blind or - # disabled have no countable income of their own. KY SSP requires - # is_ssi_eligible, so this does not change any payment. - is_aged_blind_disabled = person("is_ssi_aged_blind_disabled", period.this_year) + # NOTE: ssi_countable_income now zeroes only people who are not aged, + # blind or disabled. This keeps SSI's eligibility gate, which changes + # nothing because KY SSP requires is_ssi_eligible. + is_eligible = person("is_ssi_eligible_individual", period.this_year) | person( + "is_ssi_eligible_spouse", period.this_year + ) return where( - ~is_aged_blind_disabled, + ~is_eligible, 0, where( both_eligible, From c4542119b5e11c5426a3b476b770b2e1238ed627 Mon Sep 17 00:00:00 2001 From: Ziming Date: Thu, 29 Oct 2026 15:18:34 -0400 Subject: [PATCH 13/18] Count a mixed-couple citizen's own income only when the spouse receives CAPI; otherwise deem The 416.1161(a)(2)-(3) exclusion covers income counted for a CAPI payment the spouse receives. When the spouse's income leaves no CAPI, it is deemed and the supplement is the lesser of the individual and couple computations (416.1163). The spouse test uses the tax-unit head or spouse. Case 15. Co-Authored-By: Claude Opus 5.5 --- .../state_supplement/ca_state_supplement.yaml | 31 ++++++++++++++ .../state_supplement/ca_state_supplement.py | 42 +++++++++++++++---- 2 files changed, 66 insertions(+), 7 deletions(-) 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 e4af8cf6b72..f436198da74 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 @@ -590,3 +590,34 @@ # The spouse is paid, so CAPI is the mixed-couple amount: # 2,098.83 - 1,580 - 0 - 453.94 = 64.89. ca_capi_person: [0, 64.89] + +- name: Case 15, 2026 mixed couple whose CAPI spouse has too much income for CAPI, so the spouse's income is deemed. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 72 + immigration_status: CITIZEN + person2: + age: 68 + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 + pension_income: 24_000 # 2,000 a month + marital_units: + marital_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: CA + living_arrangements_allow_for_food_preparation: true + output: + # The spouse's 2,000 - 20 = 1,980 leaves no CAPI, so it is deemed (20 CFR + # 416.1163): the lesser of 1,233.94 - 0 and 2,098.83 - 1,980 = 118.83. + # The model's joint SSI is max(745.50 - 990, 0) = 0, so the supplement is + # 118.83. + ssi: [0, 0] + ca_state_supplement: 118.83 + # CAPI: 2,098.83 - 1,980 - 118.83 = 0. + ca_capi_person: [0, 0] 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 b94435c6591..40bf310ff62 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 @@ -2,6 +2,9 @@ from policyengine_us.variables.gov.ssa.ssi.eligibility.income._apply_ssi_exclusions import ( _apply_ssi_exclusions, ) +from policyengine_us.variables.gov.states.ca.cdss.capi._ca_capi_ssi_ssp_standard import ( + ca_capi_ssi_ssp_standard, +) class ca_state_supplement(Variable): @@ -32,15 +35,21 @@ def formula(spm_unit, period, parameters): ) meets_ssi_immigration_test = is_citizen | is_qualified_noncitizen # SSA treats a spouse who fails that test as an ineligible spouse (20 - # CFR 416.1160(d)) and deems none of the spouse's income counted for - # CAPI (20 CFR 416.1161(a)(2)-(3)), so in such a couple the recipient's - # own income counts, not half of the couple's. + # CFR 416.1160(d)). If the spouse receives CAPI, none of the income + # counted for CAPI is deemed (20 CFR 416.1161(a)(2)-(3)), so the + # recipient's own income counts, not half of the couple's. Otherwise + # the spouse's income is deemed and SSA pays the lesser of the + # individual and couple computations (20 CFR 416.1163). # NOTE: SSI couple status ignores SSI's noncitizen test, so the # model's SSI is still the couple computation (issue 10481). + head_or_spouse = person("is_tax_unit_head_or_spouse", period) + spouse_fails_test = ( + person.marital_unit.sum(~meets_ssi_immigration_test & head_or_spouse) > 0 + ) in_mixed_couple = ( person("ssi_couple_computation_applies", period) & meets_ssi_immigration_test - & (person.marital_unit.sum(~meets_ssi_immigration_test) > 0) + & spouse_fails_test ) earned = max_( person("ssi_earned_income", period.this_year) @@ -49,6 +58,8 @@ def formula(spm_unit, period, parameters): ), 0, ) + # NOTE: in-kind support uses the couple's presumed maximum value here, + # because SSI still treats the pair as a couple. unearned = person("ssi_unearned_income", period.this_year) + person( "ssi_in_kind_support_and_maintenance", period.this_year ) @@ -56,10 +67,27 @@ def formula(spm_unit, period, parameters): own_countable_income = ( _apply_ssi_exclusions(earned, unearned, parameters, period) / MONTHS_IN_YEAR ) - person_countable_income = where( - in_mixed_couple, + ssi_countable_income = person("ssi_countable_income", period) + couple_income = person.marital_unit.sum(ssi_countable_income) + individual_standard, couple_standard = ca_capi_ssi_ssp_standard( + person, period, parameters + ) + # The spouse receives CAPI when the couple standard exceeds the + # couple's income plus the recipient's SSI/SSP on own income + # (CAPI MPP 49-050.13, 49-035.221). + recipient_ssi_ssp = max_( + person("ssi", period), individual_standard - own_countable_income + ) + spouse_gets_capi = couple_standard - couple_income - recipient_ssi_ssp > 0 + deemed_countable_income = max_( own_countable_income, - person("ssi_countable_income", period), + couple_income - (couple_standard - individual_standard), + ) + mixed_countable_income = where( + spouse_gets_capi, own_countable_income, deemed_countable_income + ) + person_countable_income = where( + in_mixed_couple, mixed_countable_income, ssi_countable_income ) countable_income = spm_unit.sum( where(meets_ssi_immigration_test, person_countable_income, 0) From f4e10a9d7a3160ab68b5626ee94dd644ee98ce73 Mon Sep 17 00:00:00 2001 From: Ziming Date: Thu, 29 Oct 2026 15:18:48 -0400 Subject: [PATCH 14/18] Read is_tax_unit_head_or_spouse for the year in the CA supplement Co-Authored-By: Claude Opus 5.5 --- .../gov/states/ca/cdss/state_supplement/ca_state_supplement.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 40bf310ff62..c907b090182 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 @@ -42,7 +42,7 @@ def formula(spm_unit, period, parameters): # individual and couple computations (20 CFR 416.1163). # NOTE: SSI couple status ignores SSI's noncitizen test, so the # model's SSI is still the couple computation (issue 10481). - head_or_spouse = person("is_tax_unit_head_or_spouse", period) + head_or_spouse = person("is_tax_unit_head_or_spouse", period.this_year) spouse_fails_test = ( person.marital_unit.sum(~meets_ssi_immigration_test & head_or_spouse) > 0 ) From c065a35bee15298a2c81e57ee9735c395915a737 Mon Sep 17 00:00:00 2001 From: Ziming Date: Thu, 29 Oct 2026 15:26:15 -0400 Subject: [PATCH 15/18] Simplify the CA supplement's mixed-couple income to the lesser-of totals; cite POMS SI 01320.430 D The CAPI-receipt branch always equalled the deemed lesser-of, so it is dropped; results are unchanged. Co-Authored-By: Claude Opus 5.5 --- .../state_supplement/ca_state_supplement.py | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) 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 c907b090182..3dabf82dc8b 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 @@ -38,8 +38,11 @@ def formula(spm_unit, period, parameters): # CFR 416.1160(d)). If the spouse receives CAPI, none of the income # counted for CAPI is deemed (20 CFR 416.1161(a)(2)-(3)), so the # recipient's own income counts, not half of the couple's. Otherwise - # the spouse's income is deemed and SSA pays the lesser of the - # individual and couple computations (20 CFR 416.1163). + # the spouse's income is deemed (20 CFR 416.1163, 416.2025(b)(3)). + # Taking the lesser of the individual and couple totals gives both: + # it equals own income whenever the spouse would receive CAPI. + # NOTE: POMS SI 01320.430 D takes the lesser of each part separately; + # the totals keep CAPI at zero when the spouse's income is deemed. # NOTE: SSI couple status ignores SSI's noncitizen test, so the # model's SSI is still the couple computation (issue 10481). head_or_spouse = person("is_tax_unit_head_or_spouse", period.this_year) @@ -72,20 +75,10 @@ def formula(spm_unit, period, parameters): individual_standard, couple_standard = ca_capi_ssi_ssp_standard( person, period, parameters ) - # The spouse receives CAPI when the couple standard exceeds the - # couple's income plus the recipient's SSI/SSP on own income - # (CAPI MPP 49-050.13, 49-035.221). - recipient_ssi_ssp = max_( - person("ssi", period), individual_standard - own_countable_income - ) - spouse_gets_capi = couple_standard - couple_income - recipient_ssi_ssp > 0 - deemed_countable_income = max_( + mixed_countable_income = max_( own_countable_income, couple_income - (couple_standard - individual_standard), ) - mixed_countable_income = where( - spouse_gets_capi, own_countable_income, deemed_countable_income - ) person_countable_income = where( in_mixed_couple, mixed_countable_income, ssi_countable_income ) From 5ef420b95363c65d2b6096fad8929cb6daae936f Mon Sep 17 00:00:00 2001 From: Ziming Date: Thu, 29 Oct 2026 17:46:19 -0400 Subject: [PATCH 16/18] Count each spouse's own income when only the California facility input separates a CAPI couple Apply Pavel's SA5 fix (20 CFR 416.414(b)(3)) with Cases 14 and 15, name the state supplement change in the changelog (G11), and add a resource-test case for the dependent amount. Co-Authored-By: Claude Opus 5.5 --- changelog.d/ca-capi-ssi-ssp-standard.fixed.md | 2 +- .../states/ca/cdss/capi/ca_capi_person.yaml | 57 +++++++++++++++++++ .../ca_state_supplement_dependent_amount.yaml | 28 +++++++++ .../gov/states/ca/cdss/capi/ca_capi_person.py | 24 +++++++- 4 files changed, 109 insertions(+), 2 deletions(-) diff --git a/changelog.d/ca-capi-ssi-ssp-standard.fixed.md b/changelog.d/ca-capi-ssi-ssp-standard.fixed.md index beb3dba5fdd..f708a925b1f 100644 --- a/changelog.d/ca-capi-ssi-ssp-standard.fixed.md +++ b/changelog.d/ca-capi-ssi-ssp-standard.fixed.md @@ -1 +1 @@ -Pay California CAPI at the SSI/SSP payment standard (with no offset since June 2019) using one standard per living arrangement, compute each eligible person's benefit on their own income, count the SSI/SSP of a spouse who receives it, and apply spouse-to-spouse deeming. +Pay California CAPI at the SSI/SSP payment standard (with no offset since June 2019) using one standard per living arrangement, compute each eligible person's benefit on their own income, count the SSI/SSP of a spouse who receives it, apply spouse-to-spouse deeming, and stop the state supplement's dependent amount for a disabled or blind child who fails SSI's noncitizen or resource test. diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi_person.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi_person.yaml index 58616267e6d..d5abc2efdd6 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi_person.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi_person.yaml @@ -459,3 +459,60 @@ # nothing is deemed and the individual standard applies: 1,233.94. ca_capi_payment_standard: [1_233.94, 0] ca_capi_person: [1_233.94, 0] + +- name: Case 14, couple with one spouse in a Title XIX facility, each spouse's own income counts. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 72 + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 + ca_in_medical_care_facility: true + person2: + age: 68 + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 + # 1,000 a month; countable 980 after the $20 exclusion. + social_security: 12_000 + marital_units: + marital_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: CA + living_arrangements_allow_for_food_preparation: true + output: + # 20 CFR 416.414(b)(3): each spouse's own countable income comes off + # that spouse's standard: 62 - 0 = 62 and 1,233.94 - 980 = 253.94. + ca_capi_person: [62, 253.94] + +- name: Case 15, couple with one spouse in a Title XIX facility, the facility resident's income stays with that spouse. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 72 + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 + ca_in_medical_care_facility: true + # 1,000 a month; countable 980 after the $20 exclusion. + social_security: 12_000 + person2: + age: 68 + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 + marital_units: + marital_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: CA + living_arrangements_allow_for_food_preparation: true + output: + # 20 CFR 416.414(b)(3): max(62 - 980, 0) = 0 and 1,233.94 - 0 = 1,233.94. + ca_capi_person: [0, 1_233.94] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/state_supplement/ca_state_supplement_dependent_amount.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/state_supplement/ca_state_supplement_dependent_amount.yaml index 9ab4f1dad94..579447c1979 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/state_supplement/ca_state_supplement_dependent_amount.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/state_supplement/ca_state_supplement_dependent_amount.yaml @@ -120,3 +120,31 @@ # standard: 1,091.27 - 994 = 97.27. ssi: [0, 994] ca_state_supplement: 97.27 + +- name: Case 6, disabled citizen child who fails SSI's resource test gets no state supplement. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + person2: + age: 10 + is_disabled: true + meets_ssi_disability_criteria: true + immigration_status: CITIZEN + bank_account_assets: + '2026': 3_000 + households: + household: + members: [person1, person2] + state_code: CA + living_arrangements_allow_for_food_preparation: true + output: + # The child's 3,000 of countable resources exceed SSI's 2,000 limit (20 + # CFR 416.1205), so the child gets no SSI and no dependent amount. + meets_ssi_resource_test: [true, false] + ssi: [0, 0] + ca_state_supplement_dependent_amount: 0 + ca_state_supplement: 0 diff --git a/policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_person.py b/policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_person.py index 211bdca5d10..8c21e8748a4 100644 --- a/policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_person.py +++ b/policyengine_us/variables/gov/states/ca/cdss/capi/ca_capi_person.py @@ -1,4 +1,7 @@ from policyengine_us.model_api import * +from policyengine_us.variables.gov.ssa.ssi.eligibility.income._apply_ssi_exclusions import ( + _apply_ssi_exclusions, +) from policyengine_us.variables.gov.states.ca.cdss.capi._ca_capi_ssi_ssp_standard import ( ca_capi_couple_computation, ca_capi_in_title_xix_facility, @@ -24,7 +27,26 @@ class ca_capi_person(Variable): ) def formula(person, period, parameters): - countable_income = person("ssi_countable_income", period) + # When only the California facility input separates a couple that SSI + # computes jointly, ssi_countable_income holds half the couple's + # income; each spouse's own income counts (20 CFR 416.414(b)(3)). + # NOTE: this own income leaves out in-kind support and the student + # earned income exclusion, which SSI's joint computation would apply. + separated = person( + "ssi_couple_computation_applies", period + ) & ~ca_capi_couple_computation(person, period) + own_alone = ( + _apply_ssi_exclusions( + person("ssi_earned_income", period.this_year), + person("ssi_unearned_income", period.this_year), + parameters, + period.this_year, + ) + / MONTHS_IN_YEAR + ) + countable_income = where( + separated, own_alone, person("ssi_countable_income", period) + ) payment_standard = person("ca_capi_payment_standard", period) deemed_income = person("ssi_income_deemed_from_ineligible_spouse", period) own_income = max_(countable_income - deemed_income, 0) From 2467454e7922a06a577a8118ed6a2934c6e0b2f0 Mon Sep 17 00:00:00 2001 From: Ziming Date: Thu, 29 Oct 2026 17:48:39 -0400 Subject: [PATCH 17/18] Add the role-swapped mixed-couple cases and the above-threshold deeming case for CAPI Pavel's G10 on PR 10379: with the CAPI member as tax-unit head, the state supplement counts the citizen's own income, so CAPI deems (Cases 16 and 17). Case 18 is Case 13 above the deeming threshold. Co-Authored-By: Claude Opus 5.5 --- .../states/ca/cdss/capi/ca_capi_person.yaml | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi_person.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi_person.yaml index a3991b3308e..4b5d9901829 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi_person.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/cdss/capi/ca_capi_person.yaml @@ -510,3 +510,96 @@ output: # 20 CFR 416.414(b)(3): max(62 - 980, 0) = 0 and 1,233.94 - 0 = 1,233.94. ca_capi_person: [0, 1_233.94] + +- name: Case 16, CAPI member is the tax-unit head and the aged citizen spouse's income is too high for SSI/SSP, so CAPI deems the spouse's income. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 72 + is_tax_unit_head: true + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 + person2: + age: 68 + is_tax_unit_spouse: true + immigration_status: CITIZEN + # 1,600 a month; countable 1,580 after the $20 exclusion. + social_security: 19_200 + marital_units: + marital_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: CA + living_arrangements_allow_for_food_preparation: true + output: + # Case 8 with the roles swapped. The state supplement counts the citizen's + # own 1,580, which exceeds the 1,233.94 standard, so the citizen is paid + # no SSI/SSP and is an ineligible spouse (MPP 49-005(i)(2)). POMS SI + # 01320.430 D: federal min(994, 1,491 - 1,580) -> 0; state min(239.94, + # 607.83 - (1,580 - 1,491)) = 239.94. + ssi: [0, 0] + ca_state_supplement: 0 + ca_capi_person: [239.94, 0] + +- name: Case 17, CAPI member is the tax-unit head and the spouse's income exceeds the couple state supplement, leaving the couple state part. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 72 + is_tax_unit_head: true + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 + person2: + age: 68 + is_tax_unit_spouse: true + immigration_status: CITIZEN + # 2,000 a month; countable 1,980 after the $20 exclusion. + social_security: 24_000 + marital_units: + marital_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: CA + living_arrangements_allow_for_food_preparation: true + output: + # Case 9 with the roles swapped. POMS SI 01320.430 D: federal 0; state + # min(239.94, 607.83 - (1,980 - 1,491)) = min(239.94, 118.83) = 118.83. + ssi: [0, 0] + ca_state_supplement: 0 + ca_capi_person: [118.83, 0] + +- name: Case 18, one CAPI person with a spouse who is not aged, blind or disabled and earns above the deeming threshold. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi_qualifying_quarters_earnings: 39 + person2: + age: 50 + employment_income: 24_000 # 2,000 a month + marital_units: + marital_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: CA + living_arrangements_allow_for_food_preparation: true + output: + # Case 13 above the 1,491 - 994 = 497 deeming threshold. The couple's + # countable income is (2,000 - 20 - 65) / 2 = 957.50 (20 CFR 416.1163). + # POMS SI 01320.430 D: federal min(994 - 0, 1,491 - 957.50) = 533.50; + # state min(239.94, 607.83) = 239.94; 533.50 + 239.94 = 773.44. + ca_capi_payment_standard: [1_233.94, 0] + ca_capi_person: [773.44, 0] From df7b39883461d2af1eee2b3c41c633f1d4ce1bc9 Mon Sep 17 00:00:00 2001 From: Ziming Date: Fri, 30 Oct 2026 10:49:03 -0400 Subject: [PATCH 18/18] Key the CA supplement's mixed-couple branch on the spouse's CAPI eligibility; cite 416.1161 and 416.2025 Pavel's SA4 on PR 10240: the 416.1161(a)(2)-(3) exclusion needs a spouse who can receive CAPI, so a spouse who fails SSI's noncitizen test but is barred from CAPI (WIC 18938) has income deemed (Case 16). G8 adds the two rules the branch applies to the reference tuple. Co-Authored-By: Claude Opus 5.5 --- .../state_supplement/ca_state_supplement.yaml | 35 +++++++++++++++++++ .../state_supplement/ca_state_supplement.py | 11 ++++-- 2 files changed, 43 insertions(+), 3 deletions(-) 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 f436198da74..dba3464544a 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 @@ -621,3 +621,38 @@ ca_state_supplement: 118.83 # CAPI: 2,098.83 - 1,980 - 118.83 = 0. ca_capi_person: [0, 0] + +- name: Case 16, 2026 citizen married to an aged spouse who fails SSI's noncitizen test and cannot receive CAPI, so the spouse's income is not excluded. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 72 + immigration_status: CITIZEN + social_security: 3_840 # 320 a month + person2: + age: 70 + immigration_status: UNDOCUMENTED + pension_income: 8_400 # 700 a month + # WIC 18938 bars undocumented people from CAPI (#10482). + ca_capi_eligible_person: false + marital_units: + marital_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: CA + living_arrangements_allow_for_food_preparation: true + output: + # The spouse receives no CAPI, so 20 CFR 416.1161(a)(2)-(3) does not + # apply and the spouse's 700 a month, above the 1,491 - 994 = 497 + # threshold, is deemed (20 CFR 416.1163). The model's joint SSI gives each + # spouse (320 + 700 - 20) / 2 = 500: SSI 745.50 - 500 = 245.50 and a + # supplement of 1,233.94 - 245.50 - 500 = 488.44, 733.94 in all. + # NOTE: SSA pays min(994 - 300, 1,491 - 1,000) = 491 of SSI and 239.94 of + # supplement, 730.94 in all; the gap is the joint SSI (#10481). + ssi: [245.50, 0] + ca_state_supplement: 488.44 + ca_capi_person: [0, 0] 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 3dabf82dc8b..ef86e4890a4 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 @@ -17,6 +17,8 @@ class ca_state_supplement(Variable): reference = ( "https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?lawCode=WIC§ionNum=12200", "https://www.law.cornell.edu/cfr/text/20/416.1160", + "https://www.law.cornell.edu/cfr/text/20/416.1161", + "https://www.law.cornell.edu/cfr/text/20/416.2025", "https://www.cdss.ca.gov/Portals/9/CAPI/CAPI_Regulations-Accessible.pdf#page=25", ) @@ -46,13 +48,16 @@ def formula(spm_unit, period, parameters): # NOTE: SSI couple status ignores SSI's noncitizen test, so the # model's SSI is still the couple computation (issue 10481). head_or_spouse = person("is_tax_unit_head_or_spouse", period.this_year) - spouse_fails_test = ( - person.marital_unit.sum(~meets_ssi_immigration_test & head_or_spouse) > 0 + # The exclusion needs a spouse who can receive CAPI, so key on CAPI + # eligibility rather than on SSI's noncitizen test alone (issue 10482). + capi_eligible = person("ca_capi_eligible_person", period.this_year) + spouse_capi_eligible = ( + person.marital_unit.sum(capi_eligible & head_or_spouse) > 0 ) in_mixed_couple = ( person("ssi_couple_computation_applies", period) & meets_ssi_immigration_test - & spouse_fails_test + & spouse_capi_eligible ) earned = max_( person("ssi_earned_income", period.this_year)