Skip to content

Let farm, partnership and S corporation plans set the self-employed health insurance limit - #10120

Draft
MaxGhenis wants to merge 6 commits into
fix-sehi-earned-income-limitfrom
sehi-plan-business-base
Draft

MaxGhenis wants to merge 6 commits into
fix-sehi-earned-income-limitfrom
sehi-plan-business-base

Conversation

@MaxGhenis

@MaxGhenis MaxGhenis commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

Stacked on #10109 (fix-sehi-earned-income-limit); retargets to main when #10109 merges.

Problem

#10109's self_employed_health_insurance_earned_income_limit (Form 7206 lines 4–13) treats the person's Schedule C business (total_self_employment_income) as the only business under which a health plan can be established. The law and Form 7206 allow more:

  • 26 U.S.C. 162(l)(2)(A): the deduction may not exceed "the taxpayer's earned income (within the meaning of section 401(c)) derived by the taxpayer from the trade or business with respect to which the plan providing the medical care coverage is established."
  • 162(l)(5)(A): for an individual treated as a partner under section 1372(a) (a more-than-2% S corporation shareholder), "such individual's wages (as defined in section 3121) from the S corporation shall be treated as such individual's earned income."
  • Form 7206 instructions (2023), p. 1 list who qualifies: a net profit on Schedule C or Schedule F, a partner with net earnings on Schedule K-1 box 14 code A, or wages from an S corporation in which the person is a more-than-2% shareholder. A Schedule C or F policy can be in the business's or the individual's name.
  • One plan, one business. The form says "Use a separate Form 7206 for each trade or business under which an insurance plan is established." The instructions add: "If you have more than one health plan during the year and each plan is established under a different business, you must use a separate Form 7206 to figure each plan's net earnings limit," entering "your net profit (or wages) from that business on line 4 (or line 11)."

On #10109, a farmer or partner whose only self-employment income is Schedule F profit or K-1 box 14 code A earnings gets a $0 deduction however large their premiums. Example (2024): farm profit $20,000 and premiums $25,000 give $0, where Form 7206 gives $18,587.05.

Change

  • New input self_employed_health_insurance_plan_business (Person enum: SCHEDULE_C, SCHEDULE_F, PARTNERSHIP, S_CORPORATION, default UNSPECIFIED). It names the business under which the plan is established. The UNSPECIFIED default follows the tax_unit_role_input pattern.
  • New input s_corp_shareholder_medicare_wages (Form 7206 line 11). These are box 5 Medicare wages from an S corporation in which the person is a more-than-2% shareholder. They are part of employment_income, not in addition to it, and are net of any section 911 exclusion (line 12), like the other income inputs.
  • self_employed_health_insurance_earned_income_limit computes line 13 for each business:
    • Schedule C: total_self_employment_income.
    • Schedule F: farm_operations_income.
    • Partnership: partnership_self_employment_net_earnings.
    • Line 4 is that business's profit, floored at 0.
    • Lines 5–8: line 5 adds the three profits, leaving out losses. Each business takes Schedule 1 line 15 × its share of line 5, so the shares across businesses sum to line 15.
    • Lines 9–10: subtract Schedule 1 line 16 only from the Schedule C business. The model bases self_employed_pension_contribution_ald_person on Schedule C income, and Limit self-employed plan contributions to the Pub. 560 maximum deduction #10121 keeps Schedule C as the retirement plan's business.
    • S corporation: line 11 wages.
    • A named business selects its own amount.
    • UNSPECIFIED takes the largest of the four.

The default: why the largest business

PE has one premium input per person and no data on which business the plan sits under, so the default is a methodology choice:

  • Largest business (chosen). One plan is limited to one business's earned income, and health_insurance_premiums is one amount, most naturally one policy. A Schedule C or F filer can hold the policy in their own name under either business. A filer able to choose would pick the business with the larger limit.
  • Never lower than Limit the self-employed health insurance deduction to net profit less half of SE tax and plan deductions #10109. The largest is at least the Schedule C amount, so no deduction falls.
  • All businesses combined (rejected). Summing the businesses' limits would let one policy pool earned income across businesses, which the form forbids. That sum is reachable only with separate plans under separate businesses, with premiums split in proportion to each limit. It is an upper bound, not a default.

