Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 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
b8154a3
Apply New York's rules for a filer who can be claimed as a dependent
MaxGhenis Oct 9, 2026
4597c55
Address the federal claimable-filer review
MaxGhenis Oct 10, 2026
f56a5b2
Address the New York claimable-filer review
MaxGhenis Oct 10, 2026
290d52b
Merge commit '4597c55a86' into claimable-filer-ny
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
c1dd7bf
Merge commit '3f8870261c' into claimable-filer-ny
MaxGhenis Oct 10, 2026
2051c66
Read the split dependency inputs from #10024 in New York
MaxGhenis Oct 10, 2026
b2771d2
Follow the corrected exemption count in three Hawaii credits
MaxGhenis Oct 10, 2026
e02b7c3
Merge commit 'b2771d2f15' into claimable-filer-ny
MaxGhenis Oct 10, 2026
163fcd4
Address the second federal claimable-filer review
MaxGhenis Oct 10, 2026
b862685
Merge commit '163fcd4cfa98345d5ec0c358d2d35c8516789334' into claimabl…
MaxGhenis Oct 10, 2026
6076b2d
Keep a dependent's age out of New York's elderly property tax credit …
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
edd12b8
Merge commit '35a2cbcbb971f6b43d35db009d9bda41b76386a5' into claimabl…
MaxGhenis Oct 11, 2026
742fe06
Merge main into claimable-filer-ny after #10087
MaxGhenis Oct 16, 2026
38fb674
Merge updated main into claimable-filer-ny
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-ny.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Apply New York's rules for a filer who can be claimed as a dependent: no New York State or New York City household credit, school tax credit, real property tax credit, dependent exemptions (also under the dependent exemption and working families tax credit reforms), dependents' college tuition, under-4 New York City child care expenses, New York City income tax elimination credit or 2026 child and dependent care credit when the return's filers do not qualify (Tax Law 606, 616 and 1310), no own college tuition or 2023 inflation refund for a filer who is claimed, and the New York City school tax fixed amount at the individual rate when only one spouse qualifies; the 2026 child and dependent care credit now bars a claimable spouse under either head/spouse label.
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,13 @@ def formula(tax_unit, period, parameters):
eligible = is_child_dependent & (age < p.age_limit.threshold)
else:
eligible = is_child_dependent
count = tax_unit.sum(eligible)
# As in the baseline, a return on which a filer (or, if joint,
# either spouse) can be claimed as a dependent has no dependents
# (Tax Law 616(a), IRC 152(b)(1)).
dependent_filer = tax_unit(
"head_or_spouse_is_dependent_elsewhere_without_filing_exception", period
)
count = where(dependent_filer, 0, tax_unit.sum(eligible))
return count * p.amount

class reform(Reform):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,17 @@ class ny_exemptions(Variable):
defined_for = StateCode.NY

def formula(tax_unit, period, parameters):
count_dependents = add(tax_unit, period, ["ny_exemptions_dependent"])
# As in the baseline, a return on which a filer (or, if joint,
# either spouse) can be claimed as a dependent has no dependents
# (Tax Law 616(a), IRC 152(b)(1)).
dependent_filer = tax_unit(
"head_or_spouse_is_dependent_elsewhere_without_filing_exception", period
)
count_dependents = where(
dependent_filer,
0,
add(tax_unit, period, ["ny_exemptions_dependent"]),
)
dependent_exemption = parameters(
period
).gov.states.ny.tax.income.exemptions.dependent
Expand Down
106 changes: 106 additions & 0 deletions policyengine_us/tests/core/test_claimable_filer_ny_invariants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
"""New York rules for a filer who can be claimed as a dependent.

The household credit, real property tax credit, dependent exemptions, college
tuition, 2023 inflation refund and 2026 child and dependent care credit apply
Tax Law 606 and 616's dependent tests.

For couples with either, both or neither spouse claimed:

1. Swap invariance: each output is the same under either head/spouse
labelling (Hypothesis batches, the seeded population and the crafted
tuition cases).
2. Monotonicity: marking another filer as claimed never raises an output
(seeded population and crafted cases only).

The crafted cases give both spouses and a dependent student tuition, which the
generated population never has. The New York City credits need a New York City
household and, like the contributed reforms, are covered by YAML cases only.
"""

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,
_crafted_cases,
_seeded_couples,
adults,
dependents,
)

STATES = ["NY"]
YEARS = [2023, 2025, 2026]
OUTPUTS = [
"ny_household_credit_potential",
"ny_real_property_tax_credit",
"ny_exemptions",
"ny_allowable_college_tuition_expenses",
"ny_inflation_refund_credit",
"ny_cdcc",
]


def _tuition_cases():
# Both spouses and a dependent student with tuition, with and without a
# young child and childcare expenses.
first = {
"age": 45,
"employment_income": 20_000.0,
"qualified_tuition_expenses": 6_000.0,
}
second = {
"age": 44,
"employment_income": 12_000.0,
"qualified_tuition_expenses": 3_000.0,
}
student = {
"age": 19,
"is_full_time_student": True,
"qualified_tuition_expenses": 8_000.0,
}
child = {"age": 3, "pre_subsidy_childcare_expenses": 4_000.0}
return [
{
"state": "NY",
"adults": [first, second],
"dependents": others,
"claimed": claimed,
}
for others in ([], [student], [student, child])
for claimed in [(True, False), (False, True), (True, True)]
]


