From 40d972fe62f503f0a08efcbd3625f09a66cb0d88 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sun, 8 Nov 2026 00:46:12 -0500 Subject: [PATCH 1/4] Let Utah military retirees claim the military retirement credit when no retirement credit applies ut_claims_retirement_credit returned True whenever the retirement credit (59-10-1019) was at least the Social Security benefits credit (59-10-1042), including when both were zero. Because ut_military_retirement_credit_eligible requires ~ut_claims_retirement_credit, every military retiree born after 1952 without a Social Security credit lost the military retirement credit (59-10-1043): a 45-year-old with $30,000 of military retired pay paid $1,350 too much Utah tax in 2025. 59-10-1019(3)(b) bars the retirement credit when a 1042 or 1043 credit is claimed, and 1042(3)(b) and 1043(3)(b) bar those credits only alongside 1019, so a filer chooses between the retirement credit alone and the other two together. The choice now compares the retirement credit with the sum of the Social Security and military retirement credits, and a retirement credit worth nothing is never claimed. A new ut_military_retirement_credit_max holds the unconditional amount so the comparison has no cycle. The credit rate is zero before 2021, when 59-10-1043 took effect. Co-Authored-By: Claude Opus 5.5 --- ...military-retirement-credit-choice.fixed.md | 1 + .../credits/military_retirement/rate.yaml | 2 + .../ut_military_retirement_credit.yaml | 42 +++++++++++++++++ .../ut_military_retirement_credit_max.yaml | 47 +++++++++++++++++++ .../ut_claims_retirement_credit.yaml | 32 ++++++++++++- .../ut_military_retirement_credit_max.py | 23 +++++++++ ...ut_military_retirement_credit_potential.py | 13 +---- .../ut_claims_retirement_credit.py | 30 ++++++++++-- 8 files changed, 173 insertions(+), 17 deletions(-) create mode 100644 changelog.d/fix-ut-military-retirement-credit-choice.fixed.md create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ut/tax/income/credits/military_retirement_credit/ut_military_retirement_credit_max.yaml create mode 100644 policyengine_us/variables/gov/states/ut/tax/income/credits/military_retirement_credit/ut_military_retirement_credit_max.py diff --git a/changelog.d/fix-ut-military-retirement-credit-choice.fixed.md b/changelog.d/fix-ut-military-retirement-credit-choice.fixed.md new file mode 100644 index 00000000000..51e5065be94 --- /dev/null +++ b/changelog.d/fix-ut-military-retirement-credit-choice.fixed.md @@ -0,0 +1 @@ +Utah's military retirement credit no longer goes unclaimed when the filer has neither a retirement credit nor a Social Security benefits credit, and the retirement-credit choice now weighs the military credit alongside the Social Security credit; the credit starts in 2021. diff --git a/policyengine_us/parameters/gov/states/ut/tax/income/credits/military_retirement/rate.yaml b/policyengine_us/parameters/gov/states/ut/tax/income/credits/military_retirement/rate.yaml index f72e0bf9f0b..947609d8d76 100644 --- a/policyengine_us/parameters/gov/states/ut/tax/income/credits/military_retirement/rate.yaml +++ b/policyengine_us/parameters/gov/states/ut/tax/income/credits/military_retirement/rate.yaml @@ -1,5 +1,7 @@ description: Utah military retirement credit rate applied to taxable military retirement pay. values: + # 59-10-1043 applies to taxable years beginning on or after January 1, 2021. + 0000-01-01: 0 2021-01-01: 0.0495 2022-01-01: 0.0485 2023-01-01: 0.0465 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ut/tax/income/credits/military_retirement_credit/ut_military_retirement_credit.yaml b/policyengine_us/tests/policy/baseline/gov/states/ut/tax/income/credits/military_retirement_credit/ut_military_retirement_credit.yaml index 8902bd5b6ad..4ac71fab495 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ut/tax/income/credits/military_retirement_credit/ut_military_retirement_credit.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ut/tax/income/credits/military_retirement_credit/ut_military_retirement_credit.yaml @@ -98,3 +98,45 @@ state_code: UT output: ut_military_retirement_credit: 1350 + +- name: UT military retirement credit - retiree too young for the retirement credit gets the military credit + period: 2025 + input: + people: + person1: + age: 45 + military_retirement_pay: 30_000 + tax_units: + tax_unit: + members: [person1] + ut_income_tax_before_non_refundable_credits: 1_000_000 + households: + household: + members: [person1] + state_code: UT + output: + ut_claims_retirement_credit: false + ut_military_retirement_credit_eligible: true + ut_military_retirement_credit: 1_350 + +- name: UT military retirement credit - older retiree with little military pay takes the retirement credit instead + period: 2025 + input: + people: + person1: + age: 76 + military_retirement_pay: 4_000 + tax_units: + tax_unit: + members: [person1] + ut_income_tax_before_non_refundable_credits: 1_000_000 + households: + household: + members: [person1] + state_code: UT + output: + ut_retirement_credit_max: 450 + ut_military_retirement_credit_max: 180 + ut_claims_retirement_credit: true + ut_military_retirement_credit_eligible: false + ut_military_retirement_credit: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ut/tax/income/credits/military_retirement_credit/ut_military_retirement_credit_max.yaml b/policyengine_us/tests/policy/baseline/gov/states/ut/tax/income/credits/military_retirement_credit/ut_military_retirement_credit_max.yaml new file mode 100644 index 00000000000..f74aab6c40a --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ut/tax/income/credits/military_retirement_credit/ut_military_retirement_credit_max.yaml @@ -0,0 +1,47 @@ +- name: UT military retirement credit maximum - 4.5% of military retirement pay in 2025 + period: 2025 + input: + people: + person1: + military_retirement_pay: 30_000 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: UT + output: + ut_military_retirement_credit_max: 1_350 + +- name: UT military retirement credit maximum - survivor benefits count as military retirement pay + period: 2025 + input: + people: + person1: + military_retirement_pay_survivors: 10_000 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: UT + output: + ut_military_retirement_credit_max: 450 + +- name: UT military retirement credit maximum - none before the credit took effect in 2021 + period: 2020 + input: + people: + person1: + military_retirement_pay: 30_000 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: UT + output: + ut_military_retirement_credit_max: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ut/tax/income/credits/retirement_credit/ut_claims_retirement_credit.yaml b/policyengine_us/tests/policy/baseline/gov/states/ut/tax/income/credits/retirement_credit/ut_claims_retirement_credit.yaml index b6bc3cf82c4..afa1f905fce 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ut/tax/income/credits/retirement_credit/ut_claims_retirement_credit.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ut/tax/income/credits/retirement_credit/ut_claims_retirement_credit.yaml @@ -25,11 +25,41 @@ output: ut_claims_retirement_credit: true -- name: UT claims retirement credit unit test 4 +- name: UT claims retirement credit unit test 4 - a retirement credit worth nothing is never claimed period: 2022 input: ut_retirement_credit_max: 0 ut_ss_benefits_credit_max: 0 state_code: UT + output: + ut_claims_retirement_credit: false + +- name: UT claims retirement credit - military credit alone outweighs the retirement credit + period: 2025 + input: + ut_retirement_credit_max: 450 + ut_ss_benefits_credit_max: 0 + ut_military_retirement_credit_max: 1_350 + state_code: UT + output: + ut_claims_retirement_credit: false + +- name: UT claims retirement credit - Social Security and military credits combine against the retirement credit + period: 2025 + input: + ut_retirement_credit_max: 450 + ut_ss_benefits_credit_max: 300 + ut_military_retirement_credit_max: 200 + state_code: UT + output: + ut_claims_retirement_credit: false + +- name: UT claims retirement credit - retirement credit outweighs both alternatives combined + period: 2025 + input: + ut_retirement_credit_max: 450 + ut_ss_benefits_credit_max: 100 + ut_military_retirement_credit_max: 225 + state_code: UT output: ut_claims_retirement_credit: true diff --git a/policyengine_us/variables/gov/states/ut/tax/income/credits/military_retirement_credit/ut_military_retirement_credit_max.py b/policyengine_us/variables/gov/states/ut/tax/income/credits/military_retirement_credit/ut_military_retirement_credit_max.py new file mode 100644 index 00000000000..92df6995c7a --- /dev/null +++ b/policyengine_us/variables/gov/states/ut/tax/income/credits/military_retirement_credit/ut_military_retirement_credit_max.py @@ -0,0 +1,23 @@ +from policyengine_us.model_api import * + + +class ut_military_retirement_credit_max(Variable): + value_type = float + entity = TaxUnit + label = "Utah military retirement credit maximum amount" + unit = USD + definition_period = YEAR + reference = "https://le.utah.gov/xcode/Title59/Chapter10/59-10-S1043.html" + defined_for = StateCode.UT + + def formula(tax_unit, period, parameters): + # 59-10-1043(2)(b): only the pay included in adjusted gross income on + # the claimant's federal return, which excludes dependents' income; + # dependents report it on their own return. + military_retirement_pay = tax_unit_non_dep_add( + tax_unit, + period, + ["military_retirement_income"], + ) + p = parameters(period).gov.states.ut.tax.income.credits.military_retirement + return military_retirement_pay * p.rate diff --git a/policyengine_us/variables/gov/states/ut/tax/income/credits/military_retirement_credit/ut_military_retirement_credit_potential.py b/policyengine_us/variables/gov/states/ut/tax/income/credits/military_retirement_credit/ut_military_retirement_credit_potential.py index 011e94faa60..545d873d72f 100644 --- a/policyengine_us/variables/gov/states/ut/tax/income/credits/military_retirement_credit/ut_military_retirement_credit_potential.py +++ b/policyengine_us/variables/gov/states/ut/tax/income/credits/military_retirement_credit/ut_military_retirement_credit_potential.py @@ -10,15 +10,4 @@ class ut_military_retirement_credit_potential(Variable): reference = "https://le.utah.gov/xcode/Title59/Chapter10/59-10-S1043.html" defined_for = "ut_military_retirement_credit_eligible" - def formula(tax_unit, period, parameters): - # 59-10-1043(2)(b): only the pay included in adjusted gross income on - # the claimant's federal return, which excludes dependents' income; - # dependents report it on their own return. - military_retirement_pay = tax_unit_non_dep_add( - tax_unit, - period, - ["military_retirement_income"], - ) - - p = parameters(period).gov.states.ut.tax.income.credits.military_retirement - return military_retirement_pay * p.rate + adds = ["ut_military_retirement_credit_max"] diff --git a/policyengine_us/variables/gov/states/ut/tax/income/credits/retirement_credit/ut_claims_retirement_credit.py b/policyengine_us/variables/gov/states/ut/tax/income/credits/retirement_credit/ut_claims_retirement_credit.py index c5ada7d2d58..f400862dc62 100644 --- a/policyengine_us/variables/gov/states/ut/tax/income/credits/retirement_credit/ut_claims_retirement_credit.py +++ b/policyengine_us/variables/gov/states/ut/tax/income/credits/retirement_credit/ut_claims_retirement_credit.py @@ -6,11 +6,33 @@ class ut_claims_retirement_credit(Variable): entity = TaxUnit label = "claims the Utah retirement credit" unit = USD - documentation = "Utah residents can claim only one of the retirement credit or the social security benefits credit. We assume they claim the one with higher value." + documentation = ( + "A Utah filer who claims the retirement credit cannot also claim the " + "Social Security benefits credit or the military retirement credit, " + "but can claim those two together. We assume the filer takes whichever " + "option is worth more, and never claims a retirement credit worth " + "nothing." + ) + reference = ( + # Each section's subsection (3)(b) bars its credit alongside the + # retirement credit; nothing bars 59-10-1042 with 59-10-1043. + "https://le.utah.gov/xcode/Title59/Chapter10/59-10-S1019.html", + "https://le.utah.gov/xcode/Title59/Chapter10/59-10-S1042.html", + "https://le.utah.gov/xcode/Title59/Chapter10/59-10-S1043.html", + "https://files.tax.utah.gov/tax/forms/2025/tc-40inst.pdf#page=21", + "https://files.tax.utah.gov/tax/forms/2025/tc-40inst.pdf#page=23", + ) definition_period = YEAR defined_for = StateCode.UT def formula(tax_unit, period, parameters): - max_retirement_credit = tax_unit("ut_retirement_credit_max", period) - max_ss_benefits_credit = tax_unit("ut_ss_benefits_credit_max", period) - return max_retirement_credit >= max_ss_benefits_credit + retirement_credit = tax_unit("ut_retirement_credit_max", period) + # The Social Security benefits credit and the military retirement + # credit can be claimed together, so the retirement credit competes + # with their sum. + alternative_credits = add( + tax_unit, + period, + ["ut_ss_benefits_credit_max", "ut_military_retirement_credit_max"], + ) + return (retirement_credit > 0) & (retirement_credit >= alternative_credits) From 41bc19b59a8945f886dc1c872c68a6a5c2c8527d Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sun, 8 Nov 2026 00:49:16 -0500 Subject: [PATCH 2/4] Use Utah's income tax rate for the military retirement credit 59-10-1043(2)(a) sets the credit at the percentage listed in 59-10-104(2). The separate military_retirement/rate parameter copied that rate through 2025 but not the 4.45% rate for 2026, so the 2026 credit used 4.5%. The credit now reads gov.states.ut.tax.income.rate, as the Social Security benefits credit already does, gated by a new in_effect parameter that starts in 2021. Co-Authored-By: Claude Opus 5.5 --- ...military-retirement-credit-choice.fixed.md | 2 +- .../military_retirement/in_effect.yaml | 18 ++++++++++++ .../credits/military_retirement/rate.yaml | 28 ------------------- .../ut_military_retirement_credit_max.yaml | 16 +++++++++++ .../ut_military_retirement_credit_max.py | 7 +++-- 5 files changed, 40 insertions(+), 31 deletions(-) create mode 100644 policyengine_us/parameters/gov/states/ut/tax/income/credits/military_retirement/in_effect.yaml delete mode 100644 policyengine_us/parameters/gov/states/ut/tax/income/credits/military_retirement/rate.yaml diff --git a/changelog.d/fix-ut-military-retirement-credit-choice.fixed.md b/changelog.d/fix-ut-military-retirement-credit-choice.fixed.md index 51e5065be94..0a855d679c8 100644 --- a/changelog.d/fix-ut-military-retirement-credit-choice.fixed.md +++ b/changelog.d/fix-ut-military-retirement-credit-choice.fixed.md @@ -1 +1 @@ -Utah's military retirement credit no longer goes unclaimed when the filer has neither a retirement credit nor a Social Security benefits credit, and the retirement-credit choice now weighs the military credit alongside the Social Security credit; the credit starts in 2021. +Utah's military retirement credit no longer goes unclaimed when the filer has neither a retirement credit nor a Social Security benefits credit; the retirement-credit choice now weighs the military credit alongside the Social Security credit; and the credit uses the income tax rate, as 59-10-1043 requires (4.45% in 2026), starting in 2021. diff --git a/policyengine_us/parameters/gov/states/ut/tax/income/credits/military_retirement/in_effect.yaml b/policyengine_us/parameters/gov/states/ut/tax/income/credits/military_retirement/in_effect.yaml new file mode 100644 index 00000000000..489343b659f --- /dev/null +++ b/policyengine_us/parameters/gov/states/ut/tax/income/credits/military_retirement/in_effect.yaml @@ -0,0 +1,18 @@ +description: Utah allows the military retirement credit when this is true. +values: + 0000-01-01: false + # 59-10-1043 applies to taxable years beginning on or after January 1, 2021. + 2021-01-01: true +metadata: + unit: bool + period: year + label: Utah military retirement credit in effect + reference: + - title: Utah Code §59-10-1043 + href: https://le.utah.gov/xcode/Title59/Chapter10/59-10-S1043.html + - title: Utah Military Retirement Credit + href: https://incometax.utah.gov/credits/military-retirement + - title: 2021 Utah TC-40 Instructions, Military Retirement Credit Worksheet + href: https://files.tax.utah.gov/tax/forms/2021/tc-40inst.pdf#page=22 + - title: 2025 Utah TC-40 Instructions, Military Retirement Credit Worksheet + href: https://files.tax.utah.gov/tax/forms/2025/tc-40inst.pdf#page=23 diff --git a/policyengine_us/parameters/gov/states/ut/tax/income/credits/military_retirement/rate.yaml b/policyengine_us/parameters/gov/states/ut/tax/income/credits/military_retirement/rate.yaml deleted file mode 100644 index 947609d8d76..00000000000 --- a/policyengine_us/parameters/gov/states/ut/tax/income/credits/military_retirement/rate.yaml +++ /dev/null @@ -1,28 +0,0 @@ -description: Utah military retirement credit rate applied to taxable military retirement pay. -values: - # 59-10-1043 applies to taxable years beginning on or after January 1, 2021. - 0000-01-01: 0 - 2021-01-01: 0.0495 - 2022-01-01: 0.0485 - 2023-01-01: 0.0465 - 2024-01-01: 0.0455 - 2025-01-01: 0.045 -metadata: - unit: /1 - period: year - label: Utah military retirement credit rate - reference: - - title: Utah Code §59-10-1043 - href: https://le.utah.gov/xcode/Title59/Chapter10/59-10-S1043.html - - title: Utah Military Retirement Credit - href: https://incometax.utah.gov/credits/military-retirement - - title: 2021 Utah TC-40 Instructions, Military Retirement Credit Worksheet - href: https://files.tax.utah.gov/tax/forms/2021/tc-40inst.pdf#page=22 - - title: 2022 Utah TC-40 Instructions, Military Retirement Credit Worksheet - href: https://files.tax.utah.gov/tax/forms/2022/tc-40inst.pdf#page=22 - - title: 2023 Utah TC-40 Instructions, Military Retirement Credit Worksheet - href: https://files.tax.utah.gov/tax/forms/2023/tc-40inst.pdf#page=23 - - title: 2024 Utah TC-40 Instructions, Military Retirement Credit Worksheet - href: https://tax.utah.gov/forms/current/tc-40inst.pdf#page=23 - - title: 2025 Utah TC-40 Instructions, Military Retirement Credit Worksheet - href: https://files.tax.utah.gov/tax/forms/2025/tc-40inst.pdf#page=24 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ut/tax/income/credits/military_retirement_credit/ut_military_retirement_credit_max.yaml b/policyengine_us/tests/policy/baseline/gov/states/ut/tax/income/credits/military_retirement_credit/ut_military_retirement_credit_max.yaml index f74aab6c40a..f62fe9068b0 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ut/tax/income/credits/military_retirement_credit/ut_military_retirement_credit_max.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ut/tax/income/credits/military_retirement_credit/ut_military_retirement_credit_max.yaml @@ -45,3 +45,19 @@ state_code: UT output: ut_military_retirement_credit_max: 0 + +- name: UT military retirement credit maximum - follows the 4.45% income tax rate in 2026 + period: 2026 + input: + people: + person1: + military_retirement_pay: 30_000 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: UT + output: + ut_military_retirement_credit_max: 1_335 diff --git a/policyengine_us/variables/gov/states/ut/tax/income/credits/military_retirement_credit/ut_military_retirement_credit_max.py b/policyengine_us/variables/gov/states/ut/tax/income/credits/military_retirement_credit/ut_military_retirement_credit_max.py index 92df6995c7a..dfef909fbe3 100644 --- a/policyengine_us/variables/gov/states/ut/tax/income/credits/military_retirement_credit/ut_military_retirement_credit_max.py +++ b/policyengine_us/variables/gov/states/ut/tax/income/credits/military_retirement_credit/ut_military_retirement_credit_max.py @@ -19,5 +19,8 @@ def formula(tax_unit, period, parameters): period, ["military_retirement_income"], ) - p = parameters(period).gov.states.ut.tax.income.credits.military_retirement - return military_retirement_pay * p.rate + # 59-10-1043(2)(a): the percentage listed in 59-10-104(2), the + # income tax rate. + p = parameters(period).gov.states.ut.tax.income + in_effect = p.credits.military_retirement.in_effect + return in_effect * military_retirement_pay * p.rate From 79ac896934ce96156f717bb0befd0dca9660c7c4 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sun, 8 Nov 2026 00:55:09 -0500 Subject: [PATCH 3/4] Cite the page of the 2025 Utah instructions that describes the military retirement credit Co-Authored-By: Claude Opus 5.5 --- .../ut/tax/income/credits/military_retirement/in_effect.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/policyengine_us/parameters/gov/states/ut/tax/income/credits/military_retirement/in_effect.yaml b/policyengine_us/parameters/gov/states/ut/tax/income/credits/military_retirement/in_effect.yaml index 489343b659f..69c129cae93 100644 --- a/policyengine_us/parameters/gov/states/ut/tax/income/credits/military_retirement/in_effect.yaml +++ b/policyengine_us/parameters/gov/states/ut/tax/income/credits/military_retirement/in_effect.yaml @@ -14,5 +14,5 @@ metadata: href: https://incometax.utah.gov/credits/military-retirement - title: 2021 Utah TC-40 Instructions, Military Retirement Credit Worksheet href: https://files.tax.utah.gov/tax/forms/2021/tc-40inst.pdf#page=22 - - title: 2025 Utah TC-40 Instructions, Military Retirement Credit Worksheet + - title: 2025 Utah TC-40 Instructions, Military Retirement Credit (code AJ) href: https://files.tax.utah.gov/tax/forms/2025/tc-40inst.pdf#page=23 From a3bf81bec865957b423dd1fd59bb6a78dbf8f7ba Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sun, 8 Nov 2026 01:03:05 -0500 Subject: [PATCH 4/4] Update the Utah comment in the dependent retirement income invariants test Co-Authored-By: Claude Opus 5.5 --- .../test_dependent_retirement_income_state_invariants.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/policyengine_us/tests/core/test_dependent_retirement_income_state_invariants.py b/policyengine_us/tests/core/test_dependent_retirement_income_state_invariants.py index 49595f2d791..a399dbaa23d 100644 --- a/policyengine_us/tests/core/test_dependent_retirement_income_state_invariants.py +++ b/policyengine_us/tests/core/test_dependent_retirement_income_state_invariants.py @@ -452,9 +452,9 @@ def test_dependents_retirement_income_never_reduces_state_income_tax(year): assert (unit_has_dependent_income & filer_social_security).any() assert (unit_has_dependent_income & filer_aged_73).any() assert (unit_has_dependent_income & elderly_dependent).any() - # Utah's military retirement credit is open only when the retirement - # credit is not claimed, which needs Social Security worth more than the - # age-gated retirement credit. + # Utah's military retirement credit is open only when the filer does not + # claim the retirement credit: when that credit is worth nothing, or less + # than the Social Security and military retirement credits together. dependent_military_pay = np.tile( [any(d["income"]["military_retirement_pay"] > 0 for d in u["dependents"]) for u in units],