Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions changelog.d/cdcc-coupling-accuracy.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
- Honored the IRC § 21(e)(4) separated-taxpayer exception in the South Carolina child and dependent care credit.
- Stopped the Idaho and Georgia contributed child tax credit reforms from applying in years before their in_effect activation date.
- Computed the Kentucky, Maine, and Vermont child and dependent care credits from the pre-OBBBA federal IRC § 21 credit for 2026, matching each state's static conformity to the Internal Revenue Code as of December 31, 2024.
- Reduced the California, Idaho, and Virginia child and dependent care benefit bases by employer-provided dependent care benefits excluded under IRC § 129, matching each state's form treatment and the federal IRC § 21(c) reduction.
7 changes: 6 additions & 1 deletion policyengine_us/reforms/states/ga/ctc/ga_ctc_reform.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,12 @@ def formula(tax_unit, period, parameters):
ga_child_age_eligible = age < baseline.age_threshold
eligible_children = tax_unit.sum(ctc_eligible_child & ga_child_age_eligible)
refund_limit = p.refundable.amount * eligible_children
return min_(unused_credit, refund_limit)
refundable_credit = min_(unused_credit, refund_limit)
# Only pay the refund in periods where the reform is in effect. The
# reform is installed for the whole simulation whenever it activates
# in any of the next five years (see create_ga_ctc_reform), so this
# per-period gate prevents a refund leaking into pre-activation years.
return where(p.refundable.in_effect, refundable_credit, 0)

class ga_refundable_credits(Variable):
value_type = float
Expand Down
48 changes: 41 additions & 7 deletions policyengine_us/reforms/states/id/ctc/id_ctc_reform.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,24 @@
)


def _first_true_instant(nodes, default):
"""Earliest instant at which any of the boolean parameters is true.

Scans each parameter's ``values_list`` (which reflects user-supplied dated
overrides) for the earliest instant whose value is truthy, and returns the
minimum such instant across all nodes. Falls back to ``default`` when none
of the parameters is ever true.
"""
candidates = []
for node in nodes:
for value_at_instant in node.values_list:
if value_at_instant.value:
candidates.append(instant(value_at_instant.instant_str))
if not candidates:
return default
return min(candidates)


def create_id_ctc() -> Reform:
class id_refundable_ctc(Variable):
value_type = float
Expand Down Expand Up @@ -40,22 +58,38 @@ def formula(tax_unit, period, parameters):
return where(p.refundable.in_effect, refundable_credit, 0)

