From 5a6ca04e3d2b0c4217e17f0aa25ff3fada01bda2 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sun, 11 Oct 2026 11:51:12 -0400 Subject: [PATCH 1/6] Leave tax refunds and the section 68 reduction out of AMTI 26 U.S.C. 56(b)(1)(C): no recovery of state and local taxes is included in AMTI (Form 6251 line 2b; 2017 line 7). 56(b)(1)(E): section 68 does not apply (2017 Form 6251 line 6 subtracts the reduction). Main started from taxable income, which includes the refund and is net of the section 68 reduction, without either adjustment. Colorado AMTI (DR 0104AMT) starts from federal AMTI and adds DR 0104 lines 3-7 and 9 and subtracts DR 0104AD subtractions except the state income tax refund. Main added the line 2 state income tax addback and subtracted the refund, which offset the federal refund omission; both change together here. Co-Authored-By: Claude Opus 5.5 --- .../amti-section-68-and-tax-refunds.fixed.md | 1 + .../income/amt_income.yaml | 85 +++++++++++++++++++ ...co_alternative_minimum_taxable_income.yaml | 16 ++++ .../income/amt_income.py | 16 ++++ .../co_alternative_minimum_taxable_income.py | 17 +++- 5 files changed, 131 insertions(+), 4 deletions(-) create mode 100644 changelog.d/amti-section-68-and-tax-refunds.fixed.md diff --git a/changelog.d/amti-section-68-and-tax-refunds.fixed.md b/changelog.d/amti-section-68-and-tax-refunds.fixed.md new file mode 100644 index 00000000000..fb309349410 --- /dev/null +++ b/changelog.d/amti-section-68-and-tax-refunds.fixed.md @@ -0,0 +1 @@ +Leave state and local tax refunds and the section 68 itemized deduction reduction out of federal alternative minimum taxable income, and leave Colorado's state income tax addback and refund subtraction out of Colorado alternative minimum taxable income. diff --git a/policyengine_us/tests/policy/baseline/gov/irs/tax/federal_income/alternative_minimum_tax/income/amt_income.yaml b/policyengine_us/tests/policy/baseline/gov/irs/tax/federal_income/alternative_minimum_tax/income/amt_income.yaml index 6543111b8d2..15ed9bbe782 100644 --- a/policyengine_us/tests/policy/baseline/gov/irs/tax/federal_income/alternative_minimum_tax/income/amt_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/irs/tax/federal_income/alternative_minimum_tax/income/amt_income.yaml @@ -161,3 +161,88 @@ # The senior deduction is not in line 14 and is not added back, so # line 4 is AGI for a filer who takes the standard deduction. amt_income: 100_000 + +# 26 U.S.C. 56(b)(1)(C); 2025 Form 6251 line 2b: refunds of state and local +# taxes included in income are subtracted. +- name: Single itemizer subtracts a state income tax refund, 2025 + absolute_error_margin: 0.01 + period: 2025 + input: + tax_unit_itemizes: true + taxable_income: 100_000 + salt_deduction: 8_000 + salt_refund_income: 2_000 + filing_status: SINGLE + output: + # 100,000 + 8,000 - 2,000 + amt_income: 106_000 + +# 26 U.S.C. 56(b)(1)(E): section 68 does not apply, so the itemized deduction +# reduction in taxable income comes back out. +- name: Single itemizer reverses the section 68 reduction, 2026 + absolute_error_margin: 0.01 + period: 2026 + input: + tax_unit_itemizes: true + taxable_income: 1_000_000 + salt_deduction: 10_000 + itemized_taxable_income_deductions_reduction: 5_000 + filing_status: SINGLE + output: + # 1,000,000 + 10,000 - 5,000 + amt_income: 1_005_000 + +- name: Non-itemizer has no section 68 reduction to reverse, 2026 + absolute_error_margin: 0.01 + period: 2026 + input: + tax_unit_itemizes: false + taxable_income: 50_000 + standard_deduction: 1_000 + itemized_taxable_income_deductions_reduction: 5_000 + filing_status: SINGLE + output: + amt_income: 51_000 + +# 2017 Form 6251 line 6 enters line 9 of the Schedule A Itemized Deductions +# Worksheet (the section 68 reduction) as a negative amount. +- name: Single itemizer reverses the 2017 overall limitation on itemized deductions + absolute_error_margin: 0.01 + period: 2017 + input: + tax_unit_itemizes: true + taxable_income: 300_000 + exemptions: 4_050 + salt_deduction: 20_000 + misc_deduction: 0 + itemized_taxable_income_deductions_reduction: 4_155 + filing_status: SINGLE + output: + # 300,000 + 4,050 + 20,000 - 4,155 + amt_income: 319_895 + +- name: A dependent's state tax refund is not subtracted from the filer's AMTI, 2025 + absolute_error_margin: 0.01 + period: 2025 + input: + people: + person1: + age: 45 + salt_refund_income: 1_000 + person2: + age: 17 + is_tax_unit_dependent: true + salt_refund_income: 500 + tax_units: + tax_unit: + members: [person1, person2] + tax_unit_itemizes: true + taxable_income: 100_000 + salt_deduction: 8_000 + filing_status: HEAD_OF_HOUSEHOLD + households: + household: + members: [person1, person2] + output: + # 100,000 + 8,000 - 1,000 + amt_income: 107_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/co/tax/income/amt/co_alternative_minimum_taxable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/co/tax/income/amt/co_alternative_minimum_taxable_income.yaml index 35a377bc3f2..809ac870211 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/co/tax/income/amt/co_alternative_minimum_taxable_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/co/tax/income/amt/co_alternative_minimum_taxable_income.yaml @@ -31,3 +31,19 @@ output: # max(0, 0 + 0 - 50,000) = 0 co_alternative_minimum_taxable_income: 0 + +# DR 0104AMT (2025): line 2 sums DR 0104 lines 3 through 7 and 9, leaving out +# the state income tax addback on line 2; line 4 sums the DR 0104AD +# subtractions excluding the state income tax refund on line 1. +- name: CO AMTI leaves out the state income tax addback and the refund subtraction + period: 2025 + input: + amt_income_less_exemptions: 200_000 + co_additions: 10_000 + co_state_addback: 6_000 + co_subtractions: 5_000 + salt_refund_income: 1_500 + state_code: CO + output: + # 200,000 + (10,000 - 6,000) - (5,000 - 1,500) + co_alternative_minimum_taxable_income: 200_500 diff --git a/policyengine_us/variables/gov/irs/tax/federal_income/alternative_minimum_tax/income/amt_income.py b/policyengine_us/variables/gov/irs/tax/federal_income/alternative_minimum_tax/income/amt_income.py index 5c488f3054b..6882c72bf01 100644 --- a/policyengine_us/variables/gov/irs/tax/federal_income/alternative_minimum_tax/income/amt_income.py +++ b/policyengine_us/variables/gov/irs/tax/federal_income/alternative_minimum_tax/income/amt_income.py @@ -13,6 +13,9 @@ class amt_income(Variable): "https://www.irs.gov/pub/irs-prior/f6251--2024.pdf#page=1", "https://www.irs.gov/pub/irs-prior/f6251--2025.pdf#page=1", "https://www.irs.gov/pub/irs-prior/i6251--2025.pdf#page=2", + # 2017 Form 6251 lines 6 and 7, and instructions (PDF pages 2-3). + "https://www.irs.gov/pub/irs-prior/f6251--2017.pdf#page=1", + "https://www.irs.gov/pub/irs-prior/i6251--2017.pdf#page=2", ) def formula(tax_unit, period, parameters): @@ -36,6 +39,17 @@ def formula(tax_unit, period, parameters): deductions_add_back = ( add(tax_unit, period, p.deductions_add_back) if p.deductions_add_back else 0 ) + # 2025 line 2b (2017 line 7): refunds of state and local taxes in + # income are not AMTI (26 U.S.C. 56(b)(1)(C)). Dependents' refunds are + # on their own returns, as irs_gross_income treats them. + tax_refunds = tax_unit_non_dep_add(tax_unit, period, ["salt_refund_income"]) + # Section 68 does not apply to AMTI (26 U.S.C. 56(b)(1)(E)), so the + # itemized deduction reduction in line 1 comes back out (2017 line 6). + section_68_reduction = where( + tax_unit("tax_unit_itemizes", period), + tax_unit("itemized_taxable_income_deductions_reduction", period), + 0, + ) return ( line_1 + deductions_add_back @@ -44,4 +58,6 @@ def formula(tax_unit, period, parameters): period, ["amt_excluded_deductions", "amt_separate_addition"], ) + - tax_refunds + - section_68_reduction ) diff --git a/policyengine_us/variables/gov/states/co/tax/income/amt/co_alternative_minimum_taxable_income.py b/policyengine_us/variables/gov/states/co/tax/income/amt/co_alternative_minimum_taxable_income.py index 99a985d0093..83094b51cad 100644 --- a/policyengine_us/variables/gov/states/co/tax/income/amt/co_alternative_minimum_taxable_income.py +++ b/policyengine_us/variables/gov/states/co/tax/income/amt/co_alternative_minimum_taxable_income.py @@ -11,6 +11,7 @@ class co_alternative_minimum_taxable_income(Variable): reference = [ "https://tax.colorado.gov/DR0104AMT", "https://law.justia.com/codes/colorado/2022/title-39/article-22/part-1/section-39-22-105/", + "https://tax.colorado.gov/sites/tax/files/documents/DR0104AMT_2025.pdf#page=1", ] def formula(tax_unit, period, parameters): @@ -19,10 +20,18 @@ def formula(tax_unit, period, parameters): federal_amt_income_less_exemptions = tax_unit( "amt_income_less_exemptions", period ) - # Line 2: Colorado additions (from DR 0104, lines 3-8) - co_additions = tax_unit("co_additions", period) - # Line 4: Colorado subtractions (excluding state income tax refund) - co_subtractions = tax_unit("co_subtractions", period) + # Line 2: Colorado additions from DR 0104, lines 3 through 7 and 9. The + # state income tax addback (DR 0104 line 2) is left out because federal + # alternative minimum taxable income never deducted those taxes. + co_additions = tax_unit("co_additions", period) - tax_unit( + "co_state_addback", period + ) + # Line 4: Colorado subtractions excluding the state income tax refund + # (DR 0104AD line 1), which federal alternative minimum taxable income + # already leaves out. + co_subtractions = tax_unit("co_subtractions", period) - add( + tax_unit, period, ["salt_refund_income"] + ) # Line 5: Colorado AMTI return max_( 0, From b55c3ea3feabb48ab822beee2bee1827ca176bb7 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sun, 11 Oct 2026 12:01:08 -0400 Subject: [PATCH 2/6] Add an invariant: a state tax refund leaves AMTI unchanged With itemization fixed and no AGI-dependent deductions, a refund enters AGI and is subtracted back, and the section 68 and SALT-cap changes it causes cancel. Checked with Hypothesis for 2017, 2025 and 2026. Co-Authored-By: Claude Opus 5.5 --- ...income_refund_and_section_68_invariants.py | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 policyengine_us/tests/core/test_amt_income_refund_and_section_68_invariants.py diff --git a/policyengine_us/tests/core/test_amt_income_refund_and_section_68_invariants.py b/policyengine_us/tests/core/test_amt_income_refund_and_section_68_invariants.py new file mode 100644 index 00000000000..c157ef466eb --- /dev/null +++ b/policyengine_us/tests/core/test_amt_income_refund_and_section_68_invariants.py @@ -0,0 +1,84 @@ +"""Alternative minimum taxable income leaves out tax refunds and section 68. + +26 U.S.C. 56(b)(1)(C): no recovery of state or local taxes is in alternative +minimum taxable income (Form 6251 line 2b). 56(b)(1)(E): section 68 does not +apply. With the itemization choice fixed and no deductions that depend on AGI +(no medical expenses, charity well under its AGI limits), adding a state tax +refund to a filer's income must leave AMTI unchanged in every year: the refund +enters AGI and is subtracted back, and any change it causes in the section 68 +reduction or the capped SALT deduction cancels because AMTI reverses the +first and adds back the second. + +Each Hypothesis example evaluates a batch of tax units and their twins +without the refund in one vectorized simulation, in a state with no income tax. +""" + +import numpy as np +import pytest +from hypothesis import HealthCheck, given, settings +from hypothesis import strategies as st + +from policyengine_us import Simulation + +TOLERANCE = 0.01 + + +@st.composite +def tax_unit(draw): + earnings = draw(st.integers(20_000, 3_000_000)) + return { + "joint": draw(st.booleans()), + "itemizes": draw(st.booleans()), + "employment_income": earnings, + "salt_refund_income": draw(st.integers(1, 20_000)), + "real_estate_taxes": draw(st.integers(0, 40_000)), + "home_mortgage_interest": draw(st.integers(0, 40_000)), + # Under 10% of earnings keeps charity below every AGI limit. + "charitable_cash_donations": draw(st.integers(0, earnings // 10)), + } + + +def _amt_income(units, year): + situation = {"people": {}, "tax_units": {}, "households": {}} + for twin in (0, 1): + for i, unit in enumerate(units): + head = f"head_{twin}_{i}" + members = [head] + situation["people"][head] = { + "age": {year: 45}, + "employment_income": {year: unit["employment_income"]}, + "salt_refund_income": { + year: unit["salt_refund_income"] if twin == 0 else 0 + }, + "real_estate_taxes": {year: unit["real_estate_taxes"]}, + "home_mortgage_interest": {year: unit["home_mortgage_interest"]}, + "charitable_cash_donations": {year: unit["charitable_cash_donations"]}, + } + if unit["joint"]: + spouse = f"spouse_{twin}_{i}" + situation["people"][spouse] = {"age": {year: 45}} + members.append(spouse) + situation["tax_units"][f"unit_{twin}_{i}"] = { + "members": members, + "tax_unit_itemizes": {year: unit["itemizes"]}, + } + situation["households"][f"household_{twin}_{i}"] = { + "members": members, + "state_code": {year: "TX"}, + } + simulation = Simulation(situation=situation) + amti = np.asarray(simulation.calculate("amt_income", year), dtype=float) + return amti[: len(units)], amti[len(units) :] + + +@pytest.mark.parametrize("year", [2017, 2025, 2026]) +@settings( + max_examples=4, + deadline=None, + derandomize=True, + suppress_health_check=[HealthCheck.too_slow, HealthCheck.data_too_large], +) +@given(units=st.lists(tax_unit(), min_size=8, max_size=8)) +def test_state_tax_refund_does_not_change_amt_income(year, units): + with_refund, without_refund = _amt_income(units, year) + np.testing.assert_allclose(with_refund, without_refund, atol=TOLERANCE) From 3a7ce22baaadb64d0f6d6c8d88c1f154ed029e3d Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 2 Nov 2026 23:47:48 +0000 Subject: [PATCH 3/6] Test AMTI end to end and against the statute's definition Drop charitable gifts from the property test's draws: from 2026 the 0.5% floor of 26 U.S.C. 170(b)(1)(I) ties the charitable deduction to AGI, so a refund rightly raises AMTI by 0.5% of it. Hypothesis found that on the merged branch ( refund, +/bin/bash.02). Add a second property on the same simulations, that AMTI is AGI less the refund less the itemized deductions the AMT allows, and two YAML cases that compute AMTI from wages for a 2025 refund and the 2026 section 68 reduction. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01WR8LHahgdvZhtnGRY21L5Y --- ...income_refund_and_section_68_invariants.py | 73 +++++++++++++------ .../income/amt_income.yaml | 69 ++++++++++++++++++ 2 files changed, 119 insertions(+), 23 deletions(-) diff --git a/policyengine_us/tests/core/test_amt_income_refund_and_section_68_invariants.py b/policyengine_us/tests/core/test_amt_income_refund_and_section_68_invariants.py index c157ef466eb..224e309ab43 100644 --- a/policyengine_us/tests/core/test_amt_income_refund_and_section_68_invariants.py +++ b/policyengine_us/tests/core/test_amt_income_refund_and_section_68_invariants.py @@ -1,16 +1,26 @@ """Alternative minimum taxable income leaves out tax refunds and section 68. -26 U.S.C. 56(b)(1)(C): no recovery of state or local taxes is in alternative +26 U.S.C. 56(b)(1)(C): no recovery of a state or local tax is in alternative minimum taxable income (Form 6251 line 2b). 56(b)(1)(E): section 68 does not -apply. With the itemization choice fixed and no deductions that depend on AGI -(no medical expenses, charity well under its AGI limits), adding a state tax -refund to a filer's income must leave AMTI unchanged in every year: the refund -enters AGI and is subtracted back, and any change it causes in the section 68 -reduction or the capped SALT deduction cancels because AMTI reverses the -first and adds back the second. - -Each Hypothesis example evaluates a batch of tax units and their twins -without the refund in one vectorized simulation, in a state with no income tax. +apply. Each Hypothesis example evaluates a batch of tax units, and their twins +without the refund, in one vectorized simulation in a state with no income +tax. With the itemization choice fixed, the households have no deduction that +depends on AGI once the AMT add-backs are made: no medical expenses and no +charitable gifts. From 2026 the 0.5% floor of 26 U.S.C. 170(b)(1)(I) ties the +charitable deduction to AGI, so a refund rightly raises AMTI by 0.5% of it. + +Two properties, for 2017 (the old section 68), 2025 (no section 68) and 2026 +(the P.L. 119-21 section 68), single and joint, itemizing or not: + +1. Refund invariance: adding a filer's state tax refund leaves AMTI unchanged. + The refund enters AGI and comes back out, and any change it causes in the + section 68 reduction or the capped SALT deduction cancels, because AMTI + reverses the first and adds back the second. +2. Statutory identity: AMTI is AGI, less the refund, less the itemized + deductions the AMT allows. Those are all itemized deductions before section + 68 except taxes and miscellaneous deductions (56(b)(1)(A)), and none for a + filer who takes the standard deduction (56(b)(1)(D)). This checks the + formula's route through taxable income against the statute's definition. """ import numpy as np @@ -20,25 +30,23 @@ from policyengine_us import Simulation -TOLERANCE = 0.01 +# The model computes in float32: allow about two units in the last place. +TOLERANCE = dict(atol=0.01, rtol=2.5e-7) @st.composite def tax_unit(draw): - earnings = draw(st.integers(20_000, 3_000_000)) return { "joint": draw(st.booleans()), "itemizes": draw(st.booleans()), - "employment_income": earnings, + "employment_income": draw(st.integers(20_000, 3_000_000)), "salt_refund_income": draw(st.integers(1, 20_000)), "real_estate_taxes": draw(st.integers(0, 40_000)), "home_mortgage_interest": draw(st.integers(0, 40_000)), - # Under 10% of earnings keeps charity below every AGI limit. - "charitable_cash_donations": draw(st.integers(0, earnings // 10)), } -def _amt_income(units, year): +def _simulate(units, year): situation = {"people": {}, "tax_units": {}, "households": {}} for twin in (0, 1): for i, unit in enumerate(units): @@ -52,7 +60,6 @@ def _amt_income(units, year): }, "real_estate_taxes": {year: unit["real_estate_taxes"]}, "home_mortgage_interest": {year: unit["home_mortgage_interest"]}, - "charitable_cash_donations": {year: unit["charitable_cash_donations"]}, } if unit["joint"]: spouse = f"spouse_{twin}_{i}" @@ -66,9 +73,7 @@ def _amt_income(units, year): "members": members, "state_code": {year: "TX"}, } - simulation = Simulation(situation=situation) - amti = np.asarray(simulation.calculate("amt_income", year), dtype=float) - return amti[: len(units)], amti[len(units) :] + return Simulation(situation=situation) @pytest.mark.parametrize("year", [2017, 2025, 2026]) @@ -79,6 +84,28 @@ def _amt_income(units, year): suppress_health_check=[HealthCheck.too_slow, HealthCheck.data_too_large], ) @given(units=st.lists(tax_unit(), min_size=8, max_size=8)) -def test_state_tax_refund_does_not_change_amt_income(year, units): - with_refund, without_refund = _amt_income(units, year) - np.testing.assert_allclose(with_refund, without_refund, atol=TOLERANCE) +def test_amt_income_leaves_out_refunds_and_section_68(year, units): + simulation = _simulate(units, year) + + def calc(variable): + return np.asarray(simulation.calculate(variable, year), dtype=float) + + n = len(units) + amti = calc("amt_income") + + # 1. Refund invariance: each unit matches its twin without the refund. + np.testing.assert_allclose(amti[:n], amti[n:], **TOLERANCE) + + # 2. Statutory identity: AGI less the refund less the AMT's itemized + # deductions (before section 68, without taxes and miscellaneous ones). + refunds = np.array([unit["salt_refund_income"] for unit in units] + [0] * n) + allowed_itemized = np.where( + calc("tax_unit_itemizes").astype(bool), + calc("total_itemized_taxable_income_deductions") + - calc("salt_deduction") + - calc("misc_deduction"), + 0, + ) + np.testing.assert_allclose( + amti, calc("adjusted_gross_income") - refunds - allowed_itemized, **TOLERANCE + ) diff --git a/policyengine_us/tests/policy/baseline/gov/irs/tax/federal_income/alternative_minimum_tax/income/amt_income.yaml b/policyengine_us/tests/policy/baseline/gov/irs/tax/federal_income/alternative_minimum_tax/income/amt_income.yaml index 15ed9bbe782..bec5be84bcf 100644 --- a/policyengine_us/tests/policy/baseline/gov/irs/tax/federal_income/alternative_minimum_tax/income/amt_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/irs/tax/federal_income/alternative_minimum_tax/income/amt_income.yaml @@ -246,3 +246,72 @@ output: # 100,000 + 8,000 - 1,000 amt_income: 107_000 + +# End to end from wages, with the refund in AGI. 26 U.S.C. 56(b)(1)(C); 2025 +# Form 6251 line 2b. Sales taxes are set to zero so the SALT deduction is the +# real estate taxes, under the 2025 cap. +- name: Single itemizer's refund enters AGI and comes back out of AMTI, 2025 + absolute_error_margin: 0.01 + period: 2025 + input: + people: + person1: + age: 45 + employment_income: 100_000 + salt_refund_income: 2_000 + real_estate_taxes: 8_000 + home_mortgage_interest: 20_000 + tax_units: + tax_unit: + members: [person1] + tax_unit_itemizes: true + state_sales_tax: 0 + local_sales_tax: 0 + households: + household: + members: [person1] + state_code: TX + output: + # AGI 102,000; itemized deductions 8,000 + 20,000 = 28,000. + taxable_income: 74_000 + # Line 1b 74,000 + line 2a 8,000 - line 2b 2,000 = 80,000, which is AGI + # less the refund less the AMT's itemized deductions (102,000 - 2,000 - + # 20,000). + amt_income: 80_000 + +# End to end from wages, with the model's own 2026 section 68 reduction. +# 26 U.S.C. 56(b)(1)(E): section 68 does not apply. +- name: Single itemizer's section 68 reduction stays out of AMTI, 2026 + absolute_error_margin: 0.01 + period: 2026 + input: + people: + person1: + age: 45 + employment_income: 1_000_000 + real_estate_taxes: 10_000 + home_mortgage_interest: 30_000 + tax_units: + tax_unit: + members: [person1] + tax_unit_itemizes: true + state_sales_tax: 0 + local_sales_tax: 0 + households: + household: + members: [person1] + state_code: TX + output: + # 26 U.S.C. 164(b)(7): the 2026 SALT cap of 40,400 phases down by 30% of + # MAGI over 505,000 to its 10,000 floor at this income. + salt_deduction: 10_000 + total_itemized_taxable_income_deductions: 40_000 + # Section 68 as amended by P.L. 119-21: 2/37 of the lesser of the itemized + # deductions (40,000) and taxable income over the 37% bracket threshold + # (1,000,000 - 640,600 = 359,400): 80,000 / 37. + itemized_taxable_income_deductions_reduction: 2_162.16 + # 1,000,000 - (40,000 - 2,162.16) + taxable_income: 962_162.16 + # 962,162.16 + 10,000 SALT - 2,162.16 = 970,000, which is AGI less the + # AMT's itemized deductions (1,000,000 - 30,000). + amt_income: 970_000 From ffc09cdc0cd7589e309813d90b8620427fadbb74 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 3 Nov 2026 00:09:57 +0000 Subject: [PATCH 4/6] Cite the 2017 Form 6251 and DR 0104 pages the AMTI lines use The 2017 instructions put lines 6 and 7 on PDF pages 2 and 3, and the 2025 DR 0104 numbers the Colorado additions that DR 0104AMT line 2 sums. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01WR8LHahgdvZhtnGRY21L5Y --- .../alternative_minimum_tax/income/amt_income.py | 3 ++- .../tax/income/amt/co_alternative_minimum_taxable_income.py | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/policyengine_us/variables/gov/irs/tax/federal_income/alternative_minimum_tax/income/amt_income.py b/policyengine_us/variables/gov/irs/tax/federal_income/alternative_minimum_tax/income/amt_income.py index 6882c72bf01..e697492e86a 100644 --- a/policyengine_us/variables/gov/irs/tax/federal_income/alternative_minimum_tax/income/amt_income.py +++ b/policyengine_us/variables/gov/irs/tax/federal_income/alternative_minimum_tax/income/amt_income.py @@ -13,8 +13,9 @@ class amt_income(Variable): "https://www.irs.gov/pub/irs-prior/f6251--2024.pdf#page=1", "https://www.irs.gov/pub/irs-prior/f6251--2025.pdf#page=1", "https://www.irs.gov/pub/irs-prior/i6251--2025.pdf#page=2", - # 2017 Form 6251 lines 6 and 7, and instructions (PDF pages 2-3). + # 2017 Form 6251 lines 6 and 7, and their instructions. "https://www.irs.gov/pub/irs-prior/f6251--2017.pdf#page=1", + # PDF pages 2-3 "https://www.irs.gov/pub/irs-prior/i6251--2017.pdf#page=2", ) diff --git a/policyengine_us/variables/gov/states/co/tax/income/amt/co_alternative_minimum_taxable_income.py b/policyengine_us/variables/gov/states/co/tax/income/amt/co_alternative_minimum_taxable_income.py index 83094b51cad..0b69da459d5 100644 --- a/policyengine_us/variables/gov/states/co/tax/income/amt/co_alternative_minimum_taxable_income.py +++ b/policyengine_us/variables/gov/states/co/tax/income/amt/co_alternative_minimum_taxable_income.py @@ -11,7 +11,11 @@ class co_alternative_minimum_taxable_income(Variable): reference = [ "https://tax.colorado.gov/DR0104AMT", "https://law.justia.com/codes/colorado/2022/title-39/article-22/part-1/section-39-22-105/", + # 2025 DR 0104AMT instructions and computation schedule + # PDF pages 1, 3 "https://tax.colorado.gov/sites/tax/files/documents/DR0104AMT_2025.pdf#page=1", + # 2025 DR 0104 lines 2 through 9 + "https://tax.colorado.gov/sites/tax/files/documents/DR0104_2025.pdf#page=3", ] def formula(tax_unit, period, parameters): From 95ce584900a0a383ea46cb9d1fa348db977ace35 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 3 Nov 2026 00:25:53 +0000 Subject: [PATCH 5/6] Figure the separate filer AMTI increase and Colorado line 1 as the law does 26 U.S.C. 55(d)(2) figures a married separate filer's increase on AMTI determined without that increase, so it now uses amt_income_before_separate_addition, which carries the refund and section 68 lines; before, the refund and the reduction still raised the increase. DR 0104AMT line 1 enters Form 6251 line 4 less line 5 as a negative amount when the exemption is larger, and line 4 cannot go below zero, so the PR's line 2 and line 4 changes no longer create a Colorado AMT on a refund. The AMTI refund line now subtracts what irs_gross_income put in AGI, each filer's refund floored at zero. The 2017 test case now uses a zero exemption, which a 4,155 section 68 reduction implies. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01WR8LHahgdvZhtnGRY21L5Y --- ...income_refund_and_section_68_invariants.py | 31 +++++--- .../income/amt_income.yaml | 45 +++++++++++- ...co_alternative_minimum_taxable_income.yaml | 47 ++++++++++++ .../income/amt_income.py | 62 +++------------- .../amt_income_before_separate_addition.py | 73 +++++++++++++++++++ .../income/amt_separate_addition.py | 14 +++- .../co_alternative_minimum_taxable_income.py | 49 ++++++++----- 7 files changed, 230 insertions(+), 91 deletions(-) create mode 100644 policyengine_us/variables/gov/irs/tax/federal_income/alternative_minimum_tax/income/amt_income_before_separate_addition.py diff --git a/policyengine_us/tests/core/test_amt_income_refund_and_section_68_invariants.py b/policyengine_us/tests/core/test_amt_income_refund_and_section_68_invariants.py index 224e309ab43..a50310fd1f8 100644 --- a/policyengine_us/tests/core/test_amt_income_refund_and_section_68_invariants.py +++ b/policyengine_us/tests/core/test_amt_income_refund_and_section_68_invariants.py @@ -10,17 +10,20 @@ charitable deduction to AGI, so a refund rightly raises AMTI by 0.5% of it. Two properties, for 2017 (the old section 68), 2025 (no section 68) and 2026 -(the P.L. 119-21 section 68), single and joint, itemizing or not: +(the P.L. 119-21 section 68), single, joint and married filing separately, +itemizing or not: 1. Refund invariance: adding a filer's state tax refund leaves AMTI unchanged. The refund enters AGI and comes back out, and any change it causes in the section 68 reduction or the capped SALT deduction cancels, because AMTI - reverses the first and adds back the second. -2. Statutory identity: AMTI is AGI, less the refund, less the itemized - deductions the AMT allows. Those are all itemized deductions before section - 68 except taxes and miscellaneous deductions (56(b)(1)(A)), and none for a - filer who takes the standard deduction (56(b)(1)(D)). This checks the - formula's route through taxable income against the statute's definition. + reverses the first and adds back the second. For a separate filer, the + 55(d)(2) increase is figured on AMTI without the refund, so it holds too. +2. Statutory identity: AMTI before that separate filer increase is AGI, less + the refund, less the itemized deductions the AMT allows. Those are all + itemized deductions before section 68 except taxes and miscellaneous + deductions (56(b)(1)(A)), and none for a filer who takes the standard + deduction (56(b)(1)(D)). This checks the formula's route through taxable + income against the statute's definition. """ import numpy as np @@ -37,7 +40,7 @@ @st.composite def tax_unit(draw): return { - "joint": draw(st.booleans()), + "status": draw(st.sampled_from(["SINGLE", "JOINT", "SEPARATE"])), "itemizes": draw(st.booleans()), "employment_income": draw(st.integers(20_000, 3_000_000)), "salt_refund_income": draw(st.integers(1, 20_000)), @@ -61,12 +64,13 @@ def _simulate(units, year): "real_estate_taxes": {year: unit["real_estate_taxes"]}, "home_mortgage_interest": {year: unit["home_mortgage_interest"]}, } - if unit["joint"]: + if unit["status"] == "JOINT": spouse = f"spouse_{twin}_{i}" situation["people"][spouse] = {"age": {year: 45}} members.append(spouse) situation["tax_units"][f"unit_{twin}_{i}"] = { "members": members, + "filing_status": {year: unit["status"]}, "tax_unit_itemizes": {year: unit["itemizes"]}, } situation["households"][f"household_{twin}_{i}"] = { @@ -96,8 +100,9 @@ def calc(variable): # 1. Refund invariance: each unit matches its twin without the refund. np.testing.assert_allclose(amti[:n], amti[n:], **TOLERANCE) - # 2. Statutory identity: AGI less the refund less the AMT's itemized - # deductions (before section 68, without taxes and miscellaneous ones). + # 2. Statutory identity, before the separate filer increase: AGI less the + # refund less the AMT's itemized deductions (before section 68, without + # taxes and miscellaneous ones). refunds = np.array([unit["salt_refund_income"] for unit in units] + [0] * n) allowed_itemized = np.where( calc("tax_unit_itemizes").astype(bool), @@ -107,5 +112,7 @@ def calc(variable): 0, ) np.testing.assert_allclose( - amti, calc("adjusted_gross_income") - refunds - allowed_itemized, **TOLERANCE + calc("amt_income_before_separate_addition"), + calc("adjusted_gross_income") - refunds - allowed_itemized, + **TOLERANCE, ) diff --git a/policyengine_us/tests/policy/baseline/gov/irs/tax/federal_income/alternative_minimum_tax/income/amt_income.yaml b/policyengine_us/tests/policy/baseline/gov/irs/tax/federal_income/alternative_minimum_tax/income/amt_income.yaml index bec5be84bcf..61bb8b7b561 100644 --- a/policyengine_us/tests/policy/baseline/gov/irs/tax/federal_income/alternative_minimum_tax/income/amt_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/irs/tax/federal_income/alternative_minimum_tax/income/amt_income.yaml @@ -205,21 +205,24 @@ amt_income: 51_000 # 2017 Form 6251 line 6 enters line 9 of the Schedule A Itemized Deductions -# Worksheet (the section 68 reduction) as a negative amount. +# Worksheet (the section 68 reduction) as a negative amount. 26 U.S.C. +# 56(b)(1)(F) then; (E) since P.L. 116-94. A 4,155 reduction is 3% of AGI over +# 261,500, so AGI is at least 400,000 and the personal exemption has phased +# out (it does above 384,000 for a single filer). - name: Single itemizer reverses the 2017 overall limitation on itemized deductions absolute_error_margin: 0.01 period: 2017 input: tax_unit_itemizes: true taxable_income: 300_000 - exemptions: 4_050 + exemptions: 0 salt_deduction: 20_000 misc_deduction: 0 itemized_taxable_income_deductions_reduction: 4_155 filing_status: SINGLE output: - # 300,000 + 4,050 + 20,000 - 4,155 - amt_income: 319_895 + # 300,000 + 20,000 - 4,155 + amt_income: 315_845 - name: A dependent's state tax refund is not subtracted from the filer's AMTI, 2025 absolute_error_margin: 0.01 @@ -315,3 +318,37 @@ # 962,162.16 + 10,000 SALT - 2,162.16 = 970,000, which is AGI less the # AMT's itemized deductions (1,000,000 - 30,000). amt_income: 970_000 + +# 26 U.S.C. 55(d)(2): a married individual filing separately adds the lesser +# of 25% of AMTI "determined without regard to this sentence" over the amount +# at which the exemption is zero, and the exemption. 2025 Form 6251 +# instructions, line 4: 25% of line 4 over 900,350. Line 4 here is already net +# of the refund (line 2b). +- name: Separate filer's additional amount is figured after the refund, 2025 + absolute_error_margin: 0.01 + period: 2025 + input: + people: + person1: + age: 45 + employment_income: 1_000_000 + salt_refund_income: 20_000 + real_estate_taxes: 10_000 + tax_units: + tax_unit: + members: [person1] + filing_status: SEPARATE + tax_unit_itemizes: true + state_sales_tax: 0 + local_sales_tax: 0 + households: + household: + members: [person1] + state_code: TX + output: + # AGI 1,020,000, less the 20,000 refund; the only itemized deduction is + # the SALT deduction, which line 2a adds back. + amt_income_before_separate_addition: 1_000_000 + # min(68,500 exemption, 25% x (1,000,000 - 900,350)) + amt_separate_addition: 24_912.5 + amt_income: 1_024_912.5 diff --git a/policyengine_us/tests/policy/baseline/gov/states/co/tax/income/amt/co_alternative_minimum_taxable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/co/tax/income/amt/co_alternative_minimum_taxable_income.yaml index 809ac870211..4e284da7d07 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/co/tax/income/amt/co_alternative_minimum_taxable_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/co/tax/income/amt/co_alternative_minimum_taxable_income.yaml @@ -13,6 +13,10 @@ - name: CO AMTI with no federal AMT income period: 2024 input: + # Form 6251 line 4 equals the line 5 exemption, so line 6 and DR 0104AMT + # line 1 are zero. A line 4 below line 5 would enter as a negative amount. + amt_income: 85_700 + amt_exemption: 85_700 amt_income_less_exemptions: 0 co_additions: 10_000 co_subtractions: 5_000 @@ -47,3 +51,46 @@ output: # 200,000 + (10,000 - 6,000) - (5,000 - 1,500) co_alternative_minimum_taxable_income: 200_500 + +# DR 0104AMT line 4 takes the DR 0104AD subtractions without the refund; it +# cannot go below zero, so the refund never adds to Colorado AMTI. +- name: CO AMTI line 4 without the refund does not go below zero + period: 2025 + input: + amt_income_less_exemptions: 200_000 + co_additions: 0 + co_state_addback: 0 + co_subtractions: 500 + salt_refund_income: 1_500 + state_code: CO + output: + # 200,000 + 0 - max(0, 500 - 1,500) + co_alternative_minimum_taxable_income: 200_000 + +# DR 0104AMT line 1: "If line 5 on form 6251 is larger than line 4 on form +# 6251, subtract line 5 from line 4 and enter the resulting negative amount +# here." C.R.S. 39-22-105(2)(a) has no floor before the modifications. +- name: A negative DR 0104AMT line 1 offsets Colorado additions + period: 2025 + input: + people: + person1: + age: 40 + salt_refund_income: 15_000 + tax_units: + tax_unit: + members: [person1] + # Non-Colorado municipal bond interest (DR 0104 line 9). + co_other_additions: 15_000 + households: + household: + members: [person1] + state_code: CO + output: + # Federal: AGI 15,000; line 1b 15,000 - 15,750 = -750; line 2a 15,750; + # line 2b -15,000; line 4 = 0. Line 5 exemption 88,100. + amt_income: 0 + # Line 1: 0 - 88,100. Line 2: 15,000. Line 4: 15,000 - 15,000 refund. + # Line 5: -88,100 + 15,000 - 0 < 0. + co_alternative_minimum_taxable_income: 0 + co_amt: 0 diff --git a/policyengine_us/variables/gov/irs/tax/federal_income/alternative_minimum_tax/income/amt_income.py b/policyengine_us/variables/gov/irs/tax/federal_income/alternative_minimum_tax/income/amt_income.py index e697492e86a..267c7b0f3c4 100644 --- a/policyengine_us/variables/gov/irs/tax/federal_income/alternative_minimum_tax/income/amt_income.py +++ b/policyengine_us/variables/gov/irs/tax/federal_income/alternative_minimum_tax/income/amt_income.py @@ -7,58 +7,16 @@ class amt_income(Variable): definition_period = YEAR label = "AMT taxable income" unit = USD + documentation = ( + "Alternative minimum taxable income, Form 6251 line 4: taxable income " + "with the section 56 adjustments, plus the increase for a married " + "individual filing a separate return." + ) reference = ( - "https://www.law.cornell.edu/uscode/text/26/56", - # Form 6251 line 1 keeps a negative amount when taxable income is zero - "https://www.irs.gov/pub/irs-prior/f6251--2024.pdf#page=1", + "https://www.law.cornell.edu/uscode/text/26/55#b_2", + "https://www.law.cornell.edu/uscode/text/26/55#d_2", "https://www.irs.gov/pub/irs-prior/f6251--2025.pdf#page=1", - "https://www.irs.gov/pub/irs-prior/i6251--2025.pdf#page=2", - # 2017 Form 6251 lines 6 and 7, and their instructions. - "https://www.irs.gov/pub/irs-prior/f6251--2017.pdf#page=1", - # PDF pages 2-3 - "https://www.irs.gov/pub/irs-prior/i6251--2017.pdf#page=2", + # Line 4, married filing separately + "https://www.irs.gov/pub/irs-prior/i6251--2025.pdf#page=9", ) - - def formula(tax_unit, period, parameters): - p = parameters(period).gov.irs.income.amt - # Form 6251 line 1: Form 1040 line 15 if more than zero. If line 15 - # is zero, line 11 minus line 14, entered as a negative amount if - # less than zero. Before 2018 the personal exemptions were not - # subtracted, which taxable income plus exemptions also gives. - taxable_income = tax_unit("taxable_income", period) - exemptions = tax_unit("exemptions", period) - agi = tax_unit("adjusted_gross_income", period) - deductions = tax_unit("taxable_income_deductions", period) - # From 2018 both branches equal agi - deductions; the taxable income - # branch only differs before 2018, when exemptions were subtracted. - line_1 = where( - taxable_income > 0, - taxable_income + exemptions, - agi - deductions, - ) - # 2025 line 1a: deductions in line 14 that are not taken for the AMT. - deductions_add_back = ( - add(tax_unit, period, p.deductions_add_back) if p.deductions_add_back else 0 - ) - # 2025 line 2b (2017 line 7): refunds of state and local taxes in - # income are not AMTI (26 U.S.C. 56(b)(1)(C)). Dependents' refunds are - # on their own returns, as irs_gross_income treats them. - tax_refunds = tax_unit_non_dep_add(tax_unit, period, ["salt_refund_income"]) - # Section 68 does not apply to AMTI (26 U.S.C. 56(b)(1)(E)), so the - # itemized deduction reduction in line 1 comes back out (2017 line 6). - section_68_reduction = where( - tax_unit("tax_unit_itemizes", period), - tax_unit("itemized_taxable_income_deductions_reduction", period), - 0, - ) - return ( - line_1 - + deductions_add_back - + add( - tax_unit, - period, - ["amt_excluded_deductions", "amt_separate_addition"], - ) - - tax_refunds - - section_68_reduction - ) + adds = ["amt_income_before_separate_addition", "amt_separate_addition"] diff --git a/policyengine_us/variables/gov/irs/tax/federal_income/alternative_minimum_tax/income/amt_income_before_separate_addition.py b/policyengine_us/variables/gov/irs/tax/federal_income/alternative_minimum_tax/income/amt_income_before_separate_addition.py new file mode 100644 index 00000000000..f3ca98bff46 --- /dev/null +++ b/policyengine_us/variables/gov/irs/tax/federal_income/alternative_minimum_tax/income/amt_income_before_separate_addition.py @@ -0,0 +1,73 @@ +from policyengine_us.model_api import * + + +class amt_income_before_separate_addition(Variable): + value_type = float + entity = TaxUnit + definition_period = YEAR + label = "AMT taxable income before the married filing separately addition" + unit = USD + documentation = ( + "Alternative minimum taxable income determined without the increase " + "26 U.S.C. 55(d)(2) makes for a married individual filing a separate " + "return, which is figured on this amount (Form 6251 line 4 before the " + "additional amount)." + ) + reference = ( + "https://www.law.cornell.edu/uscode/text/26/55#d_2", + "https://www.law.cornell.edu/uscode/text/26/56", + # Form 6251 line 1 keeps a negative amount when taxable income is zero + "https://www.irs.gov/pub/irs-prior/f6251--2024.pdf#page=1", + "https://www.irs.gov/pub/irs-prior/f6251--2025.pdf#page=1", + "https://www.irs.gov/pub/irs-prior/i6251--2025.pdf#page=2", + # 2017 Form 6251 lines 6 and 7, and their instructions. + "https://www.irs.gov/pub/irs-prior/f6251--2017.pdf#page=1", + # PDF pages 2-3 + "https://www.irs.gov/pub/irs-prior/i6251--2017.pdf#page=2", + ) + + def formula(tax_unit, period, parameters): + p = parameters(period).gov.irs.income.amt + # Form 6251 line 1: Form 1040 line 15 if more than zero. If line 15 + # is zero, line 11 minus line 14, entered as a negative amount if + # less than zero. Before 2018 the personal exemptions were not + # subtracted, which taxable income plus exemptions also gives. + taxable_income = tax_unit("taxable_income", period) + exemptions = tax_unit("exemptions", period) + agi = tax_unit("adjusted_gross_income", period) + deductions = tax_unit("taxable_income_deductions", period) + # From 2018 both branches equal agi - deductions; the taxable income + # branch only differs before 2018, when exemptions were subtracted. + line_1 = where( + taxable_income > 0, + taxable_income + exemptions, + agi - deductions, + ) + # 2025 line 1a: deductions in line 14 that are not taken for the AMT. + deductions_add_back = ( + add(tax_unit, period, p.deductions_add_back) if p.deductions_add_back else 0 + ) + # 2025 line 2b (2017 line 7): refunds of state and local taxes in + # income are not AMTI (26 U.S.C. 56(b)(1)(C), formerly (D)). Subtract + # what irs_gross_income put in AGI: each head's or spouse's refund, + # floored at zero. Dependents' refunds are on their own returns. + person = tax_unit.members + filer = ~person("is_tax_unit_dependent", period) + tax_refunds = tax_unit.sum( + filer * max_(0, person("salt_refund_income", period)) + ) + # Section 68 does not apply to AMTI (26 U.S.C. 56(b)(1)(E), formerly + # (F)), so the itemized deduction reduction in line 1 comes back out + # (2017 line 6). + section_68_reduction = where( + tax_unit("tax_unit_itemizes", period), + tax_unit("itemized_taxable_income_deductions_reduction", period), + 0, + ) + return ( + line_1 + + deductions_add_back + + tax_unit("amt_excluded_deductions", period) + - tax_refunds + - section_68_reduction + ) diff --git a/policyengine_us/variables/gov/irs/tax/federal_income/alternative_minimum_tax/income/amt_separate_addition.py b/policyengine_us/variables/gov/irs/tax/federal_income/alternative_minimum_tax/income/amt_separate_addition.py index 6349705b8bf..d6c147fca1c 100644 --- a/policyengine_us/variables/gov/irs/tax/federal_income/alternative_minimum_tax/income/amt_separate_addition.py +++ b/policyengine_us/variables/gov/irs/tax/federal_income/alternative_minimum_tax/income/amt_separate_addition.py @@ -7,12 +7,18 @@ class amt_separate_addition(Variable): definition_period = YEAR label = "AMT taxable income separate addition" unit = USD - reference = "https://www.law.cornell.edu/uscode/text/26/55#b_2" + reference = ( + "https://www.law.cornell.edu/uscode/text/26/55#d_2", + # Line 4, married filing separately + "https://www.irs.gov/pub/irs-prior/i6251--2025.pdf#page=9", + ) def formula(tax_unit, period, parameters): - taxable_income = tax_unit("taxable_income", period) - excluded_deductions = tax_unit("amt_excluded_deductions", period) - amt_inc = taxable_income + excluded_deductions + # 26 U.S.C. 55(d)(2) figures the increase on alternative minimum + # taxable income "determined without regard to this sentence", so + # with every other AMT adjustment, such as the refund and section 68 + # lines. + amt_inc = tax_unit("amt_income_before_separate_addition", period) p = parameters(period).gov.irs.income.amt.exemption filing_status = tax_unit("filing_status", period) separate = filing_status == filing_status.possible_values.SEPARATE diff --git a/policyengine_us/variables/gov/states/co/tax/income/amt/co_alternative_minimum_taxable_income.py b/policyengine_us/variables/gov/states/co/tax/income/amt/co_alternative_minimum_taxable_income.py index 0b69da459d5..ff20642f7be 100644 --- a/policyengine_us/variables/gov/states/co/tax/income/amt/co_alternative_minimum_taxable_income.py +++ b/policyengine_us/variables/gov/states/co/tax/income/amt/co_alternative_minimum_taxable_income.py @@ -11,6 +11,9 @@ class co_alternative_minimum_taxable_income(Variable): reference = [ "https://tax.colorado.gov/DR0104AMT", "https://law.justia.com/codes/colorado/2022/title-39/article-22/part-1/section-39-22-105/", + # C.R.S. 39-22-104(3)(d)(I), 39-22-104(4)(e) and 39-22-105(2)(a), + # Colorado Revised Statutes 2025. PDF pages 380, 386, 401 + "https://olls.info/crs/crs2025-title-39.pdf#page=380", # 2025 DR 0104AMT instructions and computation schedule # PDF pages 1, 3 "https://tax.colorado.gov/sites/tax/files/documents/DR0104AMT_2025.pdf#page=1", @@ -19,25 +22,33 @@ class co_alternative_minimum_taxable_income(Variable): ] def formula(tax_unit, period, parameters): - # DR 0104AMT calculation: - # Line 1: Federal Form 6251 line 6 (federal AMTI less exemption) - federal_amt_income_less_exemptions = tax_unit( - "amt_income_less_exemptions", period + # C.R.S. 39-22-105(2)(a) applies the 39-22-104 modifications to + # federal alternative minimum taxable income less the exemption. + # Measured against that base, the state income tax addback of + # 39-22-104(3)(d) ("an amount equal to the deduction claimed") is + # zero, since 26 U.S.C. 56(b)(1)(A)(ii) allows no such deduction, and + # the refund subtraction of 39-22-104(4)(e), whose stated purpose is + # "to avoid re-taxing" the refund, has nothing to offset, since 26 + # U.S.C. 56(b)(1)(C) already leaves the refund out. DR 0104AMT lines + # 2 and 4 leave out both. + # Line 1: Form 6251 line 6, or, when the exemption (line 5) exceeds + # alternative minimum taxable income (line 4) and line 6 is zero, + # line 4 less line 5 as a negative amount. + line_6 = tax_unit("amt_income_less_exemptions", period) + shortfall = min_( + 0, tax_unit("amt_income", period) - tax_unit("amt_exemption", period) ) - # Line 2: Colorado additions from DR 0104, lines 3 through 7 and 9. The - # state income tax addback (DR 0104 line 2) is left out because federal - # alternative minimum taxable income never deducted those taxes. - co_additions = tax_unit("co_additions", period) - tax_unit( - "co_state_addback", period - ) - # Line 4: Colorado subtractions excluding the state income tax refund - # (DR 0104AD line 1), which federal alternative minimum taxable income - # already leaves out. - co_subtractions = tax_unit("co_subtractions", period) - add( - tax_unit, period, ["salt_refund_income"] - ) - # Line 5: Colorado AMTI - return max_( + line_1 = where(line_6 > 0, line_6, shortfall) + # Line 2: Colorado additions from DR 0104, lines 3 through 7 and 9, + # leaving out the state income tax addback on DR 0104 line 2. + line_2 = tax_unit("co_additions", period) - tax_unit("co_state_addback", period) + # Line 4: the DR 0104AD subtractions excluding the state income tax + # refund (DR 0104AD line 1). co_subtractions is floored at zero, and + # so is this line, so the refund can never act as an addition. + line_4 = max_( 0, - federal_amt_income_less_exemptions + co_additions - co_subtractions, + tax_unit("co_subtractions", period) + - add(tax_unit, period, ["salt_refund_income"]), ) + # Line 5: Colorado alternative minimum taxable income. + return max_(0, line_1 + line_2 - line_4) From 75e37bd110ce561779af508b5d8471a1a827421b Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 3 Nov 2026 00:28:47 +0000 Subject: [PATCH 6/6] Describe the separate filer and Colorado line 1 fixes in the changelog Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01WR8LHahgdvZhtnGRY21L5Y --- changelog.d/amti-section-68-and-tax-refunds.fixed.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.d/amti-section-68-and-tax-refunds.fixed.md b/changelog.d/amti-section-68-and-tax-refunds.fixed.md index fb309349410..d0828c01912 100644 --- a/changelog.d/amti-section-68-and-tax-refunds.fixed.md +++ b/changelog.d/amti-section-68-and-tax-refunds.fixed.md @@ -1 +1 @@ -Leave state and local tax refunds and the section 68 itemized deduction reduction out of federal alternative minimum taxable income, and leave Colorado's state income tax addback and refund subtraction out of Colorado alternative minimum taxable income. +Leave state and local tax refunds and the section 68 itemized deduction reduction out of federal alternative minimum taxable income, including the married filing separately increase, and in Colorado alternative minimum taxable income leave out the state income tax addback and the refund subtraction and let a federal exemption larger than AMTI enter line 1 as a negative amount.