Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 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
a484f7a
Apply Oregon, Maine and Hawaii rules for a filer who can be claimed a…
MaxGhenis Oct 9, 2026
4597c55
Address the federal claimable-filer review
MaxGhenis Oct 10, 2026
6cbe804
Address the Oregon, Maine and Hawaii claimable-filer review
MaxGhenis Oct 10, 2026
f6d174e
Merge commit '4597c55a86' into claimable-filer-or-me-hi
MaxGhenis Oct 10, 2026
b4f3dde
Depart from the head and spouse count only when a filer can be claimed
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
1ee427c
Merge commit '3f8870261c' into claimable-filer-or-me-hi
MaxGhenis Oct 10, 2026
dddfbcb
Read the split dependency inputs from #10024 in Oregon, Maine and Hawaii
MaxGhenis Oct 10, 2026
b2771d2
Follow the corrected exemption count in three Hawaii credits
MaxGhenis Oct 10, 2026
a25cbc9
Merge commit 'b2771d2f15' into claimable-filer-or-me-hi
MaxGhenis Oct 10, 2026
163fcd4
Address the second federal claimable-filer review
MaxGhenis Oct 10, 2026
e56bc8b
Merge commit '163fcd4cfa98345d5ec0c358d2d35c8516789334' into claimabl…
MaxGhenis Oct 10, 2026
cdd12e8
Address the second Oregon, Maine and Hawaii claimable-filer review
MaxGhenis Oct 10, 2026
3d0864f
Address the third federal claimable-filer review
MaxGhenis Oct 10, 2026
f4224c7
Merge commit '3d0864f778' into claimable-filer-or-me-hi
MaxGhenis Oct 10, 2026
a1d0de7
Test Oregon's expenses for an incapacitated teenager on a return with…
MaxGhenis Oct 10, 2026
35a2cbc
Give the spouse without an SSN a card type in the recovery rebate test
MaxGhenis Oct 10, 2026
f3ce000
Merge commit '35a2cbcbb9' into claimable-filer-or-me-hi
MaxGhenis Oct 10, 2026
f020367
Give Oregon's higher EITC rate only for a legal dependent under three
MaxGhenis Oct 10, 2026
8b06234
Merge main after federal claimable-filer squash merge (#10089)
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-or-me-hi.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Apply Oregon, Maine and Hawaii rules for a filer who can be claimed as a dependent: Maine's personal exemption counts only filers who may not be claimed (1040ME line 13), and Maine's dependent exemption credit, expanded childless EITC and 2021 relief rebate, Oregon's Kids Credit, disabled child exemption, higher EITC rate for a dependent under three and working family household and dependent care credit child (with its expenses and column), and Hawaii's age-65 exemption and child care credit qualifying individuals and expenses follow the dependent taxpayer rules; Oregon's working family credit now counts a disabled spouse under either head/spouse label.
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,9 @@ def formula(tax_unit, period, parameters):
# exactly as the baseline computes it).
person = tax_unit.members
head_or_spouse = person("is_tax_unit_head_or_spouse", period)
claimed = person("claimable_as_dependent_on_another_return", period)
aged = person("age", period) >= p.aged_threshold
aged_head_spouse_count = tax_unit.sum(aged & head_or_spouse)
aged_head_spouse_count = tax_unit.sum(aged & head_or_spouse & ~claimed)

personal_amount = (personal_count + aged_head_spouse_count) * p.base

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@ 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)).
is_dependent = person("is_tax_unit_dependent", period) & ~person.tax_unit(
"head_or_spouse_is_dependent_elsewhere_without_filing_exception", period
)

# Apply age limit if in effect
age_threshold = p.age_limit.threshold
Expand All @@ -39,7 +43,11 @@ class or_older_dependents_count(Variable):

def formula(tax_unit, period, parameters):
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)).
is_dependent = person("is_tax_unit_dependent", period) & ~person.tax_unit(
"head_or_spouse_is_dependent_elsewhere_without_filing_exception", period
)
total_dependents = tax_unit.sum(is_dependent)
eligible_dependents = tax_unit("or_eligible_dependents_count", period)
return max_(0, total_dependents - eligible_dependents)
Expand Down Expand Up @@ -87,9 +95,13 @@ def formula(tax_unit, period, parameters):

qualifies = federal_agi <= p.income_limit.regular[filing_status]

# Count head and spouse only (1 for single/hoh, 2 for joint)
# Count the filers' own exemptions: none for a filer whom another
# taxpayer can claim (ORS 316.085(1)(b)).
dependent_filer = tax_unit("head_or_spouse_is_dependent_elsewhere", period)
head_spouse_count = where(
filing_status == filing_status.possible_values.JOINT, 2, 1
dependent_filer,
tax_unit("head_spouse_count_not_dependent_elsewhere", period),
tax_unit("head_spouse_count", period),
)

