From 4b0709e55f26e0e9932cfffb39c2f650168bdbca Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Fri, 9 Oct 2026 09:40:51 -0400 Subject: [PATCH 1/6] Apply New Mexico's rules for a filer who can be claimed as a dependent NMSA chapter 7 article 2 bars "a dependent of another individual" from several credits and exemptions that the model gave anyway, and counts as dependents only those allowed under IRC 152, which leaves a return with a claimable filer none (IRC 152(b)(1)). Now: - the child income tax credit (7-2-18.34) needs a filer who cannot be claimed; - the 65+ medical care credit (7-2-18.13) needs a filer who is both 65+ and not claimable, and it and the 65+ medical exemption (7-2-5.9) no longer count a dependent's age; - the elderly property tax rebate (7-2-18) and the 100+ exemption (7-2-5.7) apply per filer; - the working families credit (7-2-18.15) applies the federal childless-filer dependent test and the filer-only age test; - the child day care credit (7-2-18.1) and the deduction for certain dependents (7-2-39) count no dependents when a filer can be claimed. On a joint return, a spouse who cannot be claimed keeps the credits that TRD's PIT-RC instructions say "your spouse may still qualify to claim". Co-Authored-By: Claude Opus 5.5 --- changelog.d/claimable-filer-nm.fixed.md | 1 + .../test_claimable_filer_nm_invariants.py | 69 +++++++++ .../credits/cdcc/nm_cdcc_eligible_child.yaml | 78 ++++++++++ .../eitc/nm_eitc_demographic_eligible.yaml | 138 ++++++++++++++++++ .../states/nm/tax/income/credits/nm_ctc.yaml | 104 +++++++++++++ .../credits/nm_medical_expense_credit.yaml | 55 +++++++ .../nm_deduction_for_certain_dependents.yaml | 85 +++++++++++ .../exemptions/nm_hundred_year_exemption.yaml | 107 ++++++++++++++ .../nm_medical_expense_exemption.yaml | 78 ++++++++++ .../nm_property_tax_rebate_eligibility.yaml | 121 +++++++++++++++ .../credits/cdcc/nm_cdcc_eligible_child.py | 8 +- .../eitc/nm_eitc_demographic_eligible.py | 14 +- .../states/nm/tax/income/credits/nm_ctc.py | 12 +- .../credits/nm_medical_expense_credit.py | 25 ++-- .../nm_deduction_for_certain_dependents.py | 5 +- .../exemptions/nm_hundred_year_exemption.py | 11 +- .../nm_medical_expense_exemption.py | 13 +- .../nm_property_tax_rebate_eligible.py | 14 +- 18 files changed, 912 insertions(+), 26 deletions(-) create mode 100644 changelog.d/claimable-filer-nm.fixed.md create mode 100644 policyengine_us/tests/core/test_claimable_filer_nm_invariants.py diff --git a/changelog.d/claimable-filer-nm.fixed.md b/changelog.d/claimable-filer-nm.fixed.md new file mode 100644 index 00000000000..8d7be5cbe9f --- /dev/null +++ b/changelog.d/claimable-filer-nm.fixed.md @@ -0,0 +1 @@ +Apply New Mexico's rules for a filer who can be claimed as a dependent: no child income tax credit when every filer can be claimed (NMSA 7-2-18.34), no childless EITC, child care credit child or certain-dependents deduction on a return with a claimable filer, and the medical care credit, property tax rebate and centenarian exemption only for a filer who meets the age test and cannot be claimed; the medical expense credit and exemption and the childless EITC now test filers' ages, not a dependent's. diff --git a/policyengine_us/tests/core/test_claimable_filer_nm_invariants.py b/policyengine_us/tests/core/test_claimable_filer_nm_invariants.py new file mode 100644 index 00000000000..5b6b3f8589d --- /dev/null +++ b/policyengine_us/tests/core/test_claimable_filer_nm_invariants.py @@ -0,0 +1,69 @@ +"""New Mexico rules for a filer who can be claimed as a dependent. + +The child income tax credit, the 65+ medical care credit and exemption, the +working families credit, the elderly property tax rebate, the child day care +credit, the 100+ exemption and the deduction for certain dependents apply +NMSA chapter 7 article 2's "not a dependent of another individual" tests per +filer, and count no dependents on a return with a claimable filer. + +For couples drawn by Hypothesis and a seeded population in NM, with +either, both or neither spouse claimed, each output is the same under either +head/spouse labelling, and marking another filer as claimed never raises it. +""" + +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 = ["NM"] +YEARS = [2023, 2025, 2026] +OUTPUTS = [ + "nm_ctc", + "nm_medical_expense_credit", + "nm_medical_expense_exemption", + "nm_eitc", + "nm_deduction_for_certain_dependents", + "nm_property_tax_rebate", + "nm_cdcc_max_amount", + "nm_hundred_year_exemption", +] + + +@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_nm_claimable_filer_rules_are_label_free(year, units): + check_swap(units, year, OUTPUTS) + + +@pytest.mark.parametrize("year", YEARS) +def test_nm_claimable_filer_rules_seeded_population(year): + units = _seeded_couples(STATES, per_state=3) + _crafted_cases(STATES) + check_swap(units, year, OUTPUTS) + check_monotone(units, year, OUTPUTS) diff --git a/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/credits/cdcc/nm_cdcc_eligible_child.yaml b/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/credits/cdcc/nm_cdcc_eligible_child.yaml index 107b50cc08d..67a802934ba 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/credits/cdcc/nm_cdcc_eligible_child.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/credits/cdcc/nm_cdcc_eligible_child.yaml @@ -24,3 +24,81 @@ is_tax_unit_dependent: true output: nm_cdcc_eligible_child: true + + +- name: 2025 joint return with one claimable spouse has no eligible child (the claimable spouse is the head) + period: 2025 + input: + people: + person_a: + age: 30 + claimed_as_dependent_on_another_return: true + is_tax_unit_head: true + is_tax_unit_spouse: false + person_b: + age: 30 + is_tax_unit_head: false + is_tax_unit_spouse: true + child: + age: 5 + tax_units: + tax_unit: + members: [person_a, person_b, child] + filing_status: JOINT + households: + household: + members: [person_a, person_b, child] + state_code: NM + output: + # NMSA 7-2-18.1 counts IRC 152 dependents; IRC 152(b)(1) leaves such a + # return none. + nm_cdcc_eligible_child: [false, false, false] + +- name: 2025 joint return with one claimable spouse has no eligible child (the claimable spouse is the spouse) + period: 2025 + input: + people: + person_b: + age: 30 + is_tax_unit_head: true + is_tax_unit_spouse: false + person_a: + age: 30 + claimed_as_dependent_on_another_return: true + is_tax_unit_head: false + is_tax_unit_spouse: true + child: + age: 5 + tax_units: + tax_unit: + members: [person_b, person_a, child] + filing_status: JOINT + households: + household: + members: [person_b, person_a, child] + state_code: NM + output: + # NMSA 7-2-18.1 counts IRC 152 dependents; IRC 152(b)(1) leaves such a + # return none. + nm_cdcc_eligible_child: [false, false, false] + +- name: 2025 joint return with neither spouse claimable has an eligible child + period: 2025 + input: + people: + person_a: + age: 30 + person_b: + age: 30 + child: + age: 5 + tax_units: + tax_unit: + members: [person_a, person_b, child] + filing_status: JOINT + households: + household: + members: [person_a, person_b, child] + state_code: NM + output: + nm_cdcc_eligible_child: [false, false, true] diff --git a/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/credits/eitc/nm_eitc_demographic_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/credits/eitc/nm_eitc_demographic_eligible.yaml index 4b6d82715d8..db987bd02f0 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/credits/eitc/nm_eitc_demographic_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/credits/eitc/nm_eitc_demographic_eligible.yaml @@ -48,3 +48,141 @@ state_code: NM output: nm_eitc_demographic_eligible: true + + +- name: 2025 childless single filer who can be claimed as a dependent is ineligible + period: 2025 + input: + people: + filer: + age: 21 + claimed_as_dependent_on_another_return: true + tax_units: + tax_unit: + members: [filer] + households: + household: + members: [filer] + state_code: NM + output: + # NMSA 7-2-18.15 imports IRC 32(c)(1)(A)(ii)(III). + nm_eitc_demographic_eligible: false + +- name: 2025 childless joint return with one claimable spouse is ineligible (the claimable spouse is the head) + period: 2025 + input: + people: + person_a: + age: 21 + claimed_as_dependent_on_another_return: true + is_tax_unit_head: true + is_tax_unit_spouse: false + person_b: + age: 25 + 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: NM + output: + # Publication 596, Rule 12: neither spouse may be claimable. + nm_eitc_demographic_eligible: false + +- name: 2025 childless joint return with one claimable spouse is ineligible (the claimable spouse is the spouse) + period: 2025 + input: + people: + person_b: + age: 25 + is_tax_unit_head: true + is_tax_unit_spouse: false + person_a: + age: 21 + 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: NM + output: + # Publication 596, Rule 12: neither spouse may be claimable. + nm_eitc_demographic_eligible: false + +- name: 2025 childless joint return with neither spouse claimable is eligible + period: 2025 + input: + people: + person_a: + age: 21 + person_b: + age: 25 + tax_units: + tax_unit: + members: [person_a, person_b] + filing_status: JOINT + households: + household: + members: [person_a, person_b] + state_code: NM + output: + nm_eitc_demographic_eligible: true + +- name: 2025 claimable single filer with a child is not barred by the dependent test + period: 2025 + input: + people: + filer: + age: 35 + claimed_as_dependent_on_another_return: true + child: + age: 3 + tax_units: + tax_unit: + members: [filer, child] + households: + household: + members: [filer, child] + state_code: NM + output: + # The dependent test applies only without a qualifying child. + nm_eitc_demographic_eligible: true + +- name: 2025 a dependent's age does not make a childless return eligible + period: 2025 + input: + people: + person_a: + age: 70 + is_tax_unit_head: true + is_tax_unit_spouse: false + person_b: + age: 70 + is_tax_unit_head: false + is_tax_unit_spouse: true + relative: + age: 40 + is_tax_unit_head: false + is_tax_unit_spouse: false + tax_units: + tax_unit: + members: [person_a, person_b, relative] + filing_status: JOINT + households: + household: + members: [person_a, person_b, relative] + state_code: NM + output: + # The age test applies to the filers (IRC 32(c)(1)(A)(ii)(II)), both + # above the federal maximum age of 64; the dependent aged 40 is within + # the age range but is not a filer, and is not a child. + nm_eitc_demographic_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/credits/nm_ctc.yaml b/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/credits/nm_ctc.yaml index afe322b813f..e0145ad405e 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/credits/nm_ctc.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/credits/nm_ctc.yaml @@ -37,3 +37,107 @@ filing_status: SINGLE output: nm_ctc: 75 + +- name: 2025 single filer who can be claimed as a dependent gets no child income tax credit + period: 2025 + input: + people: + parent: + age: 20 + employment_income: 10_000 + claimed_as_dependent_on_another_return: true + child: + age: 2 + tax_units: + tax_unit: + members: [parent, child] + households: + household: + members: [parent, child] + state_code: NM + output: + # NMSA 7-2-18.34(A): "a taxpayer who is a resident and is not a dependent + # of another individual". + nm_ctc: 0 + +- name: 2025 joint return with one claimable spouse keeps the child income tax credit (the claimable spouse is the head) + period: 2025 + input: + people: + person_a: + age: 20 + employment_income: 10_000 + claimed_as_dependent_on_another_return: true + is_tax_unit_head: true + is_tax_unit_spouse: false + person_b: + age: 20 + claimed_as_dependent_on_another_return: false + 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 + households: + household: + members: [person_a, person_b, child] + state_code: NM + output: + # "your spouse may still qualify to claim rebates or credits" (PIT-RC); + # AGI $10,000 is in the first bracket: $637 per qualifying child. + nm_ctc: 637 + +- name: 2025 joint return with one claimable spouse keeps the child income tax credit (the claimable spouse is the spouse) + period: 2025 + input: + people: + person_b: + age: 20 + claimed_as_dependent_on_another_return: false + is_tax_unit_head: true + is_tax_unit_spouse: false + person_a: + age: 20 + employment_income: 10_000 + claimed_as_dependent_on_another_return: true + is_tax_unit_head: false + is_tax_unit_spouse: true + child: + age: 2 + tax_units: + tax_unit: + members: [person_b, person_a, child] + filing_status: JOINT + households: + household: + members: [person_b, person_a, child] + state_code: NM + output: + nm_ctc: 637 + +- name: 2025 joint return with both spouses claimable gets no child income tax credit + period: 2025 + input: + people: + person_a: + age: 20 + employment_income: 10_000 + claimed_as_dependent_on_another_return: true + person_b: + age: 20 + claimed_as_dependent_on_another_return: true + child: + age: 2 + tax_units: + tax_unit: + members: [person_a, person_b, child] + filing_status: JOINT + households: + household: + members: [person_a, person_b, child] + state_code: NM + output: + nm_ctc: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/credits/nm_medical_expense_credit.yaml b/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/credits/nm_medical_expense_credit.yaml index f8563d24439..832af529754 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/credits/nm_medical_expense_credit.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/credits/nm_medical_expense_credit.yaml @@ -249,3 +249,58 @@ state_code: NM output: nm_medical_expense_credit: 2_800 + +- name: 2025 a dependent aged 65 or older does not qualify the return + period: 2025 + input: + people: + person_a: + age: 40 + is_tax_unit_head: true + is_tax_unit_spouse: false + person_b: + age: 40 + is_tax_unit_head: false + is_tax_unit_spouse: true + parent: + age: 70 + is_tax_unit_head: false + is_tax_unit_spouse: false + tax_units: + tax_unit: + members: [person_a, person_b, parent] + filing_status: JOINT + itemized_medical_expenses: 30_000 + households: + household: + members: [person_a, person_b, parent] + state_code: NM + output: + # NMSA 7-2-18.13(A): "a taxpayer ... who is sixty-five years of age or + # older"; PIT-RC line 23: "If you or your spouse are 65 years of age or + # older". + nm_medical_expense_credit: 0 + +- name: 2025 joint return with a spouse aged 65 or older qualifies whichever spouse is the head + period: 2025 + input: + people: + person_b: + age: 40 + is_tax_unit_head: true + is_tax_unit_spouse: false + person_a: + age: 70 + is_tax_unit_head: false + is_tax_unit_spouse: true + tax_units: + tax_unit: + members: [person_b, person_a] + filing_status: JOINT + itemized_medical_expenses: 30_000 + households: + household: + members: [person_b, person_a] + state_code: NM + output: + nm_medical_expense_credit: 2_800 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/deductions/certain_dependents/nm_deduction_for_certain_dependents.yaml b/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/deductions/certain_dependents/nm_deduction_for_certain_dependents.yaml index c819101fe40..9c40e8ef783 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/deductions/certain_dependents/nm_deduction_for_certain_dependents.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/deductions/certain_dependents/nm_deduction_for_certain_dependents.yaml @@ -51,3 +51,88 @@ nm_deduction_for_certain_dependents_eligible: true output: nm_deduction_for_certain_dependents: 16_000 + + +- name: 2025 joint return with one claimable spouse has no dependents to deduct (the claimable spouse is the head) + period: 2025 + input: + people: + person_a: + age: 30 + claimed_as_dependent_on_another_return: true + is_tax_unit_head: true + is_tax_unit_spouse: false + person_b: + age: 30 + is_tax_unit_head: false + is_tax_unit_spouse: true + child_1: + age: 5 + child_2: + age: 8 + tax_units: + tax_unit: + members: [person_a, person_b, child_1, child_2] + filing_status: JOINT + households: + household: + members: [person_a, person_b, child_1, child_2] + state_code: NM + output: + # IRC 152(b)(1): such a return has no dependents (NMSA 7-2-39 defines + # dependent by IRC 152). + nm_deduction_for_certain_dependents: 0 + +- name: 2025 joint return with one claimable spouse has no dependents to deduct (the claimable spouse is the spouse) + period: 2025 + input: + people: + person_b: + age: 30 + is_tax_unit_head: true + is_tax_unit_spouse: false + person_a: + age: 30 + claimed_as_dependent_on_another_return: true + is_tax_unit_head: false + is_tax_unit_spouse: true + child_1: + age: 5 + child_2: + age: 8 + tax_units: + tax_unit: + members: [person_b, person_a, child_1, child_2] + filing_status: JOINT + households: + household: + members: [person_b, person_a, child_1, child_2] + state_code: NM + output: + # IRC 152(b)(1): such a return has no dependents (NMSA 7-2-39 defines + # dependent by IRC 152). + nm_deduction_for_certain_dependents: 0 + +- name: 2025 joint return with neither spouse claimable deducts all but one dependent + period: 2025 + input: + people: + person_a: + age: 30 + person_b: + age: 30 + child_1: + age: 5 + child_2: + age: 8 + tax_units: + tax_unit: + members: [person_a, person_b, child_1, child_2] + filing_status: JOINT + households: + household: + members: [person_a, person_b, child_1, child_2] + state_code: NM + output: + # $4,000 x (2 - 1). + nm_deduction_for_certain_dependents: 4_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/exemptions/nm_hundred_year_exemption.yaml b/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/exemptions/nm_hundred_year_exemption.yaml index 9ed4d307148..8160a003512 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/exemptions/nm_hundred_year_exemption.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/exemptions/nm_hundred_year_exemption.yaml @@ -51,3 +51,110 @@ filing_status: SINGLE output: nm_hundred_year_exemption: 10_000 + + +- name: 2025 claimable spouse aged 100 or older gets no exemption (the claimable spouse is the head) + period: 2025 + input: + people: + person_a: + age: 100 + claimed_as_dependent_on_another_return: true + is_tax_unit_head: true + is_tax_unit_spouse: false + person_b: + age: 30 + is_tax_unit_head: false + is_tax_unit_spouse: true + tax_units: + tax_unit: + members: [person_a, person_b] + filing_status: JOINT + adjusted_gross_income: 10_000 + households: + household: + members: [person_a, person_b] + state_code: NM + output: + # NMSA 7-2-5.7: an individual 100 or older "who is not a dependent of + # another individual". + nm_hundred_year_exemption: 0 + +- name: 2025 claimable spouse aged 100 or older gets no exemption (the claimable spouse is the spouse) + period: 2025 + input: + people: + person_b: + age: 30 + is_tax_unit_head: true + is_tax_unit_spouse: false + person_a: + age: 100 + 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 + adjusted_gross_income: 10_000 + households: + household: + members: [person_b, person_a] + state_code: NM + output: + # NMSA 7-2-5.7: an individual 100 or older "who is not a dependent of + # another individual". + nm_hundred_year_exemption: 0 + +- name: 2025 spouse aged 100 or older keeps the exemption when the other spouse can be claimed (the claimable spouse is the head) + period: 2025 + input: + people: + person_a: + age: 30 + claimed_as_dependent_on_another_return: true + is_tax_unit_head: true + is_tax_unit_spouse: false + person_b: + age: 100 + is_tax_unit_head: false + is_tax_unit_spouse: true + tax_units: + tax_unit: + members: [person_a, person_b] + filing_status: JOINT + adjusted_gross_income: 10_000 + households: + household: + members: [person_a, person_b] + state_code: NM + output: + # Half of the joint income, as for any one eligible spouse. + nm_hundred_year_exemption: 5_000 + +- name: 2025 spouse aged 100 or older keeps the exemption when the other spouse can be claimed (the claimable spouse is the spouse) + period: 2025 + input: + people: + person_b: + age: 100 + is_tax_unit_head: true + is_tax_unit_spouse: false + person_a: + age: 30 + 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 + adjusted_gross_income: 10_000 + households: + household: + members: [person_b, person_a] + state_code: NM + output: + # Half of the joint income, as for any one eligible spouse. + nm_hundred_year_exemption: 5_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/exemptions/nm_medical_expense_exemption.yaml b/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/exemptions/nm_medical_expense_exemption.yaml index 65264be9353..d1c6c67950a 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/exemptions/nm_medical_expense_exemption.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/exemptions/nm_medical_expense_exemption.yaml @@ -48,3 +48,81 @@ filing_status: SURVIVING_SPOUSE output: nm_medical_expense_exemption: 3_000 + +- name: 2025 a dependent aged 65 or older does not qualify the return for the exemption + period: 2025 + input: + people: + person_a: + age: 40 + is_tax_unit_head: true + is_tax_unit_spouse: false + person_b: + age: 40 + is_tax_unit_head: false + is_tax_unit_spouse: true + parent: + age: 70 + is_tax_unit_head: false + is_tax_unit_spouse: false + tax_units: + tax_unit: + members: [person_a, person_b, parent] + filing_status: JOINT + itemized_medical_expenses: 30_000 + households: + household: + members: [person_a, person_b, parent] + state_code: NM + output: + # NMSA 7-2-5.9(A): "any individual sixty-five years of age or older"; + # PIT-ADJ line 18: "If you or your spouse are 65 years of age or older". + nm_medical_expense_exemption: 0 + +- name: 2025 joint return with a spouse aged 65 or older gets the exemption (the older spouse is the head) + period: 2025 + input: + people: + person_a: + age: 70 + is_tax_unit_head: true + is_tax_unit_spouse: false + person_b: + age: 40 + is_tax_unit_head: false + is_tax_unit_spouse: true + tax_units: + tax_unit: + members: [person_a, person_b] + filing_status: JOINT + itemized_medical_expenses: 30_000 + households: + household: + members: [person_a, person_b] + state_code: NM + output: + nm_medical_expense_exemption: 3_000 + +- name: 2025 joint return with a spouse aged 65 or older gets the exemption (the older spouse is the spouse) + period: 2025 + input: + people: + person_b: + age: 40 + is_tax_unit_head: true + is_tax_unit_spouse: false + person_a: + age: 70 + is_tax_unit_head: false + is_tax_unit_spouse: true + tax_units: + tax_unit: + members: [person_b, person_a] + filing_status: JOINT + itemized_medical_expenses: 30_000 + households: + household: + members: [person_b, person_a] + state_code: NM + output: + nm_medical_expense_exemption: 3_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/rebates/nm_property_tax_rebate_eligibility.yaml b/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/rebates/nm_property_tax_rebate_eligibility.yaml index d673a251d8f..f886a19850b 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/rebates/nm_property_tax_rebate_eligibility.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/rebates/nm_property_tax_rebate_eligibility.yaml @@ -47,3 +47,124 @@ nm_modified_gross_income: 16_000 output: nm_property_tax_rebate_eligible: true + + +- name: 2025 single filer aged 65 or older who can be claimed as a dependent is ineligible + period: 2025 + input: + people: + filer: + age: 70 + claimed_as_dependent_on_another_return: true + tax_units: + tax_unit: + members: [filer] + nm_modified_gross_income: 5_000 + households: + household: + members: [filer] + state_code: NM + output: + # NMSA 7-2-18: a resident 65 or over "who is not a dependent of another + # individual". + nm_property_tax_rebate_eligible: false + +- name: 2025 joint return whose only spouse aged 65 or older can be claimed is ineligible (the claimable spouse is the head) + period: 2025 + input: + people: + person_a: + age: 70 + claimed_as_dependent_on_another_return: true + is_tax_unit_head: true + is_tax_unit_spouse: false + person_b: + age: 30 + is_tax_unit_head: false + is_tax_unit_spouse: true + tax_units: + tax_unit: + members: [person_a, person_b] + filing_status: JOINT + nm_modified_gross_income: 5_000 + households: + household: + members: [person_a, person_b] + state_code: NM + output: + nm_property_tax_rebate_eligible: false + +- name: 2025 joint return whose only spouse aged 65 or older can be claimed is ineligible (the claimable spouse is the spouse) + period: 2025 + input: + people: + person_b: + age: 30 + is_tax_unit_head: true + is_tax_unit_spouse: false + person_a: + age: 70 + 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 + nm_modified_gross_income: 5_000 + households: + household: + members: [person_b, person_a] + state_code: NM + output: + nm_property_tax_rebate_eligible: false + +- name: 2025 joint return whose spouse aged 65 or older cannot be claimed is eligible (the claimable spouse is the head) + period: 2025 + input: + people: + person_a: + age: 30 + claimed_as_dependent_on_another_return: true + is_tax_unit_head: true + is_tax_unit_spouse: false + person_b: + age: 70 + is_tax_unit_head: false + is_tax_unit_spouse: true + tax_units: + tax_unit: + members: [person_a, person_b] + filing_status: JOINT + nm_modified_gross_income: 5_000 + households: + household: + members: [person_a, person_b] + state_code: NM + output: + nm_property_tax_rebate_eligible: true + +- name: 2025 joint return whose spouse aged 65 or older cannot be claimed is eligible (the claimable spouse is the spouse) + period: 2025 + input: + people: + person_b: + age: 70 + is_tax_unit_head: true + is_tax_unit_spouse: false + person_a: + age: 30 + 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 + nm_modified_gross_income: 5_000 + households: + household: + members: [person_b, person_a] + state_code: NM + output: + nm_property_tax_rebate_eligible: true diff --git a/policyengine_us/variables/gov/states/nm/tax/income/credits/cdcc/nm_cdcc_eligible_child.py b/policyengine_us/variables/gov/states/nm/tax/income/credits/cdcc/nm_cdcc_eligible_child.py index 14d728cf50b..34c1e2a375f 100644 --- a/policyengine_us/variables/gov/states/nm/tax/income/credits/cdcc/nm_cdcc_eligible_child.py +++ b/policyengine_us/variables/gov/states/nm/tax/income/credits/cdcc/nm_cdcc_eligible_child.py @@ -14,4 +14,10 @@ def formula(person, period, parameters): age = person("age", period) age_eligible = age < p.age_eligible dependent = person("is_tax_unit_dependent", period) - return age_eligible & dependent + # NMSA 7-2-18.1 counts a dependent as defined in IRC 152, and under + # IRC 152(b)(1) a return on which the filer (or, if joint, either + # spouse) can be claimed as a dependent has no dependents. + dependent_filer = person.tax_unit( + "head_or_spouse_is_dependent_elsewhere", period + ) + return age_eligible & dependent & ~dependent_filer diff --git a/policyengine_us/variables/gov/states/nm/tax/income/credits/eitc/nm_eitc_demographic_eligible.py b/policyengine_us/variables/gov/states/nm/tax/income/credits/eitc/nm_eitc_demographic_eligible.py index 743b732d797..cc49085a4ad 100644 --- a/policyengine_us/variables/gov/states/nm/tax/income/credits/eitc/nm_eitc_demographic_eligible.py +++ b/policyengine_us/variables/gov/states/nm/tax/income/credits/eitc/nm_eitc_demographic_eligible.py @@ -21,4 +21,16 @@ def formula(tax_unit, period, parameters): ) max_age = parameters.gov.irs.credits.eitc.eligibility.age.max(period) meets_age_requirements = (age >= min_age) & (age <= max_age) - return has_child | tax_unit.any(meets_age_requirements) + # NMSA 7-2-18.15 takes the federal credit's eligibility rules apart + # from the age and identification exceptions. As federally (IRC + # 32(c)(1)(A)(ii)(II)), the age test applies to the filers, not to + # dependents. A filer without a qualifying child must not be a + # dependent of another taxpayer (IRC 32(c)(1)(A)(ii)(III)), and on a + # joint return neither spouse may be claimable (Publication 596, + # Rule 12). + filer = person("is_tax_unit_head_or_spouse", period) + dependent_filer = tax_unit("head_or_spouse_is_dependent_elsewhere", period) + childless_eligible = ( + tax_unit.any(meets_age_requirements & filer) & ~dependent_filer + ) + return has_child | childless_eligible diff --git a/policyengine_us/variables/gov/states/nm/tax/income/credits/nm_ctc.py b/policyengine_us/variables/gov/states/nm/tax/income/credits/nm_ctc.py index 7295a240d3b..df105c86537 100644 --- a/policyengine_us/variables/gov/states/nm/tax/income/credits/nm_ctc.py +++ b/policyengine_us/variables/gov/states/nm/tax/income/credits/nm_ctc.py @@ -7,7 +7,10 @@ class nm_ctc(Variable): label = "New Mexico child income tax credit" definition_period = YEAR unit = USD - reference = "https://nmonesource.com/nmos/nmsa/en/item/4340/index.do#!fragment/zoupio-_Toc140503818/BQCwhgziBcwMYgK4DsDWszIQewE4BUBTADwBdoAvbRABwEtsBaAfX2zgEYAWABgFYeAZgAcHYQEoANMmylCEAIqJCuAJ7QA5BskRCYXAiUr1WnXoMgAynlIAhdQCUAogBknANQCCAOQDCTyVIwACNoUnZxcSA" + reference = ( + "https://nmonesource.com/nmos/nmsa/en/item/4340/index.do#!fragment/zoupio-_Toc140503818/BQCwhgziBcwMYgK4DsDWszIQewE4BUBTADwBdoAvbRABwEtsBaAfX2zgEYAWABgFYeAZgAcHYQEoANMmylCEAIqJCuAJ7QA5BskRCYXAiUr1WnXoMgAynlIAhdQCUAogBknANQCCAOQDCTyVIwACNoUnZxcSA", + "https://realfile.tax.newmexico.gov/2025pit-rc-ins.pdf#page=10", + ) defined_for = StateCode.NM def formula(tax_unit, period, parameters): @@ -25,4 +28,9 @@ def formula(tax_unit, period, parameters): filing_status = tax_unit("filing_status", period) separate = filing_status == filing_status.possible_values.SEPARATE denominator = where(separate, 2, 1) - return amount / denominator + # NMSA 7-2-18.34(A) allows the credit to "a taxpayer who is a resident + # and is not a dependent of another individual". On a joint return a + # spouse who is not a dependent may still claim it (PIT-RC: "your + # spouse may still qualify to claim rebates or credits"). + every_filer_dependent = tax_unit("every_filer_is_dependent_elsewhere", period) + return where(every_filer_dependent, 0, amount / denominator) diff --git a/policyengine_us/variables/gov/states/nm/tax/income/credits/nm_medical_expense_credit.py b/policyengine_us/variables/gov/states/nm/tax/income/credits/nm_medical_expense_credit.py index 1ee85c8bfae..a094790e1d1 100644 --- a/policyengine_us/variables/gov/states/nm/tax/income/credits/nm_medical_expense_credit.py +++ b/policyengine_us/variables/gov/states/nm/tax/income/credits/nm_medical_expense_credit.py @@ -8,6 +8,7 @@ class nm_medical_expense_credit(Variable): definition_period = YEAR reference = ( "https://nmonesource.com/nmos/nmsa/en/item/4340/index.do#!fragment/zoupio-_Toc140503776/BQCwhgziBcwMYgK4DsDWszIQewE4BUBTADwBdoAvbRABwEtsBaAfX2zgEYAWABgFYeAZgDswgGwBKADTJspQhACKiQrgCe0AOSapEQmFwJlqjdt37DIAMp5SAIQ0AlAKIAZZwDUAggDkAws5SpGAARtCk7BISQA", + # PDF pages 2, 9 "https://realfile.tax.newmexico.gov/2025pit-rc-ins.pdf#page=2", ) defined_for = StateCode.NM @@ -18,21 +19,19 @@ def formula(tax_unit, period, parameters): p = pcredits.unreimbursed_medical_care_expense age = person("age", period) medical_expense = tax_unit("itemized_medical_expenses", period) - aged = age >= p.age_eligibility expense_eligible = medical_expense >= p.min_expenses - # NMSA 7-2-18.13(A) allows the credit to a taxpayer "who is sixty-five - # years of age or older and who is not a dependent of another - # taxpayer", and the PIT-RC instructions let a spouse who is not a - # dependent claim it when the other spouse is. So when a filer is a - # dependent elsewhere, a filer who is not must be 65 or older. + # NMSA 7-2-18.13(A) allows the credit to "a taxpayer ... who is + # sixty-five years of age or older and who is not a dependent of + # another taxpayer", so both tests apply to the same filer: a + # dependent aged 65 or older does not qualify the return (PIT-RC line + # 23: "If you or your spouse are 65 years of age or older"), and on a + # joint return a spouse who is not a dependent may still qualify + # ("If you are a dependent with a spouse who was not a dependent of + # another taxpayer, your spouse may still qualify"). filer = person("is_tax_unit_head_or_spouse", period) - claimed = person("claimed_as_dependent_on_another_return", period) - independent_aged_filer = tax_unit.any(filer & ~claimed & aged) - dependent_filer = tax_unit("head_or_spouse_is_dependent_elsewhere", period) - age_eligible = where( - dependent_filer, independent_aged_filer, tax_unit.any(aged) - ) - eligible = age_eligible & expense_eligible + claimed_elsewhere = person("claimed_as_dependent_on_another_return", period) + qualifying_filer = filer & (age >= p.age_eligibility) & ~claimed_elsewhere + eligible = tax_unit.any(qualifying_filer) & expense_eligible # exemption is halved for married filing separately filing_status = tax_unit("filing_status", period) separate = filing_status == filing_status.possible_values.SEPARATE diff --git a/policyengine_us/variables/gov/states/nm/tax/income/deductions/certain_dependents/nm_deduction_for_certain_dependents.py b/policyengine_us/variables/gov/states/nm/tax/income/deductions/certain_dependents/nm_deduction_for_certain_dependents.py index 886cc8d6029..d6713d4d171 100644 --- a/policyengine_us/variables/gov/states/nm/tax/income/deductions/certain_dependents/nm_deduction_for_certain_dependents.py +++ b/policyengine_us/variables/gov/states/nm/tax/income/deductions/certain_dependents/nm_deduction_for_certain_dependents.py @@ -16,7 +16,10 @@ def formula(tax_unit, period, parameters): # The law 7-2-39(D) defines dependents as those from IRC 152. # IRC 152 refers to all dependents. # https://www.law.cornell.edu/uscode/text/26/152 - dependents = tax_unit("tax_unit_dependents", period) + # IRC 152(b)(1): a return on which the filer (or, if joint, either + # spouse) can be claimed as a dependent has no dependents. + dependent_filer = tax_unit("head_or_spouse_is_dependent_elsewhere", period) + dependents = where(dependent_filer, 0, tax_unit("tax_unit_dependents", period)) # New Mexico reduces the number of claimable dependents by one. countable_dependents = max_(dependents - 1, 0) amount_per_dependent = p.amount[filing_status] diff --git a/policyengine_us/variables/gov/states/nm/tax/income/exemptions/nm_hundred_year_exemption.py b/policyengine_us/variables/gov/states/nm/tax/income/exemptions/nm_hundred_year_exemption.py index 68d8253cc04..a6bc609baf3 100644 --- a/policyengine_us/variables/gov/states/nm/tax/income/exemptions/nm_hundred_year_exemption.py +++ b/policyengine_us/variables/gov/states/nm/tax/income/exemptions/nm_hundred_year_exemption.py @@ -14,8 +14,15 @@ def formula(tax_unit, period, parameters): age_head = tax_unit("age_head", period) age_spouse = tax_unit("age_spouse", period) p = parameters(period).gov.states.nm.tax.income.exemptions.hundred_year - head_eligible = age_head >= p.age_eligibility - spouse_eligible = age_spouse >= p.age_eligibility + # NMSA 7-2-5.7 exempts an individual 100 or older "who is not a + # dependent of another individual", so each spouse qualifies on their + # own. + head_eligible = (age_head >= p.age_eligibility) & ~tax_unit( + "head_is_dependent_elsewhere", period + ) + spouse_eligible = (age_spouse >= p.age_eligibility) & ~tax_unit( + "spouse_is_dependent_elsewhere", period + ) filing_status = tax_unit("filing_status", period) joint = filing_status == filing_status.possible_values.JOINT # Halve the exemption if only one of head and spouse is eligible of a joint filer. diff --git a/policyengine_us/variables/gov/states/nm/tax/income/exemptions/nm_medical_expense_exemption.py b/policyengine_us/variables/gov/states/nm/tax/income/exemptions/nm_medical_expense_exemption.py index 3b5bed34f4a..dd02d6d3eb8 100644 --- a/policyengine_us/variables/gov/states/nm/tax/income/exemptions/nm_medical_expense_exemption.py +++ b/policyengine_us/variables/gov/states/nm/tax/income/exemptions/nm_medical_expense_exemption.py @@ -6,7 +6,10 @@ class nm_medical_expense_exemption(Variable): entity = TaxUnit label = "New Mexico unreimbursed medical expense care exemption" definition_period = YEAR - reference = "https://nmonesource.com/nmos/nmsa/en/item/4340/index.do#!fragment/zoupio-_Toc140503680/BQCwhgziBcwMYgK4DsDWszIQewE4BUBTADwBdoAvbRABwEtsBaAfX2zgEYAWABgFYeAZgBsADh4BKADTJspQhACKiQrgCe0AOSapEQmFwJlqjdt37DIAMp5SAIQ0AlAKIAZZwDUAggDkAws5SpGAARtCk7BISQA" + reference = ( + "https://nmonesource.com/nmos/nmsa/en/item/4340/index.do#!fragment/zoupio-_Toc140503680/BQCwhgziBcwMYgK4DsDWszIQewE4BUBTADwBdoAvbRABwEtsBaAfX2zgEYAWABgFYeAZgBsADh4BKADTJspQhACKiQrgCe0AOSapEQmFwJlqjdt37DIAMp5SAIQ0AlAKIAZZwDUAggDkAws5SpGAARtCk7BISQA", + "https://klvg4oyd4j.execute-api.us-west-2.amazonaws.com/prod/PublicFiles/34821a9573ca43e7b06dfad20f5183fd/0558a902-6362-47ca-8e3b-7cca3bc69b9d/2025%20PIT%20Packet_Final.pdf#page=50", + ) defined_for = StateCode.NM def formula(tax_unit, period, parameters): @@ -16,7 +19,13 @@ def formula(tax_unit, period, parameters): ).gov.states.nm.tax.income.exemptions.unreimbursed_medical_care_expense age = person("age", period) medical_expense = tax_unit("itemized_medical_expenses", period) - age_eligible = tax_unit.any(age >= p.age_eligibility) + # NMSA 7-2-5.9(A) allows the exemption to "any individual sixty-five + # years of age or older" for expenses paid "for that individual or + # for the individual's spouse or dependent", and PIT-ADJ line 18 asks + # whether "you or your spouse are 65 years of age or older". A + # dependent aged 65 or older does not qualify the return. + filer = person("is_tax_unit_head_or_spouse", period) + age_eligible = tax_unit.any(filer & (age >= p.age_eligibility)) expense_eligible = medical_expense >= p.min_expenses eligible = age_eligible & expense_eligible # Exemption is halved for married filing separately diff --git a/policyengine_us/variables/gov/states/nm/tax/income/rebates/property_tax_rebate/nm_property_tax_rebate_eligible.py b/policyengine_us/variables/gov/states/nm/tax/income/rebates/property_tax_rebate/nm_property_tax_rebate_eligible.py index 5a84b11372c..02153417f15 100644 --- a/policyengine_us/variables/gov/states/nm/tax/income/rebates/property_tax_rebate/nm_property_tax_rebate_eligible.py +++ b/policyengine_us/variables/gov/states/nm/tax/income/rebates/property_tax_rebate/nm_property_tax_rebate_eligible.py @@ -11,12 +11,18 @@ class nm_property_tax_rebate_eligible(Variable): def formula(tax_unit, period, parameters): p = parameters(period).gov.states.nm.tax.income.rebates.property_tax - # Head or spouse eligible if 65 or over. + # NMSA 7-2-18 allows the rebate to a resident 65 or over "who is not + # a dependent of another individual", so the same filer must meet + # both tests; on a joint return either spouse may. age_head = tax_unit("age_head", period) age_spouse = tax_unit("age_spouse", period) - head_age_eligible = age_head >= p.age_eligibility - spouse_age_eligible = age_spouse >= p.age_eligibility - age_eligible = head_age_eligible | spouse_age_eligible + head_eligible = (age_head >= p.age_eligibility) & ~tax_unit( + "head_is_dependent_elsewhere", period + ) + spouse_eligible = (age_spouse >= p.age_eligibility) & ~tax_unit( + "spouse_is_dependent_elsewhere", period + ) + age_eligible = head_eligible | spouse_eligible # Person eligible if income at or below $16,000 agi = tax_unit("nm_modified_gross_income", period) agi_eligible = agi <= p.income_threshold From 0de9a0e34ec1362de486412d4f5bb859d89808d6 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sat, 10 Oct 2026 09:43:59 -0400 Subject: [PATCH 2/6] Address the New Mexico claimable-filer review - EITC: the child route counts qualifying children under IRC 32(c)(3) (a dependent under 19, a student under 24, or permanently and totally disabled) instead of members under 18, so the filer-only age test and the dependent test no longer deny a return with an older qualifying child. - Property tax rebate reference opens the page with the qualifications. - Tests: older qualifying children, swapped unclaimed controls, and centenarian cases in the property test. Co-Authored-By: Claude Opus 5.5 --- changelog.d/claimable-filer-nm.fixed.md | 2 +- .../test_claimable_filer_nm_invariants.py | 44 ++++-- .../eitc/nm_eitc_demographic_eligible.yaml | 145 +++++++++++++++++- .../credits/nm_medical_expense_credit.yaml | 24 +++ .../eitc/nm_eitc_demographic_eligible.py | 5 +- .../nm_property_tax_rebate_eligible.py | 2 +- 6 files changed, 209 insertions(+), 13 deletions(-) diff --git a/changelog.d/claimable-filer-nm.fixed.md b/changelog.d/claimable-filer-nm.fixed.md index 8d7be5cbe9f..dc1f53bb505 100644 --- a/changelog.d/claimable-filer-nm.fixed.md +++ b/changelog.d/claimable-filer-nm.fixed.md @@ -1 +1 @@ -Apply New Mexico's rules for a filer who can be claimed as a dependent: no child income tax credit when every filer can be claimed (NMSA 7-2-18.34), no childless EITC, child care credit child or certain-dependents deduction on a return with a claimable filer, and the medical care credit, property tax rebate and centenarian exemption only for a filer who meets the age test and cannot be claimed; the medical expense credit and exemption and the childless EITC now test filers' ages, not a dependent's. +Apply New Mexico's rules for a filer who can be claimed as a dependent: no child income tax credit when every filer can be claimed (NMSA 7-2-18.34), no childless EITC, child care credit child or certain-dependents deduction on a return with a claimable filer, and the medical care credit, property tax rebate and centenarian exemption only for a filer who meets the age test and cannot be claimed; the medical expense credit and exemption and the childless EITC now test filers' ages, not a dependent's, and the EITC's child route counts qualifying children under IRC 32(c)(3) (a dependent under 19, a student under 24 or a permanently disabled child) rather than members under 18. diff --git a/policyengine_us/tests/core/test_claimable_filer_nm_invariants.py b/policyengine_us/tests/core/test_claimable_filer_nm_invariants.py index 5b6b3f8589d..e34647f5b2f 100644 --- a/policyengine_us/tests/core/test_claimable_filer_nm_invariants.py +++ b/policyengine_us/tests/core/test_claimable_filer_nm_invariants.py @@ -1,14 +1,19 @@ """New Mexico rules for a filer who can be claimed as a dependent. -The child income tax credit, the 65+ medical care credit and exemption, the -working families credit, the elderly property tax rebate, the child day care -credit, the 100+ exemption and the deduction for certain dependents apply -NMSA chapter 7 article 2's "not a dependent of another individual" tests per -filer, and count no dependents on a return with a claimable filer. +Several credits and exemptions bar "a dependent of another individual", and +dependent-based amounts need dependents that a return with a claimable filer +cannot have (IRC 152(b)(1)). -For couples drawn by Hypothesis and a seeded population in NM, with -either, both or neither spouse claimed, each output is the same under either -head/spouse labelling, and marking another filer as claimed never raises it. +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 + centenarian cases). +2. Monotonicity: marking another filer as claimed never raises an output + (seeded population and crafted cases only). + +The crafted cases add spouses aged 100 or older, whom the generated population +(ages 18 to 90) never has. """ import pytest @@ -41,6 +46,23 @@ ] +def _centenarian_cases(): + # One or both spouses aged 100 or older, with income to exempt. + centenarian = {"age": 101, "taxable_pension_income": 20_000.0} + older = {"age": 103, "taxable_interest_income": 5_000.0} + younger = {"age": 70, "social_security_retirement": 12_000.0} + return [ + { + "state": "NM", + "adults": couple, + "dependents": [], + "claimed": claimed, + } + for couple in ([centenarian, younger], [centenarian, older]) + for claimed in [(True, False), (False, True), (True, True)] + ] + + @st.composite def couples(draw): return { @@ -64,6 +86,10 @@ def test_nm_claimable_filer_rules_are_label_free(year, units): @pytest.mark.parametrize("year", YEARS) def test_nm_claimable_filer_rules_seeded_population(year): - units = _seeded_couples(STATES, per_state=3) + _crafted_cases(STATES) + units = ( + _seeded_couples(STATES, per_state=3) + + _crafted_cases(STATES) + + _centenarian_cases() + ) check_swap(units, year, OUTPUTS) check_monotone(units, year, OUTPUTS) diff --git a/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/credits/eitc/nm_eitc_demographic_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/credits/eitc/nm_eitc_demographic_eligible.yaml index db987bd02f0..bb680c00916 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/credits/eitc/nm_eitc_demographic_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/credits/eitc/nm_eitc_demographic_eligible.yaml @@ -49,7 +49,6 @@ output: nm_eitc_demographic_eligible: true - - name: 2025 childless single filer who can be claimed as a dependent is ineligible period: 2025 input: @@ -186,3 +185,147 @@ # above the federal maximum age of 64; the dependent aged 40 is within # the age range but is not a filer, and is not a child. nm_eitc_demographic_eligible: false + +# The dependent test applies only without a qualifying child (IRC +# 32(c)(1)(A)(ii)), and a qualifying child is a dependent under 19, a student +# under 24, or permanently and totally disabled (IRC 32(c)(3), 152(c)(3)). +- name: 2025 claimable single filer with a child aged 18 is not barred by the dependent test + period: 2025 + input: + people: + parent: + age: 35 + claimed_as_dependent_on_another_return: true + is_tax_unit_head: true + is_tax_unit_spouse: false + child: + age: 18 + is_tax_unit_head: false + is_tax_unit_spouse: false + tax_units: + tax_unit: + members: [parent, child] + households: + household: + members: [parent, child] + state_code: NM + output: + nm_eitc_demographic_eligible: true + +- name: 2025 claimable single filer with a student aged 22 is not barred by the dependent test + period: 2025 + input: + people: + parent: + age: 45 + claimed_as_dependent_on_another_return: true + is_tax_unit_head: true + is_tax_unit_spouse: false + child: + age: 22 + is_full_time_student: true + is_tax_unit_head: false + is_tax_unit_spouse: false + tax_units: + tax_unit: + members: [parent, child] + households: + household: + members: [parent, child] + state_code: NM + output: + nm_eitc_demographic_eligible: true + +- name: 2025 claimable single filer with a permanently disabled adult child is not barred by the dependent test + period: 2025 + input: + people: + parent: + age: 60 + claimed_as_dependent_on_another_return: true + is_tax_unit_head: true + is_tax_unit_spouse: false + child: + age: 30 + is_permanently_and_totally_disabled: true + is_tax_unit_head: false + is_tax_unit_spouse: false + tax_units: + tax_unit: + members: [parent, child] + households: + household: + members: [parent, child] + state_code: NM + output: + nm_eitc_demographic_eligible: true + +- name: 2025 filer above the maximum age with a student aged 20 is eligible + period: 2025 + input: + people: + parent: + age: 70 + is_tax_unit_head: true + is_tax_unit_spouse: false + child: + age: 20 + is_full_time_student: true + is_tax_unit_head: false + is_tax_unit_spouse: false + tax_units: + tax_unit: + members: [parent, child] + households: + household: + members: [parent, child] + state_code: NM + output: + nm_eitc_demographic_eligible: true + +- name: 2025 claimable single filer with a dependent aged 22 who is not a student is barred + period: 2025 + input: + people: + parent: + age: 45 + claimed_as_dependent_on_another_return: true + is_tax_unit_head: true + is_tax_unit_spouse: false + child: + age: 22 + is_tax_unit_head: false + is_tax_unit_spouse: false + tax_units: + tax_unit: + members: [parent, child] + households: + household: + members: [parent, child] + state_code: NM + output: + # The dependent aged 22 is not a qualifying child, so the return is childless. + nm_eitc_demographic_eligible: false + +- name: 2025 childless joint return with neither spouse claimable is eligible (the younger spouse is the head) + period: 2025 + input: + people: + person_a: + age: 21 + is_tax_unit_head: true + is_tax_unit_spouse: false + person_b: + age: 25 + 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: NM + output: + nm_eitc_demographic_eligible: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/credits/nm_medical_expense_credit.yaml b/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/credits/nm_medical_expense_credit.yaml index 832af529754..2e71f96ffec 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/credits/nm_medical_expense_credit.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/credits/nm_medical_expense_credit.yaml @@ -304,3 +304,27 @@ state_code: NM output: nm_medical_expense_credit: 2_800 + +- name: 2025 joint return with a spouse aged 65 or older qualifies when that spouse is the head + period: 2025 + input: + people: + person_a: + age: 70 + is_tax_unit_head: true + is_tax_unit_spouse: false + person_b: + age: 40 + is_tax_unit_head: false + is_tax_unit_spouse: true + tax_units: + tax_unit: + members: [person_a, person_b] + filing_status: JOINT + itemized_medical_expenses: 30000 + households: + household: + members: [person_a, person_b] + state_code: NM + output: + nm_medical_expense_credit: 2800 diff --git a/policyengine_us/variables/gov/states/nm/tax/income/credits/eitc/nm_eitc_demographic_eligible.py b/policyengine_us/variables/gov/states/nm/tax/income/credits/eitc/nm_eitc_demographic_eligible.py index cc49085a4ad..da8e8ec2f47 100644 --- a/policyengine_us/variables/gov/states/nm/tax/income/credits/eitc/nm_eitc_demographic_eligible.py +++ b/policyengine_us/variables/gov/states/nm/tax/income/credits/eitc/nm_eitc_demographic_eligible.py @@ -12,7 +12,10 @@ def formula(tax_unit, period, parameters): # New Mexico applies the same criteria as the federal EITC, but # changes the minimum age. person = tax_unit.members - has_child = tax_unit("tax_unit_children", period) > 0 + # A qualifying child under IRC 32(c)(3), before the identification + # requirement that New Mexico does not apply: a dependent under 19, a + # student under 24, or permanently and totally disabled. + has_child = tax_unit.any(person("is_eitc_qualifying_child", period)) age = person("age", period) # Relative parameter reference break branching in some states that # modify EITC age limits. diff --git a/policyengine_us/variables/gov/states/nm/tax/income/rebates/property_tax_rebate/nm_property_tax_rebate_eligible.py b/policyengine_us/variables/gov/states/nm/tax/income/rebates/property_tax_rebate/nm_property_tax_rebate_eligible.py index 02153417f15..973bfcec8fc 100644 --- a/policyengine_us/variables/gov/states/nm/tax/income/rebates/property_tax_rebate/nm_property_tax_rebate_eligible.py +++ b/policyengine_us/variables/gov/states/nm/tax/income/rebates/property_tax_rebate/nm_property_tax_rebate_eligible.py @@ -6,7 +6,7 @@ class nm_property_tax_rebate_eligible(Variable): entity = TaxUnit label = "Eligible for the New Mexico property tax rebate" definition_period = YEAR - reference = "https://klvg4oyd4j.execute-api.us-west-2.amazonaws.com/prod/PublicFiles/34821a9573ca43e7b06dfad20f5183fd/1afc56af-ea90-4d48-82e5-1f9aeb43255a/PITbook2022.pdf" + reference = "https://klvg4oyd4j.execute-api.us-west-2.amazonaws.com/prod/PublicFiles/34821a9573ca43e7b06dfad20f5183fd/1afc56af-ea90-4d48-82e5-1f9aeb43255a/PITbook2022.pdf#page=70" defined_for = StateCode.NM def formula(tax_unit, period, parameters): From 631623dcc2de8ca335f7bc9e684c136dd2b1a7b5 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sat, 10 Oct 2026 09:50:50 -0400 Subject: [PATCH 3/6] Keep the New Mexico EITC child route for minors and add older qualifying children The child route still counts members under 18 (so abstract fixtures and head-less units behave as before) and adds qualifying children under IRC 32(c)(3) aged 18 or over. Co-Authored-By: Claude Opus 5.5 --- changelog.d/claimable-filer-nm.fixed.md | 2 +- .../credits/eitc/nm_eitc_demographic_eligible.py | 14 ++++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/changelog.d/claimable-filer-nm.fixed.md b/changelog.d/claimable-filer-nm.fixed.md index dc1f53bb505..228f3f97b68 100644 --- a/changelog.d/claimable-filer-nm.fixed.md +++ b/changelog.d/claimable-filer-nm.fixed.md @@ -1 +1 @@ -Apply New Mexico's rules for a filer who can be claimed as a dependent: no child income tax credit when every filer can be claimed (NMSA 7-2-18.34), no childless EITC, child care credit child or certain-dependents deduction on a return with a claimable filer, and the medical care credit, property tax rebate and centenarian exemption only for a filer who meets the age test and cannot be claimed; the medical expense credit and exemption and the childless EITC now test filers' ages, not a dependent's, and the EITC's child route counts qualifying children under IRC 32(c)(3) (a dependent under 19, a student under 24 or a permanently disabled child) rather than members under 18. +Apply New Mexico's rules for a filer who can be claimed as a dependent: no child income tax credit when every filer can be claimed (NMSA 7-2-18.34), no childless EITC, child care credit child or certain-dependents deduction on a return with a claimable filer, and the medical care credit, property tax rebate and centenarian exemption only for a filer who meets the age test and cannot be claimed; the medical expense credit and exemption and the childless EITC now test filers' ages, not a dependent's, and the EITC's child route also counts older qualifying children under IRC 32(c)(3) (a dependent aged 18, a student under 24 or a permanently disabled child). diff --git a/policyengine_us/variables/gov/states/nm/tax/income/credits/eitc/nm_eitc_demographic_eligible.py b/policyengine_us/variables/gov/states/nm/tax/income/credits/eitc/nm_eitc_demographic_eligible.py index da8e8ec2f47..08169867655 100644 --- a/policyengine_us/variables/gov/states/nm/tax/income/credits/eitc/nm_eitc_demographic_eligible.py +++ b/policyengine_us/variables/gov/states/nm/tax/income/credits/eitc/nm_eitc_demographic_eligible.py @@ -12,10 +12,16 @@ def formula(tax_unit, period, parameters): # New Mexico applies the same criteria as the federal EITC, but # changes the minimum age. person = tax_unit.members - # A qualifying child under IRC 32(c)(3), before the identification - # requirement that New Mexico does not apply: a dependent under 19, a - # student under 24, or permanently and totally disabled. - has_child = tax_unit.any(person("is_eitc_qualifying_child", period)) + # A child under 18, as before, or an older qualifying child under IRC + # 32(c)(3) before the identification requirement that New Mexico does + # not apply: a dependent aged 18, a student under 24, or permanently + # and totally disabled. + older_qualifying_child = person("is_eitc_qualifying_child", period) & ~person( + "is_child", period + ) + has_child = (tax_unit("tax_unit_children", period) > 0) | tax_unit.any( + older_qualifying_child + ) age = person("age", period) # Relative parameter reference break branching in some states that # modify EITC age limits. From 167e2ed1a44cdc3fa0ab0b867002eaf32cd643be Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sat, 10 Oct 2026 13:40:19 -0400 Subject: [PATCH 4/6] Read the split dependency inputs from #10024 in New Mexico Dependent rules (child care credit child, certain-dependents deduction) and the childless EITC read the claimable-and-not-within-the-filing-exception helper; the "not a dependent of another individual" rules read claimability. Co-Authored-By: Claude Opus 5.5 --- .../credits/cdcc/nm_cdcc_eligible_child.yaml | 61 ++++++++++++++++++- .../eitc/nm_eitc_demographic_eligible.yaml | 22 +++++++ .../credits/cdcc/nm_cdcc_eligible_child.py | 2 +- .../eitc/nm_eitc_demographic_eligible.py | 4 +- .../nm_deduction_for_certain_dependents.py | 4 +- 5 files changed, 89 insertions(+), 4 deletions(-) diff --git a/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/credits/cdcc/nm_cdcc_eligible_child.yaml b/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/credits/cdcc/nm_cdcc_eligible_child.yaml index 67a802934ba..c2967302962 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/credits/cdcc/nm_cdcc_eligible_child.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/credits/cdcc/nm_cdcc_eligible_child.yaml @@ -25,7 +25,6 @@ output: nm_cdcc_eligible_child: true - - name: 2025 joint return with one claimable spouse has no eligible child (the claimable spouse is the head) period: 2025 input: @@ -102,3 +101,63 @@ state_code: NM output: nm_cdcc_eligible_child: [false, false, true] + +# Publication 501, Dependent Taxpayer Test: a filer whose would-be claimant is not +# required to file and files no return or only for a refund can claim dependents. +- name: 2025 joint return whose claimable spouse is within the filing exception has an eligible child (the claimable spouse is the head) + period: 2025 + input: + people: + person_a: + age: 30 + claimable_as_dependent_on_another_return: true + dependent_claimant_filing_exception: true + is_tax_unit_head: true + is_tax_unit_spouse: false + person_b: + age: 30 + is_tax_unit_head: false + is_tax_unit_spouse: true + child: + age: 5 + is_tax_unit_head: false + is_tax_unit_spouse: false + tax_units: + tax_unit: + members: [person_a, person_b, child] + filing_status: JOINT + households: + household: + members: [person_a, person_b, child] + state_code: NM + output: + nm_cdcc_eligible_child: [false, false, true] + +- name: 2025 joint return whose claimable spouse is within the filing exception has an eligible child (the claimable spouse is the spouse) + period: 2025 + input: + people: + person_b: + age: 30 + is_tax_unit_head: true + is_tax_unit_spouse: false + person_a: + age: 30 + claimable_as_dependent_on_another_return: true + dependent_claimant_filing_exception: true + is_tax_unit_head: false + is_tax_unit_spouse: true + child: + age: 5 + is_tax_unit_head: false + is_tax_unit_spouse: false + tax_units: + tax_unit: + members: [person_b, person_a, child] + filing_status: JOINT + households: + household: + members: [person_b, person_a, child] + state_code: NM + output: + nm_cdcc_eligible_child: [false, false, true] diff --git a/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/credits/eitc/nm_eitc_demographic_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/credits/eitc/nm_eitc_demographic_eligible.yaml index bb680c00916..149bf5aaf68 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/credits/eitc/nm_eitc_demographic_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/credits/eitc/nm_eitc_demographic_eligible.yaml @@ -329,3 +329,25 @@ state_code: NM output: nm_eitc_demographic_eligible: true + +# Publication 596, Rule 12: a filer whose would-be claimant is not required to +# file and files no return or only for a refund is not treated as a dependent. +- name: 2025 childless single filer within the claimant filing exception is eligible + period: 2025 + input: + people: + person: + age: 21 + claimable_as_dependent_on_another_return: true + dependent_claimant_filing_exception: true + is_tax_unit_head: true + is_tax_unit_spouse: false + tax_units: + tax_unit: + members: [person] + households: + household: + members: [person] + state_code: NM + output: + nm_eitc_demographic_eligible: true diff --git a/policyengine_us/variables/gov/states/nm/tax/income/credits/cdcc/nm_cdcc_eligible_child.py b/policyengine_us/variables/gov/states/nm/tax/income/credits/cdcc/nm_cdcc_eligible_child.py index 34c1e2a375f..3f34bb8fd28 100644 --- a/policyengine_us/variables/gov/states/nm/tax/income/credits/cdcc/nm_cdcc_eligible_child.py +++ b/policyengine_us/variables/gov/states/nm/tax/income/credits/cdcc/nm_cdcc_eligible_child.py @@ -18,6 +18,6 @@ def formula(person, period, parameters): # IRC 152(b)(1) a return on which the filer (or, if joint, either # spouse) can be claimed as a dependent has no dependents. dependent_filer = person.tax_unit( - "head_or_spouse_is_dependent_elsewhere", period + "head_or_spouse_is_dependent_elsewhere_without_filing_exception", period ) return age_eligible & dependent & ~dependent_filer diff --git a/policyengine_us/variables/gov/states/nm/tax/income/credits/eitc/nm_eitc_demographic_eligible.py b/policyengine_us/variables/gov/states/nm/tax/income/credits/eitc/nm_eitc_demographic_eligible.py index 08169867655..aae39b01db4 100644 --- a/policyengine_us/variables/gov/states/nm/tax/income/credits/eitc/nm_eitc_demographic_eligible.py +++ b/policyengine_us/variables/gov/states/nm/tax/income/credits/eitc/nm_eitc_demographic_eligible.py @@ -38,7 +38,9 @@ def formula(tax_unit, period, parameters): # joint return neither spouse may be claimable (Publication 596, # Rule 12). filer = person("is_tax_unit_head_or_spouse", period) - dependent_filer = tax_unit("head_or_spouse_is_dependent_elsewhere", period) + dependent_filer = tax_unit( + "head_or_spouse_is_dependent_elsewhere_without_filing_exception", period + ) childless_eligible = ( tax_unit.any(meets_age_requirements & filer) & ~dependent_filer ) diff --git a/policyengine_us/variables/gov/states/nm/tax/income/deductions/certain_dependents/nm_deduction_for_certain_dependents.py b/policyengine_us/variables/gov/states/nm/tax/income/deductions/certain_dependents/nm_deduction_for_certain_dependents.py index d6713d4d171..6dd59817b74 100644 --- a/policyengine_us/variables/gov/states/nm/tax/income/deductions/certain_dependents/nm_deduction_for_certain_dependents.py +++ b/policyengine_us/variables/gov/states/nm/tax/income/deductions/certain_dependents/nm_deduction_for_certain_dependents.py @@ -18,7 +18,9 @@ def formula(tax_unit, period, parameters): # https://www.law.cornell.edu/uscode/text/26/152 # IRC 152(b)(1): a return on which the filer (or, if joint, either # spouse) can be claimed as a dependent has no dependents. - dependent_filer = tax_unit("head_or_spouse_is_dependent_elsewhere", period) + dependent_filer = tax_unit( + "head_or_spouse_is_dependent_elsewhere_without_filing_exception", period + ) dependents = where(dependent_filer, 0, tax_unit("tax_unit_dependents", period)) # New Mexico reduces the number of claimable dependents by one. countable_dependents = max_(dependents - 1, 0) From 99ff9fd83464ab12a52500c89351c150a1e42197 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sat, 10 Oct 2026 15:24:30 -0400 Subject: [PATCH 5/6] Do not count a filer under 18 as the New Mexico EITC's child A spouse or head under 18 made a childless joint return look as if it had a child, which bypassed the dependent test. The child route now needs a member under 18 who is not a filer, or an older qualifying child. Co-Authored-By: Claude Opus 5.5 --- .../eitc/nm_eitc_demographic_eligible.yaml | 75 +++++++++++++++++++ .../eitc/nm_eitc_demographic_eligible.py | 21 +++--- 2 files changed, 86 insertions(+), 10 deletions(-) diff --git a/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/credits/eitc/nm_eitc_demographic_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/credits/eitc/nm_eitc_demographic_eligible.yaml index 149bf5aaf68..3b071b45d3d 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/credits/eitc/nm_eitc_demographic_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/credits/eitc/nm_eitc_demographic_eligible.yaml @@ -351,3 +351,78 @@ state_code: NM output: nm_eitc_demographic_eligible: true + +# A spouse under 18 is not the return's qualifying child, so a childless joint +# return with a spouse who can be claimed stays barred (Publication 596, Rule 12). +- name: 2025 childless joint return with a claimable spouse and a spouse under 18 is ineligible (the claimable spouse is the head) + period: 2025 + input: + people: + person_a: + age: 21 + is_full_time_student: true + claimable_as_dependent_on_another_return: true + is_tax_unit_head: true + is_tax_unit_spouse: false + person_b: + age: 17 + 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: NM + output: + nm_eitc_demographic_eligible: false + +- name: 2025 childless joint return with a claimable spouse and a spouse under 18 is ineligible (the claimable spouse is the spouse) + period: 2025 + input: + people: + person_b: + age: 17 + is_tax_unit_head: true + is_tax_unit_spouse: false + person_a: + age: 21 + is_full_time_student: true + claimable_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: NM + output: + nm_eitc_demographic_eligible: false + +- name: 2025 childless joint return with a spouse under 18 and nobody claimable is eligible by the other spouse's age + period: 2025 + input: + people: + person_a: + age: 21 + is_tax_unit_head: true + is_tax_unit_spouse: false + person_b: + age: 17 + 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: NM + output: + nm_eitc_demographic_eligible: true diff --git a/policyengine_us/variables/gov/states/nm/tax/income/credits/eitc/nm_eitc_demographic_eligible.py b/policyengine_us/variables/gov/states/nm/tax/income/credits/eitc/nm_eitc_demographic_eligible.py index aae39b01db4..64f34f0f447 100644 --- a/policyengine_us/variables/gov/states/nm/tax/income/credits/eitc/nm_eitc_demographic_eligible.py +++ b/policyengine_us/variables/gov/states/nm/tax/income/credits/eitc/nm_eitc_demographic_eligible.py @@ -12,16 +12,18 @@ def formula(tax_unit, period, parameters): # New Mexico applies the same criteria as the federal EITC, but # changes the minimum age. person = tax_unit.members - # A child under 18, as before, or an older qualifying child under IRC - # 32(c)(3) before the identification requirement that New Mexico does - # not apply: a dependent aged 18, a student under 24, or permanently - # and totally disabled. - older_qualifying_child = person("is_eitc_qualifying_child", period) & ~person( - "is_child", period - ) - has_child = (tax_unit("tax_unit_children", period) > 0) | tax_unit.any( - older_qualifying_child + # A child under 18 who is not a filer, or an older qualifying child + # under IRC 32(c)(3) before the identification requirement that New + # Mexico does not apply: a dependent aged 18, a student under 24, or + # permanently and totally disabled. A filer under 18 is not their own + # or their spouse's qualifying child. + filer = person("is_tax_unit_head_or_spouse", period) + minor = person("is_child", period) + minor_child = (tax_unit("tax_unit_children", period) > 0) & tax_unit.any( + minor & ~filer ) + older_qualifying_child = person("is_eitc_qualifying_child", period) & ~minor + has_child = minor_child | tax_unit.any(older_qualifying_child) age = person("age", period) # Relative parameter reference break branching in some states that # modify EITC age limits. @@ -37,7 +39,6 @@ def formula(tax_unit, period, parameters): # dependent of another taxpayer (IRC 32(c)(1)(A)(ii)(III)), and on a # joint return neither spouse may be claimable (Publication 596, # Rule 12). - filer = person("is_tax_unit_head_or_spouse", period) dependent_filer = tax_unit( "head_or_spouse_is_dependent_elsewhere_without_filing_exception", period ) From 0ef979aed9dfa83685a3578275e728a49cf7272c Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sat, 10 Oct 2026 15:52:39 -0400 Subject: [PATCH 6/6] Open New Mexico's EITC child route only for a qualifying child A member under 18 who is not a qualifying child under IRC 32(c)(3) no longer makes the return look as if it had a child, which bypassed the dependent test. Co-Authored-By: Claude Opus 5.5 --- .../eitc/nm_eitc_demographic_eligible.yaml | 107 ++++++++++++++++++ .../eitc/nm_eitc_demographic_eligible.py | 17 +-- 2 files changed, 116 insertions(+), 8 deletions(-) diff --git a/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/credits/eitc/nm_eitc_demographic_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/credits/eitc/nm_eitc_demographic_eligible.yaml index 3b071b45d3d..6e6a7ce13f5 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/credits/eitc/nm_eitc_demographic_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/credits/eitc/nm_eitc_demographic_eligible.yaml @@ -426,3 +426,110 @@ state_code: NM output: nm_eitc_demographic_eligible: true + +# A child who is not a qualifying child (for example one who fails the residency +# test) does not open the child route, so the dependent test still applies. +- name: 2025 claimable single filer with a child who is not a qualifying child is barred + period: 2025 + input: + people: + parent: + age: 35 + claimable_as_dependent_on_another_return: true + is_tax_unit_head: true + is_tax_unit_spouse: false + child: + age: 10 + is_eitc_qualifying_child: false + is_tax_unit_head: false + is_tax_unit_spouse: false + tax_units: + tax_unit: + members: [parent, child] + households: + household: + members: [parent, child] + state_code: NM + output: + nm_eitc_demographic_eligible: false + +- name: 2025 joint return with a claimable spouse and a child who is not a qualifying child is barred (the claimable spouse is the head) + period: 2025 + input: + people: + person_a: + age: 35 + claimable_as_dependent_on_another_return: true + is_tax_unit_head: true + is_tax_unit_spouse: false + person_b: + age: 33 + is_tax_unit_head: false + is_tax_unit_spouse: true + child: + age: 10 + is_eitc_qualifying_child: false + is_tax_unit_head: false + is_tax_unit_spouse: false + tax_units: + tax_unit: + members: [person_a, person_b, child] + filing_status: JOINT + households: + household: + members: [person_a, person_b, child] + state_code: NM + output: + nm_eitc_demographic_eligible: false + +- name: 2025 joint return with a claimable spouse and a child who is not a qualifying child is barred (the claimable spouse is the spouse) + period: 2025 + input: + people: + person_b: + age: 33 + is_tax_unit_head: true + is_tax_unit_spouse: false + person_a: + age: 35 + claimable_as_dependent_on_another_return: true + is_tax_unit_head: false + is_tax_unit_spouse: true + child: + age: 10 + is_eitc_qualifying_child: false + is_tax_unit_head: false + is_tax_unit_spouse: false + tax_units: + tax_unit: + members: [person_b, person_a, child] + filing_status: JOINT + households: + household: + members: [person_b, person_a, child] + state_code: NM + output: + nm_eitc_demographic_eligible: false + +- name: 2025 childless joint return with a spouse under 18 and nobody claimable is eligible by the other spouse's age (the younger spouse is the head) + period: 2025 + input: + people: + person_b: + age: 17 + is_tax_unit_head: true + is_tax_unit_spouse: false + person_a: + age: 21 + 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: NM + output: + nm_eitc_demographic_eligible: true diff --git a/policyengine_us/variables/gov/states/nm/tax/income/credits/eitc/nm_eitc_demographic_eligible.py b/policyengine_us/variables/gov/states/nm/tax/income/credits/eitc/nm_eitc_demographic_eligible.py index 64f34f0f447..903ac290010 100644 --- a/policyengine_us/variables/gov/states/nm/tax/income/credits/eitc/nm_eitc_demographic_eligible.py +++ b/policyengine_us/variables/gov/states/nm/tax/income/credits/eitc/nm_eitc_demographic_eligible.py @@ -12,18 +12,19 @@ def formula(tax_unit, period, parameters): # New Mexico applies the same criteria as the federal EITC, but # changes the minimum age. person = tax_unit.members - # A child under 18 who is not a filer, or an older qualifying child - # under IRC 32(c)(3) before the identification requirement that New - # Mexico does not apply: a dependent aged 18, a student under 24, or - # permanently and totally disabled. A filer under 18 is not their own - # or their spouse's qualifying child. + # A qualifying child under IRC 32(c)(3), before the identification + # requirement that New Mexico does not apply: a dependent under 19, a + # student under 24, or permanently and totally disabled. A filer is + # not their own or their spouse's qualifying child. For a child under + # 18 the count of children must also be positive, so a supplied count + # of zero still means no children. filer = person("is_tax_unit_head_or_spouse", period) + qualifying_child = person("is_eitc_qualifying_child", period) minor = person("is_child", period) minor_child = (tax_unit("tax_unit_children", period) > 0) & tax_unit.any( - minor & ~filer + qualifying_child & minor ) - older_qualifying_child = person("is_eitc_qualifying_child", period) & ~minor - has_child = minor_child | tax_unit.any(older_qualifying_child) + has_child = minor_child | tax_unit.any(qualifying_child & ~minor) age = person("age", period) # Relative parameter reference break branching in some states that # modify EITC age limits.