Repository navigation
Count car loan interest on the return of the taxpayer who incurred it - #10406
Merged
Merged
Conversation
26 U.S.C. 163(h)(4)(B)(i) counts interest on indebtedness incurred by the taxpayer, and 26 CFR 1.163-16(h)(1) applies the $10,000 limit per return. The household-level input was split across a household's tax units by head count (core's group-to-group add()), so roommates and adult children each deducted a share of one loan's interest. Add a person-level input for each filer's own loans (head and spouse count; a dependent's loans do not), and give a household-level amount in full to the household head's tax unit (oldest member when no head is designated). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Multi-tax-unit households, each filer's own loans, a dependent's loan, the per-return limit, several or no flagged heads, and 26 CFR 1.163-16(h)(3) Examples 1 and 2; Indiana follows the federal deduction. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Conservation of the household total, one holder per household amount, locality across tax units, and a differential against the statute's limit and phase-out. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ions Test an adult dependent's own loan and the oldest-member fallback when the oldest member is a dependent, and draw adult dependents in the property tests. Document the several-heads and dependent-head rules on the household input, cite the payor statement legend (91 FR 57243) and point Cornell at 163(h)(4)(B)(i). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis
marked this pull request as ready for review
October 23, 2026 14:51
Keeps auto_loan_interest_deduction.yaml as on main, so this PR no longer conflicts with #10395, which appends cases to that file. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…aper locality check Cover married people filing separately in YAML and in the property generator, keep one Federal Register reference per variable with the pages in a comment, and reuse the first simulation in the locality check so each property example builds two simulations instead of three. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
So the case also fails a first-listed-member fallback, which only the property tests caught. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
Author
|
Merge audit. GitHub still requires one approving review, which no one on this PR can give, so this merge uses
|
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.
Status: GPT-6.1 Sol approved
b611bfefwith one documentation nit, the cost report (now below); the Opus 5.5 review approved an earlier head. That head includes main atf679eedd57, and all 33 CI checks pass at it. The impact below runs on that merged base for both years.Problem
qualified_passenger_vehicle_loan_interestis a Household input, andauto_loan_interest_deductionread it withadd(tax_unit, period, [...]). For a group-to-group add, policyengine-core (commons/formulas.py,for_each_variable, 3.33.12) does three things:So a household's car loan interest was split across its tax units by member count. On main:
This only arises in households with more than one tax unit. On the default dataset those hold 31.3% of the $12.16bn of weighted 2024 input, and $1.64bn of it was split to tax units other than the household head's.
The law ties the interest to the borrower:
Splitting one loan over several returns also multiplied the per-return limit.
Fix
qualified_passenger_vehicle_loan_interest_person: interest on loans the person incurred. It counts on the return of the tax unit the person heads or is the spouse in. A tax-unit dependent's own loans don't reach the filer's return.tax_unit_qualified_passenger_vehicle_loan_interest: the head's and spouse's own interest, plus the household-level amount in full for the one tax unit holding the household head. When nobody carries the head flag (API, YAML), that is the oldest member; with several flagged heads, the oldest flagged one; ties go to the first listed (get_rank, as inis_hud_dependent).auto_loan_interest_deductionreads the new variable. The limit and the phase-out don't change.Why the household head
The data can't say who took out the loan. Microcosm draws the household amount from the 2022 SCF, whose debts belong to the "primary economic unit": "an economically dominant single individual or couple ... and all other individuals in the household who are financially interdependent with that individual or couple" (2022 SCF codebook, "Unit of analysis"). It then scales by Treasury's six million qualifying loans a year.
The household head is the CPS householder, "the person (or one of the people) in whose name the housing unit is owned or rented". It is the model's closest observed stand-in for that economic unit. The default build sets exactly one head per household, and 98.9% are CPS line 1. The same Microcosm SCF stage also names it as the carrier of its household asset draws:
head_carry, conditionis_household_head, inus/source_stages.json.Microcosm picks the person whose traits drive the imputation by its own rule: the one adult, the man of a married couple, otherwise the oldest adult. In multi-tax-unit households with this interest, that person is in the head's tax unit in 70.5% of records; aligning the two is a data follow-up, noted on PolicyEngine/microcosm#1215.
us-hub/source-conflicts/RULINGS.mdlogs the ruling (us:car-loan-interest-household-attribution).Invariants
These hold for every household. Hypothesis and seeded mixed batches test them in
tests/core/test_auto_loan_interest_attribution_invariants.py:max(min(interest, 10,000) − 200 × ceil(max(MAGI − threshold, 0) / 1,000), 0), with a $200,000 threshold for a joint return and $100,000 otherwise. The test computes it from the statute's numbers.0 ≤ deduction ≤ min(tax unit interest, 10,000).The tests mix households with and without flagged heads (the fallback runs beside flagged ones), include ties, adult dependents and married people filing separately, and list people out of household order. Eight mutants each fail the property tests and at least one YAML case (
mutants/results-r4.txt, run in a scratch copy of the merged tree, where the unmutated code passes all of them):The round-1 review found that the oldest-filer and every-adult mutants survived, and the Sol review that nothing covered separate filers. The tests now catch all three.
Tests
tax_unit_qualified_passenger_vehicle_loan_interest.yaml(15 cases):in_auto_loan_interest_deduction.yaml: Indiana follows the federal deduction to the head's return.Revert check: with main's
add()deduction formula over the rest of this PR, 13 of the new cases fail: 12 of the 15 here, plus Indiana's (revert-check/old-formula-r3.txt). The 3 that still pass read only the new tax-unit variable (several flagged heads; a head claimed as a dependent) or cover one tax unit, which doesn't change.Test cost: the new Python file builds no dataset; each Hypothesis example builds two small simulations. It joins the existing Rest Python
coregroup (processcore-2, shard 2); this PR adds no job or matrix entry.b611bfef: 8.96 s of test time across its 4 tests, in a process that ran 504 tests in 1,077 s. CI doesn't report this group's peak memory, so this PR states none.Other checks at
b611bfef: the full suite passes in CI on core 3.34.2. The separate affected-file batch passed its first 6 of 26 targets atafc7741f; I stopped it there because that CI run covers the rest.Consumers
in_auto_loan_interest_deduction), South Carolina (sc_obbba_addback), Montana (mt_federal_obbba_subtraction), and the Idaho and Arizona subtraction lists read the federalauto_loan_interest_deductionper tax unit, so they follow the fix unchanged.Impact
This is a real microsimulation on the default dataset (
populace_us_2024, sha6496cc43…). It compares main at the merge basef679eedd57with this PR atafc7741f8b, for 2025 and 2026. The runs went one at a time under the hub heavy lock. The final headb611bfefdiffers fromafc7741f8bonly by the order of one test YAML's cases. All sums use the dataset's weights.auto_loan_interest_deduction(baseline $10.72bn; $10.84bn)taxable_incomeincome_taxstate_income_taxhousehold_net_incomehousehold_benefitsWhy the total deduction falls. The interest total doesn't change: every household amount still lands on exactly one return. The largest household amount in the data is $2,456, so the $10,000 limit never binds. The whole net fall therefore comes from the phase-out: more of the moved interest now sits on returns whose MAGI exceeds the $100,000 or $200,000 threshold.
Why federal income tax falls even though the deduction falls.
taxable_incomefloors at zero (max_(0, agi - exemptions - deductions)). So the $1,566M of deduction taken off other returns raises taxable income by only $1,103M in all, and the $1,448M added to the holders lowers it by $1,101M.States. State income tax moves mostly in Colorado (+$647K in 2025, +$648K in 2026), which starts from federal taxable income. Arizona is +$152K in 2025, when it subtracts the deduction. Indiana is −$108K in 2026, the year
in_deductionslists its conformity deduction. Idaho is −$87K/−$89K. Every other state's change is under $70K. South Carolina's add-back falls $1.5M, but SC tax barely moves. Montana's subtraction moves less than $100 in total; it shifts between people.Comparison files are in
fixes/10406-impact/on the hub host (compare.<year>.json,by_state.<year>.json), with copies in the evidence folder~/reviews/auto-loan-attribution-2026-10-23/impact/r2/.Axiom
axiom: us:statutes/26/163/h/4/B encoded-correct
main(fa888658),interest_is_qualified_passenger_vehicle_loan_interest(Payment) conjoinsindebtedness_incurred_by_taxpayer_after_statutory_start_datewith the other conditions.us/statutes/26/163/h/4/C.yamlapplies the $10,000 limit to the per-return amount (TaxUnit).axiom-encode teston the pinned engine (89571cc2):not_holds(8 of 8 cases pass inB.test.yaml);C.test.yaml).pe-parity) queues the cases verbatim.🤖 Generated with Claude Code