Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
1f0cd1b
Make head_is_dependent_elsewhere consumers independent of the head label
MaxGhenis Oct 8, 2026
3ecc675
Keep tax units without a filer eligible where only claimed filers are…
MaxGhenis Oct 9, 2026
8da8312
Address review: Hawaii worksheet earnings, NM same-filer age, childle…
MaxGhenis Oct 9, 2026
e838623
Allow a cent of rounding in the Hawaii self-employed joint pair
MaxGhenis Oct 9, 2026
41fb4a5
Address review round 2: worksheet earnings, minors' own status, input…
MaxGhenis Oct 9, 2026
527d47f
Merge remote-tracking branch 'upstream/main' into head-dependent-else…
MaxGhenis Oct 9, 2026
436805e
Merge the Hawaii deductions references after syncing main
MaxGhenis Oct 9, 2026
23c6229
Apply the federal rules for a filer who can be claimed as a dependent
MaxGhenis Oct 9, 2026
c1ee379
Apply Colorado, Connecticut, Illinois and Indiana rules for a filer w…
MaxGhenis Oct 10, 2026
342f417
Let either unclaimed Illinois spouse keep the 2022 rebate; add the pr…
MaxGhenis Oct 10, 2026
c8e5e48
Project the claimable-filer flag to members before combining with ages
MaxGhenis Oct 10, 2026
64d2c47
Point the Illinois dependent exemption at the live 35 ILCS 5/204 text
MaxGhenis Oct 10, 2026
2949a41
Address review: carry the bar into the IL and IN exemption reforms; I…
MaxGhenis Oct 10, 2026
4597c55
Address the federal claimable-filer review
MaxGhenis Oct 10, 2026
e4b8f36
Separate dependency facts and fix Hawaii qualified-person counts
MaxGhenis Oct 10, 2026
c7f969f
Clarify claimability outside the current tax unit
MaxGhenis Oct 10, 2026
4c8ed81
Merge commit 'c7f969f872' into claimable-filer-federal
MaxGhenis Oct 10, 2026
3f88702
Read the split dependency inputs from #10024
MaxGhenis Oct 10, 2026
b2771d2
Follow the corrected exemption count in three Hawaii credits
MaxGhenis Oct 10, 2026
163fcd4
Address the second federal claimable-filer review
MaxGhenis Oct 10, 2026
3d0864f
Address the third federal claimable-filer review
MaxGhenis Oct 10, 2026
35a2cbc
Give the spouse without an SSN a card type in the recovery rebate test
MaxGhenis Oct 10, 2026
8ff78ec
Merge remote-tracking branch 'upstream/claimable-filer-federal' into …
MaxGhenis Oct 11, 2026
3ebbde6
Read the split claimable / claimed inputs from the settled federal br…
MaxGhenis Oct 11, 2026
29a702c
Merge main into claimable-filer-co-ct-il-in after #10087
MaxGhenis Oct 16, 2026
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
1 change: 1 addition & 0 deletions changelog.d/claimable-filer-co-ct-il-in.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Apply Colorado, Connecticut, Illinois and Indiana rules for a filer who can be claimed as a dependent: no dependent-based credits, exemptions or deductions on such a return, and no childless EITC through the state ITIN and age extensions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,13 @@ class il_dependent_exemption(Variable):
def formula(tax_unit, period, parameters):
p = parameters(period).gov.contrib.states.il.dependent_exemption
person = tax_unit.members
is_dependent = person("is_tax_unit_dependent", period)
# A return on which the filer (or, if joint, either spouse) can be
# claimed as a dependent has no dependents (IRC 152(b)(1)), as in
# the baseline formula.
filer_is_dependent = person.tax_unit(
"head_or_spouse_is_dependent_elsewhere_without_filing_exception", period
)
is_dependent = person("is_tax_unit_dependent", period) & ~filer_is_dependent
# Age gate: when in effect, restrict the exemption to dependents
# under the chosen age; otherwise every dependent qualifies,
# matching the baseline tax_unit_dependents count.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,13 @@ def formula(tax_unit, period, parameters):

person = tax_unit.members
age = person("age", period)
is_dependent = person("is_tax_unit_dependent", period)
# A return on which the filer (or, if joint, either spouse) can be
# claimed as a dependent has no dependents (IRC 152(b)(1)), as in
# the baseline formula.
filer_is_dependent = person.tax_unit(
"head_or_spouse_is_dependent_elsewhere_without_filing_exception", period
)
is_dependent = person("is_tax_unit_dependent", period) & ~filer_is_dependent

