Skip to content

End the tips and overtime deductions after 2028 at the source - #10397

Open
MaxGhenis wants to merge 5 commits into
mainfrom
fix-tips-overtime-2029-termination
Open

MaxGhenis wants to merge 5 commits into
mainfrom
fix-tips-overtime-2029-termination

Conversation

@MaxGhenis

@MaxGhenis MaxGhenis commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Ready for CI. Three rounds of independent review are done (round 1 asked for changes; rounds 2 and 3 approved with nits, all addressed below), and main, with #10393, is merged in. The final-head impact is below. Before merge: the final-head local test set, queued behind a host reservation that ends 15:30Z, and CI.

What was wrong

26 U.S.C. 224(h) and 225(g) say "No deduction shall be allowed under this section for any taxable year beginning after December 31, 2028". Pub. L. 119-21 secs. 70201(j) and 70202(g) apply the two sections to taxable years beginning after December 31, 2024.

The federal deduction lists dropped both deductions from 2029, so federal taxable income was right. But tip_income_deduction and overtime_income_deduction kept computing in every year. Seven state modules read them directly, and three of them had wrong 2029 values.

Household probe at this head (b8d9ea68) against main 3128b789, 2029, single filer, age 40, $60,000 wages, $10,000 qualified tips, $5,000 FLSA overtime premium:

State Variable 2028 2029, main 2029, this PR State income tax 2029, main → this PR
MT mt_federal_obbba_subtraction 15,000 15,000 0 1,307 → 2,012
AZ az_subtractions 15,000 15,000 0 695 → 1,070
SC sc_obbba_addback 15,800 15,800 800 1,595 → 1,595
CO co_overtime_income_addback 5,000 0 0 1,858 → 1,858
MI mi_qualified_tips_deduction + overtime 15,000 0 0 2,282 → 2,282
ID id_qualified_business_income_and_federal_schedule_1a_deductions 15,000 0 0 1,844 → 1,844
  • Montana and Arizona subtracted deductions that 224(h) and 225(g) no longer allow, which cut their 2029 tax.
  • South Carolina's add-back was wrong as a value: it added back $15,000 that was never deducted federally. But from 2026 sc_taxable_income starts from federal AGI under H.4216 (sciad.in_effect), so the OBBBA add-back no longer enters it and South Carolina tax doesn't change under current law. The remaining $800 is the standard deduction add-back, which this PR doesn't touch.
  • Colorado was already 0 through a 2029 workaround (see below), Michigan through its own 2026-2028 window, and Idaho through its list, which ends at 2028. Indiana lists the deductions for 2026 only.

Change

  • New switches. gov.irs.deductions.tip_income.in_effect and gov.irs.deductions.overtime_income.in_effect: false before 2025, true for 2025-2028, false from 2029. They cite 224(h) and 225(g), and the enrolled bill's sections 70201(a) and (j) and 70202(a) and (g).
  • Early return. Each formula returns 0 when its switch is off, following the existing in_effect pattern (energy_efficient_home_improvement_credit_potential, ctc_arpa_phase_out_cap). Every consumer now gets 0 outside 2025-2028.
  • Federal lists. deductions_if_itemizing.yaml and deductions_if_not_itemizing.yaml now name both deductions in every dated block, and so do the CRFB senior deduction extension's 2029 lists (reforms/crfb/senior_deduction_extension.py). The switches are now the only place the dates live, so a reform that turns them on in another year reaches federal taxable income as well as the states. Baseline results are unchanged.
  • Colorado. C.R.S. 39-22-104(3)(u) adds back "the amount of any overtime compensation excluded or deducted from federal gross income" and has no end date. qualified_overtime/in_effect.yaml had a 2029-01-01: false entry only because the federal variable leaked, as its comment said. This PR removes the entry and rewrites the comment. Baseline is unchanged, because the federal amount is 0 from 2029. Under a reform that extends section 225, Colorado now adds the deduction back, as its statute requires.
  • Michigan keeps its own 2026-2028 switch, because MCL 206.30(1)(ee) itself covers "tax years beginning after December 31, 2025 and before January 1, 2029".
  • Montana. Its TODO: Remove this subtraction starting in 2029 stays. The tips and overtime parts are now 0, but the senior and car loan parts still leak (see follow-up).

State law: does any state continue a deduction after 2028?

No affected state does. I read each text this session:

  • Arizona, A.R.S. 43-1022(31) and (32): "the amount of qualified tips received during the taxable year that is deducted under section 224", and the same for overtime "deducted under section 225". There is no end date, but nothing is deducted under 224 or 225 after 2028.
  • Michigan, MCL 206.30(1)(ee): "for tax years beginning after December 31, 2025 and before January 1, 2029, deduct ... the following deductions allowed to be claimed on the taxpayer's federal income tax return".
  • Colorado, C.R.S. 39-22-104(3)(u) (HB25-1296 sec. 6): adds back overtime "excluded or deducted from federal gross income".
  • Montana, MCA 15-30-2101(22): "'Montana taxable income' means federal taxable income ... adjusted as provided in 15-30-2120". Section 15-30-2120 (2025 code) has no tips or overtime adjustment.
  • South Carolina, SC Information Letter make a test for max snap benefit, add to existing tests #26-4 (Revised, January 30, 2026): taxpayers adjust their return "if the following 2025 federal provisions are claimed on their federal return", listing tips and overtime.
  • Idaho and Indiana: the model's own lists already end. Idaho's Schedule 1-A list ends at 2028. Indiana's list carries the deductions for 2026 only, and the list comment cites SB 243, IC 6-3-2-31 and -32.

Tests

  • Federal, by variable. tip_income_deduction.yaml and overtime_income_deduction.yaml each open with the same filer computed in 2024 (0), 2025, 2028, 2029 (0) and 2030 (0). The cases sit at the top of the files, clear of Count only filers' tips and overtime toward the deductions, and require only the recipient's SSN #10396's appended cases.
  • Federal, lists. tip_and_overtime_income_deduction.yaml gains list-level cases, with every other listed deduction set to 0. Both lists hold 15,000 in 2028 and 0 in 2029, and 15,000 again with both switches on in 2029 and in 2024.
  • 2030 itemizing case. In taxable_income_before_itemized_deductions.yaml it now computes the two deductions instead of entering them.
  • States: 2028 and 2029 pairs, with the deductions computed, not entered:
    • SC sc_obbba_addback: 15,000, then 0 (itemizer).
    • MT mt_federal_obbba_subtraction: 10,000, then 0.
    • AZ: new az_subtractions.yaml, 15,000, then 0.
    • CO: Case 7 (2029, now computed) and Case 10 (2028), plus Case 11, which pins the add-back without an end date.
    • MI integration: 2028, then 2029.
    • Idaho: 2028.
  • Idaho's 2029 case asserted tip_income_deduction: 10_000 and overtime_income_deduction: 10_000, which pinned the leak; it now expects 0.
  • test_reform_backdating.py::test_simulation_reform_leaves_earlier_years. Its leaked-cap guard needs a nonzero 2024 tip deduction, which the gate now correctly zeroes. Both simulations now switch the tip deduction on for 2024 only, so the guard still catches a cap reform leaking back into 2024 (round 1 confirmed this with a simulated leak).
  • tests/core/test_tip_and_overtime_deduction_years.py (new): see invariants.
    • Why Python: YAML can't draw random households across 21 years or run Hypothesis, and the test checks identities across years and states rather than restating the formula.
    • CI group: Rest Python core, shard 2.
    • Cost, measured locally on macOS (not CI): 41.8 s in pytest, 67.7 s wall including import, 3.13 GB peak footprint. An earlier two-seed version took 64.5 s at 3.18 GB.

Local runs: all 40 affected files passed at ce325ed3, one process each under the hub heavy lock. The full affected set runs again at this head after the reservation. Nine code-health files pass at this head: 320 passed, 1 skipped. They are reference URLs, concatenated reference URLs, known dead reference URLs, parameter YAML keys, Rest Python groups, selective test batches, make-test-matches-CI, batched YAML collection and source conflicts. The log is in ~/reviews/tips-overtime-2029-2026-10-23/code-health-b8d9ea68.log on the hub host.

Invariants

For every input:

  1. Both deductions are 0 in every year outside 2025-2028.
  2. With both switches forced on in every year, each return gets the same amount in every year as in 2025. Inside 2025-2028 the current-law amount equals that 2025 amount. This relies on the caps, thresholds and phase-out parameters each having a single value dated 2025, and the test says so.
  3. Giving a return its tips and overtime moves South Carolina's sc_obbba_addback, Montana's mt_federal_obbba_subtraction and Arizona's az_subtractions by exactly the federal tips and overtime deductions in 2026-2028, and by 0 from 2029. This pass-through identity is checked with Hypothesis.

Mutants, with each failure read:

  • Tips 2029 set to true: every test fails. The 2029 deduction is nonzero, and the SC add-back moves $10,000 in 2029.
  • Tips before 2025 set to true: the year test fails on a nonzero 2015 deduction.
  • Overtime 2029 set to true, against the final one-draw test: both tests fail. All three are recorded in mutants.md in the same folder.

Merging with #10393 and #10396

#10393 merged first, and main is merged into this branch with no conflicts. #10396 (still open) edits the same formulas and test files: it changes some existing cases and appends others. git merge-tree with its head bbf9b859 reports no conflicts. On that trial merge, both property test files pass (7 of 7), as do tip_income_deduction.yaml (39), overtime_income_deduction.yaml (34) and tip_and_overtime_income_deduction.yaml (18). The log is in trial-merge-10396.log in the same folder.

Axiom

axiom: TheAxiomFoundation/rulespec-us#1883 queued

rulespec-us us/statutes/26/224.yaml and 225.yaml encode 224(h) and 225(g) only as and not taxable_year_begins_after_termination_date. That is an input the caller sets: nothing derives it from the period, and no upstream companion case sets it. #1883 is dispatch-ready (pe-parity) and asks to derive the termination from the taxable year and retire the input. It carries the verbatim law, a pasteable review_finding, companion cases from the same ground truth as this PR's tests, and the pipeline module's own use of the name.

As evidence of today's behaviour, I ran 2028 (input false) and 2029 (input true) cases for each section through axiom-encode test on engine cd4cbdf8 (rulespec-us fa533144, with 224/225 identical to current main). All 12 cases passed, and a negative control failed as it should.

Review

Independent Opus 5.5 reviews were used because Subfleet had no dispatchable Codex or Claude lane at the time (status snapshot lanes-status-*.txt in the same folder).

  • Round 1, REQUEST-CHANGES.
    • The blocker: switching the parameters on revived the variables but not the federal deduction. Fixed by naming both deductions in every list year.
    • Also fixed: a Colorado test for the end-date change, the Axiom line, the reference format, the figures, the wording and the test cost.
  • Round 2, APPROVE-WITH-NITS at 9551d7b6. It confirmed baseline is unchanged under the list change, with zero differences in a differential run against main's lists. It found no double-counting and confirmed the merged formulas. The nits are fixed in b8d9ea68: this body, one reference entry per source, the changelog, the NJ Child Tax Credit #1883 pipeline note, and test cost.
  • Round 3, APPROVE-WITH-NITS at b8d9ea68. Every round-2 finding is resolved. A programmatic check found that the test moves lost none of the 26 assertions. The remaining nits are about wording and saved logs, and both are fixed here and in NJ Child Tax Credit #1883.

Impact

A real microsimulation on the default dataset, main at the merge base c5837fb00b against this PR's head b8d9ea68ca, for 2024 and 2026 and 2029. The runs went one at a time under the shared heavy-job lock. Sums are weighted.

Output 2024 change 2026 change 2029 change 2024 records changed (weighted) 2026 records changed (weighted) 2029 records changed (weighted)
tip_income_deduction -15.06bn +0 -17.17bn 267 (1,497,114) 0 (0) 265 (1,524,242)
overtime_income_deduction -120.48bn +0 -141.85bn 9,955 (22,958,636) 0 (0) 9,798 (23,315,999)
sc_obbba_addback -2.52bn +0 -2.89bn 176 (529,438) 0 (0) 176 (545,828)
mt_federal_obbba_subtraction -489.87M +0 -603.77M 156 (93,607) 0 (0) 153 (95,563)
az_subtractions +0 +0 -4.57bn 0 (0) 0 (0) 210 (679,129)
taxable_income +0 +0 +0 0 (0) 0 (0) 0 (0)
state_income_tax +0 +0 +138.05M 0 (0) 0 (0) 329 (690,959)
income_tax +0 +0 +0 0 (0) 0 (0) 0 (0)
household_net_income +0 +0 -138.05M 0 (0) 0 (0) 308 (647,725)
household_benefits +0 +0 +0 0 (0) 0 (0) 0 (0)