The impact section reports both readings: they differ by $0.30M of deductions and $0.02M of federal income tax in 2026, so the choice is not queued as a decision.

Where the default can be wrong (documented on the input):

  • A partnership or S corporation that doesn't pay the premiums. A partner's or shareholder's own policy counts as established under that business only when the business pays or reimburses the premiums and reports them as guaranteed payments or wages. When such a business has the largest earned income but doesn't do that, the default overstates; name the business instead.
  • Separate plans under separate businesses. The default understates for a filer who really has two plans, which the single premium input can't represent.
  • Two Schedule C businesses. All of a person's Schedule C income, SSTB and non-SSTB, is one business here, as on Limit the self-employed health insurance deduction to net profit less half of SE tax and plan deductions #10109, because the inputs don't separate one Schedule C business from another. No record in the default dataset has both SSTB and non-SSTB Schedule C income.

Unchanged: line 2 (long-term care, a separate follow-up), 162(l)(2)(B) subsidized-employer-plan months, the premium tax credit interaction, and the is_self_employed gate on self_employed_health_insurance_premiums. The S corporation path, like every other path, needs is_self_employed; the input's documentation says so.

Invariants

These hold for every input and are tested with Hypothesis in tests/unit/test_self_employed_health_insurance_properties.py. Each drawn filer appears six times in one vectorized simulation over 2022, 2024 and 2026: with no named business, with higher premiums, and once naming each of the four businesses.

  1. Reference. Each named-business limit equals an independent closed-form Form 7206 line 13 for that business, with lines 15 and 16 taken from the model. Line 15 = ½ × SE tax. The unnamed limit is the largest of the four.
  2. Differential. The unnamed limit equals the largest of the model's own named-business limits, so one plan never pools two businesses' earned income.
  3. Bounds.
  4. Premiums. Raising premiums by d raises the deduction by between 0 and d, and the limit does not depend on premiums.
  5. AGI floor. For a filer with no business losses whose income is wages and self-employment income, AGI ≥ min(0, Schedule C line 10 before its floor).

The strategies draw losses in each business, S corporation wages, wages above the Social Security wage base, the $400 threshold, and large plan deductions. A local 300-example random sweep (1,779 filers, 6 copies each, 3 years) also passed. Hypothesis first failed on a float32 artifact: the model's $235,213.42 against the reference's $235,213.44, where the float32 spacing is $0.0156. The bound checks now carry a 1e-6 relative tolerance alongside the $0.01 absolute one.

Tests

  • Limit YAML (self_employed_health_insurance_earned_income_limit.yaml, 19 cases): 11 new cases plus Case 8 rewritten. Expected values are hand-computed from Form 7206.

    • Farm only.
    • Partnership only.
    • A larger farm beside a Schedule C business.
    • Each of the four businesses named: Schedule C, the farm, the partnership and the S corporation.
    • A Schedule C plan deduction that leaves the partnership larger.
    • S corporation wages, with and without a named Schedule C business.
    • A Schedule C loss beside a partnership.
  • ALD YAML (self_employed_health_insurance_ald.yaml, 10 cases): 4 new cases. Farm only and partnership only end with AGI 0; S corporation wages; a named farm.

  • Limit the self-employed health insurance deduction to net profit less half of SE tax and plan deductions #10109's Case 8 changes meaning. "A Schedule C loss leaves no limit" now names SCHEDULE_C, which still gives 0. The same inputs without a name give the partnership's $18,940.28 (new Case 9).

  • Fails on Limit the self-employed health insurance deduction to net profit less half of SE tax and plan deductions #10109. With the source files reverted in place to Limit the self-employed health insurance deduction to net profit less half of SE tax and plan deductions #10109's head 1bad2f16f6:

    • The limit file, as first written with 17 cases, has 10 failures and 7 passes. Cases 18 and 19, added after review, name a business, so they fail there too. The value cases fail by exactly the expected amounts: 0 vs 18,940.28, 18,587.05 and 27,880.57; 4,646.76 vs 37,174.09; 3,587.05 vs 9,293.52. The cases naming a business or using S corporation wages fail because those inputs are new.
    • The ALD file has 4 failures (0 vs 18,587.05 and 27,880.57, plus two new-input cases) and 6 passes.
  • Local runs at b03f96f65f, one file at a time:

    • limit YAML: 19 passed;
    • ALD YAML: 10 passed;
    • properties: 2 passed (12 Hypothesis examples, plus the fixed filers).
  • Cost of the expanded property test. It runs in the Rest job's remaining pytest group. Measured locally on macOS with one interpreter, two runs each, not on Linux CI:

    Version Copies per filer CPU time (user + sys) Peak resident memory
    Limit the self-employed health insurance deduction to net profit less half of SE tax and plan deductions #10109 2 22–26 s 1,098–1,107 MB
    This PR 6 21–23 s 1,126–1,127 MB

    Wall time isn't reported: the host was at load 55–60 and it ranged from 72 to 141 s across the four runs.

