Skip to content

Implement Pennsylvania CTC contributed reforms#7438

Merged
PavelMakarchuk merged 17 commits intoPolicyEngine:mainfrom
DTrim99:implement-pa-ctc-reform
Feb 25, 2026
Merged

Implement Pennsylvania CTC contributed reforms#7438
PavelMakarchuk merged 17 commits intoPolicyEngine:mainfrom
DTrim99:implement-pa-ctc-reform

Conversation

@DTrim99
Copy link
Collaborator

@DTrim99 DTrim99 commented Feb 19, 2026

Summary

Implements two Pennsylvania Child Tax Credit reform proposals as contributed reforms (not law).

Closes #7436

Proposals

1. Flat Amount CTC (pa_ctc_flat_amount)

  • $1,000 per qualifying child under age 6
  • 2% phaseout rate above $125,000 threshold (same for all filing statuses)
  • Refundable credit
  • Effective 2026

2. Federal CTC Match (pa_ctc_match)

  • 50% match of the federal Child Tax Credit
  • Limited to children under age 6
  • No income phaseout
  • Refundable credit
  • Effective 2026

Files Added

Parameters (gov/contrib/states/pa/ctc/):

  • flat_amount/ - in_effect, amount, age_limit, phaseout/threshold, phaseout/rate
  • ctc_match/ - in_effect, match, age_limit

Reform Code (reforms/states/pa/ctc/):

  • pa_ctc_flat_amount.py
  • pa_ctc_match.py
  • __init__.py files

Tests (tests/policy/contrib/states/pa/ctc/):

  • 8 tests for flat amount reform
  • 6 tests for CTC match reform

Test Plan

  • All 14 YAML tests pass
  • Tests cover income below/above threshold, phaseout calculations, age limits, filing statuses
  • make format passes

🤖 Generated with Claude Code

@DTrim99
Copy link
Collaborator Author

DTrim99 commented Feb 19, 2026

Implementation Complete

Proposal 1: Flat Amount CTC

Parameter Value
Credit Amount $1,000 per child
Age Limit Under 6
Phaseout Threshold $125,000 (all filing statuses)
Phaseout Rate 2%
Start Date 2026

Proposal 2: Federal CTC Match

Parameter Value
Match Rate 50%
Age Limit Under 6
Phaseout None
Start Date 2026

Test Coverage (14 tests)

  • ✅ Income below/at/above phaseout threshold
  • ✅ Credit fully phased out
  • ✅ Multiple filing statuses (single, joint, HOH)
  • ✅ Child at/above age limit
  • ✅ Mixed age children
  • ✅ Multiple young children

All tests pass locally.

@DTrim99
Copy link
Collaborator Author

DTrim99 commented Feb 19, 2026

Updated the CTC match implementation to use ctc_value instead of ctc_child_individual_maximum. This ensures low-income families only receive the match on their actual federal CTC amount after phase-in, not the maximum amount they would eventually receive.

Added low income test cases:

  • $2,000 income: $0 match (income below $2,500 federal CTC phase-in threshold)
  • $10,000 income: $562.50 match (partial federal CTC phase-in of $1,125)
  • $20,000 income: $1,100 match (full federal CTC phase-in to $2,200 max)

All 9 CTC match tests and 8 flat amount tests pass.

@DTrim99
Copy link
Collaborator Author

DTrim99 commented Feb 20, 2026

Fix: PA CTC Match Now Uses Actual Federal CTC Received

This commit fixes an important issue with the PA CTC match formula.

Problem

The original implementation used ctc_value which represents the theoretical federal CTC after phase-in, but doesn't account for the refundable vs nonrefundable split:

  • Refundable portion (ACTC): Max $1,700/child - can be received as a refund
  • Nonrefundable portion: $500/child - only offsets tax liability

For families with income below the standard deduction (~$24k), they have $0 tax liability and can only receive the refundable $1,700, not the full $2,200.

Example

At $20,000 income with 1 young child:

  • Old calculation: ctc_value = $2,200 → PA match = $1,100
  • New calculation: actual_ctc = $1,700 (refundable only) → PA match = $850

Changes

  1. Formula fix: Now uses refundable_ctc + min(non_refundable_ctc, tax_liability) to calculate actual federal CTC benefit received
  2. SSN requirement: Added check for meets_ctc_child_identification_requirements to exclude children without valid SSN
  3. New tests: Added tests at $15k income and for children without SSN

@DTrim99
Copy link
Collaborator Author

DTrim99 commented Feb 23, 2026

Fixes Applied

Review Comment Addressed

  • ✅ Added pa_income_tax and household_net_income as outputs to all 8 test cases in pa_ctc_flat_amount.yaml

This verifies that the PA CTC flat amount reform correctly flows through the computation tree:

  • pa_ctc_flat_amountpa_refundable_tax_creditspa_income_taxhousehold_net_income

Verification

  • ✅ All 8 tests pass locally
  • ✅ Code formatted

🤖 Generated with Claude Code

@DTrim99
Copy link
Collaborator Author

DTrim99 commented Feb 23, 2026

Additional Fixes Applied

PA CTC Match Tests Updated

  • ✅ Added pa_income_tax and household_net_income as outputs to all 11 test cases in pa_ctc_match.yaml

This verifies that the PA CTC match reform correctly flows through the computation tree:

  • pa_ctc_matchpa_refundable_tax_creditspa_income_taxhousehold_net_income