# Add older dependents (those excluded from dependent credit by age limit)
Expand Down
121 changes: 121 additions & 0 deletions policyengine_us/tests/core/test_claimable_filer_or_me_hi_invariants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
"""Oregon, Maine and Hawaii rules for a filer who can be claimed as a dependent.

Each state denies such a filer their own exemption, and several credits need
dependents that a return with a claimable filer cannot have (IRC 152(b)(1)).

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
incapacity cases).
2. Monotonicity: marking another filer as claimed never raises an output
(seeded population and crafted cases only).

The crafted cases add adults and a dependent who are incapable of self-care,
with care expenses, which the generated population never has. The contributed
reforms and the Oregon credit's column 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 = ["OR", "ME", "HI"]
YEARS = [2021, 2025, 2026]
OUTPUTS = [
"or_exemption_credit",
"or_ctc",
"or_wfhdc_has_qualified_individual_eligible",
"me_personal_exemption_deduction",
"me_dependent_exemption_credit",
"me_pro_forma_childless_eitc",
"me_relief_rebate",
"me_property_tax_fairness_credit_benefit_base",
"hi_regular_exemptions",
"hi_disabled_exemptions",
"hi_cdcc_eligible",
"hi_cdcc_qualifying_individuals",
"hi_cdcc",
]


def _incapacity_cases():
# Both spouses and an adult dependent incapable of self-care, with care
# expenses, and a young child with childcare expenses.
earner = {
"age": 45,
"employment_income": 10_000.0,
"is_disabled": True,
"is_incapable_of_self_care": True,
"pre_subsidy_care_expenses": 2_000.0,
}
other = {
"age": 44,
"employment_income": 3_000.0,
"is_disabled": True,
"is_incapable_of_self_care": True,
"pre_subsidy_care_expenses": 1_000.0,
}
relative = {
"age": 30,
"is_disabled": True,
"is_incapable_of_self_care": True,
"pre_subsidy_care_expenses": 1_500.0,
}
child = {"age": 4, "pre_subsidy_childcare_expenses": 3_000.0}
return [
{
"state": state,
"adults": couple,
"dependents": others,
"claimed": claimed,
}
for state in ("OR", "HI")
for couple in ([earner, other], [earner, {"age": 44}])
for others in ([], [child], [child, relative])
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_or_me_hi_claimable_filer_rules_are_label_free(year, units):
check_swap(units, year, OUTPUTS)


@pytest.mark.parametrize("year", YEARS)
def test_or_me_hi_claimable_filer_rules_seeded_population(year):
units = (
_seeded_couples(STATES, per_state=3)
+ _crafted_cases(STATES)
+ _incapacity_cases()
)
check_swap(units, year, OUTPUTS)
check_monotone(units, year, OUTPUTS)
Original file line number Diff line number Diff line change
Expand Up @@ -130,3 +130,127 @@
output:
# Line 11 cap is $7,500, so line 22 = 10_000 - 4_000 = 6_000; 6_000 * 22%.
hi_cdcc: 1_320

# Both spouses are incapable of self-care and one can be claimed as a dependent.
# Only that spouse is a qualifying individual (of the spouse who cannot be
# claimed), so only care expenses for that spouse count (HRS 235-55.6(b)(2)).
- name: 2025 care expenses of the spouse who is not a qualifying individual do not count (the claimable spouse is the head)
period: 2025
input:
people:
person_a:
age: 45
is_incapable_of_self_care: true
claimed_as_dependent_on_another_return: true
is_tax_unit_head: true
is_tax_unit_spouse: false
person_b:
age: 45
employment_income: 10000
is_incapable_of_self_care: true
pre_subsidy_care_expenses: 2000
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: HI
output:
hi_cdcc_qualifying_individuals: 1
hi_dependent_care_benefits: 0
hi_cdcc: 0

- name: 2025 care expenses of the spouse who is not a qualifying individual do not count (the claimable spouse is the spouse)
period: 2025
input:
people:
person_b:
age: 45
employment_income: 10000
is_incapable_of_self_care: true
pre_subsidy_care_expenses: 2000
is_tax_unit_head: true
is_tax_unit_spouse: false
person_a:
age: 45
is_incapable_of_self_care: true
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: HI
output:
hi_cdcc_qualifying_individuals: 1
hi_dependent_care_benefits: 0
hi_cdcc: 0

- name: 2025 care expenses of the claimable incapacitated spouse count (the claimable spouse is the head)
period: 2025
input:
people:
person_a:
age: 45
is_incapable_of_self_care: true
pre_subsidy_care_expenses: 2000
claimed_as_dependent_on_another_return: true
is_tax_unit_head: true
is_tax_unit_spouse: false
person_b:
age: 45
employment_income: 10000
is_incapable_of_self_care: true
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: HI
output:
# 25% x min(2,000 expenses, $10,000 limit, 10,000 earned)
hi_cdcc_qualifying_individuals: 1
hi_dependent_care_benefits: 2000
hi_cdcc: 500

- name: 2025 care expenses of the claimable incapacitated spouse count (the claimable spouse is the spouse)
period: 2025
input:
people:
person_b:
age: 45
employment_income: 10000
is_incapable_of_self_care: true
is_tax_unit_head: true
is_tax_unit_spouse: false
person_a:
age: 45
is_incapable_of_self_care: true
pre_subsidy_care_expenses: 2000
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: HI
output:
hi_cdcc_qualifying_individuals: 1
hi_dependent_care_benefits: 2000
hi_cdcc: 500
Loading
Loading