diff --git a/changelog.d/ar-ccap.added.md b/changelog.d/ar-ccap.added.md new file mode 100644 index 00000000000..3d5bcb1f69e --- /dev/null +++ b/changelog.d/ar-ccap.added.md @@ -0,0 +1 @@ +Add Arkansas School Readiness Assistance (SRA) child care subsidy program. The 4% per-family copay ceiling is computed against countable (adult) income — children's SSI and Social Security are excluded per FSU §4.3.3 — and the per-child copay used in that ceiling is clamped to the child's actual provider charge. The ESS Year-1 alt path (FSU §4.1.5.1) is gated on earned income alone exceeding the TEA limit, consistent with the regulation's "earnings alone" wording. diff --git a/policyengine_us/parameters/gov/hhs/ccdf/child_care_subsidy_programs.yaml b/policyengine_us/parameters/gov/hhs/ccdf/child_care_subsidy_programs.yaml index ed0f0a42c7d..f3866ded467 100644 --- a/policyengine_us/parameters/gov/hhs/ccdf/child_care_subsidy_programs.yaml +++ b/policyengine_us/parameters/gov/hhs/ccdf/child_care_subsidy_programs.yaml @@ -2,6 +2,7 @@ description: The federal government counts these state programs as child care su values: 2021-01-01: - ak_child_care_subsidies # Alaska Child Care Assistance Program (PASS) + - ar_child_care_subsidies # Arkansas School Readiness Assistance - ca_child_care_subsidies # California Child Care - co_child_care_subsidies # Colorado Child Care Assistance Program - ct_child_care_subsidies # Connecticut Care 4 Kids diff --git a/policyengine_us/parameters/gov/household/household_state_benefits.yaml b/policyengine_us/parameters/gov/household/household_state_benefits.yaml index b74241a36b5..52bda3a5887 100644 --- a/policyengine_us/parameters/gov/household/household_state_benefits.yaml +++ b/policyengine_us/parameters/gov/household/household_state_benefits.yaml @@ -136,6 +136,8 @@ values: - wa_rca # Louisiana benefits - la_oss + # Arkansas benefits + - ar_child_care_subsidies metadata: unit: list period: year diff --git a/policyengine_us/parameters/gov/states/ar/ade/oec/sra/eligibility/activity_hours_ess_year_1.yaml b/policyengine_us/parameters/gov/states/ar/ade/oec/sra/eligibility/activity_hours_ess_year_1.yaml new file mode 100644 index 00000000000..77c915e2b3c --- /dev/null +++ b/policyengine_us/parameters/gov/states/ar/ade/oec/sra/eligibility/activity_hours_ess_year_1.yaml @@ -0,0 +1,13 @@ +description: Arkansas sets this minimum weekly activity hours threshold for at least one adult in an Employment-Sponsored Subsidy Year 1 household under the School Readiness Assistance program. +values: + 2025-10-01: 20 + +metadata: + unit: hour + period: year + label: Arkansas SRA ESS Year 1 weekly activity hours + reference: + - title: FSU Procedural Manual (June 2023), Section 4.1.5.1 Employment + href: https://dese.ade.arkansas.gov/Files/FSU-Procedural-Manual-June-2023_UPDATED_20230629075344.pdf#page=16 + - title: OEC Rights & Responsibilities (Nov 2025) + href: https://dese.ade.arkansas.gov/Files/R_&_R__Nov_2025_(English)_(1)_OEC.pdf#page=1 diff --git a/policyengine_us/parameters/gov/states/ar/ade/oec/sra/eligibility/activity_hours_ess_year_2.yaml b/policyengine_us/parameters/gov/states/ar/ade/oec/sra/eligibility/activity_hours_ess_year_2.yaml new file mode 100644 index 00000000000..7fdbc3422e0 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ar/ade/oec/sra/eligibility/activity_hours_ess_year_2.yaml @@ -0,0 +1,13 @@ +description: Arkansas sets this minimum weekly activity hours threshold for at least one adult in an Employment-Sponsored Subsidy Year 2 household under the School Readiness Assistance program. +values: + 2025-10-01: 25 + +metadata: + unit: hour + period: year + label: Arkansas SRA ESS Year 2 weekly activity hours + reference: + - title: FSU Procedural Manual (June 2023), Section 4.1.5.1 Employment + href: https://dese.ade.arkansas.gov/Files/FSU-Procedural-Manual-June-2023_UPDATED_20230629075344.pdf#page=16 + - title: OEC Rights & Responsibilities (Nov 2025) + href: https://dese.ade.arkansas.gov/Files/R_&_R__Nov_2025_(English)_(1)_OEC.pdf#page=1 diff --git a/policyengine_us/parameters/gov/states/ar/ade/oec/sra/eligibility/activity_hours_li.yaml b/policyengine_us/parameters/gov/states/ar/ade/oec/sra/eligibility/activity_hours_li.yaml new file mode 100644 index 00000000000..9779ccf5f13 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ar/ade/oec/sra/eligibility/activity_hours_li.yaml @@ -0,0 +1,15 @@ +description: Arkansas sets this minimum weekly activity hours threshold for each adult in a Low-Income household under the School Readiness Assistance program. +# Applies to the Low-Income (LI) track only. ESS thresholds live in +# activity_hours_ess_year_1.yaml and activity_hours_ess_year_2.yaml. +values: + 2025-10-01: 30 + +metadata: + unit: hour + period: year + label: Arkansas SRA Low-Income weekly activity hours + reference: + - title: FSU Procedural Manual (June 2023), Section 4.1.5.1 Employment + href: https://dese.ade.arkansas.gov/Files/FSU-Procedural-Manual-June-2023_UPDATED_20230629075344.pdf#page=16 + - title: OEC Rights & Responsibilities (Nov 2025) + href: https://dese.ade.arkansas.gov/Files/R_&_R__Nov_2025_(English)_(1)_OEC.pdf#page=1 diff --git a/policyengine_us/parameters/gov/states/ar/ade/oec/sra/eligibility/adult_age_threshold.yaml b/policyengine_us/parameters/gov/states/ar/ade/oec/sra/eligibility/adult_age_threshold.yaml new file mode 100644 index 00000000000..75bead2cb80 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ar/ade/oec/sra/eligibility/adult_age_threshold.yaml @@ -0,0 +1,11 @@ +description: Arkansas treats household members at or above this age as adults under the School Readiness Assistance program. +values: + 2025-10-01: 18 + +metadata: + unit: year + period: year + label: Arkansas SRA adult age threshold + reference: + - title: FSU Procedural Manual (June 2023), Section 4.3 Income (defines parents/custodians "age eighteen (18) years and over") + href: https://dese.ade.arkansas.gov/Files/FSU-Procedural-Manual-June-2023_UPDATED_20230629075344.pdf#page=19 diff --git a/policyengine_us/parameters/gov/states/ar/ade/oec/sra/eligibility/child_age_limit.yaml b/policyengine_us/parameters/gov/states/ar/ade/oec/sra/eligibility/child_age_limit.yaml new file mode 100644 index 00000000000..ff6b13fc4a7 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ar/ade/oec/sra/eligibility/child_age_limit.yaml @@ -0,0 +1,11 @@ +description: Arkansas limits the School Readiness Assistance program to children younger than this age. +values: + 2025-10-01: 13 + +metadata: + unit: year + period: year + label: Arkansas SRA child age limit + reference: + - title: Arkansas CCDF Plan 2025-2027, Section 2.2.1 Eligibility Definitions + href: https://dese.ade.arkansas.gov/Files/2025-2027_CCDF_State_Plan_Final_4.26.24.1REV_OEC.pdf#page=18 diff --git a/policyengine_us/parameters/gov/states/ar/ade/oec/sra/eligibility/child_age_limit_disabled.yaml b/policyengine_us/parameters/gov/states/ar/ade/oec/sra/eligibility/child_age_limit_disabled.yaml new file mode 100644 index 00000000000..9d7c238cb39 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ar/ade/oec/sra/eligibility/child_age_limit_disabled.yaml @@ -0,0 +1,13 @@ +description: Arkansas extends School Readiness Assistance eligibility to children with verified disabilities under this age. +values: + 2025-10-01: 19 + +metadata: + unit: year + period: year + label: Arkansas SRA child age limit (disabled extension) + reference: + - title: Arkansas CCDF Plan 2025-2027, Section 2.2.1 Eligibility Definitions + href: https://dese.ade.arkansas.gov/Files/2025-2027_CCDF_State_Plan_Final_4.26.24.1REV_OEC.pdf#page=18 + - title: Arkansas FSU Procedural Manual, Section 5.6.1 Priority and Waiver Types — Children with Special Needs + href: https://dese.ade.arkansas.gov/Files/FSU-Procedural-Manual-June-2023_UPDATED_20230629075344.pdf#page=32 diff --git a/policyengine_us/parameters/gov/states/ar/ade/oec/sra/eligibility/ess_window_months.yaml b/policyengine_us/parameters/gov/states/ar/ade/oec/sra/eligibility/ess_window_months.yaml new file mode 100644 index 00000000000..e2fafe1c6ff --- /dev/null +++ b/policyengine_us/parameters/gov/states/ar/ade/oec/sra/eligibility/ess_window_months.yaml @@ -0,0 +1,11 @@ +description: Arkansas limits the Employment-Sponsored Subsidy post-Transitional Employment Assistance window to this many months under the School Readiness Assistance program. +values: + 2025-10-01: 24 + +metadata: + unit: month + period: year + label: Arkansas SRA ESS post-TEA window months + reference: + - title: FSU Procedural Manual (June 2023), Section 5.4.1 + href: https://dese.ade.arkansas.gov/Files/FSU-Procedural-Manual-June-2023_UPDATED_20230629075344.pdf#page=26 diff --git a/policyengine_us/parameters/gov/states/ar/ade/oec/sra/eligibility/ess_year_1_window_months.yaml b/policyengine_us/parameters/gov/states/ar/ade/oec/sra/eligibility/ess_year_1_window_months.yaml new file mode 100644 index 00000000000..47b276f9de8 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ar/ade/oec/sra/eligibility/ess_year_1_window_months.yaml @@ -0,0 +1,11 @@ +description: Arkansas sets this many months as the Employment-Sponsored Subsidy Year 1 window under the School Readiness Assistance program. +values: + 2025-10-01: 12 + +metadata: + unit: month + period: year + label: Arkansas SRA ESS Year 1 window months + reference: + - title: FSU Procedural Manual (June 2023), Section 4.1.5.1 Employment + href: https://dese.ade.arkansas.gov/Files/FSU-Procedural-Manual-June-2023_UPDATED_20230629075344.pdf#page=16 diff --git a/policyengine_us/parameters/gov/states/ar/ade/oec/sra/eligibility/income_smi_rate.yaml b/policyengine_us/parameters/gov/states/ar/ade/oec/sra/eligibility/income_smi_rate.yaml new file mode 100644 index 00000000000..a3e87db921a --- /dev/null +++ b/policyengine_us/parameters/gov/states/ar/ade/oec/sra/eligibility/income_smi_rate.yaml @@ -0,0 +1,11 @@ +description: Arkansas limits gross income to this share of the state median income under the School Readiness Assistance program. +values: + 2025-10-01: 0.85 + +metadata: + unit: /1 + period: year + label: Arkansas SRA income limit SMI rate + reference: + - title: Arkansas CCDF Plan 2025-2027, Section 2.2.4 + href: https://dese.ade.arkansas.gov/Files/2025-2027_CCDF_State_Plan_Final_4.26.24.1REV_OEC.pdf#page=22 diff --git a/policyengine_us/parameters/gov/states/ar/ade/oec/sra/in_effect.yaml b/policyengine_us/parameters/gov/states/ar/ade/oec/sra/in_effect.yaml new file mode 100644 index 00000000000..462c3404514 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ar/ade/oec/sra/in_effect.yaml @@ -0,0 +1,19 @@ +description: Arkansas uses this indicator to determine whether the School Readiness Assistance program applies. +# The SRA program legally launched 2025-10-01, but the Oct 2025 rate schedule +# (higher rates plus a one-month Quality Enhancement Payment) was replaced on +# 2025-11-01 by the rate sheet currently encoded. We gate the program to the +# Nov 1, 2025 rate-aligned period; the Oct 2025 transitional month is not +# modeled because its rates and QEP supplement are not in the parameter tree. +values: + 1900-01-01: false + 2025-11-01: true + +metadata: + unit: bool + period: month + label: Arkansas SRA in effect + reference: + - title: OEC Rights & Responsibilities (Nov 2025) + href: https://dese.ade.arkansas.gov/Files/R_&_R__Nov_2025_(English)_(1)_OEC.pdf#page=1 + - title: OEC SRA Announcement Regarding Rates and Copays Effective November 1 + href: https://dese.ade.arkansas.gov/Files/OEC_SRA_Announcement_Regarding_Rates_and_Copays_Effective_November_1_OEC.pdf diff --git a/policyengine_us/parameters/gov/states/ar/ade/oec/sra/income/sources.yaml b/policyengine_us/parameters/gov/states/ar/ade/oec/sra/income/sources.yaml new file mode 100644 index 00000000000..fcdfecd2200 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ar/ade/oec/sra/income/sources.yaml @@ -0,0 +1,39 @@ +description: Arkansas uses these income sources for adults under the School Readiness Assistance program. +values: + 2025-10-01: + - employment_income + - self_employment_income + - social_security_retirement + - social_security_disability + - social_security_survivors + - ssi + - unemployment_compensation + - workers_compensation + - alimony_income + - pension_income + - interest_income + - dividend_income + - rental_income + - military_retirement_pay + - veterans_benefits + # The following are counted per FSU Procedural Manual Section 4.3.1-4.3.2 + # but have no matching variables: + # - PTO and stipends (VISTA, AmeriCorps, Job Corps, OJT) + # - regular bonuses, commissions + # - armed forces pay (other than retirement) + # - piece-rate, in-kind, contractual income + # - annuities, regular contributions + # Children's SSI and Social Security are excluded; the formula filters + # contributions by age before summing. + +metadata: + unit: list + period: year + label: Arkansas SRA countable income sources + reference: + - title: FSU Procedural Manual (June 2023), Section 4.3.1 Countable Earned Income + href: https://dese.ade.arkansas.gov/Files/FSU-Procedural-Manual-June-2023_UPDATED_20230629075344.pdf#page=19 + - title: FSU Procedural Manual (June 2023), Section 4.3.2 Countable Unearned Income + href: https://dese.ade.arkansas.gov/Files/FSU-Procedural-Manual-June-2023_UPDATED_20230629075344.pdf#page=20 + - title: Arkansas CCDF Plan 2025-2027, Section 2.2.4(c) Income Definition + href: https://dese.ade.arkansas.gov/Files/2025-2027_CCDF_State_Plan_Final_4.26.24.1REV_OEC.pdf#page=24 diff --git a/policyengine_us/parameters/gov/states/ar/ade/oec/sra/rates/age_category_months.yaml b/policyengine_us/parameters/gov/states/ar/ade/oec/sra/rates/age_category_months.yaml new file mode 100644 index 00000000000..d420061baf5 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ar/ade/oec/sra/rates/age_category_months.yaml @@ -0,0 +1,38 @@ +description: Arkansas sets these age thresholds in months for age categories under the School Readiness Assistance program. +# Boundaries follow the 2020 AR Min Licensing Requirements for Child Care Centers +# (Infant Center: birth to 18 months; Toddler Center: 18 to 36 months; School-Age +# Care: kindergarten and above per Ark. Code 6-18-207, age 5 by Aug 1 of the +# school year). Preschool fills the gap (36-71 months); the school-aged 72-month +# boundary uses typical kindergarten entry rather than the strict 60-month minimum. + +brackets: + - threshold: + 2025-10-01: 0 + amount: + 2025-10-01: 0 # INFANT (0-17 months) + - threshold: + 2025-10-01: 18 + amount: + 2025-10-01: 1 # TODDLER (18-35 months) + - threshold: + 2025-10-01: 36 + amount: + 2025-10-01: 2 # PRESCHOOL (36-71 months) + - threshold: + 2025-10-01: 72 + amount: + 2025-10-01: 3 # SCHOOL_AGED (72+ months) + +metadata: + type: single_amount + threshold_unit: month + amount_unit: /1 + period: year + label: Arkansas SRA age category month thresholds + reference: + - title: SRA Sliding Fee Scale with Rates and Copays - Statewide Full Time (Nov 1, 2025) - age category labels + href: https://dese.ade.arkansas.gov/Files/SRA_Sliding_Fee_Scale_with_Rates_&_Copays--Statewide_Full_Time_20251101_OEC.pdf + - title: AR Minimum Licensing Requirements for Child Care Centers (DCCECE, 2020) - Infant Center (item 13), Toddler Center (item 21), School Age Care (item 22) + href: https://humanservices.arkansas.gov/wp-content/uploads/2020-Child-Care-centers.pdf#page=45 + - title: Arkansas Code Annotated § 6-18-207 (Compulsory school age, kindergarten by Aug 1) + href: https://law.justia.com/codes/arkansas/title-6/subtitle-2/chapter-18/subchapter-2/section-6-18-207/ diff --git a/policyengine_us/parameters/gov/states/ar/ade/oec/sra/rates/base_rate.yaml b/policyengine_us/parameters/gov/states/ar/ade/oec/sra/rates/base_rate.yaml new file mode 100644 index 00000000000..d50facf0ebd --- /dev/null +++ b/policyengine_us/parameters/gov/states/ar/ade/oec/sra/rates/base_rate.yaml @@ -0,0 +1,238 @@ +description: Arkansas provides these daily base reimbursement rates under the School Readiness Assistance program. +# Source rate sheets have no Part-Time Night/Weekend row. Per the October 7 2025 +# Provider Call ("Weekend and night time rates are set at a standard 10% increase +# of typical rates"), PT NIGHT_WEEKEND cells below are derived as PT REGULAR × 1.10. +# Note: under the Nov 1 2025 schedule, Benton/Washington and Statewide rates +# converge for Preschool ($33 FT / $16.50 PT) and School-Aged ($28 FT / $14 PT) — +# the regional premium only applies to Infant and Toddler. Verified at 1200 DPI +# against the four Nov-2025 Sliding Fee Scale PDFs. +metadata: + period: day + unit: currency-USD + label: Arkansas SRA daily base rates + breakdown: + - ar_sra_zone + - ar_sra_age_category + - ar_sra_care_type + - ar_sra_time_category + reference: + - title: SRA Sliding Fee Scale with Rates and Copays - Statewide Full Time (Nov 1, 2025) + href: https://dese.ade.arkansas.gov/Files/SRA_Sliding_Fee_Scale_with_Rates_&_Copays--Statewide_Full_Time_20251101_OEC.pdf + - title: SRA Sliding Fee Scale with Rates and Copays - Statewide Part Time (Nov 1, 2025) + href: https://dese.ade.arkansas.gov/Files/SRA_Sliding_Fee_Scale_with_Rates_&_Copays--Statewide_Part_Time_20251101_OEC.pdf + - title: SRA Sliding Fee Scale with Rates and Copays - Benton/Washington Full Time (Nov 1, 2025) + href: https://dese.ade.arkansas.gov/Files/SRA_Sliding_Fee_Scale_with_Rates_&_Copays--Benton-Washington_Co_Full_Time_20251101_OEC.pdf + - title: SRA Sliding Fee Scale with Rates and Copays - Benton/Washington Part Time (Nov 1, 2025) + href: https://dese.ade.arkansas.gov/Files/SRA_Sliding_Fee_Scale_with_Rates_&_Copays--Benton-Washington_Co_Part_Time_20251101_OEC.pdf + +BENTON_WASHINGTON: + INFANT: + REGULAR: + FULL_TIME: + 2025-11-01: 38 + PART_TIME: + 2025-11-01: 19 + NIGHT_WEEKEND: + FULL_TIME: + 2025-11-01: 41.8 + PART_TIME: + 2025-11-01: 20.9 + SN1: + FULL_TIME: + 2025-11-01: 38 + PART_TIME: + 2025-11-01: 19 + SN2: + FULL_TIME: + 2025-11-01: 53.2 + PART_TIME: + 2025-11-01: 26.6 + SN3: + FULL_TIME: + 2025-11-01: 53.2 + PART_TIME: + 2025-11-01: 26.6 + TODDLER: + REGULAR: + FULL_TIME: + 2025-11-01: 37 + PART_TIME: + 2025-11-01: 18.5 + NIGHT_WEEKEND: + FULL_TIME: + 2025-11-01: 40.7 + PART_TIME: + 2025-11-01: 20.35 + SN1: + FULL_TIME: + 2025-11-01: 37 + PART_TIME: + 2025-11-01: 18.5 + SN2: + FULL_TIME: + 2025-11-01: 51.8 + PART_TIME: + 2025-11-01: 25.9 + SN3: + FULL_TIME: + 2025-11-01: 51.8 + PART_TIME: + 2025-11-01: 25.9 + PRESCHOOL: + REGULAR: + FULL_TIME: + 2025-11-01: 33 + PART_TIME: + 2025-11-01: 16.5 + NIGHT_WEEKEND: + FULL_TIME: + 2025-11-01: 36.3 + PART_TIME: + 2025-11-01: 18.15 + SN1: + FULL_TIME: + 2025-11-01: 33 + PART_TIME: + 2025-11-01: 16.5 + SN2: + FULL_TIME: + 2025-11-01: 46.2 + PART_TIME: + 2025-11-01: 23.1 + SN3: + FULL_TIME: + 2025-11-01: 46.2 + PART_TIME: + 2025-11-01: 23.1 + SCHOOL_AGED: + REGULAR: + FULL_TIME: + 2025-11-01: 28 + PART_TIME: + 2025-11-01: 14 + NIGHT_WEEKEND: + FULL_TIME: + 2025-11-01: 30.8 + PART_TIME: + 2025-11-01: 15.4 + SN1: + FULL_TIME: + 2025-11-01: 28 + PART_TIME: + 2025-11-01: 14 + SN2: + FULL_TIME: + 2025-11-01: 39.2 + PART_TIME: + 2025-11-01: 19.6 + SN3: + FULL_TIME: + 2025-11-01: 39.2 + PART_TIME: + 2025-11-01: 19.6 + +STATEWIDE: + INFANT: + REGULAR: + FULL_TIME: + 2025-11-01: 36 + PART_TIME: + 2025-11-01: 18 + NIGHT_WEEKEND: + FULL_TIME: + 2025-11-01: 39.6 + PART_TIME: + 2025-11-01: 19.8 + SN1: + FULL_TIME: + 2025-11-01: 36 + PART_TIME: + 2025-11-01: 18 + SN2: + FULL_TIME: + 2025-11-01: 50.4 + PART_TIME: + 2025-11-01: 25.2 + SN3: + FULL_TIME: + 2025-11-01: 50.4 + PART_TIME: + 2025-11-01: 25.2 + TODDLER: + REGULAR: + FULL_TIME: + 2025-11-01: 35 + PART_TIME: + 2025-11-01: 17.5 + NIGHT_WEEKEND: + FULL_TIME: + 2025-11-01: 38.5 + PART_TIME: + 2025-11-01: 19.25 + SN1: + FULL_TIME: + 2025-11-01: 35 + PART_TIME: + 2025-11-01: 17.5 + SN2: + FULL_TIME: + 2025-11-01: 49 + PART_TIME: + 2025-11-01: 24.5 + SN3: + FULL_TIME: + 2025-11-01: 49 + PART_TIME: + 2025-11-01: 24.5 + PRESCHOOL: + REGULAR: + FULL_TIME: + 2025-11-01: 33 + PART_TIME: + 2025-11-01: 16.5 + NIGHT_WEEKEND: + FULL_TIME: + 2025-11-01: 36.3 + PART_TIME: + 2025-11-01: 18.15 + SN1: + FULL_TIME: + 2025-11-01: 33 + PART_TIME: + 2025-11-01: 16.5 + SN2: + FULL_TIME: + 2025-11-01: 46.2 + PART_TIME: + 2025-11-01: 23.1 + SN3: + FULL_TIME: + 2025-11-01: 46.2 + PART_TIME: + 2025-11-01: 23.1 + SCHOOL_AGED: + REGULAR: + FULL_TIME: + 2025-11-01: 28 + PART_TIME: + 2025-11-01: 14 + NIGHT_WEEKEND: + FULL_TIME: + 2025-11-01: 30.8 + PART_TIME: + 2025-11-01: 15.4 + SN1: + FULL_TIME: + 2025-11-01: 28 + PART_TIME: + 2025-11-01: 14 + SN2: + FULL_TIME: + 2025-11-01: 39.2 + PART_TIME: + 2025-11-01: 19.6 + SN3: + FULL_TIME: + 2025-11-01: 39.2 + PART_TIME: + 2025-11-01: 19.6 diff --git a/policyengine_us/parameters/gov/states/ar/ade/oec/sra/rates/benton_washington_counties.yaml b/policyengine_us/parameters/gov/states/ar/ade/oec/sra/rates/benton_washington_counties.yaml new file mode 100644 index 00000000000..f4260904c08 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ar/ade/oec/sra/rates/benton_washington_counties.yaml @@ -0,0 +1,15 @@ +description: Arkansas uses these counties as the higher-cost Benton/Washington reimbursement zone under the School Readiness Assistance program. +values: + 2025-10-01: + - BENTON_COUNTY_AR + - WASHINGTON_COUNTY_AR + +metadata: + unit: list + period: year + label: Arkansas SRA Benton/Washington counties + reference: + - title: SRA Sliding Fee Scale - Benton/Washington Co Full Time (Nov 1, 2025) + href: https://dese.ade.arkansas.gov/Files/SRA_Sliding_Fee_Scale_with_Rates_&_Copays--Benton-Washington_Co_Full_Time_20251101_OEC.pdf + - title: SRA Sliding Fee Scale - Benton/Washington Co Part Time (Nov 1, 2025) + href: https://dese.ade.arkansas.gov/Files/SRA_Sliding_Fee_Scale_with_Rates_&_Copays--Benton-Washington_Co_Part_Time_20251101_OEC.pdf diff --git a/policyengine_us/parameters/gov/states/ar/ade/oec/sra/rates/full_time_hours_threshold.yaml b/policyengine_us/parameters/gov/states/ar/ade/oec/sra/rates/full_time_hours_threshold.yaml new file mode 100644 index 00000000000..c30568a855e --- /dev/null +++ b/policyengine_us/parameters/gov/states/ar/ade/oec/sra/rates/full_time_hours_threshold.yaml @@ -0,0 +1,15 @@ +description: Arkansas sets this daily hours threshold for full-time child care under the School Readiness Assistance program. +values: + 2025-10-01: 7 + +metadata: + unit: hour + period: year + label: Arkansas SRA full-time daily hours threshold + reference: + - title: FSU Procedural Manual (June 2023), Section 5.4.6 Level of Care Authorized + href: https://dese.ade.arkansas.gov/Files/FSU-Procedural-Manual-June-2023_UPDATED_20230629075344.pdf#page=30 + - title: SRA Sliding Fee Scale - Statewide Full Time (Nov 1, 2025) - establishes Full Time category + href: https://dese.ade.arkansas.gov/Files/SRA_Sliding_Fee_Scale_with_Rates_&_Copays--Statewide_Full_Time_20251101_OEC.pdf + - title: SRA Sliding Fee Scale - Statewide Part Time (Nov 1, 2025) - establishes Part Time category + href: https://dese.ade.arkansas.gov/Files/SRA_Sliding_Fee_Scale_with_Rates_&_Copays--Statewide_Part_Time_20251101_OEC.pdf diff --git a/policyengine_us/parameters/gov/states/ar/ade/oec/sra/rates/max_copay_share_of_gross_income.yaml b/policyengine_us/parameters/gov/states/ar/ade/oec/sra/rates/max_copay_share_of_gross_income.yaml new file mode 100644 index 00000000000..72df0715652 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ar/ade/oec/sra/rates/max_copay_share_of_gross_income.yaml @@ -0,0 +1,17 @@ +description: Arkansas caps the total family copay at this share of countable monthly income under the School Readiness Assistance program. +# CCDF rules cap copays at 7% of gross family income; Arkansas's CCDF State +# Plan §3.1.1 self-certifies a stricter 4% maximum. The cap applies per +# family, regardless of the number of children participating in CCDF. +# The State Plan's "gross income" wording is reconciled against FSU §4.3.3 +# (file p.20), which excludes children's SSI and Social Security from the +# budget — the cap base is therefore countable (adult) income. +values: + 2025-11-01: 0.04 + +metadata: + unit: /1 + period: year + label: Arkansas SRA maximum family copay share of gross income + reference: + - title: Arkansas CCDF Plan 2025-2027, Section 3.1.1 Family Co-payment + href: https://dese.ade.arkansas.gov/Files/2025-2027_CCDF_State_Plan_Final_4.26.24.1REV_OEC.pdf#page=39 diff --git a/policyengine_us/parameters/gov/states/ar/ade/oec/sra/rates/no_copay_smi_threshold.yaml b/policyengine_us/parameters/gov/states/ar/ade/oec/sra/rates/no_copay_smi_threshold.yaml new file mode 100644 index 00000000000..389e0bc43bf --- /dev/null +++ b/policyengine_us/parameters/gov/states/ar/ade/oec/sra/rates/no_copay_smi_threshold.yaml @@ -0,0 +1,16 @@ +description: Arkansas zeroes the family copay for non-school-aged children whose family income is at or below this share of state median income under the School Readiness Assistance program. School-aged children always incur a copay (state share is 80% / 70%, not 100%) and are unaffected by this threshold. +# Source conflict: CCDF State Plan §2.3.1(b) describes a no-cost-of-care waiver +# for families at or below 75% SMI, while the Nov 2025 operational rate sheet +# only zeroes the copay for families at or below 40% SMI. The model follows +# the rate sheet (40%) because it is the operational document the agency uses +# to compute family copays. The 75% State Plan provision is not modeled. +values: + 2025-11-01: 0.4 + +metadata: + unit: /1 + period: year + label: Arkansas SRA no-copay SMI threshold + reference: + - title: SRA Sliding Fee Scale with Rates and Copays - Statewide Full Time (Nov 1, 2025) + href: https://dese.ade.arkansas.gov/Files/SRA_Sliding_Fee_Scale_with_Rates_&_Copays--Statewide_Full_Time_20251101_OEC.pdf diff --git a/policyengine_us/parameters/gov/states/ar/ade/oec/sra/rates/partial_subsidy_smi_threshold.yaml b/policyengine_us/parameters/gov/states/ar/ade/oec/sra/rates/partial_subsidy_smi_threshold.yaml new file mode 100644 index 00000000000..dcb77b019e3 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ar/ade/oec/sra/rates/partial_subsidy_smi_threshold.yaml @@ -0,0 +1,11 @@ +description: Arkansas sets this share of state median income as the upper bound of the partial-subsidy income tier under the School Readiness Assistance program. +values: + 2025-11-01: 0.6 + +metadata: + unit: /1 + period: year + label: Arkansas SRA partial-subsidy SMI threshold + reference: + - title: SRA Sliding Fee Scale with Rates and Copays - Statewide Full Time (Nov 1, 2025) + href: https://dese.ade.arkansas.gov/Files/SRA_Sliding_Fee_Scale_with_Rates_&_Copays--Statewide_Full_Time_20251101_OEC.pdf diff --git a/policyengine_us/parameters/gov/states/ar/ade/oec/sra/rates/state_share_by_tier.yaml b/policyengine_us/parameters/gov/states/ar/ade/oec/sra/rates/state_share_by_tier.yaml new file mode 100644 index 00000000000..961a05c933b --- /dev/null +++ b/policyengine_us/parameters/gov/states/ar/ade/oec/sra/rates/state_share_by_tier.yaml @@ -0,0 +1,79 @@ +description: Arkansas provides this share of the daily base rate under the School Readiness Assistance program. +metadata: + period: day + unit: /1 + label: Arkansas SRA state-share rate by income tier + breakdown: + - ar_sra_age_category + - ar_sra_time_category + - ar_sra_income_tier + reference: + - title: SRA Sliding Fee Scale with Rates and Copays - Statewide Full Time (Nov 1, 2025) + href: https://dese.ade.arkansas.gov/Files/SRA_Sliding_Fee_Scale_with_Rates_&_Copays--Statewide_Full_Time_20251101_OEC.pdf + - title: SRA Sliding Fee Scale with Rates and Copays - Statewide Part Time (Nov 1, 2025) + href: https://dese.ade.arkansas.gov/Files/SRA_Sliding_Fee_Scale_with_Rates_&_Copays--Statewide_Part_Time_20251101_OEC.pdf + - title: SRA Sliding Fee Scale with Rates and Copays - Benton/Washington Full Time (Nov 1, 2025) + href: https://dese.ade.arkansas.gov/Files/SRA_Sliding_Fee_Scale_with_Rates_&_Copays--Benton-Washington_Co_Full_Time_20251101_OEC.pdf + - title: SRA Sliding Fee Scale with Rates and Copays - Benton/Washington Part Time (Nov 1, 2025) + href: https://dese.ade.arkansas.gov/Files/SRA_Sliding_Fee_Scale_with_Rates_&_Copays--Benton-Washington_Co_Part_Time_20251101_OEC.pdf + +INFANT: + FULL_TIME: + LE_40: + 2025-11-01: 1 + GT_40_LE_60: + 2025-11-01: 0.8 + GT_60: + 2025-11-01: 0.7 + PART_TIME: + LE_40: + 2025-11-01: 1 + GT_40_LE_60: + 2025-11-01: 0.7 + GT_60: + 2025-11-01: 0.6 +TODDLER: + FULL_TIME: + LE_40: + 2025-11-01: 1 + GT_40_LE_60: + 2025-11-01: 0.8 + GT_60: + 2025-11-01: 0.7 + PART_TIME: + LE_40: + 2025-11-01: 1 + GT_40_LE_60: + 2025-11-01: 0.6 + GT_60: + 2025-11-01: 0.5 +PRESCHOOL: + FULL_TIME: + LE_40: + 2025-11-01: 1 + GT_40_LE_60: + 2025-11-01: 0.7 + GT_60: + 2025-11-01: 0.6 + PART_TIME: + LE_40: + 2025-11-01: 1 + GT_40_LE_60: + 2025-11-01: 0.6 + GT_60: + 2025-11-01: 0.5 +SCHOOL_AGED: + FULL_TIME: + LE_40: + 2025-11-01: 0.8 + GT_40_LE_60: + 2025-11-01: 0.5 + GT_60: + 2025-11-01: 0.3 + PART_TIME: + LE_40: + 2025-11-01: 0.7 + GT_40_LE_60: + 2025-11-01: 0.5 + GT_60: + 2025-11-01: 0.3 diff --git a/policyengine_us/programs.yaml b/policyengine_us/programs.yaml index 7d6212eec9a..97dc2c6a080 100644 --- a/policyengine_us/programs.yaml +++ b/policyengine_us/programs.yaml @@ -460,7 +460,7 @@ programs: category: Benefits agency: HHS status: partial - coverage: AK, CA, CO, CT, DE, DC, IL, MA, MD, ME, NC, NH, NJ, PA, RI, SC, TX, VA, VT, WV + coverage: AK, AR, CA, CO, CT, DE, DC, IL, MA, MD, ME, NC, NH, NJ, PA, RI, SC, TX, VA, VT, WV state_implementations: - state: AK status: complete @@ -468,6 +468,12 @@ programs: full_name: Alaska Child Care Assistance Program variable: ak_ccap notes: Modeled as PASS II/III; PASS I (ATAP-bundled) and PASS IV (OCS protective services) not modeled + - state: AR + status: complete + name: Arkansas SRA + full_name: Arkansas School Readiness Assistance + variable: ar_sra + parameter_prefix: gov.states.ar.ade.oec.sra - state: CA status: complete name: CalWORKs childcare diff --git a/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/ar_child_care_subsidies.yaml b/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/ar_child_care_subsidies.yaml new file mode 100644 index 00000000000..84f52c778f6 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/ar_child_care_subsidies.yaml @@ -0,0 +1,66 @@ +# Federal aggregator: ar_child_care_subsidies = adds ar_sra (annual sum +# of monthly ar_sra). Verifies the YEAR-level wiring from the federal +# child_care_subsidies path to AR's monthly benefit. + +- name: Case 1, eligible AR family's annual ar_child_care_subsidies equals 12 times the monthly ar_sra (LE_40 tier, no copay). + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 28 + weekly_hours_worked: 35 + employment_income: 18_000 + immigration_status: CITIZEN + person2: + age: 2 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + childcare_attending_days_per_month: 22 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 20_000 + households: + household: + members: [person1, person2] + state_code: AR + county_str: PULASKI_COUNTY_AR + output: + # Statewide / Toddler / REGULAR / FT / LE_40: monthly ar_sra = $770. + # Annual ar_child_care_subsidies = 12 * 770 = 9_240. + ar_child_care_subsidies: 9_240 + +- name: Case 2, non-AR household's ar_child_care_subsidies is zero (defined_for guard). + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 28 + weekly_hours_worked: 35 + employment_income: 18_000 + immigration_status: CITIZEN + person2: + age: 2 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + childcare_attending_days_per_month: 22 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 20_000 + households: + household: + members: [person1, person2] + state_code: TX + output: + ar_child_care_subsidies: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/ar_sra.yaml b/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/ar_sra.yaml new file mode 100644 index 00000000000..378a83765a6 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/ar_sra.yaml @@ -0,0 +1,222 @@ +# ar_sra unit tests — exercise the top-level formula's clamps and 4% cap. +# +# Reference parameters (Nov 1, 2025 rate sheet): +# AR SMI (FFY 2026, uprated to 2026-01-01, 4-person): $95,201.95/year +# All cases use a single eligible toddler with 22 attending days/month. + +- name: Case 1, baseline LI eligible family at LE_40 SMI tier, no copay. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 28 + weekly_hours_worked: 35 + employment_income: 18_000 + immigration_status: CITIZEN + person2: + age: 2 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + childcare_attending_days_per_month: 22 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 20_000 + households: + household: + members: [person1, person2] + state_code: AR + county_str: PULASKI_COUNTY_AR + output: + is_ar_sra_eligible: true + # Toddler Statewide FT LE_40: state share 1.00, copay 0. + # daily_state_payment = 35; monthly = 35 * 22 = 770. + ar_sra: 770 + +- name: Case 2, total_expense clamp - state payment exceeds actual expenses. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 28 + weekly_hours_worked: 35 + employment_income: 18_000 + immigration_status: CITIZEN + person2: + age: 2 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + childcare_attending_days_per_month: 22 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + # State payment alone would be $770; cap at actual expense. + spm_unit_pre_subsidy_childcare_expenses: 6_000 + households: + household: + members: [person1, person2] + state_code: AR + county_str: PULASKI_COUNTY_AR + output: + is_ar_sra_eligible: true + # Annual expense $6,000 -> monthly $500. Subsidy capped at $500. + ar_sra: 500 + +- name: Case 3, zero expense clamps subsidy to zero (even with positive state payment). + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 28 + weekly_hours_worked: 35 + employment_income: 18_000 + immigration_status: CITIZEN + person2: + age: 2 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + childcare_attending_days_per_month: 22 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 0 + households: + household: + members: [person1, person2] + state_code: AR + county_str: PULASKI_COUNTY_AR + output: + is_ar_sra_eligible: true + ar_sra: 0 + +- name: Case 4, 4% cap binds - rate-sheet copay exceeds 4% of countable income. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 28 + weekly_hours_worked: 35 + # GT_40_LE_60 tier: rate-sheet copay = $7/day = $154/month. + employment_income: 30_695 + immigration_status: CITIZEN + person2: + age: 2 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + childcare_attending_days_per_month: 22 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 20_000 + households: + household: + members: [person1, person2] + state_code: AR + county_str: PULASKI_COUNTY_AR + output: + is_ar_sra_eligible: true + # Monthly countable income = 30,695 / 12 = $2,557.92 + # 4% cap = $102.32; rate-sheet copay $154 exceeds cap. + # cap_savings = $154 - $102.32 = $51.68 + # uncapped subsidy = daily_state_payment * 22 = $28 * 22 = $616 + # ar_sra = $616 + $51.68 = $667.68 + ar_sra: 667.68 + +- name: Case 5, negative countable income is clamped at zero before applying 4% cap. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 28 + weekly_hours_worked: 35 + # Self-employment loss exceeds wages; countable income would be negative. + self_employment_income: -20_000 + employment_income: 5_000 + immigration_status: CITIZEN + person2: + age: 2 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + childcare_attending_days_per_month: 22 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 20_000 + households: + household: + members: [person1, person2] + state_code: AR + county_str: PULASKI_COUNTY_AR + output: + is_ar_sra_eligible: true + # Net countable income < 0 -> LE_40 tier (state share 1.00, copay 0). + # No copay so 4% cap is moot; full state payment. + # ar_sra = $35 * 22 = $770. Without the max_(countable, 0) clamp, + # cap_savings could become negative and corrupt the subsidy. + ar_sra: 770 + +- name: Case 6, per-child payable-copay clamp - actual expense below rate-sheet copay. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 28 + weekly_hours_worked: 35 + # GT_40_LE_60 tier: rate-sheet copay = $7/day = $154/month. + employment_income: 30_695 + immigration_status: CITIZEN + person2: + age: 2 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + childcare_attending_days_per_month: 22 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + # Annual $1,500 -> monthly $125, below $154/mo rate-sheet copay. + spm_unit_pre_subsidy_childcare_expenses: 1_500 + households: + household: + members: [person1, person2] + state_code: AR + county_str: PULASKI_COUNTY_AR + output: + is_ar_sra_eligible: true + # monthly_expense = $125; rate-sheet monthly_copay = $154. + # payable_copay = min($154, $125) = $125 (per-child clamp). + # Monthly countable income = $30,695 / 12 = $2,557.92; 4% cap = $102.32. + # cap_savings = $125 - $102.32 = $22.68. + # uncapped_subsidy per child = min(max($125 - $154, 0), $616) = 0. + # Return = min(0 + $22.68, $125) = $22.68. + # Without the per-child clamp, cap_savings would be $51.68 and ar_sra $51.68. + ar_sra: 22.68 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/eligibility/ar_sra_age_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/eligibility/ar_sra_age_eligible.yaml new file mode 100644 index 00000000000..8963a63029e --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/eligibility/ar_sra_age_eligible.yaml @@ -0,0 +1,152 @@ +- name: Case 1, child age 5 is under 13 and age-eligible. + period: 2026-01 + input: + people: + person1: + age: 30 + person2: + age: 5 + is_tax_unit_dependent: true + households: + household: + members: [person1, person2] + state_code: AR + output: + is_ar_sra_age_eligible: [false, true] + +- name: Case 2, child age 12 at boundary is age-eligible. + period: 2026-01 + input: + people: + person1: + age: 35 + person2: + age: 12 + is_tax_unit_dependent: true + households: + household: + members: [person1, person2] + state_code: AR + output: + is_ar_sra_age_eligible: [false, true] + +- name: Case 3, child age 13 is not age-eligible (strict less than). + period: 2026-01 + input: + people: + person1: + age: 40 + person2: + age: 13 + is_tax_unit_dependent: true + households: + household: + members: [person1, person2] + state_code: AR + output: + is_ar_sra_age_eligible: [false, false] + +- name: Case 4, infant age 0 is age-eligible. + period: 2026-01 + input: + people: + person1: + age: 28 + person2: + age: 0 + is_tax_unit_dependent: true + households: + household: + members: [person1, person2] + state_code: AR + output: + is_ar_sra_age_eligible: [false, true] + +- name: Case 5, disabled child age 15 is age-eligible under the disability extension (under 19). + period: 2026-01 + input: + people: + person1: + age: 40 + person2: + age: 15 + is_tax_unit_dependent: true + is_disabled: true + households: + household: + members: [person1, person2] + state_code: AR + output: + is_ar_sra_age_eligible: [false, true] + +- name: Case 6, non-disabled child age 15 is not age-eligible (over 13). + period: 2026-01 + input: + people: + person1: + age: 40 + person2: + age: 15 + is_tax_unit_dependent: true + is_disabled: false + households: + household: + members: [person1, person2] + state_code: AR + output: + is_ar_sra_age_eligible: [false, false] + +- name: Case 7, disabled child age 18 is age-eligible (disability extension covers under 19). + period: 2026-01 + input: + people: + person1: + age: 45 + person2: + age: 18 + is_tax_unit_dependent: true + is_disabled: true + households: + household: + members: [person1, person2] + state_code: AR + output: + # FSU §5.6.1 / CCDF State Plan §2.2.1: disabled children eligible + # "under nineteen (19)". + is_ar_sra_age_eligible: [false, true] + +- name: Case 8, disabled child age 19 is at the disability extension boundary and not age-eligible (strict less than). + period: 2026-01 + input: + people: + person1: + age: 45 + person2: + age: 19 + is_tax_unit_dependent: true + is_disabled: true + households: + household: + members: [person1, person2] + state_code: AR + output: + is_ar_sra_age_eligible: [false, false] + +- name: Case 9, disabled child age 13 is age-eligible (disability extension activates at the standard cutoff). + period: 2026-01 + input: + people: + person1: + age: 40 + person2: + age: 13 + is_tax_unit_dependent: true + is_disabled: true + households: + household: + members: [person1, person2] + state_code: AR + output: + # Confirms the disability extension picks up where the standard 13-year + # cutoff leaves off; a disabled 13-year-old remains eligible (< 19). + is_ar_sra_age_eligible: [false, true] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/eligibility/ar_sra_child_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/eligibility/ar_sra_child_eligible.yaml new file mode 100644 index 00000000000..dd7868f3df6 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/eligibility/ar_sra_child_eligible.yaml @@ -0,0 +1,81 @@ +# Eligible-child test: age < 13 AND immigration-eligible. + +- name: Case 1, citizen child age 5 who is a dependent is eligible. + period: 2026-01 + input: + people: + person1: + age: 30 + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + output: + is_ar_sra_child_eligible: [false, true] + +- name: Case 2, child age 13 is not age-eligible. + period: 2026-01 + input: + people: + person1: + age: 35 + person2: + age: 13 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + output: + is_ar_sra_child_eligible: [false, false] + +- name: Case 3, undocumented child is not immigration-eligible. + period: 2026-01 + input: + people: + person1: + age: 30 + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: UNDOCUMENTED + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + output: + is_ar_sra_child_eligible: [false, false] + +- name: Case 4, refugee child age 4 is eligible. + period: 2026-01 + input: + people: + person1: + age: 28 + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: REFUGEE + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + output: + is_ar_sra_child_eligible: [false, true] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/eligibility/ar_sra_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/eligibility/ar_sra_eligible.yaml new file mode 100644 index 00000000000..c316535c9f9 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/eligibility/ar_sra_eligible.yaml @@ -0,0 +1,283 @@ +# Overall SRA eligibility = in_effect AND has_eligible_child AND income-eligible +# AND asset-eligible AND (LI activity OR ESS) AND state_code == AR. + +- name: Case 1, all eligibility components met under the LI track. + period: 2026-01 + input: + people: + person1: + age: 30 + weekly_hours_worked: 35 + employment_income: 20_000 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + county_str: PULASKI_COUNTY_AR + output: + is_ar_sra_eligible: true + +- name: Case 2, household income above 85 percent SMI fails eligibility. + period: 2026-01 + input: + people: + person1: + age: 30 + weekly_hours_worked: 35 + # Well above the 85% SMI annual cap of ~$52,182 for a family of 2 + employment_income: 100_000 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + county_str: PULASKI_COUNTY_AR + output: + is_ar_sra_eligible: false + +- name: Case 3, no eligible child fails eligibility. + period: 2026-01 + input: + people: + person1: + age: 30 + weekly_hours_worked: 35 + employment_income: 20_000 + immigration_status: CITIZEN + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: AR + county_str: PULASKI_COUNTY_AR + output: + is_ar_sra_eligible: false + +- name: Case 4, parent activity below LI threshold and no ESS track fails eligibility. + period: 2026-01 + input: + people: + person1: + age: 30 + weekly_hours_worked: 20 + employment_income: 20_000 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + ar_was_tea_recipient: false + households: + household: + members: [person1, person2] + state_code: AR + county_str: PULASKI_COUNTY_AR + output: + is_ar_sra_eligible: false + +- name: Case 5, ESS track 20 hours per week makes household eligible even below LI threshold. + period: 2026-01 + input: + people: + person1: + age: 28 + weekly_hours_worked: 20 + employment_income: 15_000 + immigration_status: CITIZEN + person2: + age: 2 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + ar_was_tea_recipient: true + ar_months_since_tea_exit: 6 + ar_tea: 0 + households: + household: + members: [person1, person2] + state_code: AR + county_str: PULASKI_COUNTY_AR + output: + is_ar_sra_eligible: true + +- name: Case 6, household with assets above the CCDF asset limit fails eligibility. + period: 2026-01 + input: + people: + person1: + age: 30 + weekly_hours_worked: 35 + employment_income: 20_000 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 2_000_000 + households: + household: + members: [person1, person2] + state_code: AR + county_str: PULASKI_COUNTY_AR + output: + is_ar_sra_eligible: false + +- name: Case 7, assets exactly at the $1M CCDF limit are eligible. + period: 2026-01 + input: + people: + person1: + age: 30 + weekly_hours_worked: 35 + employment_income: 20_000 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 1_000_000 + households: + household: + members: [person1, person2] + state_code: AR + county_str: PULASKI_COUNTY_AR + output: + is_ar_sra_eligible: true + +- name: Case 8, assets one dollar above the $1M CCDF limit fail eligibility. + period: 2026-01 + input: + people: + person1: + age: 30 + weekly_hours_worked: 35 + employment_income: 20_000 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 1_000_001 + households: + household: + members: [person1, person2] + state_code: AR + county_str: PULASKI_COUNTY_AR + output: + is_ar_sra_eligible: false + +- name: Case 9, assets just below the $1M CCDF limit are eligible. + period: 2026-01 + input: + people: + person1: + age: 30 + weekly_hours_worked: 35 + employment_income: 20_000 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 999_999 + households: + household: + members: [person1, person2] + state_code: AR + county_str: PULASKI_COUNTY_AR + output: + is_ar_sra_eligible: true + +- name: Case 10, period 2025-01 is before the SRA effective date so household is not eligible. + period: 2025-01 + input: + people: + person1: + age: 30 + weekly_hours_worked: 35 + employment_income: 20_000 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + county_str: PULASKI_COUNTY_AR + output: + is_ar_sra_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/eligibility/ar_sra_ess_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/eligibility/ar_sra_ess_eligible.yaml new file mode 100644 index 00000000000..27bd278889a --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/eligibility/ar_sra_ess_eligible.yaml @@ -0,0 +1,483 @@ +# ESS eligibility: family must have exited TEA within the 24-month window +# AND not currently receiving TEA AND meet the year-specific activity hour +# threshold (20 hr/wk Yr1, 25 hr/wk Yr2). + +- name: Case 1, post-TEA family 6 months out with 20 hours per week is ESS-eligible. + period: 2026-01 + input: + people: + person1: + age: 28 + weekly_hours_worked: 20 + person2: + age: 2 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2] + ar_was_tea_recipient: true + ar_months_since_tea_exit: 6 + ar_tea: 0 + households: + household: + members: [person1, person2] + state_code: AR + output: + is_ar_sra_ess_eligible: true + +- name: Case 2, family currently receiving TEA is not ESS-eligible. + period: 2026-01 + input: + people: + person1: + age: 28 + weekly_hours_worked: 25 + person2: + age: 2 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2] + ar_was_tea_recipient: true + ar_months_since_tea_exit: 6 + ar_tea: 200 + households: + household: + members: [person1, person2] + state_code: AR + output: + is_ar_sra_ess_eligible: false + +- name: Case 3, post-TEA family 30 months out is past the 24-month window and not ESS-eligible. + period: 2026-01 + input: + people: + person1: + age: 28 + weekly_hours_worked: 25 + person2: + age: 2 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2] + ar_was_tea_recipient: true + ar_months_since_tea_exit: 30 + households: + household: + members: [person1, person2] + state_code: AR + output: + is_ar_sra_ess_eligible: false + +- name: Case 4, family that never received TEA is not ESS-eligible. + period: 2026-01 + input: + people: + person1: + age: 28 + weekly_hours_worked: 25 + person2: + age: 2 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2] + ar_was_tea_recipient: false + ar_months_since_tea_exit: 0 + households: + household: + members: [person1, person2] + state_code: AR + output: + is_ar_sra_ess_eligible: false + +- name: Case 5, ESS Year 2 family with 25 hours per week is ESS-eligible. + period: 2026-01 + input: + people: + person1: + age: 28 + weekly_hours_worked: 25 + person2: + age: 2 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2] + ar_was_tea_recipient: true + ar_months_since_tea_exit: 18 + ar_tea: 0 + households: + household: + members: [person1, person2] + state_code: AR + output: + is_ar_sra_ess_eligible: true + +- name: Case 6, month 12 is the last Year-1 month and 20 hours satisfies the Year-1 threshold. + period: 2026-01 + input: + people: + person1: + age: 28 + weekly_hours_worked: 20 + person2: + age: 2 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2] + ar_was_tea_recipient: true + ar_months_since_tea_exit: 12 + ar_tea: 0 + households: + household: + members: [person1, person2] + state_code: AR + output: + is_ar_sra_ess_eligible: true + +- name: Case 7, month 24 is the last in-window month and 25 hours satisfies the Year-2 threshold. + period: 2026-01 + input: + people: + person1: + age: 28 + weekly_hours_worked: 25 + person2: + age: 2 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2] + ar_was_tea_recipient: true + ar_months_since_tea_exit: 24 + ar_tea: 0 + households: + household: + members: [person1, person2] + state_code: AR + output: + is_ar_sra_ess_eligible: true + +- name: Case 8, month 25 is past the 24-month window so household is not ESS-eligible. + period: 2026-01 + input: + people: + person1: + age: 28 + weekly_hours_worked: 25 + person2: + age: 2 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2] + ar_was_tea_recipient: true + ar_months_since_tea_exit: 25 + ar_tea: 0 + households: + household: + members: [person1, person2] + state_code: AR + output: + is_ar_sra_ess_eligible: false + +- name: Case 9, a working teen does not satisfy the activity threshold when no adult does. + period: 2026-01 + input: + people: + person1: + age: 30 + weekly_hours_worked: 10 + person2: + age: 16 + is_tax_unit_dependent: true + weekly_hours_worked: 30 + person3: + age: 2 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2, person3] + ar_was_tea_recipient: true + ar_months_since_tea_exit: 6 + ar_tea: 0 + households: + household: + members: [person1, person2, person3] + state_code: AR + output: + # Teen's 30 hours is masked out; adult max = 10 hr, below Year-1 threshold (20) + is_ar_sra_ess_eligible: false + +- name: Case 10, month 13 (first Year-2 month) with 20 hours falls below the Year-2 threshold (25). + period: 2026-01 + input: + people: + person1: + age: 28 + weekly_hours_worked: 20 + person2: + age: 2 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2] + ar_was_tea_recipient: true + ar_months_since_tea_exit: 13 + ar_tea: 0 + households: + household: + members: [person1, person2] + state_code: AR + output: + is_ar_sra_ess_eligible: false + +- name: Case 11, month 13 with 25 hours satisfies the Year-2 threshold. + period: 2026-01 + input: + people: + person1: + age: 28 + weekly_hours_worked: 25 + person2: + age: 2 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2] + ar_was_tea_recipient: true + ar_months_since_tea_exit: 13 + ar_tea: 0 + households: + household: + members: [person1, person2] + state_code: AR + output: + is_ar_sra_ess_eligible: true + +- name: Case 12, Year-1 family with 19 hours falls one hour short of the 20-hour threshold. + period: 2026-01 + input: + people: + person1: + age: 28 + weekly_hours_worked: 19 + person2: + age: 2 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2] + ar_was_tea_recipient: true + ar_months_since_tea_exit: 6 + ar_tea: 0 + households: + household: + members: [person1, person2] + state_code: AR + output: + is_ar_sra_ess_eligible: false + +- name: Case 13, Year-2 family with 24 hours falls one hour short of the 25-hour threshold. + period: 2026-01 + input: + people: + person1: + age: 28 + weekly_hours_worked: 24 + person2: + age: 2 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2] + ar_was_tea_recipient: true + ar_months_since_tea_exit: 18 + ar_tea: 0 + households: + household: + members: [person1, person2] + state_code: AR + output: + is_ar_sra_ess_eligible: false + +- name: Case 14, Year-1 full-time college student adult with 0 hours satisfies activity via student OR-clause. + period: 2026-01 + input: + people: + person1: + age: 28 + weekly_hours_worked: 0 + is_full_time_college_student: true + person2: + age: 2 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2] + ar_was_tea_recipient: true + ar_months_since_tea_exit: 6 + ar_tea: 0 + households: + household: + members: [person1, person2] + state_code: AR + output: + is_ar_sra_ess_eligible: true + +- name: Case 15, Year-2 full-time college student adult with 0 hours satisfies activity via student OR-clause. + period: 2026-01 + input: + people: + person1: + age: 28 + weekly_hours_worked: 0 + is_full_time_college_student: true + person2: + age: 2 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2] + ar_was_tea_recipient: true + ar_months_since_tea_exit: 18 + ar_tea: 0 + households: + household: + members: [person1, person2] + state_code: AR + output: + is_ar_sra_ess_eligible: true + +- name: Case 16, ESS window starts at month 1, so months_since_tea_exit of 0 (still receiving TEA) is not yet in the post-TEA window. + period: 2026-01 + input: + people: + person1: + age: 28 + weekly_hours_worked: 35 + person2: + age: 2 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2] + ar_was_tea_recipient: true + ar_months_since_tea_exit: 0 + ar_tea: 0 + households: + household: + members: [person1, person2] + state_code: AR + output: + is_ar_sra_ess_eligible: false + +- name: Case 17, ESS Year-1 alt path (FSU 4.1.5.1) - earnings exceed TEA income limit, work hours below the 20 hr threshold. + period: 2026-01 + input: + people: + person1: + age: 28 + weekly_hours_worked: 15 + # AR TEA income limit is $513/month; $30k/yr ($2,500/mo) earnings + # make the family TEA-income-ineligible. tanf_gross_earned_income + # reads employment_income_before_lsr, so set that directly. + employment_income_before_lsr: 30_000 + person2: + age: 2 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2] + ar_was_tea_recipient: true + ar_months_since_tea_exit: 6 + ar_tea: 0 + households: + household: + members: [person1, person2] + state_code: AR + output: + is_ar_sra_ess_eligible: true + +- name: Case 18, ESS Year-1 work-hours fallback - 15 hr/wk plus TEA-income-eligible (low income) fails the activity test. + period: 2026-01 + input: + people: + person1: + age: 28 + weekly_hours_worked: 15 + # Zero income keeps the family TEA-income-eligible. + employment_income: 0 + person2: + age: 2 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2] + ar_was_tea_recipient: true + ar_months_since_tea_exit: 6 + ar_tea: 0 + households: + household: + members: [person1, person2] + state_code: AR + output: + is_ar_sra_ess_eligible: false + +- name: Case 19, ESS Year-2 alt path does NOT include TEA-income-ineligibility - Year-2 requires 25 hr/wk or full-time student. + period: 2026-01 + input: + people: + person1: + age: 28 + weekly_hours_worked: 15 + employment_income: 30_000 + person2: + age: 2 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2] + ar_was_tea_recipient: true + ar_months_since_tea_exit: 18 + ar_tea: 0 + households: + household: + members: [person1, person2] + state_code: AR + output: + is_ar_sra_ess_eligible: false + +- name: Case 20, ESS Year-1 alt path - unearned income alone does NOT trigger the gate (FSU 4.1.5.1 'earnings alone'). + period: 2026-01 + input: + people: + person1: + age: 28 + weekly_hours_worked: 15 + # Zero earned income keeps TEA-earned-income at $0, below the $513/mo limit. + employment_income: 0 + # High unearned income ($30k/yr = $2,500/mo) would push total TEA + # countable income above $513 — but FSU 4.1.5.1 says 'earnings alone'. + social_security: 30_000 + person2: + age: 2 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2] + ar_was_tea_recipient: true + ar_months_since_tea_exit: 6 + ar_tea: 0 + households: + household: + members: [person1, person2] + state_code: AR + output: + # Earned income = $0 (under $513 TEA limit); work hours = 15 (under 20). + # No adult student. Alt path does not trigger because earnings alone do + # not exceed the TEA limit; unearned income is excluded from this gate. + is_ar_sra_ess_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/eligibility/ar_sra_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/eligibility/ar_sra_income_eligible.yaml new file mode 100644 index 00000000000..862dcdf32d6 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/eligibility/ar_sra_income_eligible.yaml @@ -0,0 +1,134 @@ +# Arkansas SMI for FFY 2026 is uprated automatically in PolicyEngine. +# AR base amount at 2026-01-01 (after uprating): $95,201.95 +# Household-size adjustment for 2 persons: 0.52 + 0.16 = 0.68 +# SMI(2) annual = 95,201.95 * 0.68 = $64,737.33 +# 85% income limit annual = $64,737.33 * 0.85 = $55,026.73 + +- name: Case 1, family income at 84.9 percent SMI is income-eligible. + period: 2026-01 + input: + people: + person1: + age: 30 + # 64,737.33 * 0.849 = $54,961.99 (below 85% SMI) + employment_income: 54_961 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + output: + is_ar_sra_income_eligible: true + +- name: Case 2, family income just at 85 percent SMI is income-eligible. + period: 2026-01 + input: + people: + person1: + age: 30 + # 64,737.33 * 0.85 = $55,026.73; use 55,026.72 to avoid float32 + # round-trip precision loss during MONTH/YEAR conversion. + employment_income: 55_026.72 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + output: + is_ar_sra_income_eligible: true + +- name: Case 3, family income at 85.1 percent SMI is not income-eligible. + period: 2026-01 + input: + people: + person1: + age: 30 + # 64,737.33 * 0.851 = $55,091.46 (above 85% SMI) + employment_income: 55_092 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + output: + is_ar_sra_income_eligible: false + +- name: Case 4, family with zero income is income-eligible. + period: 2026-01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + output: + is_ar_sra_income_eligible: true + +- name: Case 5, family income one dollar below the 85 percent SMI cap is income-eligible. + period: 2026-01 + input: + people: + person1: + age: 30 + # 64,737.33 * 0.85 = $55,026.73; just-below boundary at $55,025. + employment_income: 55_025 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + output: + is_ar_sra_income_eligible: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/eligibility/ar_sra_li_activity_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/eligibility/ar_sra_li_activity_eligible.yaml new file mode 100644 index 00000000000..d0f7b08c03c --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/eligibility/ar_sra_li_activity_eligible.yaml @@ -0,0 +1,172 @@ +# LI activity requirement: each adult head/spouse must engage in +# >=30 hr/wk of work, education, or full-time study. + +- name: Case 1, single parent works 30 hours per week exactly is activity-eligible. + period: 2026-01 + input: + people: + person1: + age: 30 + weekly_hours_worked: 30 + person2: + age: 4 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + output: + is_ar_sra_li_activity_eligible: true + +- name: Case 2, single parent works 29 hours per week is not activity-eligible. + period: 2026-01 + input: + people: + person1: + age: 30 + weekly_hours_worked: 29 + person2: + age: 4 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + output: + is_ar_sra_li_activity_eligible: false + +- name: Case 3, single parent works 31 hours per week is activity-eligible. + period: 2026-01 + input: + people: + person1: + age: 30 + weekly_hours_worked: 31 + person2: + age: 4 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + output: + is_ar_sra_li_activity_eligible: true + +- name: Case 4, two parents both at or above 30 hours per week are activity-eligible. + period: 2026-01 + input: + people: + person1: + age: 32 + weekly_hours_worked: 30 + person2: + age: 30 + weekly_hours_worked: 35 + person3: + age: 4 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: AR + output: + is_ar_sra_li_activity_eligible: true + +- name: Case 5, two-parent household with one parent below threshold fails activity test. + period: 2026-01 + input: + people: + person1: + age: 32 + weekly_hours_worked: 35 + person2: + age: 30 + weekly_hours_worked: 20 + person3: + age: 4 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: AR + output: + is_ar_sra_li_activity_eligible: false + +- name: Case 6, adult with zero hours but meets_ccdf_activity_test fallback is eligible. + period: 2026-01 + input: + people: + person1: + age: 30 + weekly_hours_worked: 0 + person2: + age: 4 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2] + meets_ccdf_activity_test: true + households: + household: + members: [person1, person2] + state_code: AR + output: + is_ar_sra_li_activity_eligible: true + +- name: Case 7, two-parent household with one working and one full-time college student is eligible. + period: 2026-01 + input: + people: + person1: + age: 32 + weekly_hours_worked: 35 + person2: + age: 28 + weekly_hours_worked: 0 + is_full_time_college_student: true + person3: + age: 4 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: AR + output: + is_ar_sra_li_activity_eligible: true + +- name: Case 8, household with only children (no adult) is not activity-eligible. + period: 2026-01 + input: + people: + person1: + age: 8 + person2: + age: 4 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + output: + is_ar_sra_li_activity_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/income/ar_sra_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/income/ar_sra_countable_income.yaml new file mode 100644 index 00000000000..1f72d890543 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/income/ar_sra_countable_income.yaml @@ -0,0 +1,93 @@ +# Arkansas SRA countable income sums the parameterized list of income +# sources across adults only; income of children (<18) is excluded. +# The variable is MONTH-defined; YEAR-period income sources (e.g., +# employment_income) are auto-divided by 12 when accessed monthly. + +- name: Case 1, parent employment income is fully counted (annual $30,000 = $2,500/month). + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 30_000 + person2: + age: 4 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + output: + ar_sra_countable_income: 2_500 + +- name: Case 2, child SSI is excluded (annual $25,000 parent earnings = $2,083.33/month). + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 25_000 + person2: + age: 8 + is_tax_unit_dependent: true + ssi: 9_000 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + output: + # Only parent's $25,000 annual counts; child's SSI is excluded. + # Monthly: 25,000 / 12 = $2,083.33 + ar_sra_countable_income: 2_083.33 + +- name: Case 3, two adults combine earnings (annual $40,000 = $3,333.33/month). + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 32 + employment_income: 22_000 + person2: + age: 30 + employment_income: 18_000 + person3: + age: 3 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: AR + output: + ar_sra_countable_income: 3_333.33 + +- name: Case 4, zero-income family produces zero countable income. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 4 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + output: + ar_sra_countable_income: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/integration.yaml new file mode 100644 index 00000000000..8289f6f0e02 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/integration.yaml @@ -0,0 +1,762 @@ +# Arkansas SRA integration tests +# +# Reference parameters (Nov 1, 2025 rate sheet): +# AR SMI (FFY 2026, uprated to 2026-01-01, 4-person): $95,201.95/year +# SMI(2)=95,201.95*0.68=$64,737.33; SMI(3)=95,201.95*0.84=$79,969.64 +# 85% income limit: SMI*0.85 +# Tier percentages in test comments are computed against the uprated SMI. +# +# Income tier brackets (% SMI): LE_40 (<=40), GT_40_LE_60 (4060) +# Daily base rates (Statewide REGULAR): Infant FT $36, Toddler FT $35, +# Preschool FT $33, School-Aged FT $28; PT half (Infant $18, Toddler $17.50, +# Preschool $16.50, School-Aged $14). +# Daily base rates (Benton/Washington REGULAR): Infant FT $38, Toddler FT $37, +# Preschool FT $33, School-Aged FT $28; PT (Infant $19, Toddler $18.50, etc.). +# State share % by (age_category, time, tier): +# Toddler/Preschool/Infant FT: 1.00 / 0.80 / 0.70 (Preschool FT mid-tier 0.70) +# School-Aged FT: 0.80 / 0.50 / 0.30 (always copay) +# +# All scenarios use childcare_attending_days_per_month = 22 (typical weekday count). +# Pre-subsidy expenses are set high enough that the state-payment cap binds. +# +# 4% copay cap (CCDF State Plan §3.1.1): family copay sum is capped at 4% of +# monthly countable income. When the rate-sheet copays exceed the cap, the +# state covers the gap (cap_savings added to subsidy). + +- name: Case 1, LI single mother, 1 toddler, full-time, Statewide. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 28 + weekly_hours_worked: 35 + # 90,280 * 0.68 * 0.50 = $30,695 (50% SMI -> GT_40_LE_60 tier) + employment_income: 30_695 + immigration_status: CITIZEN + person2: + age: 2 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + childcare_attending_days_per_month: 22 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 20_000 + households: + household: + members: [person1, person2] + state_code: AR + county_str: PULASKI_COUNTY_AR + output: + is_ar_sra_eligible: true + # Toddler FT GT_40_LE_60, Statewide: + # daily_state_payment = $28, monthly = $616 (uncapped subsidy at cap) + # monthly_copay = $7 * 22 = $154 + # monthly countable income = $30,695 / 12 = $2,557.92 + # 4% cap = $102.32 -> cap_savings = $154 - $102.32 = $51.68 + # ar_sra = $616 + $51.68 = $667.68 + ar_sra: 667.68 + +- name: Case 2, LI two-parent, 1 infant, full-time, Benton/Washington zone. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 32 + weekly_hours_worked: 30 + # 90,280 * 0.84 * 0.80 = $60,668 (80% SMI of 3-person SMI -> GT_60 tier) + employment_income: 60_668 + immigration_status: CITIZEN + person2: + age: 30 + weekly_hours_worked: 30 + immigration_status: CITIZEN + person3: + age: 0 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + childcare_attending_days_per_month: 22 + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + spm_unit_pre_subsidy_childcare_expenses: 20_000 + households: + household: + members: [person1, person2, person3] + state_code: AR + county_str: BENTON_COUNTY_AR + output: + is_ar_sra_eligible: true + # Infant FT GT_60, Benton/Washington: + # daily_state_payment = $26.60, monthly = $585.20 (uncapped at cap) + # monthly_copay = $11.40 * 22 = $250.80 + # monthly countable income = $60,668 / 12 = $5,055.67 + # 4% cap = $202.23 -> cap_savings = $250.80 - $202.23 = $48.57 + # ar_sra = $585.20 + $48.57 = $633.77 + ar_sra: 633.77 + +- name: Case 3, LI single parent, 1 preschooler, FT, Statewide, no-copay floor at LE_40. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 28 + weekly_hours_worked: 35 + # 90,280 * 0.68 * 0.35 = $21,486.66 (35% SMI -> LE_40 tier) + employment_income: 21_487 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + childcare_attending_days_per_month: 22 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 20_000 + households: + household: + members: [person1, person2] + state_code: AR + county_str: PULASKI_COUNTY_AR + output: + is_ar_sra_eligible: true + # Preschool, Statewide, FT, LE_40 (no-copay tier): + # base = $33, share = 1.00, daily state payment = $33.00 + # monthly state payment = 33 * 22 = $726 + ar_sra: 726 + +- name: Case 4, ESS Year 1 (post-TEA 6 months, 22 hr/wk), 1 toddler, FT, Statewide. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 26 + weekly_hours_worked: 22 + # 90,280 * 0.68 * 0.30 = $18,417 (30% SMI -> LE_40 tier) + employment_income: 18_417 + immigration_status: CITIZEN + person2: + age: 2 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + childcare_attending_days_per_month: 22 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + ar_was_tea_recipient: true + ar_months_since_tea_exit: 6 + ar_tea: 0 + spm_unit_pre_subsidy_childcare_expenses: 20_000 + households: + household: + members: [person1, person2] + state_code: AR + county_str: PULASKI_COUNTY_AR + output: + is_ar_sra_eligible: true + # Toddler, Statewide, FT, LE_40 (no-copay tier): + # base = $35, share = 1.00, daily state payment = $35.00 + # monthly state payment = 35 * 22 = $770 + ar_sra: 770 + +- name: Case 5, ESS Year 2 (post-TEA 18 months, 26 hr/wk), 1 toddler, FT, Statewide. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 27 + weekly_hours_worked: 26 + # 90,280 * 0.68 * 0.45 = $27,625.69 (45% SMI -> GT_40_LE_60 tier) + employment_income: 27_626 + immigration_status: CITIZEN + person2: + age: 2 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + childcare_attending_days_per_month: 22 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + ar_was_tea_recipient: true + ar_months_since_tea_exit: 18 + ar_tea: 0 + spm_unit_pre_subsidy_childcare_expenses: 20_000 + households: + household: + members: [person1, person2] + state_code: AR + county_str: PULASKI_COUNTY_AR + output: + is_ar_sra_eligible: true + # Toddler FT GT_40_LE_60, Statewide (same rate-sheet cell as Case 1): + # monthly countable income = $27,626 / 12 = $2,302.17 + # 4% cap = $92.09 -> cap_savings = $154 - $92.09 = $61.91 + # ar_sra = $616 + $61.91 = $677.91 + ar_sra: 677.91 + +- name: Case 6, family income above 85 percent SMI gets zero benefit. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + weekly_hours_worked: 35 + # Well above 85% SMI annual cap + employment_income: 100_000 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + childcare_attending_days_per_month: 22 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 20_000 + households: + household: + members: [person1, person2] + state_code: AR + county_str: PULASKI_COUNTY_AR + output: + is_ar_sra_eligible: false + ar_sra: 0 + +- name: Case 7, AR resident in pre-SRA period gets zero benefit. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + weekly_hours_worked: 35 + employment_income: 20_000 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + childcare_attending_days_per_month: 22 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 20_000 + households: + household: + members: [person1, person2] + state_code: AR + county_str: PULASKI_COUNTY_AR + output: + is_ar_sra_eligible: false + ar_sra: 0 + +- name: Case 8, non-AR household (state_code CA) gets zero benefit despite otherwise meeting criteria. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + weekly_hours_worked: 35 + employment_income: 20_000 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + childcare_attending_days_per_month: 22 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 20_000 + households: + household: + members: [person1, person2] + state_code: CA + output: + is_ar_sra_eligible: false + ar_sra: 0 + +- name: Case 9, LI single parent with toddler in SN2 special-needs care, Statewide FT. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 28 + weekly_hours_worked: 35 + # LE_40 tier + employment_income: 18_417 + immigration_status: CITIZEN + person2: + age: 2 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + childcare_attending_days_per_month: 22 + ar_sra_care_type: SN2 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 20_000 + households: + household: + members: [person1, person2] + state_code: AR + county_str: PULASKI_COUNTY_AR + output: + is_ar_sra_eligible: true + # Statewide / Toddler / SN2 / FT base = $49, share LE_40 = 1.00 + # daily state payment = $49.00, monthly = $49 * 22 = $1078 + ar_sra: 1078 + +- name: Case 10, low pre-subsidy expense binds before state payment cap. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 28 + weekly_hours_worked: 35 + employment_income: 18_417 + immigration_status: CITIZEN + person2: + age: 2 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + childcare_attending_days_per_month: 22 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + # Annual $3,600 = $300/month, well below the $770 monthly cap + spm_unit_pre_subsidy_childcare_expenses: 3_600 + households: + household: + members: [person1, person2] + state_code: AR + county_str: PULASKI_COUNTY_AR + output: + is_ar_sra_eligible: true + # Toddler Statewide FT LE_40: cap = $770/mo, copay = $0 + # subsidy = min(max(300 - 0, 0), 770) = $300 (expense binds) + ar_sra: 300 + +- name: Case 11, mixed-eligibility household with one eligible child and one over-age child. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 32 + weekly_hours_worked: 35 + employment_income: 18_417 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + childcare_attending_days_per_month: 22 + person3: + age: 13 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + childcare_attending_days_per_month: 22 + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + spm_unit_pre_subsidy_childcare_expenses: 20_000 + households: + household: + members: [person1, person2, person3] + state_code: AR + county_str: PULASKI_COUNTY_AR + output: + is_ar_sra_eligible: true + # Only the 4-year-old is age-eligible; 13-year-old contributes $0 + # Preschool Statewide FT LE_40: base $33, share 1.00 + # monthly state payment = $33 * 22 = $726 + ar_sra: 726 + +- name: Case 12, eligible child with zero attending days produces zero benefit. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 28 + weekly_hours_worked: 35 + employment_income: 18_417 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + childcare_attending_days_per_month: 0 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 20_000 + households: + household: + members: [person1, person2] + state_code: AR + county_str: PULASKI_COUNTY_AR + output: + is_ar_sra_eligible: true + # attending_days = 0 -> monthly_max_state_payment = 0 + # subsidy = min(max(expense - 0, 0), 0) = 0 + ar_sra: 0 + +- name: Case 13, school-aged child at LE_40 SMI confirms 80 percent state share through to benefit. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 28 + weekly_hours_worked: 35 + # LE_40 tier + employment_income: 18_417 + immigration_status: CITIZEN + person2: + age: 7 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + childcare_attending_days_per_month: 22 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 20_000 + households: + household: + members: [person1, person2] + state_code: AR + county_str: PULASKI_COUNTY_AR + output: + is_ar_sra_eligible: true + # School-Aged FT LE_40, Statewide (school-aged always has copay): + # daily_state_payment = $28 * 0.80 = $22.40, monthly = $492.80 (uncapped) + # monthly_copay = $5.60 * 22 = $123.20 + # monthly countable income = $18,417 / 12 = $1,534.75 + # 4% cap = $61.39 -> cap_savings = $123.20 - $61.39 = $61.81 + # ar_sra = $492.80 + $61.81 = $554.61 + ar_sra: 554.61 + +- name: Case 14, part-time infant care, LI parent, Statewide. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 28 + weekly_hours_worked: 35 + employment_income: 18_417 + immigration_status: CITIZEN + person2: + age: 0 + is_tax_unit_dependent: true + immigration_status: CITIZEN + # PT (below 30 hr full-time threshold) + childcare_hours_per_day: 4 + childcare_attending_days_per_month: 22 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 20_000 + households: + household: + members: [person1, person2] + state_code: AR + county_str: PULASKI_COUNTY_AR + output: + is_ar_sra_eligible: true + # Statewide Infant PT REGULAR base = $18, share LE_40 = 1.00 + # daily state payment = $18.00, monthly = $18 * 22 = $396 + ar_sra: 396 + +- name: Case 15, NIGHT_WEEKEND care, toddler at LE_40 SMI, FT, Statewide. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 28 + weekly_hours_worked: 35 + employment_income: 18_417 + immigration_status: CITIZEN + person2: + age: 2 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + childcare_attending_days_per_month: 22 + ar_sra_care_type: NIGHT_WEEKEND + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 20_000 + households: + household: + members: [person1, person2] + state_code: AR + county_str: PULASKI_COUNTY_AR + output: + is_ar_sra_eligible: true + # Toddler NIGHT_WEEKEND FT, Statewide, LE_40: + # base = $38.50, share = 1.00 -> copay = $0 + # monthly state payment = $38.50 * 22 = $847 + ar_sra: 847 + +- name: Case 16, SN1 care, toddler at LE_40 SMI, FT, Statewide. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 28 + weekly_hours_worked: 35 + employment_income: 18_417 + immigration_status: CITIZEN + person2: + age: 2 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + childcare_attending_days_per_month: 22 + ar_sra_care_type: SN1 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 20_000 + households: + household: + members: [person1, person2] + state_code: AR + county_str: PULASKI_COUNTY_AR + output: + is_ar_sra_eligible: true + # Toddler SN1 FT, Statewide, LE_40 (SN1 rates match REGULAR for toddler): + # base = $35, share = 1.00 -> copay = $0 + # monthly state payment = $35 * 22 = $770 + ar_sra: 770 + +- name: Case 17, SN3 care, toddler at LE_40 SMI, FT, Statewide. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 28 + weekly_hours_worked: 35 + employment_income: 18_417 + immigration_status: CITIZEN + person2: + age: 2 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + childcare_attending_days_per_month: 22 + ar_sra_care_type: SN3 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 20_000 + households: + household: + members: [person1, person2] + state_code: AR + county_str: PULASKI_COUNTY_AR + output: + is_ar_sra_eligible: true + # Toddler SN3 FT, Statewide, LE_40 (SN3 base = $49, premium tier): + # base = $49, share = 1.00 -> copay = $0 + # monthly state payment = $49 * 22 = $1078 + ar_sra: 1078 + +- name: Case 18, two-child cap-binding case demonstrates 4% copay ceiling. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 28 + weekly_hours_worked: 35 + # 3-person SMI = $75,835.20; 50% = $37,918 (GT_40_LE_60 tier) + employment_income: 37_918 + immigration_status: CITIZEN + person2: + age: 2 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + childcare_attending_days_per_month: 22 + person3: + age: 2 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + childcare_attending_days_per_month: 22 + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + spm_unit_pre_subsidy_childcare_expenses: 30_000 + households: + household: + members: [person1, person2, person3] + state_code: AR + county_str: PULASKI_COUNTY_AR + output: + is_ar_sra_eligible: true + # Two toddlers, FT GT_40_LE_60, Statewide: + # per-child daily_state_payment = $28, monthly = $616 each (uncapped) + # per-child monthly_copay = $154, total uncapped copay = $308 + # monthly countable income = $37,918 / 12 = $3,159.83 + # 4% cap = $126.39 -> cap_savings = $308 - $126.39 = $181.61 + # total uncapped subsidy = $1,232 + # ar_sra = $1,232 + $181.61 = $1,413.61 + ar_sra: 1413.61 + +- name: Case 19, eligible family with zero pre-subsidy expenses gets zero subsidy (clamp guard). + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 28 + weekly_hours_worked: 35 + # GT_40_LE_60 tier + employment_income: 30_695 + immigration_status: CITIZEN + person2: + age: 2 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + childcare_attending_days_per_month: 22 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 0 + households: + household: + members: [person1, person2] + state_code: AR + county_str: PULASKI_COUNTY_AR + output: + is_ar_sra_eligible: true + # total_expense = 0; the min_(uncapped_subsidy + cap_savings, total_expense) + # clamp keeps the subsidy from inflating beyond actual cost. + ar_sra: 0 + +- name: Case 20, negative self-employment income clamps countable income at 0 (regression guard). + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 28 + weekly_hours_worked: 35 + # Self-employment loss; total countable income would be negative. + self_employment_income: -20_000 + employment_income: 5_000 + immigration_status: CITIZEN + person2: + age: 2 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + childcare_attending_days_per_month: 22 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 20_000 + households: + household: + members: [person1, person2] + state_code: AR + county_str: PULASKI_COUNTY_AR + output: + is_ar_sra_eligible: true + # Negative income -> LE_40 tier (share=1.00, copay=0) -> cap_savings=0. + # Toddler Statewide FT LE_40: monthly state payment = $35 * 22 = $770. + ar_sra: 770 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/rates/ar_sra_age_category.yaml b/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/rates/ar_sra_age_category.yaml new file mode 100644 index 00000000000..17593f3a124 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/rates/ar_sra_age_category.yaml @@ -0,0 +1,138 @@ +# Age category bracket thresholds (months): +# <=17 months -> INFANT +# 18-35 months -> TODDLER +# 36-71 months -> PRESCHOOL +# 72+ months -> SCHOOL_AGED +# +# Test inputs use age in years. The formula multiplies by MONTHS_IN_YEAR +# to compare against month-based bracket thresholds. + +- name: Case 1, eight-month-old child (0.667 years) is in the INFANT category. + period: 2026-01 + input: + people: + person1: + age: 0.667 + households: + household: + members: [person1] + state_code: AR + output: + ar_sra_age_category: INFANT + +- name: Case 2, two-year-old child (24 months) is in the TODDLER category. + period: 2026-01 + input: + people: + person1: + age: 2 + households: + household: + members: [person1] + state_code: AR + output: + ar_sra_age_category: TODDLER + +- name: Case 3, four-year-old child (48 months) is in the PRESCHOOL category. + period: 2026-01 + input: + people: + person1: + age: 4 + households: + household: + members: [person1] + state_code: AR + output: + ar_sra_age_category: PRESCHOOL + +- name: Case 4, seven-year-old child (84 months) is in the SCHOOL_AGED category. + period: 2026-01 + input: + people: + person1: + age: 7 + households: + household: + members: [person1] + state_code: AR + output: + ar_sra_age_category: SCHOOL_AGED + +- name: Case 5, 17-month-old (1.417 years) is the last INFANT month. + period: 2026-01 + input: + people: + person1: + age: 1.417 + households: + household: + members: [person1] + state_code: AR + output: + ar_sra_age_category: INFANT + +- name: Case 6, 18-month-old (1.5 years) is the first TODDLER month. + period: 2026-01 + input: + people: + person1: + age: 1.5 + households: + household: + members: [person1] + state_code: AR + output: + ar_sra_age_category: TODDLER + +- name: Case 7, 35-month-old (2.917 years) is the last TODDLER month. + period: 2026-01 + input: + people: + person1: + age: 2.917 + households: + household: + members: [person1] + state_code: AR + output: + ar_sra_age_category: TODDLER + +- name: Case 8, 36-month-old (3 years) is the first PRESCHOOL month. + period: 2026-01 + input: + people: + person1: + age: 3 + households: + household: + members: [person1] + state_code: AR + output: + ar_sra_age_category: PRESCHOOL + +- name: Case 9, 71-month-old (5.917 years) is the last PRESCHOOL month. + period: 2026-01 + input: + people: + person1: + age: 5.917 + households: + household: + members: [person1] + state_code: AR + output: + ar_sra_age_category: PRESCHOOL + +- name: Case 10, 72-month-old (6 years) is the first SCHOOL_AGED month. + period: 2026-01 + input: + people: + person1: + age: 6 + households: + household: + members: [person1] + state_code: AR + output: + ar_sra_age_category: SCHOOL_AGED diff --git a/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/rates/ar_sra_care_type.yaml b/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/rates/ar_sra_care_type.yaml new file mode 100644 index 00000000000..5203b76fa05 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/rates/ar_sra_care_type.yaml @@ -0,0 +1,71 @@ +# ar_sra_care_type is a bare-input enum variable; default is REGULAR. +# Verify each enum value round-trips correctly. + +- name: Case 1, default ar_sra_care_type is REGULAR. + period: 2026-01 + input: + people: + person1: + age: 2 + households: + household: + members: [person1] + state_code: AR + output: + ar_sra_care_type: REGULAR + +- name: Case 2, NIGHT_WEEKEND care type round-trips. + period: 2026-01 + input: + people: + person1: + age: 2 + ar_sra_care_type: NIGHT_WEEKEND + households: + household: + members: [person1] + state_code: AR + output: + ar_sra_care_type: NIGHT_WEEKEND + +- name: Case 3, SN1 care type round-trips. + period: 2026-01 + input: + people: + person1: + age: 2 + ar_sra_care_type: SN1 + households: + household: + members: [person1] + state_code: AR + output: + ar_sra_care_type: SN1 + +- name: Case 4, SN2 care type round-trips. + period: 2026-01 + input: + people: + person1: + age: 2 + ar_sra_care_type: SN2 + households: + household: + members: [person1] + state_code: AR + output: + ar_sra_care_type: SN2 + +- name: Case 5, SN3 care type round-trips. + period: 2026-01 + input: + people: + person1: + age: 2 + ar_sra_care_type: SN3 + households: + household: + members: [person1] + state_code: AR + output: + ar_sra_care_type: SN3 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/rates/ar_sra_daily_base_rate.yaml b/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/rates/ar_sra_daily_base_rate.yaml new file mode 100644 index 00000000000..88a5fb824a8 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/rates/ar_sra_daily_base_rate.yaml @@ -0,0 +1,346 @@ +# Daily base rates from rates/base_rate.yaml lookup +# Keyed by (zone, age_category, care_type, time_category). +# Care type defaults to REGULAR; verified by parameter breakdown. +# +# Selected verified values for testing (Nov 1, 2025 rate sheet): +# STATEWIDE / INFANT / REGULAR / FT = $36.00 +# STATEWIDE / TODDLER / REGULAR / FT = $35.00 +# STATEWIDE / PRESCHOOL / REGULAR / FT = $33.00 +# STATEWIDE / SCHOOL_AGED / REGULAR / FT = $28.00 +# BENTON_WASHINGTON / INFANT / REGULAR / FT = $38.00 +# BENTON_WASHINGTON / TODDLER / REGULAR / FT = $37.00 +# STATEWIDE / INFANT / REGULAR / PT = $18.00 +# BENTON_WASHINGTON / INFANT / REGULAR / PT = $19.00 + +- name: Case 1, Statewide infant full time base rate is 36.00. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 0 + childcare_hours_per_day: 8 + households: + household: + members: [person1] + county_str: PULASKI_COUNTY_AR + state_code: AR + output: + ar_sra_daily_base_rate: 36.00 + +- name: Case 2, Statewide toddler full time base rate is 35.00. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 2 + childcare_hours_per_day: 8 + households: + household: + members: [person1] + county_str: PULASKI_COUNTY_AR + state_code: AR + output: + ar_sra_daily_base_rate: 35.00 + +- name: Case 3, Statewide preschool full time base rate is 33.00. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 4 + childcare_hours_per_day: 8 + households: + household: + members: [person1] + county_str: PULASKI_COUNTY_AR + state_code: AR + output: + ar_sra_daily_base_rate: 33.00 + +- name: Case 4, Statewide school-aged full time base rate is 28.00. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 7 + childcare_hours_per_day: 8 + households: + household: + members: [person1] + county_str: PULASKI_COUNTY_AR + state_code: AR + output: + ar_sra_daily_base_rate: 28.00 + +- name: Case 5, Benton/Washington infant full time base rate is 38.00. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 0 + childcare_hours_per_day: 8 + households: + household: + members: [person1] + county_str: BENTON_COUNTY_AR + state_code: AR + output: + ar_sra_daily_base_rate: 38.00 + +- name: Case 6, Benton/Washington toddler full time base rate is 37.00. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 2 + childcare_hours_per_day: 8 + households: + household: + members: [person1] + county_str: WASHINGTON_COUNTY_AR + state_code: AR + output: + ar_sra_daily_base_rate: 37.00 + +- name: Case 7, Statewide infant part time base rate is 18.00. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 0 + childcare_hours_per_day: 4 + households: + household: + members: [person1] + county_str: PULASKI_COUNTY_AR + state_code: AR + output: + ar_sra_daily_base_rate: 18.00 + +- name: Case 8, Benton/Washington infant part time base rate is 19.00. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 0 + childcare_hours_per_day: 4 + households: + household: + members: [person1] + county_str: BENTON_COUNTY_AR + state_code: AR + output: + ar_sra_daily_base_rate: 19.00 + +- name: Case 9, Statewide infant Night/Weekend full time base rate is 39.60. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 0 + childcare_hours_per_day: 8 + ar_sra_care_type: NIGHT_WEEKEND + households: + household: + members: [person1] + county_str: PULASKI_COUNTY_AR + state_code: AR + output: + ar_sra_daily_base_rate: 39.60 + +- name: Case 10, Statewide infant SN1 full time base rate is 36.00. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 0 + childcare_hours_per_day: 8 + ar_sra_care_type: SN1 + households: + household: + members: [person1] + county_str: PULASKI_COUNTY_AR + state_code: AR + output: + ar_sra_daily_base_rate: 36.00 + +- name: Case 11, Statewide infant SN2 full time base rate is 50.40. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 0 + childcare_hours_per_day: 8 + ar_sra_care_type: SN2 + households: + household: + members: [person1] + county_str: PULASKI_COUNTY_AR + state_code: AR + output: + ar_sra_daily_base_rate: 50.40 + +- name: Case 12, Statewide infant SN3 full time base rate is 50.40. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 0 + childcare_hours_per_day: 8 + ar_sra_care_type: SN3 + households: + household: + members: [person1] + county_str: PULASKI_COUNTY_AR + state_code: AR + output: + ar_sra_daily_base_rate: 50.40 + +- name: Case 13, Statewide preschool Night/Weekend full time base rate is 36.30. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 4 + childcare_hours_per_day: 8 + ar_sra_care_type: NIGHT_WEEKEND + households: + household: + members: [person1] + county_str: PULASKI_COUNTY_AR + state_code: AR + output: + ar_sra_daily_base_rate: 36.30 + +- name: Case 14, Statewide infant Night/Weekend with part-time hours uses the PT Night/Weekend rate (19.80 = PT REGULAR 18 x 1.10). + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 0 + childcare_hours_per_day: 4 + ar_sra_care_type: NIGHT_WEEKEND + households: + household: + members: [person1] + county_str: PULASKI_COUNTY_AR + state_code: AR + output: + # Per OEC Oct 7 2025 Provider Call ("Weekend and night time rates are set + # at a standard 10% increase of typical rates"), PT Night/Weekend + # = PT REGULAR x 1.10 = 18 x 1.10 = 19.80. + ar_sra_daily_base_rate: 19.80 + +- name: Case 15, Benton/Washington infant SN2 full time base rate is 53.20. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 0 + childcare_hours_per_day: 8 + ar_sra_care_type: SN2 + households: + household: + members: [person1] + county_str: BENTON_COUNTY_AR + state_code: AR + output: + ar_sra_daily_base_rate: 53.20 + +- name: Case 16, Benton/Washington toddler Night/Weekend full time base rate is 40.70. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 2 + childcare_hours_per_day: 8 + ar_sra_care_type: NIGHT_WEEKEND + households: + household: + members: [person1] + county_str: WASHINGTON_COUNTY_AR + state_code: AR + output: + ar_sra_daily_base_rate: 40.70 + +- name: Case 17, Benton/Washington preschool REGULAR full time base rate is 33.00. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 4 + childcare_hours_per_day: 8 + households: + household: + members: [person1] + county_str: BENTON_COUNTY_AR + state_code: AR + output: + # B/W preschool rate matches Statewide ($33) at the regular tier. + ar_sra_daily_base_rate: 33.00 + +- name: Case 18, Benton/Washington school-aged REGULAR full time base rate is 28.00. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 7 + childcare_hours_per_day: 8 + households: + household: + members: [person1] + county_str: WASHINGTON_COUNTY_AR + state_code: AR + output: + # B/W school-aged rate matches Statewide ($28) at the regular tier. + ar_sra_daily_base_rate: 28.00 + +- name: Case 19, Benton/Washington preschool REGULAR part time base rate is 16.50. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 4 + childcare_hours_per_day: 4 + households: + household: + members: [person1] + county_str: BENTON_COUNTY_AR + state_code: AR + output: + ar_sra_daily_base_rate: 16.50 + +- name: Case 20, Benton/Washington school-aged REGULAR part time base rate is 14.00. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 7 + childcare_hours_per_day: 4 + households: + household: + members: [person1] + county_str: WASHINGTON_COUNTY_AR + state_code: AR + output: + ar_sra_daily_base_rate: 14.00 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/rates/ar_sra_daily_copay.yaml b/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/rates/ar_sra_daily_copay.yaml new file mode 100644 index 00000000000..ecdc0cbccf0 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/rates/ar_sra_daily_copay.yaml @@ -0,0 +1,251 @@ +# Daily family copay per child = daily_base_rate * (1 - state_share). + +- name: Case 1, Toddler Statewide FT at LE_40 SMI has zero copay (share 1.00). + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 28 + # 30% SMI -> LE_40 tier + employment_income: 18_417 + immigration_status: CITIZEN + person2: + age: 2 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + county_str: PULASKI_COUNTY_AR + output: + # Statewide / Toddler / REGULAR / FT base = $35.00, share = 1.00 + # daily copay = $35 * (1 - 1.00) = $0.00 + ar_sra_daily_copay: [0, 0.00] + +- name: Case 2, School-Aged Statewide FT at LE_40 SMI has positive copay (20 percent of base). + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 28 + # 30% SMI -> LE_40 tier + employment_income: 18_417 + immigration_status: CITIZEN + person2: + age: 7 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + county_str: PULASKI_COUNTY_AR + output: + # Statewide / School-Aged / REGULAR / FT base = $28.00, share = 0.80 + # daily copay = $28 * (1 - 0.80) = $5.60 + ar_sra_daily_copay: [0, 5.60] + +- name: Case 3, Preschool Statewide FT at GT_60 SMI has copay 40 percent of base. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 28 + # 75% SMI -> GT_60 tier + employment_income: 46_043 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + county_str: PULASKI_COUNTY_AR + output: + # Statewide / Preschool / REGULAR / FT base = $33.00, share = 0.60 + # daily copay = $33 * (1 - 0.60) = $13.20 + ar_sra_daily_copay: [0, 13.20] + +- name: Case 4, Infant Benton/Washington FT at GT_60 SMI has positive copay (30 percent of B/W base). + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 28 + # 75% SMI -> GT_60 tier + employment_income: 46_043 + immigration_status: CITIZEN + person2: + age: 0 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + county_str: BENTON_COUNTY_AR + output: + # Benton/Washington / Infant / REGULAR / FT base = $38.00, share = 0.70 + # daily copay = $38 * (1 - 0.70) = $11.40 + ar_sra_daily_copay: [0, 11.40] + +- name: Case 5, Toddler Statewide PT at GT_40_LE_60 SMI has positive copay (40 percent of PT base). + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 28 + # 50% SMI -> GT_40_LE_60 tier + employment_income: 30_695 + immigration_status: CITIZEN + person2: + age: 2 + is_tax_unit_dependent: true + immigration_status: CITIZEN + # Below the 7-hr FT threshold -> PART_TIME + childcare_hours_per_day: 4 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + county_str: PULASKI_COUNTY_AR + output: + # Statewide / Toddler / REGULAR / PT base = $17.50, share = 0.60 + # daily copay = $17.50 * (1 - 0.60) = $7.00 + ar_sra_daily_copay: [0, 7.00] + +- name: Case 6, Infant Statewide FT NIGHT_WEEKEND at GT_60 SMI shows the 10 percent supplement flows to copay. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 28 + # 75% SMI -> GT_60 tier + employment_income: 46_043 + immigration_status: CITIZEN + person2: + age: 0 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + ar_sra_care_type: NIGHT_WEEKEND + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + county_str: PULASKI_COUNTY_AR + output: + # Statewide / Infant / NIGHT_WEEKEND / FT base = $39.60, share = 0.70 + # daily copay = $39.60 * (1 - 0.70) = $11.88 + ar_sra_daily_copay: [0, 11.88] + +- name: Case 7, Toddler Statewide FT SN2 at GT_40_LE_60 SMI shows the 40 percent special-needs supplement flows to copay. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 28 + employment_income: 30_695 + immigration_status: CITIZEN + person2: + age: 2 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + ar_sra_care_type: SN2 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + county_str: PULASKI_COUNTY_AR + output: + # Statewide / Toddler / SN2 / FT base = $49.00, share = 0.80 + # daily copay = $49 * (1 - 0.80) = $9.80 + ar_sra_daily_copay: [0, 9.80] + +- name: Case 8, Toddler Statewide FT SN3 at GT_60 SMI confirms SN3 matches SN2 (premium tier). + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 28 + employment_income: 46_043 + immigration_status: CITIZEN + person2: + age: 2 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + ar_sra_care_type: SN3 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + county_str: PULASKI_COUNTY_AR + output: + # Statewide / Toddler / SN3 / FT base = $49.00, share = 0.70 + # daily copay = $49 * (1 - 0.70) = $14.70 + ar_sra_daily_copay: [0, 14.70] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/rates/ar_sra_daily_state_payment.yaml b/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/rates/ar_sra_daily_state_payment.yaml new file mode 100644 index 00000000000..753ce393150 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/rates/ar_sra_daily_state_payment.yaml @@ -0,0 +1,252 @@ +# Daily state payment per child = daily_base_rate * state_share. +# +# Arkansas SMI (2025-10-01, FFY 2026, 4-person): $90,280/year +# 2-person SPM: SMI = $61,390.40 annual + +- name: Case 1, Toddler Statewide FT at LE_40 SMI pays full base rate (no-copay). + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 28 + # 30% SMI -> LE_40 tier + employment_income: 18_417 + immigration_status: CITIZEN + person2: + age: 2 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + county_str: PULASKI_COUNTY_AR + output: + # Statewide / Toddler / REGULAR / FT base = $35.00; share = 1.00 + # daily state payment = $35.00 * 1.00 = $35.00 + ar_sra_daily_state_payment: [0, 35.00] + +- name: Case 2, School-Aged Statewide FT at LE_40 SMI has positive copay (share 0.80). + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 28 + # 30% SMI -> LE_40 tier + employment_income: 18_417 + immigration_status: CITIZEN + person2: + age: 7 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + county_str: PULASKI_COUNTY_AR + output: + # Statewide / School-Aged / REGULAR / FT base = $28.00; share = 0.80 + # daily state payment = $28.00 * 0.80 = $22.40 + ar_sra_daily_state_payment: [0, 22.40] + +- name: Case 3, Infant Benton/Washington FT at GT_60 SMI gets reduced share. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 28 + # 75% SMI -> GT_60 tier + employment_income: 46_043 + immigration_status: CITIZEN + person2: + age: 0 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + county_str: BENTON_COUNTY_AR + output: + # Benton/Washington / Infant / REGULAR / FT base = $38.00; share = 0.70 + # daily state payment = $38.00 * 0.70 = $26.60 + ar_sra_daily_state_payment: [0, 26.60] + +- name: Case 4, Toddler Statewide PT at GT_40_LE_60 SMI uses the PT base rate. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 28 + # 50% SMI -> GT_40_LE_60 tier + employment_income: 30_695 + immigration_status: CITIZEN + person2: + age: 2 + is_tax_unit_dependent: true + immigration_status: CITIZEN + # Below the 7-hr FT threshold -> PART_TIME + childcare_hours_per_day: 4 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + county_str: PULASKI_COUNTY_AR + output: + # Statewide / Toddler / REGULAR / PT base = $17.50; share = 0.60 + # daily state payment = $17.50 * 0.60 = $10.50 + ar_sra_daily_state_payment: [0, 10.50] + +- name: Case 5, Infant Statewide FT NIGHT_WEEKEND at GT_60 SMI shows the 10 percent supplement flows to state payment. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 28 + employment_income: 46_043 + immigration_status: CITIZEN + person2: + age: 0 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + ar_sra_care_type: NIGHT_WEEKEND + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + county_str: PULASKI_COUNTY_AR + output: + # Statewide / Infant / NIGHT_WEEKEND / FT base = $39.60; share = 0.70 + # daily state payment = $39.60 * 0.70 = $27.72 + ar_sra_daily_state_payment: [0, 27.72] + +- name: Case 6, Toddler Statewide FT SN2 at GT_40_LE_60 SMI shows the 40 percent special-needs supplement flows to state payment. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 28 + employment_income: 30_695 + immigration_status: CITIZEN + person2: + age: 2 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + ar_sra_care_type: SN2 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + county_str: PULASKI_COUNTY_AR + output: + # Statewide / Toddler / SN2 / FT base = $49.00; share = 0.80 + # daily state payment = $49 * 0.80 = $39.20 + ar_sra_daily_state_payment: [0, 39.20] + +- name: Case 7, Toddler Statewide FT SN3 at GT_60 SMI confirms SN3 rates match SN2. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 28 + employment_income: 46_043 + immigration_status: CITIZEN + person2: + age: 2 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + ar_sra_care_type: SN3 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + county_str: PULASKI_COUNTY_AR + output: + # Statewide / Toddler / SN3 / FT base = $49.00; share = 0.70 + # daily state payment = $49 * 0.70 = $34.30 + ar_sra_daily_state_payment: [0, 34.30] + +- name: Case 8, Preschool Benton/Washington PT at GT_60 SMI uses B/W PT rate. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 28 + employment_income: 46_043 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 4 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + county_str: BENTON_COUNTY_AR + output: + # B/W preschool PT rate matches Statewide ($16.50); share = 0.50 + # daily state payment = $16.50 * 0.50 = $8.25 + ar_sra_daily_state_payment: [0, 8.25] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/rates/ar_sra_income_tier.yaml b/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/rates/ar_sra_income_tier.yaml new file mode 100644 index 00000000000..50f8c058d41 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/rates/ar_sra_income_tier.yaml @@ -0,0 +1,241 @@ +# Income tiers (% SMI): +# LE_40: <= 40% SMI +# GT_40_LE_60: > 40%, <= 60% SMI +# GT_60: > 60% SMI +# +# Arkansas SMI (uprated at 2026-01-01): $95,201.95 +# 2-person SPM (parent + child): SMI = 95,201.95 * 0.68 = $64,737.33 annual + +- name: Case 1, family at 30 percent SMI is in the LE_40 tier. + period: 2026-01 + input: + people: + person1: + age: 30 + # 64,737.33 * 0.30 = $19,421.20 + employment_income: 19_421 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + output: + ar_sra_income_tier: LE_40 + +- name: Case 2, family at 50 percent SMI is in the GT_40_LE_60 tier. + period: 2026-01 + input: + people: + person1: + age: 30 + # 64,737.33 * 0.50 = $32,368.67 + employment_income: 32_369 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + output: + ar_sra_income_tier: GT_40_LE_60 + +- name: Case 3, family at 75 percent SMI is in the GT_60 tier. + period: 2026-01 + input: + people: + person1: + age: 30 + # 64,737.33 * 0.75 = $48,553.00 + employment_income: 48_553 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + output: + ar_sra_income_tier: GT_60 + +- name: Case 4, family just under 40 percent SMI is in the LE_40 tier. + period: 2026-01 + input: + people: + person1: + age: 30 + # 64,737.33 * 0.3985 = $25,798 (just under 40 percent) + employment_income: 25_800 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + output: + ar_sra_income_tier: LE_40 + +- name: Case 5, family just above 40 percent SMI is in the GT_40_LE_60 tier. + period: 2026-01 + input: + people: + person1: + age: 30 + # 64,737.33 * 0.4016 = $26,000 (just above 40 percent) + employment_income: 26_000 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + output: + ar_sra_income_tier: GT_40_LE_60 + +- name: Case 6, family just under 60 percent SMI is in the GT_40_LE_60 tier. + period: 2026-01 + input: + people: + person1: + age: 30 + # 64,737.33 * 0.5978 = $38,700 (just under 60 percent) + employment_income: 38_700 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + output: + ar_sra_income_tier: GT_40_LE_60 + +- name: Case 7, family just above 60 percent SMI is in the GT_60 tier. + period: 2026-01 + input: + people: + person1: + age: 30 + # 64,737.33 * 0.6025 = $39,000 (just above 60 percent) + employment_income: 39_000 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + output: + ar_sra_income_tier: GT_60 + +- name: Case 8, family at exactly 40 percent SMI is in the LE_40 tier (boundary is inclusive). + period: 2026-01 + input: + people: + person1: + age: 30 + # 64,737.33 * 0.40 = $25,894.93 + employment_income: 25_894.93 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + output: + ar_sra_income_tier: LE_40 + +- name: Case 9, family at exactly 60 percent SMI is in the GT_40_LE_60 tier (boundary is inclusive). + period: 2026-01 + input: + people: + person1: + age: 30 + # 64,737.33 * 0.60 = $38,842.40 + employment_income: 38_842.40 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + output: + ar_sra_income_tier: GT_40_LE_60 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/rates/ar_sra_state_share.yaml b/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/rates/ar_sra_state_share.yaml new file mode 100644 index 00000000000..a6dadc30dff --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/rates/ar_sra_state_share.yaml @@ -0,0 +1,693 @@ +# State payment share from rates/state_share_by_tier.yaml lookup +# Keyed by (age_category, time_category, income_tier). +# +# Examples (from parameter): +# Toddler FT LE_40 = 1.00 (no copay floor) +# Toddler FT GT_40_LE_60 = 0.80 +# Toddler FT GT_60 = 0.70 +# Preschool FT LE_40 = 1.00 +# Preschool FT GT_40_LE_60 = 0.70 +# School-Aged FT LE_40 = 0.80 (always copay) +# School-Aged FT GT_60 = 0.30 +# +# Arkansas SMI (FFY 2026, uprated to 2026-01-01, 4-person): $95,201.95/year +# 2-person SPM: SMI = 95,201.95 * 0.68 = $64,737.33 annual +# Tier percentages quoted in test names are computed against the uprated SMI. + +- name: Case 1, toddler at 30 percent SMI gets state share 1.00 (no-copay floor). + period: 2026-01 + absolute_error_margin: 0.001 + input: + people: + person1: + age: 30 + # 90,280 * 0.68 * 0.30 = $18,417.12 + employment_income: 18_417 + immigration_status: CITIZEN + person2: + age: 2 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + output: + ar_sra_state_share: [0, 1.00] + +- name: Case 2, preschooler at 50 percent SMI (FT) gets state share 0.70. + period: 2026-01 + absolute_error_margin: 0.001 + input: + people: + person1: + age: 30 + # 90,280 * 0.68 * 0.50 = $30,695.20 + employment_income: 30_695 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + output: + # Preschool FT GT_40_LE_60 = 0.70 + ar_sra_state_share: [0, 0.70] + +- name: Case 3, school-aged child at 80 percent SMI (FT) gets state share 0.30. + period: 2026-01 + absolute_error_margin: 0.001 + input: + people: + person1: + age: 30 + # 90,280 * 0.68 * 0.80 = $49,112.32 (above 60% SMI -> GT_60 tier) + employment_income: 49_112 + immigration_status: CITIZEN + person2: + age: 7 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + output: + # School-Aged FT GT_60 = 0.30 + ar_sra_state_share: [0, 0.30] + +- name: Case 4, school-aged child at 30 percent SMI (FT) still has copay (share 0.80). + period: 2026-01 + absolute_error_margin: 0.001 + input: + people: + person1: + age: 30 + # 90,280 * 0.68 * 0.30 = $18,417.12 + employment_income: 18_417 + immigration_status: CITIZEN + person2: + age: 7 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + output: + # School-Aged FT LE_40 = 0.80 (school-aged always has copay) + ar_sra_state_share: [0, 0.80] + +- name: Case 5, infant at 30 percent SMI (FT) gets state share 1.00. + period: 2026-01 + absolute_error_margin: 0.001 + input: + people: + person1: + age: 30 + employment_income: 18_417 + immigration_status: CITIZEN + person2: + age: 0 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + output: + # Infant FT LE_40 = 1.00 + ar_sra_state_share: [0, 1.00] + +- name: Case 6, infant at 50 percent SMI (FT) gets state share 0.80. + period: 2026-01 + absolute_error_margin: 0.001 + input: + people: + person1: + age: 30 + # 90,280 * 0.68 * 0.50 = $30,695.20 + employment_income: 30_695 + immigration_status: CITIZEN + person2: + age: 0 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + output: + # Infant FT GT_40_LE_60 = 0.80 + ar_sra_state_share: [0, 0.80] + +- name: Case 7, infant at 75 percent SMI (FT) gets state share 0.70. + period: 2026-01 + absolute_error_margin: 0.001 + input: + people: + person1: + age: 30 + # 90,280 * 0.68 * 0.75 = $46,043 + employment_income: 46_043 + immigration_status: CITIZEN + person2: + age: 0 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + output: + # Infant FT GT_60 = 0.70 + ar_sra_state_share: [0, 0.70] + +- name: Case 8, infant at 30 percent SMI (PT) gets state share 1.00. + period: 2026-01 + absolute_error_margin: 0.001 + input: + people: + person1: + age: 30 + employment_income: 18_417 + immigration_status: CITIZEN + person2: + age: 0 + is_tax_unit_dependent: true + immigration_status: CITIZEN + # Below 30 hr FT threshold + childcare_hours_per_day: 4 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + output: + # Infant PT LE_40 = 1.00 + ar_sra_state_share: [0, 1.00] + +- name: Case 9, infant at 50 percent SMI (PT) gets state share 0.70. + period: 2026-01 + absolute_error_margin: 0.001 + input: + people: + person1: + age: 30 + employment_income: 30_695 + immigration_status: CITIZEN + person2: + age: 0 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 4 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + output: + # Infant PT GT_40_LE_60 = 0.70 + ar_sra_state_share: [0, 0.70] + +- name: Case 10, infant at 75 percent SMI (PT) gets state share 0.60. + period: 2026-01 + absolute_error_margin: 0.001 + input: + people: + person1: + age: 30 + employment_income: 46_043 + immigration_status: CITIZEN + person2: + age: 0 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 4 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + output: + # Infant PT GT_60 = 0.60 + ar_sra_state_share: [0, 0.60] + +- name: Case 11, toddler at 30 percent SMI (PT) gets state share 1.00. + period: 2026-01 + absolute_error_margin: 0.001 + input: + people: + person1: + age: 30 + employment_income: 18_417 + immigration_status: CITIZEN + person2: + age: 2 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 4 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + output: + # Toddler PT LE_40 = 1.00 + ar_sra_state_share: [0, 1.00] + +- name: Case 12, toddler at 50 percent SMI (PT) gets state share 0.60. + period: 2026-01 + absolute_error_margin: 0.001 + input: + people: + person1: + age: 30 + employment_income: 30_695 + immigration_status: CITIZEN + person2: + age: 2 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 4 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + output: + # Toddler PT GT_40_LE_60 = 0.60 + ar_sra_state_share: [0, 0.60] + +- name: Case 13, toddler at 75 percent SMI (PT) gets state share 0.50. + period: 2026-01 + absolute_error_margin: 0.001 + input: + people: + person1: + age: 30 + employment_income: 46_043 + immigration_status: CITIZEN + person2: + age: 2 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 4 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + output: + # Toddler PT GT_60 = 0.50 + ar_sra_state_share: [0, 0.50] + +- name: Case 14, preschooler at 30 percent SMI (PT) gets state share 1.00. + period: 2026-01 + absolute_error_margin: 0.001 + input: + people: + person1: + age: 30 + employment_income: 18_417 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 4 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + output: + # Preschool PT LE_40 = 1.00 + ar_sra_state_share: [0, 1.00] + +- name: Case 15, preschooler at 50 percent SMI (PT) gets state share 0.60. + period: 2026-01 + absolute_error_margin: 0.001 + input: + people: + person1: + age: 30 + employment_income: 30_695 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 4 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + output: + # Preschool PT GT_40_LE_60 = 0.60 + ar_sra_state_share: [0, 0.60] + +- name: Case 16, preschooler at 75 percent SMI (PT) gets state share 0.50. + period: 2026-01 + absolute_error_margin: 0.001 + input: + people: + person1: + age: 30 + employment_income: 46_043 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 4 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + output: + # Preschool PT GT_60 = 0.50 + ar_sra_state_share: [0, 0.50] + +- name: Case 17, school-aged child at 30 percent SMI (PT) gets state share 0.70. + period: 2026-01 + absolute_error_margin: 0.001 + input: + people: + person1: + age: 30 + employment_income: 18_417 + immigration_status: CITIZEN + person2: + age: 7 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 4 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + output: + # School-Aged PT LE_40 = 0.70 + ar_sra_state_share: [0, 0.70] + +- name: Case 18, school-aged child at 50 percent SMI (PT) gets state share 0.50. + period: 2026-01 + absolute_error_margin: 0.001 + input: + people: + person1: + age: 30 + employment_income: 30_695 + immigration_status: CITIZEN + person2: + age: 7 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 4 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + output: + # School-Aged PT GT_40_LE_60 = 0.50 + ar_sra_state_share: [0, 0.50] + +- name: Case 19, school-aged child at 75 percent SMI (PT) gets state share 0.30. + period: 2026-01 + absolute_error_margin: 0.001 + input: + people: + person1: + age: 30 + employment_income: 46_043 + immigration_status: CITIZEN + person2: + age: 7 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 4 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + output: + # School-Aged PT GT_60 = 0.30 + ar_sra_state_share: [0, 0.30] + +- name: Case 20, toddler at 50 percent SMI (FT) gets state share 0.80. + period: 2026-01 + absolute_error_margin: 0.001 + input: + people: + person1: + age: 30 + employment_income: 30_695 + immigration_status: CITIZEN + person2: + age: 2 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + output: + # Toddler FT GT_40_LE_60 = 0.80 + ar_sra_state_share: [0, 0.80] + +- name: Case 21, toddler at 75 percent SMI (FT) gets state share 0.70. + period: 2026-01 + absolute_error_margin: 0.001 + input: + people: + person1: + age: 30 + employment_income: 46_043 + immigration_status: CITIZEN + person2: + age: 2 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + output: + # Toddler FT GT_60 = 0.70 + ar_sra_state_share: [0, 0.70] + +- name: Case 22, preschooler at 30 percent SMI (FT) gets state share 1.00. + period: 2026-01 + absolute_error_margin: 0.001 + input: + people: + person1: + age: 30 + employment_income: 18_417 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + output: + # Preschool FT LE_40 = 1.00 + ar_sra_state_share: [0, 1.00] + +- name: Case 23, preschooler at 75 percent SMI (FT) gets state share 0.60. + period: 2026-01 + absolute_error_margin: 0.001 + input: + people: + person1: + age: 30 + employment_income: 46_043 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + output: + # Preschool FT GT_60 = 0.60 + ar_sra_state_share: [0, 0.60] + +- name: Case 24, school-aged child at 50 percent SMI (FT) gets state share 0.50. + period: 2026-01 + absolute_error_margin: 0.001 + input: + people: + person1: + age: 30 + employment_income: 30_695 + immigration_status: CITIZEN + person2: + age: 7 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AR + output: + # School-Aged FT GT_40_LE_60 = 0.50 + ar_sra_state_share: [0, 0.50] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/rates/ar_sra_time_category.yaml b/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/rates/ar_sra_time_category.yaml new file mode 100644 index 00000000000..3d9a1d8e0b6 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/rates/ar_sra_time_category.yaml @@ -0,0 +1,80 @@ +# Time category: childcare_hours_per_day >= 7 -> FULL_TIME, otherwise PART_TIME. +# Per FSU §5.4.6 "7+ hours per day" (gov.states.ar.ade.oec.sra.rates.full_time_hours_threshold = 7). + +- name: Case 1, 7 hours per day is FULL_TIME at the threshold. + period: 2026-01 + input: + people: + person1: + childcare_hours_per_day: 7 + households: + household: + members: [person1] + state_code: AR + output: + ar_sra_time_category: FULL_TIME + +- name: Case 2, 8 hours per day is FULL_TIME. + period: 2026-01 + input: + people: + person1: + childcare_hours_per_day: 8 + households: + household: + members: [person1] + state_code: AR + output: + ar_sra_time_category: FULL_TIME + +- name: Case 3, 5 hours per day is PART_TIME. + period: 2026-01 + input: + people: + person1: + childcare_hours_per_day: 5 + households: + household: + members: [person1] + state_code: AR + output: + ar_sra_time_category: PART_TIME + +- name: Case 4, 6 hours per day is PART_TIME just below the threshold. + period: 2026-01 + input: + people: + person1: + childcare_hours_per_day: 6 + households: + household: + members: [person1] + state_code: AR + output: + ar_sra_time_category: PART_TIME + +- name: Case 5, 0 hours per day is PART_TIME. + period: 2026-01 + input: + people: + person1: + childcare_hours_per_day: 0 + households: + household: + members: [person1] + state_code: AR + output: + ar_sra_time_category: PART_TIME + +- name: Case 6, 8 hours per day for 4 days per week (32 hours per week total) is FULL_TIME under the per-day rule. + period: 2026-01 + input: + people: + person1: + childcare_hours_per_day: 8 + households: + household: + members: [person1] + state_code: AR + output: + ar_sra_time_category: FULL_TIME diff --git a/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/rates/ar_sra_zone.yaml b/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/rates/ar_sra_zone.yaml new file mode 100644 index 00000000000..94d650c0c77 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ar/ade/oec/sra/rates/ar_sra_zone.yaml @@ -0,0 +1,37 @@ +# SRA rate zones: Benton and Washington Counties (Northwest Arkansas) +# vs. STATEWIDE for every other AR county. + +- name: Case 1, Benton County is in the BENTON_WASHINGTON zone. + period: 2026-01 + input: + county_str: BENTON_COUNTY_AR + state_code: AR + output: + ar_sra_zone: BENTON_WASHINGTON + +- name: Case 2, Washington County is in the BENTON_WASHINGTON zone. + period: 2026-01 + input: + county_str: WASHINGTON_COUNTY_AR + state_code: AR + output: + ar_sra_zone: BENTON_WASHINGTON + +- name: Case 3, Pulaski County (Little Rock) is in the STATEWIDE zone. + period: 2026-01 + input: + county_str: PULASKI_COUNTY_AR + state_code: AR + output: + ar_sra_zone: STATEWIDE + +- name: Case 4, non-AR household with a B/W county string still defaults to STATEWIDE (state-guard). + period: 2026-01 + input: + # defined_for filters output, not the rate-table lookup; the formula's + # explicit state == "AR" check is what prevents non-AR rows from being + # classified as Benton/Washington when the county string coincides. + county_str: BENTON_COUNTY_AR + state_code: TX + output: + ar_sra_zone: STATEWIDE diff --git a/policyengine_us/variables/gov/states/ar/ade/oec/sra/ar_child_care_subsidies.py b/policyengine_us/variables/gov/states/ar/ade/oec/sra/ar_child_care_subsidies.py new file mode 100644 index 00000000000..f0aeb2b7fe8 --- /dev/null +++ b/policyengine_us/variables/gov/states/ar/ade/oec/sra/ar_child_care_subsidies.py @@ -0,0 +1,11 @@ +from policyengine_us.model_api import * + + +class ar_child_care_subsidies(Variable): + value_type = float + entity = SPMUnit + label = "Arkansas child care subsidies" + unit = USD + definition_period = YEAR + defined_for = StateCode.AR + adds = ["ar_sra"] diff --git a/policyengine_us/variables/gov/states/ar/ade/oec/sra/ar_months_since_tea_exit.py b/policyengine_us/variables/gov/states/ar/ade/oec/sra/ar_months_since_tea_exit.py new file mode 100644 index 00000000000..df962eceef4 --- /dev/null +++ b/policyengine_us/variables/gov/states/ar/ade/oec/sra/ar_months_since_tea_exit.py @@ -0,0 +1,11 @@ +from policyengine_us.model_api import * + + +class ar_months_since_tea_exit(Variable): + value_type = int + entity = SPMUnit + label = "Months since Arkansas TEA cash aid ended" + definition_period = MONTH + defined_for = StateCode.AR + default_value = 0 + reference = "https://dese.ade.arkansas.gov/Files/FSU-Procedural-Manual-June-2023_UPDATED_20230629075344.pdf#page=12" diff --git a/policyengine_us/variables/gov/states/ar/ade/oec/sra/ar_sra.py b/policyengine_us/variables/gov/states/ar/ade/oec/sra/ar_sra.py new file mode 100644 index 00000000000..41d97651275 --- /dev/null +++ b/policyengine_us/variables/gov/states/ar/ade/oec/sra/ar_sra.py @@ -0,0 +1,49 @@ +from policyengine_us.model_api import * + + +class ar_sra(Variable): + value_type = float + entity = SPMUnit + label = "Arkansas School Readiness Assistance benefit amount" + unit = USD + definition_period = MONTH + defined_for = "is_ar_sra_eligible" + reference = ( + "https://dese.ade.arkansas.gov/Files/SRA_Sliding_Fee_Scale_with_Rates_&_Copays--Statewide_Full_Time_20251101_OEC.pdf", + "https://dese.ade.arkansas.gov/Files/SRA_Sliding_Fee_Scale_with_Rates_&_Copays--Statewide_Part_Time_20251101_OEC.pdf", + "https://dese.ade.arkansas.gov/Files/SRA_Sliding_Fee_Scale_with_Rates_&_Copays--Benton-Washington_Co_Full_Time_20251101_OEC.pdf", + "https://dese.ade.arkansas.gov/Files/SRA_Sliding_Fee_Scale_with_Rates_&_Copays--Benton-Washington_Co_Part_Time_20251101_OEC.pdf", + "https://dese.ade.arkansas.gov/Files/2025-2027_CCDF_State_Plan_Final_4.26.24.1REV_OEC.pdf#page=39", + "https://dese.ade.arkansas.gov/Files/FSU-Procedural-Manual-June-2023_UPDATED_20230629075344.pdf#page=20", + ) + + def formula(spm_unit, period, parameters): + person = spm_unit.members + is_eligible_child = person("is_ar_sra_child_eligible", period) + daily_state_payment = person("ar_sra_daily_state_payment", period) + daily_copay = person("ar_sra_daily_copay", period) + attending_days = person("childcare_attending_days_per_month", period.this_year) + monthly_max_state_payment = daily_state_payment * attending_days + monthly_copay = daily_copay * attending_days + monthly_expense = person("pre_subsidy_childcare_expenses", period) + uncapped_subsidy = min_( + max_(monthly_expense - monthly_copay, 0), + monthly_max_state_payment, + ) + total_uncapped_subsidy = spm_unit.sum(uncapped_subsidy * is_eligible_child) + # CCDF State Plan §3.1.1 caps family copay at 4% of monthly income. + # FSU §4.3.3 (file p.20) excludes children's SSI and Social Security + # from the budget, so the cap base is countable (adult) income — not + # the literal "gross income" wording. + p = parameters(period).gov.states.ar.ade.oec.sra.rates + # Each child's payable copay is the lesser of the rate-sheet copay and + # the child's actual provider charge — a child whose expense is below + # the scheduled copay does not owe the full scheduled amount. + payable_copay = min_(monthly_copay, monthly_expense) + total_payable_copay = spm_unit.sum(payable_copay * is_eligible_child) + # Clamp at 0 so a self-employment loss doesn't inflate cap_savings. + countable_income = max_(spm_unit("ar_sra_countable_income", period), 0) + copay_ceiling = p.max_copay_share_of_gross_income * countable_income + cap_savings = max_(total_payable_copay - copay_ceiling, 0) + total_expense = spm_unit.sum(monthly_expense * is_eligible_child) + return min_(total_uncapped_subsidy + cap_savings, total_expense) diff --git a/policyengine_us/variables/gov/states/ar/ade/oec/sra/ar_sra_age_category.py b/policyengine_us/variables/gov/states/ar/ade/oec/sra/ar_sra_age_category.py new file mode 100644 index 00000000000..47caed46d21 --- /dev/null +++ b/policyengine_us/variables/gov/states/ar/ade/oec/sra/ar_sra_age_category.py @@ -0,0 +1,34 @@ +from policyengine_us.model_api import * + + +class ArSraAgeCategory(Enum): + INFANT = "Infant" + TODDLER = "Toddler" + PRESCHOOL = "Preschool" + SCHOOL_AGED = "School-Aged" + + +class ar_sra_age_category(Variable): + value_type = Enum + entity = Person + possible_values = ArSraAgeCategory + default_value = ArSraAgeCategory.INFANT + definition_period = MONTH + defined_for = StateCode.AR + label = "Arkansas SRA child age category" + reference = ( + "https://dese.ade.arkansas.gov/Files/SRA_Sliding_Fee_Scale_with_Rates_&_Copays--Statewide_Full_Time_20251101_OEC.pdf", + "https://dese.ade.arkansas.gov/Files/SRA_Sliding_Fee_Scale_with_Rates_&_Copays--Statewide_Part_Time_20251101_OEC.pdf", + "https://dese.ade.arkansas.gov/Files/SRA_Sliding_Fee_Scale_with_Rates_&_Copays--Benton-Washington_Co_Full_Time_20251101_OEC.pdf", + "https://dese.ade.arkansas.gov/Files/SRA_Sliding_Fee_Scale_with_Rates_&_Copays--Benton-Washington_Co_Part_Time_20251101_OEC.pdf", + "https://law.justia.com/codes/arkansas/title-6/subtitle-2/chapter-18/subchapter-2/section-6-18-207/", + ) + + def formula(person, period, parameters): + # Infant/Toddler boundaries follow AR Min Licensing (DCCECE 2020). + # The 72-month School-Aged boundary tracks typical kindergarten entry + # under Ark. Code §6-18-207 (age 5 by Aug 1 of the school year); + # Preschool spans the 36-71 month gap. + p = parameters(period).gov.states.ar.ade.oec.sra.rates.age_category_months + age_months = person("age", period.this_year) * MONTHS_IN_YEAR + return p.calc(age_months) diff --git a/policyengine_us/variables/gov/states/ar/ade/oec/sra/ar_sra_care_type.py b/policyengine_us/variables/gov/states/ar/ade/oec/sra/ar_sra_care_type.py new file mode 100644 index 00000000000..fcc469b20f5 --- /dev/null +++ b/policyengine_us/variables/gov/states/ar/ade/oec/sra/ar_sra_care_type.py @@ -0,0 +1,27 @@ +from policyengine_us.model_api import * + + +class ArSraCareType(Enum): + REGULAR = "Regular" + NIGHT_WEEKEND = "Night/Weekend" + SN1 = "Special Needs Level 1" + SN2 = "Special Needs Level 2" + SN3 = "Special Needs Level 3" + + +# Per FSU Procedural Manual §5.6.1: SN1 = no extra staff, SN2 = temporary extra +# staff, SN3 = full-time 1:1 staff, set by a licensed medical practitioner. We +# don't track that operational determination at the moment, so this is a bare +# input — users modeling a known case set it directly. +class ar_sra_care_type(Variable): + value_type = Enum + entity = Person + possible_values = ArSraCareType + default_value = ArSraCareType.REGULAR + definition_period = MONTH + defined_for = StateCode.AR + label = "Arkansas SRA care type" + reference = ( + "https://dese.ade.arkansas.gov/Files/SRA_Sliding_Fee_Scale_with_Rates_&_Copays--Statewide_Full_Time_20251101_OEC.pdf", + "https://dese.ade.arkansas.gov/Files/FSU-Procedural-Manual-June-2023_UPDATED_20230629075344.pdf#page=32", + ) diff --git a/policyengine_us/variables/gov/states/ar/ade/oec/sra/ar_sra_income_tier.py b/policyengine_us/variables/gov/states/ar/ade/oec/sra/ar_sra_income_tier.py new file mode 100644 index 00000000000..b5ecd0ed1fc --- /dev/null +++ b/policyengine_us/variables/gov/states/ar/ade/oec/sra/ar_sra_income_tier.py @@ -0,0 +1,38 @@ +from policyengine_us.model_api import * + + +class ArSraIncomeTier(Enum): + LE_40 = "At or below 40% SMI" + GT_40_LE_60 = "Above 40% and at or below 60% SMI" + GT_60 = "Above 60% SMI" + + +class ar_sra_income_tier(Variable): + value_type = Enum + entity = SPMUnit + possible_values = ArSraIncomeTier + default_value = ArSraIncomeTier.GT_60 + definition_period = MONTH + defined_for = StateCode.AR + label = "Arkansas SRA family income tier (% SMI)" + reference = ( + "https://dese.ade.arkansas.gov/Files/SRA_Sliding_Fee_Scale_with_Rates_&_Copays--Statewide_Full_Time_20251101_OEC.pdf", + "https://dese.ade.arkansas.gov/Files/SRA_Sliding_Fee_Scale_with_Rates_&_Copays--Statewide_Part_Time_20251101_OEC.pdf", + "https://dese.ade.arkansas.gov/Files/SRA_Sliding_Fee_Scale_with_Rates_&_Copays--Benton-Washington_Co_Full_Time_20251101_OEC.pdf", + "https://dese.ade.arkansas.gov/Files/SRA_Sliding_Fee_Scale_with_Rates_&_Copays--Benton-Washington_Co_Part_Time_20251101_OEC.pdf", + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ar.ade.oec.sra + monthly_income = spm_unit("ar_sra_countable_income", period) + # hhs_smi is YEAR-defined; bare period auto-divides annual → monthly. + monthly_smi = spm_unit("hhs_smi", period) + ratio = where(monthly_smi > 0, monthly_income / monthly_smi, np.inf) + return select( + [ + ratio <= p.rates.no_copay_smi_threshold, + ratio <= p.rates.partial_subsidy_smi_threshold, + ], + [ArSraIncomeTier.LE_40, ArSraIncomeTier.GT_40_LE_60], + default=ArSraIncomeTier.GT_60, + ) diff --git a/policyengine_us/variables/gov/states/ar/ade/oec/sra/ar_sra_time_category.py b/policyengine_us/variables/gov/states/ar/ade/oec/sra/ar_sra_time_category.py new file mode 100644 index 00000000000..0884784e3c4 --- /dev/null +++ b/policyengine_us/variables/gov/states/ar/ade/oec/sra/ar_sra_time_category.py @@ -0,0 +1,29 @@ +from policyengine_us.model_api import * + + +class ArSraTimeCategory(Enum): + FULL_TIME = "Full-Time" + PART_TIME = "Part-Time" + + +class ar_sra_time_category(Variable): + value_type = Enum + entity = Person + possible_values = ArSraTimeCategory + default_value = ArSraTimeCategory.FULL_TIME + definition_period = MONTH + defined_for = StateCode.AR + label = "Arkansas SRA time category" + reference = ( + "https://dese.ade.arkansas.gov/Files/SRA_Sliding_Fee_Scale_with_Rates_&_Copays--Statewide_Full_Time_20251101_OEC.pdf", + "https://dese.ade.arkansas.gov/Files/SRA_Sliding_Fee_Scale_with_Rates_&_Copays--Statewide_Part_Time_20251101_OEC.pdf", + ) + + def formula(person, period, parameters): + p = parameters(period).gov.states.ar.ade.oec.sra.rates + hours = person("childcare_hours_per_day", period.this_year) + return where( + hours >= p.full_time_hours_threshold, + ArSraTimeCategory.FULL_TIME, + ArSraTimeCategory.PART_TIME, + ) diff --git a/policyengine_us/variables/gov/states/ar/ade/oec/sra/ar_sra_zone.py b/policyengine_us/variables/gov/states/ar/ade/oec/sra/ar_sra_zone.py new file mode 100644 index 00000000000..6f520a5e42f --- /dev/null +++ b/policyengine_us/variables/gov/states/ar/ade/oec/sra/ar_sra_zone.py @@ -0,0 +1,33 @@ +from policyengine_us.model_api import * + + +class ArSraZone(Enum): + BENTON_WASHINGTON = "Benton/Washington" + STATEWIDE = "Statewide" + + +class ar_sra_zone(Variable): + value_type = Enum + entity = Household + possible_values = ArSraZone + default_value = ArSraZone.STATEWIDE + definition_period = MONTH + defined_for = StateCode.AR + label = "Arkansas SRA rate zone" + reference = ( + "https://dese.ade.arkansas.gov/Files/SRA_Sliding_Fee_Scale_with_Rates_&_Copays--Benton-Washington_Co_Full_Time_20251101_OEC.pdf", + "https://dese.ade.arkansas.gov/Files/SRA_Sliding_Fee_Scale_with_Rates_&_Copays--Statewide_Full_Time_20251101_OEC.pdf", + ) + + def formula(household, period, parameters): + # Guard against non-AR rows: defined_for filters output but not the lookup. + state = household("state_code_str", period.this_year) + county = household("county_str", period.this_year) + p = parameters(period).gov.states.ar.ade.oec.sra.rates + in_bw_county = np.isin(county, p.benton_washington_counties) + in_benton_washington = (state == "AR") & in_bw_county + return where( + in_benton_washington, + ArSraZone.BENTON_WASHINGTON, + ArSraZone.STATEWIDE, + ) diff --git a/policyengine_us/variables/gov/states/ar/ade/oec/sra/ar_was_tea_recipient.py b/policyengine_us/variables/gov/states/ar/ade/oec/sra/ar_was_tea_recipient.py new file mode 100644 index 00000000000..e4784ec1732 --- /dev/null +++ b/policyengine_us/variables/gov/states/ar/ade/oec/sra/ar_was_tea_recipient.py @@ -0,0 +1,11 @@ +from policyengine_us.model_api import * + + +class ar_was_tea_recipient(Variable): + value_type = bool + entity = SPMUnit + label = "Was an Arkansas Transitional Employment Assistance recipient" + definition_period = YEAR + defined_for = StateCode.AR + default_value = False + reference = "https://dese.ade.arkansas.gov/Files/FSU-Procedural-Manual-June-2023_UPDATED_20230629075344.pdf#page=12" diff --git a/policyengine_us/variables/gov/states/ar/ade/oec/sra/eligibility/is_ar_sra_age_eligible.py b/policyengine_us/variables/gov/states/ar/ade/oec/sra/eligibility/is_ar_sra_age_eligible.py new file mode 100644 index 00000000000..762534901dc --- /dev/null +++ b/policyengine_us/variables/gov/states/ar/ade/oec/sra/eligibility/is_ar_sra_age_eligible.py @@ -0,0 +1,20 @@ +from policyengine_us.model_api import * + + +class is_ar_sra_age_eligible(Variable): + value_type = bool + entity = Person + label = "Age-eligible for Arkansas SRA" + definition_period = MONTH + defined_for = StateCode.AR + reference = ( + "https://dese.ade.arkansas.gov/Files/2025-2027_CCDF_State_Plan_Final_4.26.24.1REV_OEC.pdf#page=18", + "https://dese.ade.arkansas.gov/Files/FSU-Procedural-Manual-June-2023_UPDATED_20230629075344.pdf#page=32", + ) + + def formula(person, period, parameters): + p = parameters(period).gov.states.ar.ade.oec.sra.eligibility + age = person("age", period.this_year) + is_disabled = person("is_disabled", period.this_year) + age_limit = where(is_disabled, p.child_age_limit_disabled, p.child_age_limit) + return age < age_limit diff --git a/policyengine_us/variables/gov/states/ar/ade/oec/sra/eligibility/is_ar_sra_child_eligible.py b/policyengine_us/variables/gov/states/ar/ade/oec/sra/eligibility/is_ar_sra_child_eligible.py new file mode 100644 index 00000000000..ea1ed437832 --- /dev/null +++ b/policyengine_us/variables/gov/states/ar/ade/oec/sra/eligibility/is_ar_sra_child_eligible.py @@ -0,0 +1,17 @@ +from policyengine_us.model_api import * + + +class is_ar_sra_child_eligible(Variable): + value_type = bool + entity = Person + label = "Eligible child for Arkansas SRA" + definition_period = MONTH + defined_for = StateCode.AR + reference = "https://dese.ade.arkansas.gov/Files/2025-2027_CCDF_State_Plan_Final_4.26.24.1REV_OEC.pdf#page=18" + + def formula(person, period, parameters): + age_eligible = person("is_ar_sra_age_eligible", period) + immigration_eligible = person( + "is_ccdf_immigration_eligible_child", period.this_year + ) + return age_eligible & immigration_eligible diff --git a/policyengine_us/variables/gov/states/ar/ade/oec/sra/eligibility/is_ar_sra_eligible.py b/policyengine_us/variables/gov/states/ar/ade/oec/sra/eligibility/is_ar_sra_eligible.py new file mode 100644 index 00000000000..0ba23bbbcc9 --- /dev/null +++ b/policyengine_us/variables/gov/states/ar/ade/oec/sra/eligibility/is_ar_sra_eligible.py @@ -0,0 +1,24 @@ +from policyengine_us.model_api import * + + +class is_ar_sra_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Eligible for Arkansas School Readiness Assistance" + definition_period = MONTH + defined_for = StateCode.AR + reference = ( + "https://dese.ade.arkansas.gov/Files/FSU-Procedural-Manual-June-2023_UPDATED_20230629075344.pdf#page=13", + "https://dese.ade.arkansas.gov/Files/R_&_R__Nov_2025_(English)_(1)_OEC.pdf#page=1", + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ar.ade.oec.sra + if not p.in_effect: + return False + has_eligible_child = add(spm_unit, period, ["is_ar_sra_child_eligible"]) > 0 + income_ok = spm_unit("is_ar_sra_income_eligible", period) + asset_ok = spm_unit("is_ccdf_asset_eligible", period.this_year) + li_active = spm_unit("is_ar_sra_li_activity_eligible", period) + ess_active = spm_unit("is_ar_sra_ess_eligible", period) + return has_eligible_child & income_ok & asset_ok & (li_active | ess_active) diff --git a/policyengine_us/variables/gov/states/ar/ade/oec/sra/eligibility/is_ar_sra_ess_eligible.py b/policyengine_us/variables/gov/states/ar/ade/oec/sra/eligibility/is_ar_sra_ess_eligible.py new file mode 100644 index 00000000000..634549209a1 --- /dev/null +++ b/policyengine_us/variables/gov/states/ar/ade/oec/sra/eligibility/is_ar_sra_ess_eligible.py @@ -0,0 +1,45 @@ +from policyengine_us.model_api import * + + +class is_ar_sra_ess_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Eligible for Arkansas SRA Employment-Sponsored Subsidy (ESS) track" + definition_period = MONTH + defined_for = StateCode.AR + reference = "https://dese.ade.arkansas.gov/Files/FSU-Procedural-Manual-June-2023_UPDATED_20230629075344.pdf#page=16" + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ar.ade.oec.sra.eligibility + was_tea = spm_unit("ar_was_tea_recipient", period.this_year) + months_since = spm_unit("ar_months_since_tea_exit", period) + ar_tea = spm_unit("ar_tea", period) + within_window = (months_since > 0) & (months_since <= p.ess_window_months) + in_track = was_tea & (ar_tea == 0) & within_window + in_year_1 = months_since <= p.ess_year_1_window_months + person = spm_unit.members + is_adult = person("age", period.this_year) >= p.adult_age_threshold + hours = person("weekly_hours_worked", period.this_year) + adult_hours = where(is_adult, hours, 0) + max_adult_hours = spm_unit.max(adult_hours) + adult_is_student = is_adult & person( + "is_full_time_college_student", period.this_year + ) + any_adult_student = spm_unit.sum(adult_is_student) > 0 + # FSU §4.1.5.1 Year-1 alt path: earnings *alone* make family + # TEA-income-ineligible. The "alone" qualifier constrains the gate + # input to earned income — unearned income (pension, child support, + # Social Security) does not count toward this specific test. + tea_earned = spm_unit("ar_tea_countable_earned_income", period) + tea_limit = parameters(period).gov.states.ar.dhs.tea.income.income_limit + earnings_make_tea_ineligible = tea_earned > tea_limit + year_1_active = ( + (max_adult_hours >= p.activity_hours_ess_year_1) + | any_adult_student + | earnings_make_tea_ineligible + ) + year_2_active = ( + max_adult_hours >= p.activity_hours_ess_year_2 + ) | any_adult_student + activity_ok = where(in_year_1, year_1_active, year_2_active) + return in_track & activity_ok diff --git a/policyengine_us/variables/gov/states/ar/ade/oec/sra/eligibility/is_ar_sra_income_eligible.py b/policyengine_us/variables/gov/states/ar/ade/oec/sra/eligibility/is_ar_sra_income_eligible.py new file mode 100644 index 00000000000..9c81ba6b444 --- /dev/null +++ b/policyengine_us/variables/gov/states/ar/ade/oec/sra/eligibility/is_ar_sra_income_eligible.py @@ -0,0 +1,17 @@ +from policyengine_us.model_api import * + + +class is_ar_sra_income_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Income-eligible for Arkansas SRA" + definition_period = MONTH + defined_for = StateCode.AR + reference = "https://dese.ade.arkansas.gov/Files/2025-2027_CCDF_State_Plan_Final_4.26.24.1REV_OEC.pdf#page=22" + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ar.ade.oec.sra.eligibility + monthly_income = spm_unit("ar_sra_countable_income", period) + # hhs_smi is YEAR-defined; bare period auto-divides annual → monthly. + monthly_smi_limit = spm_unit("hhs_smi", period) * p.income_smi_rate + return monthly_income <= monthly_smi_limit diff --git a/policyengine_us/variables/gov/states/ar/ade/oec/sra/eligibility/is_ar_sra_li_activity_eligible.py b/policyengine_us/variables/gov/states/ar/ade/oec/sra/eligibility/is_ar_sra_li_activity_eligible.py new file mode 100644 index 00000000000..6288dd186cc --- /dev/null +++ b/policyengine_us/variables/gov/states/ar/ade/oec/sra/eligibility/is_ar_sra_li_activity_eligible.py @@ -0,0 +1,24 @@ +from policyengine_us.model_api import * + + +class is_ar_sra_li_activity_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Activity-eligible for Arkansas SRA Low-Income track" + definition_period = MONTH + defined_for = StateCode.AR + reference = "https://dese.ade.arkansas.gov/Files/FSU-Procedural-Manual-June-2023_UPDATED_20230629075344.pdf#page=16" + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ar.ade.oec.sra.eligibility + person = spm_unit.members + is_adult = person("age", period.this_year) >= p.adult_age_threshold + hours = person("weekly_hours_worked", period.this_year) + # FSU §4.1.5.4 converts full-time college (12+ credits @ 2.5 hr/credit ≥ 30 hr) + # into work-equivalent; K-12 students excluded (rule applies to post-secondary). + is_student = person("is_full_time_college_student", period.this_year) + meets_activity = (hours >= p.activity_hours_li) | is_student + has_adult = spm_unit.sum(is_adult) > 0 + all_adults_qualify = spm_unit.sum(is_adult & ~meets_activity) == 0 + ccdf_fallback = spm_unit("meets_ccdf_activity_test", period.this_year) + return (has_adult & all_adults_qualify) | ccdf_fallback diff --git a/policyengine_us/variables/gov/states/ar/ade/oec/sra/income/ar_sra_countable_income.py b/policyengine_us/variables/gov/states/ar/ade/oec/sra/income/ar_sra_countable_income.py new file mode 100644 index 00000000000..dbeb694537a --- /dev/null +++ b/policyengine_us/variables/gov/states/ar/ade/oec/sra/income/ar_sra_countable_income.py @@ -0,0 +1,22 @@ +from policyengine_us.model_api import * + + +class ar_sra_countable_income(Variable): + value_type = float + entity = SPMUnit + label = "Arkansas SRA countable income" + unit = USD + definition_period = MONTH + defined_for = StateCode.AR + reference = ( + "https://dese.ade.arkansas.gov/Files/FSU-Procedural-Manual-June-2023_UPDATED_20230629075344.pdf#page=19", + "https://dese.ade.arkansas.gov/Files/FSU-Procedural-Manual-June-2023_UPDATED_20230629075344.pdf#page=20", + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ar.ade.oec.sra + # FSU §4.3.2 excludes children's SSI and Social Security; mask by adult status. + person = spm_unit.members + is_adult = person("age", period.this_year) >= p.eligibility.adult_age_threshold + per_person_income = sum(person(source, period) for source in p.income.sources) + return spm_unit.sum(per_person_income * is_adult) diff --git a/policyengine_us/variables/gov/states/ar/ade/oec/sra/rates/ar_sra_daily_base_rate.py b/policyengine_us/variables/gov/states/ar/ade/oec/sra/rates/ar_sra_daily_base_rate.py new file mode 100644 index 00000000000..7d406d5f959 --- /dev/null +++ b/policyengine_us/variables/gov/states/ar/ade/oec/sra/rates/ar_sra_daily_base_rate.py @@ -0,0 +1,29 @@ +from policyengine_us.model_api import * + + +class ar_sra_daily_base_rate(Variable): + value_type = float + entity = Person + unit = USD + label = "Arkansas SRA daily base provider rate" + definition_period = MONTH + defined_for = "is_ar_sra_child_eligible" + reference = ( + "https://dese.ade.arkansas.gov/Files/SRA_Sliding_Fee_Scale_with_Rates_&_Copays--Statewide_Full_Time_20251101_OEC.pdf", + "https://dese.ade.arkansas.gov/Files/SRA_Sliding_Fee_Scale_with_Rates_&_Copays--Statewide_Part_Time_20251101_OEC.pdf", + "https://dese.ade.arkansas.gov/Files/SRA_Sliding_Fee_Scale_with_Rates_&_Copays--Benton-Washington_Co_Full_Time_20251101_OEC.pdf", + "https://dese.ade.arkansas.gov/Files/SRA_Sliding_Fee_Scale_with_Rates_&_Copays--Benton-Washington_Co_Part_Time_20251101_OEC.pdf", + "https://dese.ade.arkansas.gov/Files/October_2025_Provider_Call_10.7.25_OEC.pdf#page=4", + ) + + def formula(person, period, parameters): + # Benton/Washington rates exceed Statewide for INFANT and TODDLER only; + # PRESCHOOL and SCHOOL_AGED rates are identical across both zones. The + # zone × age × care_type × time table preserves all four rate sheets + # so the structure stays explicit even where two cells collapse. + p = parameters(period).gov.states.ar.ade.oec.sra.rates + zone = person.household("ar_sra_zone", period) + age_category = person("ar_sra_age_category", period) + care_type = person("ar_sra_care_type", period) + time_category = person("ar_sra_time_category", period) + return p.base_rate[zone][age_category][care_type][time_category] diff --git a/policyengine_us/variables/gov/states/ar/ade/oec/sra/rates/ar_sra_daily_copay.py b/policyengine_us/variables/gov/states/ar/ade/oec/sra/rates/ar_sra_daily_copay.py new file mode 100644 index 00000000000..8cf141dc34e --- /dev/null +++ b/policyengine_us/variables/gov/states/ar/ade/oec/sra/rates/ar_sra_daily_copay.py @@ -0,0 +1,27 @@ +from policyengine_us.model_api import * + + +class ar_sra_daily_copay(Variable): + value_type = float + entity = Person + unit = USD + label = "Arkansas SRA daily family copay" + definition_period = MONTH + defined_for = "is_ar_sra_child_eligible" + reference = ( + "https://dese.ade.arkansas.gov/Files/SRA_Sliding_Fee_Scale_with_Rates_&_Copays--Statewide_Full_Time_20251101_OEC.pdf", + "https://dese.ade.arkansas.gov/Files/SRA_Sliding_Fee_Scale_with_Rates_&_Copays--Statewide_Part_Time_20251101_OEC.pdf", + "https://dese.ade.arkansas.gov/Files/SRA_Sliding_Fee_Scale_with_Rates_&_Copays--Benton-Washington_Co_Full_Time_20251101_OEC.pdf", + "https://dese.ade.arkansas.gov/Files/SRA_Sliding_Fee_Scale_with_Rates_&_Copays--Benton-Washington_Co_Part_Time_20251101_OEC.pdf", + ) + + def formula(person, period, parameters): + # Source conflict: CCDF State Plan §2.3.1(b) describes a no-cost-of-care + # waiver for families at or below 75% SMI, while the Nov 2025 operational + # rate sheet only zeroes the copay for families at or below 40% SMI. The + # model follows the rate sheet (40%) because it is the operational + # document the agency uses to compute family copays. The 75% State Plan + # provision is not modeled. + base = person("ar_sra_daily_base_rate", period) + state_share = person("ar_sra_state_share", period) + return base * (1 - state_share) diff --git a/policyengine_us/variables/gov/states/ar/ade/oec/sra/rates/ar_sra_daily_state_payment.py b/policyengine_us/variables/gov/states/ar/ade/oec/sra/rates/ar_sra_daily_state_payment.py new file mode 100644 index 00000000000..e9cc2eff4d7 --- /dev/null +++ b/policyengine_us/variables/gov/states/ar/ade/oec/sra/rates/ar_sra_daily_state_payment.py @@ -0,0 +1,21 @@ +from policyengine_us.model_api import * + + +class ar_sra_daily_state_payment(Variable): + value_type = float + entity = Person + unit = USD + label = "Arkansas SRA daily state payment per child" + definition_period = MONTH + defined_for = "is_ar_sra_child_eligible" + reference = ( + "https://dese.ade.arkansas.gov/Files/SRA_Sliding_Fee_Scale_with_Rates_&_Copays--Statewide_Full_Time_20251101_OEC.pdf", + "https://dese.ade.arkansas.gov/Files/SRA_Sliding_Fee_Scale_with_Rates_&_Copays--Statewide_Part_Time_20251101_OEC.pdf", + "https://dese.ade.arkansas.gov/Files/SRA_Sliding_Fee_Scale_with_Rates_&_Copays--Benton-Washington_Co_Full_Time_20251101_OEC.pdf", + "https://dese.ade.arkansas.gov/Files/SRA_Sliding_Fee_Scale_with_Rates_&_Copays--Benton-Washington_Co_Part_Time_20251101_OEC.pdf", + ) + + def formula(person, period, parameters): + base = person("ar_sra_daily_base_rate", period) + state_share = person("ar_sra_state_share", period) + return base * state_share diff --git a/policyengine_us/variables/gov/states/ar/ade/oec/sra/rates/ar_sra_state_share.py b/policyengine_us/variables/gov/states/ar/ade/oec/sra/rates/ar_sra_state_share.py new file mode 100644 index 00000000000..7bb27b81e29 --- /dev/null +++ b/policyengine_us/variables/gov/states/ar/ade/oec/sra/rates/ar_sra_state_share.py @@ -0,0 +1,22 @@ +from policyengine_us.model_api import * + + +class ar_sra_state_share(Variable): + value_type = float + entity = Person + label = "Arkansas SRA state share of daily base rate" + definition_period = MONTH + defined_for = "is_ar_sra_child_eligible" + reference = ( + "https://dese.ade.arkansas.gov/Files/SRA_Sliding_Fee_Scale_with_Rates_&_Copays--Statewide_Full_Time_20251101_OEC.pdf", + "https://dese.ade.arkansas.gov/Files/SRA_Sliding_Fee_Scale_with_Rates_&_Copays--Statewide_Part_Time_20251101_OEC.pdf", + "https://dese.ade.arkansas.gov/Files/SRA_Sliding_Fee_Scale_with_Rates_&_Copays--Benton-Washington_Co_Full_Time_20251101_OEC.pdf", + "https://dese.ade.arkansas.gov/Files/SRA_Sliding_Fee_Scale_with_Rates_&_Copays--Benton-Washington_Co_Part_Time_20251101_OEC.pdf", + ) + + def formula(person, period, parameters): + p = parameters(period).gov.states.ar.ade.oec.sra.rates + age_category = person("ar_sra_age_category", period) + time_category = person("ar_sra_time_category", period) + income_tier = person.spm_unit("ar_sra_income_tier", period) + return p.state_share_by_tier[age_category][time_category][income_tier]