# Apply age limit if in effect
if p.age_limit.in_effect:
Expand Down Expand Up @@ -49,7 +55,12 @@ class in_older_dependents_count(Variable):

def formula(tax_unit, period, parameters):
person = tax_unit.members
is_dependent = person("is_tax_unit_dependent", period)
# Dependents barred by a claimable filer are not moved into the
# personal portion either.
filer_is_dependent = person.tax_unit(
"head_or_spouse_is_dependent_elsewhere_without_filing_exception", period
)
is_dependent = person("is_tax_unit_dependent", period) & ~filer_is_dependent
total_dependents = tax_unit.sum(is_dependent)
eligible_dependent_exemptions = tax_unit(
"in_eligible_dependents_count", period
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
"""Colorado, Connecticut, Illinois and Indiana rules for a filer who can be
claimed as a dependent.

A return on which the filer, or on a joint return either spouse, can be claimed
as a dependent has no dependents (IRC 152(b)(1)), so it gets no state
dependent exemption or child-based deduction and no Colorado child credit, and
a childless filer who can be claimed gets no state EITC through the ITIN or age
extensions (IRC 32(c)(1)(A)(ii)(III)). Indiana keeps each filer's own $1,000
exemption; Illinois' child tax credit follows the IRC 152 qualifying child.

For couples drawn by Hypothesis and a seeded population in these states, with
either, both or neither spouse claimed:

1. Swap invariance: each output is the same under either head/spouse
labelling.
2. Monotonicity: marking another filer as claimed never raises the outputs in
MONOTONE (amounts not capped by a tax liability that the claim can raise).
3. Identities: a return with a claimable filer has no Illinois dependent
exemption, Colorado child tax credit or Indiana additional exemption, and
its Indiana base exemptions are $1,000 per filer.

Hypothesis batches check 1 and 3; the seeded population checks 1, 2 and 3.
"""

import numpy as np
import pytest
from hypothesis import HealthCheck, given, settings
from hypothesis import strategies as st

from policyengine_us.tests.core.test_claimable_filer_federal_invariants import (
check_monotone,
check_swap,
)
from policyengine_us.tests.core.test_dependent_elsewhere_head_spouse_swap_invariance import (
CLAIM_PATTERNS,
_calc,
_crafted_cases,
_seeded_couples,
adults,
dependents,
)

STATES = ["CO", "CT", "IL", "IN"]
YEARS = [2021, 2023, 2025, 2026]
MONOTONE = [
"co_eitc",
"co_ctc",
"co_low_income_cdcc",
"ct_property_tax_credit_eligible",
"ct_child_tax_rebate",
"il_dependent_exemption",
"il_eitc",
"il_ctc",
"il_income_tax_rebate",
"il_income_tax_rebate_eligible",
"in_base_exemptions",
"in_additional_exemptions",
"in_adoption_exemption",
]
OUTPUTS = MONOTONE + ["co_refundable_credits"]


@st.composite
def couples(draw):
return {
"state": draw(st.sampled_from(STATES)),
"adults": [draw(adults()), draw(adults())],
"dependents": draw(st.lists(dependents(), max_size=2)),
"claimed": draw(st.sampled_from(CLAIM_PATTERNS)),
}


def _identities(units):
states = np.array([unit["state"] for unit in units])

def check(sim, year):
claimed_filer = _calc(sim, "head_or_spouse_is_dependent_elsewhere", year) > 0
# Each unit is simulated as consecutive copies (labellings or claim
# patterns), in the order of the units.
state = np.repeat(states, len(claimed_filer) // len(units))
for name in (
"il_dependent_exemption",
"co_ctc",
"in_additional_exemptions",
):
assert not _calc(sim, name, year)[claimed_filer].any(), (
f"{name} in {year} is positive on a return with a claimable filer"
)
filers = _calc(sim, "tax_unit_size", year) - _calc(
sim, "tax_unit_dependents", year
)
base = _calc(sim, "in_base_exemptions", year)
mask = claimed_filer & (state == "IN")
np.testing.assert_array_equal(base[mask], 1_000 * filers[mask])

return check


@settings(
max_examples=2,
deadline=None,
derandomize=True,
suppress_health_check=[HealthCheck.too_slow, HealthCheck.data_too_large],
)
@given(st.sampled_from(YEARS), st.lists(couples(), min_size=6, max_size=12))
def test_co_ct_il_in_claimable_filer_rules_are_label_free(year, units):
check_swap(units, year, OUTPUTS, _identities(units))


@pytest.mark.parametrize("year", YEARS)
def test_co_ct_il_in_claimable_filer_rules_seeded_population(year):
units = _seeded_couples(STATES, per_state=3) + _crafted_cases(STATES)
check_swap(units, year, OUTPUTS, _identities(units))
check_monotone(units, year, MONOTONE, _identities(units))
Original file line number Diff line number Diff line change
Expand Up @@ -173,3 +173,146 @@
state_code: CO
output:
co_cdcc: 0


- name: 2025 single filer who can be claimed as a dependent, no Colorado child care credit for a child under 13
period: 2025
input:
people:
filer:
age: 30
employment_income: 50_000
is_tax_unit_head: true
is_tax_unit_spouse: false
claimed_as_dependent_on_another_return: true
child:
age: 2
tax_units:
tax_unit:
members: [filer, child]
tax_unit_childcare_expenses: 1_000
households:
household:
members: [filer, child]
state_code: CO
output:
# Already zero through the federal child care credit, which no
# longer counts a child under 13 on such a return.
co_cdcc: 0

- name: 2025 joint return with one spouse who can be claimed as a dependent, no Colorado child care credit for a child under 13 (the claimable spouse is the head)
period: 2025
input:
people:
person_a:
age: 30
employment_income: 25_000
is_tax_unit_head: true
is_tax_unit_spouse: false
claimed_as_dependent_on_another_return: true
person_b:
age: 30
employment_income: 25_000
is_tax_unit_head: false
is_tax_unit_spouse: true
child:
age: 2
tax_units:
tax_unit:
members: [person_a, person_b, child]
filing_status: JOINT
tax_unit_childcare_expenses: 1_000
households:
household:
members: [person_a, person_b, child]
state_code: CO
output:
co_cdcc: 0

- name: 2025 joint return with one spouse who can be claimed as a dependent, no Colorado child care credit for a child under 13 (the claimable spouse is the spouse)
period: 2025
input:
people:
person_b:
age: 30
employment_income: 25_000
is_tax_unit_head: true
is_tax_unit_spouse: false
person_a:
age: 30
employment_income: 25_000
is_tax_unit_head: false
is_tax_unit_spouse: true
claimed_as_dependent_on_another_return: true
child:
age: 2
tax_units:
tax_unit:
members: [person_b, person_a, child]
filing_status: JOINT
tax_unit_childcare_expenses: 1_000
households:
household:
members: [person_b, person_a, child]
state_code: CO
output:
co_cdcc: 0

- name: 2025 joint return with both spouses claimable as dependents, no Colorado child care credit for a child under 13
period: 2025
input:
people:
person_a:
age: 30
employment_income: 25_000
is_tax_unit_head: true
is_tax_unit_spouse: false
claimed_as_dependent_on_another_return: true
person_b:
age: 30
employment_income: 25_000
is_tax_unit_head: false
is_tax_unit_spouse: true
claimed_as_dependent_on_another_return: true
child:
age: 2
tax_units:
tax_unit:
members: [person_a, person_b, child]
filing_status: JOINT
tax_unit_childcare_expenses: 1_000
households:
household:
members: [person_a, person_b, child]
state_code: CO
output:
co_cdcc: 0

- name: 2025 joint return with neither spouse claimable, no Colorado child care credit for a child under 13
period: 2025
input:
people:
person_a:
age: 30
employment_income: 25_000
is_tax_unit_head: true
is_tax_unit_spouse: false
person_b:
age: 30
employment_income: 25_000
is_tax_unit_head: false
is_tax_unit_spouse: true
child:
age: 2
tax_units:
tax_unit:
members: [person_a, person_b, child]
filing_status: JOINT
tax_unit_childcare_expenses: 1_000
households:
household:
members: [person_a, person_b, child]
state_code: CO
output:
# Federal 20% x 1,000 = 200; Colorado 50% match = 100.
co_cdcc: 100
Loading