Repository navigation
Make household state tax totals equal each state's own income tax - #10039
Merged
MaxGhenis merged 8 commits intoOct 18, 2026
Merged
Conversation
Household net income subtracts household_state_tax_before_refundable_credits and adds household_refundable_state_tax_credits, which sum the cross-state lists of state tax before refundable credits and refundable credits. Five state taxes applied rules outside those components, so household net income disagreed with the state's own income tax: - Wisconsin: the retirement income exclusion election (fixed in #10026's components); drop the WI override in state_income_tax and household_state_income_tax, which now follow the decomposition. - New Jersey: the override was redundant (the filing-threshold zero-out is already in nj_income_tax_before_refundable_credits); drop it. - Vermont: add vt_child_care_contributions (Form IN-111 line 21). - Colorado: add co_amt (DR 0104 line 14). - Mississippi: add ms_income_tax_before_refundable_credits, which applies nonrefundable credits (Form 80-105 lines 18-19), and build ms_income_tax from it less ms_refundable_credits. - Michigan (contributed surtax): add mi_surtax. Add table-sourced YAML cases for each state and an every-state invariant test: structural list membership, state_income_tax == xx_income_tax, and household before-refundable less refundable == state_income_tax + use tax. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Takes main's version of every file #10026 changed. The branch's own change is the one commit "Make household state tax totals equal each state's own income tax", rebased onto main. It no longer edits gov/household/household_tax_before_refundable_credits.yaml, which #10071 removes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Say which properties find a new state's gap and what property 3 guards. - Add a seeded 2023 population for the formula states, so Montana's separate filing on one form is always exercised. - Skip Hypothesis shrinking: each example builds a full simulation. - Correct the NC and NJ notes, the household_state_income_tax comment, and note that the Michigan surtax reform must stay unconditional because the baseline list adds mi_surtax. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis
marked this pull request as ready for review
October 18, 2026 16:02
Contributor
Author
|
Hand-off to the US + core hub.
State: |
Contributor
Author
|
US + core hub merge audit, us#10039 at
|
MaxGhenis
deleted the
fix-wi-retirement-exclusion-household-accounting
branch
October 18, 2026 20:02
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Household net income now subtracts each state's own final income tax. Before this change, five state taxes applied a rule that the household totals never saw, so
household_net_incomedisagreed withstate_income_taxor with the state's ownxx_income_tax.#10026 (merged) moved the Wisconsin retirement income exclusion election into
wi_income_tax_before_refundable_creditsandwi_refundable_credits, which closed the Wisconsin gap. This PR closes the same gap in four other states, removes the overrides that hid it, and adds a test that holds every state to the identity.Mechanism (read from code)
household_net_incomeaddshousehold_refundable_tax_creditsand subtractshousehold_tax_before_refundable_credits. The state parts of those arehousehold_state_tax_before_refundable_credits(thegov.states.household.state_income_tax_before_refundable_creditslist plusstate_use_tax) andhousehold_refundable_state_tax_credits(thegov.household.household_refundable_state_creditslist). Neither readsstate_income_tax. The state list reads each state's before-refundable-credits amount, with one exception: North Carolina's entry is its finalnc_income_tax. So any rule a state other than North Carolina applies only inside its ownxx_income_tax, or only in an override insidestate_income_tax, never reaches household net income.state_income_tax)state_income_taxused an override towi_income_tax, which tookmin_(standard, exclusion); the household path used the standard taxstate_income_taxandhousehold_state_income_tax, which become plainadds/subtractsnj_income_taxwas redundant, sincenj_income_tax_before_refundable_creditsalready applies the filing-threshold zero-outvt_income_taxaddsvt_child_care_contributions(Form IN-111 line 21); the list did notco_income_taxaddsco_amt(DR 0104 line 14, inside the line 16 subtotal, before refundable credits on line 31); the list did notms_income_taxsubtracted nonrefundable credits (Form 80-105 lines 18-19); the list heldms_income_tax_before_credits_unit, before those credits.ms_income_taxalso ignoredms_refundable_creditsms_income_tax_before_refundable_credits= max(0, tax before credits − nonrefundable credits);ms_income_tax= that −ms_refundable_credits; the list uses itmi_surtaxreform addsmi_surtaxtomi_income_tax; the list did not, so the surtax never reached household net income. Zero unlessgov.contrib.states.mi.surtax.in_effectThe abolish-federal-income-tax and abolish-payroll-tax reforms sum a separate hand-kept list,
gov.household.household_tax_before_refundable_credits, with the same gaps and more: it still holdsms_income_tax_before_credits_unitand lacksco_amt,vt_child_care_contributionsandmi_surtax. #10071 removes that list and those reforms, so this PR leaves it alone and the two do not conflict. If #10071 does not land, that list needs the same four changes.Baseline
ms_refundable_creditshas no formula, soms_income_taxis unchanged in baseline. Under the contributed Mississippi EITC reform it now subtracts the credit, asstate_income_taxalready did.Sources for expected values
Some cases are structural rather than sourced: the Colorado case (tax 4,000, AMT 500, refundable credits 100), the Vermont case (tax 1,000, refundable credits 200), the Mississippi credit of 159, and the two Wisconsin election cases in
household_refundable_state_tax_credits.yamlset chosen inputs. For those, only the line structure (what adds before refundable credits) comes from the cited form. The Wisconsin household cases use whole-return arithmetic from those tables. For example, a single filer aged 68 with a $40,250 pension, $24,000 of Social Security and a $5,000 long-term gain: with credits, line 7 = $43,750, standard deduction $10,656, taxable income $32,144, tax $1,282; with the $24,000 exclusion, line 7 = $19,750, standard deduction $13,536, taxable income $5,264, tax $184. On main the household total carried $1,282 whilestate_income_taxwas $184.Tests
New and changed YAML:
household_state_tax_before_refundable_credits.yaml: six Wisconsin households (single, joint, renter, age 66), plus Vermont, Mississippi and Colorado cases.household_refundable_state_tax_credits.yaml: a Wisconsin renter who keeps the $588 homestead credit, and the 2025 and 2026 credit treatment under the election.household_net_income.yaml: a Wisconsin retiree, end to end ($41,250 − $96 = $41,154).state_income_tax.yaml,ms_income_tax.yaml,ms_income_tax_before_refundable_credits.yaml,contrib/states/mi/mi_surtax.yaml.Run against upstream main's Wisconsin variables (00968de, before #10026), the table-sourced Wisconsin household cases, written then with my own election variable's name, failed by $341 to $2,092 on the household total, and the end-to-end net income case by $1,063. After porting them to #10026's names and leaf inputs, they pass on this branch.
New Python test
tests/core/test_state_income_tax_accounting_invariants.py. YAML cannot express these properties, because each compares two computed totals on every row:xx_income_taxis a sum, it adds exactly that state's members of the before-refundable list and subtracts exactly its members of the refundable list. List members must be defined variables, and the household refundable list must equal the state one.state_income_tax == xx_income_taxfor every state, on a seeded population of 18 households per state and DC (12 archetypes, 6 random), plus Hypothesis draws in the four states whosexx_income_taxis a formula (MT, NC, NJ, WI) for 2023 and 2025.state_income_tax+state_use_tax. Use tax is the one labelled exception: it is paid to the state but is not income tax (state_income_tax_excludes_use_tax.yaml).Mutation check, run before the Hypothesis layer was added: reverting each fix in turn (the MS list entry, VT, CO, MI, and the WI variables as on main) fails the test every time: MS and VT fail properties 1 and 2, CO and MI fail property 1, WI fails property 2.
Local runs (macOS, shared host):
household/income/household53 passed;gov/states/tax/income77;gov/states/ms/tax/income149;gov/states/vt/tax/income181;gov/states/wi/tax/income165;gov/states/co/tax/income335;household/household_state_income_tax.yaml1.nj_income_tax.yaml(10 files, one process): 49 passed;contrib/states/mi/mi_surtax.yaml: 10 passed;contrib/states/ms:ms_eitc.yaml5 passed,dependent_exemption_reform_test.yaml5 passed;gov/states/ms/tax/income, five batches throughtest_batched.py): 151 passed, none failed.CI: the new file runs in the existing
coregroup,make test-other-python-rest-core(REST_PYTHON_GROUPS; the Makefile records 142 s for that group in run 37198184683). No Linux measurement yet. No runners or matrix entries are added.Partner contract tests: none can move. A static scan found no partner case in WI, MS, VT, MI or NJ. None of the 50 Colorado cases asserts a household total,
state_income_taxorco_income_tax. No partner file is edited.Review
GPT-6.1 Sol, round 1 at 84edf5b: APPROVE, no blocking findings (static review;
~/reviews/us-hub/fixes/10039/review-r1-out.mdon the hub host). Round 2, a delta review at b54018f: APPROVE, no blocking findings (review-r2-out.md); it confirmed the 2023 Montana population, the Hypothesis settings and the NJ decision, and flagged that an earlier version of this body claimed test results before they existed (fixed).git diff --stat 23285ce622 mainover this PR's files is empty: the merge of main brings no change to them. Round 1's non-blocking findings and what changed at b54018f:coregroup. Shrinking is off (phases=[explicit, generate]), since each example builds a full simulation.state_income_tax.nj_income_taxa plain sum: not taken. Two existing NJ cases setnj_income_tax_before_refundable_creditsas an input with income under the filing threshold and expect the zero-out, so the second copy still does work; the test comment now says so.household_state_income_taxcomment: updated (same sum asstate_income_tax, kept for callers).reforms/states/mi/surtax.pythat the reform must stay unconditional;test_list_members_are_defined_variablesalso catches it.nc_income_tax).Invariants
state_income_tax == xx_income_tax. It is zero in AK, FL, NV, SD, TN, TX and WY.household_state_tax_before_refundable_credits − household_refundable_state_tax_credits == Σ state_income_tax + state_use_tax.xx_income_taxis built from exactly its state's list members.ms_income_tax_before_refundable_credits ≥ 0, andms_income_tax == ms_income_tax_before_refundable_credits − ms_refundable_credits.Hub microsimulation impact (current head)
A real microsimulation on the default dataset, main at the merge base
5ec60b209aagainst this PR's headb54018fa60, for 2025 and 2026. The runs went one at a time under the shared heavy-job lock. Sums are weighted.household_state_tax_before_refundable_creditshousehold_refundable_state_tax_creditsspm_unit_state_taxvt_child_care_contributionsco_amtms_non_refundable_creditsstate_income_taxincome_taxhousehold_net_incomehousehold_benefitsBy state: weighted change, summed to households, states with any change
household_net_income2025household_net_income2026state_income_tax2025state_income_tax2026Comparison files are in
fixes/10039-impact/on the hub host.Impact
The hub table above is a real microsimulation of the default dataset at this head (b54018f) against its merge base with main (5ec60b2), for 2025 and 2026. Only Mississippi and Vermont move, each by exactly the component the household totals used to miss:
ms_non_refundable_credits($2.85M in 2025, $3.16M in 2026)vt_child_care_contributions($2.22M in 2025, $2.36M in 2026)co_amtis $0 for every record in the dataset in both years, so the fix matters only for households with a Colorado AMT, such as household calculations.income_taxandhousehold_benefits: no change.state_income_taxandspm_unit_state_taxmove by the same amounts with the opposite sign, and now matchms_income_taxandvt_income_tax. By code:federal_state_income_tax(defined intotal_income_tax.py),taxsim_siitaxandstate_marginal_tax_ratereadstate_income_tax, andspm_unit_net_incomesubtractsspm_unit_taxes, which addsspm_unit_state_tax. No state's ownxx_income_taxchanges.axiom: n/a: household aggregation only. No state's own income tax changes in baseline; the Wisconsin provision is queued in TheAxiomFoundation/rulespec-us#1610 through #10026.
Changelog:
changelog.d/fix-wi-retirement-exclusion-household-accounting.fixed.md.🤖 Generated with Claude Code