@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)),
}


@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_ny_claimable_filer_rules_are_label_free(year, units):
check_swap(units, year, OUTPUTS)


@pytest.mark.parametrize("year", YEARS)
def test_ny_claimable_filer_rules_seeded_population(year):
units = (
_seeded_couples(STATES, per_state=3) + _crafted_cases(STATES) + _tuition_cases()
)
check_swap(units, year, OUTPUTS)
check_monotone(units, year, OUTPUTS)
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,85 @@
in_nyc: true
output:
nyc_cdcc_age_restricted_expenses: 0


- name: 2025 joint return with one claimable spouse has no NYC child care dependent (the claimable spouse is the head)
period: 2025
input:
people:
person_a:
age: 22
claimed_as_dependent_on_another_return: true
is_tax_unit_head: true
is_tax_unit_spouse: false
person_b:
age: 22
is_tax_unit_head: false
is_tax_unit_spouse: true
child:
age: 3
pre_subsidy_childcare_expenses: 1000
tax_units:
tax_unit:
members: [person_a, person_b, child]
filing_status: JOINT
households:
household:
members: [person_a, person_b, child]
state_code: NY
in_nyc: true
output:
# NYC Admin Code 11-1706(e)(1): children "who are dependents of the
# taxpayer"; IRC 152(b)(1).
nyc_cdcc_age_restricted_expenses: 0

- name: 2025 joint return with one claimable spouse has no NYC child care dependent (the claimable spouse is the spouse)
period: 2025
input:
people:
person_b:
age: 22
is_tax_unit_head: true
is_tax_unit_spouse: false
person_a:
age: 22
claimed_as_dependent_on_another_return: true
is_tax_unit_head: false
is_tax_unit_spouse: true
child:
age: 3
pre_subsidy_childcare_expenses: 1000
tax_units:
tax_unit:
members: [person_b, person_a, child]
filing_status: JOINT
households:
household:
members: [person_b, person_a, child]
state_code: NY
in_nyc: true
output:
nyc_cdcc_age_restricted_expenses: 0

- name: 2025 joint return with neither spouse claimable counts the child under 4
period: 2025
input:
people:
person_a:
age: 22
person_b:
age: 22
child:
age: 3
pre_subsidy_childcare_expenses: 1000
tax_units:
tax_unit:
members: [person_a, person_b, child]
filing_status: JOINT
households:
household:
members: [person_a, person_b, child]
state_code: NY
in_nyc: true
output:
nyc_cdcc_age_restricted_expenses: 1_000
Original file line number Diff line number Diff line change
Expand Up @@ -233,3 +233,119 @@
tax_unit_size: 4
output:
nyc_household_credit: 0


- name: 2025 single filer who can be claimed as a dependent gets no NYC household credit
period: 2025
input:
people:
filer:
age: 22
employment_income: 10000
claimed_as_dependent_on_another_return: true
tax_units:
tax_unit:
members: [filer]
households:
household:
members: [filer]
state_code: NY
in_nyc: true
output:
# Tax Law 1310(d); IT-201 line 48.
nyc_household_credit: 0

- name: 2025 single filer who cannot be claimed gets the NYC household credit
period: 2025
input:
people:
filer:
age: 22
employment_income: 10000
tax_units:
tax_unit:
members: [filer]
households:
household:
members: [filer]
state_code: NY
in_nyc: true
output:
nyc_household_credit: 15

- name: 2025 joint return with one claimable spouse gets no NYC household credit (the claimable spouse is the head)
period: 2025
input:
people:
person_a:
age: 22
employment_income: 5000
claimed_as_dependent_on_another_return: true
is_tax_unit_head: true
is_tax_unit_spouse: false
person_b:
age: 22
employment_income: 5000
is_tax_unit_head: false
is_tax_unit_spouse: true
tax_units:
tax_unit:
members: [person_a, person_b]
filing_status: JOINT
households:
household:
members: [person_a, person_b]
state_code: NY
in_nyc: true
output:
nyc_household_credit: 0

- name: 2025 joint return with one claimable spouse gets no NYC household credit (the claimable spouse is the spouse)
period: 2025
input:
people:
person_b:
age: 22
employment_income: 5000
is_tax_unit_head: true
is_tax_unit_spouse: false
person_a:
age: 22
employment_income: 5000
claimed_as_dependent_on_another_return: true
is_tax_unit_head: false
is_tax_unit_spouse: true
tax_units:
tax_unit:
members: [person_b, person_a]
filing_status: JOINT
households:
household:
members: [person_b, person_a]
state_code: NY
in_nyc: true
output:
nyc_household_credit: 0

- name: 2025 joint return with neither spouse claimable gets the NYC household credit
period: 2025
input:
people:
person_a:
age: 22
employment_income: 5000
person_b:
age: 22
employment_income: 5000
tax_units:
tax_unit:
members: [person_a, person_b]
filing_status: JOINT
households:
household:
members: [person_a, person_b]
state_code: NY
in_nyc: true
output:
# $30 x 2.
nyc_household_credit: 60
Loading
Loading