Skip to content

Add Pennsylvania CCAP (Child Care Assistance Program)#7829

Merged
MaxGhenis merged 9 commits intoPolicyEngine:mainfrom
hua7450:pa-ccap
Apr 6, 2026
Merged

Add Pennsylvania CCAP (Child Care Assistance Program)#7829
MaxGhenis merged 9 commits intoPolicyEngine:mainfrom
hua7450:pa-ccap

Conversation

@hua7450
Copy link
Copy Markdown
Collaborator

@hua7450 hua7450 commented Mar 23, 2026

Summary

Implements Pennsylvania Child Care Works (CCW) — the state's CCDF child care subsidy program — in PolicyEngine.

Closes #7828

Regulatory Authority

Income Eligibility Tests

Test Threshold Source
Initial application Annual income <= 200% FPIG 55 Pa. Code 3042.31(a)
Between redeterminations Annual income <= 85% SMI 55 Pa. Code 3042.31(b)
Redetermination Annual income <= min(235% FPIG, 85% SMI) 55 Pa. Code 3042.31(c)
Asset limit Family assets < $1,000,000 55 Pa. Code 3042.31(e)
TANF exclusion Not receiving TANF cash assistance 55 Pa. Code 3042.15(a)
Child age Under 13 (under 19 if incapable of self-care) 55 Pa. Code 3042.11(b),(d)
Child citizenship US citizen or lawful permanent resident 55 Pa. Code 3042.36
Residency Pennsylvania resident 55 Pa. Code 3042.32(a)

New applicants use the 200% FPIG threshold. Currently enrolled families (pa_ccw_enrolled = True) use 85% SMI between redeterminations (55 Pa. Code 3042.31(b)). The 235% FPIG cap applies only at the redetermination itself (3042.31(c)), which is not separately modeled.

Income Deductions & Exemptions

Income counted (55 Pa. Code 3042.42): Parent/caretaker, spouse, and children's unearned income. Appendix A Part I lists 21 income types (wages, self-employment, Social Security, pensions, unemployment, workers comp, veterans benefits, child support received, alimony, dividends, interest, rental income, etc.). Implemented via sources.yaml with 16 mapped PolicyEngine variables.

Deductions (55 Pa. Code Appendix A Part II):

Deduction Rule Source
Spousal support paid Court-ordered or voluntary, to person not in household Appendix A Part II, item A
Child support paid Court-ordered or voluntary, to person not in household Appendix A Part II, item B
Medical expenses Unreimbursed amount exceeding 10% of gross monthly income Appendix A Part II, item C
Stepparent deduction Fixed amount by county group (4 groups) and family size (Appendix C) 55 Pa. Code Appendix C

Stepparent Deduction (Appendix C):

County Group Size 2 Size 3 Size 4 Size 5 Size 6 Each add'l
Group 1 (30 counties incl. Philadelphia, Allegheny, Delaware) $461 $587 $724 $859 $976 $121
Group 2 (15 counties incl. Cambria, Fayette, Greene) $406 $532 $662 $791 $894 $121
Group 3 (17 counties incl. Beaver, Washington, Lawrence) $444 $573 $698 $829 $943 $121
Group 4 (5 counties: Bucks, Chester, Lancaster, Montgomery, Pike) $481 $614 $749 $885 $1,001 $121

Income exclusions (55 Pa. Code Appendix A Part III): Teen earnings, tax refunds/EITC, SNAP, WIC, foster care payments, student aid, LIHEAP, and ~15 other categories. These are excluded by not including them in the sources.yaml income list.

Income adjustment procedure (55 Pa. Code 3042.43): 8-step process — determine gross income per Appendix A Part I, estimate monthly per conversion table (55 Pa. Code Appendix A), apply stepparent deduction and other deductions, multiply result by 12 for annual adjusted family income.

Copayment

The copayment is weekly, per family (not per child) — 55 Pa. Code 3042.91(c)-(d); CCDF State Plan 3.2.1.

Formula (implemented as rate-based calculation per 55 Pa. Code 3042.98):

weekly_copay = max($5, annual_income * rate / 52)

where:

  • rate = 5% if annual income <= 100% FPIG, otherwise 7%
  • Minimum copay: $5/week — 3042.98(a)(2)
  • Maximum copay: 7% of annual income — 3042.98(a)(3)
  • Lower cap for poverty: 5% of annual income if income <= 100% FPIG — 3042.98(a)(4)
  • Copay waived for homelessness — 3042.146

Note: Appendix B contains a detailed sliding-fee copayment chart by family size and income bracket. The implementation uses the 5%/7% caps as an approximation, which overestimates copay by $4-35/month within the eligibility range (conservative — understates the actual benefit). The exact formula PA DHS uses to generate Appendix B is not published.