def modify_parameters(parameters):
# Revive id_ctc in the ordered nonrefundable list (it was dropped as of
# 2026), so the baseline credit applies against liability again.
# The baseline id_ctc drops out of the ordered nonrefundable list as of
# 2026-01-01. Revive it only from the instant the reform actually turns
# on, so a delayed activation does not leak the credit into
# pre-activation years. The activation instant is the earliest date at
# which either in_effect toggle is true; default to 2026-01-01 (the
# baseline drop date) when neither carries a dated override.
p_id = parameters.gov.contrib.states.id.ctc
baseline_drop = instant("2026-01-01")
activation = _first_true_instant(
[p_id.in_effect, p_id.refundable.in_effect],
default=baseline_drop,
)
# Never revive before the baseline drop date: id_ctc is already in the
# list through 2025, so revival only matters from 2026 onward.
revival_start = max(activation, baseline_drop)
non_refundable = parameters.gov.states.id.tax.income.credits.non_refundable
current_non_refundable = non_refundable(instant("2026-01-01"))
current_non_refundable = non_refundable(revival_start)
if "id_ctc" not in current_non_refundable:
non_refundable.update(
start=instant("2026-01-01"),
start=revival_start,
stop=instant("2100-12-31"),
value=list(current_non_refundable) + ["id_ctc"],
)
# Register the refundable top-up in the refundable list.
# Register the refundable top-up in the refundable list. The
# id_refundable_ctc variable self-gates on refundable.in_effect, so it
# pays nothing before activation; registering it from the same revival
# instant keeps the list free of a dead entry in pre-activation years.
refundable = parameters.gov.states.id.tax.income.credits.refundable
current_refundable = refundable(instant("2026-01-01"))
current_refundable = refundable(revival_start)
if "id_refundable_ctc" not in current_refundable:
refundable.update(
start=instant("2026-01-01"),
start=revival_start,
stop=instant("2100-12-31"),
value=list(current_refundable) + ["id_refundable_ctc"],
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# The pre_obbba_cdcc family recomputes the federal section 21 credit on the
# rate schedule as it stood before the One Big Beautiful Bill Act (OBBBA). For
# 2025 it must equal the live cdcc (identical schedule); for 2026 it must hold
# the pre-OBBBA rate (max 35%, min 20%, no amended second phase-out) while the
# live cdcc reflects the OBBBA increase (max 50%, min 35%). Read by states whose
# income tax statically conforms to a pre-2026 IRC (KY, ME, VT).

# Low-income joint family, two children, $6,000 childcare, AGI below the first
# phase-out start so the applicable rate is at its maximum.
- name: 2025 pre-OBBBA CDCC equals the live CDCC (identical schedule)
period: 2025
absolute_error_margin: 0.01
input:
people:
head:
age: 35
employment_income: 25_000
spouse:
age: 35
employment_income: 25_000
child1:
age: 5
child2:
age: 7
tax_units:
tax_unit:
members: [head, spouse, child1, child2]
filing_status: JOINT
tax_unit_childcare_expenses: 6_000
premium_tax_credit: 0
output:
# $6,000 x 20% applicable rate at this AGI = $1,200 (same as live cdcc).
cdcc: 1_200
pre_obbba_cdcc_potential: 1_200
pre_obbba_cdcc: 1_200
pre_obbba_capped_cdcc: 1_200

- name: 2026 pre-OBBBA CDCC holds the pre-OBBBA rate while live CDCC rises
period: 2026
absolute_error_margin: 0.01
input:
people:
head:
age: 35
employment_income: 25_000
spouse:
age: 35
employment_income: 25_000
child1:
age: 5
child2:
age: 7
tax_units:
tax_unit:
members: [head, spouse, child1, child2]
filing_status: JOINT
tax_unit_childcare_expenses: 6_000
premium_tax_credit: 0
output:
# Live 2026 credit uses the OBBBA rate (35% here) = $2,100 potential,
# $1,780 after the section 26 cap for this family.
cdcc_potential: 2_100
cdcc: 1_780
# Pre-OBBBA credit holds the 20% pre-OBBBA rate = $1,200.
pre_obbba_cdcc_potential: 1_200
pre_obbba_cdcc: 1_200
pre_obbba_capped_cdcc: 1_200
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,18 @@
# One qualifying individual at the pre-ARPA $3,000 cap:
# min(10_000 adult care, 3_000, 50_000) = 3_000.
ca_cdcc_relevant_expenses: 3_000

# FTB 3506 Part IV reduces the $3,000 / $6,000 dollar limit by the IRC § 129
# employer-provided dependent care benefits excluded from income, matching the
# federal § 21(c) reduction.
- name: Section 129 employer benefits reduce the California base
period: 2024
input:
state_code: CA
tax_unit_childcare_expenses: 10_000
count_cdcc_eligible: 2
min_head_spouse_earned: 50_000
dependent_care_assistance_exclusion: 5_000
output:
# min(10_000 expenses, $6,000 two-child cap - $5,000 exclusion, 50_000) = 1_000.
ca_cdcc_relevant_expenses: 1_000
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,18 @@
state_code: ID
output:
id_household_and_dependent_care_expense_deduction: 3_000

# Idaho Form 39R Line 6 worksheet line 4 reduces the operative cap by the IRC
# § 129 employer-provided dependent care benefits ("excluded benefits from Part
# III of Form 2441"). Here the reduced $12,000 cap binds below the expenses.
- name: Section 129 employer benefits reduce the Idaho deduction cap
period: 2023
input:
tax_unit_childcare_expenses: 10_000
id_cdcc_limit: 6_000
min_head_spouse_earned: 60_000
dependent_care_assistance_exclusion: 5_000
state_code: ID
output:
# min(10_000 expenses, max(6_000, 12_000) - 5_000 = 7_000, 60_000) = 7_000.
id_household_and_dependent_care_expense_deduction: 7_000
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,39 @@
ky_tuition_tax_credit: 0
output:
ky_cdcc: 0

# KRS 141.010(21) freezes Kentucky's IRC at December 31, 2024, so from 2026 the
# credit uses the pre-OBBBA federal section 21 credit (20% of $1,200 = $240),
# not the OBBBA-inflated live credit (which would give 20% of $1,780 = $356).
- name: 2026 uses the pre-OBBBA federal credit under static conformity
period: 2026
absolute_error_margin: 0.01
input:
people:
head:
age: 35
employment_income: 25_000
spouse:
age: 35
employment_income: 25_000
child1:
age: 5
child2:
age: 7
tax_units:
tax_unit:
members: [head, spouse, child1, child2]
filing_status: JOINT
tax_unit_childcare_expenses: 6_000
premium_tax_credit: 0
ky_income_tax_before_non_refundable_credits_unit: 1_000_000
ky_personal_tax_credits: 0
ky_family_size_tax_credit: 0
ky_tuition_tax_credit: 0
households:
household:
members: [head, spouse, child1, child2]
state_code: KY
output:
# 20% of the pre-OBBBA $1,200 federal credit.
ky_cdcc: 240
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,21 @@
me_child_care_credit: 750
me_refundable_child_care_credit: 500
me_non_refundable_child_care_credit: 250

# 36 M.R.S. § 111(1-A) freezes Maine's "Code" at December 31, 2024, so from 2026
# the credit is 25% of the pre-OBBBA federal credit (pre_obbba_cdcc), not the
# OBBBA-inflated live cdcc. Inject both to confirm the pin reads the frozen
# variable.
- name: 2026 uses the pre-OBBBA federal credit under static conformity
period: 2026
absolute_error_margin: 0
input:
state_code: ME
filing_status: SINGLE
cdcc: 4_000
pre_obbba_cdcc: 1_000
me_step_4_share_of_child_care_expenses: 0
me_income_tax_before_credits: 1_000_000
output:
# 25% of the frozen $1,000, ignoring the $4,000 live credit.
me_child_care_credit: 250
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,60 @@
sc_income_tax_before_non_refundable_credits: 1000000
output:
sc_cdcc: 210

# S.C. Code § 12-6-3380 computes the credit "as provided in Internal Revenue
# Code Section 21," importing § 21(e)(2)'s joint-return rule together with the
# § 21(e)(4) separated-taxpayer exception. An ordinary married-separate filer
# remains ineligible; a separated filer who lives apart while maintaining a home
# for a qualifying individual qualifies, matching the federal treatment.
- name: Ordinary married-filing-separately filer gets no SC CDCC
period: 2024
input:
people:
head:
age: 35
is_tax_unit_head: true
employment_income: 40_000
child:
age: 5
is_tax_unit_head: false
is_tax_unit_spouse: false
tax_units:
tax_unit:
members: [head, child]
filing_status: SEPARATE
cdcc_relevant_expenses: 3_000
sc_income_tax_before_non_refundable_credits: 1_000_000
households:
household:
members: [head, child]
state_code: SC
output:
sc_cdcc: 0

- name: Separated MFS filer maintaining a home for a qualifying child gets the SC CDCC
period: 2024
input:
people:
head:
age: 35
is_tax_unit_head: true
is_separated: true
employment_income: 40_000
child:
age: 5
is_tax_unit_head: false
is_tax_unit_spouse: false
tax_units:
tax_unit:
members: [head, child]
filing_status: SEPARATE
cdcc_relevant_expenses: 3_000
sc_income_tax_before_non_refundable_credits: 1_000_000
households:
household:
members: [head, child]
state_code: SC
output:
# 7% of min($3,000 spent, $3,000 one-person 2024 cap) = $210.
sc_cdcc: 210
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,26 @@
state_code: VA
output:
va_child_dependent_care_deduction_cdcc_limit: 3_000

# Va. Code § 58.1-322.03(3) deducts the amount on which the federal credit is
# based (Form 2441 line 31), which IRC § 21(c) reduces by § 129 employer
# benefits. The Virginia limit inherits that reduction.
- name: Section 129 employer benefits reduce the Virginia limit
period: 2024
input:
capped_count_cdcc_eligible: 2
dependent_care_assistance_exclusion: 5_000
state_code: VA
output:
# $6,000 two-child limit less the $5,000 exclusion.
va_child_dependent_care_deduction_cdcc_limit: 1_000

- name: Section 129 benefits exceeding the limit floor it at zero
period: 2024
input:
capped_count_cdcc_eligible: 1
dependent_care_assistance_exclusion: 5_000
state_code: VA
output:
# max($3,000 - $5,000, 0) = $0.
va_child_dependent_care_deduction_cdcc_limit: 0
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,17 @@
state_code: VT
output:
vt_cdcc: 720

# 32 V.S.A. § 5824 freezes Vermont's IRC at December 31, 2024, so from 2026 the
# credit is 72% of the pre-OBBBA federal credit (pre_obbba_capped_cdcc), not the
# OBBBA-inflated live capped_cdcc. Inject both to confirm the pin reads the
# frozen variable.
- name: Vermont CDCC 2026 uses the pre-OBBBA federal credit under static conformity
period: 2026
input:
capped_cdcc: 2_000
pre_obbba_capped_cdcc: 1_000
state_code: VT
output:
# 72% of the frozen $1,000, ignoring the $2,000 live credit.
vt_cdcc: 720
Loading
Loading