diff --git a/changelog.d/vt-ssp-2026.added.md b/changelog.d/vt-ssp-2026.added.md new file mode 100644 index 00000000000..20d0d98ce03 --- /dev/null +++ b/changelog.d/vt-ssp-2026.added.md @@ -0,0 +1 @@ +Add Vermont federally administered optional AABD supplement rates and calculations for 2026. Add Vermont 2026 Essential Person grants alongside federally administered AABD. diff --git a/policyengine_us/parameters/gov/household/household_state_benefits.yaml b/policyengine_us/parameters/gov/household/household_state_benefits.yaml index 235a7a5d63a..aec76e82b21 100644 --- a/policyengine_us/parameters/gov/household/household_state_benefits.yaml +++ b/policyengine_us/parameters/gov/household/household_state_benefits.yaml @@ -84,6 +84,8 @@ values: - sd_ssp # Texas benefits - tx_ssi_state_supplement + # Vermont benefits + - vt_aabd # Virginia benefits - va_child_care_subsidies - va_ag @@ -191,6 +193,8 @@ values: - sd_ssp # Texas benefits - tx_ssi_state_supplement + # Vermont benefits + - vt_aabd # Virginia benefits - va_child_care_subsidies - va_ag @@ -309,6 +313,8 @@ values: - sd_ssp # Texas benefits - tx_ssi_state_supplement + # Vermont benefits + - vt_aabd # Virginia benefits - va_child_care_subsidies - va_ag @@ -428,6 +434,8 @@ values: - sd_ssp # Texas benefits - tx_ssi_state_supplement + # Vermont benefits + - vt_aabd # Virginia benefits - va_child_care_subsidies - va_ag diff --git a/policyengine_us/parameters/gov/hud/annual_income/sources/unearned.yaml b/policyengine_us/parameters/gov/hud/annual_income/sources/unearned.yaml index 257416a9692..a8191353a56 100644 --- a/policyengine_us/parameters/gov/hud/annual_income/sources/unearned.yaml +++ b/policyengine_us/parameters/gov/hud/annual_income/sources/unearned.yaml @@ -29,6 +29,7 @@ values: - ny_ssp - ri_ssp - sd_ssp + - vt_aabd - va_ag - general_assistance - total_unemployment_compensation diff --git a/policyengine_us/parameters/gov/states/vt/dcf/aabd/amount/couple.yaml b/policyengine_us/parameters/gov/states/vt/dcf/aabd/amount/couple.yaml new file mode 100644 index 00000000000..2615a7a89f6 --- /dev/null +++ b/policyengine_us/parameters/gov/states/vt/dcf/aabd/amount/couple.yaml @@ -0,0 +1,32 @@ +description: Vermont provides this amount as the optional state supplement for an eligible couple under the Aid to the Aged, Blind or Disabled program. + +metadata: + unit: currency-USD + period: month + label: Vermont AABD couple payment rate + breakdown: + - vt_aabd_living_arrangement + reference: + - title: POMS SI 01415.058 M.2.b, Vermont January 2026 couple payment levels + href: https://secure.ssa.gov/poms.nsf/lnx/0501415058#m2b + +INDEPENDENT: + 2026-01-01: 105.8 + +HOUSEHOLD_OF_ANOTHER: + 2026-01-01: 51.69 + +RESIDENTIAL_CARE_LEVEL_III: + 2026-01-01: 103.54 + +RESIDENTIAL_CARE_LEVEL_IV: + 2026-01-01: 601.4 + +CUSTODIAL_CARE: + 2026-01-01: 356.12 + +MEDICAID_INSTITUTION: + 2026-01-01: 99.85 + +NONE: + 2026-01-01: 0 diff --git a/policyengine_us/parameters/gov/states/vt/dcf/aabd/amount/individual.yaml b/policyengine_us/parameters/gov/states/vt/dcf/aabd/amount/individual.yaml new file mode 100644 index 00000000000..7db6c2a8d35 --- /dev/null +++ b/policyengine_us/parameters/gov/states/vt/dcf/aabd/amount/individual.yaml @@ -0,0 +1,32 @@ +description: Vermont provides this amount as the optional state supplement for an eligible individual under the Aid to the Aged, Blind or Disabled program. + +metadata: + unit: currency-USD + period: month + label: Vermont AABD individual payment rate + breakdown: + - vt_aabd_living_arrangement + reference: + - title: POMS SI 01415.058 M.2.a, Vermont January 2026 recipient payment levels + href: https://secure.ssa.gov/poms.nsf/lnx/0501415058#m2a + +INDEPENDENT: + 2026-01-01: 55.68 + +HOUSEHOLD_OF_ANOTHER: + 2026-01-01: 42.05 + +RESIDENTIAL_CARE_LEVEL_III: + 2026-01-01: 51.77 + +RESIDENTIAL_CARE_LEVEL_IV: + 2026-01-01: 239.62 + +CUSTODIAL_CARE: + 2026-01-01: 105.6 + +MEDICAID_INSTITUTION: + 2026-01-01: 49.93 + +NONE: + 2026-01-01: 0 diff --git a/policyengine_us/parameters/gov/states/vt/dcf/aabd/ep/couple_increment.yaml b/policyengine_us/parameters/gov/states/vt/dcf/aabd/ep/couple_increment.yaml new file mode 100644 index 00000000000..8233aa93215 --- /dev/null +++ b/policyengine_us/parameters/gov/states/vt/dcf/aabd/ep/couple_increment.yaml @@ -0,0 +1,13 @@ +description: Vermont provides this amount as the Essential Person increment for an eligible couple under the Aid to the Aged, Blind or Disabled program. +values: + 2025-01-01: 183.84 + +metadata: + unit: currency-USD + period: month + label: Vermont Essential Person couple payment increment + reference: + - title: "AABD rule 2784(C) #page 44-45" + href: https://outside.vermont.gov/dept/DCF/Shared%20Documents/ESD/Rules/2700-AABD.pdf#page=44 + - title: Bulletin 25-26, P2740B, AABD-EP payment maximums + href: https://outside.vermont.gov/dept/DCF/Shared%20Documents/ESD/Rules/B25-26.pdf#page=12 diff --git a/policyengine_us/parameters/gov/states/vt/dcf/aabd/ep/employment_expense.yaml b/policyengine_us/parameters/gov/states/vt/dcf/aabd/ep/employment_expense.yaml new file mode 100644 index 00000000000..ac961f3ad30 --- /dev/null +++ b/policyengine_us/parameters/gov/states/vt/dcf/aabd/ep/employment_expense.yaml @@ -0,0 +1,11 @@ +description: Vermont deducts this amount from each worker's earnings as an Essential Person employment expense under the Aid to the Aged, Blind or Disabled program. +values: + 2026-01-01: 90 + +metadata: + unit: currency-USD + period: month + label: Vermont Essential Person employment expense deduction per worker + reference: + - title: AABD rules 2786 interpretive memo + href: https://outside.vermont.gov/dept/DCF/Shared%20Documents/ESD/Rules/2700-AABD.pdf#page=50 diff --git a/policyengine_us/parameters/gov/states/vt/dcf/aabd/ep/rate.yaml b/policyengine_us/parameters/gov/states/vt/dcf/aabd/ep/rate.yaml new file mode 100644 index 00000000000..00de7ce7524 --- /dev/null +++ b/policyengine_us/parameters/gov/states/vt/dcf/aabd/ep/rate.yaml @@ -0,0 +1,23 @@ +description: Vermont provides this share of the Essential Person maximum above the combined payment under the Aid to the Aged, Blind or Disabled program. + +metadata: + unit: /1 + period: year + label: Vermont Essential Person care fraction + breakdown: + - vt_aabd_ep_level + reference: + - title: AABD rules 2784(A) + href: https://outside.vermont.gov/dept/DCF/Shared%20Documents/ESD/Rules/2700-AABD.pdf#page=44 + +NONE: + 2026-01-01: 0 + +FULL: + 2026-01-01: 1 + +PARTIAL_67: + 2026-01-01: 0.67 + +PARTIAL_34: + 2026-01-01: 0.34 diff --git a/policyengine_us/parameters/gov/usda/snap/income/sources/unearned.yaml b/policyengine_us/parameters/gov/usda/snap/income/sources/unearned.yaml index e8d950512b9..9b515b0fad3 100644 --- a/policyengine_us/parameters/gov/usda/snap/income/sources/unearned.yaml +++ b/policyengine_us/parameters/gov/usda/snap/income/sources/unearned.yaml @@ -59,6 +59,7 @@ values: - sd_ssp - tx_ssi_state_supplement - va_ag + - vt_aabd - wa_ssp - wy_ssp # Listed elsewhere: ca_state_supplement is an SPM unit variable with no diff --git a/policyengine_us/programs.yaml b/policyengine_us/programs.yaml index 43fdd714b80..400da39280f 100644 --- a/policyengine_us/programs.yaml +++ b/policyengine_us/programs.yaml @@ -1257,6 +1257,17 @@ programs: notes: Models 2026 locality rates and SSI and non-SSI budgets for certified assisted living, adult foster care and supportive housing residents. Conditional resource benefits and historical grandfathering are not modeled. + - state: VT + status: partial + name: Vermont optional AABD + full_name: Vermont Aid to the Aged, Blind or Disabled optional supplement + variable: vt_aabd + parameter_prefix: gov.states.vt.dcf.aabd + verified_years: "2026" + notes: >- + Models 2026 federally administered supplements and state Essential Person + grants. Mandatory grandfathered payments and the state-administered + limited-nursing Level III supplement are not modeled. - id: social_security name: Social Security diff --git a/policyengine_us/tests/policy/baseline/gov/states/vt/dcf/aabd/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/vt/dcf/aabd/integration.yaml new file mode 100644 index 00000000000..3821c74ea92 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/vt/dcf/aabd/integration.yaml @@ -0,0 +1,299 @@ +- name: Case 1, independent couple. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 65 + person2: + age: 65 + marital_units: + couple: + members: [person1, person2] + tax_units: + unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: VT + output: + # Joint couple, no countable income: 105.80 couple rate / 2 = 52.90 each. + vt_aabd: [52.9, 52.9] + +- name: Case 2, residential_care_level_iii couple. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 65 + vt_aabd_care_setting: RESIDENTIAL_CARE_LEVEL_III + person2: + age: 65 + vt_aabd_care_setting: RESIDENTIAL_CARE_LEVEL_III + marital_units: + couple: + members: [person1, person2] + tax_units: + unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: VT + output: + # 103.54 couple rate / 2 = 51.77 each. + vt_aabd: [51.77, 51.77] + +- name: Case 3, residential_care_level_iv couple. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 65 + vt_aabd_care_setting: RESIDENTIAL_CARE_LEVEL_IV + person2: + age: 65 + vt_aabd_care_setting: RESIDENTIAL_CARE_LEVEL_IV + marital_units: + couple: + members: [person1, person2] + tax_units: + unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: VT + output: + # 601.40 couple rate / 2 = 300.70 each. + vt_aabd: [300.7, 300.7] + +- name: Case 4, custodial_care couple. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 65 + vt_aabd_care_setting: CUSTODIAL_CARE + person2: + age: 65 + vt_aabd_care_setting: CUSTODIAL_CARE + marital_units: + couple: + members: [person1, person2] + tax_units: + unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: VT + output: + # 356.12 couple rate / 2 = 178.06 each. + vt_aabd: [178.06, 178.06] + +- name: Case 5, household_of_another couple. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 65 + ssi_lives_in_another_persons_household: true + ssi_receives_shelter_from_others_in_household: true + ssi_others_pay_all_meals: true + person2: + age: 65 + ssi_lives_in_another_persons_household: true + ssi_receives_shelter_from_others_in_household: true + ssi_others_pay_all_meals: true + marital_units: + couple: + members: [person1, person2] + tax_units: + unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: VT + output: + # 51.69 couple rate / 2 = 25.845, rounded up to the cent = 25.85 each. + vt_aabd: [25.85, 25.85] + +- name: Case 6, medicaid_institution couple. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 65 + ssi_lives_in_medical_treatment_facility: true + ssi_medicaid_pays_majority_of_care: true + person2: + age: 65 + ssi_lives_in_medical_treatment_facility: true + ssi_medicaid_pays_majority_of_care: true + marital_units: + couple: + members: [person1, person2] + tax_units: + unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: VT + output: + # Both in the facility, so the couple computation applies: + # 99.85 couple rate / 2 = 49.925, rounded up to the cent = 49.93 each. + vt_aabd: [49.93, 49.93] + +- name: Case 7, annual benefits and SNAP income. + period: 2026 + absolute_error_margin: 0.01 + input: + state_code: VT + age: 65 + # SNAP take-up off so spm_unit_benefits does not rest on projected SNAP amounts. + takes_up_snap_if_eligible: false + output: + # 55.68 independent rate * 12 = 668.16. + vt_aabd: 668.16 + household_state_benefits: 668.16 + # SSI 994 * 12 = 11,928 + 668.16 = 12,596.16. + snap_unearned_income: 12_596.16 + # SSI 11,928 + vt_aabd 668.16; SNAP is 0 without take-up. + spm_unit_benefits: 12_596.16 + +- name: Case 8, Essential-person grant enters the annual Vermont benefit total. + period: 2026 + absolute_error_margin: 0.01 + input: + state_code: VT + age: 70 + vt_aabd_ep_level: + 2026: FULL + output: + # 994 * 12 = 11,928. + ssi: 11_928 + # 55.68 * 12 = 668.16. + vt_aabd_federal: 668.16 + # Monthly maximum 1,491 + 105.80 = 1,596.80; countable 994 + 55.68 = 1,049.68; + # floor(1,596.80 - 1,049.68) = floor(547.12) = 547 * 12 = 6,564. + vt_aabd_ep: 6_564 + # 668.16 + 6,564 = 7,232.16. + vt_aabd: 7_232.16 + # 11,928 + 7,232.16 = 19,160.16. + snap_unearned_income: 19_160.16 + # SSI plus the whole AABD payment, including the Essential Person grant: + # 11,928 + 7,232.16 = 19,160.16. + hud_unearned_income: 19_160.16 + +- name: Case 9, Two eligible spouses share one essential-person grant. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + vt_aabd_ep_level: FULL + person2: + age: 70 + vt_aabd_ep_level: FULL + marital_units: + couple: + members: [person1, person2] + households: + home: + members: [person1, person2] + state_code: VT + output: + # Couple maximum 1,491 + 105.80 + 183.84 = 1,780.64; countable SSI 745.50 * 2 + # + AABD 52.90 * 2 = 1,596.80; floor(183.84) = 183 / 2 = 91.50 each. + vt_aabd_ep: [91.5, 91.5] + # 52.90 AABD + 91.50 Essential Person grant = 144.40 each. + vt_aabd: [144.4, 144.4] + +- name: Case 10, Ineligible spouse earnings do not get the ABD half-earnings deduction. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + vt_aabd_ep_level: FULL + person2: + age: 40 + employment_income: 6_000 + marital_units: + couple: + members: [person1, person2] + households: + home: + members: [person1, person2] + state_code: VT + output: + # person2 (40, not blind or disabled) is the ineligible spouse. + vt_aabd_ep_is_spouse: [true, false] + # SSI receipt passes the resource test for the group. + vt_aabd_ep_resources_eligible: [true, true] + # Spouse earnings 500 - 90 employment expense - 20 general = 390, with no + # half-earnings exclusion, + SSI 994 + AABD 55.68 = 1,439.68. + vt_aabd_ep_countable_income: [1_439.68, 1_439.68] + # floor(1,596.80 - 1,439.68) = floor(157.12) = 157 for the recipient only. + vt_aabd_ep: [157, 0] + +- name: Case 11, Vermont essential care for a disabled member counts as HUD income. + period: 2026 + absolute_error_margin: 0.01 + input: + state_code: VT + age: 40 + meets_ssi_disability_criteria: true + is_disabled: true + vt_aabd_ep_level: FULL + output: + # AABD 55.68 * 12 = 668.16 + Essential Person grant floor(1,596.80 - 1,049.68) + # = 547 * 12 = 6,564; 668.16 + 6,564 = 7,232.16. + vt_aabd: 7_232.16 + # SSI 994 * 12 = 11,928 + 7,232.16 = 19,160.16. + snap_unearned_income: 19_160.16 + # HUD counts the whole AABD payment, including the Essential Person grant: + # 11,928 + 7,232.16 = 19,160.16. + hud_unearned_income: 19_160.16 + +- name: Case 12, One spouse in a Medicaid facility is paid as an individual. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + ssi_lives_in_medical_treatment_facility: true + ssi_medicaid_pays_majority_of_care: true + person2: + age: 70 + marital_units: + couple: + members: [person1, person2] + tax_units: + unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: VT + output: + vt_aabd_living_arrangement: [MEDICAID_INSTITUTION, INDEPENDENT] + # 20 CFR 416.414(b)(3): each spouse is paid at an individual rate. + ssi_couple_computation_applies: [false, false] + # $30 facility rate and the 994 individual FBR. + ssi_amount_if_eligible: [30, 994] + ssi: [30, 994] + # POMS SI 01415.058 M.2.a individual rates: code I 49.93, code A 55.68. + vt_aabd: [49.93, 55.68] diff --git a/policyengine_us/tests/policy/baseline/gov/states/vt/dcf/aabd/vt_aabd.yaml b/policyengine_us/tests/policy/baseline/gov/states/vt/dcf/aabd/vt_aabd.yaml new file mode 100644 index 00000000000..9e216d7a7e0 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/vt/dcf/aabd/vt_aabd.yaml @@ -0,0 +1,196 @@ +# POMS SI 01415.058 M, Vermont January 2026 optional supplement schedule. +- name: Case 1, independent individual. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: VT + age: 65 + output: + vt_aabd_living_arrangement: INDEPENDENT + vt_aabd: 55.68 + +- name: Case 2, residential care level iii individual. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: VT + age: 65 + vt_aabd_care_setting: RESIDENTIAL_CARE_LEVEL_III + output: + vt_aabd: 51.77 + +- name: Case 3, residential care level iv individual. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: VT + age: 65 + vt_aabd_care_setting: RESIDENTIAL_CARE_LEVEL_IV + output: + vt_aabd: 239.62 + +- name: Case 4, custodial care individual. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: VT + age: 65 + vt_aabd_care_setting: CUSTODIAL_CARE + output: + vt_aabd: 105.6 + +- name: Case 5, household of another individual. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: VT + age: 65 + ssi_lives_in_another_persons_household: true + ssi_receives_shelter_from_others_in_household: true + ssi_others_pay_all_meals: true + output: + # Federal another person's household maps to HOUSEHOLD_OF_ANOTHER. + vt_aabd_living_arrangement: HOUSEHOLD_OF_ANOTHER + # No countable income: 42.05 rate - 0 excess over the 662.67 reduced FBR = 42.05. + vt_aabd: 42.05 + +- name: Case 6, medicaid institution individual. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: VT + age: 65 + ssi_lives_in_medical_treatment_facility: true + ssi_medicaid_pays_majority_of_care: true + output: + # Federal Medicaid-paid medical treatment facility maps to MEDICAID_INSTITUTION. + vt_aabd_living_arrangement: MEDICAID_INSTITUTION + # No countable income: 49.93 rate - 0 excess over the $30 facility FBR = 49.93. + vt_aabd: 49.93 + +- name: Case 7, a recipient who declines SSI gets no supplement. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: VT + age: 65 + takes_up_ssi_if_eligible: false + output: + # 33 V.S.A. § 1301(3) requires SSI receipt if eligible. + ssi: 0 + vt_aabd: 0 + +- name: Case 8, Chittenden County independent living uses the same rate as the rest of the state. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: VT + county: CHITTENDEN_COUNTY_VT + age: 65 + output: + # POMS SI 01415.058 M.2.a: OS code B (Chittenden County) and code A both + # pay 55.68. + vt_aabd_living_arrangement: INDEPENDENT + vt_aabd: 55.68 + +- name: Case 9, income above federal SSI standard. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: VT + age: 65 + social_security_retirement: 12_360 + output: + vt_aabd: 39.68 + +- name: Case 10, income at combined cutoff. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: VT + age: 65 + social_security_retirement: 12_836.16 + output: + vt_aabd: 0 + +- name: Case 11, minimum positive payment. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: VT + age: 65 + social_security_retirement: 12_836.04 + output: + vt_aabd: 1 + +- name: Case 12, excess resources. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: VT + age: 65 + ssi_countable_resources: 2_001 + output: + vt_aabd: 0 + +- name: Case 13, not aged blind or disabled. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: VT + age: 30 + output: + vt_aabd: 0 + +- name: Case 14, non Vermont resident. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NH + age: 65 + output: + vt_aabd: 0 + +- name: Case 15, a care setting for one of two unrelated people leaves the other independent. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + vt_aabd_care_setting: CUSTODIAL_CARE + person2: + age: 70 + marital_units: + marital_unit1: + members: [person1] + marital_unit2: + members: [person2] + tax_units: + tax_unit1: + members: [person1] + tax_unit2: + members: [person2] + households: + household: + members: [person1, person2] + state_code: VT + output: + vt_aabd_living_arrangement: [CUSTODIAL_CARE, INDEPENDENT] + # Individual rates with no income: 105.60 custodial care and 55.68 independent. + vt_aabd: [105.6, 55.68] + +- name: Case 16, a Title XIX facility precedes a care setting. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: VT + age: 65 + ssi_lives_in_medical_treatment_facility: true + ssi_medicaid_pays_majority_of_care: true + vt_aabd_care_setting: RESIDENTIAL_CARE_LEVEL_III + output: + # POMS SI 01415.058 M.2.a uses code I with federal arrangement D. + vt_aabd_living_arrangement: MEDICAID_INSTITUTION + # 49.93 rate - 0 excess over the $30 facility FBR = 49.93. + vt_aabd: 49.93 diff --git a/policyengine_us/tests/policy/baseline/gov/states/vt/dcf/aabd/vt_aabd_ep.yaml b/policyengine_us/tests/policy/baseline/gov/states/vt/dcf/aabd/vt_aabd_ep.yaml new file mode 100644 index 00000000000..6c865dcc3f0 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/vt/dcf/aabd/vt_aabd_ep.yaml @@ -0,0 +1,594 @@ +- name: Case 1, Full essential-person payment supplements existing SSI and AABD. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: VT + age: 70 + ssi: 994 + vt_aabd_federal: 55.68 + vt_aabd_ep_level: FULL + output: + vt_aabd_ep: 547 + +- name: Case 2, Sixty-seven percent care level. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: VT + age: 70 + ssi: 994 + vt_aabd_federal: 55.68 + vt_aabd_ep_level: PARTIAL_67 + output: + vt_aabd_ep: 366 + +- name: Case 3, Thirty-four percent care level. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: VT + age: 70 + ssi: 994 + vt_aabd_federal: 55.68 + vt_aabd_ep_level: PARTIAL_34 + output: + vt_aabd_ep: 186 + +- name: Case 4, No certified essential-person arrangement. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: VT + age: 70 + ssi: 994 + vt_aabd_federal: 55.68 + vt_aabd_ep_level: NONE + output: + vt_aabd_ep: 0 + +- name: Case 5, An ineligible spouse cannot qualify at the 34 percent service level. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + vt_aabd_ep_level: PARTIAL_34 + person2: + age: 60 + marital_units: + couple: + members: [person1, person2] + households: + home: + members: [person1, person2] + state_code: VT + output: + # person2 (60, not blind or disabled) is the ineligible spouse. + vt_aabd_ep_is_spouse: [true, false] + # No spouse income, so no deeming. + ssi: [994, 0] + vt_aabd_federal: [55.68, 0] + # Rule 2784(A)(3) pays the 34 percent level only for a nonspouse. + vt_aabd_ep: [0, 0] + +- name: Case 6, Prorated nonspouse essential-person net income counts. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: VT + age: 70 + ssi: 994 + vt_aabd_federal: 55.68 + vt_aabd_ep_level: FULL + vt_aabd_ep_additional_countable_income: 100 + output: + vt_aabd_ep: 447 + +- name: Case 7, Income at payment maximum. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: VT + age: 70 + ssi: 994 + vt_aabd_federal: 55.68 + vt_aabd_ep_level: FULL + vt_aabd_ep_additional_countable_income: 547.12 + output: + # SSI 994 + AABD 55.68 + 547.12 additional = 1,596.80, the payment maximum. + vt_aabd_ep_countable_income: 1_596.8 + vt_aabd_ep: 0 + +- name: Case 8, Additional countable income for one of two unrelated recipients stays with that recipient. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + vt_aabd_ep_level: FULL + vt_aabd_ep_additional_countable_income: 100 + person2: + age: 70 + vt_aabd_ep_level: FULL + marital_units: + marital_unit1: + members: [person1] + marital_unit2: + members: [person2] + tax_units: + tax_unit1: + members: [person1] + tax_unit2: + members: [person2] + households: + household: + members: [person1, person2] + state_code: VT + output: + # SSI 994 + AABD 55.68 = 1,049.68, plus 100 additional for person1 only. + vt_aabd_ep_countable_income: [1_149.68, 1_049.68] + # floor(1,596.80 - 1,149.68) = 447; floor(1,596.80 - 1,049.68) = 547. + vt_aabd_ep: [447, 547] + +- name: Case 9, A spouse who is not aged, blind or disabled defaults as the essential person in another household. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + vt_aabd_ep_level: FULL + ssi_lives_in_another_persons_household: true + ssi_receives_shelter_from_others_in_household: true + ssi_others_pay_all_meals: true + person2: + age: 60 + ssi_lives_in_another_persons_household: true + ssi_receives_shelter_from_others_in_household: true + ssi_others_pay_all_meals: true + marital_units: + couple: + members: [person1, person2] + households: + home: + members: [person1, person2] + state_code: VT + output: + # person1 is aged and person2 (60, not blind or disabled) is in the same marital unit. + vt_aabd_ep_is_spouse: [true, false] + vt_aabd_living_arrangement: [HOUSEHOLD_OF_ANOTHER, HOUSEHOLD_OF_ANOTHER] + # No spouse income, so no deeming: 994 * (1 - 1/3) = 662.67 reduced FBR. + ssi: [662.67, 0] + # 42.05 another-household rate - 0 excess = 42.05. + vt_aabd_federal: [42.05, 0] + # Maximum 994 + 55.68 = 1,049.68; countable 662.67 + 42.05 = 704.72; + # floor(1,049.68 - 704.72) = floor(344.96) = 344. + vt_aabd_ep: [344, 0] + +- name: Case 10, Essential-person coverage does not extend to residential care. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: VT + age: 70 + vt_aabd_ep_level: FULL + vt_aabd_care_setting: RESIDENTIAL_CARE_LEVEL_III + output: + vt_aabd_living_arrangement: RESIDENTIAL_CARE_LEVEL_III + vt_aabd_federal: 51.77 + vt_aabd_ep: 0 + +- name: Case 11, Nonspouse essential person cannot qualify in another household. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: VT + age: 70 + vt_aabd_ep_level: FULL + ssi_lives_in_another_persons_household: true + ssi_receives_shelter_from_others_in_household: true + ssi_others_pay_all_meals: true + output: + vt_aabd_living_arrangement: HOUSEHOLD_OF_ANOTHER + # 994 * (1 - 1/3) = 662.67 reduced FBR. + ssi: 662.67 + vt_aabd_federal: 42.05 + # Rule 2783.2 excludes a nonspouse essential person in another's household. + vt_aabd_ep: 0 + +- name: Case 12, Ineligible spouse qualifies at 67 percent in another household. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + vt_aabd_ep_level: PARTIAL_67 + ssi_lives_in_another_persons_household: true + ssi_receives_shelter_from_others_in_household: true + ssi_others_pay_all_meals: true + person2: + age: 50 + ssi_lives_in_another_persons_household: true + ssi_receives_shelter_from_others_in_household: true + ssi_others_pay_all_meals: true + marital_units: + couple: + members: [person1, person2] + households: + home: + members: [person1, person2] + state_code: VT + output: + vt_aabd_ep_is_spouse: [true, false] + ssi: [662.67, 0] + vt_aabd_federal: [42.05, 0] + # P2740B 67 percent another's-household maximum 935.84; + # floor(935.84 - (662.67 + 42.05)) = floor(231.12) = 231. + vt_aabd_ep: [231, 0] + +- name: Case 13, Non-SSI recipient requires verified resource eligibility. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: VT + age: 70 + vt_aabd_ep_level: FULL + # Scaled low earner claiming at 65: $15,238 in 2025 dollars (2025 Trustees + # Report Table V.C7) * 1.028 COLA = about $15,665 a year, $1,305.42 a month. + social_security_retirement: 15_665 + output: + # SSI countable 1,305.42 - 20 = 1,285.42 > 994 FBR, so SSI is 0. + ssi: 0 + # 55.68 - (1,285.42 - 994) excess of 291.42 < 0, so no AABD supplement. + vt_aabd_federal: 0 + # No SSI, AABD or reported SSI receipt and no state resource determination. + vt_aabd_ep_resources_eligible: false + vt_aabd_ep: 0 + +- name: Case 14, State-only essential-person grant with verified resources. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: VT + age: 70 + vt_aabd_ep_level: FULL + vt_aabd_ep_passes_state_resource_test: true + # Same scaled low earner Social Security benefit as Case 13: $1,305.42 a month. + social_security_retirement: 15_665 + output: + # SSI countable 1,285.42 > 994 FBR and 291.42 excess > 55.68 supplement. + ssi: 0 + vt_aabd_federal: 0 + vt_aabd_ep_resources_eligible: true + # 1,305.42 - 20 general exclusion = 1,285.42. + vt_aabd_ep_countable_income: 1_285.42 + # Maximum 1,491 + 105.80 = 1,596.80; floor(1,596.80 - 1,285.42) = floor(311.38) = 311. + vt_aabd_ep: 311 + +- name: Case 15, A worker receives the state employment-expense deduction. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: VT + age: 70 + vt_aabd_ep_level: FULL + vt_aabd_ep_passes_state_resource_test: true + # Full time at Vermont's 2026 minimum wage: $14.42 * 2,080 hours = $29,993.60, + # $2,499.47 a month. + employment_income: 29_993.6 + output: + # SSI countable (2,499.47 - 20 - 65) * 0.5 = 1,207.23 > 994 FBR. + ssi: 0 + # 1,207.23 - 994 = 213.23 excess > 55.68 supplement. + vt_aabd_federal: 0 + # (2,499.47 - 90 employment expense - 20 - 65) * 0.5 = 1,162.23. + vt_aabd_ep_countable_income: 1_162.23 + # floor(1,596.80 - 1,162.23) = floor(434.57) = 434. + vt_aabd_ep: 434 + +- name: Case 16, Needs-based veterans pension does not get the general exclusion. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: VT + age: 70 + vt_aabd_ep_level: FULL + vt_aabd_ep_passes_state_resource_test: true + # VA pension MAPR for a veteran with no dependents from December 1, 2025: + # $17,441 a year, $1,453.42 a month, with no other income. + veterans_benefits: 17_441 + output: + # SSI countable 1,453.42 - 20 = 1,433.42 > 994 FBR. + ssi: 0 + # 1,433.42 - 994 = 439.42 excess > 55.68 supplement. + vt_aabd_federal: 0 + # The needs-based pension counts in full, without the $20 general exclusion. + vt_aabd_ep_countable_income: 1_453.42 + # floor(1,596.80 - 1,453.42) = floor(143.38) = 143. + vt_aabd_ep: 143 + +- name: Case 17, Out of state. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NH + age: 70 + ssi: 994 + vt_aabd_federal: 55.68 + vt_aabd_ep_level: FULL + output: + vt_aabd_ep: 0 + +- name: Case 18, A nonspouse essential person qualifies at 34 percent next to an ineligible spouse. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + vt_aabd_ep_level: PARTIAL_34 + vt_aabd_ep_nonspouse_essential_person: true + person2: + age: 45 + marital_units: + couple: + members: [person1, person2] + households: + home: + members: [person1, person2] + state_code: VT + output: + # The certified essential person is not the spouse (rules 2781(E), 2782). + vt_aabd_ep_is_spouse: [false, false] + # SSI 994 + AABD 55.68; the spouse has no income. + vt_aabd_ep_countable_income: [1_049.68, 1_049.68] + # 1,049.68 + 0.34 * (1,596.80 - 1,049.68) = 1,235.70; + # floor(1,235.70 - 1,049.68) = floor(186.02) = 186. + vt_aabd_ep: [186, 0] + # 55.68 AABD + 186 Essential Person grant = 241.68. + vt_aabd: [241.68, 0] + +- name: Case 19, A state resource determination for one of two unrelated recipients stays with that recipient. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + vt_aabd_ep_level: FULL + vt_aabd_ep_passes_state_resource_test: true + # Same scaled low earner Social Security benefit as Case 13: $1,305.42 a month. + social_security_retirement: 15_665 + person2: + age: 70 + vt_aabd_ep_level: FULL + marital_units: + marital_unit1: + members: [person1] + marital_unit2: + members: [person2] + tax_units: + tax_unit1: + members: [person1] + tax_unit2: + members: [person2] + households: + household: + members: [person1, person2] + state_code: VT + output: + # person1 passes the state test; person2 receives SSI. + vt_aabd_ep_resources_eligible: [true, true] + # floor(1,596.80 - 1,285.42) = 311; floor(1,596.80 - 1,049.68) = 547. + vt_aabd_ep: [311, 547] + # person2: 55.68 AABD + 547 = 602.68. + vt_aabd: [311, 602.68] + +- name: Case 20, A nonspouse flag on one recipient leaves another recipient's spouse as the essential person. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + vt_aabd_ep_nonspouse_essential_person: true + person2: + age: 70 + vt_aabd_ep_level: FULL + ssi_lives_in_another_persons_household: true + ssi_receives_shelter_from_others_in_household: true + ssi_others_pay_all_meals: true + person3: + age: 60 + ssi_lives_in_another_persons_household: true + ssi_receives_shelter_from_others_in_household: true + ssi_others_pay_all_meals: true + marital_units: + marital_unit1: + members: [person1] + marital_unit2: + members: [person2, person3] + tax_units: + tax_unit1: + members: [person1] + tax_unit2: + members: [person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: VT + output: + vt_aabd_ep_is_spouse: [false, true, false] + # person2: floor(1,049.68 - (662.67 + 42.05)) = floor(344.96) = 344. + vt_aabd_ep: [0, 344, 0] + # person1: 55.68 independent rate; person2: 42.05 + 344 = 386.05. + vt_aabd: [55.68, 386.05, 0] + +- name: Case 21, One certified essential person for an eligible couple uses the couple maximum. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + vt_aabd_ep_level: FULL + person2: + age: 70 + marital_units: + couple: + members: [person1, person2] + households: + home: + members: [person1, person2] + state_code: VT + output: + # Rules 2780(A), 2783.1 and 2784(C): one grant for the couple. + # Couple maximum 1,491 + 105.80 + 183.84 = 1,780.64; countable SSI 745.50 * 2 + # + AABD 52.90 * 2 = 1,596.80; floor(183.84) = 183 / 2 = 91.50 each. + vt_aabd_ep: [91.5, 91.5] + +- name: Case 22, An eligible couple certified at different levels uses the higher 67 percent couple level. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + vt_aabd_ep_level: PARTIAL_67 + person2: + age: 70 + vt_aabd_ep_level: PARTIAL_34 + marital_units: + couple: + members: [person1, person2] + households: + home: + members: [person1, person2] + state_code: VT + output: + # P2740B 67 percent couple maximum 1,719.97; countable SSI 745.50 * 2 + # + AABD 52.90 * 2 = 1,596.80; floor(123.17) = 123 / 2 = 61.50 each. + vt_aabd_ep: [61.5, 61.5] + +- name: Case 23, A spouse in a Medicaid facility is left out of the at-home spouse's group income. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + ssi_lives_in_medical_treatment_facility: true + ssi_medicaid_pays_majority_of_care: true + social_security_retirement: 15_665 + person2: + age: 70 + vt_aabd_ep_level: FULL + marital_units: + couple: + members: [person1, person2] + households: + home: + members: [person1, person2] + state_code: VT + output: + # Rule 2782: only household members count; the at-home spouse has SSI + # 994 + AABD 55.68 = 1,049.68 against the 1,596.80 individual maximum. + vt_aabd_ep_countable_income: [1_049.68, 1_049.68] + vt_aabd_ep: [0, 547] + +- name: Case 24, Pre-tax health premiums stay in an ineligible spouse's earnings. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + vt_aabd_ep_level: FULL + person2: + age: 40 + # Reviewer's example: integration Case 10's $500 a month of wages, with + # $100 a month of health premiums paid by salary reduction. + employment_income: 6_000 + pre_tax_health_insurance_premiums: 1_200 + marital_units: + couple: + members: [person1, person2] + households: + home: + members: [person1, person2] + state_code: VT + output: + # SSI wages 500 - 100 premiums = 400 do not exceed the 1,491 - 994 = 497 + # FBR difference, so nothing is deemed and SSI is the 994 FBR. + ssi: [994, 0] + # Reach Up rule 2251(a) counts wages before insurance deductions: + # 500 - 90 employment expense - 20 general = 390, with no half-earnings + # exclusion, + SSI 994 + AABD 55.68 = 1,439.68. + vt_aabd_ep_countable_income: [1_439.68, 1_439.68] + # floor(1,596.80 - 1,439.68) = floor(157.12) = 157, as in integration Case 10. + vt_aabd_ep: [157, 0] + +- name: Case 25, Pre-tax health premiums stay in an aged worker's earnings. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + vt_aabd_ep_level: FULL + # Reviewer's example: $1,000 a month of wages, with $100 a month of + # health premiums paid by salary reduction. + employment_income: 12_000 + pre_tax_health_insurance_premiums: 1_200 + person2: + age: 60 + marital_units: + couple: + members: [person1, person2] + households: + home: + members: [person1, person2] + state_code: VT + output: + # SSI excludes the premiums (POMS SI 00820.102 C.2): + # (1,000 - 100 - 20 - 65) / 2 = 407.50, and 994 - 407.50 = 586.50. + ssi: [586.5, 0] + vt_aabd_federal: [55.68, 0] + # Reach Up rule 2251(a) keeps them: (1,000 - 90 - 20 - 65) / 2 = 412.50, + # + SSI 586.50 + AABD 55.68 = 1,054.68. + vt_aabd_ep_countable_income: [1_054.68, 1_054.68] + # floor(1,596.80 - 1,054.68) = floor(542.12) = 542. + vt_aabd_ep: [542, 0] + +- name: Case 26, A spouse in a Medicaid facility does not pass the resource test for the spouse at home. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + ssi_lives_in_medical_treatment_facility: true + ssi_medicaid_pays_majority_of_care: true + person2: + age: 70 + vt_aabd_ep_level: FULL + # Same scaled low earner Social Security benefit as Case 13: $1,305.42 a month. + social_security_retirement: 15_665 + marital_units: + couple: + members: [person1, person2] + households: + home: + members: [person1, person2] + state_code: VT + output: + # $30 facility rate; at home, 1,305.42 - 20 = 1,285.42 > 994, so no SSI. + ssi: [30, 0] + # Rule 2782 limits the group to members of the same household, so the + # facility spouse's SSI does not pass rule 2785's test for the spouse at + # home, who has no state resource determination. + vt_aabd_ep_resources_eligible: [false, false] + vt_aabd_ep: [0, 0] diff --git a/policyengine_us/variables/gov/states/vt/dcf/aabd/vt_aabd.py b/policyengine_us/variables/gov/states/vt/dcf/aabd/vt_aabd.py new file mode 100644 index 00000000000..0e0494c54cd --- /dev/null +++ b/policyengine_us/variables/gov/states/vt/dcf/aabd/vt_aabd.py @@ -0,0 +1,18 @@ +from policyengine_us.model_api import * + + +class vt_aabd(Variable): + value_type = float + entity = Person + label = "Vermont Aid to the Aged, Blind or Disabled supplements" + definition_period = MONTH + unit = USD + defined_for = StateCode.VT + reference = ( + # 33 V.S.A. §§ 1301(3), 1309(a) + "https://legislature.vermont.gov/statutes/fullchapter/33/013", + "https://secure.ssa.gov/poms.nsf/lnx/0501415058#m2", + # PDF pages 27, 36 + "https://outside.vermont.gov/dept/DCF/Shared%20Documents/ESD/Rules/2700-AABD.pdf#page=27", + ) + adds = ["vt_aabd_federal", "vt_aabd_ep"] diff --git a/policyengine_us/variables/gov/states/vt/dcf/aabd/vt_aabd_care_setting.py b/policyengine_us/variables/gov/states/vt/dcf/aabd/vt_aabd_care_setting.py new file mode 100644 index 00000000000..5b68c7f78d9 --- /dev/null +++ b/policyengine_us/variables/gov/states/vt/dcf/aabd/vt_aabd_care_setting.py @@ -0,0 +1,28 @@ +from policyengine_us.model_api import * + + +class VTAABDCareSetting(Enum): + RESIDENTIAL_CARE_LEVEL_III = ( + "Level III residential care home with assistive community care (code C)" + ) + RESIDENTIAL_CARE_LEVEL_IV = ( + "Level IV residential care home or therapeutic community residence (code G)" + ) + CUSTODIAL_CARE = "Custodial care family home (code H)" + NONE = "No state-identified care setting" + + +class vt_aabd_care_setting(Variable): + value_type = Enum + entity = Person + label = "Vermont AABD care setting" + definition_period = MONTH + defined_for = StateCode.VT + possible_values = VTAABDCareSetting + default_value = VTAABDCareSetting.NONE + reference = ( + "https://secure.ssa.gov/poms.nsf/lnx/0501415058#m1", + # PDF pages 31-33 + "https://outside.vermont.gov/dept/DCF/Shared%20Documents/ESD/Rules/2700-AABD.pdf#page=31", + ) + documentation = "Residence in a care setting that meets the state's licensing, certification and service rules (rules 2764.1, 2764.3 and 2766)." diff --git a/policyengine_us/variables/gov/states/vt/dcf/aabd/vt_aabd_ep.py b/policyengine_us/variables/gov/states/vt/dcf/aabd/vt_aabd_ep.py new file mode 100644 index 00000000000..19a5268f52e --- /dev/null +++ b/policyengine_us/variables/gov/states/vt/dcf/aabd/vt_aabd_ep.py @@ -0,0 +1,70 @@ +from policyengine_us.model_api import * + + +class vt_aabd_ep(Variable): + value_type = float + entity = Person + label = "Vermont state-administered Essential Person grant" + definition_period = MONTH + unit = USD + # PDF pages 36, 43-45, 49-50 + reference = "https://outside.vermont.gov/dept/DCF/Shared%20Documents/ESD/Rules/2700-AABD.pdf#page=36" + defined_for = StateCode.VT + + def formula(person, period, parameters): + p = parameters(period).gov.states.vt.dcf.aabd + federal = parameters(period).gov.ssa.ssi.amount + level = person("vt_aabd_ep_level", period) + levels = level.possible_values + arrangement = person("vt_aabd_living_arrangement", period) + la = arrangement.possible_values + independent = arrangement == la.INDEPENDENT + other = arrangement == la.HOUSEHOLD_OF_ANOTHER + spouse = person("vt_aabd_ep_is_spouse", period) + valid_level = (level != levels.NONE) & ~(spouse & (level == levels.PARTIAL_34)) + # vt_aabd_ep_resources_eligible already tests the marital unit's + # household members. + abd_eligible = ( + person("is_ssi_aged_blind_disabled", period.this_year) + & (independent | (other & spouse)) + & person("vt_aabd_ep_resources_eligible", period) + & ~person("is_incarcerated", period) + & person("takes_up_ssi_if_eligible", period.this_year) + ) + # Rules 2780(A), 2783.1 and 2784(C): an eligible couple receives one + # grant for a shared essential person. The rules do not address + # different levels for each spouse; use the highest level certified for + # either spouse. + certified = abd_eligible & valid_level + person_eligible = abd_eligible & person.marital_unit.any(certified) + rate = person.marital_unit.max(where(certified, p.ep.rate[level], 0)) + count = person.marital_unit.sum(person_eligible) + couple = count > 1 + # Rule 2784(B)-(C): the individual maximum is the combined couple + # payment, the another-household maximum is the combined independent + # individual payment, and the couple maximum adds an increment to the + # combined couple payment. Both 2026 geographic schedules have the + # same amounts. + couple_combined = federal.couple + p.amount.couple.INDEPENDENT + individual_combined = federal.individual + p.amount.individual.INDEPENDENT + maximum = where( + other, + individual_combined, + couple_combined + couple * p.ep.couple_increment, + ) + base = where( + couple, + couple_combined, + where( + other, + federal.individual * (1 - federal.one_third_reduction_rate) + + p.amount.individual.HOUSEHOLD_OF_ANOTHER, + individual_combined, + ), + ) + # Derive the partial levels from rule 2784(A) and round to cents. + standard = np.round(base + rate * (maximum - base), 2) + amount = max_(standard - person("vt_aabd_ep_countable_income", period), 0) + # NOTE: The rule 2784 application-month proration is not modeled. + eligible = person_eligible & (independent | ~couple) + return eligible * np.floor(amount) / max_(count, 1) diff --git a/policyengine_us/variables/gov/states/vt/dcf/aabd/vt_aabd_ep_additional_countable_income.py b/policyengine_us/variables/gov/states/vt/dcf/aabd/vt_aabd_ep_additional_countable_income.py new file mode 100644 index 00000000000..a0491978763 --- /dev/null +++ b/policyengine_us/variables/gov/states/vt/dcf/aabd/vt_aabd_ep_additional_countable_income.py @@ -0,0 +1,12 @@ +from policyengine_us.model_api import * + + +class vt_aabd_ep_additional_countable_income(Variable): + value_type = float + entity = Person + label = "Vermont Essential Person income outside the marital group" + definition_period = MONTH + unit = USD + # PDF pages 48-51 + reference = "https://outside.vermont.gov/dept/DCF/Shared%20Documents/ESD/Rules/2700-AABD.pdf#page=48" + documentation = "Verified net income of a nonspouse essential person and any parental allocation. Apply the Reach Up exclusions, dependent proration, worker expense allowance and any unused share of the single group general exclusion before entering this amount; do not duplicate the marital group income." diff --git a/policyengine_us/variables/gov/states/vt/dcf/aabd/vt_aabd_ep_countable_income.py b/policyengine_us/variables/gov/states/vt/dcf/aabd/vt_aabd_ep_countable_income.py new file mode 100644 index 00000000000..1cc1084e95b --- /dev/null +++ b/policyengine_us/variables/gov/states/vt/dcf/aabd/vt_aabd_ep_countable_income.py @@ -0,0 +1,68 @@ +from policyengine_us.model_api import * + + +class vt_aabd_ep_countable_income(Variable): + value_type = float + entity = Person + label = "Vermont Essential Person assistance-group countable income" + definition_period = MONTH + unit = USD + reference = ( + # PDF pages 42, 48-51 + "https://outside.vermont.gov/dept/DCF/Shared%20Documents/ESD/Rules/2700-AABD.pdf#page=42", + "https://outside.vermont.gov/dept/DCF/Shared%20Documents/ESD/Rules/2200-Reach-Up.pdf#page=70", + ) + documentation = """ + Income of the marital unit's household members under rule 2786, with + earnings counted before payroll deductions (Reach Up rule 2251(a)), plus + vt_aabd_ep_additional_countable_income. + NOTE: Reach Up income sources or exclusions without an SSI input are not + modeled. + """ + + def formula(person, period, parameters): + p = parameters(period).gov.states.vt.dcf.aabd.ep + ssi_income = parameters(period).gov.ssa.ssi.income + exclusions = ssi_income.exclusions + abd = person("is_ssi_aged_blind_disabled", period.this_year) + arrangement = person("vt_aabd_living_arrangement", period) + la = arrangement.possible_values + # Rule 2782: the group includes only members living in the same + # household, so a spouse in a facility is left out. + in_household = (arrangement == la.INDEPENDENT) | ( + arrangement == la.HOUSEHOLD_OF_ANOTHER + ) + # Rule 2786 applies the Reach Up income rules, and Reach Up rule + # 2251(a) counts earnings "prior to any voluntary or involuntary + # deductions including ... insurance". + # NOTE: SSI excludes salary-reduction health premiums from wages (POMS + # SI 00820.102 C.2), so this sums SSI's earned sources rather than + # reading ssi_earned_income; the ssi term below keeps SSA's treatment. + gross_earned = add(person, period, ssi_income.sources.earned) + earned = in_household * max_(gross_earned - p.employment_expense, 0) + abd_earned = person.marital_unit.sum(earned * abd) + other_earned = person.marital_unit.sum(earned * ~abd) + # NOTE: Rule 2786 withholds the $20 exclusion from VA pension only; with + # no pension-specific input, all veterans benefits are treated as pension. + veterans = max_(person("veterans_benefits", period), 0) + unearned = person.marital_unit.sum( + in_household * max_(person("ssi_unearned_income", period) - veterans, 0) + ) + general = exclusions.general + remaining_general = max_(general - unearned, 0) + unearned = max_(unearned - general, 0) + # Apply any remaining group disregard to non-ABD earnings first, + # since only the ABD members receive the half-earnings exclusion. + remaining_general_abd = max_(remaining_general - other_earned, 0) + other_earned = max_(other_earned - remaining_general, 0) + abd_earned = max_(abd_earned - remaining_general_abd - exclusions.earned, 0) * ( + 1 - exclusions.earned_share + ) + needs_based = person.marital_unit.sum( + in_household + * (veterans + person("ssi", period) + person("vt_aabd_federal", period)) + ) + additional = person.marital_unit.max( + max_(person("vt_aabd_ep_additional_countable_income", period), 0) + ) + return unearned + abd_earned + other_earned + needs_based + additional diff --git a/policyengine_us/variables/gov/states/vt/dcf/aabd/vt_aabd_ep_is_spouse.py b/policyengine_us/variables/gov/states/vt/dcf/aabd/vt_aabd_ep_is_spouse.py new file mode 100644 index 00000000000..c9ea361fbc5 --- /dev/null +++ b/policyengine_us/variables/gov/states/vt/dcf/aabd/vt_aabd_ep_is_spouse.py @@ -0,0 +1,21 @@ +from policyengine_us.model_api import * + + +class vt_aabd_ep_is_spouse(Variable): + value_type = bool + entity = Person + label = "Vermont AABD recipient's Essential Person is an ineligible spouse" + definition_period = MONTH + # PDF pages 38, 44 + reference = "https://outside.vermont.gov/dept/DCF/Shared%20Documents/ESD/Rules/2700-AABD.pdf#page=38" + documentation = "True for an aged, blind or disabled recipient whose marital unit includes a spouse who is not aged, blind or disabled, unless vt_aabd_ep_nonspouse_essential_person is set." + + def formula(person, period, parameters): + abd = person("is_ssi_aged_blind_disabled", period.this_year) + # A marital unit has at most two members, so a non-ABD member of an + # ABD person's marital unit is that person's spouse. + return ( + abd + & person.marital_unit.any(~abd) + & ~person("vt_aabd_ep_nonspouse_essential_person", period) + ) diff --git a/policyengine_us/variables/gov/states/vt/dcf/aabd/vt_aabd_ep_level.py b/policyengine_us/variables/gov/states/vt/dcf/aabd/vt_aabd_ep_level.py new file mode 100644 index 00000000000..02a5e86c2b1 --- /dev/null +++ b/policyengine_us/variables/gov/states/vt/dcf/aabd/vt_aabd_ep_level.py @@ -0,0 +1,30 @@ +from policyengine_us.model_api import * + + +class VTAABDEssentialPersonLevel(Enum): + FULL = "Certified full Essential Person care level" + PARTIAL_67 = "Certified 67 percent Essential Person care level" + PARTIAL_34 = "Certified 34 percent Essential Person care level" + NONE = "No certified Essential Person arrangement" + + +class vt_aabd_ep_level(Variable): + value_type = Enum + entity = Person + label = "Vermont certified Essential Person care level" + definition_period = MONTH + possible_values = VTAABDEssentialPersonLevel + default_value = VTAABDEssentialPersonLevel.NONE + # PDF pages 38, 40-41, 44 + reference = "https://outside.vermont.gov/dept/DCF/Shared%20Documents/ESD/Rules/2700-AABD.pdf#page=38" + documentation = """ + Certified co-resident essential person under rules 2781-2784: full for + an ineligible spouse 55 or older, or required personal care, or seven + homemaker services; 67 percent for a younger spouse unable to work who + provides qualifying care, or a nonspouse providing four to six services; + 34 percent for a nonspouse providing one to three services. Certification + includes benefit pursuit and care preventing institutionalization. Set it + on the aged, blind or disabled recipient, not on the essential person; for + an eligible couple, set it on either spouse and the couple's grant uses the + highest level set on either spouse. + """ diff --git a/policyengine_us/variables/gov/states/vt/dcf/aabd/vt_aabd_ep_nonspouse_essential_person.py b/policyengine_us/variables/gov/states/vt/dcf/aabd/vt_aabd_ep_nonspouse_essential_person.py new file mode 100644 index 00000000000..f5e5a229a02 --- /dev/null +++ b/policyengine_us/variables/gov/states/vt/dcf/aabd/vt_aabd_ep_nonspouse_essential_person.py @@ -0,0 +1,13 @@ +from policyengine_us.model_api import * + + +class vt_aabd_ep_nonspouse_essential_person(Variable): + value_type = bool + entity = Person + label = "Vermont AABD recipient's certified Essential Person is not the spouse" + definition_period = MONTH + defined_for = StateCode.VT + default_value = False + # PDF pages 38, 40, 42 + reference = "https://outside.vermont.gov/dept/DCF/Shared%20Documents/ESD/Rules/2700-AABD.pdf#page=38" + documentation = "Set on the aged, blind or disabled recipient whose ineligible spouse lives with them but is not the certified essential person (rule 2781(E)); rule 2782 allows both in one assistance group." diff --git a/policyengine_us/variables/gov/states/vt/dcf/aabd/vt_aabd_ep_passes_state_resource_test.py b/policyengine_us/variables/gov/states/vt/dcf/aabd/vt_aabd_ep_passes_state_resource_test.py new file mode 100644 index 00000000000..0cd06e28150 --- /dev/null +++ b/policyengine_us/variables/gov/states/vt/dcf/aabd/vt_aabd_ep_passes_state_resource_test.py @@ -0,0 +1,13 @@ +from policyengine_us.model_api import * + + +class vt_aabd_ep_passes_state_resource_test(Variable): + value_type = bool + entity = Person + label = "Vermont Essential Person state resource test passed" + definition_period = MONTH + defined_for = StateCode.VT + default_value = False + # PDF pages 46-48 + reference = "https://outside.vermont.gov/dept/DCF/Shared%20Documents/ESD/Rules/2700-AABD.pdf#page=46" + documentation = "Resource determination for state-only applicants under rule 2785, including Reach Up resource exclusions as of August 2024, Medicaid limits, and nonspouse dependent proration. SSI/AABD receipt by a household member of the group passes the resource test without this input." diff --git a/policyengine_us/variables/gov/states/vt/dcf/aabd/vt_aabd_ep_resources_eligible.py b/policyengine_us/variables/gov/states/vt/dcf/aabd/vt_aabd_ep_resources_eligible.py new file mode 100644 index 00000000000..b05591f9e52 --- /dev/null +++ b/policyengine_us/variables/gov/states/vt/dcf/aabd/vt_aabd_ep_resources_eligible.py @@ -0,0 +1,29 @@ +from policyengine_us.model_api import * + + +class vt_aabd_ep_resources_eligible(Variable): + value_type = bool + entity = Person + label = "Vermont Essential Person resource eligibility" + definition_period = MONTH + # PDF pages 42, 46-47 + reference = "https://outside.vermont.gov/dept/DCF/Shared%20Documents/ESD/Rules/2700-AABD.pdf#page=42" + documentation = "SSI/AABD receipt by a member of the assistance group living in the same household automatically passes the resource test; otherwise the group passes through vt_aabd_ep_passes_state_resource_test." + + def formula(person, period, parameters): + receives = ( + (person("ssi", period) > 0) + | person("receives_ssi", period) + | (person("vt_aabd_federal", period) > 0) + ) + passes_state_test = person("vt_aabd_ep_passes_state_resource_test", period) + arrangement = person("vt_aabd_living_arrangement", period) + la = arrangement.possible_values + # Rule 2782: the group includes only members living in the same + # household, so a spouse in a facility cannot pass the test for the + # spouse at home. + in_household = (arrangement == la.INDEPENDENT) | ( + arrangement == la.HOUSEHOLD_OF_ANOTHER + ) + # Rule 2785 tests the assistance group's combined resources once. + return person.marital_unit.any((receives | passes_state_test) & in_household) diff --git a/policyengine_us/variables/gov/states/vt/dcf/aabd/vt_aabd_federal.py b/policyengine_us/variables/gov/states/vt/dcf/aabd/vt_aabd_federal.py new file mode 100644 index 00000000000..7d450b5f1df --- /dev/null +++ b/policyengine_us/variables/gov/states/vt/dcf/aabd/vt_aabd_federal.py @@ -0,0 +1,22 @@ +from policyengine_us.model_api import * +from policyengine_us.variables.gov.ssa.ssi._ssi_state_supplement import ( + ssi_state_supplement, +) + + +class vt_aabd_federal(Variable): + value_type = float + entity = Person + label = "Vermont federally administered AABD supplement" + definition_period = MONTH + unit = USD + defined_for = StateCode.VT + reference = "https://secure.ssa.gov/poms.nsf/lnx/0501415058#m2" + + def formula(person, period, parameters): + p = parameters(period).gov.states.vt.dcf.aabd.amount + arrangement = person("vt_aabd_living_arrangement", period) + # NOTE: A spouse who declines SSI still makes a joint claim (issue 10243). + return ssi_state_supplement( + person, period, parameters, p.individual[arrangement], p.couple[arrangement] + ) diff --git a/policyengine_us/variables/gov/states/vt/dcf/aabd/vt_aabd_living_arrangement.py b/policyengine_us/variables/gov/states/vt/dcf/aabd/vt_aabd_living_arrangement.py new file mode 100644 index 00000000000..5b63538d64f --- /dev/null +++ b/policyengine_us/variables/gov/states/vt/dcf/aabd/vt_aabd_living_arrangement.py @@ -0,0 +1,72 @@ +from policyengine_us.model_api import * +from policyengine_us.variables.gov.ssa.ssi.eligibility.status.ssi_federal_living_arrangement import ( + SSIFederalLivingArrangement, +) + + +class VTAABDLivingArrangement(Enum): + INDEPENDENT = "Independent living" + HOUSEHOLD_OF_ANOTHER = "Living in another household" + RESIDENTIAL_CARE_LEVEL_III = ( + "Level III residential care with assistive community care (PNMI, code C)" + ) + RESIDENTIAL_CARE_LEVEL_IV = ( + "State-identified Level IV residential or therapeutic care" + ) + CUSTODIAL_CARE = "Qualifying custodial family home" + MEDICAID_INSTITUTION = "Title XIX medical institution" + NONE = "No supplement" + + +class vt_aabd_living_arrangement(Variable): + value_type = Enum + entity = Person + label = "Vermont AABD living arrangement" + definition_period = MONTH + defined_for = StateCode.VT + possible_values = VTAABDLivingArrangement + default_value = VTAABDLivingArrangement.NONE + reference = ( + "https://secure.ssa.gov/poms.nsf/lnx/0501415058#m1", + "https://secure.ssa.gov/poms.nsf/lnx/0501415970BOS", + "https://secure.ssa.gov/poms.nsf/lnx/0501415013BOS", + # PDF pages 28, 31 + "https://outside.vermont.gov/dept/DCF/Shared%20Documents/ESD/Rules/2700-AABD.pdf#page=28", + ) + documentation = """ + Defaults follow federal SSI living arrangements. Residential and custodial + care settings come from vt_aabd_care_setting; those residents are in + federal arrangement A, so do not also set the household-of-another SSI + inputs for them. Independent rates are identical inside and outside + Chittenden County in 2026. Children under 18 in a facility paid by private + health insurance map to independent living (SI BOS01415.970). The + state-administered Level III residential care home with limited nursing + care (rule 2764.2) is not modeled; SI BOS01415.013 reports that all such + homes converted to code C. + NOTE: OS code Y (optional supplementation waived) records a recipient's + choice and is not modeled. + """ + + def formula(person, period, parameters): + federal = person("ssi_federal_living_arrangement", period) + setting = person("vt_aabd_care_setting", period) + settings = setting.possible_values + # POMS SI 01415.058 M.2.a pairs codes C, G and H only with federal + # arrangement A, and code I only with federal arrangement D. + return select( + [ + federal == SSIFederalLivingArrangement.MEDICAL_TREATMENT_FACILITY, + setting == settings.RESIDENTIAL_CARE_LEVEL_III, + setting == settings.RESIDENTIAL_CARE_LEVEL_IV, + setting == settings.CUSTODIAL_CARE, + federal == SSIFederalLivingArrangement.ANOTHER_PERSONS_HOUSEHOLD, + ], + [ + VTAABDLivingArrangement.MEDICAID_INSTITUTION, + VTAABDLivingArrangement.RESIDENTIAL_CARE_LEVEL_III, + VTAABDLivingArrangement.RESIDENTIAL_CARE_LEVEL_IV, + VTAABDLivingArrangement.CUSTODIAL_CARE, + VTAABDLivingArrangement.HOUSEHOLD_OF_ANOTHER, + ], + default=VTAABDLivingArrangement.INDEPENDENT, + ) 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 4613c4da26a..c17d80d8f85 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 + "vt_aabd", # Vermont benefits "ky_ssp", # Kentucky benefits "de_ssp", # Delaware benefits "fl_oss",