Repository navigation
Conversation
… the forms - Federal income tax deduction (through 2023): attribute federal tax to the spouse who earned the income and cap each spouse at $5,000, instead of prorating the jointly capped amount by Montana AGI (2022 Form 2 instructions, Itemized Deductions Schedule, line 4). - Child and dependent care expense deduction (through 2023): phase out on the couple's combined Montana AGI and split the result equally only for spouses filing separately on the same form; a single filer and a joint return take the whole deduction (Form 2441-M lines 3-7). - Elderly homeowner/renter credit: count federal AGI without regard to losses (MCA 15-30-2337(9)(a); Form 2EC line 9). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ions Each spouse filing separately on the same form deducts their own federal income tax up to $5,000, so both spouses itemize and Montana tax is 6,295.56. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…chedule - A married person filing on a separate form (federal filing status SEPARATE) cannot take the child and dependent care expense deduction: "married couples shall file a joint return or file separately on the same form" (MCA 15-30-2131(1)(c)(vi)(A)); 2022 instructions, line 14. - The 2023 credit schedule was the Elderly Homeowner/Renter Credit Schedule; it became Schedule 2EC in 2024. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MCA 15-30-2337(4) defines gross household income as "all income received by all individuals of a household while they are members of the household". The 2023 Elderly Homeowner/Renter Credit Schedule combines the returns of "ALL members of the household" (lines 1-7 and 9) and has non-filing members report their wages on line 8; the 2024 and 2025 Schedule 2EC put "Income received by other members of your household" on line 17. The model summed each person's federal AGI over the tax unit. A tax unit dependent's federal AGI is zero (their income is on their own return), so a dependent's wages and other income were left out, and household members who file their own returns were never counted. - Add dependent_gross_income to the gross income sources. It counts a dependent's gross income items, gains but not losses, and the taxable part of their Social Security; the formula now subtracts that part before adding the untaxed remainder, so the benefits count once. - Sum gross household income over the household instead of the tax unit in the net household income and the credit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… tests dependent_gross_income counts anyone who is not the head or spouse, while irs_gross_income counts anyone who is not a dependent. A person with neither role (a minor alone in a tax unit whose dependent flag is input as false) was counted by both. Count dependent_gross_income in the formula for tax unit dependents only, so the two paths split people exactly. The property tests check, for random claimants and household members, that gross household income is the Schedule 2EC total whether the other member is a dependent or files their own return, that the credit is the same either way, stays within its bounds, and never rises with income. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PR Review: Count household members' income in Montana's elderly homeowner/renter creditPR #9882 (author: MaxGhenis, head This review covers only the two commits on top of #9877: SummaryThe two commits change how gross household income is counted for Montana's elderly homeowner/renter credit:
Both changes follow the law:
What I checked:
I found no critical issues. Each household member's income now enters exactly once, and multi-tax-unit households are handled consistently. Two items need attention:
Critical (must fix)None. Should addressS1. Mixed-sign capital gains: the filer path nets a person's own losses, so gross household income depends on the tax-unit split.
S2. The dependent gate from commit
Suggestions
Verified correct
Axiom line assessment
CI statusAll green: Branch status
Verdict: REQUEST_CHANGES |
DTrim99
left a comment
There was a problem hiding this comment.
This review covers only the two commits on top of #9877 (#9877's findings are in its own review). Counting household members' income follows MCA 15-30-2337(4), the elderly-credit tests pass on the head, and rulespec-us#1512 is dispatch-ready. Two should items (see the comment above): S1, a member on their own return still nets a short-term loss against a long-term gain, so gross household income depends on how members are split into tax units, which contradicts the invariant the PR claims (26,000 on their own return vs 30,000 as a dependent; the form gives 30,000); and S2, the is_tax_unit_dependent gate has no deterministic test (add the minor-alone-in-a-tax-unit YAML case). Merge #9877 first.
|
Closing as superseded. This PR's two commits ( Thanks @DTrim99 for the review. Here is where each item from it, and from the second independent review (GPT-6.1 Sol, Subfleet, 2026-10-06), now stands. Fixed in #10139 (draft, off main):
Already handled on main by #9915:
Owned by #9900 (the US + core hub), to keep a single writer on files it is rewriting:
Filed as a follow-up: SSI, TANF and workers' compensation are still missing from gross household income (2024 Schedule 2EC line 16). Not changed, with reasons:
🤖 Generated with Claude Code |
…in Montana's elderly credit income (#10139) * Count a filer's gains without netted losses and Social Security once in Montana elderly credit income Gross household income is federal AGI "without regard to loss" (MCA 15-30-2337(9)(a)); 2024 Schedule 2EC line 7 says "do not include any capital losses". The loss add-back restores only loss_ald, which holds the capital loss deducted in AGI. A filer's short-term loss netted against their own long-term gain never reaches it, so a member on their own return with a $10,000 long-term gain and a $4,000 short-term loss counted $6,000; as a dependent the same person counted $10,000. Restore the netted loss for everyone who is not a tax unit dependent, as dependent_gross_income does. The untaxed Social Security add-back subtracted both taxable_social_security and dependent_taxable_social_security. A person input as a dependent who is also the head (every adult in the unit input as a dependent) has neither counted, so part of their benefits dropped out. Subtract only the taxable part that irs_gross_income or dependent_gross_income actually counted. Review findings S1 (DTrim99) and P2 (GPT-6.1 Sol) on #9882, whose changes landed in #9915. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Add Schedule 2EC cases for netted gains, the dependent gate and overlapping roles Four cases fail on main (a filer's and a claimant's netted capital loss, Social Security for a person input as both dependent and head, and the credit-level netting case); five guard behavior main already has (the dependent gate for a minor alone in a tax unit, a business loss on another member's return, cross-spouse netting on a joint return, and a dependent in another member's tax unit). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Restore the year's gain hidden by a capital loss carryover in Montana elderly credit income long_term_capital_gains already includes the prior-year long-term capital loss carryover as a loss (Schedule D line 15; long_term_capital_loss_carryover is a memo). A carryover is a loss, so it must not reduce gross household income (MCA 15-30-2337(9)(a); 2024 Schedule 2EC line 7, "do not include any capital losses"). Add it back to get the year's own long-term gain, as az_property_tax_credit_capital_gains does, and restore only the gain it hid, on both income paths. Restoration applies where an income path counts the person, so a person input as both a dependent and the head stays excluded from both, as before. New cases: a carryover smaller than, larger than and equal to the year's gain; a dependent's carryover; a long-term loss netted against a short-term gain; losses exceeding the gain; and Social Security for a spouse also input as a dependent. Review finding P2 (GPT-6.1 Sol) on #10139. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Describe the carryover in the changelog fragment Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Count a carryover only against gains a direct net capital_gains input shows; add capital gains property tests When capital_gains is supplied directly as a net amount, the long-term and short-term parts default to zero, so adding the carryover to the long-term part invented a gain: a direct -5,000 net with a 5,000 carryover counted 5,000 (review round 2 on #10139). Compute gains without losses as the year's net, max(0, capital_gains + carryover), plus the netting between the year's long-term and short-term amounts, max(0, a) + max(0, b) - max(0, a + b). With parts supplied this is the floored parts; with a direct net it is the net alone. test_mt_elderly_credit_capital_gains.py checks, for random long-term and short-term amounts or a direct net, a carryover and distributions, that a household member's gains count without losses whether they are a dependent, file their own return or are the claimant, against a reference written from Schedule 2EC line 7, and that the credit is the same either way. It is derandomized (20 examples, 11 s of test time locally); a 300-example random local run passed, and it fails on main and on the previous head. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Let the long-term and short-term parts decide Montana elderly credit gains; test every sign region in one simulation Once capital_gains is an input for anyone in a simulation, everyone without one holds its default of zero, not the sum of their parts. The previous identity started from capital_gains, so a dependent with only a 10,000 long-term gain, beside a claimant whose capital_gains was supplied as 0, counted nothing (review round 3 on #10139). The parts now decide the gains whenever either is nonzero, max(0, long-term + carryover) + max(0, short-term); without parts, capital_gains is a net supplied directly and counts as max(0, net + carryover). The restoration replaces whatever the income path counted, so an inconsistent capital_gains input yields to the parts. test_mt_elderly_credit_capital_gains.py now builds one simulation from a grid covering every sign region of the long-term amount plus carryover, the short-term amount and a direct net, with and without distributions, in three input styles (parts with their net, parts with the net left to default, a net alone) and three placements (dependent, own return, claimant). It replaces 20 Hypothesis-built simulations: 3.1 s of test time locally, peak footprint 1.25 GB against 1.24 GB for importing the model and building a one-person simulation, so about 8 MB for the test itself. It fails on main and on the previous two heads. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Summary
Montana's elderly homeowner/renter credit left out two groups of household members when it computed gross household income:
adjusted_gross_income_personover the tax unit. That is zero for a dependent, becauseirs_gross_incomeleaves dependents off the filer's return. So a dependent's wages, interest, gains and other gross income were never counted.The law counts both:
Stacked on #9877. This PR is based on
fix-mt-separate-filing-allocations, which edits the same variable to add back losses. The PR workflow runs only for PRs intomain, so this PR targetsmain, and its diff includes #9877's commits until #9877 merges. This PR's own changes are the last two commits (compare). Merge #9877 first, then mergemaininto this branch.Example: 2024, a 70-year-old with a working dependent
The claimant has $20,000 of taxable pension and is billed $2,000 of property tax. Their 16-year-old dependent earned $10,000 of wages.
Now make the other member a 40-year-old who files their own return with $10,000 of wages. Before this PR the credit was $1,150. After it is $1,126.84: gross household income is $30,063.20, because their $63.20 Montana EITC (
mt_eitc, 10% of their $632 federal EITC) counts as a refundable credit received (line 8).Changes
mt_elderly_homeowner_or_renter_credit_gross_household_income(per person) now addsis_tax_unit_dependent * dependent_gross_income.dependent_gross_incomeis the existing person-level variable for a dependent's own gross income. It takes the IRS gross income sources at positive amounts, gains without losses, unemployment compensation in full, and the IRC 86 taxable part of Social Security.is_tax_unit_dependent, the same flag that zeroesirs_gross_income, splits people exactly between the federal-AGI path and the dependent path. Without the gate,dependent_gross_income's own test, "not head or spouse", would count a person with neither role twice. That case is a minor alone in a tax unit whose dependent flag is input as false.dependent_taxable_social_securityas well astaxable_social_security. Otherwise a dependent's taxable benefits would count twice.mt_elderly_homeowner_or_renter_credit_net_household_incomeandmt_elderly_homeowner_or_renter_creditsum gross household income overperson.householdinstead ofperson.tax_unit. They also get statute and Schedule 2EC references.Scope: why the household, not the tax unit or SPM unit
I chose PolicyEngine's
Householdentity.ut_homeowner_renter_relief_household_income) uses it for the same kind of definition.Limits of the proxy:
Tests
6eefe271dc) and pass here...._gross_household_income.yaml: three cases. A dependent's wages count. A dependent's Social Security counts once: $25,000 wages and $10,000 benefits give $35,000, not $37,500, withdependent_taxable_social_security$2,500 asserted. A dependent's capital loss does not offset their wages (2024 line 7: "do not include any capital losses")...._net_household_income.yaml: one case. A member in another tax unit counts: [870, 0].mt_elderly_homeowner_or_renter_credit.yaml: five cases.policyengine_us/tests/test_mt_elderly_credit_household_members.py, using Hypothesis.dependent_gross_incomeanddependent_taxable_social_securityin A, and federal AGI, Align Montana separate-filing deductions and the elderly credit's income with the forms #9877's loss add-back andtaxable_social_securityin B. YAML can't check agreement across the input space; this test does. It caught the double count that the gate above now prevents.Simulationper example. Locally on a loaded macOS host, the file runs in 4.0 s of test time and 19 s wall including model import, with a 0.95 GB peak footprint. These are local measurements, not CI. A one-off 400-example local run, with up to 12 cases each, also passed. The file lands in the Rest job'sremaininggroup (make test-other-python-rest-remaining);code_health/test_rest_python_groups.pyassigns it there automatically.mt/folder,contrib/states/mtand the state tax rollups are queued under the shared heavy lock. Results to follow below.Invariants
dependent_gross_incomefor tax unit dependents. The two paths are disjoint because both are keyed tois_tax_unit_dependent.social_security.Microsim impact
MICROSIM_PENDING
Not changed (follow-ups)
gov.states.mt.tax.income.credits.refundablelists onlymt_eitc. This gap predates the PR.axiom: TheAxiomFoundation/rulespec-us#1512 queued (required output 6 already specifies gross household income over "every statutory household member … including dependents", membership per §2337(7); this PR's companion cases are added in this comment)
🤖 Generated with Claude Code