From b91db663d217c5b0375ff36f478bb4bb91fdea5a Mon Sep 17 00:00:00 2001 From: Deepak Jindal Date: Mon, 12 Oct 2026 14:54:24 -0700 Subject: [PATCH 1/5] Wire military retirement pay and survivors into federal and state tax (#10181) - Add military_retirement_pay and military_retirement_pay_survivors to federal irs_gross_income sources - Add military_retirement_pay and military_retirement_pay_survivors to market_income, SNAP unearned income, and SSI unearned income - Harmonize state military retirement subtractions and senior pension exclusions to include military_retirement_pay_survivors (AZ, AR, CO, CT, GA, IA, ID, LA, MI, ND, NE, NM, OK, RI, UT, VA, VT, WV) - Fix typo in ne_military_retirement_subtraction filename - Add YAML test for federal gross income, AGI, market income, and SNAP/SSI unearned income - Add CA taxable income test verifying military retirement pay inclusion - Update NC and VT baseline tests to reflect wiring into AGI - Add changelog fragment --- .../wire-military-retirement-pay.fixed.md | 1 + .../gov/irs/gross_income/sources.yaml | 3 + .../gov/ssa/ssi/income/sources/unearned.yaml | 2 + .../gross_income/sources/individual.yaml | 4 + .../income/gross_income/sources/joint.yaml | 4 + .../subtractions/pension/income_sources.yaml | 4 + .../tax/income/subtractions/subtractions.yaml | 1 + .../agi/exclusions/retirement/sources.yaml | 2 + .../income/taxable_income/subtractions.yaml | 1 + .../retirement_benefits/income_sources.yaml | 1 + .../la/tax/income/exempt_income/sources.yaml | 1 + .../states/mi/tax/income/subtractions.yaml | 2 + .../taxable_income/subtractions/sources.yaml | 3 + .../income/agi/subtractions/subtractions.yaml | 1 + .../modification_sources.yaml | 1 + .../tax/income/subtractions/subtractions.yaml | 1 + .../usda/snap/income/sources/unearned.yaml | 2 + .../military_retirement_pay.yaml | 95 +++++++++++++++++++ .../ca/tax/income/ca_taxable_income.yaml | 11 +++ .../nc_military_retirement_deduction.yaml | 9 -- .../vt_retirement_income_exemption.yaml | 6 +- .../ar_military_retirement_income_person.py | 9 +- .../az_military_retirement_subtraction.py | 6 +- ... => ne_military_retirement_subtraction.py} | 9 +- ..._forces_retirement_pay_exemption_person.py | 9 +- .../ok_military_retirement_exclusion.py | 9 +- .../ut_military_retirement_credit_eligible.py | 9 +- ...ut_military_retirement_credit_potential.py | 9 +- .../va_military_benefit_subtraction_person.py | 12 ++- ...military_retirement_cap_based_exemption.py | 9 +- ...itary_retirement_income_based_exemption.py | 9 +- .../vt_military_retirement_pay_exclusion.py | 9 +- ...vt_retirement_income_exemption_eligible.py | 1 + .../income/person/general/market_income.py | 2 + 34 files changed, 229 insertions(+), 28 deletions(-) create mode 100644 changelog.d/wire-military-retirement-pay.fixed.md create mode 100644 policyengine_us/tests/policy/baseline/gov/irs/income/taxable_income/adjusted_gross_income/irs_gross_income/military_retirement_pay.yaml rename policyengine_us/variables/gov/states/ne/tax/income/adjusted_gross_income/subtractions/{ne_military_retirement_substraction.py => ne_military_retirement_subtraction.py} (87%) diff --git a/changelog.d/wire-military-retirement-pay.fixed.md b/changelog.d/wire-military-retirement-pay.fixed.md new file mode 100644 index 00000000000..4b9f113c81f --- /dev/null +++ b/changelog.d/wire-military-retirement-pay.fixed.md @@ -0,0 +1 @@ +Add military retirement pay and survivor benefits to federal gross income, market income, and SNAP and SSI unearned income sources. diff --git a/policyengine_us/parameters/gov/irs/gross_income/sources.yaml b/policyengine_us/parameters/gov/irs/gross_income/sources.yaml index af8391cacdf..9390fdd0a2f 100644 --- a/policyengine_us/parameters/gov/irs/gross_income/sources.yaml +++ b/policyengine_us/parameters/gov/irs/gross_income/sources.yaml @@ -39,6 +39,9 @@ values: - taxable_alimony_income # Taxable state and local income tax refunds (Schedule 1 line 1 / IRC § 111). - salt_refund_income + # Military retirement pay and survivor benefit plan payments (IRC § 61, Form 1040 line 5b). + - military_retirement_pay + - military_retirement_pay_survivors metadata: unit: list diff --git a/policyengine_us/parameters/gov/ssa/ssi/income/sources/unearned.yaml b/policyengine_us/parameters/gov/ssa/ssi/income/sources/unearned.yaml index 31f8890c835..c911da70691 100644 --- a/policyengine_us/parameters/gov/ssa/ssi/income/sources/unearned.yaml +++ b/policyengine_us/parameters/gov/ssa/ssi/income/sources/unearned.yaml @@ -10,6 +10,8 @@ values: - workers_compensation - total_unemployment_compensation - retirement_distributions + - military_retirement_pay + - military_retirement_pay_survivors - gi_cash_assistance # (b) Alimony and support payments. - alimony_income diff --git a/policyengine_us/parameters/gov/states/ar/tax/income/gross_income/sources/individual.yaml b/policyengine_us/parameters/gov/states/ar/tax/income/gross_income/sources/individual.yaml index c9705de6925..6c466502a47 100644 --- a/policyengine_us/parameters/gov/states/ar/tax/income/gross_income/sources/individual.yaml +++ b/policyengine_us/parameters/gov/states/ar/tax/income/gross_income/sources/individual.yaml @@ -16,6 +16,7 @@ values: - taxable_ira_distributions # Line 16, or Lines 17A/17B after age 59 1/2 - taxable_roth_conversions # Line 16, or Lines 17A/17B after age 59 1/2 - military_retirement_pay # Line 17A/17B + - military_retirement_pay_survivors # Line 17A/17B - taxable_pension_income # Line 17A/17B - disability_benefits # Line 17A/17B - rental_income # Line 18 @@ -42,6 +43,7 @@ values: - taxable_ira_distributions # Line 16, or Lines 18A/18B after age 59 1/2 - taxable_roth_conversions # Line 16, or Lines 18A/18B after age 59 1/2 - military_retirement_pay # Line 17 (Lines 17A/17B on the 2018 form) + - military_retirement_pay_survivors # Line 17 - taxable_pension_income # Line 18A/18B - disability_benefits # Line 18A/18B - rental_income # Line 19 @@ -62,6 +64,7 @@ values: - taxable_ira_distributions # Line 16, or Lines 18A/18B after age 59 1/2 - taxable_roth_conversions # Line 16, or Lines 18A/18B after age 59 1/2 - military_retirement_pay # Line 17 + - military_retirement_pay_survivors # Line 17 - taxable_pension_income # Line 18A/18B - disability_benefits # Line 18A/18B - rental_income # Line 19 @@ -81,6 +84,7 @@ values: - taxable_ira_distributions # Line 16, or Lines 18A/18B after age 59 1/2 - taxable_roth_conversions # Line 16, or Lines 18A/18B after age 59 1/2 - military_retirement_pay # Line 17 + - military_retirement_pay_survivors # Line 17 - taxable_pension_income # Line 18A/18B - taxable_401k_distributions # Line 18A/18B - taxable_403b_distributions # Line 18A/18B diff --git a/policyengine_us/parameters/gov/states/ar/tax/income/gross_income/sources/joint.yaml b/policyengine_us/parameters/gov/states/ar/tax/income/gross_income/sources/joint.yaml index c8583b5dd2e..c5de4323370 100644 --- a/policyengine_us/parameters/gov/states/ar/tax/income/gross_income/sources/joint.yaml +++ b/policyengine_us/parameters/gov/states/ar/tax/income/gross_income/sources/joint.yaml @@ -16,6 +16,7 @@ values: - taxable_ira_distributions # Line 16, or Lines 17A/17B after age 59 1/2 - taxable_roth_conversions # Line 16, or Lines 17A/17B after age 59 1/2 - military_retirement_pay # Line 17A/17B + - military_retirement_pay_survivors # Line 17A/17B - taxable_pension_income # Line 17A/17B - disability_benefits # Line 17A/17B - rental_income # Line 18 @@ -42,6 +43,7 @@ values: - taxable_ira_distributions # Line 16, or Lines 18A/18B after age 59 1/2 - taxable_roth_conversions # Line 16, or Lines 18A/18B after age 59 1/2 - military_retirement_pay # Line 17 (Lines 17A/17B on the 2018 form) + - military_retirement_pay_survivors # Line 17 - taxable_pension_income # Line 18A/18B - disability_benefits # Line 18A/18B - rental_income # Line 19 @@ -62,6 +64,7 @@ values: - taxable_ira_distributions # Line 16, or Lines 18A/18B after age 59 1/2 - taxable_roth_conversions # Line 16, or Lines 18A/18B after age 59 1/2 - military_retirement_pay # Line 17 + - military_retirement_pay_survivors # Line 17 - taxable_pension_income # Line 18A/18B - disability_benefits # Line 18A/18B - rental_income # Line 19 @@ -81,6 +84,7 @@ values: - taxable_ira_distributions # Line 16, or Lines 18A/18B after age 59 1/2 - taxable_roth_conversions # Line 16, or Lines 18A/18B after age 59 1/2 - military_retirement_pay # Line 17 + - military_retirement_pay_survivors # Line 17 - taxable_pension_income # Line 18A/18B - taxable_401k_distributions # Line 18A/18B - taxable_403b_distributions # Line 18A/18B diff --git a/policyengine_us/parameters/gov/states/co/tax/income/subtractions/pension/income_sources.yaml b/policyengine_us/parameters/gov/states/co/tax/income/subtractions/pension/income_sources.yaml index 8ac10e703f7..dc0541bb509 100644 --- a/policyengine_us/parameters/gov/states/co/tax/income/subtractions/pension/income_sources.yaml +++ b/policyengine_us/parameters/gov/states/co/tax/income/subtractions/pension/income_sources.yaml @@ -10,6 +10,8 @@ values: - keogh_distributions - taxable_roth_conversions - disability_benefits + - military_retirement_pay + - military_retirement_pay_survivors # In 2022 the taxable social security is calculated separately. 2022-01-01: - taxable_pension_income @@ -20,6 +22,8 @@ values: - keogh_distributions - taxable_roth_conversions - disability_benefits + - military_retirement_pay + - military_retirement_pay_survivors metadata: period: year unit: list diff --git a/policyengine_us/parameters/gov/states/ct/tax/income/subtractions/subtractions.yaml b/policyengine_us/parameters/gov/states/ct/tax/income/subtractions/subtractions.yaml index aea3a9f1f80..adeaff9aee3 100644 --- a/policyengine_us/parameters/gov/states/ct/tax/income/subtractions/subtractions.yaml +++ b/policyengine_us/parameters/gov/states/ct/tax/income/subtractions/subtractions.yaml @@ -4,6 +4,7 @@ values: - us_govt_interest #ln 39 - ct_social_security_benefit_adjustment #ln 41 - military_retirement_pay #ln 44 + - military_retirement_pay_survivors #ln 44 - ct_pension_annuity_subtraction #ln 48b - salt_refund_income #ln 38 diff --git a/policyengine_us/parameters/gov/states/ga/tax/income/agi/exclusions/retirement/sources.yaml b/policyengine_us/parameters/gov/states/ga/tax/income/agi/exclusions/retirement/sources.yaml index b40bfa87e32..447b2d2a5cd 100644 --- a/policyengine_us/parameters/gov/states/ga/tax/income/agi/exclusions/retirement/sources.yaml +++ b/policyengine_us/parameters/gov/states/ga/tax/income/agi/exclusions/retirement/sources.yaml @@ -28,3 +28,5 @@ values: - taxable_sep_distributions - keogh_distributions - taxable_roth_conversions + - military_retirement_pay + - military_retirement_pay_survivors diff --git a/policyengine_us/parameters/gov/states/ia/tax/income/taxable_income/subtractions.yaml b/policyengine_us/parameters/gov/states/ia/tax/income/taxable_income/subtractions.yaml index a4e6efa99de..78458a82846 100644 --- a/policyengine_us/parameters/gov/states/ia/tax/income/taxable_income/subtractions.yaml +++ b/policyengine_us/parameters/gov/states/ia/tax/income/taxable_income/subtractions.yaml @@ -21,6 +21,7 @@ values: # Dividends from federal securities # Line 4B - military_retirement_pay + - military_retirement_pay_survivors # Line 5B - taxable_social_security # Line 6B diff --git a/policyengine_us/parameters/gov/states/id/tax/income/deductions/retirement_benefits/income_sources.yaml b/policyengine_us/parameters/gov/states/id/tax/income/deductions/retirement_benefits/income_sources.yaml index 156089394b4..9f6d3769613 100644 --- a/policyengine_us/parameters/gov/states/id/tax/income/deductions/retirement_benefits/income_sources.yaml +++ b/policyengine_us/parameters/gov/states/id/tax/income/deductions/retirement_benefits/income_sources.yaml @@ -3,6 +3,7 @@ values: 2021-01-01: - public_pension_income - military_retirement_pay + - military_retirement_pay_survivors 2025-01-01: - public_pension_income metadata: diff --git a/policyengine_us/parameters/gov/states/la/tax/income/exempt_income/sources.yaml b/policyengine_us/parameters/gov/states/la/tax/income/exempt_income/sources.yaml index 4c013831a8e..c2f5c62e3c2 100644 --- a/policyengine_us/parameters/gov/states/la/tax/income/exempt_income/sources.yaml +++ b/policyengine_us/parameters/gov/states/la/tax/income/exempt_income/sources.yaml @@ -5,6 +5,7 @@ values: # Louisiana State Employees’ Retirement Benefits 02E # Louisiana State Teachers’ Retirement Benefits 03E - military_retirement_pay # 04E + - military_retirement_pay_survivors # 04E # Other Retirement Benefits 05E (federal civil service, municipal, etc.) # Proxy note: Schedule E exempts specific Louisiana state/municipal systems and federal # retirement systems (codes 02E, 03E, 05E). Out-of-state public pensions are not exempt. diff --git a/policyengine_us/parameters/gov/states/mi/tax/income/subtractions.yaml b/policyengine_us/parameters/gov/states/mi/tax/income/subtractions.yaml index 62d9a981878..11c6e110f9f 100644 --- a/policyengine_us/parameters/gov/states/mi/tax/income/subtractions.yaml +++ b/policyengine_us/parameters/gov/states/mi/tax/income/subtractions.yaml @@ -3,6 +3,7 @@ values: 2017-01-01: - us_govt_interest # Line 10 - military_retirement_pay # Line 11 + - military_retirement_pay_survivors # Line 11 - taxable_social_security # Line 14 - military_service_income # Line 14 - section_22_income # Line 22 @@ -14,6 +15,7 @@ values: 2026-01-01: - us_govt_interest # Line 10 - military_retirement_pay # Line 11 + - military_retirement_pay_survivors # Line 11 - taxable_social_security # Line 14 - military_service_income # Line 14 - section_22_income # Line 22 diff --git a/policyengine_us/parameters/gov/states/nd/tax/income/taxable_income/subtractions/sources.yaml b/policyengine_us/parameters/gov/states/nd/tax/income/taxable_income/subtractions/sources.yaml index b4baa1b3a2c..b65d7ca51df 100644 --- a/policyengine_us/parameters/gov/states/nd/tax/income/taxable_income/subtractions/sources.yaml +++ b/policyengine_us/parameters/gov/states/nd/tax/income/taxable_income/subtractions/sources.yaml @@ -6,6 +6,7 @@ values: - nd_qdiv_subtraction # qualified dividends - taxable_social_security - military_retirement_pay + - military_retirement_pay_survivors - nd_529_deduction - nd_stillborn_subtraction @@ -15,6 +16,7 @@ values: - nd_qdiv_subtraction # qualified dividends - taxable_social_security - military_retirement_pay + - military_retirement_pay_survivors - nd_529_deduction - nd_stillborn_subtraction @@ -24,6 +26,7 @@ values: - nd_qdiv_subtraction # qualified dividends - taxable_social_security - military_retirement_pay + - military_retirement_pay_survivors - military_service_income # military pay exclusion - nd_529_deduction - nd_stillborn_subtraction diff --git a/policyengine_us/parameters/gov/states/ri/tax/income/agi/subtractions/subtractions.yaml b/policyengine_us/parameters/gov/states/ri/tax/income/agi/subtractions/subtractions.yaml index 702508f7f68..d70a7d47e8f 100644 --- a/policyengine_us/parameters/gov/states/ri/tax/income/agi/subtractions/subtractions.yaml +++ b/policyengine_us/parameters/gov/states/ri/tax/income/agi/subtractions/subtractions.yaml @@ -13,6 +13,7 @@ values: - ri_retirement_income_subtraction - us_govt_interest - military_retirement_pay + - military_retirement_pay_survivors metadata: unit: list diff --git a/policyengine_us/parameters/gov/states/wv/tax/income/subtractions/senior_citizen_disability_deduction/modification_sources.yaml b/policyengine_us/parameters/gov/states/wv/tax/income/subtractions/senior_citizen_disability_deduction/modification_sources.yaml index 2d33df6161d..908296d35f2 100644 --- a/policyengine_us/parameters/gov/states/wv/tax/income/subtractions/senior_citizen_disability_deduction/modification_sources.yaml +++ b/policyengine_us/parameters/gov/states/wv/tax/income/subtractions/senior_citizen_disability_deduction/modification_sources.yaml @@ -9,6 +9,7 @@ values: # certain federal law enforcement retirement Line 28 # West Virginia state or local police, deputy sheriff's or firemen's retirement Line 29 - military_retirement_pay # Line 30 + - military_retirement_pay_survivors # Line 30 - wv_public_pension_subtraction_person # Line 31 - wv_social_security_benefits_subtraction_person # Line 32 diff --git a/policyengine_us/parameters/gov/states/wv/tax/income/subtractions/subtractions.yaml b/policyengine_us/parameters/gov/states/wv/tax/income/subtractions/subtractions.yaml index a3fe563b8fb..631cf66d310 100644 --- a/policyengine_us/parameters/gov/states/wv/tax/income/subtractions/subtractions.yaml +++ b/policyengine_us/parameters/gov/states/wv/tax/income/subtractions/subtractions.yaml @@ -3,6 +3,7 @@ values: 2021-01-01: - us_govt_interest # Line 27 - military_retirement_pay # Line 30 + - military_retirement_pay_survivors # Line 30 - wv_public_pension_subtraction # Line 31 - wv_social_security_benefits_subtraction # Line 32 - military_service_income # Line 34 diff --git a/policyengine_us/parameters/gov/usda/snap/income/sources/unearned.yaml b/policyengine_us/parameters/gov/usda/snap/income/sources/unearned.yaml index e9baee603e8..7137710c258 100644 --- a/policyengine_us/parameters/gov/usda/snap/income/sources/unearned.yaml +++ b/policyengine_us/parameters/gov/usda/snap/income/sources/unearned.yaml @@ -63,6 +63,8 @@ values: - social_security - survivor_benefits - retirement_distributions + - military_retirement_pay + - military_retirement_pay_survivors # Assume all rental income meets this criteria (rest is earned): # "gross income minus the cost of doing business derived from rental # property in which a household member is not actively engaged in the diff --git a/policyengine_us/tests/policy/baseline/gov/irs/income/taxable_income/adjusted_gross_income/irs_gross_income/military_retirement_pay.yaml b/policyengine_us/tests/policy/baseline/gov/irs/income/taxable_income/adjusted_gross_income/irs_gross_income/military_retirement_pay.yaml new file mode 100644 index 00000000000..8dccdb84493 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/irs/income/taxable_income/adjusted_gross_income/irs_gross_income/military_retirement_pay.yaml @@ -0,0 +1,95 @@ +# IRC § 61(a)(11) includes pensions, including military retirement pay and +# military retirement survivor benefit payments, in gross income. +# Military retirement pay is also market income, SNAP unearned income, +# and SSI unearned income. + +- name: Military retirement pay flows into federal gross income, AGI, and taxable income + period: 2024 + absolute_error_margin: 1 + input: + people: + person: + age: 60 + is_tax_unit_head: true + military_retirement_pay: 30_000 + tax_units: + tax_unit: + members: [person] + households: + household: + members: [person] + state_code: TX + output: + irs_gross_income: 30_000 + adjusted_gross_income: 30_000 + market_income: 30_000 + snap_unearned_income: 30_000 + ssi_unearned_income: 30_000 + +- name: Military retirement pay survivors flows into federal gross income, AGI, and taxable income + period: 2024 + absolute_error_margin: 1 + input: + people: + person: + age: 60 + is_tax_unit_head: true + military_retirement_pay_survivors: 25_000 + tax_units: + tax_unit: + members: [person] + households: + household: + members: [person] + state_code: TX + output: + irs_gross_income: 25_000 + adjusted_gross_income: 25_000 + market_income: 25_000 + snap_unearned_income: 25_000 + ssi_unearned_income: 25_000 + +- name: Military retirement pay adds with employment income + period: 2024 + input: + people: + person: + age: 50 + is_tax_unit_head: true + employment_income: 40_000 + military_retirement_pay: 20_000 + military_retirement_pay_survivors: 10_000 + tax_units: + tax_unit: + members: [person] + households: + household: + members: [person] + state_code: TX + output: + irs_gross_income: 70_000 + adjusted_gross_income: 70_000 + market_income: 70_000 + +- name: Dependent military retirement pay is excluded from the tax unit filer gross income + period: 2024 + input: + people: + head: + age: 45 + is_tax_unit_head: true + employment_income: 50_000 + dependent: + age: 18 + is_tax_unit_dependent: true + military_retirement_pay_survivors: 15_000 + tax_units: + tax_unit: + members: [head, dependent] + households: + household: + members: [head, dependent] + state_code: TX + output: + irs_gross_income: [50_000, 0] + adjusted_gross_income: 50_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/ca_taxable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/ca_taxable_income.yaml index 0b8fa6db0c6..88ec985eb7a 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/ca_taxable_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/ca_taxable_income.yaml @@ -15,3 +15,14 @@ state_code: CA output: ca_taxable_income: 10_000 - 4_900 + +- name: Military retirement pay flows into CA taxable income via federal AGI + period: 2024 + input: + military_retirement_pay: 50_000 + ca_deductions: 5_363 + state_code: CA + output: + ca_agi: 50_000 + ca_taxable_income: 50_000 - 5_363 + diff --git a/policyengine_us/tests/policy/baseline/gov/states/nc/tax/income/deductions/military_retirement/nc_military_retirement_deduction.yaml b/policyengine_us/tests/policy/baseline/gov/states/nc/tax/income/deductions/military_retirement/nc_military_retirement_deduction.yaml index 284887089b2..17e2f2ac373 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nc/tax/income/deductions/military_retirement/nc_military_retirement_deduction.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nc/tax/income/deductions/military_retirement/nc_military_retirement_deduction.yaml @@ -117,14 +117,11 @@ employment_income: 60_000 years_in_military: 20 military_retirement_pay: 20_000 - # Military pension descriptors do not add themselves to federal AGI. - taxable_public_pension_income: 20_000 person2: # A civilian spouse receiving Survivor Benefit Plan payments as the # beneficiary of a former spouse who retired after 20 years. age: 48 military_retirement_pay: 10_000 - taxable_public_pension_income: 10_000 nc_military_retirement_survivor_eligible: true tax_units: tax_unit: @@ -153,7 +150,6 @@ # The deceased member met the service test, but the recipient does not. military_retirement_pay_survivors: 10_000 nc_military_retirement_survivor_eligible: true - taxable_public_pension_income: 30_000 state_code: NC output: adjusted_gross_income: 30_000 @@ -165,7 +161,6 @@ age: 50 military_retirement_pay: 20_000 military_retirement_pay_survivors: 10_000 - taxable_public_pension_income: 30_000 # The caller supplies own-pay eligibility instead of service inputs. nc_military_retirement_deduction_eligible: true nc_military_retirement_survivor_eligible: false @@ -181,14 +176,12 @@ person1: age: 50 military_retirement_pay: 20_000 - taxable_public_pension_income: 20_000 nc_military_retirement_deduction_eligible: true person2: age: 48 years_in_military: 20 military_retirement_pay: 10_000 military_retirement_pay_survivors: 5_000 - taxable_public_pension_income: 15_000 # The head opens the unit's gate, but the spouse's explicit false # input must not be overridden by recomputing their service test. nc_military_retirement_deduction_eligible: false @@ -290,14 +283,12 @@ age: 50 years_in_military: 20 military_retirement_pay: 20_000 - taxable_public_pension_income: 20_000 # Supplying the spouse's eligibility makes this variable an input # for every member, so also supply the qualifying head's value. nc_military_retirement_deduction_eligible: true person2: age: 48 military_retirement_pay_survivors: 5_000 - taxable_public_pension_income: 5_000 # The head opens the unit's gate, but the spouse's explicit false # must also exclude separately recorded survivor benefits. nc_military_retirement_deduction_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/vt/tax/income/agi/subtractions/vt_retirement_income_exemption.yaml b/policyengine_us/tests/policy/baseline/gov/states/vt/tax/income/agi/subtractions/vt_retirement_income_exemption.yaml index 2f741281a38..9ed82a14d15 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/vt/tax/income/agi/subtractions/vt_retirement_income_exemption.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/vt/tax/income/agi/subtractions/vt_retirement_income_exemption.yaml @@ -285,7 +285,7 @@ person: age: 66 military_retirement_pay: 30_000 - employment_income: 60_000 # military_retirement_pay is not itself wired into AGI + employment_income: 30_000 tax_units: tax_unit: members: [person] @@ -306,7 +306,7 @@ person: age: 66 military_retirement_pay: 30_000 - employment_income: 100_000 # military_retirement_pay is not itself wired into AGI + employment_income: 70_000 tax_units: tax_unit: members: [person] @@ -327,7 +327,7 @@ person: age: 66 military_retirement_pay: 30_000 - employment_income: 150_000 # military_retirement_pay is not itself wired into AGI + employment_income: 120_000 tax_units: tax_unit: members: [person] diff --git a/policyengine_us/variables/gov/states/ar/tax/income/exemptions/ar_military_retirement_income_person.py b/policyengine_us/variables/gov/states/ar/tax/income/exemptions/ar_military_retirement_income_person.py index 5eb6c9345f5..faa8e489f52 100644 --- a/policyengine_us/variables/gov/states/ar/tax/income/exemptions/ar_military_retirement_income_person.py +++ b/policyengine_us/variables/gov/states/ar/tax/income/exemptions/ar_military_retirement_income_person.py @@ -12,5 +12,12 @@ class ar_military_retirement_income_person(Variable): def formula(person, period, parameters): head_or_spouse = person("is_tax_unit_head_or_spouse", period) - military_retirement_pay = person("military_retirement_pay", period) + military_retirement_pay = add( + person, + period, + [ + "military_retirement_pay", + "military_retirement_pay_survivors", + ], + ) return military_retirement_pay * head_or_spouse diff --git a/policyengine_us/variables/gov/states/az/tax/income/subtractions/az_military_retirement_subtraction.py b/policyengine_us/variables/gov/states/az/tax/income/subtractions/az_military_retirement_subtraction.py index 78cfa7c7e54..43f3372eff8 100644 --- a/policyengine_us/variables/gov/states/az/tax/income/subtractions/az_military_retirement_subtraction.py +++ b/policyengine_us/variables/gov/states/az/tax/income/subtractions/az_military_retirement_subtraction.py @@ -18,7 +18,11 @@ def formula(tax_unit, period, parameters): p = parameters(period).gov.states.az.tax.income.subtractions.military_retirement person = tax_unit.members head_or_spouse = person("is_tax_unit_head_or_spouse", period) - military_retirement_pay = person("military_retirement_pay", period) + military_retirement_pay = add( + person, + period, + ["military_retirement_pay", "military_retirement_pay_survivors"], + ) eligible_military_pay = military_retirement_pay * head_or_spouse capped_military_pay = min_(eligible_military_pay, p.max_amount) return tax_unit.sum(capped_military_pay) diff --git a/policyengine_us/variables/gov/states/ne/tax/income/adjusted_gross_income/subtractions/ne_military_retirement_substraction.py b/policyengine_us/variables/gov/states/ne/tax/income/adjusted_gross_income/subtractions/ne_military_retirement_subtraction.py similarity index 87% rename from policyengine_us/variables/gov/states/ne/tax/income/adjusted_gross_income/subtractions/ne_military_retirement_substraction.py rename to policyengine_us/variables/gov/states/ne/tax/income/adjusted_gross_income/subtractions/ne_military_retirement_subtraction.py index 214de6b0576..5f26d9b7ef0 100644 --- a/policyengine_us/variables/gov/states/ne/tax/income/adjusted_gross_income/subtractions/ne_military_retirement_substraction.py +++ b/policyengine_us/variables/gov/states/ne/tax/income/adjusted_gross_income/subtractions/ne_military_retirement_subtraction.py @@ -23,7 +23,14 @@ def formula(tax_unit, period, parameters): person = tax_unit.members age = person("age", period) age_eligible = age >= p.age_threshold - military_retirement_benefit = person("military_retirement_pay", period) + military_retirement_benefit = add( + person, + period, + [ + "military_retirement_pay", + "military_retirement_pay_survivors", + ], + ) # Dependents' income is not in federal AGI; they report it on their # own return. head_or_spouse = person("is_tax_unit_head_or_spouse", period) diff --git a/policyengine_us/variables/gov/states/nm/tax/income/exemptions/nm_armed_forces_retirement_pay_exemption_person.py b/policyengine_us/variables/gov/states/nm/tax/income/exemptions/nm_armed_forces_retirement_pay_exemption_person.py index 6e4d9988ec0..febf44d585c 100644 --- a/policyengine_us/variables/gov/states/nm/tax/income/exemptions/nm_armed_forces_retirement_pay_exemption_person.py +++ b/policyengine_us/variables/gov/states/nm/tax/income/exemptions/nm_armed_forces_retirement_pay_exemption_person.py @@ -14,7 +14,14 @@ def formula(person, period, parameters): p = parameters( period ).gov.states.nm.tax.income.exemptions.armed_forces_retirement_pay - armed_forces_retirement_pay = person("military_retirement_pay", period) + armed_forces_retirement_pay = add( + person, + period, + [ + "military_retirement_pay", + "military_retirement_pay_survivors", + ], + ) capped_amount = min_(armed_forces_retirement_pay, p.cap) qualifies = person("is_tax_unit_head_or_spouse", period) return qualifies * capped_amount diff --git a/policyengine_us/variables/gov/states/ok/tax/income/subtractions/ok_military_retirement_exclusion.py b/policyengine_us/variables/gov/states/ok/tax/income/subtractions/ok_military_retirement_exclusion.py index a686e17469f..9742e080117 100644 --- a/policyengine_us/variables/gov/states/ok/tax/income/subtractions/ok_military_retirement_exclusion.py +++ b/policyengine_us/variables/gov/states/ok/tax/income/subtractions/ok_military_retirement_exclusion.py @@ -24,7 +24,14 @@ def formula(tax_unit, period, parameters): period ).gov.states.ok.tax.income.agi.subtractions.military_retirement person = tax_unit.members - military_retirement_benefits = person("military_retirement_pay", period) + military_retirement_benefits = add( + person, + period, + [ + "military_retirement_pay", + "military_retirement_pay_survivors", + ], + ) adjust_military_retirement_amount = military_retirement_benefits * p.rate capped_exclusion_amount = max_(p.floor, adjust_military_retirement_amount) # Dependents' income is not in federal AGI; they report it on their diff --git a/policyengine_us/variables/gov/states/ut/tax/income/credits/military_retirement_credit/ut_military_retirement_credit_eligible.py b/policyengine_us/variables/gov/states/ut/tax/income/credits/military_retirement_credit/ut_military_retirement_credit_eligible.py index cade8f049d3..8024b88d32b 100644 --- a/policyengine_us/variables/gov/states/ut/tax/income/credits/military_retirement_credit/ut_military_retirement_credit_eligible.py +++ b/policyengine_us/variables/gov/states/ut/tax/income/credits/military_retirement_credit/ut_military_retirement_credit_eligible.py @@ -12,8 +12,13 @@ class ut_military_retirement_credit_eligible(Variable): def formula(tax_unit, period, parameters): # Has military retirement pay included in federal AGI, which excludes # dependents' income; dependents report it on their own return. - military_retirement_pay = tax_unit_non_dep_sum( - "military_retirement_pay", tax_unit, period + military_retirement_pay = tax_unit_non_dep_add( + tax_unit, + period, + [ + "military_retirement_pay", + "military_retirement_pay_survivors", + ], ) has_military_retirement_pay = military_retirement_pay > 0 # Cannot claim if claiming the retirement credit (code 18) 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 dfd712fefa9..66d7340dcf8 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 @@ -14,8 +14,13 @@ 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_sum( - "military_retirement_pay", tax_unit, period + military_retirement_pay = tax_unit_non_dep_add( + tax_unit, + period, + [ + "military_retirement_pay", + "military_retirement_pay_survivors", + ], ) 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/va/tax/income/subtractions/va_military_benefit_subtraction_person.py b/policyengine_us/variables/gov/states/va/tax/income/subtractions/va_military_benefit_subtraction_person.py index 7196e7e2112..72fb9f88c15 100644 --- a/policyengine_us/variables/gov/states/va/tax/income/subtractions/va_military_benefit_subtraction_person.py +++ b/policyengine_us/variables/gov/states/va/tax/income/subtractions/va_military_benefit_subtraction_person.py @@ -12,7 +12,17 @@ class va_military_benefit_subtraction_person(Variable): def formula(person, period, parameters): p = parameters(period).gov.states.va.tax.income.subtractions.military_benefit - subtractable = min_(person("military_retirement_pay", period), p.amount) + subtractable = min_( + add( + person, + period, + [ + "military_retirement_pay", + "military_retirement_pay_survivors", + ], + ), + p.amount, + ) eligible = person("is_tax_unit_head_or_spouse", period) if p.availability: eligible = eligible & (person("age", period) >= p.age_threshold) diff --git a/policyengine_us/variables/gov/states/vt/tax/income/adjusted_gross_income/subtractions/retirement_income_exemption/vt_military_retirement_cap_based_exemption.py b/policyengine_us/variables/gov/states/vt/tax/income/adjusted_gross_income/subtractions/retirement_income_exemption/vt_military_retirement_cap_based_exemption.py index 577a7eec701..db8fd660021 100644 --- a/policyengine_us/variables/gov/states/vt/tax/income/adjusted_gross_income/subtractions/retirement_income_exemption/vt_military_retirement_cap_based_exemption.py +++ b/policyengine_us/variables/gov/states/vt/tax/income/adjusted_gross_income/subtractions/retirement_income_exemption/vt_military_retirement_cap_based_exemption.py @@ -21,8 +21,13 @@ def formula(tax_unit, period, parameters): # Get retirement amount from military retirement system # Dependents' income is not in federal AGI; they report it on their # own return, so only the head's and spouse's pay counts. - tax_unit_military_retirement_pay = tax_unit_non_dep_sum( - "military_retirement_pay", tax_unit, period + tax_unit_military_retirement_pay = tax_unit_non_dep_add( + tax_unit, + period, + [ + "military_retirement_pay", + "military_retirement_pay_survivors", + ], ) # Cap exemption at the specified amount diff --git a/policyengine_us/variables/gov/states/vt/tax/income/adjusted_gross_income/subtractions/retirement_income_exemption/vt_military_retirement_income_based_exemption.py b/policyengine_us/variables/gov/states/vt/tax/income/adjusted_gross_income/subtractions/retirement_income_exemption/vt_military_retirement_income_based_exemption.py index 387a12db3dc..daaa6469859 100644 --- a/policyengine_us/variables/gov/states/vt/tax/income/adjusted_gross_income/subtractions/retirement_income_exemption/vt_military_retirement_income_based_exemption.py +++ b/policyengine_us/variables/gov/states/vt/tax/income/adjusted_gross_income/subtractions/retirement_income_exemption/vt_military_retirement_income_based_exemption.py @@ -20,8 +20,13 @@ def formula(tax_unit, period, parameters): # Get retirement amount from military retirement system # Dependents' income is not in federal AGI; they report it on their # own return, so only the head's and spouse's pay counts. - tax_unit_military_retirement_pay = tax_unit_non_dep_sum( - "military_retirement_pay", tax_unit, period + tax_unit_military_retirement_pay = tax_unit_non_dep_add( + tax_unit, + period, + [ + "military_retirement_pay", + "military_retirement_pay_survivors", + ], ) agi = tax_unit("adjusted_gross_income", period) diff --git a/policyengine_us/variables/gov/states/vt/tax/income/adjusted_gross_income/subtractions/retirement_income_exemption/vt_military_retirement_pay_exclusion.py b/policyengine_us/variables/gov/states/vt/tax/income/adjusted_gross_income/subtractions/retirement_income_exemption/vt_military_retirement_pay_exclusion.py index 64e81b7660b..84b0d3663ed 100644 --- a/policyengine_us/variables/gov/states/vt/tax/income/adjusted_gross_income/subtractions/retirement_income_exemption/vt_military_retirement_pay_exclusion.py +++ b/policyengine_us/variables/gov/states/vt/tax/income/adjusted_gross_income/subtractions/retirement_income_exemption/vt_military_retirement_pay_exclusion.py @@ -19,8 +19,13 @@ def formula(tax_unit, period, parameters): # Get retirement amount from military retirement system # Dependents' income is not in federal AGI; they report it on their # own return, so only the head's and spouse's pay counts. - tax_unit_military_retirement_pay = tax_unit_non_dep_sum( - "military_retirement_pay", tax_unit, period + tax_unit_military_retirement_pay = tax_unit_non_dep_add( + tax_unit, + period, + [ + "military_retirement_pay", + "military_retirement_pay_survivors", + ], ) # S.51 (2025): Income-based military pension exemption diff --git a/policyengine_us/variables/gov/states/vt/tax/income/adjusted_gross_income/subtractions/retirement_income_exemption/vt_retirement_income_exemption_eligible.py b/policyengine_us/variables/gov/states/vt/tax/income/adjusted_gross_income/subtractions/retirement_income_exemption/vt_retirement_income_exemption_eligible.py index b5b64167c1a..c2c08f0c857 100644 --- a/policyengine_us/variables/gov/states/vt/tax/income/adjusted_gross_income/subtractions/retirement_income_exemption/vt_retirement_income_exemption_eligible.py +++ b/policyengine_us/variables/gov/states/vt/tax/income/adjusted_gross_income/subtractions/retirement_income_exemption/vt_retirement_income_exemption_eligible.py @@ -31,6 +31,7 @@ def formula(tax_unit, period, parameters): [ "tax_unit_taxable_social_security", "military_retirement_pay", + "military_retirement_pay_survivors", "csrs_retirement_pay", ], ) diff --git a/policyengine_us/variables/household/income/person/general/market_income.py b/policyengine_us/variables/household/income/person/general/market_income.py index a8dd2902b24..391afa7e4ad 100644 --- a/policyengine_us/variables/household/income/person/general/market_income.py +++ b/policyengine_us/variables/household/income/person/general/market_income.py @@ -27,5 +27,7 @@ def formula(person, period, parameters): "alimony_income", "strike_benefits", "retirement_distributions", + "military_retirement_pay", + "military_retirement_pay_survivors", ] return add(person, period, COMPONENTS) From 09b63b78b43f0076b1552672f6c9ea37557f707e Mon Sep 17 00:00:00 2001 From: Deepak Jindal Date: Mon, 12 Oct 2026 19:41:53 -0700 Subject: [PATCH 2/5] Add military_retirement_pay_survivors to AR gross income code health check --- .../code_health/test_ar_gross_income_source_line_comments.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/policyengine_us/tests/code_health/test_ar_gross_income_source_line_comments.py b/policyengine_us/tests/code_health/test_ar_gross_income_source_line_comments.py index 3dc05f9dd9b..5af5ffe9139 100644 --- a/policyengine_us/tests/code_health/test_ar_gross_income_source_line_comments.py +++ b/policyengine_us/tests/code_health/test_ar_gross_income_source_line_comments.py @@ -46,6 +46,7 @@ "taxable_ira_distributions": "16", "taxable_roth_conversions": "16", "military_retirement_pay": "17A/17B", + "military_retirement_pay_survivors": "17A/17B", "taxable_pension_income": "17A/17B", "disability_benefits": "17A/17B", "rental_income": "18", @@ -67,6 +68,7 @@ "taxable_ira_distributions": "16", "taxable_roth_conversions": "16", "military_retirement_pay": "17", + "military_retirement_pay_survivors": "17", "taxable_pension_income": "18A/18B", "taxable_401k_distributions": "18A/18B", "taxable_403b_distributions": "18A/18B", From a08169daead86049f1586faf7bc019e2e0890902 Mon Sep 17 00:00:00 2001 From: Deepak Jindal Date: Wed, 14 Oct 2026 14:16:50 -0700 Subject: [PATCH 3/5] Address review feedback on military retirement and survivor pay handling across states --- .../wire-military-retirement-pay.fixed.md | 9 ++- .../gov/household/market_income_sources.yaml | 2 + .../agi/military_retirement/agi_limit.yaml | 35 +++++++++++ .../income/agi/military_retirement/cap.yaml | 11 ++++ .../ca/tax/income/agi/subtractions.yaml | 6 ++ .../dc/tax/income/subtractions/sources.yaml | 1 + .../survivor_benefits/min_age.yaml | 9 +++ .../exclusions/pension/income_sources.yaml | 2 + .../agi/exclusions/retirement/sources.yaml | 1 - .../tax/income/subtractions/subtractions.yaml | 4 ++ .../income/taxable_income/subtractions.yaml | 4 +- .../il/tax/income/base/subtractions.yaml | 2 + .../in/tax/income/deductions/deductions.yaml | 9 +++ .../deductions/military_retirement/base.yaml | 9 +++ .../military_retirement/excess_rate.yaml | 10 +++ .../income/subtractions/agi_subtractions.yaml | 2 + .../survivors_eligible.yaml | 16 +++++ .../tax/income/agi/subtractions/sources.yaml | 3 +- .../eligibility_income_sources.yaml | 2 + .../tax/income/nontaxable_income_sources.yaml | 2 + .../taxable_retirement_income/sources.yaml | 6 ++ .../wi/tax/income/subtractions/sources.yaml | 4 ++ .../military_retirement_pay.yaml | 63 +++++++++++-------- .../ca/tax/income/ca_taxable_income.yaml | 18 +++++- .../dc_survivor_benefits_subtraction.yaml | 33 ++++++++++ .../de_pension_exclusion.yaml | 22 +++++++ .../states/hi/tax/income/hi_subtractions.yaml | 30 +++++++++ .../in_military_retirement_deduction.yaml | 33 ++++++++++ .../me_pension_income_deduction.yaml | 25 ++++++++ ...ion_and_ss_or_ssd_deduction_section_a.yaml | 13 ++++ ..._services_retirement_income_deduction.yaml | 36 +++++++++++ .../wi_military_retirement_subtraction.yaml | 16 +++++ .../ca_military_retirement_exclusion.py | 32 ++++++++++ .../pension/co_pension_subtraction_indv.py | 6 +- .../dc_survivor_benefits_subtraction.py | 27 ++++++++ .../pension_exclusion/de_pension_exclusion.py | 6 +- ...ment_income_exclusion_retirement_income.py | 10 ++- .../id_military_retirement_deduction.py | 6 +- .../in_military_retirement_deduction.py | 28 +++++++++ .../income/deductions/in_other_deductions.py | 2 +- .../ks/tax/income/ks_agi_subtractions.py | 19 ++++-- .../ky_pension_income_exclusion.py | 10 ++- .../income/gross_income/ma_gross_income.py | 10 ++- .../md_pension_subtraction_amount.py | 17 ++++- .../me_pension_income_deduction.py | 8 ++- ...erest_dividends_capital_gains_deduction.py | 6 +- ..._expanded_retirement_benefits_deduction.py | 5 +- ...ment_benefits_deduction_tier_one_amount.py | 5 +- ...uction_tier_three_ss_exempt_not_retired.py | 9 +-- ..._deduction_tier_three_ss_exempt_retired.py | 9 +-- .../mi_standard_deduction_tier_three.py | 6 +- .../mi_standard_deduction_tier_two.py | 6 +- .../tax/income/amt/mn_amt_taxable_income.py | 1 + ...nsion_and_ss_or_ssd_deduction_section_a.py | 5 +- .../ne_military_retirement_subtraction.py | 14 ++--- ...ed_services_retirement_income_deduction.py | 12 +++- .../retirement_credit/or_retirement_credit.py | 7 ++- ...military_retirement_cap_based_exemption.py | 9 +-- .../vt_military_retirement_pay_exclusion.py | 13 ---- ...vt_retirement_income_exemption_eligible.py | 14 +++-- .../retirement/military_retirement_pay.py | 10 ++- .../military_retirement_pay_survivors.py | 11 ++++ 62 files changed, 653 insertions(+), 108 deletions(-) create mode 100644 policyengine_us/parameters/gov/states/ca/tax/income/agi/military_retirement/agi_limit.yaml create mode 100644 policyengine_us/parameters/gov/states/ca/tax/income/agi/military_retirement/cap.yaml create mode 100644 policyengine_us/parameters/gov/states/dc/tax/income/subtractions/survivor_benefits/min_age.yaml create mode 100644 policyengine_us/parameters/gov/states/in/tax/income/deductions/military_retirement/base.yaml create mode 100644 policyengine_us/parameters/gov/states/in/tax/income/deductions/military_retirement/excess_rate.yaml create mode 100644 policyengine_us/parameters/gov/states/ne/tax/income/agi/subtractions/military_retirement/survivors_eligible.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/dc/tax/income/subtractions/dc_survivor_benefits_subtraction.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/in/tax/income/deductions/in_military_retirement_deduction.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/oh/tax/income/deductions/oh_uniformed_services_retirement_income_deduction.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/wi/tax/income/subtractions/wi_military_retirement_subtraction.yaml create mode 100644 policyengine_us/variables/gov/states/ca/tax/income/ca_military_retirement_exclusion.py create mode 100644 policyengine_us/variables/gov/states/dc/tax/income/subtractions/dc_survivor_benefits_subtraction.py create mode 100644 policyengine_us/variables/gov/states/in/tax/income/deductions/in_military_retirement_deduction.py diff --git a/changelog.d/wire-military-retirement-pay.fixed.md b/changelog.d/wire-military-retirement-pay.fixed.md index 4b9f113c81f..91a68e64f52 100644 --- a/changelog.d/wire-military-retirement-pay.fixed.md +++ b/changelog.d/wire-military-retirement-pay.fixed.md @@ -1 +1,8 @@ -Add military retirement pay and survivor benefits to federal gross income, market income, and SNAP and SSI unearned income sources. +Wire military retirement pay and military retirement pay survivors to federal gross income (`irs_gross_income`), person `market_income`, household `market_income_sources`, SNAP unearned income, and SSI unearned income. Update state tax calculations and exclusions across all affected states to conform with federal AGI inclusion and statutory state treatment: +- State military retirement and survivor subtractions added or updated in AR, AZ, CA, CO, CT, DC, DE, GA, HI, IA, ID, IL, IN, KS, KY, LA, MA, MD, ME, MI, MN, MO, ND, NE, NM, NY, OH, OK, OR, PA, RI, UT, VA, VT, WV. +- Fix Georgia double-counting under O.C.G.A. § 48-7-27(a)(5)(E) and Rule 560-7-4-.02(3). +- Model California 2025–2029 military retirement and SBP exclusion under R&TC §§ 17132.9–17132.10. +- Model Indiana military retirement deduction under IC 6-3-2-4. +- Model DC survivor benefits exclusion for age 62+ under D.C. Code § 47-1803.02(a)(2)(N)(ii). +- Update Michigan retirement worksheets to account for military survivor benefits. +- Update variable docstrings and references referencing IRC § 61(a)(10) and IRS Pubs 525/575. diff --git a/policyengine_us/parameters/gov/household/market_income_sources.yaml b/policyengine_us/parameters/gov/household/market_income_sources.yaml index b5c78f13734..e565944ad98 100644 --- a/policyengine_us/parameters/gov/household/market_income_sources.yaml +++ b/policyengine_us/parameters/gov/household/market_income_sources.yaml @@ -15,6 +15,8 @@ values: - dividend_income - pension_income # Pension income includes annuities and endowment contracts + - military_retirement_pay + - military_retirement_pay_survivors - debt_relief # Income from estates and trusts (Schedule E Part III), including income # in respect of a decedent received through an estate or trust. diff --git a/policyengine_us/parameters/gov/states/ca/tax/income/agi/military_retirement/agi_limit.yaml b/policyengine_us/parameters/gov/states/ca/tax/income/agi/military_retirement/agi_limit.yaml new file mode 100644 index 00000000000..e90c310d33a --- /dev/null +++ b/policyengine_us/parameters/gov/states/ca/tax/income/agi/military_retirement/agi_limit.yaml @@ -0,0 +1,35 @@ +description: Federal AGI limit to qualify for California military retirement and SBP exclusion under R&TC §§ 17132.9 and 17132.10. +metadata: + unit: currency-USD + period: year + breakdown: + - filing_status + reference: + - title: Cal. Rev. & Tax. Code §§ 17132.9, 17132.10 + href: https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?sectionNum=17132.9.&lawCode=RTC + +SINGLE: + values: + 2021-01-01: 0 + 2025-01-01: 125000 + 2030-01-01: 0 +JOINT: + values: + 2021-01-01: 0 + 2025-01-01: 250000 + 2030-01-01: 0 +SEPARATE: + values: + 2021-01-01: 0 + 2025-01-01: 125000 + 2030-01-01: 0 +HEAD_OF_HOUSEHOLD: + values: + 2021-01-01: 0 + 2025-01-01: 125000 + 2030-01-01: 0 +SURVIVING_SPOUSE: + values: + 2021-01-01: 0 + 2025-01-01: 250000 + 2030-01-01: 0 diff --git a/policyengine_us/parameters/gov/states/ca/tax/income/agi/military_retirement/cap.yaml b/policyengine_us/parameters/gov/states/ca/tax/income/agi/military_retirement/cap.yaml new file mode 100644 index 00000000000..033e8ad9884 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ca/tax/income/agi/military_retirement/cap.yaml @@ -0,0 +1,11 @@ +description: California maximum military retirement and SBP exclusion amount per category per person under R&TC §§ 17132.9 and 17132.10. +values: + 2021-01-01: 0 + 2025-01-01: 20000 + 2030-01-01: 0 +metadata: + unit: currency-USD + period: year + reference: + - title: Cal. Rev. & Tax. Code §§ 17132.9, 17132.10 + href: https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?sectionNum=17132.9.&lawCode=RTC diff --git a/policyengine_us/parameters/gov/states/ca/tax/income/agi/subtractions.yaml b/policyengine_us/parameters/gov/states/ca/tax/income/agi/subtractions.yaml index afe1c819140..702fc0bc886 100644 --- a/policyengine_us/parameters/gov/states/ca/tax/income/agi/subtractions.yaml +++ b/policyengine_us/parameters/gov/states/ca/tax/income/agi/subtractions.yaml @@ -5,6 +5,12 @@ values: - taxable_unemployment_compensation - us_govt_interest - salt_refund_income + 2025-01-01: + - taxable_social_security + - taxable_unemployment_compensation + - us_govt_interest + - salt_refund_income + - ca_military_retirement_exclusion metadata: reference: diff --git a/policyengine_us/parameters/gov/states/dc/tax/income/subtractions/sources.yaml b/policyengine_us/parameters/gov/states/dc/tax/income/subtractions/sources.yaml index 8ba9d6dafad..0769b131ae3 100644 --- a/policyengine_us/parameters/gov/states/dc/tax/income/subtractions/sources.yaml +++ b/policyengine_us/parameters/gov/states/dc/tax/income/subtractions/sources.yaml @@ -21,3 +21,4 @@ values: - dc_disability_exclusion - us_govt_interest_person - salt_refund_income + - dc_survivor_benefits_subtraction diff --git a/policyengine_us/parameters/gov/states/dc/tax/income/subtractions/survivor_benefits/min_age.yaml b/policyengine_us/parameters/gov/states/dc/tax/income/subtractions/survivor_benefits/min_age.yaml new file mode 100644 index 00000000000..62b7119466e --- /dev/null +++ b/policyengine_us/parameters/gov/states/dc/tax/income/subtractions/survivor_benefits/min_age.yaml @@ -0,0 +1,9 @@ +description: Minimum age to exclude government survivor benefits in DC. +values: + 2015-01-01: 62 +metadata: + unit: year + period: year + reference: + - title: D.C. Code § 47-1803.02(a)(2)(N)(ii) + href: https://code.dccouncil.gov/us/dc/council/code/sections/47-1803.02 diff --git a/policyengine_us/parameters/gov/states/de/tax/income/subtractions/exclusions/pension/income_sources.yaml b/policyengine_us/parameters/gov/states/de/tax/income/subtractions/exclusions/pension/income_sources.yaml index 68d01d3af09..fbdab67a336 100644 --- a/policyengine_us/parameters/gov/states/de/tax/income/subtractions/exclusions/pension/income_sources.yaml +++ b/policyengine_us/parameters/gov/states/de/tax/income/subtractions/exclusions/pension/income_sources.yaml @@ -6,6 +6,8 @@ values: - taxable_interest_income - rental_income - taxable_pension_income + - military_retirement_pay + - military_retirement_pay_survivors - taxable_ira_distributions - taxable_401k_distributions - taxable_403b_distributions diff --git a/policyengine_us/parameters/gov/states/ga/tax/income/agi/exclusions/retirement/sources.yaml b/policyengine_us/parameters/gov/states/ga/tax/income/agi/exclusions/retirement/sources.yaml index 447b2d2a5cd..a8ad771452e 100644 --- a/policyengine_us/parameters/gov/states/ga/tax/income/agi/exclusions/retirement/sources.yaml +++ b/policyengine_us/parameters/gov/states/ga/tax/income/agi/exclusions/retirement/sources.yaml @@ -28,5 +28,4 @@ values: - taxable_sep_distributions - keogh_distributions - taxable_roth_conversions - - military_retirement_pay - military_retirement_pay_survivors diff --git a/policyengine_us/parameters/gov/states/hi/tax/income/subtractions/subtractions.yaml b/policyengine_us/parameters/gov/states/hi/tax/income/subtractions/subtractions.yaml index 241ecdea1a0..24605dce1a7 100644 --- a/policyengine_us/parameters/gov/states/hi/tax/income/subtractions/subtractions.yaml +++ b/policyengine_us/parameters/gov/states/hi/tax/income/subtractions/subtractions.yaml @@ -2,12 +2,16 @@ description: Hawaii subtracts these sources from adjusted gross income. values: 2021-01-01: - taxable_pension_income # Line 13 + - military_retirement_pay # Line 13 + - military_retirement_pay_survivors # Line 13 - taxable_social_security # Line 14 - hi_military_pay_exclusion # Line 15 - us_govt_interest # Line 18 - student_loan_interest_ald # Line 18 2025-01-01: - taxable_pension_income # Line 13 + - military_retirement_pay # Line 13 + - military_retirement_pay_survivors # Line 13 - taxable_social_security # Line 14 - hi_military_pay_exclusion # Line 15 - us_govt_interest # Line 18 diff --git a/policyengine_us/parameters/gov/states/ia/tax/income/taxable_income/subtractions.yaml b/policyengine_us/parameters/gov/states/ia/tax/income/taxable_income/subtractions.yaml index 78458a82846..8ec924b5ea4 100644 --- a/policyengine_us/parameters/gov/states/ia/tax/income/taxable_income/subtractions.yaml +++ b/policyengine_us/parameters/gov/states/ia/tax/income/taxable_income/subtractions.yaml @@ -4,6 +4,8 @@ values: # Line 1B - us_govt_interest # Dividends from federal securities + - military_retirement_pay + - military_retirement_pay_survivors # Line 5B - taxable_social_security # Line 6B @@ -15,7 +17,7 @@ values: # Iowa Health Insurance Deduction # Iowa capital gains deduction - ia_529_plan_subtraction - 2024-01-01: # military_retirement_pay added in 2024. + 2024-01-01: # Line 4B on 2024 Form IA 1040 # Line 1B - us_govt_interest # Dividends from federal securities diff --git a/policyengine_us/parameters/gov/states/il/tax/income/base/subtractions.yaml b/policyengine_us/parameters/gov/states/il/tax/income/base/subtractions.yaml index 0ec538b1f97..a01b72bbbaf 100644 --- a/policyengine_us/parameters/gov/states/il/tax/income/base/subtractions.yaml +++ b/policyengine_us/parameters/gov/states/il/tax/income/base/subtractions.yaml @@ -6,6 +6,8 @@ values: - taxable_pension_income - taxable_retirement_distributions - taxable_roth_conversions + - military_retirement_pay + - military_retirement_pay_survivors - il_schedule_m_subtractions - il_529_plan_subtraction - salt_refund_income diff --git a/policyengine_us/parameters/gov/states/in/tax/income/deductions/deductions.yaml b/policyengine_us/parameters/gov/states/in/tax/income/deductions/deductions.yaml index 8debf2504a8..876b0139a12 100644 --- a/policyengine_us/parameters/gov/states/in/tax/income/deductions/deductions.yaml +++ b/policyengine_us/parameters/gov/states/in/tax/income/deductions/deductions.yaml @@ -12,6 +12,7 @@ values: - in_unemployment_compensation_deduction - in_other_deductions - in_civil_service_annuity_deduction + - in_military_retirement_deduction 2023-01-01: # IC 6-3-2-6 @@ -38,6 +39,8 @@ values: - military_basic_pay # IC 6-3-2-3.7 - in_civil_service_annuity_deduction + # IC 6-3-2-4(a) + - in_military_retirement_deduction 2024-01-01: # IC 6-3-2-6 @@ -66,6 +69,8 @@ values: - in_healthcare_sharing_deduction # IC 6-3-2-3.7 - in_civil_service_annuity_deduction + # IC 6-3-2-4(a) + - in_military_retirement_deduction 2026-01-01: # IC 6-3-2-6 @@ -100,6 +105,8 @@ values: - in_auto_loan_interest_deduction # IC 6-3-2-3.7 - in_civil_service_annuity_deduction + # IC 6-3-2-4(a) + - in_military_retirement_deduction 2027-01-01: # IC 6-3-2-6 @@ -128,6 +135,8 @@ values: - in_healthcare_sharing_deduction # IC 6-3-2-3.7 - in_civil_service_annuity_deduction + # IC 6-3-2-4(a) + - in_military_retirement_deduction metadata: unit: list diff --git a/policyengine_us/parameters/gov/states/in/tax/income/deductions/military_retirement/base.yaml b/policyengine_us/parameters/gov/states/in/tax/income/deductions/military_retirement/base.yaml new file mode 100644 index 00000000000..1845157e0de --- /dev/null +++ b/policyengine_us/parameters/gov/states/in/tax/income/deductions/military_retirement/base.yaml @@ -0,0 +1,9 @@ +description: Indiana base military retirement deduction amount. +values: + 2021-01-01: 6250 +metadata: + unit: currency-USD + period: year + reference: + - title: IC 6-3-2-4 + href: http://iga.in.gov/legislative/laws/2021/ic/titles/006#6-3-2-4 diff --git a/policyengine_us/parameters/gov/states/in/tax/income/deductions/military_retirement/excess_rate.yaml b/policyengine_us/parameters/gov/states/in/tax/income/deductions/military_retirement/excess_rate.yaml new file mode 100644 index 00000000000..bf9383d47c1 --- /dev/null +++ b/policyengine_us/parameters/gov/states/in/tax/income/deductions/military_retirement/excess_rate.yaml @@ -0,0 +1,10 @@ +description: Indiana rate of deduction for military retirement benefits exceeding the base amount. +values: + 2021-01-01: 0.75 + 2022-01-01: 1.0 +metadata: + unit: /1 + period: year + reference: + - title: IC 6-3-2-4 + href: http://iga.in.gov/legislative/laws/2021/ic/titles/006#6-3-2-4 diff --git a/policyengine_us/parameters/gov/states/mo/tax/income/subtractions/agi_subtractions.yaml b/policyengine_us/parameters/gov/states/mo/tax/income/subtractions/agi_subtractions.yaml index 9d81d585c0c..ed68d518c76 100644 --- a/policyengine_us/parameters/gov/states/mo/tax/income/subtractions/agi_subtractions.yaml +++ b/policyengine_us/parameters/gov/states/mo/tax/income/subtractions/agi_subtractions.yaml @@ -5,12 +5,14 @@ values: - us_govt_interest_person - mo_529_deduction - salt_refund_income # 143.121 RSMo / Form MO-A Line 9 + - military_retirement_pay # 143.121.3(12) RSMo / Form MO-A Line 10 2025-01-01: - mo_qualified_health_insurance_premiums - mo_capital_gains_subtraction_person - us_govt_interest_person - mo_529_deduction - salt_refund_income # 143.121 RSMo / Form MO-A Line 9 + - military_retirement_pay # 143.121.3(12) RSMo / Form MO-A Line 10 metadata: diff --git a/policyengine_us/parameters/gov/states/ne/tax/income/agi/subtractions/military_retirement/survivors_eligible.yaml b/policyengine_us/parameters/gov/states/ne/tax/income/agi/subtractions/military_retirement/survivors_eligible.yaml new file mode 100644 index 00000000000..e98017517e9 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ne/tax/income/agi/subtractions/military_retirement/survivors_eligible.yaml @@ -0,0 +1,16 @@ +description: Whether military retirement survivor benefit payments are eligible for the Nebraska military retirement subtraction. +values: + 2015-01-01: false + 2022-01-01: true + +metadata: + label: Nebraska military retirement survivor benefits eligible + unit: bool + period: year + reference: + - title: Neb. Rev. Stat. § 77-2716(15) + href: https://nebraskalegislature.gov/laws/statutes.php?statute=77-2716 + - title: 2021 Form 1040N-MIL + href: https://revenue.nebraska.gov/sites/revenue.nebraska.gov/files/doc/f_1040n_booklet.pdf#page=16 + - title: 2025 Form 1040N Schedule I, line 32 + href: https://revenue.nebraska.gov/sites/default/files/doc/tax-forms/2025/f_Individual_Income_Tax_Booklet.pdf#page=26 diff --git a/policyengine_us/parameters/gov/states/ny/tax/income/agi/subtractions/sources.yaml b/policyengine_us/parameters/gov/states/ny/tax/income/agi/subtractions/sources.yaml index 674a75e731a..f54fa63e677 100644 --- a/policyengine_us/parameters/gov/states/ny/tax/income/agi/subtractions/sources.yaml +++ b/policyengine_us/parameters/gov/states/ny/tax/income/agi/subtractions/sources.yaml @@ -8,8 +8,9 @@ values: - salt_refund_income # N.Y. Tax Law § 612(c)(3) / Form IT-201 Line 26: subtracts pensions paid by NY state, # local governments, or the federal government. Pensions from other states are not exempt. - # PolicyEngine subtracts taxable_public_pension_income as an in-state/federal proxy. - taxable_public_pension_income + - military_retirement_pay + - military_retirement_pay_survivors metadata: unit: list period: year diff --git a/policyengine_us/parameters/gov/states/pa/tax/income/forgiveness/eligibility_income_sources.yaml b/policyengine_us/parameters/gov/states/pa/tax/income/forgiveness/eligibility_income_sources.yaml index dc17bfc0a77..fbef577ec26 100644 --- a/policyengine_us/parameters/gov/states/pa/tax/income/forgiveness/eligibility_income_sources.yaml +++ b/policyengine_us/parameters/gov/states/pa/tax/income/forgiveness/eligibility_income_sources.yaml @@ -9,6 +9,8 @@ values: # gifts awards and prizes # non-PA income # nontaxable military income + - military_retirement_pay + - military_retirement_pay_survivors # gain excluded from the sale of a residence # nontaxable education assistance # cash received for personal use outside your home diff --git a/policyengine_us/parameters/gov/states/pa/tax/income/nontaxable_income_sources.yaml b/policyengine_us/parameters/gov/states/pa/tax/income/nontaxable_income_sources.yaml index e5270142c66..b5e95573307 100644 --- a/policyengine_us/parameters/gov/states/pa/tax/income/nontaxable_income_sources.yaml +++ b/policyengine_us/parameters/gov/states/pa/tax/income/nontaxable_income_sources.yaml @@ -8,6 +8,8 @@ values: - taxable_social_security - us_govt_interest - salt_refund_income + - military_retirement_pay + - military_retirement_pay_survivors metadata: unit: currency-USD label: PA nontaxable income sources diff --git a/policyengine_us/parameters/gov/states/ri/tax/income/agi/subtractions/taxable_retirement_income/sources.yaml b/policyengine_us/parameters/gov/states/ri/tax/income/agi/subtractions/taxable_retirement_income/sources.yaml index 07b706da34b..1ddcdf7ac62 100644 --- a/policyengine_us/parameters/gov/states/ri/tax/income/agi/subtractions/taxable_retirement_income/sources.yaml +++ b/policyengine_us/parameters/gov/states/ri/tax/income/agi/subtractions/taxable_retirement_income/sources.yaml @@ -1,6 +1,12 @@ description: Rhode Island subtracts these retirement income sources from adjusted gross income under the individual income tax retirement income subtraction program. values: 2021-01-01: + - taxable_pension_income + - military_retirement_pay + - military_retirement_pay_survivors + - taxable_401k_distributions + - taxable_403b_distributions + 2023-01-01: - taxable_pension_income - taxable_401k_distributions - taxable_403b_distributions diff --git a/policyengine_us/parameters/gov/states/wi/tax/income/subtractions/sources.yaml b/policyengine_us/parameters/gov/states/wi/tax/income/subtractions/sources.yaml index 9f9d8a3984c..6835cf08903 100644 --- a/policyengine_us/parameters/gov/states/wi/tax/income/subtractions/sources.yaml +++ b/policyengine_us/parameters/gov/states/wi/tax/income/subtractions/sources.yaml @@ -6,6 +6,8 @@ values: - wi_capital_gain_loss_subtraction - wi_childcare_expense_subtraction - wi_retirement_income_subtraction + - military_retirement_pay + - military_retirement_pay_survivors - us_govt_interest - wi_529_plan_deduction - salt_refund_income @@ -14,6 +16,8 @@ values: - tax_unit_taxable_social_security - wi_capital_gain_loss_subtraction - wi_retirement_income_subtraction + - military_retirement_pay + - military_retirement_pay_survivors - us_govt_interest - wi_529_plan_deduction - salt_refund_income diff --git a/policyengine_us/tests/policy/baseline/gov/irs/income/taxable_income/adjusted_gross_income/irs_gross_income/military_retirement_pay.yaml b/policyengine_us/tests/policy/baseline/gov/irs/income/taxable_income/adjusted_gross_income/irs_gross_income/military_retirement_pay.yaml index 8dccdb84493..e62d44de1bf 100644 --- a/policyengine_us/tests/policy/baseline/gov/irs/income/taxable_income/adjusted_gross_income/irs_gross_income/military_retirement_pay.yaml +++ b/policyengine_us/tests/policy/baseline/gov/irs/income/taxable_income/adjusted_gross_income/irs_gross_income/military_retirement_pay.yaml @@ -1,59 +1,64 @@ -# IRC § 61(a)(11) includes pensions, including military retirement pay and +# IRC § 61(a)(10) includes pensions, including military retirement pay and # military retirement survivor benefit payments, in gross income. +# See IRS Publication 525 (Taxable and Nontaxable Income) and +# IRS Publication 575 (Pension and Annuity Income). # Military retirement pay is also market income, SNAP unearned income, # and SSI unearned income. -- name: Military retirement pay flows into federal gross income, AGI, and taxable income +- name: Case 1, Military retirement pay flows into federal gross income, AGI, and taxable income. period: 2024 - absolute_error_margin: 1 input: people: - person: + person1: age: 60 is_tax_unit_head: true military_retirement_pay: 30_000 tax_units: tax_unit: - members: [person] + members: [person1] households: household: - members: [person] + members: [person1] state_code: TX output: irs_gross_income: 30_000 adjusted_gross_income: 30_000 + taxable_income: 30_000 - 14_600 market_income: 30_000 + household_market_income: 30_000 snap_unearned_income: 30_000 ssi_unearned_income: 30_000 + household_net_income: 28_915 -- name: Military retirement pay survivors flows into federal gross income, AGI, and taxable income +- name: Case 2, Military retirement pay survivors flows into federal gross income, AGI, and taxable income. period: 2024 - absolute_error_margin: 1 input: people: - person: + person1: age: 60 is_tax_unit_head: true - military_retirement_pay_survivors: 25_000 + military_retirement_pay_survivors: 24_000 tax_units: tax_unit: - members: [person] + members: [person1] households: household: - members: [person] + members: [person1] state_code: TX output: - irs_gross_income: 25_000 - adjusted_gross_income: 25_000 - market_income: 25_000 - snap_unearned_income: 25_000 - ssi_unearned_income: 25_000 + irs_gross_income: 24_000 + adjusted_gross_income: 24_000 + taxable_income: 24_000 - 14_600 + market_income: 24_000 + household_market_income: 24_000 + snap_unearned_income: 24_000 + ssi_unearned_income: 24_000 -- name: Military retirement pay adds with employment income +- name: Case 3, Military retirement pay adds with employment income. period: 2024 input: people: - person: + person1: age: 50 is_tax_unit_head: true employment_income: 40_000 @@ -61,35 +66,41 @@ military_retirement_pay_survivors: 10_000 tax_units: tax_unit: - members: [person] + members: [person1] households: household: - members: [person] + members: [person1] state_code: TX output: irs_gross_income: 70_000 adjusted_gross_income: 70_000 + taxable_income: 70_000 - 14_600 market_income: 70_000 + household_market_income: 70_000 + household_net_income: 59_699 -- name: Dependent military retirement pay is excluded from the tax unit filer gross income +- name: Case 4, Dependent military retirement pay is excluded from the tax unit filer gross income. period: 2024 input: people: - head: + person1: age: 45 is_tax_unit_head: true employment_income: 50_000 - dependent: + person2: age: 18 is_tax_unit_dependent: true military_retirement_pay_survivors: 15_000 tax_units: tax_unit: - members: [head, dependent] + members: [person1, person2] households: household: - members: [head, dependent] + members: [person1, person2] state_code: TX output: irs_gross_income: [50_000, 0] adjusted_gross_income: 50_000 + taxable_income: 50_000 - 21_900 + market_income: [50_000, 15_000] + household_market_income: 65_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/ca_taxable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/ca_taxable_income.yaml index 88ec985eb7a..2b8158fb796 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/ca_taxable_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/ca_taxable_income.yaml @@ -16,13 +16,25 @@ output: ca_taxable_income: 10_000 - 4_900 -- name: Military retirement pay flows into CA taxable income via federal AGI +- name: Military retirement pay flows into CA taxable income via federal AGI (2024, pre-exclusion) period: 2024 input: military_retirement_pay: 50_000 - ca_deductions: 5_363 + ca_deductions: 5_540 state_code: CA output: ca_agi: 50_000 - ca_taxable_income: 50_000 - 5_363 + ca_taxable_income: 50_000 - 5_540 + +- name: Military retirement pay and SBP exclusion under R&TC §§ 17132.9 and 17132.10 (2025) + period: 2025 + input: + military_retirement_pay: 50_000 + military_retirement_pay_survivors: 10_000 + ca_deductions: 5_706 + state_code: CA + output: + ca_military_retirement_exclusion: 20_000 + 10_000 + ca_agi: 60_000 - 30_000 + ca_taxable_income: 30_000 - 5_706 diff --git a/policyengine_us/tests/policy/baseline/gov/states/dc/tax/income/subtractions/dc_survivor_benefits_subtraction.yaml b/policyengine_us/tests/policy/baseline/gov/states/dc/tax/income/subtractions/dc_survivor_benefits_subtraction.yaml new file mode 100644 index 00000000000..58228f08ab9 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/dc/tax/income/subtractions/dc_survivor_benefits_subtraction.yaml @@ -0,0 +1,33 @@ +- name: Case 1, DC government survivor benefits subtraction eligible at age 62+. + period: 2024 + input: + people: + person1: + age: 65 + military_retirement_pay_survivors: 15_000 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: DC + output: + dc_survivor_benefits_subtraction: 15_000 + +- name: Case 2, DC government survivor benefits subtraction ineligible under age 62. + period: 2024 + input: + people: + person1: + age: 55 + military_retirement_pay_survivors: 15_000 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: DC + output: + dc_survivor_benefits_subtraction: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/de/tax/income/subtractions/pension_exclusion/de_pension_exclusion.yaml b/policyengine_us/tests/policy/baseline/gov/states/de/tax/income/subtractions/pension_exclusion/de_pension_exclusion.yaml index 36f594749d8..6ab03fcd95b 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/de/tax/income/subtractions/pension_exclusion/de_pension_exclusion.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/de/tax/income/subtractions/pension_exclusion/de_pension_exclusion.yaml @@ -133,3 +133,25 @@ output: de_pension_exclusion: 10_000 +- name: DE under-60 survivor benefits treated as pension (capped at 2,000) + period: 2024 + input: + age: 50 + military_retirement_pay_survivors: 1_500 + is_tax_unit_head_or_spouse: true + state_code: DE + output: + de_pension_exclusion: 1_500 + +- name: DE 60+ filer with military retirement and survivor benefits in retirement basket + period: 2024 + input: + age: 65 + military_retirement_pay_survivors: 8_000 + military_retirement_pay: 8_000 + is_tax_unit_head_or_spouse: true + state_code: DE + output: + de_pension_exclusion: 12_500 + + diff --git a/policyengine_us/tests/policy/baseline/gov/states/hi/tax/income/hi_subtractions.yaml b/policyengine_us/tests/policy/baseline/gov/states/hi/tax/income/hi_subtractions.yaml index 124df1de700..9696f42ec09 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/hi/tax/income/hi_subtractions.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/hi/tax/income/hi_subtractions.yaml @@ -119,3 +119,33 @@ # $40,000 - $16,000 joint standard deduction - 5 exemptions x $1,144 # (3 people plus 2 aged exemptions) = $18,280. hi_taxable_income: 18_280 + +- name: Hawaii subtracts military retirement pay and survivor benefits on line 13 + period: 2024 + input: + people: + head: + age: 60 + employment_income: 30_000 + military_retirement_pay: 20_000 + military_retirement_pay_survivors: 10_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [head] + filing_status: SINGLE + marital_units: + marital_unit: + members: [head] + spm_units: + spm_unit: + members: [head] + households: + household: + members: [head] + state_code: HI + output: + adjusted_gross_income: 60_000 + hi_subtractions: 30_000 + hi_agi: 30_000 + diff --git a/policyengine_us/tests/policy/baseline/gov/states/in/tax/income/deductions/in_military_retirement_deduction.yaml b/policyengine_us/tests/policy/baseline/gov/states/in/tax/income/deductions/in_military_retirement_deduction.yaml new file mode 100644 index 00000000000..5d7d2005361 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/in/tax/income/deductions/in_military_retirement_deduction.yaml @@ -0,0 +1,33 @@ +- name: Case 1, Indiana military retirement deduction under 2021 phase-in. + period: 2021 + input: + people: + person1: + military_retirement_pay: 10_000 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IN + output: + in_military_retirement_deduction: 6_250 + 0.75 * (10_000 - 6_250) + +- name: Case 2, Indiana military retirement and survivor benefit deduction 100% exempt from 2022. + period: 2024 + input: + people: + person1: + military_retirement_pay: 30_000 + person2: + military_retirement_pay_survivors: 10_000 + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IN + output: + in_military_retirement_deduction: 40_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/me/tax/income/taxable_income/me_pension_income_deduction.yaml b/policyengine_us/tests/policy/baseline/gov/states/me/tax/income/taxable_income/me_pension_income_deduction.yaml index 55f750bd65b..9ae585384b1 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/me/tax/income/taxable_income/me_pension_income_deduction.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/me/tax/income/taxable_income/me_pension_income_deduction.yaml @@ -367,3 +367,28 @@ me_pension_income_deduction: 0 me_agi: 60_000 +- name: Maine 2025 military retirement survivor benefits deducted in full (not phased out) + period: 2025 + input: + people: + person1: + is_tax_unit_head: true + age: 67 + social_security: 0 + military_retirement_pay_survivors: 35_000 + taxable_interest_income: 300_000 + tax_units: + tax_unit: + members: [person1] + filing_status: SINGLE + households: + household: + members: [person1] + state_code: ME + spm_units: + spm_unit: + members: [person1] + output: + me_pension_income_deduction: 35_000 + + diff --git a/policyengine_us/tests/policy/baseline/gov/states/mo/tax/income/deductions/mo_pension_and_ss_or_ssd_deduction/mo_pension_and_ss_or_ssd_deduction_section_a.yaml b/policyengine_us/tests/policy/baseline/gov/states/mo/tax/income/deductions/mo_pension_and_ss_or_ssd_deduction/mo_pension_and_ss_or_ssd_deduction_section_a.yaml index ebd097bcf3d..eb2b1ca4499 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mo/tax/income/deductions/mo_pension_and_ss_or_ssd_deduction/mo_pension_and_ss_or_ssd_deduction_section_a.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mo/tax/income/deductions/mo_pension_and_ss_or_ssd_deduction/mo_pension_and_ss_or_ssd_deduction_section_a.yaml @@ -364,3 +364,16 @@ mo_pension_and_ss_or_ssd_deduction_section_a: [15_000, 0] # Section D: 15,000 (A) + 0 (B) + 5,000 (C). mo_pension_and_ss_or_ssd_deduction: 20_000 + +- name: Military retirement pay survivors is included in public pension amount in Section A + period: 2024 + absolute_error_margin: 0 + input: + mo_adjusted_gross_income: 30_000 + taxable_social_security: 0 + military_retirement_pay_survivors: 8_000 + filing_status: SINGLE + mo_pension_and_ss_or_ssd_deduction_section_c: 0 + state_code: MO + output: + mo_pension_and_ss_or_ssd_deduction_section_a: 8_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/oh/tax/income/deductions/oh_uniformed_services_retirement_income_deduction.yaml b/policyengine_us/tests/policy/baseline/gov/states/oh/tax/income/deductions/oh_uniformed_services_retirement_income_deduction.yaml new file mode 100644 index 00000000000..4e724fead7d --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/oh/tax/income/deductions/oh_uniformed_services_retirement_income_deduction.yaml @@ -0,0 +1,36 @@ +- name: Case 1, Ohio uniformed services retirement deduction for retiree and survivor benefits. + period: 2024 + input: + people: + person1: + is_tax_unit_head: true + military_retirement_pay: 20_000 + military_retirement_pay_survivors: 10_000 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: OH + output: + oh_uniformed_services_retirement_income_deduction: 30_000 + +- name: Case 2, Dependent is ineligible for Ohio uniformed services retirement deduction. + period: 2024 + input: + people: + person1: + is_tax_unit_head: true + person2: + is_tax_unit_dependent: true + military_retirement_pay: 10_000 + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: OH + output: + oh_uniformed_services_retirement_income_deduction: [0, 0] diff --git a/policyengine_us/tests/policy/baseline/gov/states/wi/tax/income/subtractions/wi_military_retirement_subtraction.yaml b/policyengine_us/tests/policy/baseline/gov/states/wi/tax/income/subtractions/wi_military_retirement_subtraction.yaml new file mode 100644 index 00000000000..4c9f4b6e557 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/wi/tax/income/subtractions/wi_military_retirement_subtraction.yaml @@ -0,0 +1,16 @@ +- name: Case 1, Wisconsin excludes military retirement pay and survivor benefits on Schedule SB. + period: 2024 + input: + people: + person1: + military_retirement_pay: 20_000 + military_retirement_pay_survivors: 10_000 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: WI + output: + wi_income_subtractions: 30_000 diff --git a/policyengine_us/variables/gov/states/ca/tax/income/ca_military_retirement_exclusion.py b/policyengine_us/variables/gov/states/ca/tax/income/ca_military_retirement_exclusion.py new file mode 100644 index 00000000000..f0c612687c2 --- /dev/null +++ b/policyengine_us/variables/gov/states/ca/tax/income/ca_military_retirement_exclusion.py @@ -0,0 +1,32 @@ +from policyengine_us.model_api import * + + +class ca_military_retirement_exclusion(Variable): + value_type = float + entity = TaxUnit + label = "California military retirement and survivor benefit exclusion" + unit = USD + definition_period = YEAR + reference = ( + "https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?sectionNum=17132.9.&lawCode=RTC", + "https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?sectionNum=17132.10.&lawCode=RTC", + ) + defined_for = StateCode.CA + + def formula(tax_unit, period, parameters): + p = parameters(period).gov.states.ca.tax.income.agi.military_retirement + agi = tax_unit("adjusted_gross_income", period) + filing_status = tax_unit("filing_status", period) + limit = p.agi_limit[filing_status] + eligible = agi <= limit + + person = tax_unit.members + head_or_spouse = person("is_tax_unit_head_or_spouse", period) + # R&TC § 17132.9 excludes up to $20,000 of retired pay. + # R&TC § 17132.10 excludes up to $20,000 of SBP survivor benefits. + capped_retiree = min_(p.cap, person("military_retirement_pay", period)) + capped_survivors = min_( + p.cap, person("military_retirement_pay_survivors", period) + ) + total_person = (capped_retiree + capped_survivors) * head_or_spouse + return eligible * tax_unit.sum(total_person) diff --git a/policyengine_us/variables/gov/states/co/tax/income/subtractions/pension/co_pension_subtraction_indv.py b/policyengine_us/variables/gov/states/co/tax/income/subtractions/pension/co_pension_subtraction_indv.py index e6c4cf3f78e..1c63c5bd3f7 100644 --- a/policyengine_us/variables/gov/states/co/tax/income/subtractions/pension/co_pension_subtraction_indv.py +++ b/policyengine_us/variables/gov/states/co/tax/income/subtractions/pension/co_pension_subtraction_indv.py @@ -18,7 +18,11 @@ class co_pension_subtraction_indv(Variable): def formula(person, period, parameters): p = parameters(period).gov.states.co.tax.income.subtractions.pension taxable_pension_income = person("co_pension_subtraction_income", period) - pension_survivors = person("pension_survivors", period) + pension_survivors = add( + person, + period, + ["pension_survivors", "military_retirement_pay_survivors"], + ) co_social_security_subtraction = person( "co_social_security_subtraction_indv", period ) diff --git a/policyengine_us/variables/gov/states/dc/tax/income/subtractions/dc_survivor_benefits_subtraction.py b/policyengine_us/variables/gov/states/dc/tax/income/subtractions/dc_survivor_benefits_subtraction.py new file mode 100644 index 00000000000..5cee9cf2b9f --- /dev/null +++ b/policyengine_us/variables/gov/states/dc/tax/income/subtractions/dc_survivor_benefits_subtraction.py @@ -0,0 +1,27 @@ +from policyengine_us.model_api import * + + +class dc_survivor_benefits_subtraction(Variable): + value_type = float + entity = Person + label = "DC government survivor benefits subtraction" + unit = USD + definition_period = YEAR + reference = ( + "https://code.dccouncil.gov/us/dc/council/code/sections/47-1803.02#a_2_N_ii", + "https://otr.cfo.dc.gov/sites/default/files/dc/sites/otr/publication/attachments/2024_D40_Booklet_011525.pdf#page=34", + ) + defined_for = StateCode.DC + + def formula(person, period, parameters): + p = ( + parameters(period) + .gov.states["dc"] + .tax.income.subtractions.survivor_benefits + ) + age = person("age", period) + eligible = age >= p.min_age + # D.C. Code § 47-1803.02(a)(2)(N)(ii) allows exclusion of survivor benefits + # received from the District or federal government by persons 62 or older. + survivor_pay = person("military_retirement_pay_survivors", period) + return eligible * survivor_pay diff --git a/policyengine_us/variables/gov/states/de/tax/income/subtractions/pension_exclusion/de_pension_exclusion.py b/policyengine_us/variables/gov/states/de/tax/income/subtractions/pension_exclusion/de_pension_exclusion.py index ead5baabac0..205a7a9709e 100644 --- a/policyengine_us/variables/gov/states/de/tax/income/subtractions/pension_exclusion/de_pension_exclusion.py +++ b/policyengine_us/variables/gov/states/de/tax/income/subtractions/pension_exclusion/de_pension_exclusion.py @@ -25,8 +25,10 @@ def formula(person, period, parameters): eligible_for_pension_exclusion_income = p.age_threshold.calc(age) eligible_pension_income = ( - person("taxable_pension_income", period) * head_or_spouse - ) + person("taxable_pension_income", period) + + person("military_retirement_pay", period) + + person("military_retirement_pay_survivors", period) + ) * head_or_spouse eligible_retirement_income = ( person("de_pension_exclusion_income", period) * head_or_spouse diff --git a/policyengine_us/variables/gov/states/ga/tax/income/subtractions/retirement/ga_retirement_income_exclusion_retirement_income.py b/policyengine_us/variables/gov/states/ga/tax/income/subtractions/retirement/ga_retirement_income_exclusion_retirement_income.py index 7b81a1610bd..fdf8666eea5 100644 --- a/policyengine_us/variables/gov/states/ga/tax/income/subtractions/retirement/ga_retirement_income_exclusion_retirement_income.py +++ b/policyengine_us/variables/gov/states/ga/tax/income/subtractions/retirement/ga_retirement_income_exclusion_retirement_income.py @@ -22,6 +22,14 @@ def formula(person, period, parameters): countable_earned_income = max_( 0, person("ga_retirement_exclusion_countable_earned_income", period) ) - other_retirement_income = add(person, period, p.sources) + # Ga. Comp. R. & Regs. r. 560-7-4-.02(3): Only retirement income included + # in Georgia taxable income can be included. Subtract the military + # retirement exclusion already taken under O.C.G.A. § 48-7-27(a)(5)(E). + military_pay = person("military_retirement_pay", period) + military_exclusion = person("ga_military_retirement_exclusion_person", period) + remaining_military_pay = max_(0, military_pay - military_exclusion) + other_retirement_income = ( + add(person, period, p.sources) + remaining_military_pay + ) countable_other_retirement_income = max_(0, other_retirement_income) return countable_earned_income + countable_other_retirement_income diff --git a/policyengine_us/variables/gov/states/id/tax/income/subtractions/military_retirement/id_military_retirement_deduction.py b/policyengine_us/variables/gov/states/id/tax/income/subtractions/military_retirement/id_military_retirement_deduction.py index 340443b3009..abaecd358a8 100644 --- a/policyengine_us/variables/gov/states/id/tax/income/subtractions/military_retirement/id_military_retirement_deduction.py +++ b/policyengine_us/variables/gov/states/id/tax/income/subtractions/military_retirement/id_military_retirement_deduction.py @@ -17,7 +17,11 @@ def formula(tax_unit, period, parameters): p = parameters(period).gov.states.id.tax.income.subtractions.military_retirement person = tax_unit.members head_or_spouse = person("is_tax_unit_head_or_spouse", period) - military_retirement_pay = person("military_retirement_pay", period) + military_retirement_pay = add( + person, + period, + ["military_retirement_pay", "military_retirement_pay_survivors"], + ) eligible_military_pay = military_retirement_pay * head_or_spouse # Multiply by applies parameter (False when military retirement # is already handled in general retirement benefits deduction) diff --git a/policyengine_us/variables/gov/states/in/tax/income/deductions/in_military_retirement_deduction.py b/policyengine_us/variables/gov/states/in/tax/income/deductions/in_military_retirement_deduction.py new file mode 100644 index 00000000000..d71748426f3 --- /dev/null +++ b/policyengine_us/variables/gov/states/in/tax/income/deductions/in_military_retirement_deduction.py @@ -0,0 +1,28 @@ +from policyengine_us.model_api import * + + +class in_military_retirement_deduction(Variable): + value_type = float + entity = TaxUnit + label = "Indiana military retirement deduction" + unit = USD + definition_period = YEAR + reference = ( + "http://iga.in.gov/legislative/laws/2021/ic/titles/006#6-3-2-4", + "https://forms.in.gov/Download.aspx?id=16915#page=20", + ) + defined_for = StateCode.IN + + def formula(tax_unit, period, parameters): + person = tax_unit.members + p = ( + parameters(period) + .gov.states["in"] + .tax.income.deductions.military_retirement + ) + military_retirement = person("military_retirement_pay", period) + person( + "military_retirement_pay_survivors", period + ) + excess = max_(0, military_retirement - p.base) + person_deduction = min_(military_retirement, p.base) + p.excess_rate * excess + return tax_unit.sum(person_deduction) diff --git a/policyengine_us/variables/gov/states/in/tax/income/deductions/in_other_deductions.py b/policyengine_us/variables/gov/states/in/tax/income/deductions/in_other_deductions.py index e3650257bea..e82164c2f84 100644 --- a/policyengine_us/variables/gov/states/in/tax/income/deductions/in_other_deductions.py +++ b/policyengine_us/variables/gov/states/in/tax/income/deductions/in_other_deductions.py @@ -7,6 +7,6 @@ class in_other_deductions(Variable): label = "Indiana other deductions" unit = USD definition_period = YEAR - documentation = "Other deductions available in Indiana including those for civil service annuities, disability retirement, government or civic group capital contributions, human services for Medicaid recipients, infrastructure fund gifts, indiana lottery winings annuity, Indiana partnership long-term care policy premiums, military retirement income or survivor's benefits, National Guard and reserve component members, Olympic/Paralymic medal winners, qualified patents income eemption, railroad unemployment and sickness benefits, repayment of previously taxed income deductions, COVID-related employee retention credit dissalowed expenses, and Indiana-only tax-exempt bonds." + documentation = "Other deductions available in Indiana including those for disability retirement, government or civic group capital contributions, human services for Medicaid recipients, infrastructure fund gifts, indiana lottery winings annuity, Indiana partnership long-term care policy premiums, National Guard and reserve component members, Olympic/Paralymic medal winners, qualified patents income eemption, railroad unemployment and sickness benefits, repayment of previously taxed income deductions, COVID-related employee retention credit dissalowed expenses, and Indiana-only tax-exempt bonds." reference = "http://iga.in.gov/legislative/laws/2021/ic/titles/006#6-3-2" defined_for = StateCode.IN diff --git a/policyengine_us/variables/gov/states/ks/tax/income/ks_agi_subtractions.py b/policyengine_us/variables/gov/states/ks/tax/income/ks_agi_subtractions.py index d85b4251917..0e623486d57 100644 --- a/policyengine_us/variables/gov/states/ks/tax/income/ks_agi_subtractions.py +++ b/policyengine_us/variables/gov/states/ks/tax/income/ks_agi_subtractions.py @@ -27,16 +27,23 @@ def formula(tax_unit, period, parameters): "salt_refund_income", tax_unit, period ) # K.S.A. § 79-32,117(c)(ii), (vii)–(ix) / Form K-40 Schedule S Line A13 - # Proxy note: Kansas exempts KPERS, Kansas police/firemen, Kansas judges, and federal - # civil service/military pensions; out-of-state public pensions are not exempt. - # PolicyEngine models this by subtracting taxable_public_pension_income as an in-state proxy. - taxable_public_pension_income = tax_unit_non_dep_sum( - "taxable_public_pension_income", tax_unit, period + # Kansas exempts KPERS, Kansas police/firemen, Kansas judges, federal civil service, + # military retirement pay, and military survivor benefits (10 U.S.C. 1450). + # Out-of-state public pensions are not exempt. PolicyEngine models this by subtracting + # taxable_public_pension_income as an in-state proxy, plus military retirement pay and survivors. + public_and_military_pension = tax_unit_non_dep_add( + tax_unit, + period, + [ + "taxable_public_pension_income", + "military_retirement_pay", + "military_retirement_pay_survivors", + ], ) return ( oasdi_subtraction + us_govt_interest + plan_529 + salt_refund_income - + taxable_public_pension_income + + public_and_military_pension ) diff --git a/policyengine_us/variables/gov/states/ky/tax/income/exclusions/pension_income/ky_pension_income_exclusion.py b/policyengine_us/variables/gov/states/ky/tax/income/exclusions/pension_income/ky_pension_income_exclusion.py index 29368948f28..34a738def77 100644 --- a/policyengine_us/variables/gov/states/ky/tax/income/exclusions/pension_income/ky_pension_income_exclusion.py +++ b/policyengine_us/variables/gov/states/ky/tax/income/exclusions/pension_income/ky_pension_income_exclusion.py @@ -13,7 +13,15 @@ def formula(person, period, parameters): p = parameters(period).gov.states.ky.tax.income.exclusions.pension_income # Get taxable pension and retirement income. - pension_income = person("taxable_pension_income", period) + pension_income = add( + person, + period, + [ + "taxable_pension_income", + "military_retirement_pay", + "military_retirement_pay_survivors", + ], + ) # Check if person is eligible for exemption. exemption_eligible = person( diff --git a/policyengine_us/variables/gov/states/ma/tax/income/gross_income/ma_gross_income.py b/policyengine_us/variables/gov/states/ma/tax/income/gross_income/ma_gross_income.py index ca107287104..4aa9125de0e 100644 --- a/policyengine_us/variables/gov/states/ma/tax/income/gross_income/ma_gross_income.py +++ b/policyengine_us/variables/gov/states/ma/tax/income/gross_income/ma_gross_income.py @@ -43,8 +43,14 @@ def formula(tax_unit, period, parameters): salt_refund_income = tax_unit_non_dep_sum( "salt_refund_income", tax_unit, period ) - public_pension = tax_unit_non_dep_sum( - "taxable_public_pension_income", tax_unit, period + public_pension = tax_unit_non_dep_add( + tax_unit, + period, + [ + "taxable_public_pension_income", + "military_retirement_pay", + "military_retirement_pay_survivors", + ], ) deductions = social_security_in_agi + salt_refund_income + public_pension return max_( diff --git a/policyengine_us/variables/gov/states/md/tax/income/agi/subtractions/md_pension_subtraction_amount.py b/policyengine_us/variables/gov/states/md/tax/income/agi/subtractions/md_pension_subtraction_amount.py index 6ce758fe58e..669cbf6550a 100644 --- a/policyengine_us/variables/gov/states/md/tax/income/agi/subtractions/md_pension_subtraction_amount.py +++ b/policyengine_us/variables/gov/states/md/tax/income/agi/subtractions/md_pension_subtraction_amount.py @@ -19,8 +19,23 @@ def formula(person, period, parameters): disabled = person("is_disabled", period) partner_is_disabled = person("has_disabled_spouse", period) eligible = ~dependent & (elderly | disabled | partner_is_disabled) + # Under Md. Code Tax-General § 10-209(d)(1) and Form 502 instructions + # (Worksheet 13A, line 1), military retirement income exceeding the + # § 10-207(q) military retirement subtraction qualifies for the + # general pension exclusion. + p_mil = p.military_retirement + military_income = person("military_retirement_pay", period) + person( + "military_retirement_pay_survivors", period + ) + mil_cap = where( + elderly, + p_mil.max_amount.at_or_above_age_threshold, + p_mil.max_amount.under_age_threshold, + ) + excess_military = max_(0, military_income - mil_cap) + # calculate pension subtraction amount for each person - peninc = add(person, period, p.pension.sources) + peninc = add(person, period, p.pension.sources) + excess_military socsec = person("social_security", period) amount = min_(peninc, max_(0, p.pension.max_amount - socsec)) # return pension subtraction amount for each eligible person diff --git a/policyengine_us/variables/gov/states/me/tax/income/adjusted_gross_income/me_pension_income_deduction.py b/policyengine_us/variables/gov/states/me/tax/income/adjusted_gross_income/me_pension_income_deduction.py index 74e668f9c3e..bf0348d0a27 100644 --- a/policyengine_us/variables/gov/states/me/tax/income/adjusted_gross_income/me_pension_income_deduction.py +++ b/policyengine_us/variables/gov/states/me/tax/income/adjusted_gross_income/me_pension_income_deduction.py @@ -37,7 +37,9 @@ def formula(tax_unit, period, parameters): ss_reduced_cap = max_(p.cap - gross_ss, 0) non_military_deduction = min_(pension_income, ss_reduced_cap) - military_retirement_pay = person("military_retirement_pay", period) + military_retirement = person("military_retirement_pay", period) + person( + "military_retirement_pay_survivors", period + ) # Restrict to the head (and spouse if filing jointly) per Schedule 1S # line 4. @@ -52,9 +54,9 @@ def formula(tax_unit, period, parameters): total_non_military = where( is_joint, non_military_with_spouse, non_military_head_only ) - military_head_only = tax_unit.sum(where(is_head, military_retirement_pay, 0)) + military_head_only = tax_unit.sum(where(is_head, military_retirement, 0)) military_with_spouse = tax_unit.sum( - where(is_head | is_spouse, military_retirement_pay, 0) + where(is_head | is_spouse, military_retirement, 0) ) total_military = where(is_joint, military_with_spouse, military_head_only) diff --git a/policyengine_us/variables/gov/states/mi/tax/income/deductions/interest_dividends_capital_gains/mi_interest_dividends_capital_gains_deduction.py b/policyengine_us/variables/gov/states/mi/tax/income/deductions/interest_dividends_capital_gains/mi_interest_dividends_capital_gains_deduction.py index f8b7ea7cabc..ea9bf5183c3 100644 --- a/policyengine_us/variables/gov/states/mi/tax/income/deductions/interest_dividends_capital_gains/mi_interest_dividends_capital_gains_deduction.py +++ b/policyengine_us/variables/gov/states/mi/tax/income/deductions/interest_dividends_capital_gains/mi_interest_dividends_capital_gains_deduction.py @@ -34,7 +34,11 @@ def formula(tax_unit, period, parameters): reductions_pay = add( person, period, - ["military_retirement_pay", "taxable_pension_income"], + [ + "military_retirement_pay", + "military_retirement_pay_survivors", + "taxable_pension_income", + ], ) elderly_disabled_credit = tax_unit("elderly_disabled_credit", period) diff --git a/policyengine_us/variables/gov/states/mi/tax/income/deductions/retirement/expanded/mi_expanded_retirement_benefits_deduction.py b/policyengine_us/variables/gov/states/mi/tax/income/deductions/retirement/expanded/mi_expanded_retirement_benefits_deduction.py index c6e48c01193..55d34385b5a 100644 --- a/policyengine_us/variables/gov/states/mi/tax/income/deductions/retirement/expanded/mi_expanded_retirement_benefits_deduction.py +++ b/policyengine_us/variables/gov/states/mi/tax/income/deductions/retirement/expanded/mi_expanded_retirement_benefits_deduction.py @@ -54,8 +54,9 @@ def formula(tax_unit, period, parameters): # Line 1 tier_one_cap = p.tier_one.amount[filing_status] head_or_spouse_military_retirement_pay = ( - person("military_retirement_pay", period) * is_head_or_spouse - ) + person("military_retirement_pay", period) + + person("military_retirement_pay_survivors", period) + ) * is_head_or_spouse # Line 2 total_military_retirement_pay = tax_unit.sum( head_or_spouse_military_retirement_pay diff --git a/policyengine_us/variables/gov/states/mi/tax/income/deductions/retirement/tier_one/mi_retirement_benefits_deduction_tier_one_amount.py b/policyengine_us/variables/gov/states/mi/tax/income/deductions/retirement/tier_one/mi_retirement_benefits_deduction_tier_one_amount.py index 41afc7173ce..1a80ed57e9d 100644 --- a/policyengine_us/variables/gov/states/mi/tax/income/deductions/retirement/tier_one/mi_retirement_benefits_deduction_tier_one_amount.py +++ b/policyengine_us/variables/gov/states/mi/tax/income/deductions/retirement/tier_one/mi_retirement_benefits_deduction_tier_one_amount.py @@ -32,8 +32,9 @@ def formula(tax_unit, period, parameters): # Line 10 is_head_or_spouse = person("is_tax_unit_head_or_spouse", period) military_retirement_pay = ( - person("military_retirement_pay", period) * is_head_or_spouse - ) + person("military_retirement_pay", period) + + person("military_retirement_pay_survivors", period) + ) * is_head_or_spouse total_military_retirement_pay = tax_unit.sum(military_retirement_pay) # the cap is reduced by the amount of military retirement pay diff --git a/policyengine_us/variables/gov/states/mi/tax/income/deductions/retirement/tier_three/ss_exempt/not_retired/mi_retirement_benefits_deduction_tier_three_ss_exempt_not_retired.py b/policyengine_us/variables/gov/states/mi/tax/income/deductions/retirement/tier_three/ss_exempt/not_retired/mi_retirement_benefits_deduction_tier_three_ss_exempt_not_retired.py index 39aac5d1ec0..5e5e5a75ba9 100644 --- a/policyengine_us/variables/gov/states/mi/tax/income/deductions/retirement/tier_three/ss_exempt/not_retired/mi_retirement_benefits_deduction_tier_three_ss_exempt_not_retired.py +++ b/policyengine_us/variables/gov/states/mi/tax/income/deductions/retirement/tier_three/ss_exempt/not_retired/mi_retirement_benefits_deduction_tier_three_ss_exempt_not_retired.py @@ -63,10 +63,11 @@ def formula(tax_unit, period, parameters): # the tier one or tier three deduction amount # Worksheet 3.2 counts only military retirement pay on the filer's Schedule 1, line 11, # which excludes a dependent's pay (not in the filer's AGI). - military_retirement_pay_received = ( - tax_unit.sum(person("military_retirement_pay", period) * is_head_or_spouse) - > 0 - ) + military_pay = ( + person("military_retirement_pay", period) + + person("military_retirement_pay_survivors", period) + ) * is_head_or_spouse + military_retirement_pay_received = tax_unit.sum(military_pay) > 0 # Line 8 tier_one_amount = tax_unit( "mi_retirement_benefits_deduction_tier_one_amount", diff --git a/policyengine_us/variables/gov/states/mi/tax/income/deductions/retirement/tier_three/ss_exempt/retired/mi_retirement_benefits_deduction_tier_three_ss_exempt_retired.py b/policyengine_us/variables/gov/states/mi/tax/income/deductions/retirement/tier_three/ss_exempt/retired/mi_retirement_benefits_deduction_tier_three_ss_exempt_retired.py index 8210b1e48cb..3cd71e63089 100644 --- a/policyengine_us/variables/gov/states/mi/tax/income/deductions/retirement/tier_three/ss_exempt/retired/mi_retirement_benefits_deduction_tier_three_ss_exempt_retired.py +++ b/policyengine_us/variables/gov/states/mi/tax/income/deductions/retirement/tier_three/ss_exempt/retired/mi_retirement_benefits_deduction_tier_three_ss_exempt_retired.py @@ -78,10 +78,11 @@ def formula(tax_unit, period, parameters): # the tier one or tier three deduction amount # Worksheet 3.1 counts only military retirement pay on the filer's Schedule 1, line 11, # which excludes a dependent's pay (not in the filer's AGI). - military_retirement_pay_eligible = ( - tax_unit.sum(person("military_retirement_pay", period) * is_head_or_spouse) - > 0 - ) + military_pay = ( + person("military_retirement_pay", period) + + person("military_retirement_pay_survivors", period) + ) * is_head_or_spouse + military_retirement_pay_eligible = tax_unit.sum(military_pay) > 0 # Line 8 tier_one_amount = tax_unit( "mi_retirement_benefits_deduction_tier_one_amount", diff --git a/policyengine_us/variables/gov/states/mi/tax/income/deductions/standard/tier_three/mi_standard_deduction_tier_three.py b/policyengine_us/variables/gov/states/mi/tax/income/deductions/standard/tier_three/mi_standard_deduction_tier_three.py index 2798667deb7..4c9d4c492ff 100644 --- a/policyengine_us/variables/gov/states/mi/tax/income/deductions/standard/tier_three/mi_standard_deduction_tier_three.py +++ b/policyengine_us/variables/gov/states/mi/tax/income/deductions/standard/tier_three/mi_standard_deduction_tier_three.py @@ -30,8 +30,10 @@ def formula(tax_unit, period, parameters): person = tax_unit.members is_head_or_spouse = person("is_tax_unit_head_or_spouse", period) - # Line 2: enter military retirement pay - military_retirement_pay = person("military_retirement_pay", period) + # Line 2: enter military retirement pay and survivor benefits + military_retirement_pay = person("military_retirement_pay", period) + person( + "military_retirement_pay_survivors", period + ) # Line 3: enter military service income or taxable social security taxable_ss = person("taxable_social_security", period) military_service_income = person("military_service_income", period) diff --git a/policyengine_us/variables/gov/states/mi/tax/income/deductions/standard/tier_two/mi_standard_deduction_tier_two.py b/policyengine_us/variables/gov/states/mi/tax/income/deductions/standard/tier_two/mi_standard_deduction_tier_two.py index 6f87ca02091..3b283f28118 100644 --- a/policyengine_us/variables/gov/states/mi/tax/income/deductions/standard/tier_two/mi_standard_deduction_tier_two.py +++ b/policyengine_us/variables/gov/states/mi/tax/income/deductions/standard/tier_two/mi_standard_deduction_tier_two.py @@ -32,7 +32,11 @@ def formula(tax_unit, period, parameters): military_pay = add( person, period, - ["military_retirement_pay", "military_service_income"], + [ + "military_retirement_pay", + "military_retirement_pay_survivors", + "military_service_income", + ], ) is_head_or_spouse = person("is_tax_unit_head_or_spouse", period) head_or_spouse_military_pay = tax_unit.sum(military_pay * is_head_or_spouse) diff --git a/policyengine_us/variables/gov/states/mn/tax/income/amt/mn_amt_taxable_income.py b/policyengine_us/variables/gov/states/mn/tax/income/amt/mn_amt_taxable_income.py index 83736e79da5..eac3dca4bfc 100644 --- a/policyengine_us/variables/gov/states/mn/tax/income/amt/mn_amt_taxable_income.py +++ b/policyengine_us/variables/gov/states/mn/tax/income/amt/mn_amt_taxable_income.py @@ -30,6 +30,7 @@ def formula(tax_unit, period, parameters): "us_govt_interest", "mn_charity_subtraction", "mn_social_security_subtraction", + "mn_military_pension_subtraction", ] amt_subs = add(tax_unit, period, AMT_SUBTRACTIONS) return fagi - some_itm_deds - amt_subs diff --git a/policyengine_us/variables/gov/states/mo/tax/income/deductions/mo_pension_and_ss_or_ssd_deduction_section_a.py b/policyengine_us/variables/gov/states/mo/tax/income/deductions/mo_pension_and_ss_or_ssd_deduction_section_a.py index 70e8129ef39..3f9475edea3 100644 --- a/policyengine_us/variables/gov/states/mo/tax/income/deductions/mo_pension_and_ss_or_ssd_deduction_section_a.py +++ b/policyengine_us/variables/gov/states/mo/tax/income/deductions/mo_pension_and_ss_or_ssd_deduction_section_a.py @@ -48,8 +48,9 @@ def formula(person, period, parameters): # AGI; they report it on their own return. head_or_spouse = person("is_tax_unit_head_or_spouse", period) public_pension_amount = ( - person("taxable_public_pension_income", period) * head_or_spouse - ) + person("taxable_public_pension_income", period) + + person("military_retirement_pay_survivors", period) + ) * head_or_spouse max_social_security_benefit = ( p.mo_max_social_security_benefit ) # Seen on Line 7, Section A diff --git a/policyengine_us/variables/gov/states/ne/tax/income/adjusted_gross_income/subtractions/ne_military_retirement_subtraction.py b/policyengine_us/variables/gov/states/ne/tax/income/adjusted_gross_income/subtractions/ne_military_retirement_subtraction.py index 5f26d9b7ef0..e3094e42160 100644 --- a/policyengine_us/variables/gov/states/ne/tax/income/adjusted_gross_income/subtractions/ne_military_retirement_subtraction.py +++ b/policyengine_us/variables/gov/states/ne/tax/income/adjusted_gross_income/subtractions/ne_military_retirement_subtraction.py @@ -23,14 +23,12 @@ def formula(tax_unit, period, parameters): person = tax_unit.members age = person("age", period) age_eligible = age >= p.age_threshold - military_retirement_benefit = add( - person, - period, - [ - "military_retirement_pay", - "military_retirement_pay_survivors", - ], - ) + military_retirement_pay = person("military_retirement_pay", period) + if p.survivors_eligible: + survivor_pay = person("military_retirement_pay_survivors", period) + else: + survivor_pay = 0 + military_retirement_benefit = military_retirement_pay + survivor_pay # Dependents' income is not in federal AGI; they report it on their # own return. head_or_spouse = person("is_tax_unit_head_or_spouse", period) diff --git a/policyengine_us/variables/gov/states/oh/tax/income/deductions/oh_uniformed_services_retirement_income_deduction.py b/policyengine_us/variables/gov/states/oh/tax/income/deductions/oh_uniformed_services_retirement_income_deduction.py index 3f38596b82e..8f9f83f85ec 100644 --- a/policyengine_us/variables/gov/states/oh/tax/income/deductions/oh_uniformed_services_retirement_income_deduction.py +++ b/policyengine_us/variables/gov/states/oh/tax/income/deductions/oh_uniformed_services_retirement_income_deduction.py @@ -7,5 +7,15 @@ class oh_uniformed_services_retirement_income_deduction(Variable): label = "Ohio Uniformed services retirement income" definition_period = YEAR unit = USD - reference = "https://tax.ohio.gov/static/forms/ohio_individual/individual/2022/it1040-bundle.pdf#page=4" + reference = ( + "https://codes.ohio.gov/ohio-revised-code/section-5747.01#A_23", + "https://tax.ohio.gov/static/forms/ohio_individual/individual/2022/it1040-bundle.pdf#page=4", + ) defined_for = StateCode.OH + + def formula(person, period, parameters): + is_head_or_spouse = person("is_tax_unit_head_or_spouse", period) + military_retirement = person("military_retirement_pay", period) + person( + "military_retirement_pay_survivors", period + ) + return is_head_or_spouse * military_retirement diff --git a/policyengine_us/variables/gov/states/or/tax/income/credits/retirement_credit/or_retirement_credit.py b/policyengine_us/variables/gov/states/or/tax/income/credits/retirement_credit/or_retirement_credit.py index 37c6920071b..e95f20765ad 100644 --- a/policyengine_us/variables/gov/states/or/tax/income/credits/retirement_credit/or_retirement_credit.py +++ b/policyengine_us/variables/gov/states/or/tax/income/credits/retirement_credit/or_retirement_credit.py @@ -16,7 +16,12 @@ def formula(tax_unit, period, parameters): # Line 1, retirement income person = tax_unit.members eligible = person("or_retirement_credit_eligible_person", period) - retirement_income = eligible * person("taxable_pension_income", period) + pension = ( + person("taxable_pension_income", period) + + person("military_retirement_pay", period) + + person("military_retirement_pay_survivors", period) + ) + retirement_income = eligible * pension total_retirement_income = tax_unit.sum(retirement_income) # Line 2, federal pension subtraction diff --git a/policyengine_us/variables/gov/states/vt/tax/income/adjusted_gross_income/subtractions/retirement_income_exemption/vt_military_retirement_cap_based_exemption.py b/policyengine_us/variables/gov/states/vt/tax/income/adjusted_gross_income/subtractions/retirement_income_exemption/vt_military_retirement_cap_based_exemption.py index db8fd660021..577a7eec701 100644 --- a/policyengine_us/variables/gov/states/vt/tax/income/adjusted_gross_income/subtractions/retirement_income_exemption/vt_military_retirement_cap_based_exemption.py +++ b/policyengine_us/variables/gov/states/vt/tax/income/adjusted_gross_income/subtractions/retirement_income_exemption/vt_military_retirement_cap_based_exemption.py @@ -21,13 +21,8 @@ def formula(tax_unit, period, parameters): # Get retirement amount from military retirement system # Dependents' income is not in federal AGI; they report it on their # own return, so only the head's and spouse's pay counts. - tax_unit_military_retirement_pay = tax_unit_non_dep_add( - tax_unit, - period, - [ - "military_retirement_pay", - "military_retirement_pay_survivors", - ], + tax_unit_military_retirement_pay = tax_unit_non_dep_sum( + "military_retirement_pay", tax_unit, period ) # Cap exemption at the specified amount diff --git a/policyengine_us/variables/gov/states/vt/tax/income/adjusted_gross_income/subtractions/retirement_income_exemption/vt_military_retirement_pay_exclusion.py b/policyengine_us/variables/gov/states/vt/tax/income/adjusted_gross_income/subtractions/retirement_income_exemption/vt_military_retirement_pay_exclusion.py index 84b0d3663ed..55d3a72cbfe 100644 --- a/policyengine_us/variables/gov/states/vt/tax/income/adjusted_gross_income/subtractions/retirement_income_exemption/vt_military_retirement_pay_exclusion.py +++ b/policyengine_us/variables/gov/states/vt/tax/income/adjusted_gross_income/subtractions/retirement_income_exemption/vt_military_retirement_pay_exclusion.py @@ -16,21 +16,8 @@ class vt_military_retirement_pay_exclusion(Variable): def formula(tax_unit, period, parameters): p = parameters(period).gov.states.vt.tax.income.agi.retirement_income_exemption - # Get retirement amount from military retirement system - # Dependents' income is not in federal AGI; they report it on their - # own return, so only the head's and spouse's pay counts. - tax_unit_military_retirement_pay = tax_unit_non_dep_add( - tax_unit, - period, - [ - "military_retirement_pay", - "military_retirement_pay_survivors", - ], - ) - # S.51 (2025): Income-based military pension exemption is_income_based_system = p.military_retirement.income_based_structure.in_effect - agi = tax_unit("adjusted_gross_income", period) # Calculate exemption based on system type income_based_exemption = tax_unit( diff --git a/policyengine_us/variables/gov/states/vt/tax/income/adjusted_gross_income/subtractions/retirement_income_exemption/vt_retirement_income_exemption_eligible.py b/policyengine_us/variables/gov/states/vt/tax/income/adjusted_gross_income/subtractions/retirement_income_exemption/vt_retirement_income_exemption_eligible.py index c2c08f0c857..a32b84737d9 100644 --- a/policyengine_us/variables/gov/states/vt/tax/income/adjusted_gross_income/subtractions/retirement_income_exemption/vt_retirement_income_exemption_eligible.py +++ b/policyengine_us/variables/gov/states/vt/tax/income/adjusted_gross_income/subtractions/retirement_income_exemption/vt_retirement_income_exemption_eligible.py @@ -25,15 +25,17 @@ def formula(tax_unit, period, parameters): # One of the retirement income should be greater than 0 # Dependents' income is not in federal AGI; they report it on their # own return, so only the head's and spouse's pay counts. + retirement_sources = [ + "tax_unit_taxable_social_security", + "military_retirement_pay", + "csrs_retirement_pay", + ] + if p.military_retirement.income_based_structure.in_effect: + retirement_sources.append("military_retirement_pay_survivors") retirement_income = tax_unit_non_dep_add( tax_unit, period, - [ - "tax_unit_taxable_social_security", - "military_retirement_pay", - "military_retirement_pay_survivors", - "csrs_retirement_pay", - ], + retirement_sources, ) retirement_income_qualified = retirement_income > 0 # Determine which retirement system the filer uses, mirroring the diff --git a/policyengine_us/variables/household/income/person/retirement/military_retirement_pay.py b/policyengine_us/variables/household/income/person/retirement/military_retirement_pay.py index b0bac6477ad..129edfae26f 100644 --- a/policyengine_us/variables/household/income/person/retirement/military_retirement_pay.py +++ b/policyengine_us/variables/household/income/person/retirement/military_retirement_pay.py @@ -7,6 +7,12 @@ class military_retirement_pay(Variable): label = "Military retirement pay" unit = USD definition_period = YEAR - documentation = "The benefits received under a United States military retirement plan, including survivor benefits." - reference = "https://militarypay.defense.gov/Pay/Retirement/" + documentation = ( + "Retirement pay received by former members of the uniformed services " + "of the United States. Included in federal gross income under 26 U.S.C. § 61(a)(10)." + ) + reference = ( + "https://militarypay.defense.gov/Pay/Retirement/", + "https://www.irs.gov/publications/p525", + ) uprating = "calibration.gov.irs.soi.taxable_pension_income" diff --git a/policyengine_us/variables/household/income/person/retirement/military_retirement_pay_survivors.py b/policyengine_us/variables/household/income/person/retirement/military_retirement_pay_survivors.py index df7f481d9bc..0ce9e3bc6e4 100644 --- a/policyengine_us/variables/household/income/person/retirement/military_retirement_pay_survivors.py +++ b/policyengine_us/variables/household/income/person/retirement/military_retirement_pay_survivors.py @@ -7,4 +7,15 @@ class military_retirement_pay_survivors(Variable): label = "Military retirement income paid to surviving spouses" unit = USD definition_period = YEAR + documentation = ( + "Survivor annuity payments received by surviving spouses or other designated " + "beneficiaries under a United States uniformed services retirement plan (such as " + "the Survivor Benefit Plan or Retired Serviceman's Family Protection Plan). " + "Included in federal gross income under 26 U.S.C. § 61(a)(10) and § 72." + ) + reference = ( + "https://militarypay.defense.gov/Benefits/Survivor-Benefit-Program/", + "https://www.irs.gov/publications/p525", + "https://www.irs.gov/publications/p575", + ) uprating = "calibration.gov.irs.soi.taxable_pension_income" From 9f9074f169bdba6df95b03bd69b9fd7c1b3d9e9d Mon Sep 17 00:00:00 2001 From: Deepak Jindal Date: Wed, 14 Oct 2026 19:53:08 -0700 Subject: [PATCH 4/5] Isolate tax unit filer retirement and survivor income in DC, IN, PA, and WI --- changelog.d/wire-military-retirement-pay.fixed.md | 1 + .../dc_survivor_benefits_subtraction.py | 5 ++++- .../deductions/in_military_retirement_deduction.py | 14 ++++++++++---- .../income/forgiveness/pa_eligibility_income.py | 9 ++++++++- .../income/subtractions/wi_income_subtractions.py | 2 +- 5 files changed, 24 insertions(+), 7 deletions(-) diff --git a/changelog.d/wire-military-retirement-pay.fixed.md b/changelog.d/wire-military-retirement-pay.fixed.md index 91a68e64f52..85e437e7722 100644 --- a/changelog.d/wire-military-retirement-pay.fixed.md +++ b/changelog.d/wire-military-retirement-pay.fixed.md @@ -5,4 +5,5 @@ Wire military retirement pay and military retirement pay survivors to federal gr - Model Indiana military retirement deduction under IC 6-3-2-4. - Model DC survivor benefits exclusion for age 62+ under D.C. Code § 47-1803.02(a)(2)(N)(ii). - Update Michigan retirement worksheets to account for military survivor benefits. +- Restrict military retirement and survivor deductions/subtractions in DC, IN, PA, and WI to tax unit filers to prevent dependent income leakage. - Update variable docstrings and references referencing IRC § 61(a)(10) and IRS Pubs 525/575. diff --git a/policyengine_us/variables/gov/states/dc/tax/income/subtractions/dc_survivor_benefits_subtraction.py b/policyengine_us/variables/gov/states/dc/tax/income/subtractions/dc_survivor_benefits_subtraction.py index 5cee9cf2b9f..33630124a12 100644 --- a/policyengine_us/variables/gov/states/dc/tax/income/subtractions/dc_survivor_benefits_subtraction.py +++ b/policyengine_us/variables/gov/states/dc/tax/income/subtractions/dc_survivor_benefits_subtraction.py @@ -19,8 +19,11 @@ def formula(person, period, parameters): .gov.states["dc"] .tax.income.subtractions.survivor_benefits ) + # Dependents' income is not in federal AGI; they report it on their + # own return. + head_or_spouse = person("is_tax_unit_head_or_spouse", period) age = person("age", period) - eligible = age >= p.min_age + eligible = (age >= p.min_age) & head_or_spouse # D.C. Code § 47-1803.02(a)(2)(N)(ii) allows exclusion of survivor benefits # received from the District or federal government by persons 62 or older. survivor_pay = person("military_retirement_pay_survivors", period) diff --git a/policyengine_us/variables/gov/states/in/tax/income/deductions/in_military_retirement_deduction.py b/policyengine_us/variables/gov/states/in/tax/income/deductions/in_military_retirement_deduction.py index d71748426f3..5cb35d27d3b 100644 --- a/policyengine_us/variables/gov/states/in/tax/income/deductions/in_military_retirement_deduction.py +++ b/policyengine_us/variables/gov/states/in/tax/income/deductions/in_military_retirement_deduction.py @@ -20,9 +20,15 @@ def formula(tax_unit, period, parameters): .gov.states["in"] .tax.income.deductions.military_retirement ) - military_retirement = person("military_retirement_pay", period) + person( - "military_retirement_pay_survivors", period - ) + # Dependents' income is not in federal AGI; they report it on their + # own return. + head_or_spouse = person("is_tax_unit_head_or_spouse", period) + military_retirement = ( + person("military_retirement_pay", period) + + person("military_retirement_pay_survivors", period) + ) * head_or_spouse excess = max_(0, military_retirement - p.base) - person_deduction = min_(military_retirement, p.base) + p.excess_rate * excess + person_deduction = ( + min_(military_retirement, p.base) + p.excess_rate * excess + ) * head_or_spouse return tax_unit.sum(person_deduction) diff --git a/policyengine_us/variables/gov/states/pa/tax/income/forgiveness/pa_eligibility_income.py b/policyengine_us/variables/gov/states/pa/tax/income/forgiveness/pa_eligibility_income.py index 5e84425cb75..89f5a5f0578 100644 --- a/policyengine_us/variables/gov/states/pa/tax/income/forgiveness/pa_eligibility_income.py +++ b/policyengine_us/variables/gov/states/pa/tax/income/forgiveness/pa_eligibility_income.py @@ -12,4 +12,11 @@ class pa_eligibility_income(Variable): reference = "https://www.pa.gov/content/dam/copapwp-pagov/en/revenue/documents/formsandpublications/formsforindividuals/pit/documents/2021/2021_pa-40sp.pdf" defined_for = StateCode.PA - adds = "gov.states.pa.tax.income.forgiveness.eligibility_income_sources" + def formula(tax_unit, period, parameters): + sources = parameters( + period + ).gov.states.pa.tax.income.forgiveness.eligibility_income_sources + # The sources are amounts of the claimant and spouse; dependents file + # their own PA return and their income is not part of the filer's + # eligibility income. + return tax_unit_non_dep_add(tax_unit, period, sources) diff --git a/policyengine_us/variables/gov/states/wi/tax/income/subtractions/wi_income_subtractions.py b/policyengine_us/variables/gov/states/wi/tax/income/subtractions/wi_income_subtractions.py index b11879fe327..77999458b0c 100644 --- a/policyengine_us/variables/gov/states/wi/tax/income/subtractions/wi_income_subtractions.py +++ b/policyengine_us/variables/gov/states/wi/tax/income/subtractions/wi_income_subtractions.py @@ -17,6 +17,6 @@ class wi_income_subtractions(Variable): def formula(tax_unit, period, parameters): p = parameters(period).gov.states.wi.tax.income.subtractions - total_subtractions = add(tax_unit, period, p.sources) + total_subtractions = tax_unit_non_dep_add(tax_unit, period, p.sources) # Prevent negative subtractions from acting as additions return max_(0, total_subtractions) From 6e7667f257668cc321cd599ca6323c64fa8f692d Mon Sep 17 00:00:00 2001 From: Deepak Jindal Date: Thu, 15 Oct 2026 12:40:32 -0700 Subject: [PATCH 5/5] Address review feedback: shared military retirement variable, state edge cases, and test overhaul --- .../wire-military-retirement-pay.fixed.md | 2 +- .../gov/household/market_income_sources.yaml | 3 +- .../agi/military_retirement/agi_limit.yaml | 15 +-- .../income/agi/military_retirement/cap.yaml | 9 +- .../survivor_benefits/min_age.yaml | 1 + .../exclusions/pension/income_sources.yaml | 3 +- .../additional/amount.yaml | 1 + .../exclusions/military_retirement/base.yaml | 1 + .../tax/income/subtractions/subtractions.yaml | 6 +- .../income/taxable_income/subtractions.yaml | 21 +---- .../il/tax/income/base/subtractions.yaml | 3 +- .../deductions/military_retirement/base.yaml | 3 +- .../military_retirement/excess_rate.yaml | 3 +- .../income/disallowed_deductions.yaml | 1 + .../survivors_eligible.yaml | 8 +- .../tax/income/agi/subtractions/sources.yaml | 4 +- .../eligibility_income_sources.yaml | 3 +- .../tax/income/nontaxable_income_sources.yaml | 3 +- .../taxable_retirement_income/sources.yaml | 3 +- .../wi/tax/income/subtractions/sources.yaml | 6 +- .../military_retirement_pay.yaml | 6 +- .../ca/tax/income/ca_taxable_income.yaml | 91 +++++++++++++++++++ .../pension/co_pension_subtraction_indv.yaml | 10 ++ .../de_pension_exclusion.yaml | 6 +- ...nt_income_exclusion_retirement_income.yaml | 21 +++++ .../ia_subtractions_consolidated.yaml | 24 +++++ .../id_military_retirement_deduction.yaml | 19 ++++ .../income/il_base_income_subtractions.yaml | 23 +++++ .../ks/tax/income/ks_agi_subtractions.yaml | 11 +++ .../ky_pension_income_exclusion.yaml | 10 ++ .../ma_scb_total_income.yaml | 29 ++++++ .../income/gross_income/ma_gross_income.yaml | 13 +++ .../agi/md_pension_subtraction_amount.yaml | 14 +++ ...est_dividends_capital_gains_deduction.yaml | 24 +++++ ...xpanded_retirement_benefits_deduction.yaml | 19 +++- ...nt_benefits_deduction_tier_one_amount.yaml | 22 ++++- ...tion_tier_three_ss_exempt_not_retired.yaml | 22 +++++ ...eduction_tier_three_ss_exempt_retired.yaml | 21 +++++ .../mi_standard_deduction_tier_three.yaml | 23 +++++ .../mi_standard_deduction_tier_two.yaml | 21 +++++ .../mn/tax/income/mn_amt_taxable_income.yaml | 10 ++ .../subtractions/mo_agi_subtractions.yaml | 16 ++++ .../ne_military_retirement_subtraction.yaml | 36 ++++++++ .../nj_529_deduction.yaml | 11 +++ .../ny/tax/income/ny_agi_subtractions.yaml | 12 +++ .../or_retirement_credit.yaml | 22 +++++ .../forgiveness/pa_eligibility_income.yaml | 17 ++++ .../ri_retirement_income_subtraction.yaml | 10 ++ .../vt_military_retirement_pay_exclusion.yaml | 39 ++++++++ .../ca_military_retirement_exclusion.py | 19 ++-- .../pension_exclusion/de_pension_exclusion.py | 3 +- .../id_military_retirement_deduction.py | 6 +- .../in_military_retirement_deduction.py | 11 +-- .../ks/tax/income/ks_agi_subtractions.py | 3 +- .../ky_pension_income_exclusion.py | 3 +- .../income/gross_income/ma_gross_income.py | 3 +- .../md_military_retirement_subtraction.py | 22 +---- ..._military_retirement_subtraction_amount.py | 31 +++++++ .../md_pension_subtraction_amount.py | 13 +-- .../me_pension_income_deduction.py | 4 +- ...erest_dividends_capital_gains_deduction.py | 3 +- ..._expanded_retirement_benefits_deduction.py | 5 +- ...ment_benefits_deduction_tier_one_amount.py | 5 +- ...uction_tier_three_ss_exempt_not_retired.py | 5 +- ..._deduction_tier_three_ss_exempt_retired.py | 5 +- .../mi_standard_deduction_tier_three.py | 4 +- .../mi_standard_deduction_tier_two.py | 3 +- .../nc_military_retirement_deduction.py | 5 +- ...c_military_retirement_survivor_eligible.py | 3 - .../ne_military_retirement_subtraction.py | 7 +- .../nj_529_deduction.py | 6 +- ...ed_services_retirement_income_deduction.py | 4 +- .../retirement_credit/or_retirement_credit.py | 6 +- .../income/person/general/market_income.py | 3 +- .../retirement/military_retirement_income.py | 18 ++++ .../retirement/military_retirement_pay.py | 16 +++- .../military_retirement_pay_survivors.py | 20 ++-- 77 files changed, 758 insertions(+), 179 deletions(-) create mode 100644 policyengine_us/tests/policy/baseline/gov/states/pa/tax/income/forgiveness/pa_eligibility_income.yaml create mode 100644 policyengine_us/variables/gov/states/md/tax/income/agi/subtractions/md_military_retirement_subtraction_amount.py create mode 100644 policyengine_us/variables/household/income/person/retirement/military_retirement_income.py diff --git a/changelog.d/wire-military-retirement-pay.fixed.md b/changelog.d/wire-military-retirement-pay.fixed.md index 85e437e7722..d358df46655 100644 --- a/changelog.d/wire-military-retirement-pay.fixed.md +++ b/changelog.d/wire-military-retirement-pay.fixed.md @@ -1,5 +1,5 @@ Wire military retirement pay and military retirement pay survivors to federal gross income (`irs_gross_income`), person `market_income`, household `market_income_sources`, SNAP unearned income, and SSI unearned income. Update state tax calculations and exclusions across all affected states to conform with federal AGI inclusion and statutory state treatment: -- State military retirement and survivor subtractions added or updated in AR, AZ, CA, CO, CT, DC, DE, GA, HI, IA, ID, IL, IN, KS, KY, LA, MA, MD, ME, MI, MN, MO, ND, NE, NM, NY, OH, OK, OR, PA, RI, UT, VA, VT, WV. +- State military retirement and survivor subtractions added or updated in AR, AZ, CA, CO, CT, DC, DE, GA, HI, IA, ID, IL, IN, KS, KY, LA, MA, MD, ME, MI, MN, MO, ND, NE, NJ, NM, NY, OH, OK, OR, PA, RI, UT, VA, VT, WI, WV. - Fix Georgia double-counting under O.C.G.A. § 48-7-27(a)(5)(E) and Rule 560-7-4-.02(3). - Model California 2025–2029 military retirement and SBP exclusion under R&TC §§ 17132.9–17132.10. - Model Indiana military retirement deduction under IC 6-3-2-4. diff --git a/policyengine_us/parameters/gov/household/market_income_sources.yaml b/policyengine_us/parameters/gov/household/market_income_sources.yaml index e565944ad98..bbf4153f1ca 100644 --- a/policyengine_us/parameters/gov/household/market_income_sources.yaml +++ b/policyengine_us/parameters/gov/household/market_income_sources.yaml @@ -15,8 +15,7 @@ values: - dividend_income - pension_income # Pension income includes annuities and endowment contracts - - military_retirement_pay - - military_retirement_pay_survivors + - military_retirement_income - debt_relief # Income from estates and trusts (Schedule E Part III), including income # in respect of a decedent received through an estate or trust. diff --git a/policyengine_us/parameters/gov/states/ca/tax/income/agi/military_retirement/agi_limit.yaml b/policyengine_us/parameters/gov/states/ca/tax/income/agi/military_retirement/agi_limit.yaml index e90c310d33a..f84ee74ac2c 100644 --- a/policyengine_us/parameters/gov/states/ca/tax/income/agi/military_retirement/agi_limit.yaml +++ b/policyengine_us/parameters/gov/states/ca/tax/income/agi/military_retirement/agi_limit.yaml @@ -2,34 +2,37 @@ description: Federal AGI limit to qualify for California military retirement and metadata: unit: currency-USD period: year + label: California military retirement and survivor benefit exclusion federal AGI limit breakdown: - filing_status reference: - - title: Cal. Rev. & Tax. Code §§ 17132.9, 17132.10 + - title: Cal. Rev. & Tax. Code § 17132.9 href: https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?sectionNum=17132.9.&lawCode=RTC + - title: Cal. Rev. & Tax. Code § 17132.10 + href: https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?sectionNum=17132.10.&lawCode=RTC SINGLE: values: 2021-01-01: 0 - 2025-01-01: 125000 + 2025-01-01: 125_000 2030-01-01: 0 JOINT: values: 2021-01-01: 0 - 2025-01-01: 250000 + 2025-01-01: 250_000 2030-01-01: 0 SEPARATE: values: 2021-01-01: 0 - 2025-01-01: 125000 + 2025-01-01: 125_000 2030-01-01: 0 HEAD_OF_HOUSEHOLD: values: 2021-01-01: 0 - 2025-01-01: 125000 + 2025-01-01: 125_000 2030-01-01: 0 SURVIVING_SPOUSE: values: 2021-01-01: 0 - 2025-01-01: 250000 + 2025-01-01: 250_000 2030-01-01: 0 diff --git a/policyengine_us/parameters/gov/states/ca/tax/income/agi/military_retirement/cap.yaml b/policyengine_us/parameters/gov/states/ca/tax/income/agi/military_retirement/cap.yaml index 033e8ad9884..1aa74bcca46 100644 --- a/policyengine_us/parameters/gov/states/ca/tax/income/agi/military_retirement/cap.yaml +++ b/policyengine_us/parameters/gov/states/ca/tax/income/agi/military_retirement/cap.yaml @@ -1,11 +1,14 @@ -description: California maximum military retirement and SBP exclusion amount per category per person under R&TC §§ 17132.9 and 17132.10. +description: California maximum military retirement and SBP exclusion amount per category per return under R&TC §§ 17132.9 and 17132.10. values: 2021-01-01: 0 - 2025-01-01: 20000 + 2025-01-01: 20_000 2030-01-01: 0 metadata: unit: currency-USD period: year + label: California military retirement and survivor benefit exclusion cap reference: - - title: Cal. Rev. & Tax. Code §§ 17132.9, 17132.10 + - title: Cal. Rev. & Tax. Code § 17132.9 href: https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?sectionNum=17132.9.&lawCode=RTC + - title: Cal. Rev. & Tax. Code § 17132.10 + href: https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?sectionNum=17132.10.&lawCode=RTC diff --git a/policyengine_us/parameters/gov/states/dc/tax/income/subtractions/survivor_benefits/min_age.yaml b/policyengine_us/parameters/gov/states/dc/tax/income/subtractions/survivor_benefits/min_age.yaml index 62b7119466e..d9150089f4b 100644 --- a/policyengine_us/parameters/gov/states/dc/tax/income/subtractions/survivor_benefits/min_age.yaml +++ b/policyengine_us/parameters/gov/states/dc/tax/income/subtractions/survivor_benefits/min_age.yaml @@ -2,6 +2,7 @@ description: Minimum age to exclude government survivor benefits in DC. values: 2015-01-01: 62 metadata: + label: DC minimum age for survivor benefits exclusion unit: year period: year reference: diff --git a/policyengine_us/parameters/gov/states/de/tax/income/subtractions/exclusions/pension/income_sources.yaml b/policyengine_us/parameters/gov/states/de/tax/income/subtractions/exclusions/pension/income_sources.yaml index fbdab67a336..74344c13e5e 100644 --- a/policyengine_us/parameters/gov/states/de/tax/income/subtractions/exclusions/pension/income_sources.yaml +++ b/policyengine_us/parameters/gov/states/de/tax/income/subtractions/exclusions/pension/income_sources.yaml @@ -6,8 +6,7 @@ values: - taxable_interest_income - rental_income - taxable_pension_income - - military_retirement_pay - - military_retirement_pay_survivors + - military_retirement_income - taxable_ira_distributions - taxable_401k_distributions - taxable_403b_distributions diff --git a/policyengine_us/parameters/gov/states/ga/tax/income/agi/exclusions/military_retirement/additional/amount.yaml b/policyengine_us/parameters/gov/states/ga/tax/income/agi/exclusions/military_retirement/additional/amount.yaml index 614e99cab0c..5461deca436 100644 --- a/policyengine_us/parameters/gov/states/ga/tax/income/agi/exclusions/military_retirement/additional/amount.yaml +++ b/policyengine_us/parameters/gov/states/ga/tax/income/agi/exclusions/military_retirement/additional/amount.yaml @@ -14,4 +14,5 @@ metadata: - title: 2025 IT-511 Individual Income Tax Booklet - Subtractions(2) href: https://dor.georgia.gov/document/document/2025-it-511-individual-income-tax-booklet/download#page=21 values: + 2021-01-01: 0 2022-01-01: 17_500 diff --git a/policyengine_us/parameters/gov/states/ga/tax/income/agi/exclusions/military_retirement/base.yaml b/policyengine_us/parameters/gov/states/ga/tax/income/agi/exclusions/military_retirement/base.yaml index f6204c1ae37..85a779bd1d5 100644 --- a/policyengine_us/parameters/gov/states/ga/tax/income/agi/exclusions/military_retirement/base.yaml +++ b/policyengine_us/parameters/gov/states/ga/tax/income/agi/exclusions/military_retirement/base.yaml @@ -14,4 +14,5 @@ metadata: - title: 2025 IT-511 Individual Income Tax Booklet - Subtractions(2) href: https://dor.georgia.gov/document/document/2025-it-511-individual-income-tax-booklet/download#page=21 values: + 2021-01-01: 0 2022-01-01: 17_500 diff --git a/policyengine_us/parameters/gov/states/hi/tax/income/subtractions/subtractions.yaml b/policyengine_us/parameters/gov/states/hi/tax/income/subtractions/subtractions.yaml index 24605dce1a7..0d109beb922 100644 --- a/policyengine_us/parameters/gov/states/hi/tax/income/subtractions/subtractions.yaml +++ b/policyengine_us/parameters/gov/states/hi/tax/income/subtractions/subtractions.yaml @@ -2,16 +2,14 @@ description: Hawaii subtracts these sources from adjusted gross income. values: 2021-01-01: - taxable_pension_income # Line 13 - - military_retirement_pay # Line 13 - - military_retirement_pay_survivors # Line 13 + - military_retirement_income # Line 13 - taxable_social_security # Line 14 - hi_military_pay_exclusion # Line 15 - us_govt_interest # Line 18 - student_loan_interest_ald # Line 18 2025-01-01: - taxable_pension_income # Line 13 - - military_retirement_pay # Line 13 - - military_retirement_pay_survivors # Line 13 + - military_retirement_income # Line 13 - taxable_social_security # Line 14 - hi_military_pay_exclusion # Line 15 - us_govt_interest # Line 18 diff --git a/policyengine_us/parameters/gov/states/ia/tax/income/taxable_income/subtractions.yaml b/policyengine_us/parameters/gov/states/ia/tax/income/taxable_income/subtractions.yaml index 8ec924b5ea4..515e58b18a0 100644 --- a/policyengine_us/parameters/gov/states/ia/tax/income/taxable_income/subtractions.yaml +++ b/policyengine_us/parameters/gov/states/ia/tax/income/taxable_income/subtractions.yaml @@ -4,26 +4,7 @@ values: # Line 1B - us_govt_interest # Dividends from federal securities - - military_retirement_pay - - military_retirement_pay_survivors - # Line 5B - - taxable_social_security - # Line 6B - - military_service_income - # Line 7B - - ia_pension_exclusion - # Railroad unemployment income - # Bonus Depreciation - # Iowa Health Insurance Deduction - # Iowa capital gains deduction - - ia_529_plan_subtraction - 2024-01-01: # Line 4B on 2024 Form IA 1040 - # Line 1B - - us_govt_interest - # Dividends from federal securities - # Line 4B - - military_retirement_pay - - military_retirement_pay_survivors + - military_retirement_income # Line 5B - taxable_social_security # Line 6B diff --git a/policyengine_us/parameters/gov/states/il/tax/income/base/subtractions.yaml b/policyengine_us/parameters/gov/states/il/tax/income/base/subtractions.yaml index a01b72bbbaf..d5b497a05b3 100644 --- a/policyengine_us/parameters/gov/states/il/tax/income/base/subtractions.yaml +++ b/policyengine_us/parameters/gov/states/il/tax/income/base/subtractions.yaml @@ -6,8 +6,7 @@ values: - taxable_pension_income - taxable_retirement_distributions - taxable_roth_conversions - - military_retirement_pay - - military_retirement_pay_survivors + - military_retirement_income - il_schedule_m_subtractions - il_529_plan_subtraction - salt_refund_income diff --git a/policyengine_us/parameters/gov/states/in/tax/income/deductions/military_retirement/base.yaml b/policyengine_us/parameters/gov/states/in/tax/income/deductions/military_retirement/base.yaml index 1845157e0de..1d61c9a03f5 100644 --- a/policyengine_us/parameters/gov/states/in/tax/income/deductions/military_retirement/base.yaml +++ b/policyengine_us/parameters/gov/states/in/tax/income/deductions/military_retirement/base.yaml @@ -1,7 +1,8 @@ description: Indiana base military retirement deduction amount. values: - 2021-01-01: 6250 + 2021-01-01: 6_250 metadata: + label: Indiana military retirement deduction base amount unit: currency-USD period: year reference: diff --git a/policyengine_us/parameters/gov/states/in/tax/income/deductions/military_retirement/excess_rate.yaml b/policyengine_us/parameters/gov/states/in/tax/income/deductions/military_retirement/excess_rate.yaml index bf9383d47c1..f9a17e64874 100644 --- a/policyengine_us/parameters/gov/states/in/tax/income/deductions/military_retirement/excess_rate.yaml +++ b/policyengine_us/parameters/gov/states/in/tax/income/deductions/military_retirement/excess_rate.yaml @@ -1,8 +1,9 @@ description: Indiana rate of deduction for military retirement benefits exceeding the base amount. values: 2021-01-01: 0.75 - 2022-01-01: 1.0 + 2022-01-01: 1 metadata: + label: Indiana military retirement deduction excess rate unit: /1 period: year reference: diff --git a/policyengine_us/parameters/gov/states/ma/tax/income/credits/senior_circuit_breaker/income/disallowed_deductions.yaml b/policyengine_us/parameters/gov/states/ma/tax/income/credits/senior_circuit_breaker/income/disallowed_deductions.yaml index 51a91ae417a..879ff14cb15 100644 --- a/policyengine_us/parameters/gov/states/ma/tax/income/credits/senior_circuit_breaker/income/disallowed_deductions.yaml +++ b/policyengine_us/parameters/gov/states/ma/tax/income/credits/senior_circuit_breaker/income/disallowed_deductions.yaml @@ -29,6 +29,7 @@ values: - ssi - ma_state_supplement - tanf + - military_retirement_income # In-kind under § 6(k)(1) item 2; see the note above before re-enabling. # - snap # - wic diff --git a/policyengine_us/parameters/gov/states/ne/tax/income/agi/subtractions/military_retirement/survivors_eligible.yaml b/policyengine_us/parameters/gov/states/ne/tax/income/agi/subtractions/military_retirement/survivors_eligible.yaml index e98017517e9..a0daf2d781e 100644 --- a/policyengine_us/parameters/gov/states/ne/tax/income/agi/subtractions/military_retirement/survivors_eligible.yaml +++ b/policyengine_us/parameters/gov/states/ne/tax/income/agi/subtractions/military_retirement/survivors_eligible.yaml @@ -10,7 +10,7 @@ metadata: reference: - title: Neb. Rev. Stat. § 77-2716(15) href: https://nebraskalegislature.gov/laws/statutes.php?statute=77-2716 - - title: 2021 Form 1040N-MIL - href: https://revenue.nebraska.gov/sites/revenue.nebraska.gov/files/doc/f_1040n_booklet.pdf#page=16 - - title: 2025 Form 1040N Schedule I, line 32 - href: https://revenue.nebraska.gov/sites/default/files/doc/tax-forms/2025/f_Individual_Income_Tax_Booklet.pdf#page=26 + - title: Form 1040N-MIL + href: https://revenue.nebraska.gov/sites/default/files/doc/f_1040n_mil.pdf#page=2 + - title: Nebraska Information Guide 8-364 + href: https://revenue.nebraska.gov/sites/default/files/doc/info/8-364.pdf#page=2 diff --git a/policyengine_us/parameters/gov/states/ny/tax/income/agi/subtractions/sources.yaml b/policyengine_us/parameters/gov/states/ny/tax/income/agi/subtractions/sources.yaml index f54fa63e677..54ba1f86c1c 100644 --- a/policyengine_us/parameters/gov/states/ny/tax/income/agi/subtractions/sources.yaml +++ b/policyengine_us/parameters/gov/states/ny/tax/income/agi/subtractions/sources.yaml @@ -8,9 +8,9 @@ values: - salt_refund_income # N.Y. Tax Law § 612(c)(3) / Form IT-201 Line 26: subtracts pensions paid by NY state, # local governments, or the federal government. Pensions from other states are not exempt. + # PolicyEngine subtracts taxable_public_pension_income as an in-state/federal proxy. - taxable_public_pension_income - - military_retirement_pay - - military_retirement_pay_survivors + - military_retirement_income metadata: unit: list period: year diff --git a/policyengine_us/parameters/gov/states/pa/tax/income/forgiveness/eligibility_income_sources.yaml b/policyengine_us/parameters/gov/states/pa/tax/income/forgiveness/eligibility_income_sources.yaml index fbef577ec26..7b18b8e1c08 100644 --- a/policyengine_us/parameters/gov/states/pa/tax/income/forgiveness/eligibility_income_sources.yaml +++ b/policyengine_us/parameters/gov/states/pa/tax/income/forgiveness/eligibility_income_sources.yaml @@ -8,8 +8,7 @@ values: # insurance proceeds and inheritances # gifts awards and prizes # non-PA income - # nontaxable military income - - military_retirement_pay + # nontaxable military income (military pension benefits excluded per PA-40 SP) - military_retirement_pay_survivors # gain excluded from the sale of a residence # nontaxable education assistance diff --git a/policyengine_us/parameters/gov/states/pa/tax/income/nontaxable_income_sources.yaml b/policyengine_us/parameters/gov/states/pa/tax/income/nontaxable_income_sources.yaml index b5e95573307..e4c198a1e2b 100644 --- a/policyengine_us/parameters/gov/states/pa/tax/income/nontaxable_income_sources.yaml +++ b/policyengine_us/parameters/gov/states/pa/tax/income/nontaxable_income_sources.yaml @@ -8,8 +8,7 @@ values: - taxable_social_security - us_govt_interest - salt_refund_income - - military_retirement_pay - - military_retirement_pay_survivors + - military_retirement_income metadata: unit: currency-USD label: PA nontaxable income sources diff --git a/policyengine_us/parameters/gov/states/ri/tax/income/agi/subtractions/taxable_retirement_income/sources.yaml b/policyengine_us/parameters/gov/states/ri/tax/income/agi/subtractions/taxable_retirement_income/sources.yaml index 1ddcdf7ac62..b9e9db7b587 100644 --- a/policyengine_us/parameters/gov/states/ri/tax/income/agi/subtractions/taxable_retirement_income/sources.yaml +++ b/policyengine_us/parameters/gov/states/ri/tax/income/agi/subtractions/taxable_retirement_income/sources.yaml @@ -2,8 +2,7 @@ description: Rhode Island subtracts these retirement income sources from adjuste values: 2021-01-01: - taxable_pension_income - - military_retirement_pay - - military_retirement_pay_survivors + - military_retirement_income - taxable_401k_distributions - taxable_403b_distributions 2023-01-01: diff --git a/policyengine_us/parameters/gov/states/wi/tax/income/subtractions/sources.yaml b/policyengine_us/parameters/gov/states/wi/tax/income/subtractions/sources.yaml index 6835cf08903..ece88e50beb 100644 --- a/policyengine_us/parameters/gov/states/wi/tax/income/subtractions/sources.yaml +++ b/policyengine_us/parameters/gov/states/wi/tax/income/subtractions/sources.yaml @@ -6,8 +6,7 @@ values: - wi_capital_gain_loss_subtraction - wi_childcare_expense_subtraction - wi_retirement_income_subtraction - - military_retirement_pay - - military_retirement_pay_survivors + - military_retirement_income - us_govt_interest - wi_529_plan_deduction - salt_refund_income @@ -16,8 +15,7 @@ values: - tax_unit_taxable_social_security - wi_capital_gain_loss_subtraction - wi_retirement_income_subtraction - - military_retirement_pay - - military_retirement_pay_survivors + - military_retirement_income - us_govt_interest - wi_529_plan_deduction - salt_refund_income diff --git a/policyengine_us/tests/policy/baseline/gov/irs/income/taxable_income/adjusted_gross_income/irs_gross_income/military_retirement_pay.yaml b/policyengine_us/tests/policy/baseline/gov/irs/income/taxable_income/adjusted_gross_income/irs_gross_income/military_retirement_pay.yaml index e62d44de1bf..befdc3853b7 100644 --- a/policyengine_us/tests/policy/baseline/gov/irs/income/taxable_income/adjusted_gross_income/irs_gross_income/military_retirement_pay.yaml +++ b/policyengine_us/tests/policy/baseline/gov/irs/income/taxable_income/adjusted_gross_income/irs_gross_income/military_retirement_pay.yaml @@ -10,7 +10,7 @@ input: people: person1: - age: 60 + age: 55 is_tax_unit_head: true military_retirement_pay: 30_000 tax_units: @@ -28,14 +28,14 @@ household_market_income: 30_000 snap_unearned_income: 30_000 ssi_unearned_income: 30_000 - household_net_income: 28_915 + household_net_income: 28_384 - name: Case 2, Military retirement pay survivors flows into federal gross income, AGI, and taxable income. period: 2024 input: people: person1: - age: 60 + age: 55 is_tax_unit_head: true military_retirement_pay_survivors: 24_000 tax_units: diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/ca_taxable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/ca_taxable_income.yaml index 2b8158fb796..fb71aafa40e 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/ca_taxable_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/ca_taxable_income.yaml @@ -38,3 +38,94 @@ ca_agi: 60_000 - 30_000 ca_taxable_income: 30_000 - 5_706 +- name: CA AGI cliff at $125,000 (excludes when AGI does not exceed limit) + period: 2025 + input: + state_code: CA + employment_income: 105_000 + military_retirement_pay: 20_000 + output: + ca_military_retirement_exclusion: 20_000 + +- name: CA AGI cliff at $125,001 (cliff denies exclusion when AGI exceeds limit) + period: 2025 + input: + state_code: CA + employment_income: 105_001 + military_retirement_pay: 20_000 + output: + ca_military_retirement_exclusion: 0 + +- name: CA joint return at $250,000 AGI limit + period: 2025 + input: + people: + head: + is_tax_unit_head: true + employment_income: 100_000 + military_retirement_pay: 25_000 + spouse: + is_tax_unit_spouse: true + employment_income: 100_000 + military_retirement_pay: 25_000 + tax_units: + tax_unit: + members: [head, spouse] + filing_status: JOINT + households: + household: + members: [head, spouse] + state_code: CA + output: + ca_military_retirement_exclusion: 20_000 + +- name: CA dependent recipient does not generate exclusion on filer return + period: 2025 + input: + people: + head: + is_tax_unit_head: true + employment_income: 50_000 + dependent: + is_tax_unit_dependent: true + military_retirement_pay: 20_000 + tax_units: + tax_unit: + members: [head, dependent] + households: + household: + members: [head, dependent] + state_code: CA + output: + ca_military_retirement_exclusion: 0 + +- name: CA 2030 sunset of military retirement exclusion + period: 2030 + input: + state_code: CA + military_retirement_pay: 20_000 + output: + ca_military_retirement_exclusion: 0 + +- name: CA joint return with both spouses receiving military pay capped at $20,000 per return + period: 2025 + input: + people: + head: + age: 62 + is_tax_unit_head: true + military_retirement_pay: 60_000 + spouse: + age: 62 + is_tax_unit_spouse: true + military_retirement_pay: 60_000 + tax_units: + tax_unit: + members: [head, spouse] + filing_status: JOINT + households: + household: + members: [head, spouse] + state_code: CA + output: + ca_military_retirement_exclusion: 20_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/co/tax/income/subtractions/pension/co_pension_subtraction_indv.yaml b/policyengine_us/tests/policy/baseline/gov/states/co/tax/income/subtractions/pension/co_pension_subtraction_indv.yaml index 42a1ef07bbc..3f921336f26 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/co/tax/income/subtractions/pension/co_pension_subtraction_indv.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/co/tax/income/subtractions/pension/co_pension_subtraction_indv.yaml @@ -155,3 +155,13 @@ co_pension_subtraction_income: 15_000 co_pension_subtraction_indv: 15_000 +- name: Filer under 55 with military retirement survivor benefits subtracts up to $20,000 under Book 104 line 4 + period: 2025 + input: + state_code: CO + age: 45 + co_social_security_subtraction_indv: 0 + military_retirement_pay_survivors: 18_000 + co_pension_subtraction_indv_eligible: true + output: + co_pension_subtraction_indv: 18_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/de/tax/income/subtractions/pension_exclusion/de_pension_exclusion.yaml b/policyengine_us/tests/policy/baseline/gov/states/de/tax/income/subtractions/pension_exclusion/de_pension_exclusion.yaml index 6ab03fcd95b..935d7bd10f1 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/de/tax/income/subtractions/pension_exclusion/de_pension_exclusion.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/de/tax/income/subtractions/pension_exclusion/de_pension_exclusion.yaml @@ -137,11 +137,11 @@ period: 2024 input: age: 50 - military_retirement_pay_survivors: 1_500 + military_retirement_pay_survivors: 3_000 is_tax_unit_head_or_spouse: true state_code: DE output: - de_pension_exclusion: 1_500 + de_pension_exclusion: 2_000 - name: DE 60+ filer with military retirement and survivor benefits in retirement basket period: 2024 @@ -153,5 +153,3 @@ state_code: DE output: de_pension_exclusion: 12_500 - - diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/tax/income/subtractions/retirement/ga_retirement_income_exclusion_retirement_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/tax/income/subtractions/retirement/ga_retirement_income_exclusion_retirement_income.yaml index bb3b80f3fcd..79b111584db 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ga/tax/income/subtractions/retirement/ga_retirement_income_exclusion_retirement_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ga/tax/income/subtractions/retirement/ga_retirement_income_exclusion_retirement_income.yaml @@ -36,3 +36,24 @@ taxable_roth_conversions: 25_000 output: ga_retirement_income_exclusion_retirement_income: 25_000 + +- name: GA 2021 military retirement pay is fully included in retirement income (military exclusion starts in 2022) + period: 2021 + input: + state_code: GA + is_disabled: true + age: 50 + military_retirement_pay: 30_000 + output: + ga_retirement_income_exclusion_retirement_income: 30_000 + +- name: GA 2024 military retirement pay reduced by under-62 exclusion plus survivor pay + period: 2024 + input: + state_code: GA + is_disabled: true + age: 50 + military_retirement_pay: 40_000 + military_retirement_pay_survivors: 5_000 + output: + ga_retirement_income_exclusion_retirement_income: 27_500 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ia/tax/income/consolidated/taxable_income/ia_subtractions_consolidated.yaml b/policyengine_us/tests/policy/baseline/gov/states/ia/tax/income/consolidated/taxable_income/ia_subtractions_consolidated.yaml index 6b554452380..a857eb1a419 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ia/tax/income/consolidated/taxable_income/ia_subtractions_consolidated.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ia/tax/income/consolidated/taxable_income/ia_subtractions_consolidated.yaml @@ -163,3 +163,27 @@ output: ia_pension_exclusion: [0, 12_000, 0] ia_subtractions_consolidated: 12_000 + +- name: Filer military retirement pay and survivors subtracted in TY2023 under Iowa Code § 422.7(20)-(21) + period: 2023 + absolute_error_margin: 0.01 + input: + people: + head: + age: 50 + employment_income: 40_000 + military_retirement_pay: 30_000 + military_retirement_pay_survivors: 10_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [head] + marital_units: + head_marital_unit: + members: [head] + households: + household: + members: [head] + state_code: IA + output: + ia_subtractions_consolidated: 40_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/id/tax/income/subtractions/military_retirement/id_military_retirement_deduction.yaml b/policyengine_us/tests/policy/baseline/gov/states/id/tax/income/subtractions/military_retirement/id_military_retirement_deduction.yaml index 40fd93a78ef..f17e31fa1db 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/id/tax/income/subtractions/military_retirement/id_military_retirement_deduction.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/id/tax/income/subtractions/military_retirement/id_military_retirement_deduction.yaml @@ -81,3 +81,22 @@ state_code: ID output: id_military_retirement_deduction: 30_000 + +- name: Military retirement survivor benefits fully exempt for 2025 under Idaho Code § 63-3022A(1)(b) + period: 2025 + input: + people: + person1: + is_tax_unit_head_or_spouse: true + military_retirement_pay_survivors: 25_000 + age: 50 + tax_units: + tax_unit: + members: [person1] + filing_status: SINGLE + households: + household: + members: [person1] + state_code: ID + output: + id_military_retirement_deduction: 25_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/il/tax/income/income/il_base_income_subtractions.yaml b/policyengine_us/tests/policy/baseline/gov/states/il/tax/income/income/il_base_income_subtractions.yaml index abc24ec6242..5ea94fe1e66 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/il/tax/income/income/il_base_income_subtractions.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/il/tax/income/income/il_base_income_subtractions.yaml @@ -142,3 +142,26 @@ adjusted_gross_income: 50_000 il_base_income_subtractions: 10_000 il_base_income: 40_000 + +- name: Filer military retirement pay and survivor benefits are subtracted from IL base income. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + head: + age: 60 + employment_income: 50_000 + military_retirement_pay: 20_000 + military_retirement_pay_survivors: 10_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [head] + households: + household: + members: [head] + state_code: IL + output: + adjusted_gross_income: 80_000 + il_base_income_subtractions: 30_000 + il_base_income: 50_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/tax/income/ks_agi_subtractions.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/tax/income/ks_agi_subtractions.yaml index f36e6e880ac..187d331cf36 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/tax/income/ks_agi_subtractions.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/tax/income/ks_agi_subtractions.yaml @@ -149,3 +149,14 @@ ks_taxable_income: 29_170 # 23,001 * 5.2% + (29,170 - 23,001) * 5.58% = 1,196.05 + 344.23 ks_income_tax_before_credits: 1_540.28 + +- name: Filer military retirement pay and survivor benefits subtracted under K.S.A. § 79-32,117(c) + period: 2025 + input: + state_code: KS + employment_income: 50_000 + military_retirement_pay: 15_000 + military_retirement_pay_survivors: 10_000 + output: + ks_agi_subtractions: 25_000 + ks_agi: 50_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ky/tax/income/exclusions/pension_income/ky_pension_income_exclusion.yaml b/policyengine_us/tests/policy/baseline/gov/states/ky/tax/income/exclusions/pension_income/ky_pension_income_exclusion.yaml index 9b71e683b27..2b46d160a1b 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ky/tax/income/exclusions/pension_income/ky_pension_income_exclusion.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ky/tax/income/exclusions/pension_income/ky_pension_income_exclusion.yaml @@ -73,3 +73,13 @@ state_code: KY output: ky_pension_income_exclusion: 20_000 + +- name: Military retirement pay and survivor benefits qualify for KY pension exclusion + period: 2024 + input: + state_code: KY + military_retirement_pay: 15_000 + military_retirement_pay_survivors: 10_000 + ky_pension_income_exclusion_exemption_eligible: false + output: + ky_pension_income_exclusion: 25_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ma/tax/income/credits/senior_circuit_breaker/ma_scb_total_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ma/tax/income/credits/senior_circuit_breaker/ma_scb_total_income.yaml index b336c7edd98..5f536473a77 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ma/tax/income/credits/senior_circuit_breaker/ma_scb_total_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ma/tax/income/credits/senior_circuit_breaker/ma_scb_total_income.yaml @@ -157,3 +157,32 @@ # The child's 10,000 public pension, 4,000 tax-exempt pension and 3,000 # Social Security are not the taxpayer's income and are not re-added. ma_scb_total_income: 52_600 + +- name: Military retirement pay is re-added to SCB total income under § 6(k)(1). + period: 2025 + absolute_error_margin: 0.1 + input: + people: + head: + age: 65 + military_retirement_pay: 30_000 + is_tax_unit_head: true + is_tax_unit_dependent: false + ssi: 0 + ma_state_supplement: 0 + tax_units: + tax_unit: + members: [head] + spm_units: + spm_unit: + tanf: 0 + members: [head] + households: + household: + members: [head] + state_code: MA + output: + # 30,000 pay is excluded from ma_gross_income (0), but re-added under § 6(k)(1); + # reduced by 700 aged exemption = 29,300. + ma_gross_income: 0 + ma_scb_total_income: 29_300 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ma/tax/income/gross_income/ma_gross_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ma/tax/income/gross_income/ma_gross_income.yaml index 00d8ca39995..2b3d6210c7d 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ma/tax/income/gross_income/ma_gross_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ma/tax/income/gross_income/ma_gross_income.yaml @@ -157,3 +157,16 @@ adjusted_gross_income: 50_000 ma_gross_income: 50_000 ma_agi: 50_000 + +- name: Filer military retirement pay and survivor benefits are excluded from MA gross income. + period: 2025 + absolute_error_margin: 0.1 + input: + state_code: MA + employment_income: 50_000 + military_retirement_pay: 20_000 + military_retirement_pay_survivors: 10_000 + output: + adjusted_gross_income: 80_000 + ma_gross_income: 50_000 + ma_agi: 50_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/md/tax/income/agi/md_pension_subtraction_amount.yaml b/policyengine_us/tests/policy/baseline/gov/states/md/tax/income/agi/md_pension_subtraction_amount.yaml index 8a0e83c35fb..8334a56705a 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/md/tax/income/agi/md_pension_subtraction_amount.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/md/tax/income/agi/md_pension_subtraction_amount.yaml @@ -72,3 +72,17 @@ state_code: MD output: md_pension_subtraction_amount: 15_000 + +- name: Disabled filer aged 60 measures excess military pay against age-55 military cap under § 10-209(d)(1) + period: 2024 + input: + state_code: MD + is_tax_unit_dependent: false + age: 60 + is_disabled: true + military_retirement_pay: 40_000 + social_security: 0 + output: + # Military subtraction is $20,000; excess is $20,000 which feeds pension subtraction + md_military_retirement_subtraction_amount: 20_000 + md_pension_subtraction_amount: 20_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/mi/tax/income/deductions/interest_dividends_capital_gains/mi_interest_dividends_capital_gains_deduction.yaml b/policyengine_us/tests/policy/baseline/gov/states/mi/tax/income/deductions/interest_dividends_capital_gains/mi_interest_dividends_capital_gains_deduction.yaml index f2610ec056d..b58c60f5e55 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mi/tax/income/deductions/interest_dividends_capital_gains/mi_interest_dividends_capital_gains_deduction.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mi/tax/income/deductions/interest_dividends_capital_gains/mi_interest_dividends_capital_gains_deduction.yaml @@ -118,3 +118,27 @@ state_code: MI output: # 2025 MI-1040 booklet, Schedule 1 line 28: $14,688 single limit < 50,000 mi_interest_dividends_capital_gains_deduction: 14_688 + +- name: 2022 single filer with interest and dividends deduction reduced by military retirement and survivor pay + period: 2022 + input: + people: + person1: + taxable_pension_income: 10_000 + military_retirement_pay: 500 + military_retirement_pay_survivors: 500 + taxable_interest_income: 5_000 + dividend_income: 400 + capital_gains: 100 + is_tax_unit_head_or_spouse: true + tax_units: + tax_unit: + mi_interest_dividends_capital_gains_deduction_eligible: true + elderly_disabled_credit: 300 + members: [person1] + filing_status: SINGLE + household: + members: [person1] + state_code: MI + output: # 12697 - 10000 - (500 + 500) - 300 = 1397 < 5000 + 400 + 100 + mi_interest_dividends_capital_gains_deduction: 1_397 diff --git a/policyengine_us/tests/policy/baseline/gov/states/mi/tax/income/deductions/retirement/expanded/mi_expanded_retirement_benefits_deduction.yaml b/policyengine_us/tests/policy/baseline/gov/states/mi/tax/income/deductions/retirement/expanded/mi_expanded_retirement_benefits_deduction.yaml index b7ff6a65dba..3839bf0b58a 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mi/tax/income/deductions/retirement/expanded/mi_expanded_retirement_benefits_deduction.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mi/tax/income/deductions/retirement/expanded/mi_expanded_retirement_benefits_deduction.yaml @@ -199,4 +199,21 @@ mi_expanded_retirement_benefits_deduction: 20_000 mi_pension_benefit: 20_000 - +- name: 2023 single filer with expanded retirement deduction reduced by military survivor pay + period: 2023 + input: + people: + person1: + taxable_pension_income: 20_000 + military_retirement_pay_survivors: 1_000 + is_tax_unit_head_or_spouse: true + tax_units: + tax_unit: + mi_expanded_retirement_benefits_deduction_eligible: true + members: [person1] + filing_status: SINGLE + household: + members: [person1] + state_code: MI + output: # min(0.25 * (61518 - 1000), 20000) + mi_expanded_retirement_benefits_deduction: 15_129.5 diff --git a/policyengine_us/tests/policy/baseline/gov/states/mi/tax/income/deductions/retirement/tier_one/mi_retirement_benefits_deduction_tier_one_amount.yaml b/policyengine_us/tests/policy/baseline/gov/states/mi/tax/income/deductions/retirement/tier_one/mi_retirement_benefits_deduction_tier_one_amount.yaml index 3c9cdb576c0..c6e1780f293 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mi/tax/income/deductions/retirement/tier_one/mi_retirement_benefits_deduction_tier_one_amount.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mi/tax/income/deductions/retirement/tier_one/mi_retirement_benefits_deduction_tier_one_amount.yaml @@ -461,4 +461,24 @@ # 401(k) ($15,000) also qualifies -> total $35,000. mi_retirement_benefits_deduction_tier_one_amount: 35_000 - +- name: 2025 single filer with tier 1 cap reduced by military retirement and survivor pay + period: 2025 + input: + people: + person1: + taxable_public_pension_income: 0 + taxable_private_pension_income: 50_000 + military_retirement_pay: 10_000 + military_retirement_pay_survivors: 10_000 + is_tax_unit_head_or_spouse: true + tax_units: + tax_unit: + members: [person1] + filing_status: SINGLE + household: + members: [person1] + state_code: MI + output: + # Cap: $65,897 - ($10,000 + $10,000) = $45,897 + # min($45,897, $50,000) = $45,897 + mi_retirement_benefits_deduction_tier_one_amount: 45_897 diff --git a/policyengine_us/tests/policy/baseline/gov/states/mi/tax/income/deductions/retirement/tier_three/ss_exempt/not_retired/mi_retirement_benefits_deduction_tier_three_ss_exempt_not_retired.yaml b/policyengine_us/tests/policy/baseline/gov/states/mi/tax/income/deductions/retirement/tier_three/ss_exempt/not_retired/mi_retirement_benefits_deduction_tier_three_ss_exempt_not_retired.yaml index e9667c90be4..040f0f15a38 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mi/tax/income/deductions/retirement/tier_three/ss_exempt/not_retired/mi_retirement_benefits_deduction_tier_three_ss_exempt_not_retired.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mi/tax/income/deductions/retirement/tier_three/ss_exempt/not_retired/mi_retirement_benefits_deduction_tier_three_ss_exempt_not_retired.yaml @@ -295,3 +295,25 @@ output: mi_retirement_benefits_deduction_tier_three_eligible: false mi_retirement_benefits_deduction_tier_three_ss_exempt_not_retired: 0 + +- name: 2022 single filer with tier 3 not retired deduction limited to tier 1 due to military survivor pay + period: 2022 + input: + people: + person1: + taxable_pension_income: 40_000 + military_retirement_pay_survivors: 1_000 + is_tax_unit_head_or_spouse: true + tax_units: + tax_unit: + mi_retirement_benefits_deduction_tier_three_eligible: true + mi_retirement_benefits_deduction_tier_three_ss_exempt_not_retired_eligible_people: 1 + mi_retirement_benefits_deduction_tier_one_amount: 10_000 + mi_expanded_retirement_benefits_deduction: 0 + members: [person1] + filing_status: SINGLE + household: + members: [person1] + state_code: MI + output: # min(min(15000, 10000), 40000) = 10000 + mi_retirement_benefits_deduction_tier_three_ss_exempt_not_retired: 10_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/mi/tax/income/deductions/retirement/tier_three/ss_exempt/retired/mi_retirement_benefits_deduction_tier_three_ss_exempt_retired.yaml b/policyengine_us/tests/policy/baseline/gov/states/mi/tax/income/deductions/retirement/tier_three/ss_exempt/retired/mi_retirement_benefits_deduction_tier_three_ss_exempt_retired.yaml index fa8af99ffb7..a4dc58d4a61 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mi/tax/income/deductions/retirement/tier_three/ss_exempt/retired/mi_retirement_benefits_deduction_tier_three_ss_exempt_retired.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mi/tax/income/deductions/retirement/tier_three/ss_exempt/retired/mi_retirement_benefits_deduction_tier_three_ss_exempt_retired.yaml @@ -154,3 +154,24 @@ # The head's own military pay limits the cap: min(70,000, 60,000) = 60,000. # min(20,000 + 30,000, 60,000) = 50,000 mi_retirement_benefits_deduction_tier_three_ss_exempt_retired: 50_000 + +- name: 2022 single filer with tier 3 retired deduction limited to tier 1 due to military survivor pay + period: 2022 + input: + people: + person1: + taxable_pension_income: 40_000 + military_retirement_pay_survivors: 1_000 + is_tax_unit_head_or_spouse: true + tax_units: + tax_unit: + mi_retirement_benefits_deduction_tier_three_eligible: true + mi_retirement_benefits_deduction_tier_three_ss_exempt_retired_eligible_people: 1 + mi_retirement_benefits_deduction_tier_one_amount: 10_000 + members: [person1] + filing_status: SINGLE + household: + members: [person1] + state_code: MI + output: # min(35000 < 10000, 40000) = 10000 + mi_retirement_benefits_deduction_tier_three_ss_exempt_retired: 10_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/mi/tax/income/deductions/standard/tier_three/mi_standard_deduction_tier_three.yaml b/policyengine_us/tests/policy/baseline/gov/states/mi/tax/income/deductions/standard/tier_three/mi_standard_deduction_tier_three.yaml index 5d3d636f0e6..cb513bc35af 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mi/tax/income/deductions/standard/tier_three/mi_standard_deduction_tier_three.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mi/tax/income/deductions/standard/tier_three/mi_standard_deduction_tier_three.yaml @@ -157,3 +157,26 @@ state_code: MI output: mi_standard_deduction_tier_three: 4_790 + +- name: 2022 single filer with tier 3 standard deduction reduced by military retirement and survivor pay + period: 2022 + input: + people: + person1: + military_retirement_pay: 1_000 + military_retirement_pay_survivors: 500 + military_service_income: 500 + taxable_social_security: 100 + is_tax_unit_head_or_spouse: true + tax_units: + tax_unit: + mi_standard_deduction_tier_three_eligible: true + mi_personal_exemptions: 2_000 + mi_expanded_retirement_benefits_deduction: 0 + members: [person1] + filing_status: SINGLE + household: + members: [person1] + state_code: MI + output: # 20000 - (1000 + 500) - (500 > 100) - 2000 = 16000 + mi_standard_deduction_tier_three: 16_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/mi/tax/income/deductions/standard/tier_two/mi_standard_deduction_tier_two.yaml b/policyengine_us/tests/policy/baseline/gov/states/mi/tax/income/deductions/standard/tier_two/mi_standard_deduction_tier_two.yaml index 22b0a71930d..f62ff181535 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mi/tax/income/deductions/standard/tier_two/mi_standard_deduction_tier_two.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mi/tax/income/deductions/standard/tier_two/mi_standard_deduction_tier_two.yaml @@ -68,3 +68,24 @@ state_code: MI output: # 20000 - 9000 - 10000 < 20000 mi_standard_deduction_tier_two: 20_000 + +- name: 2022 single filer with tier 2 standard deduction reduced by military retirement and survivor pay + period: 2022 + input: + people: + person1: + military_retirement_pay: 3_000 + military_retirement_pay_survivors: 2_000 + is_tax_unit_head_or_spouse: true + tax_units: + tax_unit: + mi_standard_deduction_tier_two_eligible: true + mi_standard_deduction_tier_two_increase_eligible_people: 0 + mi_expanded_retirement_benefits_deduction: 0 + members: [person1] + filing_status: SINGLE + household: + members: [person1] + state_code: MI + output: # 20000 - 3000 - 2000 = 15000 + mi_standard_deduction_tier_two: 15_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/mn/tax/income/mn_amt_taxable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/mn/tax/income/mn_amt_taxable_income.yaml index 4310e3a2c90..0b04373bb34 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mn/tax/income/mn_amt_taxable_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mn/tax/income/mn_amt_taxable_income.yaml @@ -45,3 +45,13 @@ state_code: MN output: mn_amt_taxable_income: 200_000 + +- name: MN AMT taxable income subtracts military pension subtraction + period: 2024 + input: + state_code: MN + adjusted_gross_income: 200_000 + military_retirement_pay: 50_000 + output: + mn_military_pension_subtraction: 50_000 + mn_amt_taxable_income: 200_000 - 50_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/mo/tax/income/subtractions/mo_agi_subtractions.yaml b/policyengine_us/tests/policy/baseline/gov/states/mo/tax/income/subtractions/mo_agi_subtractions.yaml index 3eee4f44290..fb6d128b363 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mo/tax/income/subtractions/mo_agi_subtractions.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mo/tax/income/subtractions/mo_agi_subtractions.yaml @@ -174,3 +174,19 @@ mo_qualified_health_insurance_premiums: [6_000, 6_000] # Total subtractions per person: 6_000+6_000=12_000 and 4_000+6_000=10_000 mo_agi_subtractions: [12_000, 10_000] + +- name: Military retirement pay subtracted from MO AGI under MO-A line 10 + period: 2024 + input: + people: + person1: + military_retirement_pay: 30_000 + tax_units: + tax_unit1: + members: [person1] + households: + household1: + members: [person1] + state_code: MO + output: + mo_agi_subtractions: 30_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ne/tax/income/adjusted_gross_income/ne_military_retirement_subtraction.yaml b/policyengine_us/tests/policy/baseline/gov/states/ne/tax/income/adjusted_gross_income/ne_military_retirement_subtraction.yaml index 2c56b418ac8..9e500965817 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ne/tax/income/adjusted_gross_income/ne_military_retirement_subtraction.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ne/tax/income/adjusted_gross_income/ne_military_retirement_subtraction.yaml @@ -162,3 +162,39 @@ # The head is under 67, and the dependent relative is excluded despite # being 67 or older, so only the spouse's 10,000 counts: 40% * 10,000. ne_military_retirement_subtraction: 4_000 + +- name: NE 2021 military retirement survivor benefits are not eligible for subtraction (Form 1040N-MIL) + period: 2021 + input: + people: + person1: + age: 69 + military_retirement_pay_survivors: 20_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: NE + output: + ne_military_retirement_subtraction: 0 + +- name: NE 2022 military retirement survivor benefits are eligible for 100% subtraction (Info Guide 8-364) + period: 2022 + input: + people: + person1: + age: 60 + military_retirement_pay_survivors: 20_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: NE + output: + ne_military_retirement_subtraction: 20_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/tax/income/deductions/plan_529_contributions/nj_529_deduction.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/tax/income/deductions/plan_529_contributions/nj_529_deduction.yaml index 906d537ce4f..e3dabdad557 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nj/tax/income/deductions/plan_529_contributions/nj_529_deduction.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/tax/income/deductions/plan_529_contributions/nj_529_deduction.yaml @@ -39,3 +39,14 @@ employment_income: 100_000 output: nj_529_deduction: 0 + +- name: Case 5, filer with military retirement pay and wages under NJ gross income limit. + period: 2025 + absolute_error_margin: 0.1 + input: + state_code: NJ + employment_income: 185_000 + military_retirement_pay: 30_000 + investment_in_529_plan_indv: 10_000 + output: + nj_529_deduction: 10_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ny/tax/income/ny_agi_subtractions.yaml b/policyengine_us/tests/policy/baseline/gov/states/ny/tax/income/ny_agi_subtractions.yaml index a61d2c71252..6fbcf257f9b 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ny/tax/income/ny_agi_subtractions.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ny/tax/income/ny_agi_subtractions.yaml @@ -67,3 +67,15 @@ output: # 1,000 (head's refund) + 500 (tax-unit U.S. government interest). ny_agi_subtractions: 1_500 + +- name: Military retirement pay and survivor benefits subtracted from NY AGI under § 612(c)(3) + period: 2024 + input: + state_code: NY + employment_income: 50_000 + military_retirement_pay: 20_000 + military_retirement_pay_survivors: 10_000 + output: + adjusted_gross_income: 80_000 + ny_agi_subtractions: 30_000 + ny_agi: 50_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/or/tax/income/credits/retirement_income/or_retirement_credit.yaml b/policyengine_us/tests/policy/baseline/gov/states/or/tax/income/credits/retirement_income/or_retirement_credit.yaml index 2529896a7a5..59d020855c0 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/or/tax/income/credits/retirement_income/or_retirement_credit.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/or/tax/income/credits/retirement_income/or_retirement_credit.yaml @@ -197,3 +197,25 @@ state_code: OR output: or_retirement_credit: 0 + +- name: Military retirement pay and survivor benefits count toward Line 1 retirement income under ORS 316.157 + period: 2022 + input: + people: + person1: + or_retirement_credit_eligible_person: true + military_retirement_pay: 5_000 + military_retirement_pay_survivors: 2_500 + social_security: 0 + tax_units: + tax_unit: + members: [person1] + filing_status: SINGLE + or_retirement_credit_household_income: 10_000 + or_federal_pension_subtraction: 0 + households: + household: + members: [person1] + state_code: OR + output: + or_retirement_credit: 675 diff --git a/policyengine_us/tests/policy/baseline/gov/states/pa/tax/income/forgiveness/pa_eligibility_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/pa/tax/income/forgiveness/pa_eligibility_income.yaml new file mode 100644 index 00000000000..5070c586a99 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/pa/tax/income/forgiveness/pa_eligibility_income.yaml @@ -0,0 +1,17 @@ +- name: Military pension benefits are excluded from PA tax forgiveness eligibility income per PA-40 SP + period: 2025 + input: + state_code: PA + employment_income: 5_000 + military_retirement_pay: 30_000 + output: + pa_eligibility_income: 5_000 + +- name: Military retirement survivor benefits are included in PA tax forgiveness eligibility income per PA-40 SP + period: 2025 + input: + state_code: PA + employment_income: 5_000 + military_retirement_pay_survivors: 10_000 + output: + pa_eligibility_income: 15_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ri/tax/income/agi/subtractions/taxable_retirement_income/ri_retirement_income_subtraction.yaml b/policyengine_us/tests/policy/baseline/gov/states/ri/tax/income/agi/subtractions/taxable_retirement_income/ri_retirement_income_subtraction.yaml index 30e11ab4738..cf0fb9772ce 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ri/tax/income/agi/subtractions/taxable_retirement_income/ri_retirement_income_subtraction.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ri/tax/income/agi/subtractions/taxable_retirement_income/ri_retirement_income_subtraction.yaml @@ -138,3 +138,13 @@ taxable_ira_distributions: 20_000 output: ri_retirement_income_subtraction: 15_000 + +- name: 2022 - Eligible with military retirement pay and survivor pay + period: 2022 + input: + state_code: RI + ri_retirement_income_subtraction_eligible: true + military_retirement_pay: 10_000 + military_retirement_pay_survivors: 5_000 + output: + ri_retirement_income_subtraction: 15_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/vt/tax/income/agi/subtractions/vt_military_retirement_pay_exclusion.yaml b/policyengine_us/tests/policy/baseline/gov/states/vt/tax/income/agi/subtractions/vt_military_retirement_pay_exclusion.yaml index 21ce4ae0fa9..de17eece6d1 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/vt/tax/income/agi/subtractions/vt_military_retirement_pay_exclusion.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/vt/tax/income/agi/subtractions/vt_military_retirement_pay_exclusion.yaml @@ -193,3 +193,42 @@ # Federal AGI 50,000 is below the 125,000 full-exemption threshold, so the # head's 6,000 is fully exempt; the child's 10,000 is not counted. vt_military_retirement_pay_exclusion: 6_000 + +- name: VT 2024 military retirement survivor benefits are not eligible for exclusion under pre-2025 law + period: 2024 + input: + people: + person1: + age: 50 + military_retirement_pay_survivors: 10_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + filing_status: SINGLE + households: + household: + members: [person1] + state_code: VT + output: + vt_military_retirement_pay_exclusion: 0 + +- name: VT 2025 military retirement survivor benefits are eligible for exclusion under Act 71 (S.51) + period: 2025 + input: + people: + person1: + age: 50 + employment_income: 30_000 + military_retirement_pay_survivors: 10_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + filing_status: SINGLE + households: + household: + members: [person1] + state_code: VT + output: + vt_military_retirement_pay_exclusion: 10_000 diff --git a/policyengine_us/variables/gov/states/ca/tax/income/ca_military_retirement_exclusion.py b/policyengine_us/variables/gov/states/ca/tax/income/ca_military_retirement_exclusion.py index f0c612687c2..bd182663468 100644 --- a/policyengine_us/variables/gov/states/ca/tax/income/ca_military_retirement_exclusion.py +++ b/policyengine_us/variables/gov/states/ca/tax/income/ca_military_retirement_exclusion.py @@ -22,11 +22,16 @@ def formula(tax_unit, period, parameters): person = tax_unit.members head_or_spouse = person("is_tax_unit_head_or_spouse", period) - # R&TC § 17132.9 excludes up to $20,000 of retired pay. - # R&TC § 17132.10 excludes up to $20,000 of SBP survivor benefits. - capped_retiree = min_(p.cap, person("military_retirement_pay", period)) - capped_survivors = min_( - p.cap, person("military_retirement_pay_survivors", period) + # R&TC § 17132.9 excludes up to $20,000 of retired pay per return. + # R&TC § 17132.10 excludes up to $20,000 of SBP survivor benefits per return. + # The exclusion is capped at $20,000 for each payment category on a joint return, + # surviving spouse, or any other individual (Schedule CA (540) line 5a/5b). + retiree_pay = tax_unit.sum( + person("military_retirement_pay", period) * head_or_spouse ) - total_person = (capped_retiree + capped_survivors) * head_or_spouse - return eligible * tax_unit.sum(total_person) + survivor_pay = tax_unit.sum( + person("military_retirement_pay_survivors", period) * head_or_spouse + ) + capped_retiree = min_(p.cap, retiree_pay) + capped_survivors = min_(p.cap, survivor_pay) + return eligible * (capped_retiree + capped_survivors) diff --git a/policyengine_us/variables/gov/states/de/tax/income/subtractions/pension_exclusion/de_pension_exclusion.py b/policyengine_us/variables/gov/states/de/tax/income/subtractions/pension_exclusion/de_pension_exclusion.py index 205a7a9709e..a1d22553862 100644 --- a/policyengine_us/variables/gov/states/de/tax/income/subtractions/pension_exclusion/de_pension_exclusion.py +++ b/policyengine_us/variables/gov/states/de/tax/income/subtractions/pension_exclusion/de_pension_exclusion.py @@ -26,8 +26,7 @@ def formula(person, period, parameters): eligible_pension_income = ( person("taxable_pension_income", period) - + person("military_retirement_pay", period) - + person("military_retirement_pay_survivors", period) + + person("military_retirement_income", period) ) * head_or_spouse eligible_retirement_income = ( diff --git a/policyengine_us/variables/gov/states/id/tax/income/subtractions/military_retirement/id_military_retirement_deduction.py b/policyengine_us/variables/gov/states/id/tax/income/subtractions/military_retirement/id_military_retirement_deduction.py index abaecd358a8..adeff6fc322 100644 --- a/policyengine_us/variables/gov/states/id/tax/income/subtractions/military_retirement/id_military_retirement_deduction.py +++ b/policyengine_us/variables/gov/states/id/tax/income/subtractions/military_retirement/id_military_retirement_deduction.py @@ -17,11 +17,7 @@ def formula(tax_unit, period, parameters): p = parameters(period).gov.states.id.tax.income.subtractions.military_retirement person = tax_unit.members head_or_spouse = person("is_tax_unit_head_or_spouse", period) - military_retirement_pay = add( - person, - period, - ["military_retirement_pay", "military_retirement_pay_survivors"], - ) + military_retirement_pay = person("military_retirement_income", period) eligible_military_pay = military_retirement_pay * head_or_spouse # Multiply by applies parameter (False when military retirement # is already handled in general retirement benefits deduction) diff --git a/policyengine_us/variables/gov/states/in/tax/income/deductions/in_military_retirement_deduction.py b/policyengine_us/variables/gov/states/in/tax/income/deductions/in_military_retirement_deduction.py index 5cb35d27d3b..c2f10bb42c1 100644 --- a/policyengine_us/variables/gov/states/in/tax/income/deductions/in_military_retirement_deduction.py +++ b/policyengine_us/variables/gov/states/in/tax/income/deductions/in_military_retirement_deduction.py @@ -23,12 +23,7 @@ def formula(tax_unit, period, parameters): # Dependents' income is not in federal AGI; they report it on their # own return. head_or_spouse = person("is_tax_unit_head_or_spouse", period) - military_retirement = ( - person("military_retirement_pay", period) - + person("military_retirement_pay_survivors", period) - ) * head_or_spouse + military_retirement = person("military_retirement_income", period) excess = max_(0, military_retirement - p.base) - person_deduction = ( - min_(military_retirement, p.base) + p.excess_rate * excess - ) * head_or_spouse - return tax_unit.sum(person_deduction) + person_deduction = min_(military_retirement, p.base) + p.excess_rate * excess + return tax_unit.sum(person_deduction * head_or_spouse) diff --git a/policyengine_us/variables/gov/states/ks/tax/income/ks_agi_subtractions.py b/policyengine_us/variables/gov/states/ks/tax/income/ks_agi_subtractions.py index 0e623486d57..07a261b9c49 100644 --- a/policyengine_us/variables/gov/states/ks/tax/income/ks_agi_subtractions.py +++ b/policyengine_us/variables/gov/states/ks/tax/income/ks_agi_subtractions.py @@ -36,8 +36,7 @@ def formula(tax_unit, period, parameters): period, [ "taxable_public_pension_income", - "military_retirement_pay", - "military_retirement_pay_survivors", + "military_retirement_income", ], ) return ( diff --git a/policyengine_us/variables/gov/states/ky/tax/income/exclusions/pension_income/ky_pension_income_exclusion.py b/policyengine_us/variables/gov/states/ky/tax/income/exclusions/pension_income/ky_pension_income_exclusion.py index 34a738def77..225e9aa1469 100644 --- a/policyengine_us/variables/gov/states/ky/tax/income/exclusions/pension_income/ky_pension_income_exclusion.py +++ b/policyengine_us/variables/gov/states/ky/tax/income/exclusions/pension_income/ky_pension_income_exclusion.py @@ -18,8 +18,7 @@ def formula(person, period, parameters): period, [ "taxable_pension_income", - "military_retirement_pay", - "military_retirement_pay_survivors", + "military_retirement_income", ], ) diff --git a/policyengine_us/variables/gov/states/ma/tax/income/gross_income/ma_gross_income.py b/policyengine_us/variables/gov/states/ma/tax/income/gross_income/ma_gross_income.py index 4aa9125de0e..b51ee14128a 100644 --- a/policyengine_us/variables/gov/states/ma/tax/income/gross_income/ma_gross_income.py +++ b/policyengine_us/variables/gov/states/ma/tax/income/gross_income/ma_gross_income.py @@ -48,8 +48,7 @@ def formula(tax_unit, period, parameters): period, [ "taxable_public_pension_income", - "military_retirement_pay", - "military_retirement_pay_survivors", + "military_retirement_income", ], ) deductions = social_security_in_agi + salt_refund_income + public_pension diff --git a/policyengine_us/variables/gov/states/md/tax/income/agi/subtractions/md_military_retirement_subtraction.py b/policyengine_us/variables/gov/states/md/tax/income/agi/subtractions/md_military_retirement_subtraction.py index a7973d16495..3bf4527f886 100644 --- a/policyengine_us/variables/gov/states/md/tax/income/agi/subtractions/md_military_retirement_subtraction.py +++ b/policyengine_us/variables/gov/states/md/tax/income/agi/subtractions/md_military_retirement_subtraction.py @@ -18,28 +18,10 @@ class md_military_retirement_subtraction(Variable): ) def formula(tax_unit, period, parameters): - # Md. Code Tax-General § 10-207(q)(1): "military retirement income" - # includes death benefits received as a result of military service, so - # Survivor Benefit Plan payments to surviving spouses qualify. - p = parameters( - period - ).gov.states.md.tax.income.agi.subtractions.military_retirement person = tax_unit.members - age = person("age", period) - military_retirement_income = add( - person, - period, - ["military_retirement_pay", "military_retirement_pay_survivors"], - ) - at_or_above_threshold = age >= p.age_threshold - cap = where( - at_or_above_threshold, - p.max_amount.at_or_above_age_threshold, - p.max_amount.under_age_threshold, - ) - capped = min_(military_retirement_income, cap) # § 10-207(a) subtracts amounts only to the extent included in federal # AGI. Dependents' income is not in federal AGI; they report it on # their own return (Form 502 filing status 6, dependent taxpayer). head_or_spouse = person("is_tax_unit_head_or_spouse", period) - return tax_unit.sum(capped * head_or_spouse) + person_subtraction = person("md_military_retirement_subtraction_amount", period) + return tax_unit.sum(person_subtraction * head_or_spouse) diff --git a/policyengine_us/variables/gov/states/md/tax/income/agi/subtractions/md_military_retirement_subtraction_amount.py b/policyengine_us/variables/gov/states/md/tax/income/agi/subtractions/md_military_retirement_subtraction_amount.py new file mode 100644 index 00000000000..ef068373b81 --- /dev/null +++ b/policyengine_us/variables/gov/states/md/tax/income/agi/subtractions/md_military_retirement_subtraction_amount.py @@ -0,0 +1,31 @@ +from policyengine_us.model_api import * + + +class md_military_retirement_subtraction_amount(Variable): + value_type = float + entity = Person + label = "Maryland military retirement income subtraction per person" + unit = USD + definition_period = YEAR + defined_for = StateCode.MD + reference = ( + "https://mgaleg.maryland.gov/mgawebsite/Laws/StatuteText?article=gtg§ion=10-207", + "https://www.marylandcomptroller.gov/content/dam/mdcomp/tax/instructions/2025/resident-booklet.pdf#page=17", + ) + + def formula(person, period, parameters): + # Md. Code Tax-General § 10-207(q)(1): "military retirement income" + # includes death benefits received as a result of military service, so + # Survivor Benefit Plan payments to surviving spouses qualify. + p = parameters( + period + ).gov.states.md.tax.income.agi.subtractions.military_retirement + age = person("age", period) + military_retirement_income = person("military_retirement_income", period) + at_or_above_threshold = age >= p.age_threshold + cap = where( + at_or_above_threshold, + p.max_amount.at_or_above_age_threshold, + p.max_amount.under_age_threshold, + ) + return min_(military_retirement_income, cap) diff --git a/policyengine_us/variables/gov/states/md/tax/income/agi/subtractions/md_pension_subtraction_amount.py b/policyengine_us/variables/gov/states/md/tax/income/agi/subtractions/md_pension_subtraction_amount.py index 669cbf6550a..07795b5966a 100644 --- a/policyengine_us/variables/gov/states/md/tax/income/agi/subtractions/md_pension_subtraction_amount.py +++ b/policyengine_us/variables/gov/states/md/tax/income/agi/subtractions/md_pension_subtraction_amount.py @@ -23,16 +23,11 @@ def formula(person, period, parameters): # (Worksheet 13A, line 1), military retirement income exceeding the # § 10-207(q) military retirement subtraction qualifies for the # general pension exclusion. - p_mil = p.military_retirement - military_income = person("military_retirement_pay", period) + person( - "military_retirement_pay_survivors", period + military_income = person("military_retirement_income", period) + military_subtraction = person( + "md_military_retirement_subtraction_amount", period ) - mil_cap = where( - elderly, - p_mil.max_amount.at_or_above_age_threshold, - p_mil.max_amount.under_age_threshold, - ) - excess_military = max_(0, military_income - mil_cap) + excess_military = max_(0, military_income - military_subtraction) # calculate pension subtraction amount for each person peninc = add(person, period, p.pension.sources) + excess_military diff --git a/policyengine_us/variables/gov/states/me/tax/income/adjusted_gross_income/me_pension_income_deduction.py b/policyengine_us/variables/gov/states/me/tax/income/adjusted_gross_income/me_pension_income_deduction.py index bf0348d0a27..045b49f6391 100644 --- a/policyengine_us/variables/gov/states/me/tax/income/adjusted_gross_income/me_pension_income_deduction.py +++ b/policyengine_us/variables/gov/states/me/tax/income/adjusted_gross_income/me_pension_income_deduction.py @@ -37,9 +37,7 @@ def formula(tax_unit, period, parameters): ss_reduced_cap = max_(p.cap - gross_ss, 0) non_military_deduction = min_(pension_income, ss_reduced_cap) - military_retirement = person("military_retirement_pay", period) + person( - "military_retirement_pay_survivors", period - ) + military_retirement = person("military_retirement_income", period) # Restrict to the head (and spouse if filing jointly) per Schedule 1S # line 4. diff --git a/policyengine_us/variables/gov/states/mi/tax/income/deductions/interest_dividends_capital_gains/mi_interest_dividends_capital_gains_deduction.py b/policyengine_us/variables/gov/states/mi/tax/income/deductions/interest_dividends_capital_gains/mi_interest_dividends_capital_gains_deduction.py index ea9bf5183c3..298e32bf081 100644 --- a/policyengine_us/variables/gov/states/mi/tax/income/deductions/interest_dividends_capital_gains/mi_interest_dividends_capital_gains_deduction.py +++ b/policyengine_us/variables/gov/states/mi/tax/income/deductions/interest_dividends_capital_gains/mi_interest_dividends_capital_gains_deduction.py @@ -35,8 +35,7 @@ def formula(tax_unit, period, parameters): person, period, [ - "military_retirement_pay", - "military_retirement_pay_survivors", + "military_retirement_income", "taxable_pension_income", ], ) diff --git a/policyengine_us/variables/gov/states/mi/tax/income/deductions/retirement/expanded/mi_expanded_retirement_benefits_deduction.py b/policyengine_us/variables/gov/states/mi/tax/income/deductions/retirement/expanded/mi_expanded_retirement_benefits_deduction.py index 55d34385b5a..ad383d90463 100644 --- a/policyengine_us/variables/gov/states/mi/tax/income/deductions/retirement/expanded/mi_expanded_retirement_benefits_deduction.py +++ b/policyengine_us/variables/gov/states/mi/tax/income/deductions/retirement/expanded/mi_expanded_retirement_benefits_deduction.py @@ -54,9 +54,8 @@ def formula(tax_unit, period, parameters): # Line 1 tier_one_cap = p.tier_one.amount[filing_status] head_or_spouse_military_retirement_pay = ( - person("military_retirement_pay", period) - + person("military_retirement_pay_survivors", period) - ) * is_head_or_spouse + person("military_retirement_income", period) * is_head_or_spouse + ) # Line 2 total_military_retirement_pay = tax_unit.sum( head_or_spouse_military_retirement_pay diff --git a/policyengine_us/variables/gov/states/mi/tax/income/deductions/retirement/tier_one/mi_retirement_benefits_deduction_tier_one_amount.py b/policyengine_us/variables/gov/states/mi/tax/income/deductions/retirement/tier_one/mi_retirement_benefits_deduction_tier_one_amount.py index 1a80ed57e9d..e38dd186796 100644 --- a/policyengine_us/variables/gov/states/mi/tax/income/deductions/retirement/tier_one/mi_retirement_benefits_deduction_tier_one_amount.py +++ b/policyengine_us/variables/gov/states/mi/tax/income/deductions/retirement/tier_one/mi_retirement_benefits_deduction_tier_one_amount.py @@ -32,9 +32,8 @@ def formula(tax_unit, period, parameters): # Line 10 is_head_or_spouse = person("is_tax_unit_head_or_spouse", period) military_retirement_pay = ( - person("military_retirement_pay", period) - + person("military_retirement_pay_survivors", period) - ) * is_head_or_spouse + person("military_retirement_income", period) * is_head_or_spouse + ) total_military_retirement_pay = tax_unit.sum(military_retirement_pay) # the cap is reduced by the amount of military retirement pay diff --git a/policyengine_us/variables/gov/states/mi/tax/income/deductions/retirement/tier_three/ss_exempt/not_retired/mi_retirement_benefits_deduction_tier_three_ss_exempt_not_retired.py b/policyengine_us/variables/gov/states/mi/tax/income/deductions/retirement/tier_three/ss_exempt/not_retired/mi_retirement_benefits_deduction_tier_three_ss_exempt_not_retired.py index 5e5e5a75ba9..cc10c4d90e7 100644 --- a/policyengine_us/variables/gov/states/mi/tax/income/deductions/retirement/tier_three/ss_exempt/not_retired/mi_retirement_benefits_deduction_tier_three_ss_exempt_not_retired.py +++ b/policyengine_us/variables/gov/states/mi/tax/income/deductions/retirement/tier_three/ss_exempt/not_retired/mi_retirement_benefits_deduction_tier_three_ss_exempt_not_retired.py @@ -63,10 +63,7 @@ def formula(tax_unit, period, parameters): # the tier one or tier three deduction amount # Worksheet 3.2 counts only military retirement pay on the filer's Schedule 1, line 11, # which excludes a dependent's pay (not in the filer's AGI). - military_pay = ( - person("military_retirement_pay", period) - + person("military_retirement_pay_survivors", period) - ) * is_head_or_spouse + military_pay = person("military_retirement_income", period) * is_head_or_spouse military_retirement_pay_received = tax_unit.sum(military_pay) > 0 # Line 8 tier_one_amount = tax_unit( diff --git a/policyengine_us/variables/gov/states/mi/tax/income/deductions/retirement/tier_three/ss_exempt/retired/mi_retirement_benefits_deduction_tier_three_ss_exempt_retired.py b/policyengine_us/variables/gov/states/mi/tax/income/deductions/retirement/tier_three/ss_exempt/retired/mi_retirement_benefits_deduction_tier_three_ss_exempt_retired.py index 3cd71e63089..721fe145a53 100644 --- a/policyengine_us/variables/gov/states/mi/tax/income/deductions/retirement/tier_three/ss_exempt/retired/mi_retirement_benefits_deduction_tier_three_ss_exempt_retired.py +++ b/policyengine_us/variables/gov/states/mi/tax/income/deductions/retirement/tier_three/ss_exempt/retired/mi_retirement_benefits_deduction_tier_three_ss_exempt_retired.py @@ -78,10 +78,7 @@ def formula(tax_unit, period, parameters): # the tier one or tier three deduction amount # Worksheet 3.1 counts only military retirement pay on the filer's Schedule 1, line 11, # which excludes a dependent's pay (not in the filer's AGI). - military_pay = ( - person("military_retirement_pay", period) - + person("military_retirement_pay_survivors", period) - ) * is_head_or_spouse + military_pay = person("military_retirement_income", period) * is_head_or_spouse military_retirement_pay_eligible = tax_unit.sum(military_pay) > 0 # Line 8 tier_one_amount = tax_unit( diff --git a/policyengine_us/variables/gov/states/mi/tax/income/deductions/standard/tier_three/mi_standard_deduction_tier_three.py b/policyengine_us/variables/gov/states/mi/tax/income/deductions/standard/tier_three/mi_standard_deduction_tier_three.py index 4c9d4c492ff..92b51903250 100644 --- a/policyengine_us/variables/gov/states/mi/tax/income/deductions/standard/tier_three/mi_standard_deduction_tier_three.py +++ b/policyengine_us/variables/gov/states/mi/tax/income/deductions/standard/tier_three/mi_standard_deduction_tier_three.py @@ -31,9 +31,7 @@ def formula(tax_unit, period, parameters): person = tax_unit.members is_head_or_spouse = person("is_tax_unit_head_or_spouse", period) # Line 2: enter military retirement pay and survivor benefits - military_retirement_pay = person("military_retirement_pay", period) + person( - "military_retirement_pay_survivors", period - ) + military_retirement_pay = person("military_retirement_income", period) # Line 3: enter military service income or taxable social security taxable_ss = person("taxable_social_security", period) military_service_income = person("military_service_income", period) diff --git a/policyengine_us/variables/gov/states/mi/tax/income/deductions/standard/tier_two/mi_standard_deduction_tier_two.py b/policyengine_us/variables/gov/states/mi/tax/income/deductions/standard/tier_two/mi_standard_deduction_tier_two.py index 3b283f28118..d97feba92af 100644 --- a/policyengine_us/variables/gov/states/mi/tax/income/deductions/standard/tier_two/mi_standard_deduction_tier_two.py +++ b/policyengine_us/variables/gov/states/mi/tax/income/deductions/standard/tier_two/mi_standard_deduction_tier_two.py @@ -33,8 +33,7 @@ def formula(tax_unit, period, parameters): person, period, [ - "military_retirement_pay", - "military_retirement_pay_survivors", + "military_retirement_income", "military_service_income", ], ) diff --git a/policyengine_us/variables/gov/states/nc/tax/income/deductions/military_retirement/nc_military_retirement_deduction.py b/policyengine_us/variables/gov/states/nc/tax/income/deductions/military_retirement/nc_military_retirement_deduction.py index ad0d6c43f21..66c2d43b422 100644 --- a/policyengine_us/variables/gov/states/nc/tax/income/deductions/military_retirement/nc_military_retirement_deduction.py +++ b/policyengine_us/variables/gov/states/nc/tax/income/deductions/military_retirement/nc_military_retirement_deduction.py @@ -38,9 +38,8 @@ def formula(tax_unit, period, parameters): # eligibility, which needs the recipient's service or medical record. own_pay_eligible = eligible & (~survivor | own_record_eligible) military_pay_eligible = where(survivor_pay > 0, own_pay_eligible, eligible) - # With no separate survivor amount, military_retirement_pay can instead - # contain only survivor benefits, as its documentation permits. Mixed - # own and survivor pay must be split between the two income inputs. + # When survivor_pay is 0, eligible applies to military_retirement_pay directly. + # Mixed own and survivor pay must be split between the two income inputs. qualifying_pay = ( person("military_retirement_pay", period) * military_pay_eligible + survivor_pay * survivor * eligible diff --git a/policyengine_us/variables/gov/states/nc/tax/income/deductions/military_retirement/nc_military_retirement_survivor_eligible.py b/policyengine_us/variables/gov/states/nc/tax/income/deductions/military_retirement/nc_military_retirement_survivor_eligible.py index 792a626fd62..3b5fe602f4b 100644 --- a/policyengine_us/variables/gov/states/nc/tax/income/deductions/military_retirement/nc_military_retirement_survivor_eligible.py +++ b/policyengine_us/variables/gov/states/nc/tax/income/deductions/military_retirement/nc_military_retirement_survivor_eligible.py @@ -18,9 +18,6 @@ class nc_military_retirement_survivor_eligible(Variable): "In that case, supply the recipient's years_in_military or " "is_permanently_disabled_veteran record: setting the combined " "nc_military_retirement_deduction_eligible input to true alone " - "does not establish eligibility for their own pay. " - "If military_retirement_pay_survivors is zero, this flag also allows " - "military_retirement_pay to contain qualifying survivor benefits. " "Do not record the same survivor benefits in both income inputs." ) definition_period = YEAR diff --git a/policyengine_us/variables/gov/states/ne/tax/income/adjusted_gross_income/subtractions/ne_military_retirement_subtraction.py b/policyengine_us/variables/gov/states/ne/tax/income/adjusted_gross_income/subtractions/ne_military_retirement_subtraction.py index e3094e42160..803b453e703 100644 --- a/policyengine_us/variables/gov/states/ne/tax/income/adjusted_gross_income/subtractions/ne_military_retirement_subtraction.py +++ b/policyengine_us/variables/gov/states/ne/tax/income/adjusted_gross_income/subtractions/ne_military_retirement_subtraction.py @@ -24,10 +24,9 @@ def formula(tax_unit, period, parameters): age = person("age", period) age_eligible = age >= p.age_threshold military_retirement_pay = person("military_retirement_pay", period) - if p.survivors_eligible: - survivor_pay = person("military_retirement_pay_survivors", period) - else: - survivor_pay = 0 + survivor_pay = ( + person("military_retirement_pay_survivors", period) * p.survivors_eligible + ) military_retirement_benefit = military_retirement_pay + survivor_pay # Dependents' income is not in federal AGI; they report it on their # own return. diff --git a/policyengine_us/variables/gov/states/nj/tax/income/deductions/plan_529_contributions/nj_529_deduction.py b/policyengine_us/variables/gov/states/nj/tax/income/deductions/plan_529_contributions/nj_529_deduction.py index d44aa2d8bf4..fd069a104ba 100644 --- a/policyengine_us/variables/gov/states/nj/tax/income/deductions/plan_529_contributions/nj_529_deduction.py +++ b/policyengine_us/variables/gov/states/nj/tax/income/deductions/plan_529_contributions/nj_529_deduction.py @@ -17,9 +17,9 @@ def formula(person, period, parameters): p = parameters( period ).gov.states.nj.tax.income.deductions.plan_529_contributions - # Check AGI income limit - agi = person.tax_unit("adjusted_gross_income", period) - income_eligible = agi <= p.income_limit + # Check NJ gross income limit (NJ-1040 line 29) + nj_gross_income = person.tax_unit("nj_agi", period) + income_eligible = nj_gross_income <= p.income_limit # Get the TaxUnit-level deduction cap total_contributions = person.tax_unit("investment_in_529_plan", period) unit_deduction = min_(total_contributions, p.cap) diff --git a/policyengine_us/variables/gov/states/oh/tax/income/deductions/oh_uniformed_services_retirement_income_deduction.py b/policyengine_us/variables/gov/states/oh/tax/income/deductions/oh_uniformed_services_retirement_income_deduction.py index 8f9f83f85ec..d9a25bffb4d 100644 --- a/policyengine_us/variables/gov/states/oh/tax/income/deductions/oh_uniformed_services_retirement_income_deduction.py +++ b/policyengine_us/variables/gov/states/oh/tax/income/deductions/oh_uniformed_services_retirement_income_deduction.py @@ -15,7 +15,5 @@ class oh_uniformed_services_retirement_income_deduction(Variable): def formula(person, period, parameters): is_head_or_spouse = person("is_tax_unit_head_or_spouse", period) - military_retirement = person("military_retirement_pay", period) + person( - "military_retirement_pay_survivors", period - ) + military_retirement = person("military_retirement_income", period) return is_head_or_spouse * military_retirement diff --git a/policyengine_us/variables/gov/states/or/tax/income/credits/retirement_credit/or_retirement_credit.py b/policyengine_us/variables/gov/states/or/tax/income/credits/retirement_credit/or_retirement_credit.py index e95f20765ad..deac860a046 100644 --- a/policyengine_us/variables/gov/states/or/tax/income/credits/retirement_credit/or_retirement_credit.py +++ b/policyengine_us/variables/gov/states/or/tax/income/credits/retirement_credit/or_retirement_credit.py @@ -16,10 +16,8 @@ def formula(tax_unit, period, parameters): # Line 1, retirement income person = tax_unit.members eligible = person("or_retirement_credit_eligible_person", period) - pension = ( - person("taxable_pension_income", period) - + person("military_retirement_pay", period) - + person("military_retirement_pay_survivors", period) + pension = person("taxable_pension_income", period) + person( + "military_retirement_income", period ) retirement_income = eligible * pension total_retirement_income = tax_unit.sum(retirement_income) diff --git a/policyengine_us/variables/household/income/person/general/market_income.py b/policyengine_us/variables/household/income/person/general/market_income.py index 391afa7e4ad..6447143a423 100644 --- a/policyengine_us/variables/household/income/person/general/market_income.py +++ b/policyengine_us/variables/household/income/person/general/market_income.py @@ -27,7 +27,6 @@ def formula(person, period, parameters): "alimony_income", "strike_benefits", "retirement_distributions", - "military_retirement_pay", - "military_retirement_pay_survivors", + "military_retirement_income", ] return add(person, period, COMPONENTS) diff --git a/policyengine_us/variables/household/income/person/retirement/military_retirement_income.py b/policyengine_us/variables/household/income/person/retirement/military_retirement_income.py new file mode 100644 index 00000000000..76e850d4ddb --- /dev/null +++ b/policyengine_us/variables/household/income/person/retirement/military_retirement_income.py @@ -0,0 +1,18 @@ +from policyengine_us.model_api import * + + +class military_retirement_income(Variable): + value_type = float + entity = Person + label = "Military retirement income" + unit = USD + definition_period = YEAR + documentation = ( + "Total military retirement income, combining military retirement pay " + "and military retirement survivor benefit payments." + ) + reference = ( + "https://militarypay.defense.gov/Pay/Retirement/", + "https://www.irs.gov/pub/irs-prior/p525--2024.pdf#page=16", + ) + adds = ["military_retirement_pay", "military_retirement_pay_survivors"] diff --git a/policyengine_us/variables/household/income/person/retirement/military_retirement_pay.py b/policyengine_us/variables/household/income/person/retirement/military_retirement_pay.py index 129edfae26f..8a9a5539c9e 100644 --- a/policyengine_us/variables/household/income/person/retirement/military_retirement_pay.py +++ b/policyengine_us/variables/household/income/person/retirement/military_retirement_pay.py @@ -8,11 +8,21 @@ class military_retirement_pay(Variable): unit = USD definition_period = YEAR documentation = ( - "Retirement pay received by former members of the uniformed services " - "of the United States. Included in federal gross income under 26 U.S.C. § 61(a)(10)." + "Taxable retirement pay received by former members of the uniformed services " + "of the United States, meaning after the Survivor Benefit Plan (SBP) premium reduction, " + "and excluding Combat-Related Special Compensation (CRSC) and disability retirement pay " + "excludable under 26 U.S.C. § 104 (see IRS Pub 525 (2024), p. 16). Excludable amounts " + "such as CRSC and VA Dependency and Indemnity Compensation (DIC) should be reported " + "under veterans_benefits. Included in federal gross income under 26 U.S.C. § 61(a)(10).\n\n" + "Known limitations:\n" + "- Montana (MCA 15-30-2120(3)(n)): allows a deduction of up to 50% of military retired pay " + "(capped at Montana earned income) starting in 2024; this deduction is not yet modeled.\n" + "- North Carolina (N.C. Gen. Stat. § 105-153.5(b)(5a)): deduction requires either 20 years of military " + "service or medical retirement; entering military_retirement_pay alone without service record " + "variables (years_in_military or is_permanently_disabled_veteran) defaults to no deduction." ) reference = ( "https://militarypay.defense.gov/Pay/Retirement/", - "https://www.irs.gov/publications/p525", + "https://www.irs.gov/pub/irs-prior/p525--2024.pdf#page=16", ) uprating = "calibration.gov.irs.soi.taxable_pension_income" diff --git a/policyengine_us/variables/household/income/person/retirement/military_retirement_pay_survivors.py b/policyengine_us/variables/household/income/person/retirement/military_retirement_pay_survivors.py index 0ce9e3bc6e4..fa69f8c92c6 100644 --- a/policyengine_us/variables/household/income/person/retirement/military_retirement_pay_survivors.py +++ b/policyengine_us/variables/household/income/person/retirement/military_retirement_pay_survivors.py @@ -4,18 +4,26 @@ class military_retirement_pay_survivors(Variable): value_type = float entity = Person - label = "Military retirement income paid to surviving spouses" + label = "Military retirement survivor benefit payments" unit = USD definition_period = YEAR documentation = ( - "Survivor annuity payments received by surviving spouses or other designated " - "beneficiaries under a United States uniformed services retirement plan (such as " - "the Survivor Benefit Plan or Retired Serviceman's Family Protection Plan). " - "Included in federal gross income under 26 U.S.C. § 61(a)(10) and § 72." + "Taxable survivor annuity payments received by surviving spouses, dependent children, " + "or other designated annuitants under a United States uniformed services retirement plan " + "(such as the Survivor Benefit Plan (SBP) or Retired Serviceman's Family Protection Plan). " + "Excludes tax-exempt payments such as VA Dependency and Indemnity Compensation (DIC), " + "which should be reported under veterans_benefits (see IRS Pub 525 (2024), p. 16). " + "Included in federal gross income under 26 U.S.C. § 61(a)(10) and § 72.\n\n" + "Known limitations:\n" + "- Montana (MCA 15-30-2120(3)(n)): allows a deduction of up to 50% of military survivor benefits " + "(capped at Montana earned income) starting in 2024; this deduction is not yet modeled.\n" + "- North Carolina (N.C. Gen. Stat. § 105-153.5(b)(5a)): deduction requires either 20 years of military " + "service or medical retirement; entering military_retirement_pay_survivors alone without survivor " + "eligibility variables (nc_military_retirement_survivor_eligible) defaults to no deduction." ) reference = ( "https://militarypay.defense.gov/Benefits/Survivor-Benefit-Program/", - "https://www.irs.gov/publications/p525", + "https://www.irs.gov/pub/irs-prior/p525--2024.pdf#page=16", "https://www.irs.gov/publications/p575", ) uprating = "calibration.gov.irs.soi.taxable_pension_income"