Benefit Calculation

Formula (55 Pa. Code 3042.14(b), 3042.92, 3042.118(c)):

monthly_copay = weekly_copay * WEEKS_IN_YEAR / MONTHS_IN_YEAR

max_monthly_payment = sum over eligible children:
    MCCA_daily_rate(region, provider_type, age_group, time_category) * attending_days_per_month

pa_ccw = max(0, min(childcare_expenses - monthly_copay, max_monthly_payment))
  • Minimum department payment: $5/week — if department's weekly payment < $5, family is not eligible with that provider (3042.92(c))
  • Provider may charge difference above MCCA to family (3042.14(d))

MCCA Rates

Structure: 19 regions x 4 provider types (CENTER, GROUP, FAMILY, R/N) x 5 age groups (Infant, Young Toddler, Old Toddler, Pre-School, School-Age) x 2 time categories (Full-Time, Part-Time).

Rate eras:

  • 2025 rates (eff. 2025-01-01): 760 values across 19 region YAML files
  • 2023 rates (eff. 2023-03-01): 760 values (2023 chart had 6 age groups including Old School-Age; School-Age and Old School-Age had identical rates, so only 5 age groups are parameterized)

Region mapping: Each PA county maps to one of 19 ELRC regions. pa_ccw_region derives the region from county_str using 18 parameter files (region 1 is the default). Source: PA DHS ELRC page.

Age group thresholds: Defined in age_group/months.yaml — Infant, Young Toddler, Old Toddler, Pre-School, School-Age based on child's age in months.

Not Modeled

Requirement Reason
Domestic violence copay waiver (3042.145) No input variable for DV status
Single parent disability exemption (3042.37(a)-(b)) Not simulatable
Two-parent disability exemption (3042.37(e)) Not simulatable
Provider charges above MCCA (3042.14(d)) Informational — no code needed
Copayment chart bracket lookup (Appendix B) Approximated by formula-based 5%/7% rate; unused bracket files exist but are not wired to variables

Files Added

policyengine_us/
├── parameters/gov/states/pa/dhs/ccw/
│   ├── eligibility/
│   │   ├── age_threshold/child.yaml
│   │   ├── age_threshold/disabled_child.yaml
│   │   ├── initial_income_limit.yaml
│   │   ├── redetermination_income_limit.yaml
│   │   └── continuous_smi_limit.yaml
│   ├── income/
│   │   ├── countable_income/sources.yaml
│   │   └── medical_expense_threshold.yaml
│   ├── copay/
│   │   ├── minimum.yaml
│   │   ├── max_rate.yaml
│   │   ├── low_income_max_rate.yaml
│   │   └── low_income_threshold.yaml
│   ├── stepparent_deduction/
│   │   ├── group_{1-4}.yaml (bracket params by family size)
│   │   ├── county_group_{1-4}.yaml (county-to-group mapping)
│   │   ├── each_additional.yaml
│   │   └── max_family_size.yaml
│   ├── activity_requirements/
│   │   ├── weekly_hours.yaml
│   │   ├── training_combo_min_work_hours.yaml
│   │   └── teen_parent_max_age.yaml
│   ├── region/region_{1-19}.yaml (county-to-ELRC-region mapping)
│   ├── rates/region_{1-19}.yaml (MCCA daily rates, nested by provider/age/time)
│   ├── age_group/months.yaml
│   ├── full_time_hours_per_day.yaml
│   └── min_dept_payment.yaml
├── variables/gov/states/pa/dhs/ccw/
│   ├── eligibility/
│   │   ├── pa_ccw_eligible.py
│   │   ├── pa_ccw_eligible_child.py
│   │   ├── pa_ccw_income_eligible.py
│   │   └── pa_ccw_activity_eligible.py
│   ├── income/
│   │   ├── pa_ccw_countable_income.py
│   │   ├── pa_ccw_adjusted_income.py
│   │   ├── pa_ccw_stepparent_deduction.py
│   │   ├── pa_ccw_stepparent_county_group.py
│   │   └── pa_ccw_has_stepparent.py
│   ├── copay/pa_ccw_copay.py
│   ├── pa_ccw.py (top-level benefit)
│   ├── pa_ccw_maximum_monthly_payment.py
│   ├── pa_ccw_market_rate.py
│   ├── pa_ccw_region.py
│   ├── pa_ccw_age_group.py
│   ├── pa_ccw_time_category.py
│   ├── pa_ccw_provider_type.py
│   ├── pa_ccw_enrolled.py
│   └── pa_child_care_subsidies.py
└── tests/policy/baseline/gov/states/pa/dhs/ccw/
    ├── pa_ccw.yaml
    ├── pa_ccw_eligible.yaml
    ├── pa_ccw_eligible_child.yaml
    ├── pa_ccw_income_eligible.yaml
    ├── pa_ccw_activity_eligible.yaml
    ├── pa_ccw_countable_income.yaml
    ├── pa_ccw_adjusted_income.yaml
    ├── pa_ccw_stepparent_deduction.yaml
    ├── pa_ccw_stepparent_county_group.yaml
    ├── pa_ccw_has_stepparent.yaml
    ├── pa_ccw_copay.yaml
    ├── pa_ccw_market_rate.yaml
    ├── pa_ccw_maximum_monthly_payment.yaml
    ├── pa_ccw_region.yaml
    ├── pa_ccw_age_group.yaml
    ├── pa_ccw_time_category.yaml
    ├── pa_ccw_enrolled.yaml
    ├── pa_child_care_subsidies.yaml
    └── integration.yaml

