Skip to content

Exclude dependents from Schedule D specialty capital gain worksheets - #9988

Merged
MaxGhenis merged 3 commits into
mainfrom
exclude-dependents-28-percent-rate-gain
Oct 7, 2026
Merged

MaxGhenis merged 3 commits into
mainfrom
exclude-dependents-28-percent-rate-gain

Conversation

@MaxGhenis

@MaxGhenis MaxGhenis commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

What and why

Exclude dependents from every person-level aggregation in capital_gains_28_percent_rate_gain.py, including reported Schedule D line 18 inputs and the shared gains-minus-losses helper. This ports only that formula change and its comment from a0d4dce2e4fcc149da257978e643f1a32061d5f8 in #9977; the §163(d) cap and its dataset dependency remain with #9977.

The 2025 Schedule D instructions, 28% Rate Gain Worksheet, page 11, lines 1–7, use amounts on the filer's forms. Dependents' gains and losses belong on their own returns. The Unrecaptured Section 1250 Gain Worksheet, page 13, lines 14–18, uses the same netting, so the shared helper correction also fixes that sibling. Its own gain inputs are already TaxUnit variables and need no separate source edit.

Reviewed main after #9841's netting helpers and #9852's regular-tax cap. Both shared-helper callers and the downstream Schedule D, §911 and AMT worksheet consumers were checked. Consumers read TaxUnit results; no additional person aggregation needs changing in this worksheet path.

Test plan

  • YAML expected values follow the two IRS worksheets, including dependent gains/losses and joint-filer spouse netting.
  • Port the eight dependent specialty-input cohorts from Limit investment interest deductions under §163(d) and Form 4952 #9977's property tests across single/joint returns and gain/excess-loss regimes, without its Form 4952 code.
  • Hypothesis checks batched populations, dependent perturbations, pooling head/spouse amounts, membership order, and independent worksheet totals.
  • make format.
  • Changelog fragment in changelog.d/.

All commands used one file per foreground process, without parallel workers, on main e3a38da446392dd5c44753f7b109e042328d279f and fixed head a274001030e07b3155a7b9ffd65b223d5bc79984.

File On main After
capital_gains_28_percent_rate_gain.yaml 13 passed, 5 new regressions failed 18 passed
schedule_d_unrecaptured_section_1250_gain.yaml 12 passed, 2 new regressions failed 14 passed
core/test_capital_gains_rate_worksheet_properties.py 2 failed 2 passed

Hypothesis reduced the main bug to a dependent's $1 reported small-business-stock gain incorrectly raising the filer's worksheet from $0 to $1. Existing test_capital_gain_rate_group_netting.py also passed (3 tests covering worksheet transcription, netting invariants and §911/AMT consumers); existing capital_gains_tax.yaml passed all 11 cases. The post-fix total is 48 passing tests across the five files. No partner-test edits.

Invariants: dependents' person-level specialty gains and losses never change the filer's 28% or unrecaptured §1250 worksheet. For each person input, the head-and-spouse aggregate equals the sum over non-dependents; their short-term gains and losses net before the loss floor.

The isolated 2025 example has $140,000 wages and $10,000 filer capital gain, with a dependent's $10,000 reported collectibles gain. Main gives regular tax $25,067 rather than the correct $24,167. The YAML holds the filer's net_capital_gain at $10,000 to isolate this worksheet correction. Recomputing the original r2 household, which also enters the dependent's $10,000 total gain, gives $24,167 on current main because main's separate generic net_capital_gain aggregation includes that dependent gain. After this narrow fix it gives $23,267: the 28% worksheet now correctly excludes the dependent, but generic net capital gain remains overstated. That separate aggregation defect remains outside this port and still needs follow-up with #9977's wider changes.

Python tests create fresh small Core systems with production classes per example; package import constructs the global US model once. Existing core CI group context: successful run 37613339193 took 502.62 s and peaked at 6,261,696 KiB (~5.97 GiB). Local macOS property-file measurements including import/setup: main 243.367 s / 1,413 MiB peak RSS (both expected failures); fixed 207.690 s / 797.55 MiB peak RSS (both passed, 60 Hypothesis examples). Pytest test times were 120.30 s and 76.88 s respectively; the main run includes failure shrinking. These are local measurements, not a prediction of Linux CI cost. No CI jobs or concurrency were added.

Impact

No change on the default dataset in 2025 or 2026: 0 records change. Base: main at the merge base e3a38da446. Branch: a274001030, which has the same PR diff as the current head 6372059a31 (the US + core hub merged main on 2026-10-07 with no conflicts). Both ran one at a time under the shared heavy-job lock on populace_us_2024.h5@populace-us-2024-spm-20260909 (79,729 tax units).

variable (tax unit) 2025 base = branch 2026 base = branch records nonzero (base) records changed
capital_gains_28_percent_rate_gain $41.62bn $43.24bn 63 0
schedule_d_unrecaptured_section_1250_gain $46.53bn $48.34bn 737 0
capital_gains_tax $279.61bn $294.01bn 14,425 (2025), 14,229 (2026) 0
regular_tax_before_credits $2,550.02bn $2,717.77bn 0
income_tax $2,416.13bn $2,589.90bn 0
state_income_tax $551.27bn $580.03bn 0
household_net_income (household) $16,357.06bn $17,171.08bn 0