Impact

Three real microsimulation runs on the default dataset (populace-us-2024-spm-20260909) for 2026, one per column: #10109's head 1bad2f16f6; this PR's formula (snapshot 97e05a7935; later commits change only documentation, tests and the changelog); and the same snapshot with the default switched to the sum of the businesses' limits. The third is a scratch patch, not committed.

2026 #10109 This PR (largest business) All businesses combined (not adopted)
Self-employed health insurance deduction $15,738.4M $15,771.6M (+$33.1M) $15,771.9M (+$33.4M)
Adjusted gross income −$33.1M −$33.4M
Federal income tax $2,593,331.7M −$8.21M −$8.23M
State income tax −$0.25M −$0.27M
Household net income +$8.46M +$8.50M
Tax units with a larger deduction: records (weighted) 36 (117,598) 39 (133,099)
  • No deduction falls in either run.
  • The two readings differ little: $0.30M of deductions (23 person records) and $0.02M of federal income tax. They can differ only for people with two or more profitable businesses whose premiums exceed the largest one's limit.
  • Why so few records move. The limit itself rises for 1,959 person records (5.5M people weighted), but the deduction also needs premiums. In this dataset every one of the 3.74M people carrying premiums has positive Schedule C profit, because Microcosm attributes premiums and is_self_employed only to them. 0.24M of them also have farm or partnership profit. The farm-only and partner-only filers this PR fixes have no premiums in the data yet (see follow-ups).
  • Rounding. The limit moves down on 128 records by at most $0.125 (1.2 parts in 10 million), from float32 rounding of the rearranged line 6–7 proration.

Review

  • Round 1: APPROVE at 319445c2e7, nothing blocking (independent Opus 5.5 on a Subfleet lane, the Codex lanes being closed).
    • It recomputed all 27 YAML expected values of that head from the form with exact fractions, re-derived property 5 by hand for each business, and ran the three test files.
    • It judged the largest-business default defensible: for a single plan it never understates, and nothing in 162(l) or the form forbids it.
  • Fixes made after round 1 (47bba5e893, b03f96f65f):
    • the S corporation input now states the is_self_employed gate;
    • YAML Cases 18 and 19 name the partnership and the S corporation;
    • the plan business input documents the reimbursement condition and the single Schedule C business;
    • references cite PDF pages 1–2 of the instructions;
    • a sum-of-businesses bound that the differential property already implied is gone;
    • the test cost is reported above.
  • Round 2 (delta review at b03f96f65f): pending.

Follow-ups

axiom: us/statute/26/162/l queued (TheAxiomFoundation/rulespec-us#1676; to be extended for the plan business after round 2)

🤖 Generated with Claude Code

MaxGhenis and others added 5 commits October 11, 2026 16:15
…nd S corporation plans

Form 7206 allows the plan to be established under a Schedule F farm, a
partnership with K-1 box 14 code A earnings, or an S corporation in which
the person is a more-than-2% shareholder (162(l)(5), line 11), one form per
plan. Add self_employed_health_insurance_plan_business (default: the business
with the largest earned income) and s_corp_shareholder_medicare_wages.

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

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

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…the default's limits

- Limit YAML Cases 18 and 19 name PARTNERSHIP and S_CORPORATION.
- The plan business input says when a partner's or shareholder's own policy
  counts, and that all Schedule C income is one business.
- Cite PDF pages 1-2 of the Form 7206 instructions.
- Drop the sum-of-businesses bound, which the differential property implies.

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

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