Skip to content

Count passive estate and trust income in the EITC investment income test - #10194

Open
MaxGhenis wants to merge 4 commits into
mainfrom
fix/eitc-investment-income-estate-trust
Open

MaxGhenis wants to merge 4 commits into
mainfrom
fix/eitc-investment-income-estate-trust

Conversation

@MaxGhenis

@MaxGhenis MaxGhenis commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

What changes

The EITC investment income test now counts passive income and losses from estates and trusts. eitc_relevant_investment_income nets a new person-level input, passive_estate_income, with rental, farm rental and passive partnership and S corporation income in the passive basket (Publication 596 Worksheet 1 lines 11–13). It sums the head's and spouse's amounts and floors the total at zero. A passive estate or trust loss therefore offsets other passive income, but never interest, dividends or capital gains.

passive_estate_income is the section 469 passive subset of estate_income: Schedule E Part III line 34a column (d) less line 34b column (c). It defaults to zero, like passive_partnership_s_corp_income. estate_income itself (the Part III total in AGI since #9633) is unchanged.

Part of #9635, which listed this as a known gap: "Passive estate and trust income or loss (Schedule E lines 34a/34b) is not in the basket."

What the sources say

  • 26 U.S.C. 32(i)(2)(E) counts "the aggregate income from all passive activities" over "the aggregate losses from all passive activities". Its last sentence gives "passive activity" "the meaning given such term by section 469".
  • Publication 596 (2024) Worksheet 1, PDF page 6. Line 11 counts "net income from passive activities (such as income included on Schedule E, line 26, 29a (col. (h)), 34a (col. (d)), or 40 …)". Line 12 counts the matching losses "(… 34b (col. (c)) …)". Line 13 combines them; "If the result is less than zero, enter -0-". The 2018–2025 worksheets cite the same Part III columns.
  • 2024 Schedule E, page 2. Part III has passive columns (c) "Passive deduction or loss allowed" and (d) "Passive income from Schedule K-1". Its nonpassive columns are (e) and (f). Line 37 nets all four.
  • 2024 Schedule K-1 (Form 1041) and its instructions, page 2. Box 5 is "royalties, annuities, and other income that isn't subject to the passive activity rules", including income in respect of a decedent, and goes to column (f). Boxes 6–8 (business, rental real estate, other rental) go to column (d) or (f).

So only columns (d) and (c) belong in the passive basket, not the Part III total.

Why the passive part defaults to zero

estate_income has no passive split, so I needed a default. Most Part III income is nonpassive. SOI Publication 4801 (Rev. 6-2026, tax year 2023, PDF page 50) shows column (d) passive income of $19.0 billion against column (f) nonpassive income of $31.1 billion. That puts 37.9% of positive Part III income in the passive column. On page 49, 277,770 returns report passive income and 451,903 report nonpassive income.

Treating all of estate_income as passive, as the model does for its undifferentiated rental income, would therefore overstate disqualified income for most beneficiaries. That would wrongly deny the credit to someone whose trust income is an annuity or an inherited IRA's distribution. The worksheet itself also starts from the passive columns. So passive_estate_income defaults to zero, and the data layer can impute the split (a follow-up is proposed).

I first tried a formula default (all of estate_income, overridable). The differential test showed it is unsafe in policyengine-core. Once any person in a simulation sets the input, every person who left it unset gets default_value (0), not the formula. That includes people in other households. simulation_builder.py fills a whole-population default array and sets it as input. A pure input with default zero has no such trap. estate_income_niit_magi_adjustment has the same latent problem; a separate fix is proposed.

Tests

  • YAML cases. eitc_investment_income_estate_trust.yaml has 17 hand-computed cases at the 2024 $11,600 limit:

    • the exact boundary and $1 over;
    • netting against rental and passive partnership losses;
    • the floor;
    • no offset against interest or capital gains;
    • only the entered passive part counting;
    • estate income with no passive part entered;
    • spousal netting;
    • a mixed couple where only one spouse enters the input;
    • dependents' amounts staying off the filer's test;
    • end to end, the credit at the limit, $1 over, and with all-nonpassive income.

    On main's formula, 10 cases fail (each carries a "Before" note) and 7 pass.

  • Differential test. test_dependent_eitc_investment_income_invariants.py now covers estate and trust income. Its Hypothesis batches and seeded 200-unit population draw estate_income and passive_estate_income for filers and dependents. The passive amount is unset, all, half or none of the estate amount, or an unrelated signed amount, so each simulation mixes people who set the input with people who don't. Each tax unit's result must equal an independent numpy computation of Worksheet 1 over the head and spouse. The seeded population has 8 (2021) and 4 (2025) units whose eligibility turns on the passive estate amount. A new bound checks that no passive loss reaches the interest or capital gain baskets.

  • Mutation checks. On the YAML and the differential, the tests catch each of these:

    • reading all of estate_income as passive;
    • flooring the estate amount separately;
    • adding it outside the floor;
    • counting dependents' amounts.
  • Other suites. The surrounding EITC and income YAML suites pass (660 cases).

Invariants

These hold for every tax unit. The extended differential checks each one on every drawn unit, because it asserts the exact Worksheet 1 value. The YAML cases pin the legal mapping by hand, and they also check the AGI half of invariant 1, which the differential doesn't assert.

  1. Only the passive subset counts. estate_income moves AGI, but only passive_estate_income moves the test.
  2. The test is monotone and 1-Lipschitz in passive estate income.
  3. Baskets stay isolated. Investment income is never below the filers' interest and dividends plus their capital gains floored at zero. This one is asserted directly.
  4. Unset means zero for each person, even when others in the simulation set the input.
  5. A dependent's estate and trust income never changes the filer's test, credit or AGI. This one is asserted directly.
  6. Differential: the result equals the Worksheet 1 computation.

CI cost

The only Python test change extends tests/core/test_dependent_eitc_investment_income_invariants.py, in the Rest core group. I measured it locally on macOS at a load average of about 20–30, so these aren't Linux CI numbers:

Version Test time Wall time with import Peak RSS
Main 5.8–8.8 s 23–28 s 1.11 GB
This PR 5.7–6.9 s 23–24 s 1.11–1.12 GB

The draws only add inputs to the same simulations, so the change is not measurable. I dropped a separate invariants file I had first written, because the differential already implies its properties (repo CLAUDE.md, "Test design and CI cost").

Impact

There's no change in microsimulation aggregates. This is deduced, not run: passive_estate_income is new, defaults to zero, and no Microcosm dataset carries it (git grep passive_estate on microcosm main finds nothing). Household results change only when a user enters it. When one does, the change reaches every credit that reads eitc_relevant_investment_income or eitc_investment_income_eligible, whether directly or through the federal EITC. Direct readers include:

  • the CA, DC, IN, MD, ME, MN, MO, NJ, NM, OK, WA and WI credits;
  • the NYC income tax elimination credit;
  • the shared calculate_eitc_like_amount helper;
  • the MT HB 268 and NY WFTC reforms.

Not in scope

Schedule K-1 box 5 royalties in Schedule E Part III column (f) are "rents or royalties" under 32(i)(2)(C) as the statute is written. Worksheet 1 line 8 reads only Part I royalties (line 23b), and the model has no separate lines 8–10 basket. This predates this PR.

Also

The 2024 Rev. Proc. 2023-34 links in max_investment_income.yaml, max.yaml and phase_out/start.yaml pointed to PDF page 10. The 2024 EITC table and the $11,600 limit (§3.06) are on page 9.

axiom: rulespec-us#1416 queued (extended with the estate and trust scope, a review_finding addendum and companion cases T1–T7: TheAxiomFoundation/rulespec-us#1416 (comment))

🤖 Generated with Claude Code

MaxGhenis and others added 4 commits October 12, 2026 23:49
Publication 596 Worksheet 1 lines 11 and 12 name Schedule E line 34a
column (d) and line 34b column (c), the passive income and loss from
estates and trusts, and line 13 nets them with the other passive
activities before the zero floor. The passive basket left them out.

Add passive_estate_income, the section 469 passive part of estate_income,
defaulting to all of it as the model treats its undifferentiated rental
income, and net it in the passive basket over the head and spouse.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
SOI Publication 4801 (tax year 2023) puts 38% of positive Schedule E
Part III income in the passive column (d), so most estate and trust
income is nonpassive and estate_income alone does not establish passive
income. Make passive_estate_income a pure input defaulting to zero, like
passive_partnership_s_corp_income. A formula default also misbehaved in
core: once any member set the input, every member who left it unset got
zero rather than the formula.

Add YAML cases at the 2024 $11,600 boundary, a property-based test of
the estate-specific invariants, and estate income in the Worksheet 1
differential test.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The 2024 EITC table and the $11,600 investment income limit (section
3.06) are on PDF page 9 of Rev. Proc. 2023-34, not page 10.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- passive_estate_income: column (c) also takes box 9 deductions, box 5
  goes only to column (f), and cite the Schedule K-1 (Form 1041) form page
  that maps boxes to columns.
- estate_income: point to passive_estate_income for the passive part.
- YAML: add the missing "Before" notes.
- Drop the separate invariants file, which the extended Worksheet 1
  differential already implies, per the repo's CI cost rule; keep its
  basket-isolation assertion in the differential test.

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

Copy link
Copy Markdown
Contributor Author

Hand-off to the US + core hub

  • Head: 500679c7471f91369176f0d5154a9bee48f562c6
  • Independent review: APPROVE, twice (both Opus 5.5 on Subfleet; no Codex lane was free).
    • Full review of f3546b1fd6: ~/reviews/eitc-estate-trust-2026-10-12/review/out.md. It re-derived all 17 YAML values, reran the mutation checks, and verified Pub 596, Schedule E, the K-1, Pub 4801 and Rev. Proc. 2023-34.
    • Delta review of the fix commit 500679c747, run read-only during the disk pause: ~/reviews/eitc-estate-trust-2026-10-12/review/delta-out.md. It found only low nits. The PR-text nits are fixed in the body. An optional "allowed" wording nit in passive_estate_income.py was left, because its definition line already says "allowed".
  • Source check: an independent research run, ~/reviews/eitc-estate-trust-2026-10-12/research/report-files/report.md.
  • CI at hand-off:
    • Passed: PR validation, Quick Feedback, Package and compatibility, Household API Partners.
    • Pending: the full Baseline, Contrib, Microsimulation and Rest suites.
  • Local runs at this head:
    • the new YAML file: 17 passed;
    • the extended differential test: 3 passed;
    • the EITC and income YAML suites (at the previous head, which differs only in docs and tests): 660 passed.
  • Merge: the PR needs only green CI and a merge. Branch protection asks for an approving review that only Max could give, so per ~/.claude/CLAUDE.md it can land with gh pr merge 10194 --squash --admin --match-head-commit 500679c7471f91369176f0d5154a9bee48f562c6 once every check passes. There is no dependency on other PRs and no Max decision.
  • Axiom: queued on rulespec-us#1416 (Encode IRC §32(i)(2) disqualified income; replace the opaque eitc_relevant_investment_income input TheAxiomFoundation/rulespec-us#1416 (comment)).
  • Follow-ups (proposed sessions, not part of this PR):
    • fix the core partial-input zeroing in formula-default inputs such as estate_income_niit_magi_adjustment;
    • impute passive_estate_income in Microcosm from SOI Publication 4801.

🤖 Generated with Claude Code

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