Review Fixes

Fix Details
Activity test formula Derives from weekly_hours_worked, is_full_time_student; requires ALL parents to qualify in two-parent households; training combo requires student status AND >=10 hrs; falls back to meets_ccdf_activity_test
YEAR period for child/activity pa_ccw_eligible_child and pa_ccw_activity_eligible changed to YEAR to match PA's 12-month certification rules (55 Pa. Code 3042.11(d), 3042.19)
Foster/protective services bypass pa_ccw_eligible_child now accepts foster care and protective services children regardless of tax dependency or immigration (55 Pa. Code 3042.3)
Region from county pa_ccw_region derives ELRC region from county_str (18 county-mapping parameter files, 67 counties)
MCCA rate references Added public hrefs to all 19 rate files (2025 via pakeys.org, 2023 via pa.gov)
Copay documented Documented per-family copay and Appendix B approximation ($4-35/mo overestimate, conservative)
Adjusted income simplified Formula stays in annual units; stepparent deduction annualized instead of converting all inputs to monthly
Market rate compact 19-way select() replaced with getattr loop (2 lines instead of 22)
Enrolled income limit Enrolled families use 85% SMI only (not min(235% FPIG, 85% SMI)); the 235% cap applies at redetermination, not between (55 Pa. Code 3042.31(b)-(c))

Test plan

  • 100 tests pass
  • CI passes

hua7450 and others added 3 commits March 23, 2026 10:41
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@codecov
Copy link
Copy Markdown

codecov bot commented Mar 23, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (fd8a1f8) to head (d95d3cd).
⚠️ Report is 103 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##              main     #7829    +/-   ##
==========================================
  Coverage   100.00%   100.00%            
==========================================
  Files           12        19     +7     
  Lines          174       297   +123     
==========================================
+ Hits           174       297   +123     
Flag Coverage Δ
unittests 100.00% <100.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

hua7450 and others added 5 commits March 23, 2026 12:31
…_hours_per_day, age_group

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Activity test (pa_ccw_activity_eligible):
- Fix training combo: require is_student AND >=10 hrs/week (was >=10 hrs
  alone, violating 55 Pa. Code 3042.33)
- Require ALL parents to qualify in two-parent households
- Add meets_ccdf_activity_test fallback for non-derivable activities
- Change to YEAR period: eligibility continues through 12-month
  certification after a break in work/education (55 Pa. Code 3042.19)

Child eligibility (pa_ccw_eligible_child):
- Change to YEAR period: child turning 13 mid-period stays eligible
  until next redetermination (55 Pa. Code 3042.11(d))
- Add foster care and protective services bypass (55 Pa. Code 3042.3)

Region lookup (pa_ccw_region):
- Add formula deriving ELRC region from county_str (18 parameter files
  mapping 67 counties to 19 regions)
- Use compact getattr + list comprehension pattern

Code simplification:
- pa_ccw_adjusted_income: keep formula in annual units (annualize
  stepparent deduction instead of converting all inputs to monthly)
- pa_ccw_market_rate: replace 18-way select + default with compact
  getattr loop over all 19 regions
- pa_ccw_copay: document per-family copay and Appendix B approximation

References:
- Add href links to all 19 rate files (MCCA 2025 + 2023 PDFs)
- Remove sources/working_references.md

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Enrolled families use 85% SMI as the income cap between
redeterminations, not min(235% FPIG, 85% SMI). The 235% FPIG cap
applies only at the redetermination itself (55 Pa. Code 3042.31(b)-(c)).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@hua7450 hua7450 marked this pull request as ready for review April 6, 2026 04:15
@MaxGhenis MaxGhenis merged commit 87c6a42 into PolicyEngine:main Apr 6, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement Pennsylvania CCAP (Child Care Assistance Program)

2 participants