Both worksheets are populated in the dataset, and still no record's worksheet amount, tax or net income moves. So in this sample, excluding dependents' amounts never changes either worksheet. The fix changes results for households that enter such amounts for a dependent, as in the $140,000 example above. Compare files: ~/reviews/us-hub/fixes/9988-impact/compare.{2025,2026}.json.

axiom: n/a (pe-parity follow-up if rulespec-us lacks the worksheet)

🤖 Generated with Claude Code

@MaxGhenis
MaxGhenis merged commit d96f2b2 into main Oct 7, 2026
35 checks passed
@MaxGhenis
MaxGhenis deleted the exclude-dependents-28-percent-rate-gain branch October 7, 2026 21:01
@MaxGhenis

Copy link
Copy Markdown
Contributor Author

US + core hub sweep audit (2026-10-07): squash-merged #9988 as d96f2b2d98f11150bc162e02a742ad8fe8e1d4e9.

Reviewed head: 6372059a3118b7def09d25d9b3005c2dcba6fd6a.
Independent approval: GPT-6.1 Sol, /Users/maxghenis/reviews/us-hub/reviews-gen/us-9988/review-r2.md.
Latest exact-head Pull request CI: https://github.com/PolicyEngine/policyengine-us/actions/runs/37666386986 (success).
Live gates: gh pr checks exited 0; MERGEABLE; ready; no CHANGES_REQUESTED; no unresolved Max hold; no semantic area overlap since CI base.
Merge used --match-head-commit to pin the approved head.
Approval-only --admin bypass under ~/.claude/CLAUDE.md; one required approving review was the sole branch-protection block.

MaxGhenis added a commit that referenced this pull request Oct 9, 2026
The 28% Rate Gain Worksheet was already filer-only on main (#9988), so the
fragment no longer claims this PR changes it, and it now names Vermont's
dividend subtraction. The helper docstring sentence was missing an "and".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis added a commit that referenced this pull request Oct 9, 2026
* Use the filers' Schedule D for the tax on net capital gain

Net capital gain (26 U.S.C. 1222(11), 1(h)(11)), the Schedule D Tax
Worksheet and the 28% rate gain summed long- and short-term gains,
capital gain distributions, qualified dividends, collectibles gain and
Form 4952 elections over every tax unit member. Adjusted gross income
leaves out tax unit dependents, whose items are on their own returns
(2025 Form 8814, line 4), so a dependent's gain or dividends let the
filer's ordinary income be taxed at capital gain rates. The rate side
also added a negative capital gain distributions input, which AGI
floors at zero (Form 1099-DIV box 2a).

A new helper, filer_schedule_d_lines, gives the head and spouse's
Schedule D lines 7, 15 and 16 with distributions floored per person. It
now feeds filer_loss_limited_net_capital_gains (Form 1040 line 7a),
has_qdiv_or_ltcg, net_capital_gain and the worksheet's Form 4952 lines,
so the AGI side and the rate side read the same lines. Qualified
dividends, the Form 4952 election and the 28% rate gain inputs are
summed over the head and spouse with tax_unit_non_dep_add.

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

* Trim the Schedule D property tests' Hypothesis examples

Keeps the remaining pytest group's added time small: the file now takes
about 50 s of CPU locally (6 tests, 1.4 GB peak footprint).

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

* Keep a supplied net_capital_gains in Schedule D line 16

Line 16 of the filers' Schedule D now starts from the tax unit
net_capital_gains and takes out dependents' person-level gains and
losses, as #9796 does for Form 1040 line 7a. The Schedule D Tax
Worksheet read net_capital_gains on main, so a tax unit amount supplied
there keeps reaching worksheet line 7.

filer_loss_limited_net_capital_gains goes back to main's formula, so
this PR no longer edits the file #9796 and #9840 change.

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

* Use the filers' amounts in Vermont's and Hawaii's capital gain lines

Review r1 found that Vermont's flat capital gains exclusion took every
member's qualified dividends out of the now filer-only
adjusted_net_capital_gain. A dependent's 3,000 of dividends cut a 4,000
exclusion to 1,000 (Vermont tax 936.33 to 1,036.82). The dividends are
now the head and spouse's, as in the federal amount.

Hawaii's Tax on Capital Gains Worksheet took the smaller of the filers'
net capital gain (line 7) and every member's long-term gains (line 4),
so a dependent's loss shrank the head's line 8. Line 4 is now the head
and spouse's too.

The property tests also give dependents section 1202 gain, a long-term
loss carryover and Schedule D line 18 small business stock gain, and
no longer claim the grid runs without Hypothesis.

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

* Test that a supplied net_capital_gains reaches Schedule D line 16

Review r2 asked for a case covering 2b7bf4f: distributions of 1,000
and a tax unit net_capital_gains input of -5,000 make line 16 a loss of
4,000, so has_qdiv_or_ltcg is false and worksheet line 9 is 0. Main
turned the flag on there. The helper's line 16 comment now says it is
figured from net_capital_gains.

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

* Clarify Schedule D worksheet scope and aggregate input limitation

* Match the changelog and helper docstring to the PR's scope

The 28% Rate Gain Worksheet was already filer-only on main (#9988), so the
fragment no longer claims this PR changes it, and it now names Vermont's
dividend subtraction. The helper docstring sentence was missing an "and".

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

---------

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