Skip to content

Add S.770 section 8 investment and active income tax options - #10402

Merged
MaxGhenis merged 10 commits into
mainfrom
reform-s770-section8-investment-business-income-tax
Oct 28, 2026
Merged

MaxGhenis merged 10 commits into
mainfrom
reform-s770-section8-investment-business-income-tax

Conversation

@MaxGhenis

@MaxGhenis MaxGhenis commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Adds two independently enabled, parametric S.770 §8 options for scoring: an NII add-on and an active pass-through base. Both default off under gov.contrib.congress.s770.section_8, each with its own start year, rate and OASDI share. Bill example rates are .124 and .162. No scenario or package-specific values are encoded.

Bill and scope

Congress.gov introduced S.770, 119th Congress, §§8–9, fetched October 23, 2026:

“16.2 percent” (§8(a)(1))

“other than the deduction for net operating losses provided in section 172” (§8(b)(2))

“taxable years beginning after the date of enactment” (§8(c))

Each excerpt is under 25 words. Section 8 has no fixed effective year: the configurable 2026 defaults illustrate an enactment assumption. Section 9(a), rather than §8, transfers 62% of all resulting §1411 tax to the merged Social Security fund from the first fiscal year beginning after enactment; fund assets transfer on January 1 of the first calendar year beginning after enactment. The independent annual transfer start does not model collection lags or fiscal-year proration.

This is the documented split pass-through model, not a complete literal-bill preset. The implementation README audits ordinary-course investment sources, active trade/business categories, business-property gains, NOL treatment and FICA/SECA exclusions. Classification of all statutory categories remains unsupported; matching rates and transfers does not close those gaps.

Tax computation and independent options

Use existing niit_magi (including estate and §911 adjustments) and §1411(b) thresholds. Let N be signed adjusted NII, A the signed additional active base (zero if disabled), and X the positive MAGI excess. Compute:

L = min(max(N + A, 0), X)
n = min(max(N, 0), L)
a = L - n
tax = (existing_rate + enabled_addon_rate) * n + enabled_active_rate * a

NII receives threshold room first, even with an add-on rate of zero. Both allocations are nonnegative. Active inclusion also replaces the existing 3.8% component's base with n. net_investment_income_tax is the full resulting liability, so the new component taxes are not added again downstream.

The active residual uses partnership_s_corp_income (derived from s_corp_income + partnership_income), less passive income and already-SE active income. Head/spouse amounts are included; dependents stay on their own return. Nonpassive is only a material-participation proxy; cross-entity netting is an approximation. Validated overlap and FICA exclusion inputs avoid treating overlapping passive/SE sources or embedded wage amounts twice.

The future owners-draw integration hooks implement the actual-SECA exclusion: with OASDI only, exclude capped draw net earnings / q; with uncapped HI, exclude the actual full gross draw. Above-room profits remain active with draw HI off; undrawn and floor-rejected amounts remain active in either mode. The hooks classify supplied amounts and do not themselves impose SECA.

There is no baseline federal §172 NOL deduction input/formula in NII; the Indiana NOL variables are state-specific. s770_niit_nol_deduction accepts a validated deduction already subtracted from supplied NII. When active inclusion and denial are enabled, the addback changes broadened NII before allocation, including the existing NIIT component. Default zero is not complete NOL coverage and ordinary signed business losses are not NOL deductions.

OASDI allocation

Four transfer modes use integer choices because core has no string parameter scalars:

  • 0 custom: each component share (defaults .62), without existing NIIT.
  • 1 combined_rate_share: OASDI rate / combined NII rate and OASDI rate / active rate. OACT 2025 F8 attributes active-tax receipts to 12.4 of 16.2 points; this convention differs from the bill's 62%. With no positive NII add-on, that custom mode transfers no existing NIIT and keeps the active transfer independent.
  • 2 all_addon: all NII add-on points to OASDI, plus the chosen active share.
  • 3 bill: .62 of all resulting §1411 tax, including a separately reported existing-NIIT transfer.

