PolicyEngine / PolicyEngine/policyengine-us

VT: 2025 Act 71 lets the military retirement exclusion stack with the §5830e(a)-(c) election; model still forces a single max_() choice

Open
#9,146 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
162
Forks
212
Avg merge
3d 3h
Merged PRs (30d)
97

Description

Found while verifying #9136 against the enacted text of 2025 Act No. 71 (S.51). Related: #9069, #9020, #9021, #8853.

## Problem

Act 71 (2025), Sec. 3 didn't just give U.S. military retirement/survivor income its own AGI thresholds in 32 V.S.A. § 5830e(d) — it also **removed the military exclusion from the elect-one-exclusion rule**. Subsection (e) as amended (verified against the enrolled act and the current Vermont Statutes Online codification, "amended … 2025, No. 71, § 3, eff. January 1, 2025"):

> (e)(1) Requirement to elect one exclusion. A taxpayer of this State who is eligible during the taxable year for more than one of the exclusions under subsections **(a), (b), and (c)** of this section shall elect only one of the exclusions for which the taxpayer is eligible.
> (2) A taxpayer of this State who is eligible during the taxable year for the military retirement and survivor benefit exclusion under subsection (d) of this section **may elect that exclusion regardless of whether the taxpayer also elects an exclusion under subsections (a)–(c)** of this section.

The old language routing military through the (b) CSRS regime and the (e) election ("pursuant to subsection (b) … and shall be subject to the limitations under subsection (e)") was struck by the act.

But `vt_retirement_income_exemption` (and the mirrored logic in `vt_retirement_income_exemption_eligible`) still models a single election across all three:

```python
chosen_retirement_income = max_(
max_(tax_unit_taxable_social_security, vt_military_retirement_pay_exclusion),
vt_csrs_retirement_pay_exclusion,
)
```

## Effect (2025+)

A filer with **both** military retirement income and taxable Social Security (or CSRS/other-contributory pension income) is under-computed: the statute allows the (d) military exclusion **plus** one elected exclusion among (a)–(c); the model grants only `max_()` of them. Direction: model overtaxes affected filers. (#9136 fixed the severe single-source defects — double-phasing and the CSRS-end zeroing — but deliberately kept the election structure.)

## Suggested direction

For `military_retirement.income_based_structure.in_effect` years:
- `vt_retirement_income_exemption` = `vt_military_retirement_income_based_exemption` (self-phased on the $125k/$175k band) **+** the elected-one exclusion among (a) Social Security, (b) CSRS, (c) other-contributory (the latter two still subject to the (b) reduction band, SS to its own band).
- The election among (a)–(c) should compare **post-phase-out** outcomes rather than raw amounts — the current raw `max_()` can elect an option that the AGI gate then zeroes (e.g. a dual CSRS+SS case where the bands differ).
- `vt_retirement_income_exemption_eligible`'s CSRS-end AGI gate needs the same restructure (it should gate only the elected (a)–(c) component, never the (d) component — #9136 already bypasses it for the military-chosen case).

## Also in scope for the follow-up

1. **Citation fix:** two comments added in #9136 (the test-file header and `vt_retirement_income_exemption.py`) cite "Act 51 (2025)". S.51 was enacted as **Act No. 71 (2025)**; Act 51 of 2025 is S.59 (Open Meeting Law). The parameter files already cite the S.51 bill PDF correctly.
2. **Survivor benefits:** § 5830e(d) covers "U.S. military survivor benefit income … received by an eligible beneficiary." The model computes (d) from `military_retirement_pay`, whose documentation says it includes survivor benefits; confirm that's the intended input convention (a separate `military_retirement_pay_survivors` variable also exists and is used by some states).

Source: enrolled act, https://legislature.vermont.gov/Documents/2026/Docs/BILLS/S-0051/S-0051%20As%20Passed%20by%20Both%20House%20and%20Senate%20Official.pdf (Secs. 1–6 begin at p. 6; subsection (e) at pp. 10–11), cross-checked against https://legislature.vermont.gov/statutes/section/32/151/05830e.

Contributor guide

Open the contributing guide

Research direction

Start in vt_retirement_income_exemption.py and the mirrored vt_retirement_income_exemption_eligible logic, then review the tests and citation changes from #9136. Verify the 2025 Act No. 71 rules for combining the military exclusion with one post-phase-out exclusion under subsections (a)–(c), and confirm the survivor-benefit input convention. Done means the affected calculations and tests reflect the statute and the Act 51 citations are corrected.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.