Skip to content

Offset SSTB and non-SSTB Schedule C results in federal AGI - #9995

Merged
PavelMakarchuk merged 5 commits into
mainfrom
fix-schedule-c-category-losses-agi
Oct 13, 2026
Merged

PavelMakarchuk merged 5 commits into
mainfrom
fix-schedule-c-category-losses-agi

Conversation

@PavelMakarchuk

@PavelMakarchuk PavelMakarchuk commented Oct 7, 2026 •

Copy link
Copy Markdown
Collaborator

Fixes #9989

What and why

irs_gross_income counts each Schedule C category's profit on its own (self_employment_income and sstb_self_employment_income are separate entries in gov.irs.gross_income.sources, each floored at zero), but the business-loss deduction took the loss only from the net total_self_employment_income. A loss in one category next to a profit in the other was dropped: a non-SSTB loss of 5,000 and an SSTB profit of 5,000 gave AGI 5,000.

limited_business_loss (moved out of loss_ald by #9762) now takes each category's profit and loss on its own, the same way irs_gross_income counts them. Per the 2024 Schedule C (lines 31 and 32a), both results go on Schedule 1 line 3, which flows to Form 1040 lines 8, 9 and 11, so AGI is 0. #9989 has the verbatim form quotes.

State code that matched the old net loss now takes each category on its own too:

  • Wisconsin homestead credit (disqualified_loss_sources): the 2023 Schedule H instructions, line 11j (page 16), say "consider each business individually. Do not net a business with a gain against a business with a loss" (Example 1: two Schedules C). The add-back now lists the two categories separately. Without this, household income in wi_homestead_income.yaml case 5 fell from 5,000 to 0, the CI failure on the previous push.
  • Kentucky (ky_federal_agi): the 2025 Form 740 instructions, page 13, line 9: "Each spouse must claim his or her own income and deductions. The total of line 5, Columns A and B, must equal the combined federal adjusted gross income." The spouse who owns both Schedules C now gets the loss; before, it was split 50/50 when that spouse's net was 0.
  • Maryland (md_two_income_subtraction): BUSINESS_LOSS_SOURCES lists the two categories separately. That split only runs when the couple has no gross income, where both categories are zero or negative, so results do not change.

Notes:

  • § 461(l): the cap compares the same totals. With business profit I, loss L and threshold T, the allowed net is I − min(L, I + T) = max(I − L, −T) whether or not the categories are netted first.
  • Self-employment tax already nets the two categories and does not change.
  • Not changed: dc_self_employment_loss_addition also uses the net of the two categories. The D-40 Schedule I line 6 text ("Pass through losses from DC unincorporated businesses that exceed the $12,000 threshold") does not say how to treat two businesses, and D.C. Schedule I line 6: the $12,000 threshold is a business gross-income test, not a loss threshold #9867 already questions that rule. Michigan (MCL 206.508(4) nets all business income and loss) and North Dakota's marriage penalty credit use their own definitions and do not change.
  • Open PR Give each spouse their own above-the-line deductions in per-person AGI #9890 also edits the business-loss block. Whichever merges second needs the same split.
  • test_dependent_losses_agi_invariants.py and test_loss_ald_extraction_parity.py build an independent reference of the old formula; both references now treat each category as its own source.

Test plan

  • Three YAML tests in self_employment_income.yaml. Expected values come from the 2024 Schedule C, Schedule 1 and Form 1040 arithmetic in Federal AGI drops a Schedule C loss when the same person has Schedule C profit in the other SSTB category #9989 (AGI 0, 0 and 50,000). All three fail without the limited_business_loss change and pass with it.
  • wi_homestead_disqualified_losses.yaml case 9 (expected 5,000 from the line 11j instructions) and wi_homestead_income.yaml case 5 fail without the Wisconsin change and pass with it.
  • New ky_federal_agi.yaml case (expected [0, 40_000] from the Form 740 line 9 instructions) fails without the Kentucky change ([2_500, 37_500]) and passes with it.
  • Local suites (macOS). On this branch (main at 00ce2281d0): states WI 361, KY 594, MD 606, DC 397 passed, and the targeted federal, Wisconsin, Kentucky and Python loss tests pass. On the previous merge with main (2308800c88): IRS shard 1,892 passed; 55 other YAML files that reference loss_ald, limited_business_loss or sstb_self_employment_income 461 passed; 34 Python test files that reference these variables 378 passed.
  • ruff format and ruff check (ruff 0.15.5, as in uv.lock)
  • Changelog fragment in changelog.d/

axiom: TheAxiomFoundation/rulespec-us#1542 queued (§62(a)(1) composition, deferred in us/statutes/26/62.yaml; the signed encoder run needs approval)

🤖 Generated with Claude Code

irs_gross_income counts each Schedule C category's profit on its own,
but loss_ald took the loss only from the net total_self_employment_income,
so a loss in one category next to a profit in the other never reached AGI.
loss_ald now takes each category's profit and loss on its own.

Fixes #9989.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PavelMakarchuk and others added 2 commits October 8, 2026 09:33
The all-member reference in test_dependent_losses_agi_invariants netted
self_employment_income and sstb_self_employment_income per person before
splitting income from loss, so it disagreed with loss_ald once loss_ald
takes each category on its own (#9989). Use each input on its own, as
irs_gross_income does.

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

Copy link
Copy Markdown
Collaborator Author

Fixed the two red checks:

  • Full Suite - Rest: tests/core/test_dependent_losses_agi_invariants.py::test_units_without_dependents_match_all_member_formula (2024, 2025) failed because its all-member reference netted self_employment_income and sstb_self_employment_income per person before splitting income from loss. With this PR loss_ald takes each Schedule C category on its own, as irs_gross_income does, so the reference now uses each input on its own. The nine Python test files that reference loss_ald or sstb_self_employment_income pass (78).
  • Full Suite - Baseline (states-shard-3): the Mississippi HSA test that was red on main at the time; main is merged in (it was fixed by Update the Mississippi HSA test for joint-column combination (main is red) #9992).

Main moved the section 461(l) business-loss logic from loss_ald into
limited_business_loss. Take main's loss_ald and apply the per-category
Schedule C change to limited_business_loss.

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

Wisconsin's homestead disqualified-loss add-back, Kentucky's spouse loss
allocation and Maryland's two-income loss allocation took the Schedule C loss
from the net total_self_employment_income, matching the old loss_ald. They now
take each category on its own, as loss_ald does. The 2023 Schedule H
instructions (line 11j, page 16) say not to net a business with a gain against
one with a loss, and the 2025 Form 740 instructions (page 13, line 9) say each
spouse claims their own income and deductions. The loss_ald extraction parity
reference now treats each category as its own source as well.

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

@hua7450 hua7450 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving. Read all 11 files at d922bb7 plus irs_gross_income with gov/irs/gross_income/sources.yaml, loss_ald, limited_business_loss on main, adjusted_gross_income, wi_homestead_disqualified_losses, wi_homestead_income, the full ky_federal_agi and md_two_income_subtraction formulas, dc_self_employment_loss_addition and taxable_self_employment_income, against the 2024 Schedule C (lines 31 and 32a), Schedule 1 line 3, Form 1040 lines 8 to 11, IRC 461(l), the 2023 Wisconsin Schedule H instructions (page 16), the 2025 Kentucky Form 740 instructions and the Maryland two-income subtraction instructions.

Federal: irs_gross_income floors self_employment_income and sstb_self_employment_income separately, so taking the loss only from the net total dropped a loss that sat next to a profit in the other category. The new per-category profit and loss in limited_business_loss mirrors that, both Schedule C results go on Schedule 1 line 3 and net in AGI, and the 461(l) identity holds (I - min(L, I + T) = max(I - L, -T)), so the cap is unchanged; the dependent mask and the other seven loss sources are untouched, as are the capital pieces. The 5,000 SSTB profit / 5,000 non-SSTB loss household now gives AGI 0.

Wisconsin: with the federal change, the earlier total_self_employment_income entry would have given household income 0 for that household; listing the two categories separately gives 5,000, which is what the line 11j text requires ("consider each business individually. Do not net a business with a gain against a business with a loss"; Example 1 adds back the full 30,000 beside a 20,000 profit). Kentucky: the spouse who owns both Schedules C now carries the loss, [0, 40,000] on the new case instead of the old [2,500, 37,500] split, consistent with "Each spouse must claim his or her own income and deductions"; a couple with one category each gives [-5,000, 5,000]. Maryland: the split only enters the no-gross-income branch, where both categories are zero or negative, so it is a no-op as the description says. All 18 YAML cases across the six test files recompute by hand, and each new case fails on the old lines. Other consumers (MA, MI, ND, AZ, MT) need no change; DC stays on the net and only diverges when the 461(l) cap binds, which issue 9867 already covers. CI is fully green and the axiom: line is present.

Merge interaction with PR 9890: loss_ald_person.BUSINESS_INCOME_SOURCES and its test list still use total_self_employment_income, so whichever lands second must apply the same split or adjusted_gross_income_person stays [2,500, 37,500] for the Kentucky household.

Nits, not blocking:

  1. The Kentucky comment and description cite "page 13, line 9", but the quoted sentence sits under the Filing Status 2 / line 5 instructions; line 9 is Kentucky AGI.
  2. Three comments still say "as loss_ald deducts them" where limited_business_loss now holds the per-category floor.
  3. The _pre_extraction_reference docstring in the core test predates the split.
  4. Optional: assert limited_business_loss: 5_000 in the federal cases to pin the deducted amount, not only AGI.

Pre-existing, for follow-ups: the 50/50 loss_ald split in adjusted_gross_income_person (9890 fixes it) and the DC cap-binding divergence.

@PavelMakarchuk
PavelMakarchuk merged commit 8955fc1 into main Oct 13, 2026
26 checks passed
@PavelMakarchuk
PavelMakarchuk deleted the fix-schedule-c-category-losses-agi branch October 13, 2026 11:47
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.

Federal AGI drops a Schedule C loss when the same person has Schedule C profit in the other SSTB category

2 participants