Each source revenue equals its selected share times its tax. The three revenue sources sum to s770_revenue_oasdi; aggregate each TaxUnit once alongside tob_revenue_oasdi. Transfers have a separate start year and are zero when both provisions are off. Liability equality and OASDI-allocation equality are distinct claims.

Data limitation

The certified pre-repair artifact forces S-corp income to zero, carries combined income with passive mass in the reweighted partnership column, and omits the passive subset. The formula runs on current data, but (b) overstates active income and (a) understates NII until Microcosm #1251 and #1261 repairs are present in the selected scoring artifact and the columns are verified. These limitations are also in the variables' documentation. Population scoring remains provisional.

Invariants and validation

With both options enabled, identical signed sources, exclusions, NOL treatment, MAGI, thresholds and timing, and existing + add-on = active = .162, liability equals .162 × L for every signed input. N=-$10,000, A=$20,000, X=$50,000 yields $1,620, as does N=$20,000, A=-$10,000. The latter is lower than add-on-only liability of $3,240. Activation monotonicity requires nonnegative active income and fixed NII source rules, including exclusions and NOL treatment. Activating a SECA exclusion can also lower existing NIIT with no active loss: the paired $10,000 passive/SE overlap example falls from $380 to zero. Tests pin these necessary corrections to the brief.

Hand-computed YAML covers S-corp, limited/general partners, below-threshold cases, NOL hooks, each option alone/together, signed losses, zero rates, all filing thresholds, dependent exclusion, overlap, M7 draws (including changed SECA rates and supplied zero actual draws) and transfer modes. Hypothesis covers signed equivalence, nonnegative allocations/taxes, monotonicity under its stated conditions, disjoint SECA classification, activation and transfer identities through vector helpers. One shared multi-year household simulation checks actual registration, independent timing, formula allocations, MAGI adjustments and component accounts without rebuilding the model for each generated example.

All 133 checks passed, with each file run in its own foreground process and all requested thread caps set to four:

Validation Passed
New reform YAML (four files) 39
New Hypothesis/helper and multi-year integration Python tests 19
Existing NIIT YAML: federal tax, MAGI, dependent, estate, Minnesota 56
Existing section 911 and dependent-NII Python regressions 18
Existing reform-combination budget check 1

The 19 includes the netting-factor coverage test added with the main merge. At head 8c3b927a90, test_s770_section_8.py (19 passed) and test_ss_calculator_differential.py (8 passed) were rerun locally, and CI passes every check. The other rows were run before the main merge, which changed none of this PR's 41 files.

make format (Ruff format and lint) and git diff --check passed. The YAML cases are grouped into files with configuration weights 5, 3, 5 and 4, within the existing per-file limit of five. All 39 cases were preserved when split.

Local macOS wall times for the four new YAML files were approximately 8.7, 4.4, 8.5 and 6.1 minutes, including model initialization and shutdown; the new Python file took 1.7 minutes. Peak RSS was unavailable because the sandbox denied kernel statistics. Linux CI resource usage was not measured locally. No microsimulation was run.

impact: none at defaults. Both options' in_effect parameters default to false, and create_s770_section_8_reform installs the reform only if some in_effect value is true. Measured at 8c3b927a90 against main 462672c1a4: 500 drawn households (5 seeds × 100; 43–53 of each 100 tax units owe NIIT and 47–54 people per batch owe SE tax) × 2025, 2026 and 2030, one year per process. Every cached array (10,748–11,124 per run) is identical, no array exists on only one side, and no s770_ variable is computed. No population run for the enabled options (see Data limitation).

axiom: n/a: proposed-bill reform (S. 770, 119th Congress), not enacted law