Verification

  • ✅ All 11 PA CTC match tests pass locally
  • ✅ All 8 PA CTC flat amount tests pass locally

🤖 Generated with Claude Code

DTrim99 and others added 5 commits February 23, 2026 11:50
Add two Pennsylvania Child Tax Credit reform proposals:

1. Flat Amount CTC (pa_ctc_flat_amount):
   - $1,000 per child under age 6
   - 2% phaseout rate above $125k threshold (all filing statuses)
   - Effective 2026

2. Federal CTC Match (pa_ctc_match):
   - 50% match of federal CTC for children under 6
   - No income phaseout
   - Effective 2026

Includes:
- Parameter files in gov/contrib/states/pa/ctc/
- Reform code in reforms/states/pa/ctc/
- __init__.py files for proper imports
- Updates to reforms.py
- 14 YAML tests with full coverage

Closes PolicyEngine#7436

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Updates the PA CTC match formula to use ctc_value instead of
ctc_child_individual_maximum. This ensures low-income families
only receive the match on their actual federal CTC amount after
phase-in, not the maximum amount they would eventually receive.

Adds low income test cases:
- $2,000 income: $0 match (below $2,500 phase-in threshold)
- $10,000 income: $562.50 match (partial phase-in)
- $20,000 income: $1,100 match (full phase-in)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Changed formula to use refundable_ctc + min(non_refundable_ctc, tax_liability)
  instead of ctc_value, which overstated the federal CTC for low/moderate income
  families who cannot use the nonrefundable portion due to $0 tax liability
- Added SSN requirement check (meets_ctc_child_identification_requirements)
  to exclude children without valid SSN from the match
- Updated test at $20k income: expected PA match is $850 (not $1,100)
  since only $1,700 refundable CTC is received, not $2,200
- Added test at $15k income verifying refundable CTC cap behavior
- Added test for child without SSN verifying $0 PA match

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Addresses review comment to verify that the PA CTC reform flows
through the computation tree to pa_income_tax and household_net_income.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Addresses review comment to verify that the PA CTC match reform flows
through the computation tree to pa_income_tax and household_net_income.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@DTrim99 DTrim99 force-pushed the implement-pa-ctc-reform branch from 2b2f436 to 5f27145 Compare February 23, 2026 16:55
@DTrim99
Copy link
Collaborator Author

DTrim99 commented Feb 23, 2026

Fixes Applied

🔴 Critical Issues Fixed

  • Rebased onto upstream/main: Incorporated fix from PR Fix CI Fail #7459 to resolve CI failures

Verification

  • ✅ All 19 PA CTC tests pass locally (8 flat_amount + 11 match tests)
  • ✅ Code rebased and pushed

CI should now pass with the upstream fix included.

🤖 Generated with Claude Code

PavelMakarchuk and others added 9 commits February 23, 2026 15:05
Add reference metadata to all 8 parameter files pointing to issue PolicyEngine#7436.
Fix parameter descriptions and labels to spell out "Child Tax Credit".
Add reference attribute to both reform variable classes.
Rename test cases to "Case N, description." format and person names
from child1/child2/child3 to person2/person3/person4.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Resolve merge conflicts by keeping both PA CTC reforms and CT tax rebate 2026.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Remove pa_income_tax and household_net_income assertions that break
when unrelated parameters change. Add non-PA resident test cases to
verify defined_for=StateCode.PA works correctly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Comments now clarify the match is based on actual federal CTC received
(after phase-in and refundability limits), not the per-child maximum.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The baseline --exclude states tests were running ~565 YAML files in a
single subprocess, causing OOM/timeout on CI runners. Updated
test_batched.py to actually respect the --batches parameter for this
code path, and set --batches 2 in the Makefile.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Accept upstream's memory-aware batching system for baseline tests.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add age boundary tests (age 5, last eligible age)
- Add income threshold boundary tests ($124,999, $125,001)
- Add SEPARATE and SURVIVING_SPOUSE filing status tests
- Add federal CTC phaseout range tests ($205k single, $405k joint)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@DTrim99
Copy link
Collaborator Author

DTrim99 commented Feb 25, 2026

PR Review Summary

Overall Assessment: APPROVED

This is a well-implemented contributed reform with no critical issues. All CI checks pass.

Added Edge Case Tests

Added 7 new tests to improve boundary condition coverage:

pa_ctc_flat_amount.yaml:

  • Age 5 (last eligible age)
  • Income at $124,999 (just below threshold)
  • Income at $125,001 (just above threshold)
  • SEPARATE filing status
  • SURVIVING_SPOUSE filing status

pa_ctc_match.yaml:

  • Age 5 (last eligible age)
  • Single filer in federal CTC phaseout range ($205k)
  • Joint filer in federal CTC phaseout range ($405k)

All 29 tests pass.

Validation Summary

Check Result
Regulatory Accuracy N/A - Contributed reform
Reference Quality ✅ All parameters reference issue #7436
Code Patterns ✅ No hard-coded values, correct vectorization
Test Coverage ✅ Comprehensive (29 tests)
CI Status ✅ All passing

DTrim99 and others added 3 commits February 25, 2026 17:21
Migrates from old changelog_entry.yaml format to towncrier fragment
after merging main.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@PavelMakarchuk PavelMakarchuk merged commit 4091b47 into PolicyEngine:main Feb 25, 2026
7 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 CTC Reform (Contributed)

2 participants