diff --git a/changelog.d/ky-ssp.added.md b/changelog.d/ky-ssp.added.md new file mode 100644 index 00000000000..43356ba2d8d --- /dev/null +++ b/changelog.d/ky-ssp.added.md @@ -0,0 +1 @@ +Kentucky State Supplementary Payment (SSP) covering Personal Care Home, Community Integration Supplementation, Family Care Home, and Caretaker Services categories. diff --git a/policyengine_us/parameters/gov/household/household_state_benefits.yaml b/policyengine_us/parameters/gov/household/household_state_benefits.yaml index 40379c1b954..45ab14f7b6e 100644 --- a/policyengine_us/parameters/gov/household/household_state_benefits.yaml +++ b/policyengine_us/parameters/gov/household/household_state_benefits.yaml @@ -34,6 +34,8 @@ values: - fl_oss # Idaho benefits - id_aabd + # Kentucky benefits + - ky_ssp # Nebraska benefits - ne_child_care_subsidies # South Carolina benefits @@ -91,6 +93,8 @@ values: - fl_oss # Idaho benefits - id_aabd + # Kentucky benefits + - ky_ssp # Nebraska benefits - ne_child_care_subsidies # New Mexico benefits diff --git a/policyengine_us/parameters/gov/states/ky/dcbs/ssp/payment_standard.yaml b/policyengine_us/parameters/gov/states/ky/dcbs/ssp/payment_standard.yaml new file mode 100644 index 00000000000..18d5daeda65 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ky/dcbs/ssp/payment_standard.yaml @@ -0,0 +1,124 @@ +description: Kentucky provides this amount as the monthly state supplementation payment standard under the State Supplementation program. +metadata: + unit: currency-USD + period: month + label: Kentucky SSP payment standard + breakdown: + - ky_ssp_category + - ky_ssp_claim_type + - ky_ssp_care_receivers + reference: + - title: 921 KAR 2:015 Section 9 — Standard of Need + href: https://apps.legislature.ky.gov/law/kar/titles/921/002/015/ + - title: KRS 205.245 + href: https://apps.legislature.ky.gov/law/statutes/statute.aspx?id=7671 + - title: CHFS Division of Family Support Operation Manual, Volume V, MS 1200 — State Supplementation Standards (OMTL-690, R. 3/9/26) + href: https://www.chfs.ky.gov/agencies/dcbs/dfs/Documents/OMVOLV.pdf#page=5 + +PCH: + INDIVIDUAL: + ONE: + 2000-01-01: 0 + 2026-01-01: 1_610 + BOTH: + 2000-01-01: 0 + 2026-01-01: 1_610 + COUPLE_BOTH_ELIGIBLE: + ONE: + 2000-01-01: 0 + 2026-01-01: 1_610 + BOTH: + 2000-01-01: 0 + 2026-01-01: 1_610 + COUPLE_ONE_ELIGIBLE: + ONE: + 2000-01-01: 0 + 2026-01-01: 1_610 + BOTH: + 2000-01-01: 0 + 2026-01-01: 1_610 +CIS: + INDIVIDUAL: + ONE: + 2000-01-01: 0 + 2026-01-01: 1_514 + BOTH: + 2000-01-01: 0 + 2026-01-01: 1_514 + COUPLE_BOTH_ELIGIBLE: + ONE: + 2000-01-01: 0 + 2026-01-01: 1_514 + BOTH: + 2000-01-01: 0 + 2026-01-01: 1_514 + COUPLE_ONE_ELIGIBLE: + ONE: + 2000-01-01: 0 + 2026-01-01: 1_514 + BOTH: + 2000-01-01: 0 + 2026-01-01: 1_514 +FCH: + INDIVIDUAL: + ONE: + 2000-01-01: 0 + 2026-01-01: 1_166 + BOTH: + 2000-01-01: 0 + 2026-01-01: 1_166 + COUPLE_BOTH_ELIGIBLE: + ONE: + 2000-01-01: 0 + 2026-01-01: 1_166 + BOTH: + 2000-01-01: 0 + 2026-01-01: 1_166 + COUPLE_ONE_ELIGIBLE: + ONE: + 2000-01-01: 0 + 2026-01-01: 1_166 + BOTH: + 2000-01-01: 0 + 2026-01-01: 1_166 +CARETAKER: + INDIVIDUAL: + ONE: + 2000-01-01: 0 + 2026-01-01: 1_056 + BOTH: + 2000-01-01: 0 + 2026-01-01: 1_056 + # §9(1)(c): couple rates are reduced. Regulation states couple totals + # ($1,552 for one-care, $1,606 for both-care); stored here as per-person + # (total / 2) so the formula treats every category uniformly. + COUPLE_BOTH_ELIGIBLE: + ONE: + 2000-01-01: 0 + 2026-01-01: 776 + BOTH: + 2000-01-01: 0 + 2026-01-01: 803 + COUPLE_ONE_ELIGIBLE: + ONE: + 2000-01-01: 0 + 2026-01-01: 1_056 + BOTH: + 2000-01-01: 0 + 2026-01-01: 1_056 +NONE: + INDIVIDUAL: + ONE: + 2000-01-01: 0 + BOTH: + 2000-01-01: 0 + COUPLE_BOTH_ELIGIBLE: + ONE: + 2000-01-01: 0 + BOTH: + 2000-01-01: 0 + COUPLE_ONE_ELIGIBLE: + ONE: + 2000-01-01: 0 + BOTH: + 2000-01-01: 0 diff --git a/policyengine_us/parameters/gov/states/ky/dcbs/ssp/personal_needs_allowance/fch.yaml b/policyengine_us/parameters/gov/states/ky/dcbs/ssp/personal_needs_allowance/fch.yaml new file mode 100644 index 00000000000..939d39a38aa --- /dev/null +++ b/policyengine_us/parameters/gov/states/ky/dcbs/ssp/personal_needs_allowance/fch.yaml @@ -0,0 +1,14 @@ +description: Kentucky provides this amount as the personal needs allowance for Family Care Home residents under the State Supplementation program. +values: + 2000-01-01: 0 + 2026-01-01: 40 + +metadata: + unit: currency-USD + period: month + label: Kentucky SSP Family Care Home personal needs allowance + reference: + - title: 921 KAR 2:015 Section 9(4) + href: https://apps.legislature.ky.gov/law/kar/titles/921/002/015/ + - title: CHFS Division of Family Support Operation Manual, Volume V, MS 1200(C)(2) — Personal Needs Allowance + href: https://www.chfs.ky.gov/agencies/dcbs/dfs/Documents/OMVOLV.pdf#page=6 diff --git a/policyengine_us/parameters/gov/states/ky/dcbs/ssp/personal_needs_allowance/pch.yaml b/policyengine_us/parameters/gov/states/ky/dcbs/ssp/personal_needs_allowance/pch.yaml new file mode 100644 index 00000000000..9f626b94685 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ky/dcbs/ssp/personal_needs_allowance/pch.yaml @@ -0,0 +1,14 @@ +description: Kentucky provides this amount as the personal needs allowance for Personal Care Home residents under the State Supplementation program. +values: + 2000-01-01: 0 + 2026-01-01: 60 + +metadata: + unit: currency-USD + period: month + label: Kentucky SSP Personal Care Home personal needs allowance + reference: + - title: 921 KAR 2:015 Section 9(3) + href: https://apps.legislature.ky.gov/law/kar/titles/921/002/015/ + - title: CHFS Division of Family Support Operation Manual, Volume V, MS 1200(C)(1) — Personal Needs Allowance + href: https://www.chfs.ky.gov/agencies/dcbs/dfs/Documents/OMVOLV.pdf#page=6 diff --git a/policyengine_us/programs.yaml b/policyengine_us/programs.yaml index b4ffcdde3d1..9e40717ce2d 100644 --- a/policyengine_us/programs.yaml +++ b/policyengine_us/programs.yaml @@ -661,6 +661,11 @@ programs: name: Louisiana OSS full_name: Louisiana Optional State Supplement variable: la_oss + - state: KY + status: complete + name: Kentucky SSP + full_name: Kentucky State Supplementary Payment + variable: ky_ssp - state: IL status: complete name: Illinois AABD diff --git a/policyengine_us/tests/policy/baseline/gov/states/ky/dcbs/ssp/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/ky/dcbs/ssp/integration.yaml new file mode 100644 index 00000000000..1c3beba122a --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ky/dcbs/ssp/integration.yaml @@ -0,0 +1,602 @@ +# Integration tests for Kentucky State Supplementary Payment. +# Uses real income sources (social_security, employment_income) rather than +# injected SSI intermediates, so the federal SSI → state SSP chain is +# exercised end-to-end. Tests use MONTH period with monthly expected values. +# +# Key reference values (MS 1200, effective 1/1/2026, monthly): +# PCH standard: $1,610 +# CIS standard: $1,514 +# FCH standard: $1,166 +# Caretaker individual: $1,056 +# Caretaker couple, one receives care: $1,552 (per-person $776) +# Caretaker couple, both receive care: $1,606 (per-person $803) +# Federal SSI FBR (individual, 2026): $994 +# PCH PNA / FCH PNA: $60 / $40 + +- name: Case 1, aged PCH individual with SSI and Social Security. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + # Age ≥ 65 → is_ssi_aged auto-derives to true. + social_security: 9_600 # $800/mo unearned. + ky_ssp_category: PCH + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: KY + output: + # Federal SSI still applies the $20: $800 − $20 = $780/mo countable. + ssi_countable_income: [780] + # Federal SSI = FBR − countable = $994 − $780 = $214/mo. + ssi: [214] + is_ssi_eligible: [true] + ky_ssp_eligible: [true] + ky_ssp_payment_standard: [1_610] + # §8(8): KY uses gross $800 (no $20 deduction). + ky_ssp_countable_income: [800] + # §8(2): ky_ssp = max(0, $1,610 − $800) = $810/mo. + ky_ssp: [810] + +- name: Case 2, aged PCH individual with no income receives full PCH supplement. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + ky_ssp_category: PCH + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: KY + output: + ssi_countable_income: [0] + ssi: [994] + ky_ssp_eligible: [true] + ky_ssp_payment_standard: [1_610] + # §8(2): full PCH standard because countable income = 0. + ky_ssp: [1_610] + +- name: Case 3, Group 2 pathway — SSI-eligible but income above federal FBR. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + # $1,100/mo RSDI > federal SSI FBR ($994) but below PCH state + # standard ($1,610) → Group 2 pathway per §4(1)(b). + social_security: 13_200 + ky_ssp_category: PCH + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: KY + output: + # Federal: $1,100 − $20 = $1,080/mo countable. + ssi_countable_income: [1_080] + # Federal SSI = max(0, $994 − $1,080) = $0 → no SSI receipt. + ssi: [0] + # But still SSI-eligible categorically (ABD + resources) per §4(1)(a). + is_ssi_eligible: [true] + # §8(8): KY uses gross $1,100 (no $20 deduction). Below PCH standard. + ky_ssp_countable_income: [1_100] + ky_ssp_eligible: [true] + ky_ssp_payment_standard: [1_610] + # ky_ssp = max(0, $1,610 − $1,100) = $510/mo. + ky_ssp: [510] + +- name: Case 4, income above state standard fails §4(1)(b). + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + # $2,000/mo RSDI > PCH standard $1,610 → income-ineligible. + social_security: 24_000 + ky_ssp_category: PCH + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: KY + output: + # KY countable = gross $2,000/mo > PCH standard $1,610 → not eligible. + ky_ssp_countable_income: [2_000] + ky_ssp_eligible: [false] + ky_ssp: [0] + +- name: Case 5, SSI recipient with earned income uses $65+50% exclusion. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 68 + employment_income: 6_000 # $500/mo earned. + ky_ssp_category: CIS + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: KY + output: + # Federal: $20 general + $65 earned = $85, then 50% of remainder excluded. + # max(0, $500 − $85) × 0.5 = $207.50. + ssi_countable_income: [207.50] + # SSI = $994 − $207.50 = $786.50/mo. + ssi: [786.50] + # §8(8): KY skips the $20 general → only $65 earned + 50% applies. + # max(0, $500 − $65) × 0.5 = $217.50. + ky_ssp_countable_income: [217.50] + ky_ssp_eligible: [true] + ky_ssp_payment_standard: [1_514] + # ky_ssp = $1,514 − $217.50 = $1,296.50/mo. + ky_ssp: [1_296.50] + +- name: Case 6, eligible individual with ineligible spouse (Caretaker). + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 50 + is_ssi_disabled: true + ky_ssp_category: CARETAKER + person2: + # Non-ABD spouse is not SSI-eligible. + age: 45 + 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: KY + output: + # person1: SSI-eligible adult with ineligible spouse → COUPLE_ONE_ELIGIBLE. + # person2: not SSI-eligible → INDIVIDUAL default. + ky_ssp_claim_type: [COUPLE_ONE_ELIGIBLE, INDIVIDUAL] + # person1 uses Caretaker "individual with ineligible spouse" rate $1,056/mo. + # person2: not eligible, no supplement. + ky_ssp_payment_standard: [1_056, 0] + ky_ssp_eligible: [true, false] + ky_ssp: [1_056, 0] + +- name: Case 7, Caretaker couple — both SSI-eligible, both receive care. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 68 + ky_ssp_category: CARETAKER + ky_ssp_care_receivers: BOTH + person2: + age: 67 + ky_ssp_category: CARETAKER + ky_ssp_care_receivers: BOTH + 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: KY + output: + # Both SSI-eligible aged → COUPLE_BOTH_ELIGIBLE. + ky_ssp_claim_type: [COUPLE_BOTH_ELIGIBLE, COUPLE_BOTH_ELIGIBLE] + # Per-person standard $803/mo (half of $1,606 couple total). + ky_ssp_payment_standard: [803, 803] + ky_ssp_eligible: [true, true] + # Each: $803 − $0 = $803. Couple total = $1,606/mo. + ky_ssp: [803, 803] + +- name: Case 8, Caretaker couple — both SSI-eligible, only one receives care. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 68 + # Care receiver. + ky_ssp_category: CARETAKER + ky_ssp_care_receivers: ONE + person2: + age: 67 + ky_ssp_category: CARETAKER + ky_ssp_care_receivers: ONE + 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: KY + output: + ky_ssp_claim_type: [COUPLE_BOTH_ELIGIBLE, COUPLE_BOTH_ELIGIBLE] + # Per-person $776/mo (half of $1,552 couple total). + # Note: OMVOLV example #6 pays the full $1,552 to the care receiver only. + # This model distributes equally across both eligible spouses; household + # total matches the regulation ($1,552/mo). + ky_ssp_payment_standard: [776, 776] + ky_ssp_eligible: [true, true] + ky_ssp: [776, 776] + +- name: Case 9, minor fails §4(1)(c) age ≥ 18 requirement. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 10 + is_ssi_disabled: true + ky_ssp_category: PCH + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: KY + output: + # §4(1)(c) requires age ≥ 18 for all four categories. + ky_ssp_eligible: [false] + ky_ssp: [0] + +- name: Case 10, non-Kentucky resident receives no state supplement. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + ky_ssp_category: PCH + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: TN + output: + # defined_for = StateCode.KY → TN resident zeroed out. + ky_ssp: [0] + +- name: Case 11, SSI-eligible adult in NONE category is not SSP-eligible. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + # Lives in private home without caretaker/CIS → NONE (default). + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: KY + output: + # NONE category → fails §4(1)(c) in_qualifying_category test. + ky_ssp_eligible: [false] + ky_ssp: [0] + # Federal SSI still flows normally. + ssi: [994] + +- name: Case 12, FCH individual with zero income receives full FCH supplement. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 55 + is_ssi_disabled: true + ky_ssp_category: FCH + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: KY + output: + ky_ssp_eligible: [true] + ky_ssp_payment_standard: [1_166] + ky_ssp: [1_166] + # FCH PNA = $40/mo. + ky_ssp_personal_needs_allowance: [40] + +- name: Case 13, OMVOLV MS 1200 §C example — Bob, PCH with $900 RSDI. + # Reproduces the Personal Needs Allowance illustration on OMVOLV page 5: + # "Bob resides in a PCH. He receives RSDI of $900 a month. The PCH standard + # is $1,610. His State Supplementation payment is $710. Bob must pay the + # PCH $1,500 and he will keep $60." + # https://www.chfs.ky.gov/agencies/dcbs/dfs/Documents/OMVOLV.pdf#page=5 + # + # Demonstrates §8(8): the $20 SSI general exclusion is NOT applied. Federal + # SSI countable income = $900 − $20 = $880, but KY SSP uses gross $900, so + # SSP = $1,610 − $900 = $710 (not $730 with the federal exclusion). + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + social_security: 10_800 # $900/mo RSDI. + ky_ssp_category: PCH + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: KY + output: + # Federal SSI still applies the $20 exclusion: $900 − $20 = $880. + ssi_countable_income: [880] + # Federal SSI = $994 − $880 = $114/mo. + ssi: [114] + is_ssi_eligible: [true] + ky_ssp_eligible: [true] + ky_ssp_payment_standard: [1_610] + # §8(8): KY SSP uses gross $900, no $20 deduction → $1,610 − $900 = $710. + ky_ssp: [710] + # PCH PNA = $60/mo. + ky_ssp_personal_needs_allowance: [60] + +- name: Case 14, OMVOLV MS 1200 §B.2 example — Sue, CIS with $1,000 RSDI. + # "Sue receives $1,000 per month in Retirement, Survivors, Disability + # Insurance (RSDI) and lives in an apartment and receives CIS. Her State + # Supplementation payment is $514 ($1,514 - $1,000)." + # https://www.chfs.ky.gov/agencies/dcbs/dfs/Documents/OMVOLV.pdf#page=5 + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + social_security: 12_000 # $1,000/mo RSDI. + ky_ssp_category: CIS + marital_units: + marital_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: KY + output: + ky_ssp_eligible: [true] + ky_ssp_payment_standard: [1_514] + ky_ssp_countable_income: [1_000] + ky_ssp: [514] + +- name: Case 15, OMVOLV MS 1200 §B.5 example — Dan, Caretaker with ineligible spouse. + # "Dan is disabled and receives $855 per month in RSDI and receives + # Caretaker Services. His spouse, Joan, is not aged, blind, or disabled + # and has no income. His State Supplementation payment is $201 + # ($1,056 - $855)." + # https://www.chfs.ky.gov/agencies/dcbs/dfs/Documents/OMVOLV.pdf#page=5 + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 50 + is_ssi_disabled: true + social_security: 10_260 # $855/mo RSDI. + ky_ssp_category: CARETAKER + person2: + # Joan: not ABD → not SSI-eligible. + age: 45 + 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: KY + output: + ky_ssp_claim_type: [COUPLE_ONE_ELIGIBLE, INDIVIDUAL] + ky_ssp_payment_standard: [1_056, 0] + ky_ssp_countable_income: [855, 0] + ky_ssp_eligible: [true, false] + # $1,056 − $855 = $201. + ky_ssp: [201, 0] + +- name: Case 16, OMVOLV MS 1200 §B.6 example — Mark and Amy, Caretaker couple, one needs care. + # "Mark and Amy are disabled, and each receive RSDI in the amount of $600. + # However, only Mark requires care and receives Caretaker Services. His + # State Supplementation payment is $352 ($1,552 - $1,200 combined income)." + # https://www.chfs.ky.gov/agencies/dcbs/dfs/Documents/OMVOLV.pdf#page=5 + # The model splits the $1,552 standard equally ($776 per spouse) and the + # household total matches the regulation: 2 × $176 = $352. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 50 + is_ssi_disabled: true + social_security: 7_200 # $600/mo RSDI. + ky_ssp_category: CARETAKER + ky_ssp_care_receivers: ONE + person2: + age: 50 + is_ssi_disabled: true + social_security: 7_200 # $600/mo RSDI. + ky_ssp_category: CARETAKER + ky_ssp_care_receivers: ONE + 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: KY + output: + ky_ssp_claim_type: [COUPLE_BOTH_ELIGIBLE, COUPLE_BOTH_ELIGIBLE] + ky_ssp_payment_standard: [776, 776] + # SSI couple computation attributes combined ($1,200) /2 = $600 to each. + ky_ssp_countable_income: [600, 600] + ky_ssp_eligible: [true, true] + # Each: $776 − $600 = $176. Household total = $352, matching OMVOLV. + ky_ssp: [176, 176] + +- name: Case 17, OMVOLV MS 1200 §B.7 example — Charlie and Becky, Caretaker couple, both need care. + # "Charlie and Becky are both disabled and receive RSDI. They both require + # care and each receive Caretaker Services. The State Supplementation + # payment is $1,606 - $1,276 (combined income) = $330/2 (divided by 2 as + # they both require care) = $165 each." + # https://www.chfs.ky.gov/agencies/dcbs/dfs/Documents/OMVOLV.pdf#page=5 + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 50 + is_ssi_disabled: true + social_security: 7_656 # $638/mo RSDI. + ky_ssp_category: CARETAKER + ky_ssp_care_receivers: BOTH + person2: + age: 50 + is_ssi_disabled: true + social_security: 7_656 # $638/mo RSDI; combined = $1,276. + ky_ssp_category: CARETAKER + ky_ssp_care_receivers: BOTH + 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: KY + output: + ky_ssp_claim_type: [COUPLE_BOTH_ELIGIBLE, COUPLE_BOTH_ELIGIBLE] + ky_ssp_payment_standard: [803, 803] + # SSI couple computation attributes combined ($1,276) /2 = $638 to each. + ky_ssp_countable_income: [638, 638] + ky_ssp_eligible: [true, true] + # Each: $803 − $638 = $165. Matches OMVOLV exactly. + ky_ssp: [165, 165] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ky/dcbs/ssp/ky_ssp.yaml b/policyengine_us/tests/policy/baseline/gov/states/ky/dcbs/ssp/ky_ssp.yaml new file mode 100644 index 00000000000..88e350fe614 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ky/dcbs/ssp/ky_ssp.yaml @@ -0,0 +1,187 @@ +- name: Case 1, eligible PCH individual with zero income receives full standard. + period: 2026-01 + input: + state_code: KY + ky_ssp_eligible: true + # ky_ssp_countable_income is MONTH-period → monthly input. + ky_ssp_countable_income: 0 + # ky_ssp_payment_standard is MONTH-period → monthly input. + ky_ssp_payment_standard: 1_610 + output: + # supplement = max(0, 1_610 - 0) * eligible(1) = 1_610/mo. + ky_ssp: 1_610 + +- name: Case 2, small countable income reduces the supplement. + period: 2026-01 + input: + state_code: KY + ky_ssp_eligible: true + # $500/mo countable (MONTH-defined input). + ky_ssp_countable_income: 500 + ky_ssp_payment_standard: 1_610 + output: + # supplement = max(0, 1_610 - 500) = 1_110/mo. + ky_ssp: 1_110 + +- name: Case 3, moderate countable income reduces the supplement further. + period: 2026-01 + input: + state_code: KY + ky_ssp_eligible: true + # $1,000/mo countable. + ky_ssp_countable_income: 1_000 + ky_ssp_payment_standard: 1_610 + output: + # supplement = max(0, 1_610 - 1_000) = 610/mo. + ky_ssp: 610 + +- name: Case 4, countable income above the standard floors benefit at zero. + period: 2026-01 + input: + state_code: KY + ky_ssp_eligible: true + # $2,000/mo countable. + ky_ssp_countable_income: 2_000 + ky_ssp_payment_standard: 1_610 + output: + # supplement = max(0, 1_610 - 2_000) = 0. + ky_ssp: 0 + +- name: Case 5, ineligible individual gets zero benefit. + period: 2026-01 + input: + state_code: KY + ky_ssp_eligible: false + ky_ssp_countable_income: 0 + ky_ssp_payment_standard: 1_610 + output: + # Not eligible => supplement * 0 = 0. + ky_ssp: 0 + +- name: Case 6, extreme countable income does not inflate benefit. + period: 2026-01 + input: + state_code: KY + ky_ssp_eligible: true + # $5M/mo countable. + ky_ssp_countable_income: 5_000_000 + ky_ssp_payment_standard: 1_610 + output: + # supplement = max(0, 1_610 - 5_000_000) = 0. + ky_ssp: 0 + +- name: Case 7, countable income exactly equals the payment standard. + period: 2026-01 + input: + state_code: KY + ky_ssp_eligible: true + # $1,610/mo countable. + ky_ssp_countable_income: 1_610 + ky_ssp_payment_standard: 1_610 + output: + # supplement = max(0, 1_610 - 1_610) = 0. + ky_ssp: 0 + +- name: Case 8, both-eligible couple CARETAKER both-care pays per-person standard to each. + period: 2026-01 + input: + people: + person1: + ky_ssp_eligible: true + ky_ssp_countable_income: 0 + # CARETAKER.COUPLE_BOTH_ELIGIBLE.BOTH stored per-person at $803/mo. + # §9(2) combined income is already equally split into each spouse's + # ssi_countable_income, so the per-person formula reproduces the + # couple-total outcome. + ky_ssp_payment_standard: 803 + person2: + ky_ssp_eligible: true + ky_ssp_countable_income: 0 + ky_ssp_payment_standard: 803 + marital_units: + marital_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: KY + output: + # Each person: supplement = max(0, 803 - 0) * 1 = 803/mo. + # Couple total = 2 * 803 = $1,606/mo (matches §9(1)(c) couple rate). + ky_ssp: [803, 803] + +- name: Case 9, both-eligible couple CARETAKER one-care pays per-person standard to each. + period: 2026-01 + input: + people: + person1: + ky_ssp_eligible: true + ky_ssp_countable_income: 0 + # CARETAKER.COUPLE_BOTH_ELIGIBLE.ONE stored per-person at $776/mo. + ky_ssp_payment_standard: 776 + person2: + ky_ssp_eligible: true + ky_ssp_countable_income: 0 + ky_ssp_payment_standard: 776 + marital_units: + marital_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: KY + output: + # Each person: supplement = max(0, 776 - 0) * 1 = 776/mo. + # Couple total = 2 * 776 = $1,552/mo. + ky_ssp: [776, 776] + +- name: Case 10, countable income one dollar below standard leaves one dollar supplement. + period: 2026-01 + input: + state_code: KY + ky_ssp_eligible: true + # $1,609/mo countable. + ky_ssp_countable_income: 1_609 + ky_ssp_payment_standard: 1_610 + output: + # supplement = max(0, 1_610 - 1_609) = 1/mo. + ky_ssp: 1 + +- name: Case 11, countable income one dollar above standard floors benefit at zero. + period: 2026-01 + input: + state_code: KY + ky_ssp_eligible: true + # $1,611/mo countable. + ky_ssp_countable_income: 1_611 + ky_ssp_payment_standard: 1_610 + output: + # supplement = max(0, 1_610 - 1_611) = 0. + ky_ssp: 0 + +- name: Case 12, one SSP-eligible + one ineligible spouse receives individual benefit. + period: 2026-01 + input: + people: + person1: + ky_ssp_eligible: true + ky_ssp_countable_income: 0 + ky_ssp_payment_standard: 1_610 + person2: + # Spouse is not SSP-eligible (e.g., fails resource test or not in + # qualifying category). + ky_ssp_eligible: false + ky_ssp_countable_income: 0 + ky_ssp_payment_standard: 1_610 + marital_units: + marital_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: KY + output: + # Eligible spouse receives full individual benefit; ineligible spouse + # receives nothing. §9(2) couple combining applies only "if both are + # eligible" — here only person1 is SSP-eligible. + ky_ssp: [1_610, 0] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ky/dcbs/ssp/ky_ssp_claim_type.yaml b/policyengine_us/tests/policy/baseline/gov/states/ky/dcbs/ssp/ky_ssp_claim_type.yaml new file mode 100644 index 00000000000..568acb1b1ac --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ky/dcbs/ssp/ky_ssp_claim_type.yaml @@ -0,0 +1,170 @@ +- name: Case 1, single SSI-eligible individual in qualifying category. + period: 2026-01 + input: + people: + person1: + age: 70 + is_ssi_aged_blind_disabled: true + meets_ssi_resource_test: true + ky_ssp_category: PCH + households: + household: + members: [person1] + state_code: KY + marital_units: + marital_unit: + members: [person1] + output: + # Solo marital unit => INDIVIDUAL. + ky_ssp_claim_type: [INDIVIDUAL] + +- name: Case 2, couple with both SSP-eligible. + period: 2026-01 + input: + people: + person1: + age: 70 + is_ssi_aged_blind_disabled: true + meets_ssi_resource_test: true + ky_ssp_category: CARETAKER + person2: + age: 68 + is_ssi_aged_blind_disabled: true + meets_ssi_resource_test: true + ky_ssp_category: CARETAKER + households: + household: + members: [person1, person2] + state_code: KY + marital_units: + marital_unit: + members: [person1, person2] + output: + # Both SSI-eligible, both adults, both in qualifying category + # => COUPLE_BOTH_ELIGIBLE for each. + ky_ssp_claim_type: [COUPLE_BOTH_ELIGIBLE, COUPLE_BOTH_ELIGIBLE] + +- name: Case 3, eligible spouse with ABD but resource-ineligible spouse uses individual rate. + period: 2026-01 + input: + people: + person1: + age: 70 + is_ssi_aged_blind_disabled: true + meets_ssi_resource_test: true + ky_ssp_category: CARETAKER + person2: + age: 68 + is_ssi_aged_blind_disabled: true + # Spouse is ABD but fails resource test => not SSI-eligible. + meets_ssi_resource_test: false + ky_ssp_category: CARETAKER + households: + household: + members: [person1, person2] + state_code: KY + marital_units: + marital_unit: + members: [person1, person2] + output: + # §9(1)(c)1 — couple rates require both SSP-eligible. With only one + # SSI-eligible spouse, eligible spouse uses COUPLE_ONE_ELIGIBLE (individual + # rate); ineligible spouse falls through to default INDIVIDUAL. + ky_ssp_claim_type: [COUPLE_ONE_ELIGIBLE, INDIVIDUAL] + +- name: Case 4, eligible individual with non-ABD spouse uses one-eligible-couple. + period: 2026-01 + input: + people: + person1: + age: 70 + is_ssi_aged_blind_disabled: true + meets_ssi_resource_test: true + ky_ssp_category: CARETAKER + person2: + age: 68 + is_ssi_aged_blind_disabled: false + households: + household: + members: [person1, person2] + state_code: KY + marital_units: + marital_unit: + members: [person1, person2] + output: + # person1 eligible, person2 non-ABD ineligible => COUPLE_ONE_ELIGIBLE / INDIVIDUAL. + ky_ssp_claim_type: [COUPLE_ONE_ELIGIBLE, INDIVIDUAL] + +- name: Case 5, unmarried solo person is INDIVIDUAL. + period: 2026-01 + input: + people: + person1: + age: 45 + is_ssi_aged_blind_disabled: true + meets_ssi_resource_test: true + ky_ssp_category: PCH + households: + household: + members: [person1] + state_code: KY + marital_units: + marital_unit: + members: [person1] + output: + ky_ssp_claim_type: [INDIVIDUAL] + +- name: Case 6, SSI-eligible couple where only one spouse is in an SSP-qualifying category. + period: 2026-01 + input: + people: + person1: + age: 70 + is_ssi_aged_blind_disabled: true + meets_ssi_resource_test: true + ky_ssp_category: CARETAKER + person2: + age: 68 + is_ssi_aged_blind_disabled: true + meets_ssi_resource_test: true + # Not in any qualifying SSP category (defaults to NONE). + households: + household: + members: [person1, person2] + state_code: KY + marital_units: + marital_unit: + members: [person1, person2] + output: + # §9(1)(c) couple rates require both spouses to be SSP-eligible. person2 + # is SSI-eligible but in NONE category, so not SSP-eligible. person1 is + # treated as an eligible individual with an ineligible-for-SSP spouse + # (COUPLE_ONE_ELIGIBLE). person2 defaults to INDIVIDUAL and receives no + # SSP payment standard. + ky_ssp_claim_type: [COUPLE_ONE_ELIGIBLE, INDIVIDUAL] + +- name: Case 7, SSI-eligible minor with SSI-eligible adult spouse — minor fails §4(1)(c) age test. + period: 2026-01 + input: + people: + person1: + age: 50 + is_ssi_aged_blind_disabled: true + meets_ssi_resource_test: true + ky_ssp_category: CARETAKER + person2: + age: 17 + is_ssi_aged_blind_disabled: true + meets_ssi_resource_test: true + ky_ssp_category: CARETAKER + households: + household: + members: [person1, person2] + state_code: KY + marital_units: + marital_unit: + members: [person1, person2] + output: + # §4(1)(c) requires age ≥ 18 for SSP. Minor spouse fails SSP age test + # even though SSI-eligible, so couple pair is not "both SSP-eligible". + ky_ssp_claim_type: [COUPLE_ONE_ELIGIBLE, INDIVIDUAL] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ky/dcbs/ssp/ky_ssp_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ky/dcbs/ssp/ky_ssp_countable_income.yaml new file mode 100644 index 00000000000..bc994517b8e --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ky/dcbs/ssp/ky_ssp_countable_income.yaml @@ -0,0 +1,73 @@ +- name: Case 1, single person with unearned income — no $20 deduction. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + social_security: 12_000 # $1,000/mo unearned. + marital_units: + marital_unit: + members: [person1] + households: + household: + members: [person1] + state_code: KY + output: + # §8(8): no $20 general exclusion → full $1,000 counted. + ky_ssp_countable_income: [1_000] + +- name: Case 2, single person with earned income — $65 + 50% still apply. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + employment_income: 6_000 # $500/mo earned. + marital_units: + marital_unit: + members: [person1] + households: + household: + members: [person1] + state_code: KY + output: + # max(0, $500 − $65) × 0.5 = $217.50. + ky_ssp_countable_income: [217.50] + +- name: Case 3, no income. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + marital_units: + marital_unit: + members: [person1] + households: + household: + members: [person1] + state_code: KY + output: + ky_ssp_countable_income: [0] + +- name: Case 4, ineligible person — countable income is zero. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + social_security: 12_000 + # Not aged/blind/disabled → not SSI-eligible. + marital_units: + marital_unit: + members: [person1] + households: + household: + members: [person1] + state_code: KY + output: + ky_ssp_countable_income: [0] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ky/dcbs/ssp/ky_ssp_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ky/dcbs/ssp/ky_ssp_eligible.yaml new file mode 100644 index 00000000000..d1c1eb5866c --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ky/dcbs/ssp/ky_ssp_eligible.yaml @@ -0,0 +1,186 @@ +- name: Case 1, SSI-eligible aged adult in PCH is eligible. + period: 2026-01 + input: + people: + person1: + age: 70 + is_ssi_aged_blind_disabled: true + is_ssi_eligible: true + meets_ssi_resource_test: true + ky_ssp_countable_income: 0 + ky_ssp_category: PCH + households: + household: + members: [person1] + state_code: KY + output: + ky_ssp_eligible: [true] + +- name: Case 2, SSI-eligible adult with NONE category is not eligible. + period: 2026-01 + input: + people: + person1: + age: 70 + is_ssi_aged_blind_disabled: true + is_ssi_eligible: true + meets_ssi_resource_test: true + ky_ssp_countable_income: 0 + ky_ssp_category: NONE + households: + household: + members: [person1] + state_code: KY + output: + # Category NONE => not in a qualifying category => not eligible. + ky_ssp_eligible: [false] + +- name: Case 3, not SSI-eligible with PCH category is not eligible. + period: 2026-01 + input: + people: + person1: + age: 70 + is_ssi_aged_blind_disabled: false + is_ssi_eligible: false + meets_ssi_resource_test: true + ky_ssp_countable_income: 0 + ky_ssp_category: PCH + households: + household: + members: [person1] + state_code: KY + output: + # Fails is_ssi_eligible => not eligible. + ky_ssp_eligible: [false] + +- name: Case 4, SSI-eligible minor in CARETAKER fails §4(1)(c)3 age ≥ 18 requirement. + period: 2026-01 + input: + people: + person1: + age: 8 + is_ssi_aged_blind_disabled: true + is_ssi_eligible: true + meets_ssi_resource_test: true + ky_ssp_countable_income: 0 + ky_ssp_category: CARETAKER + households: + household: + members: [person1] + state_code: KY + output: + # 921 KAR 2:015 §4(1)(c)3 requires caretaker recipients to be at least 18. + ky_ssp_eligible: [false] + +- name: Case 5, SSI-eligible adult in FCH is eligible. + period: 2026-01 + input: + people: + person1: + age: 55 + is_ssi_aged_blind_disabled: true + is_ssi_eligible: true + meets_ssi_resource_test: true + ky_ssp_countable_income: 0 + ky_ssp_category: FCH + households: + household: + members: [person1] + state_code: KY + output: + ky_ssp_eligible: [true] + +- name: Case 6, SSI-eligible adult in CIS is eligible. + period: 2026-01 + input: + people: + person1: + age: 50 + is_ssi_aged_blind_disabled: true + is_ssi_eligible: true + meets_ssi_resource_test: true + ky_ssp_countable_income: 0 + ky_ssp_category: CIS + households: + household: + members: [person1] + state_code: KY + output: + ky_ssp_eligible: [true] + +- name: Case 7, fails resource test so not SSI-eligible and not SSP-eligible. + period: 2026-01 + input: + people: + person1: + age: 70 + is_ssi_aged_blind_disabled: true + is_ssi_eligible: false + meets_ssi_resource_test: false + ky_ssp_countable_income: 0 + ky_ssp_category: PCH + households: + household: + members: [person1] + state_code: KY + output: + ky_ssp_eligible: [false] + +- name: Case 8, countable income below PCH standard is eligible. + period: 2026-01 + input: + people: + person1: + age: 70 + is_ssi_aged_blind_disabled: true + is_ssi_eligible: true + meets_ssi_resource_test: true + # Countable income ($994/mo) is below the PCH monthly standard + # ($1,610) so §4(1)(b) is satisfied. + ky_ssp_countable_income: 994 + ky_ssp_category: PCH + households: + household: + members: [person1] + state_code: KY + output: + ky_ssp_eligible: [true] + +- name: Case 9, countable income above the PCH standard fails §4(1)(b). + period: 2026-01 + input: + people: + person1: + age: 70 + is_ssi_aged_blind_disabled: true + is_ssi_eligible: true + meets_ssi_resource_test: true + # Countable income ($4,167/mo) exceeds PCH standard ($1,610) — not eligible. + ky_ssp_countable_income: 4_167 + ky_ssp_category: PCH + households: + household: + members: [person1] + state_code: KY + output: + ky_ssp_eligible: [false] + +- name: Case 10, SSI-eligible minor in PCH fails §4(1)(c)1 age ≥ 18 requirement. + period: 2026-01 + input: + people: + person1: + age: 10 + is_ssi_aged_blind_disabled: true + is_ssi_eligible: true + meets_ssi_resource_test: true + ky_ssp_countable_income: 0 + ky_ssp_category: PCH + households: + household: + members: [person1] + state_code: KY + output: + # 921 KAR 2:015 §4(1)(c)1 requires PCH residents to be at least 18. + ky_ssp_eligible: [false] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ky/dcbs/ssp/ky_ssp_payment_standard.yaml b/policyengine_us/tests/policy/baseline/gov/states/ky/dcbs/ssp/ky_ssp_payment_standard.yaml new file mode 100644 index 00000000000..05c240a8e84 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ky/dcbs/ssp/ky_ssp_payment_standard.yaml @@ -0,0 +1,154 @@ +- name: Case 1, PCH individual. + period: 2026-01 + input: + state_code: KY + ky_ssp_category: PCH + ky_ssp_claim_type: INDIVIDUAL + ky_ssp_care_receivers: ONE + output: + # PCH.INDIVIDUAL.ONE = $1,610/mo + ky_ssp_payment_standard: 1_610 + +- name: Case 2, CIS individual. + period: 2026-01 + input: + state_code: KY + ky_ssp_category: CIS + ky_ssp_claim_type: INDIVIDUAL + ky_ssp_care_receivers: ONE + output: + # CIS.INDIVIDUAL.ONE = $1,514/mo + ky_ssp_payment_standard: 1_514 + +- name: Case 3, FCH individual. + period: 2026-01 + input: + state_code: KY + ky_ssp_category: FCH + ky_ssp_claim_type: INDIVIDUAL + ky_ssp_care_receivers: ONE + output: + # FCH.INDIVIDUAL.ONE = $1,166/mo + ky_ssp_payment_standard: 1_166 + +- name: Case 4, Caretaker individual. + period: 2026-01 + input: + state_code: KY + ky_ssp_category: CARETAKER + ky_ssp_claim_type: INDIVIDUAL + ky_ssp_care_receivers: ONE + output: + # CARETAKER.INDIVIDUAL.ONE = $1,056/mo + ky_ssp_payment_standard: 1_056 + +- name: Case 5, Caretaker couple both eligible, one receives care. + period: 2026-01 + input: + state_code: KY + ky_ssp_category: CARETAKER + ky_ssp_claim_type: COUPLE_BOTH_ELIGIBLE + ky_ssp_care_receivers: ONE + output: + # §9(1)(c) couple total $1,552/mo stored per-person as $776/mo. + ky_ssp_payment_standard: 776 + +- name: Case 6, Caretaker couple both eligible, both receive care. + period: 2026-01 + input: + state_code: KY + ky_ssp_category: CARETAKER + ky_ssp_claim_type: COUPLE_BOTH_ELIGIBLE + ky_ssp_care_receivers: BOTH + output: + # §9(1)(c) couple total $1,606/mo stored per-person as $803/mo. + ky_ssp_payment_standard: 803 + +- name: Case 7, Caretaker couple one eligible with ineligible spouse (individual rate). + period: 2026-01 + input: + state_code: KY + ky_ssp_category: CARETAKER + ky_ssp_claim_type: COUPLE_ONE_ELIGIBLE + ky_ssp_care_receivers: ONE + output: + # §9(1)(c)1: eligible spouse with ineligible spouse uses individual rate. + # CARETAKER.COUPLE_ONE_ELIGIBLE.ONE = $1,056/mo. + ky_ssp_payment_standard: 1_056 + +- name: Case 8, PCH couple both eligible — each uses full individual per-person rate. + period: 2026-01 + input: + state_code: KY + ky_ssp_category: PCH + ky_ssp_claim_type: COUPLE_BOTH_ELIGIBLE + ky_ssp_care_receivers: ONE + output: + # PCH has no reduced couple rate (§9(1)(a)); each person's standard is + # the individual rate. $1,610/mo per person. + ky_ssp_payment_standard: 1_610 + +- name: Case 9, NONE category returns zero payment standard. + period: 2026-01 + input: + state_code: KY + ky_ssp_category: NONE + ky_ssp_claim_type: INDIVIDUAL + ky_ssp_care_receivers: ONE + output: + ky_ssp_payment_standard: 0 + +- name: Case 10, CIS couple both eligible — each uses full individual per-person rate. + period: 2026-01 + input: + state_code: KY + ky_ssp_category: CIS + ky_ssp_claim_type: COUPLE_BOTH_ELIGIBLE + ky_ssp_care_receivers: ONE + output: + # CIS has no reduced couple rate (§9(1)(d)). Per-person $1,514/mo. + ky_ssp_payment_standard: 1_514 + +- name: Case 11, FCH couple both eligible — each uses full individual per-person rate. + period: 2026-01 + input: + state_code: KY + ky_ssp_category: FCH + ky_ssp_claim_type: COUPLE_BOTH_ELIGIBLE + ky_ssp_care_receivers: ONE + output: + # FCH has no reduced couple rate (§9(1)(b)). Per-person $1,166/mo. + ky_ssp_payment_standard: 1_166 + +- name: Case 12, PCH couple one eligible (individual rate). + period: 2026-01 + input: + state_code: KY + ky_ssp_category: PCH + ky_ssp_claim_type: COUPLE_ONE_ELIGIBLE + ky_ssp_care_receivers: ONE + output: + # PCH.COUPLE_ONE_ELIGIBLE.ONE = $1,610/mo. + ky_ssp_payment_standard: 1_610 + +- name: Case 13, Caretaker couple one eligible, care_receivers=BOTH (unused dimension). + period: 2026-01 + input: + state_code: KY + ky_ssp_category: CARETAKER + ky_ssp_claim_type: COUPLE_ONE_ELIGIBLE + ky_ssp_care_receivers: BOTH + output: + # CARETAKER.COUPLE_ONE_ELIGIBLE.BOTH = $1,056/mo. + ky_ssp_payment_standard: 1_056 + +- name: Case 14, PCH care_receivers=BOTH individual (dimension unused for non-Caretaker). + period: 2026-01 + input: + state_code: KY + ky_ssp_category: PCH + ky_ssp_claim_type: INDIVIDUAL + ky_ssp_care_receivers: BOTH + output: + # PCH.INDIVIDUAL.BOTH = $1,610/mo (same as ONE — dimension unused for PCH). + ky_ssp_payment_standard: 1_610 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ky/dcbs/ssp/ky_ssp_personal_needs_allowance.yaml b/policyengine_us/tests/policy/baseline/gov/states/ky/dcbs/ssp/ky_ssp_personal_needs_allowance.yaml new file mode 100644 index 00000000000..1ca99ee80be --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ky/dcbs/ssp/ky_ssp_personal_needs_allowance.yaml @@ -0,0 +1,108 @@ +- name: Case 1, PCH resident receives PCH personal needs allowance. + period: 2026-01 + input: + people: + person1: + age: 70 + is_ssi_aged_blind_disabled: true + is_ssi_eligible: true + meets_ssi_resource_test: true + ky_ssp_category: PCH + households: + household: + members: [person1] + state_code: KY + output: + # PCH PNA = $60/mo. + ky_ssp_personal_needs_allowance: [60] + +- name: Case 2, FCH resident receives FCH personal needs allowance. + period: 2026-01 + input: + people: + person1: + age: 65 + is_ssi_aged_blind_disabled: true + is_ssi_eligible: true + meets_ssi_resource_test: true + ky_ssp_category: FCH + households: + household: + members: [person1] + state_code: KY + output: + # FCH PNA = $40/mo. + ky_ssp_personal_needs_allowance: [40] + +- name: Case 3, CIS resident receives no personal needs allowance. + period: 2026-01 + input: + people: + person1: + age: 50 + is_ssi_aged_blind_disabled: true + is_ssi_eligible: true + meets_ssi_resource_test: true + ky_ssp_category: CIS + households: + household: + members: [person1] + state_code: KY + output: + # CIS category => no PNA applies. + ky_ssp_personal_needs_allowance: [0] + +- name: Case 4, Caretaker resident receives no personal needs allowance. + period: 2026-01 + input: + people: + person1: + age: 40 + is_ssi_aged_blind_disabled: true + is_ssi_eligible: true + meets_ssi_resource_test: true + ky_ssp_category: CARETAKER + households: + household: + members: [person1] + state_code: KY + output: + # CARETAKER category => no PNA applies. + ky_ssp_personal_needs_allowance: [0] + +- name: Case 5, NONE category receives no personal needs allowance. + period: 2026-01 + input: + people: + person1: + age: 30 + is_ssi_aged_blind_disabled: true + is_ssi_eligible: true + meets_ssi_resource_test: true + ky_ssp_category: NONE + households: + household: + members: [person1] + state_code: KY + output: + ky_ssp_personal_needs_allowance: [0] + +- name: Case 6, ineligible PCH resident (minor) receives no personal needs allowance. + period: 2026-01 + input: + people: + person1: + age: 10 + is_ssi_aged_blind_disabled: true + is_ssi_eligible: true + meets_ssi_resource_test: true + ky_ssp_category: PCH + households: + household: + members: [person1] + state_code: KY + output: + # §4(1)(c) requires age ≥ 18 => ky_ssp_eligible is false => no SSP + # payment => no PNA to retain. + ky_ssp_eligible: [false] + ky_ssp_personal_needs_allowance: [0] diff --git a/policyengine_us/variables/gov/states/ky/dcbs/ssp/ky_ssp.py b/policyengine_us/variables/gov/states/ky/dcbs/ssp/ky_ssp.py new file mode 100644 index 00000000000..0ddeac07a32 --- /dev/null +++ b/policyengine_us/variables/gov/states/ky/dcbs/ssp/ky_ssp.py @@ -0,0 +1,38 @@ +from policyengine_us.model_api import * + + +class ky_ssp(Variable): + value_type = float + entity = Person + label = "Kentucky State Supplementary Payment" + unit = USD + definition_period = MONTH + defined_for = StateCode.KY + exhaustive_parameter_dependencies = "gov.states.ky.dcbs.ssp" + reference = ( + "https://apps.legislature.ky.gov/law/kar/titles/921/002/015/", + "https://apps.legislature.ky.gov/law/statutes/statute.aspx?id=7671", + "https://www.chfs.ky.gov/agencies/dcbs/dfs/Documents/OMVOLV.pdf#page=5", + ) + + def formula(person, period, parameters): + # §8(2): supplement = max(0, standard_of_need − countable_income). + # ky_ssp_countable_income mirrors federal SSI countable income but + # omits the $20 general exclusion per §8(8). + # + # For eligible joint couples (§9(2)), SSI already attributes combined + # income equally to each spouse via ssi_marital_{earned,unearned}_income, + # and per-person standards stored in payment_standard (half of couple + # totals for CARETAKER) reproduce the §9(2)(b) "one-half of the + # deficit to each" outcome without explicit marital_unit averaging. + # + # APPROXIMATION: Per OMVOLV examples, the Caretaker "Eligible Couple, + # One Receives Care" standard ($1,552) is paid entirely to the care + # receiver (per MS 1200 §B.6). This model stores that standard as + # per-person ($776) and pays each spouse an equal share. The household + # total matches the regulation exactly; only the per-spouse split + # differs. + payment_standard = person("ky_ssp_payment_standard", period) + countable_income = person("ky_ssp_countable_income", period) + eligible = person("ky_ssp_eligible", period) + return max_(0, payment_standard - countable_income) * eligible diff --git a/policyengine_us/variables/gov/states/ky/dcbs/ssp/ky_ssp_care_receivers.py b/policyengine_us/variables/gov/states/ky/dcbs/ssp/ky_ssp_care_receivers.py new file mode 100644 index 00000000000..4f355f19d2d --- /dev/null +++ b/policyengine_us/variables/gov/states/ky/dcbs/ssp/ky_ssp_care_receivers.py @@ -0,0 +1,20 @@ +from policyengine_us.model_api import * + + +class KYSSPCareReceivers(Enum): + ONE = "One spouse receives care" + BOTH = "Both spouses receive care" + + +class ky_ssp_care_receivers(Variable): + value_type = Enum + entity = Person + label = "Kentucky SSP caretaker couple care receivers" + definition_period = MONTH + defined_for = StateCode.KY + possible_values = KYSSPCareReceivers + default_value = KYSSPCareReceivers.ONE + reference = ( + "https://apps.legislature.ky.gov/law/kar/titles/921/002/015/", + "https://www.chfs.ky.gov/agencies/dcbs/dfs/Documents/OMVOLV.pdf#page=5", + ) diff --git a/policyengine_us/variables/gov/states/ky/dcbs/ssp/ky_ssp_category.py b/policyengine_us/variables/gov/states/ky/dcbs/ssp/ky_ssp_category.py new file mode 100644 index 00000000000..7cd0cd12db7 --- /dev/null +++ b/policyengine_us/variables/gov/states/ky/dcbs/ssp/ky_ssp_category.py @@ -0,0 +1,23 @@ +from policyengine_us.model_api import * + + +class KYSSPCategory(Enum): + PCH = "Personal Care Home" + CIS = "Community Integration Supplementation" + FCH = "Family Care Home" + CARETAKER = "Caretaker Services" + NONE = "None" + + +class ky_ssp_category(Variable): + value_type = Enum + entity = Person + label = "Kentucky SSP category" + definition_period = MONTH + defined_for = StateCode.KY + possible_values = KYSSPCategory + default_value = KYSSPCategory.NONE + reference = ( + "https://apps.legislature.ky.gov/law/kar/titles/921/002/015/", + "https://www.chfs.ky.gov/agencies/dcbs/dfs/Documents/OMVOLV.pdf#page=23", + ) diff --git a/policyengine_us/variables/gov/states/ky/dcbs/ssp/ky_ssp_claim_type.py b/policyengine_us/variables/gov/states/ky/dcbs/ssp/ky_ssp_claim_type.py new file mode 100644 index 00000000000..6f67eb9df34 --- /dev/null +++ b/policyengine_us/variables/gov/states/ky/dcbs/ssp/ky_ssp_claim_type.py @@ -0,0 +1,50 @@ +from policyengine_us.model_api import * + + +class KYSSPClaimType(Enum): + INDIVIDUAL = "Individual" + COUPLE_BOTH_ELIGIBLE = "Couple, both eligible" + COUPLE_ONE_ELIGIBLE = "Couple, one eligible with ineligible spouse" + + +class ky_ssp_claim_type(Variable): + value_type = Enum + entity = Person + label = "Kentucky SSP claim type" + definition_period = MONTH + defined_for = StateCode.KY + possible_values = KYSSPClaimType + default_value = KYSSPClaimType.INDIVIDUAL + reference = ( + "https://apps.legislature.ky.gov/law/kar/titles/921/002/015/", + "https://www.chfs.ky.gov/agencies/dcbs/dfs/Documents/OMVOLV.pdf#page=41", + ) + + def formula(person, period, parameters): + # §9(1)(c) couple rates apply to an "eligible couple" — both spouses + # must qualify for SSP itself, not merely for SSI. The §4(1) SSP + # categorical tests (SSI-eligible + age ≥ 18 + qualifying living + # arrangement) are applied here. The §4(1)(b) income test is + # intentionally excluded to avoid a cycle through + # ky_ssp_payment_standard → ky_ssp_claim_type. + is_ssi_eligible = person("is_ssi_eligible", period) + is_adult = person("is_adult", period) + category = person("ky_ssp_category", period) + in_qualifying_category = category != category.possible_values.NONE + ssp_categorically_eligible = is_ssi_eligible & is_adult & in_qualifying_category + eligible_count = person.marital_unit.sum(ssp_categorically_eligible) + marital_unit_size = person.marital_unit.nb_persons() + both_eligible = (eligible_count == 2) & ssp_categorically_eligible + one_eligible_couple = ( + (eligible_count == 1) + & ssp_categorically_eligible + & (marital_unit_size == 2) + ) + return select( + [both_eligible, one_eligible_couple], + [ + KYSSPClaimType.COUPLE_BOTH_ELIGIBLE, + KYSSPClaimType.COUPLE_ONE_ELIGIBLE, + ], + default=KYSSPClaimType.INDIVIDUAL, + ) 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 new file mode 100644 index 00000000000..eb2954a2282 --- /dev/null +++ b/policyengine_us/variables/gov/states/ky/dcbs/ssp/ky_ssp_countable_income.py @@ -0,0 +1,51 @@ +from policyengine_us.model_api import * + + +class ky_ssp_countable_income(Variable): + value_type = float + entity = Person + label = "Kentucky SSP countable income" + unit = USD + definition_period = MONTH + defined_for = StateCode.KY + reference = ( + # 921 KAR 2:015 §8(8): "The SSI twenty (20) dollar general exclusion + # shall not be an allowable deduction from income." + "https://apps.legislature.ky.gov/law/kar/titles/921/002/015/", + # OMVOLV MS 2300: "The $20 general exclusion from unearned income and + # deductions for medical expenses are not allowed in State + # Supplementation." + "https://www.chfs.ky.gov/agencies/dcbs/dfs/Documents/OMVOLV.pdf#page=5", + ) + + def formula(person, period, parameters): + # Mirror ssi_countable_income but skip the $20 general exclusion per + # §8(8). The $65 earned exclusion and 50% earned share still apply. + earned = max_( + person("ssi_marital_earned_income", period) + - person("ssi_blind_or_disabled_working_student_exclusion", period), + 0, + ) + unearned = ( + person("ssi_marital_unearned_income", period) + + person("ssi_unearned_income_deemed_from_ineligible_parent", period) + + person("ssi_in_kind_support_and_maintenance", period) + ) + p = parameters(period).gov.ssa.ssi.income.exclusions + countable_earned = max_(earned - p.earned, 0) * (1 - p.earned_share) + personal_countable = unearned + countable_earned + + both_eligible = person("ssi_couple_computation_applies", period.this_year) + 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 + ) + return where( + ~is_eligible, + 0, + where( + both_eligible, + personal_countable / 2, + personal_countable + spousal_deemed, + ), + ) diff --git a/policyengine_us/variables/gov/states/ky/dcbs/ssp/ky_ssp_eligible.py b/policyengine_us/variables/gov/states/ky/dcbs/ssp/ky_ssp_eligible.py new file mode 100644 index 00000000000..1aeaa5ae30b --- /dev/null +++ b/policyengine_us/variables/gov/states/ky/dcbs/ssp/ky_ssp_eligible.py @@ -0,0 +1,39 @@ +from policyengine_us.model_api import * + + +class ky_ssp_eligible(Variable): + value_type = bool + entity = Person + label = "Eligible for Kentucky State Supplementary Payment" + definition_period = MONTH + defined_for = StateCode.KY + reference = ( + "https://apps.legislature.ky.gov/law/kar/titles/921/002/015/", + "https://apps.legislature.ky.gov/law/statutes/statute.aspx?id=7671", + ) + + def formula(person, period, parameters): + # 921 KAR 2:015 §4(1) — Group 2 pathway. An eligible individual must + # meet SSI categorical criteria (ABD, resources, immigration) and + # have income below the state standard. Actual SSI receipt is NOT + # required: §4(1)(b) only requires "insufficient income to meet the + # payment standards established in Section 9". §3(3) makes SSI + # application mandatory if potentially eligible, but non-receipt + # with income below the state standard still qualifies. + categorically_eligible = person("is_ssi_eligible", period) + # §4(1)(c): age ≥ 18 required for all four categories (PCH, CIS, FCH, + # Caretaker). + is_adult = person("is_adult", period) + category = person("ky_ssp_category", period) + in_qualifying_category = category != category.possible_values.NONE + # §4(1)(b): insufficient income to meet the standard in §9. Uses + # ky_ssp_countable_income (no $20 general exclusion per §8(8)). + countable_income = person("ky_ssp_countable_income", period) + payment_standard = person("ky_ssp_payment_standard", period) + income_below_standard = countable_income < payment_standard + return ( + categorically_eligible + & is_adult + & in_qualifying_category + & income_below_standard + ) diff --git a/policyengine_us/variables/gov/states/ky/dcbs/ssp/ky_ssp_payment_standard.py b/policyengine_us/variables/gov/states/ky/dcbs/ssp/ky_ssp_payment_standard.py new file mode 100644 index 00000000000..546aa79bb72 --- /dev/null +++ b/policyengine_us/variables/gov/states/ky/dcbs/ssp/ky_ssp_payment_standard.py @@ -0,0 +1,24 @@ +from policyengine_us.model_api import * + + +class ky_ssp_payment_standard(Variable): + value_type = float + entity = Person + label = "Kentucky SSP payment standard" + unit = USD + definition_period = MONTH + defined_for = StateCode.KY + reference = ( + "https://apps.legislature.ky.gov/law/kar/titles/921/002/015/", + "https://www.chfs.ky.gov/agencies/dcbs/dfs/Documents/OMVOLV.pdf#page=5", + ) + + def formula(person, period, parameters): + # 921 KAR 2:015 §9: per-person standard of need by category, claim + # type, and (for CARETAKER) whether one or both spouses receive care. + # Parameter stores per-person values — see payment_standard.yaml. + category = person("ky_ssp_category", period) + claim_type = person("ky_ssp_claim_type", period) + care_receivers = person("ky_ssp_care_receivers", period) + p = parameters(period).gov.states.ky.dcbs.ssp.payment_standard + return p[category][claim_type][care_receivers] diff --git a/policyengine_us/variables/gov/states/ky/dcbs/ssp/ky_ssp_personal_needs_allowance.py b/policyengine_us/variables/gov/states/ky/dcbs/ssp/ky_ssp_personal_needs_allowance.py new file mode 100644 index 00000000000..5720a0c013b --- /dev/null +++ b/policyengine_us/variables/gov/states/ky/dcbs/ssp/ky_ssp_personal_needs_allowance.py @@ -0,0 +1,29 @@ +from policyengine_us.model_api import * + + +class ky_ssp_personal_needs_allowance(Variable): + value_type = float + entity = Person + label = "Kentucky SSP personal needs allowance" + unit = USD + definition_period = MONTH + defined_for = StateCode.KY + reference = ( + "https://apps.legislature.ky.gov/law/kar/titles/921/002/015/", + "https://www.chfs.ky.gov/agencies/dcbs/dfs/Documents/OMVOLV.pdf#page=6", + ) + + def formula(person, period, parameters): + # Informational only: §9(3)/(4) define the PNA as an amount retained + # by the resident out of the SSP standard paid to the facility. With + # no SSP payment (ineligible), there is nothing to retain. + eligible = person("ky_ssp_eligible", period) + category = person("ky_ssp_category", period) + categories = category.possible_values + p = parameters(period).gov.states.ky.dcbs.ssp.personal_needs_allowance + monthly_amount = select( + [category == categories.PCH, category == categories.FCH], + [p.pch, p.fch], + default=0, + ) + return monthly_amount * eligible diff --git a/policyengine_us/variables/household/income/spm_unit/spm_unit_benefits.py b/policyengine_us/variables/household/income/spm_unit/spm_unit_benefits.py index fea853635de..a37c1899330 100644 --- a/policyengine_us/variables/household/income/spm_unit/spm_unit_benefits.py +++ b/policyengine_us/variables/household/income/spm_unit/spm_unit_benefits.py @@ -19,6 +19,7 @@ def formula(spm_unit, period, parameters): "ak_ssp", "dc_ossp", # DC benefits "id_aabd", # Idaho benefits + "ky_ssp", # Kentucky benefits "de_ssp", # Delaware benefits "fl_oss", "ks_sspp", # Kansas benefits diff --git a/uv.lock b/uv.lock index a54c7b86df6..ab3334c406c 100644 --- a/uv.lock +++ b/uv.lock @@ -2974,7 +2974,7 @@ wheels = [ [[package]] name = "policyengine-us" -version = "1.659.5" +version = "1.665.0" source = { editable = "." } dependencies = [ { name = "microdf-python" },