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.

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