Main merge

  • Merged main 462672c1a48b9c00f99cf73d9dff2f5ad17b353e in merge commit f47d2f9dac83bc996b85393d69e59ce6af9348a7. No conflicts or resolved hunks.
  • Narrowed the calculator reference deletion from gov.contrib.congress.s770 to gov.contrib.congress.s770.section_2, the calculator-only addition. This preserves this PR's sibling section_8 during simulation initialization. Add composable Social Security benefit levers #10400's shared benefit-lever and COLA-history namespaces remain available. The reference still removes gov.contrib.ssa.pia, gov.contrib.congress.s770.section_2, gov.ssa.social_security.pia.bend_points, and gov.ssa.social_security.cola; none contains this PR's nodes.
  • Mutation check: with a mutant in which ss_retirement_eligible reads gov.contrib.congress.s770.section_2.in_effect, the working case of test_calculator_off_matches_model_without_feature fails (1 failed in 85 s, 2 GB RSS cap) with ParameterNotFoundError for gov.contrib.congress.s770[section_2], while section_8 remains. So the narrowed reference still catches a legacy formula that reads the calculator-only node.

@MaxGhenis MaxGhenis changed the title WIP: Add S.770 section 8 investment and active income tax options Add S.770 section 8 investment and active income tax options Oct 23, 2026
@MaxGhenis
MaxGhenis marked this pull request as ready for review October 23, 2026 09:02
@codecov

codecov Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (909176a) to head (8c3b927).
⚠️ Report is 712 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##              main    #10402    +/-   ##
==========================================
  Coverage   100.00%   100.00%            
==========================================
  Files            4        18    +14     
  Lines           76       226   +150     
  Branches         2         6     +4     
==========================================
+ Hits            76       226   +150     
Flag Coverage Δ
unittests 100.00% <100.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Zero the SE netting factor q = 1 - employer share x (OASDI + HI SE
rates) for 2026 only, so s770_active_business_income raises its
positivity error there, while 2025 keeps q = 0.9235 and excludes
9,235 / 0.9235 = 10,000 of a 100,000 S-corp profit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaxGhenis
MaxGhenis merged commit 56f1961 into main Oct 28, 2026
35 checks passed
@MaxGhenis
MaxGhenis deleted the reform-s770-section8-investment-business-income-tax branch October 28, 2026 08:24
@MaxGhenis

Copy link
Copy Markdown
Contributor Author

Merge audit (US + core hub), #10402 at 8c3b927a906061f32aac02a2ab15f5fc2708326d, squash.

  • Independent reviews:
    • r1, GPT-6.1 Sol, at 24192e504c: APPROVE, no findings. It checked the signed allocation, the owners-draw hooks, the four transfer modes and an exact 8-household differential (17,831 arrays) with both options off.
    • r2, an independent Opus 5.5 agent (the Codex lanes were closed), at this head: APPROVE, two P3s.
      • It found the merge clean: apart from the coverage test and one reference hunk, the PR's diff is byte-identical to r1's, and no file overlaps main's changes.
      • It confirmed that the new coverage test pins the netting factor.
      • It confirmed that the mutant fails as designed.
      • It reran test_s770_section_8.py (19 passed) and test_ss_calculator_differential.py (8 passed).
  • P3s:
    • The stale test counts and mutation line are fixed in the body.
    • The narrowed calculator reference would not catch a future calculator-only sibling under gov.contrib.congress.s770. The hub will follow up with a test asserting the node's children.
  • Defaults differential at this head (hub, after r2):
    • Compared against main 462672c1a4: 500 drawn households (5 seeds × 100) × 2025, 2026 and 2030, one year per process under a 4 GB RSS cap.
    • All 15 runs are exact: every cached array (10,748–11,124 per run) matches, no array exists on only one side, all 13 headline outputs have equal totals, and no s770_ variable is computed.
  • Gates at merge:
    • gh pr checks exits 0, with a successful Pull request run at this head.
    • MERGEABLE, not a draft, and no review requests changes.
    • It merges cleanly with current main.
  • Impact: none at defaults (measured above). Both options default off, and the reform installs only if an in_effect value is true.
  • Axiom: n/a. S. 770 (119th Congress) is a proposed bill, not enacted law.

MaxGhenis added a commit that referenced this pull request Oct 28, 2026
Brings in main up to fe9ec12 (S.770 section 8 options, #10402, and the
2.75.0 bump). Neither commit touches the Montana AGI invariant test or this
branch's changelog fragment, so the merge applied cleanly with no resolved
hunks; the test file's resolution is the one in the previous merge,
56ec6ef.

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