Fix WI retirement income exclusion applied after standard-deduction phaseout (#8817)#8818
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #8818 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 3 2 -1
Lines 55 41 -14
=========================================
- Hits 55 41 -14
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
PavelMakarchuk
left a comment
There was a problem hiding this comment.
Review: Fix WI retirement exclusion applied after standard-deduction phaseout
Nice fix — the ordering correction is algebraically exact and matches WI Form 1. Requesting changes on a couple of minor items (one real reference-format bug + some boundary test coverage); the core logic is sound.
Verified correct
- The fix is algebraically exact.
taxinc − line16 − (SD(wi_agi−line16) − SD(wi_agi))cancels theSD_fullterms, leaving exactly Form 1's(wi_agi − line16) − SD(wi_agi − line16). Confirmed against the 2025 Form 1: line 6 (Schedule SB subtractions) → line 7 (Wisconsin income) → line 8 standard deduction "use the amount on line 7". Because the deduction phases down, subtracting the exclusion first correctly unlocks more deduction. (Sanity check: single $45k/$20k excl → extra deduction = SD(25k) − SD(45k) = $2,400, matching the 474→390 result.) - Correct provision: Act 15 / Schedule SB line 16 ($24k/person age 67+, no AGI cap), correctly distinguished from the $5k line-17 subtraction (statute
71.05(6)(b)54mcorroborated). - Idiomatic pattern: the module-level
wi_standard_deduction_for_incomehelper is the right choice (aVariablecan't be evaluated at an arbitrarywi_agi − line16input), reusesgov.states.wi.tax.income.deductions.standardparams (no hardcoding), no circular-import risk, no behavior change to plainwi_standard_deduction, regression-free below the threshold. Changelog present (fixed).
Requested changes
wi_standard_deduction.pyreferenceis five adjacent string literals with no commas, so Python concatenates them into one mashed, unclickable URL. Make it a comma-separated tuple. (Pre-existing, but the fix now leans on this variable.) While there, add a source that actually corroborates the phaseout the fix depends on — the 2025 Standard Deduction Table (2025-Form1-Inst.pdf#page=35, keyed to line 7) orWis. Stat. 71.05(22).- Add a few boundary tests around the fix:
- below-threshold no-regression (currently only implicit — the low-income unit tests stub
wi_taxable_incomeand don't mention the extra-SD term); - the fully-phased-out top end (the "age-85 unchanged" claim isn't asserted anywhere);
- the partial-unlock boundary —
wi_agipast the phaseout end whilewi_agi − line16lands inside it (all current cases keep both endpoints in the linear region); - one-spouse-67+ joint ($24k per-person branch; all joint tests use two eligible spouses / $48k).
- below-threshold no-regression (currently only implicit — the low-income unit tests stub
Suggestions
- Age 66/67 eligibility boundary case.
- The phaseout thresholds param cites efile.com (third-party) — prefer an official WI source (pre-existing).
- If the helper is expected to be reused beyond WI, a
_helpers-style module would aid discoverability; co-locating inwi_standard_deduction.pyis fine as-is.
🤖 Reviewed with Claude Code
…t boundary tests - Fix wi_standard_deduction.py reference: the five adjacent string literals had no commas and concatenated into one broken URL; make it a proper tuple and add the 2025 Standard Deduction Table (2025-Form1-inst.pdf#page=35) and Wis. Stat. 71.05(22), which corroborate the phaseout the fix relies on. - Add four boundary tests around the ordering fix: below-phaseout no-regression (extra deduction 0 -> tax 175), fully phased-out top end (age 85 -> 350), partial unlock (full income past phaseout end, reduced inside -> 490.49), and joint with one spouse 67+ using the $24k per-person cap (amount 24k / tax 210). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Fixes applied (addressing @PavelMakarchuk's review)Pushed as Requested changes
Suggestions
CI running now. |
…haseout (PolicyEngine#8817) The Act 15 retirement income exclusion (Schedule SB line 16) reduces WI income (Form 1 line 7), and the standard deduction (line 8) is a function of that reduced income. wi_retirement_income_exclusion_tax subtracted the exclusion from post-standard-deduction taxable income, leaving the phaseout keyed to the higher pre-subtraction income and over-taxing elderly filers with retirement income. Add back the extra standard deduction the subtraction unlocks (equivalent to recomputing the standard deduction on the post-subtraction WI income) via a new wi_standard_deduction_for_income helper. Add a 67+ MFJ regression test above the standard-deduction phaseout threshold and update the affected E2E case. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…t boundary tests - Fix wi_standard_deduction.py reference: the five adjacent string literals had no commas and concatenated into one broken URL; make it a proper tuple and add the 2025 Standard Deduction Table (2025-Form1-inst.pdf#page=35) and Wis. Stat. 71.05(22), which corroborate the phaseout the fix relies on. - Add four boundary tests around the ordering fix: below-phaseout no-regression (extra deduction 0 -> tax 175), fully phased-out top end (age 85 -> 350), partial unlock (full income past phaseout end, reduced inside -> 490.49), and joint with one spouse 67+ using the $24k per-person cap (amount 24k / tax 210). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
3175ffa to
8433324
Compare
|
@PavelMakarchuk both requested changes were addressed in Requested changes — resolved1. Reference tuple. 2. Boundary tests. Added the four cases you asked for in
Rebase
VerificationFull WI test directory passes locally against current- SuggestionsLeft the phaseout-threshold param's efile.com citation and the helper's location in |
Fixes #8817.
Problem
Wisconsin's Act 15 retirement income exclusion (Schedule SB line 16, $24,000/person for age 67+) was applied after the standard-deduction phaseout. On Form 1 the line-16 subtraction reduces WI income (line 7), and the standard deduction (line 8) is looked up on that reduced income — which is larger. Applying the subtraction after the phaseout kept the standard deduction too small and over-taxed elderly filers with retirement income.
Root cause
wi_retirement_income_exclusion_taxcomputedwi_taxable_income − line16, butwi_taxable_incomealready baked in the standard deduction computed on the higher pre-subtraction WI income.Fix
Add back the extra standard deduction the line-16 subtraction unlocks — algebraically equivalent to recomputing taxable income on the post-subtraction WI income, while keeping
wi_taxable_incomeas the base (so existing behaviour below the phaseout threshold is unchanged). Factored the standard-deduction phaseout into a reusablewi_standard_deduction_for_incomehelper so both the normal path (onwi_agi) and the exclusion path (onwi_agi − line16) share one implementation.Verification / tests
References
🤖 Generated with Claude Code