Skip to content

Fix West Virginia low-income exclusion double count - #9166

Open
PavelMakarchuk wants to merge 1 commit into
mainfrom
fix/wv-low-income-exclusion-once
Open

Fix West Virginia low-income exclusion double count#9166
PavelMakarchuk wants to merge 1 commit into
mainfrom
fix/wv-low-income-exclusion-once

Conversation

@PavelMakarchuk

Copy link
Copy Markdown
Collaborator

Summary

  • remove the low-income earned-income exclusion from West Virginia Schedule M subtractions
  • preserve its single application between West Virginia adjusted gross income and taxable income
  • add an integrated 2026 regression covering the intermediate values and pre-credit tax

Statutory and form basis

West Virginia IT-140 lines 1-7 compute West Virginia adjusted gross income from federal AGI plus Schedule M additions minus Schedule M subtractions, then subtract the low-income earned-income exclusion and personal exemptions to reach taxable income. This matches West Virginia Code sections 11-21-10 through 11-21-12 and prevents the exclusion from being applied twice.

Checks

  • focused wv_taxable_income YAML: 3 passed
  • full baseline WV income-tax YAML directory: 109 passed
  • WV contrib/reform YAML: 16 passed (test assertions completed; Python 3.14 process was interrupted during teardown)
  • household marginal-tax-rate YAML: 5 passed
  • make format (including Ruff): passed
  • git diff --check: passed
  • independent review-fix-review cycle: CLEAN at ad56b65

No partner contract files are changed.

@PavelMakarchuk
PavelMakarchuk requested a review from MaxGhenis July 28, 2026 05:11
@codecov

codecov Bot commented Jul 28, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (4c6ac7e) to head (ad56b65).
⚠️ Report is 3 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff            @@
##              main     #9166   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files            3         1    -2     
  Lines           49        14   -35     
=========================================
- Hits            49        14   -35     
Flag Coverage Δ
unittests 100.00% <100.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@PavelMakarchuk

Copy link
Copy Markdown
Collaborator Author

@MaxGhenis This is ready for maintainer review: exact reviewed head ad56b658abc3 is 33/33 green. The independent review-fix-review cycle corrected the public WV AGI structure (single low-income exclusion application) and ended CLEAN; full WV income-tax checks are 109/109.

@DTrim99

DTrim99 commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

Program Review — PR #9166 (Fix West Virginia low-income exclusion double count)

Author: PavelMakarchuk · Bug fix

Source Documents

  • WV IT-140 (2024) form order of operations · W. Va. Code §§ 11-21-10, -11, -12

Branch Status

⚠ 6 commits behind main (1 ahead). Minor; review scoped to the merge-base diff.

Summary

Correct fix for a real, confirmed double-count bug. 0 critical, 0 blocking. The WV low-income earned-income exclusion was being subtracted twice on main — once inside the Schedule M subtractions list (federal AGI → WV AGI) and again between WV AGI and taxable income. The PR removes exactly the Schedule M listing, preserving the single correct application. CI green (33/33). Verified correct against the statute and IT-140.

The bug was real (confirmed against IT-140 + §11-21-11)

IT-140's front-of-form order of operations is decisive:

Line Item
4 WV AGI = federal AGI + Schedule M additions − Schedule M subtractions
5 Low-Income Earned Income Exclusion (worksheet)
7 WV Taxable Income = Line 4 − Lines 5 & 6, floored at 0

The exclusion appears only on Line 5 — it is not among the Schedule M decreasing modifications (lines 29–52). On main it was in both places:

  • subtractions.yaml listed it → wv_subtractions → subtracted in wv_agi (path 1)
  • wv_taxable_income.py subtracted it again (path 2)

Net effect: over-stated subtractions, under-stated taxable income, under-stated tax for eligible low-income earners — contradicting §11-21-11 and IT-140.

The fix is correct

  • Removes wv_low_income_earned_income_exclusion from subtractions.yaml (it leaves WV AGI). ✅
  • Keeps the single subtraction in wv_taxable_income.py (IT-140 Line 5 / §11-21-11) — not removed entirely. ✅
  • Grep-confirmed the exclusion's only remaining consumer is wv_taxable_income.py (applied exactly once). ✅
  • Direction/magnitude correct: raises taxable income for affected earners to the statutory amount. ✅
  • Reference updated §11-21-4E§11-21-11 (the correct "WV taxable income = WV AGI less exemptions" section). ✅

Worked example (new regression test, 2026 SINGLE, fed AGI 10,000, earned 7,000): exclusion = 7,000; wv_subtractions: 0; wv_agi: 10,000 (exclusion NOT in AGI — pins the fix); wv_taxable_income = max(10,000 − 7,000 − 2,000, 0) = 1,000 (applied once); tax = 21.10. Under the old double-count, taxable income would have been 0 — so the test asserts a strictly-higher value and fails on multiple lines if the duplicate returns. Non-vacuous, well-constructed.

Blast radius — clean

The Schedule M subtractions list feeds only wv_subtractionswv_agiwv_taxable_income. No other WV variable relied on the exclusion being in that list; notably the LIFTC AGI variable builds its own base from adjusted_gross_income and is unaffected. Removing the list entry breaks nothing.

Critical / Should Address

None.

Suggestions (optional)

  • Add a second integration case for a JOINT/SEPARATE filer (cap 10,000 vs 5,000) or one with a genuine non-zero Schedule M subtraction alongside the exclusion — to lock in that the exclusion no longer leaks into wv_subtractions when other subtractions are present.
  • Minor: subtractions.yaml metadata still references §11-21-12 (Schedule M) while the variable now cites §11-21-11 — both correct for their respective scopes, worth a glance for consistency.

Validation Summary

Check Result
Regulatory Accuracy Double-count confirmed real via IT-140 (Line 5, not Schedule M) + §11-21-11; fix removes exactly the duplicate, keeps single application; direction/magnitude correct
Code Patterns 0 critical / 0 should — correct add()-list de-dup mechanism, no hardcoded values, all TaxUnit entities, changelog fixed correct, reference corrected
Test Coverage Strong non-vacuous regression (old→taxable 0, new→1,000; pins intermediate WV AGI = exclusion excluded, and single application)
Blast Radius Clean — LIFTC and all other consumers unaffected
CI Status Passing (33/33)

Review Severity: APPROVE

A correct, well-scoped bug fix backed by the IT-140 form and §11-21-11: the exclusion was genuinely double-applied and is now applied exactly once, with a rigorous end-to-end regression test and a clean blast radius. No blocking or should-address items. Rebase off the 6-commit lag before merge.

Review generated with Claude Code via /review-program

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants