Skip to content

Add back income excluded under sections 911, 931 and 933 in modified AGIs (student loan interest and 11 siblings) - #9817

Merged
MaxGhenis merged 9 commits into
mainfrom
fix-student-loan-magi-931-911
Oct 7, 2026
Merged

MaxGhenis merged 9 commits into
mainfrom
fix-student-loan-magi-931-911

Conversation

@MaxGhenis

@MaxGhenis MaxGhenis commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Summary

The student loan interest deduction phases out on a modified AGI that, by statute, adds back income excluded under 26 U.S.C. 911, 931 and 933. PolicyEngine-US got three parts of that definition wrong. Auditing the other modified AGIs turned up the same gap in eleven more places. Each now adds back what its statute says.

Every modified AGI adds back the full section 911 amount, Form 2555 lines 45 and 50, as the IRS worksheets do. The rate stacking of #9761 keeps its smaller amount. The clean vehicle credits apply their test over two years. IRMAA sums person-level amounts over the same members as AGI does after #9801.

Statute

26 U.S.C. 221(b)(2)(C) (current text, Cornell LII; same as the pinned Axiom corpus row us/statute/26/221/b/2):

The term "modified adjusted gross income" means adjusted gross income determined— (i) without regard to this section and sections 85(c) [sic, no comma] 911, 931, and 933, and (ii) after application of sections 86, 135, 137, 219, and 469.

The amendment notes give the history of clause (i):

Change Law Taxable years
"85(c)" inserted Pub. L. 117-2 §9042(b)(6) beginning after 2019
"222" struck Pub. L. 116-260 div. EE §104(b)(2)(G) beginning after 2020
"199" struck Pub. L. 115-97 §13305(b)(1) beginning after 2017
"199" inserted Pub. L. 108-357 beginning after 2004
"222" inserted Pub. L. 107-16 §431(c)(2) beginning after 2001

Clause (ii) lists no section 220.

The bug

student_loan_interest_ald_magi builds MAGI from gross income sources, less every above-the-line deduction not in excluded_alds. That list held only the deduction itself and puerto_rico_income (933). Three things followed:

  • Section 931. specified_possession_income is in gov.irs.ald.deductions, so it was subtracted. A bona fide resident of Guam, American Samoa or the Northern Mariana Islands had a lower MAGI than the law gives, and a larger deduction in the phase-out range.
  • Section 911. foreign_earned_income_exclusion is not an above-the-line deduction. The income inputs are already net of it: its documentation says "Other income inputs are the amounts left after the exclusion", and Tax Form 2555 filers' income at stacked rates (26 U.S.C. 911(f)) #9761 adds it back only for the 911(f) rate stacking. Student-loan MAGI therefore never contained the excluded income. Adding that input back would not be enough, either. Tax Form 2555 filers' income at stacked rates (26 U.S.C. 911(f)) #9761 defines it as line 2c of the Foreign Earned Income Tax Worksheet: Form 2555 lines 45 and 50, less "any itemized deductions or exclusions you couldn't claim because they are related to excluded income" (2025 Form 1040 instructions, p. 37). Every modified AGI worksheet adds lines 45 and 50 without that subtraction:
    • Schedule 8812 line 2b;
    • Schedule 1-A lines 2b and 2c;
    • Pub. 970 Worksheet 4-1 lines 5 and 6;
    • Form 8936 lines 1c and 1d;
    • Form 8962 Worksheet 1-1 line 3.
  • Section 85(c). excluded_gross_income_sources removed taxable_unemployment_compensation from MAGI in every year ("Unemployment compensation is not considered in MAGI"). Clause (i) says "without regard to section 85(c)", the 2020-only exclusion of up to $10,200. It does not remove unemployment compensation, and Pub. 970 (2024) Worksheet 4-1 starts from total income (Form 1040 line 9), which includes it. So all unemployment compensation counts, including the 2020 excluded part. The exclusion probably also side-stepped a cycle (taxable UC depends on AGI, which includes this deduction). Reading unemployment_compensation instead is cycle-free, and exact for every year the model supports (2015 on). It is not a claim about all years: TY2009, outside the supported range, had a separate $2,400 unemployment compensation exclusion.

The fix

Section 911 amount. New input section_911_excluded_income holds Form 2555 lines 45 and 50 (both spouses' forms on a joint return). Every modified AGI below adds back this amount. When not provided, it equals foreign_earned_income_exclusion, which is exact when no deductions are disallowed. foreign_earned_income_exclusion keeps #9761's meaning (worksheet line 2c), and the rate stacking still reads it. So does the default of #9808's niit_magi_section_911_addition, which follows section 1411(d)'s own definition.

Student-loan MAGI (student_loan_interest_ald_magi.py, excluded_alds.yaml):

  • §931: specified_possession_income joins excluded_alds.
  • §911: the formula adds section_911_excluded_income back, split between spouses like the tax unit's deductions.
  • §85(c): the formula reads unemployment_compensation in place of taxable_unemployment_compensation. excluded_gross_income_sources.yaml is removed; nothing else read it.
  • History: excluded_alds follows the amendments, with §222 (capped_qualified_tuition_expenses_ald) through 2020 and §199 (domestic_production_ald) for 2005–2017.

Shared modified AGI. New variable agi_plus_section_911_931_933_exclusions adds adjusted_gross_income, section_911_excluded_income, specified_possession_income and puerto_rico_income (Schedule 1-A line 3). Ten provisions define MAGI exactly this way, and each now reads it (table below). additional_senior_deduction_magi already computed this sum with foreign_earned_income_exclusion. It now reads the shared variable, so its results change only where section_911_excluded_income is provided and differs.

Clean vehicles, two years. Sections 30D(f)(10)(A) and 25E(b)(1) deny the credit only if the lesser of this year's and the preceding year's modified AGI exceeds the limit. The model had no prior-year input, so the add-back alone would deny buyers the statute admits. For example, in 2024 a single filer has AGI of $140,000 and a $20,000 section 911 exclusion, so modified AGI is $160,000, but their 2023 modified AGI was $130,000. Two new inputs, matching Form 8936 lines 4 and 5, carry the preceding year:

  • clean_vehicle_credit_prior_year_magi (default: this year's modified AGI, with the add-backs);
  • clean_vehicle_credit_prior_year_filing_status (default: this year's filing status).

Each year's modified AGI is compared with the limit for that year's filing status. That is the special rule of 26 CFR 1.30D-4(b)(3) and 1.25E-1(c)(3) for a change in filing status; with one status in both years it is the statute's lesser-of test. The prior-year input is a modified AGI, so the add-backs apply in both years.

Why default to the current year: policyengine-core carries inputs forward to later years and uprates them from earlier years, but never fills an earlier year from a later one (Simulation._calculate, auto_carry_over_input_variables). Reading period.last_year in a single-year household or microsimulation would see zero income and pass every buyer. With the defaults, the current year alone decides unless the preceding year is supplied. A buyer whose prior-year modified AGI qualifies is admitted once that amount is provided. Without it, a buyer pushed over the limit by the add-back is denied, as on main for any buyer over the limit; the dataset has no section 911, 931 or 933 income, so no record is affected.

Other MAGIs:

  • taxable_ss_magi adds back §911 (section_911_excluded_income).
  • medicare_irmaa_magi_two_years_prior adds back §§135, 911, 931 and 933, and sums person-level amounts over the same members as AGI does (next paragraph).
  • The Medicaid and ACA modified AGI (gov.hhs.medicaid.income.modification, read by medicaid_magi, medicaid_magi_person and aca_magi) lists section_911_excluded_income in place of foreign_earned_income_exclusion (Form 8962 Worksheet 1-1 line 3). Results change only where the new input is provided and differs.
  • niit_magi (§1411(d)) is Add the section 911(a)(1) exclusion to NIIT modified AGI (26 U.S.C. 1411(d)) #9808's, now merged; this PR does not touch it.

IRMAA and dependents. IRMAA reads the beneficiary's own return, joint with a spouse if any (42 U.S.C. 1395r(i)(4)). After #9801, AGI sums person-level deductions over the head and spouse, plus every member for amounts in gov.irs.ald.filer_amounts_recorded_on_dependents. The IRMAA add-backs now use that same rule (tax_unit_non_dep_add):

  • Tax-exempt interest: head and spouse only. A dependent's interest is on the dependent's own return, like the rest of the dependent's income, which irs_gross_income leaves off. Main summed it over every member. This changes main's behavior, for households whose lag-year return has a dependent with tax-exempt interest.
  • §135 (us_bonds_for_higher_ed): every member. Keep dependents' above-the-line deductions off the filer's AGI #9801 lists it in filer_amounts_recorded_on_dependents. A bond issued in the name of a child under 24 does not qualify (§135(c)(1)(B); Form 8815), so an amount recorded on a dependent is the parent's exclusion for the dependent's tuition, and AGI deducts it. An add-back over the head and spouse only would leave that deduction in place. A parent with $100,000 of wages and $1,000 recorded on the child has AGI of $99,000, and IRMAA MAGI would be $99,000 instead of $100,000. Reading the same parameter keeps the add-back equal to the deduction if the list changes.
  • 2015–2016 fallback (lag year before the model): the same rule, with the benefit year's roles, reading stored values only.

Audit of modified AGI definitions

I read each statute (Cornell LII, plus 42 U.S.C. 1395r for IRMAA) and each variable. Every "911" add-back below is Form 2555 lines 45 and 50.

Provision Statute's add-backs PE variable Before Now
Student loan interest, 221(b)(2)(C) 85(c), 911, 931, 933 (+199, 222 historically) student_loan_interest_ald_magi 933 only; 931 subtracted; UC dropped Fixed
CTC, 24(b)(1) (+2021 ARPA phase-out, Sch. 8812 line 3) 911, 931, 933 ctc_phase_out, ctc_arpa_uncapped_phase_out plain AGI Fixed
AOTC and LLC, 25A(d)(2) 911, 931, 933 education_credit_phase_out, lifetime_learning_credit_phase_out plain AGI Fixed
Saver's credit, 25B(e) 911, 931, 933 savers_credit_person plain AGI Fixed
Used clean vehicle, 25E(b) 911, 931, 933; lesser of two years used_clean_vehicle_credit_eligible plain AGI, current year Fixed
New clean vehicle, 30D(f)(10) 911, 931, 933; lesser of two years new_clean_vehicle_credit_eligible plain AGI, current year Fixed
Car loan interest, 163(h)(4)(C)(ii)(II) 911, 931, 933 auto_loan_interest_deduction plain AGI Fixed
SALT cap phase-down, 164(b)(7)(B)(iv) 911, 931, 933 salt_cap plain AGI Fixed
Tips, 224(b)(2)(B) 911, 931, 933 tip_income_deduction plain AGI Fixed
Overtime, 225(b)(2)(B) 911, 931, 933 overtime_income_deduction plain AGI Fixed
Senior deduction, 151(d)(5)(C)(iii)(II) 911, 931, 933 additional_senior_deduction_magi 911 net of disallowed deductions Reads shared variable
Taxable Social Security, 86(b)(2) 85(c), 135, 137, 221, 911, 931, 933, + tax-exempt interest taxable_ss_magi all but 911 Fixed (911)
NIIT, 1411(d) 911(a)(1), net of 911(d)(6) niit_magi — #9808 (merged)
Medicare IRMAA, 42 U.S.C. 1395r(i)(4)(A) 135, 911, 931, 933, + tax-exempt interest medicare_irmaa_magi_two_years_prior tax-exempt interest, every member Fixed (members as AGI)
PTC, Medicaid, CHIP: 36B(d)(2)(B) 911, + tax-exempt interest, nontaxable SS medicaid_magi, aca_magi 911 net of disallowed deductions Fixed (911 in full)
CDCC, 21(a)(2) none (plain AGI) cdcc_rate correct No change
Dependent care assistance, 129 no income test — — N/A
IRA deduction, 219(g)(3)(A) 85(c), 135, 137, 221, 911 — phase-out not modeled N/A
Roth IRA limit, 408A(c)(3) (uses 219(g)(3)) same — phase-out not modeled N/A
Adoption assistance, 137(b)(3) 85(c), 221, 911, 931, 933 qualified_adoption_assistance_expense (input) phase-out not modeled N/A
Savings bonds, 135(c)(4) 85(c), 137, 221, 911, 931, 933 us_bonds_for_higher_ed (input) phase-out not modeled N/A
Adoption credit, 23(b)(2)(B) 911, 931, 933 — not modeled N/A
Coverdell ESA, 530(c)(2) 911, 931, 933 — not modeled N/A
Tuition and fees (repealed 2021), 222(b)(2)(C) 199, 911, 931, 933 capped_qualified_tuition_expenses_ald no 911 Not changed (follow-up below)

Follow-ups found in the audit and left out of this PR:

  • The model does not apply 86(b)(2)'s historical 199 and 222 add-backs.
  • The pre-2021 222 MAGI has no 911 add-back.
  • tuition_and_fees_deduction is both an above-the-line and a below-the-line deduction in 2018–2019.
  • PE caps the 2020 85(c) exclusion at $10,200 per return, where the statute allows $10,200 per spouse.
  • 32(c)(1)(C) (Form 2555 filers cannot take the EITC) is not modeled; Deny the refundable CTC and the EITC to section 911 filers (26 U.S.C. 24(d)(3), 32(c)(1)(C), 6012(c)) #9750 (open) covers it.
  • Schedule 1-A floors the tip and overtime phase-outs to whole $1,000 steps; PE phases them out continuously.
  • The Form 2555 filer tests (ctc_credit_limit_worksheet_b_applies; the section 911(f) worksheet flags) check foreign_earned_income_exclusion > 0. A filer whose disallowed deductions use up the whole section 911 amount still files Form 2555, but with a zero stacking amount.
  • ma_gross_income subtracts foreign_earned_income_exclusion from federal gross income, which the input contract says is already net of it. I did not check this against Massachusetts law.

Invariants

These hold for every household:

  1. Accounting identity (differential). On every return, student-loan MAGI summed over the filers equals adjusted_gross_income + student_loan_interest_ald + the 911, 931 and 933 amounts + (unemployment compensation − taxable unemployment compensation). The two sides are built by different routes: sources with the excluded deductions left in, against gross income minus every deduction.
  2. agi_plus_section_911_931_933_exclusions = AGI + the three amounts, and additional_senior_deduction_magi equals it exactly. medicaid_magi = max(0, AGI + section_911_excluded_income) for these households.
  3. Two sizes of §911. The modified AGIs add Form 2555 lines 45 and 50; the rate stacking (taxable_income_plus_section_911_exclusion − taxable_income) adds foreign_earned_income_exclusion, the amount net of disallowed deductions.
  4. Clean vehicles. A buyer is income-eligible exactly when the lesser of this year's and the preceding year's modified AGI is within the limit, in the years the credit is in effect.
  5. Monotonicity at fixed AGI. Suppose income moves into an excluded category while every other part of AGI stays fixed: the 911 exclusion rises, the deductions it disallows rise, or wages and the 931/933 deduction rise together. Then:
    • student-loan MAGI and taxable_ss_magi rise by exactly the amount shifted;
    • the student loan interest deduction never rises;
    • no phase-out reduction falls (ctc_phase_out, education_credit_phase_out, lifetime_learning_credit_phase_out);
    • no deduction, cap or eligibility rises (tips, overtime, car loan interest, salt_cap, both clean vehicle eligibilities);
    • AGI moves only by the fall in the deduction and, in 2020, by any unemployment compensation that fall makes taxable.
  6. Bounds. 0 ≤ student loan interest deduction ≤ min(interest paid, $2,500).
  7. IRMAA identity. With lag-year AGI provided, IRMAA MAGI = AGI + the head's and spouse's tax-exempt interest + every member's §135 amount + the 911, 931 and 933 amounts. With AGI computed from wages, it does not depend on §135 amounts at all, wherever they are recorded. Both hold in modeled lag years and in the 2015–2016 fallback.

policyengine_us/tests/test_modified_agi_add_backs.py checks these with Hypothesis (10 random batches of up to 15 households for each property, over 2020, 2024, 2025 and 2026, and IRMAA benefit years 2016, 2017 and 2026), fixed grids of households in each phase-out range shifted into each category, and a 2020 85(c) case.

Review r1

An independent review of 361ccac6e1 requested changes. Each finding, how it is handled, and a mutation check: the defect reinserted into the fixed code, and the tests that then fail.

Finding Handling Mutation reinserted → tests that fail
1. §911 MAGI used the net stacking amount. AGI $180,000, Form 2555 $25,000, $10,000 disallowed: MAGI was $195,000 and the CTC phase-out $0; the worksheet gives $205,000 and $250. New input section_911_excluded_income (Form 2555 lines 45 and 50), used by the shared MAGI, student-loan, Social Security, IRMAA and Medicaid/ACA MAGIs. The reviewer's case is a YAML test (ctc_phase_out.yaml). Shared MAGI on the net amount → 3 YAML cases (CTC, shared MAGI, section_911_excluded_income) and the property grid. Student-loan MAGI → 2. Social Security MAGI → 1. IRMAA → 2 and the IRMAA property. Medicaid/ACA → 1. No default to the stacking amount → 4.
2. Clean vehicles denied buyers whose preceding-year MAGI qualifies. Two-year test with new prior-year MAGI and filing-status inputs (above). The reviewer's two TY2024 cases are YAML tests. Current year only (new) → 2 YAML cases and the property grid (2024). Current year only (used) → 2. Prior year tested against this year's status (new, used) → 2, 1. Prior-year default without the add-back → 3. Prior-year default of zero → 5.
3. IRMAA's §135 add-back included dependents. Supplied AGI $100,000 plus $1,000 recorded on a dependent gave $101,000. Not restricted to the head and spouse, and the reason is #9801, merged since. AGI deducts a §135 amount recorded on a dependent (filer_amounts_recorded_on_dependents: it is the parent's exclusion), so the add-back must cover it. Restricting it to the head and spouse gives $99,000 of IRMAA MAGI for $100,000 of wages. The reviewer's principle does apply to tax-exempt interest, which now counts for the head and spouse only. The $101,000 is right under this convention: the supplied AGI is net of the parent's $1,000 exclusion. Head and spouse only (r1's request) → 2 YAML cases ($99,000 for $100,000; $103,000 for $107,000).
4. Test counts described the pre-NIIT-revert head. Corrected below: at 361ccac6e1 the 18-file set was 121 cases, 29 failing and 92 passing on main, all 121 passing on the branch. —

The mutation checks found one gap, now closed. The property tests missed the current-year-only new-vehicle test, because no grid household was over the new-vehicle limit in the current year only. A grid household now buys a vehicle with a prior-year MAGI of $140,000, and the grid catches the mutation.

Tests: before and after

At 361ccac6e1 (review r1 reran this): the 18 YAML files the PR changed held 121 cases. On main (d7a526fbe2), 29 failed and 92 passed; on the branch all 121 passed. The earlier description said 30 failed; that count included the NIIT case dropped when #9808 took NIIT. On main, test_modified_agi_add_backs.py failed 6 of 6 (the shared variable didn't exist), and the student-loan-only invariants failed 4 of 4.

At approved head ae35fea93b. The PR's own diff contains 20 YAML files and 141 cases. The 22-file regression set additionally includes unchanged NIIT and senior-MAGI files. Local verification during that round was limited: the machine ran out of memory during the round (swap 34.8 of 35.8 GB used, load average 100–500), and test processes stalled for tens of minutes. What ran:

  • The mutation checks above, on the round-2 code before the merge. Each mutation made at least one test fail.
  • After the merge, on the final IRMAA code: medicare_irmaa_magi_two_years_prior.yaml, 16 passed; the IRMAA property tests (provided AGI, computed AGI, grid), 7 passed.
  • Formatting: ruff format --check and ruff check pass on every changed Python file.

Not rerun locally on this head: the full 22-file set against the branch and main, the other property tests, and the folder runs. CI's full suite on this head is the check for those.

CI follow-up (5669235456). The original Form 4952/§911 test_grid failed locally with AssertionError: more_excluded. Its fixed-taxable-income premise did not account for the SALT MAGI add-back required by §164(b)(7)(B)(iv) and the 2025 Schedule A worksheet, page 7. The corrected property retains equality for election changes and unchanged deductions, asserts nondecreasing taxable income for same-choice exclusion pairs, and reuses the existing grid simulation for two hand-calculated SALT cases and independent form comparisons. The complete interaction file passes all 5 tests; make format passes formatting and lint. No production formulas changed, so no microsimulation variables need rerunning.

Local macOS/Python 3.13 measurements, including setup: the original grid-only failure took 306 seconds (peak memory unavailable because the sandbox denied the platform resource query); the corrected five-test file took 167 seconds with 2.10 GiB peak RSS. These are different selections and cold-start conditions, not a causal runtime comparison. Existing Linux CI reported 18:05 and 10.09 GiB peak RSS for the affected Rest Python subgroup; current-head CI is pending. The two new households add ten variant tax units to the reused grid, with no new simulation construction or CI job.

Merging main

main (at bab1a47c60) is merged in with a merge commit; no force-push.

Impact

Exact-head run: the hub compared merge base bab1a47c60 against approved head ae35fea93b for 2024 and 2026 using the default dataset, with real microsimulation outputs compared record by record. Dollar figures are weighted totals; weighted counts describe changed records.

Weighted change from base (exact head) 2024 2026
student_loan_interest_ald_magi (summed over people) +$32.6bn (2,917 records) +$40.9bn (2,917 records)
student_loan_interest_ald −$1.07M (13 records, 5.9k weighted) −$0.40M (12 records, 1.0k weighted)
adjusted_gross_income and medicaid_magi +$1.07M each +$0.40M each
income_tax +$0.24M +$0.09M
medicare_irmaa_magi_two_years_prior $0 −$0.15M (20 records, 9.5k weighted)

CTC, taxable Social Security, NIIT, Part B premium and new/used clean vehicle credits change by $0 in both years. foreign_earned_income_exclusion, specified_possession_income and puerto_rico_income are $0 on every record, so the §911/931/933 add-backs themselves move no outputs in this dataset. The student-loan deduction change comes from counting unemployment compensation in full. The 2026 IRMAA change reflects the dependent tax-exempt-interest correction.

section_911_excluded_income, agi_plus_section_911_931_933_exclusions and clean_vehicle_credit_prior_year_magi are new on this branch and have no base comparator; their missing comparison entries do not mean a measured $0 change.

axiom: TheAxiomFoundation/rulespec-us#1496 queued (§221(b)(2)); TheAxiomFoundation/rulespec-us#1500 queued (§§30D(f)(10), 25E(b))

🤖 Generated with Claude Code

MaxGhenis and others added 4 commits October 5, 2026 16:22
Section 221(b)(2)(C) defines modified AGI as adjusted gross income
determined "(i) without regard to this section and sections 85(c), 911,
931, and 933, and (ii) after application of sections 86, 135, 137, 219,
and 469". The model got three parts wrong:

- Section 931 (specified_possession_income) was subtracted like any other
  above-the-line deduction. It is now in excluded_alds with section 933.
- Section 911: income inputs are net of foreign_earned_income_exclusion,
  and nothing added it back. The formula now adds it, split between
  spouses like the tax unit's deductions.
- Unemployment compensation was dropped entirely (excluded_gross_income_
  sources), a misreading of "without regard to section 85(c)": only the
  2020 exclusion is disregarded, so all of it counts. The formula reads
  the untaxed amount, which also avoids the cycle through AGI that the
  old exclusion side-stepped. The parameter is removed.

excluded_alds also follows the amendment history: section 222 until 2020
(Pub. L. 116-260) and section 199 from 2005 through 2017 (Pub. L.
108-357, Pub. L. 115-97).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ten provisions phase out on "adjusted gross income increased by any
amount excluded from gross income under section 911, 931, or 933":
24(b)(1) (CTC, and the 2021 ARPA phase-out through Schedule 8812 line 3),
25A(d)(2) (education credits), 25B(e) (saver's credit), 25E(b)(3) and
30D(f)(10)(C) (clean vehicle credits), 151(d)(5)(C) (senior deduction),
163(h)(4)(C) (car loan interest), 164(b)(7)(B) (SALT cap), 224(b)(2)(B)
(tips) and 225(b)(2)(B) (overtime). Only the senior deduction added the
exclusions back; the rest read plain AGI.

agi_plus_section_911_931_933_exclusions computes the amount once
(Schedule 1-A line 3), and every one of them reads it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Taxable Social Security, 26 U.S.C. 86(b)(2)(A): determined without
  regard to section 911. The revoked-deductions list already covered
  sections 931 and 933; the 911 exclusion is netted out of the income
  inputs, so taxable_ss_magi adds it back.
- Net investment income tax, 26 U.S.C. 1411(d): adds back the section
  911(a)(1) exclusion (Form 8960 line 13 worksheet). The model's one
  exclusion input also holds the housing amounts, which the worksheet
  leaves out; niit_magi documents that.
- Medicare IRMAA, 42 U.S.C. 1395r(i)(4)(A): determined without regard to
  IRC sections 135, 911, 931 and 933, plus tax-exempt interest. All four
  are added back, for both the modeled and the provided lag years.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Differential: on every return, student-loan MAGI (built from gross income
sources) equals AGI plus the student loan interest deduction, the section
911, 931 and 933 amounts and any unemployment compensation section 85(c)
excluded; the shared modified AGI equals AGI plus the three amounts.

Shifting income into an excluded category at otherwise fixed AGI raises
student-loan MAGI and taxable_ss_magi by exactly the amount shifted,
never raises the student loan interest deduction, and moves every phase-
out the shared modified AGI feeds in one direction only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#9808 adds the section 1411(d) add-back with a
separate, overridable section 911(a)(1) amount, which is more precise than
adding the whole foreign_earned_income_exclusion input. Restore niit_magi
and its tests to main and drop the NIIT assertion from the property test.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis and others added 3 commits October 6, 2026 05:48
… 135

- Modified AGIs add back section 911 in full: Form 2555 lines 45 and 50
  (Schedule 8812 line 2b, Schedule 1-A lines 2b and 2c, Pub. 970
  Worksheet 4-1, Form 8936 lines 1c and 1d, Form 8962 Worksheet 1-1
  line 3). New input section_911_excluded_income carries that amount; it
  defaults to foreign_earned_income_exclusion, which stays the section
  911(f) stacking amount net of disallowed deductions. The shared modified
  AGI, student-loan MAGI, Social Security MAGI, IRMAA MAGI and the
  Medicaid/ACA modification list use it.
- Clean vehicles: 30D(f)(10) and 25E(b) allow the credit when the lesser
  of this year's and the preceding year's modified AGI is within the
  limit. New inputs clean_vehicle_credit_prior_year_magi (defaults to this
  year's modified AGI) and clean_vehicle_credit_prior_year_filing_status
  (defaults to this year's status); each year is tested against its own
  status's limit (26 CFR 1.30D-4(b)(3), 1.25E-1(c)(3)).
- IRMAA keeps adding back the section 135 exclusion wherever it is
  recorded, because AGI deducts it there: a bond in a child's name does
  not qualify (135(c)(1)(B), Form 8815), so an amount on a dependent is
  the filer's. A filer-only add-back would leave the dependent-recorded
  deduction in AGI and give 99,000 for 100,000 of wages.
- Tests: the reviewer's reproductions as YAML cases, Hypothesis
  invariants for the gross and net section 911 amounts, the lesser-of
  test and the IRMAA identity on provided and computed AGI.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Conflicts resolved keeping both sides:
- student_loan_interest_ald_magi: #9801's tax_unit_non_dep_add (with
  filer_amounts_recorded_on_dependents) for the tax unit deduction sum,
  and this branch's section_911_excluded_income add-back.
- foreign_earned_income_exclusion documentation: both notes (modified
  AGIs add back section_911_excluded_income; NIIT adds back only the
  section 911(a)(1) part, niit_magi_section_911_addition).

taxable_ss_magi and test_ald_determinism merged cleanly with both changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
42 U.S.C. 1395r(i)(4) reads the beneficiary's own return. After #9801,
adjusted gross income sums person-level deductions over the head and
spouse, plus every member for gov.irs.ald.filer_amounts_recorded_on_
dependents. The IRMAA MAGI now sums its person-level add-backs with the
same rule (tax_unit_non_dep_add):

- Tax-exempt interest counts for the head and spouse only. A dependent's
  interest is on the dependent's own return, like the rest of the
  dependent's income; main summed it over every member.
- The section 135 exclusion counts for every member, because #9801 lists
  it: a bond in a child's name does not qualify (135(c)(1)(B), Form
  8815), so an amount recorded on a dependent is the parent's exclusion,
  and AGI deducts it. Head and spouse only would give 99,000 for a parent
  with 100,000 of wages and 1,000 recorded on the child.
- The 2015-2016 fallback applies the same rule with the benefit year's
  roles, reading stored values only.

Tests: YAML cases for a dependent's tax-exempt interest in a modeled and
an unmodeled lag year; the Hypothesis IRMAA identity now draws spouse and
dependent tax-exempt interest and sets lag-year ages in both paths (age
defaults to 40, which would make a child a second adult).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Section 164(b)(7)(B)(iv) and the 2025 Schedule A worksheet add Form 2555 lines 45 and 50 to SALT MAGI. An exclusion can reduce itemized deductions even when the choice to itemize holds, so fixed taxable income was an invalid premise.

Preserve equality for election changes and unchanged deductions, assert nondecreasing taxable income for same-choice exclusion pairs, and reuse the grid simulation for a hand-calculated SALT regression and independent form comparisons. Production formulas are unchanged.
@MaxGhenis
MaxGhenis merged commit 07227ea into main Oct 7, 2026
35 checks passed
@MaxGhenis

Copy link
Copy Markdown
Contributor Author

US + core hub merge audit, us#9817 at 5669235456ee479c1d994f85f70c2830a899559a (squash)

  • Reviews:

    • Independent review (Subfleet) APPROVE at ae35fea: all four r1 findings fixed. The IRMAA handling of §135 and dependent interest is correct under 42 U.S.C. 1395r(i)(4); it is not a methodology choice.
    • Delta review APPROVE at 5669235: the corrected test_form_4952_section_911_interaction property is right. Under the 2025 Schedule A worksheet, §911 income is added to MAGI before the SALT phase-down, so it can raise taxable income. The reviewer's hand calculation: SALT cap $40,000 → $16,000 on +$100,000 of §911 income.
  • Gates checked live at merge:

    • gh pr checks exits 0;
    • MERGEABLE;
    • not a draft;
    • no CHANGES_REQUESTED review;
    • head pinned with --match-head-commit.
  • Impact: an exact-head microsim, base bab1a47c60 against ae35fea93b, on the default dataset. The later commits change tests only.

    2024 2026
    Student-loan interest deduction −$1.07M −$0.40M
    AGI and Medicaid MAGI +$1.07M +$0.40M
    Income tax +$0.24M +$0.09M
    IRMAA lag MAGI $0 −$0.15M

    CTC, taxable Social Security, NIIT, Part B premiums and clean vehicle credits are unchanged.

  • Follow-up: a pre-existing MFS SALT-cap phase-down bug (salt_cap.py:21, outside this PR) is chipped separately.

  • --admin: used only because a required approving review is the sole block.

@MaxGhenis
MaxGhenis deleted the fix-student-loan-magi-931-911 branch October 7, 2026 14:33
MaxGhenis added a commit that referenced this pull request Oct 7, 2026
Resolve salt_cap.py by keeping #9817's 164(b)(7)(B)(iv) modified AGI and
applying the separate-filer fraction to the reduction it produces.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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