Repository navigation
Conversation
…ption MCA 15-30-2120(3)(n) and (8), from tax year 2024: the lesser of half the return's military retirement pay or its Montana earned income (Form WMRE lines 2-5), plus half of military survivor benefits. An input records the section (9) residency and five-year conditions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… June 30, 2023) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Main's #10331 drops the disability income exclusion from Montana's subtractions for 2024 on, after SB 399 repealed it. This branch adds the working military retirement exemption to the same lists. The resolution keeps both: the exemption joins the 2024 and 2025 lists, the exclusion stays out, and the references keep both changes' sources. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
David, I'd like your read on two Montana choices here:
If you can look by Tuesday afternoon, we can merge it before the Veterans Day post (PolicyEngine/policyengine-app-v2#1523). |
PR Review: Model Montana's working military retirement and survivor benefit exemptionSummaryThe structure follows the law. MCA 15-30-2120(3)(n)(i) and (8)(a) give a retiree "the lesser of: (i) the amount of Montana source wage income on the return; or (ii) 50% of the taxpayer's military pension or military retirement income". (3)(n)(ii) gives "up to 50% of all income received as survivor benefits", with no earnings cap. (9) adds the residency and five-year conditions. The rates (0.5 and 0.5), the 2024 start, pooling the earnings cap over the return, carrying the return's amount on the head, keeping dependents out, the zero floor on each business source, and the per-person eligibility mask all match the statute, Form WMRE (2025) and its instructions. The exemption flows through the 2024+ federal-taxable-income path ( One critical problem remains. Two of the four earnings sources that set the cap are the wrong PolicyEngine variables:
Three should items remain: the PR's two statute-over-form readings have no source-conflict candidate entries; four new terms are unpinned by tests; and one reference title carries page text. On the two questions in the thread:
Critical (must fix)
Should address
Suggestions
Verified correct
Axiom line assessment
rulespec-us#2075 is OPEN and labelled
It records the encoding debt (the held It matches the head's behavior. Its output 4 is stated at the level of the law ("net income from a trade or business and net farm income"), so the Critical fix doesn't contradict it. When the fix lands, consider adding a farm companion test, such as "$30,000 of military retirement income and $40,000 of net farm income gives output 5 = 15,000". Also consider correcting "SB 124" (Suggestion 5). CI statusAt head 2eeb5d3, 36 checks pass and 7 are skipped, with none failing or pending. The passing checks include:
The head already includes main, so CI ran the merged tree. Locally on that tree:
Branch statusThe branch is 3 commits ahead and 0 behind main. #10331 (merged today) edited No file overlaps with the sibling military retirement PRs (#10702 UT, #10714 MI, #10715 ID, #10716 DE, #10717 ID). Verdict: REQUEST_CHANGES |
DTrim99
left a comment
There was a problem hiding this comment.
Requesting changes per the review above: 1 critical (the earnings cap reads self_employment_income and farm_income, so it drops SSTB business income and Schedule F farm income that 15-30-2120(8)(b) counts, and counts a non-AGI input; use total_self_employment_income and farm_operations_income), 3 should (record two statute-over-form readings; four unpinned terms; a reference title), 5 suggestions.
MCA 15-30-2120(8)(b) counts net income from a trade, business, profession or occupation and net farming income. The cap read self_employment_income (non-SSTB Schedule C only) and farm_income (the Schedule J averaging input, outside AGI). A new earned_income_sources parameter lists irs_employment_income, total_self_employment_income, partnership_s_corp_income and farm_operations_income, and the formula loops over it with the per-source zero floor. Also records three readings as source-conflict candidates (Schedule E income, both subtractions on one return, the per-source loss floor), pins the 2024 subtractions entry, the partnership and farm sources, the filer mask on earnings and the eligibility mask on survivor benefits, adds the ARM 42.15.1510(3)(a) and (b) examples, documents the armed forces scope, passive income and when the eligibility default stops being exact, drops page text from the RIC memo title, adds the 2024 Form 2 instructions as a source for the 2024 start, and removes the stale Montana limitation from military_retirement_pay_survivors. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
What was missing
PolicyEngine-US did not model Montana's working military retirement and survivor benefit exemption.
military_retirement_pay.pyandmilitary_retirement_pay_survivors.pylisted it as a limitation and the Montanasubtractions.yamlmarked it "not yet modeled", so PolicyEngine-US taxed all of a Montana military retiree's pay.The law
Change
gov.states.mt.tax.income.subtractions.military_retirement:rate(0.5) andsurvivor_rate(0.5);in_effect(false before 2024, true from 2024; parameters extend their first value backward, so the rates alone would have reached 2023);earned_income_sources:irs_employment_income((8)(b)(i), WMRE line 2),total_self_employment_income((8)(b)(ii), line 3: all Schedule C income, including a specified service trade or business),partnership_s_corp_income(line 4) andfarm_operations_income((8)(b)(iii), line 5: Schedule F).mt_military_retirement_exemption_eligible(Person, default true) for the (9) residency and five-year conditions, which PolicyEngine-US cannot derive.mt_military_retirement_exemption(Person). The head's record carries the return's amount:in_effect× [min(rate× the eligible head's and spouse'smilitary_retirement_pay, the return's earned income) +survivor_rate× their eligiblemilitary_retirement_pay_survivors]. Earned income sums each source inearned_income_sourcesover head and spouse and floors each sum at 0, as WMRE lines 3 to 5 do. Dependents' pay and income do not count.subtractions.yamladds the variable to its 2024 and 2025 lists (2026 carries 2025 forward).military_retirement_pay.pyandmilitary_retirement_pay_survivors.pydrop their Montana limitation lines.Readings taken
Three readings go into
source_conflicts/candidates.yaml(step 1 of CONTRIBUTING.md#source-conflicts; no marker until the register holds them):us-mt:military-retirement-exemption-schedule-e-incomeus-mt:military-retirement-and-survivor-exemptions-same-returnus-mt:military-retirement-exemption-business-loss-floorAssumptions
mt_military_retirement_exemption_eligibledefaults to true, which overstates the exemption in two known ways. From 2024, it includes a resident from before July 2023 whose pay or benefits began while living in another state (WMRE's example of Albert, who moved to Montana in 2021 after his pay began in Georgia in 2020). From 2029, it also includes every filer whose five years have run out, starting with those whose five years began in 2024 (WMRE: "The last year these taxpayers can claim the exemption will be tax year 2028"). As a benchmark, the committee memo reports 1,711 resident claimants and $24.8 million for tax year 2024 (more than 1,783 claimants and $25.5 million with nonresidents and part-year residents). The input has no formula, so it stays a calculator input.military_retirement_payandmilitary_retirement_pay_survivorscover every uniformed service; (3)(n)(i) covers the armed forces, the guard and the reserves. The variable assumes none of the pay comes from the NOAA Corps or the Public Health Service.Invariants
For every input:
A local randomized check (300 tax units and 572 people: 60% married, 30% with a dependent; random pay, survivor benefits, wages, Schedule C income including SSTB losses, partnership and S corporation income, Schedule F income, Schedule J
farm_income, rents, farm rent, estate income and eligibility; seed 20261111; not committed, following this repo's YAML-first test policy) found every invariant held in TY2024 and TY2026. The exemption equaled an independent restatement of Form WMRE on every unit, Montana income tax never exceeded a reform that setsin_effectto false, and every TY2023 amount was 0.Tests
mt_military_retirement_exemption.yaml, 22 cases:mt_subtractions15,000; $8,000 of wages binds (8,000); no earnings gives 0; $10,000 of survivor benefits alone gives 5,000; retired pay and a spouse's survivor benefits on one return give 10,000; a retiree who is also a survivor beside an ineligible spouse with wages and pay gives 16,000.farm_income(0); rents, Form 4835 farm rent and estate income (0); a dependent's pay (0); a dependent's wages (0).mt_subtractions15,000; TY2023 (0).Removing each new term fails at least one case:
irs_employment_incomefromearned_income_sourcestotal_self_employment_incomepartnership_s_corp_incomefarm_operations_incomeself_employment_income(non-SSTB only) instead oftotal_self_employment_incomefarm_income(Schedule J) to the listsubtractions.yamlentryfilermask on earningsfilerinstead ofeligibleAt 09ed698 (this branch, with main merged at 3386304), all 1,122 cases under
tests/policy/baseline/gov/states/mtpass, and so do the 107 tests intests/code_health/test_source_conflicts.pyandtests/code_health/test_military_retirement_readers.py. ruff format and check pass on the changed Python files.Before and after
TY2026, a single filer age 55 with $30,000 of military retired pay, before this fix (2eeb5d3) and after (09ed698):
farm_income(AGI $30,000)A married couple, one spouse age 45 with $30,000 of military retired pay and $60,000 of wages, TY2026, at 09ed698: Montana income tax is 2,716.60 with
in_effectset to false and 2,011.60 with the 15,000 exemption (2eeb5d3 gave the same 2,011.60). With no pension the couple owes 1,306.60, so Montana's tax on the pay falls from 1,410 to 705. A retired couple, ages 67 and 65, with $45,000 of military retired pay, $30,000 of Social Security and no earnings gets no exemption.axiom: us-mt/statute/15-30-2120 queued (TheAxiomFoundation/rulespec-us#2075)
🤖 Generated with Claude Code