Comparison files are in fixes/10397-impact/ on the hub host.

  • 2029, the year the fix bites: state income tax rises $138.05M, all in two states, and no record's tax falls. Federal income tax and taxable income don't change, because the federal lists already left these deductions out in 2029.
    • Arizona: +$108.00M across 172 households (561,565 weighted).
    • Montana: +$30.05M across 136 households (86,160 weighted).
    • South Carolina's add-back falls by $2.89bn with no tax effect, since its taxable income has started from federal AGI since 2026.
  • 2026: every output is unchanged. Listing both deductions in every year leaves the 2025-2028 window as it was.
  • 2024: the two variables no longer compute, but no state reads them before 2025, so no tax or net income changes.
  • The large drops in tip_income_deduction and overtime_income_deduction in 2024 and 2029 are amounts that were computed but never deducted federally.

Follow-up (not in this PR)

The senior deduction (151(d)(5)(C)) and the car loan interest deduction (163(h)(4)) leak the same way. additional_senior_deduction and auto_loan_interest_deduction keep computing after 2028, and three states read them:

  • SC, through sc_obbba_addback.
  • MT, through mt_federal_obbba_subtraction.
  • AZ, which lists additional_senior_deduction from 2026.

At this head, a single 67-year-old with $5,000 of car loan interest still gets, in 2029, an SC add-back of $11,800, an MT subtraction of $11,000 and an AZ subtraction of $6,000. A separate session has been proposed for it; the CRFB senior extension needs care there.

🤖 Generated with Claude Code

MaxGhenis and others added 3 commits October 22, 2026 21:22
26 U.S.C. 224(h) and 225(g) allow no deduction for any taxable year
beginning after December 31, 2028, and sections 70201(j) and 70202(g) of
Pub. L. 119-21 start both in 2025. The federal deduction lists already
dropped them from 2029, but tip_income_deduction and
overtime_income_deduction kept computing, and South Carolina's add-back,
Montana's Schedule 1-A subtraction and Arizona's 2026 subtraction list
read them directly. Each now gets zero outside 2025-2028.

Colorado's add-back (C.R.S. 39-22-104(3)(u)) has no end date and needed
a 2029 switch only because the federal variable leaked; the switch goes,
and its 2029 test now computes the deduction instead of entering it.
The reform-backdating test switches the tip deduction on for 2024 so its
leaked-cap guard still sees a nonzero deduction.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Over 2015-2035 the deductions are zero outside 2025-2028; with the year
switch forced on, every year gives the 2025 amount, so the switch is the
only change across years. South Carolina's add-back, Montana's Schedule
1-A subtraction and Arizona's subtractions move by exactly the federal
deductions in 2026-2028 and not at all from 2029.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ches taxable income

Review round 1 found that switching the new in_effect parameters on for
2029 revived the two variables but not the federal deduction, because the
federal lists dropped both at 2029; Colorado would then add back a
deduction never taken federally. Both lists, and the CRFB senior
deduction extension's 2029 lists, now name the two deductions in every
year, so the in_effect parameters are the only place the dates live.
Baseline results are unchanged: the variables are zero outside
2025-2028.

Tests: the federal years file asserts both lists in 2028, 2029 and under
the switch in 2029 and 2024; the 2030 itemizing case computes the two
deductions instead of entering them; Colorado Case 11 pins its add-back
without an end date.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis and others added 2 commits October 23, 2026 06:33
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- The two in_effect parameters cite the enrolled bill once each, with
  both pages in the title, as CLAUDE.md's one-entry-per-source rule asks.
- The year cases move into the variable-named files
  (tip_income_deduction.yaml, overtime_income_deduction.yaml, at the top,
  clear of #10396's appended cases), the list-level cases into the
  existing tip_and_overtime_income_deduction.yaml, and the Arizona cases
  into az_subtractions.yaml beside its variable.
- The property test draws once for its year check, so the switched-on
  reform builds one model: 41.8 s and 3.13 GB peak footprint locally,
  down from 64.5 s and 3.18 GB.
- The changelog says the lists now name both deductions in every year.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
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.

1 participant