Skip to content

Net spouses' self-employment losses in state EITC helper earned income (IL, CO, DC, IN) - #9820

Open
PavelMakarchuk wants to merge 3 commits into
mainfrom
state-eitc-helper-earned-income
Open

PavelMakarchuk wants to merge 3 commits into
mainfrom
state-eitc-helper-earned-income

Conversation

@PavelMakarchuk

Copy link
Copy Markdown
Collaborator

Fixes #9819.

Change

  • calculate_eitc_amount_from_parameters (policyengine_us/tools/state_eitc_helpers.py) now uses eitc_earned_income instead of filer_adjusted_earnings. This is the same earned income as the federal eitc_phased_in and eitc_reduction (Fix EITC earned income self-employment netting #8337). It combines both spouses' wages and net self-employment earnings and floors only the total, per Form 1040 EIC Worksheet B.
  • The Indiana decoupled branch of in_eitc (2011–2022) gets the same change.

The helper feeds il_eitc, co_eitc (ITIN and under-25 paths), dc_eitc_with_qualifying_child and in_eitc_eligible. The Washington credit imports other helper functions, not this one.

Tests

  • Four existing cases set filer_adjusted_earnings as an input. They now set eitc_earned_income with the same value and keep the same outputs.
  • Seven new cases have a joint return where one spouse has a self-employment loss. The expected values are TAXSIM-35 outputs for the same households (v39):
Test Year Expected TAXSIM v39
IL, 2 children, wages 10,000, spouse SE −4,000 2021 432 432
same 2023 480 480
IL 65+ couple, wages 7,000, SE −2,000 2023 76.50 76.50
CO under-25 couple, no children, wages 10,000, SE −4,000 2023 229.50 229.50
DC, 1 child, wages 10,000, SE −4,000 2023 1,428 1,428
IN, 2 children, wages 10,000, SE −4,000 2022 240 240
same 2021 216 216

Before this change, PE gave 720, 800, 107.10, 300, 2,380, 400 and 360.

Local runs: the IL, CO credit, DC, IN, WA and federal EITC test folders pass (2,218 tests).

Census effect

In the TAXSIM-35 census comparison for IL, CO, DC and IN (2021–2025), 15 household-years change, 12 now match TAXSIM, and none that matched before stop matching. The other 3 are 2021 Illinois households that still differ by the Illinois rebate.

🤖 Generated with Claude Code

The shared state EITC helper and the Indiana decoupled branch used
filer_adjusted_earnings, which floors each spouse at zero. The federal
eitc uses eitc_earned_income (#8337), which combines both spouses'
amounts per Form 1040 EIC Worksheet B. Fixes #9819.

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

codecov Bot commented Oct 5, 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 (6232ba0).
⚠️ Report is 311 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff            @@
##              main     #9820   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files            4         1    -3     
  Lines           76        40   -36     
  Branches         2         3    +1     
=========================================
- Hits            76        40   -36     
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.

@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.

Reviewed 03e3718. No calculation defect found in the static review: netting both spouses' wages and self-employment earnings before flooring the tax-unit total matches the IRS EIC Worksheet B treatment. I traced the helper's Illinois, Colorado, DC and Indiana callers, including Indiana's separate 2011–2022 calculation.

  • Please add the required axiom: parity declaration to the PR description, following CLAUDE.md's Axiom Parity section.
  • Optional regression coverage: add a spousal self-employment loss case in the state-credit phase-out range. The new cases primarily exercise phase-in and maximum-credit behavior.

Verification limits: I did not independently run the tests. All 37 check runs on this commit are successful as of October 6, 02:40 UTC. The source audit is partial: IRS and DC material was accessible, but some historical Illinois, Colorado and Indiana primary documents could not be retrieved.

PavelMakarchuk and others added 2 commits October 8, 2026 09:25
Both sides appended test cases to co_eitc.yaml and il_eitc.yaml; keep
both.

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

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

Copy link
Copy Markdown
Collaborator Author

Thanks. Merged main (both sides had appended cases to co_eitc.yaml and il_eitc.yaml; kept both) and added the phase-out range case you suggested:

  • Illinois 2023, joint, two children, head wages 40,000, spouse self-employment loss 5,000. Earned income and AGI are 35,000, above the 28,120 joint phase-out start (Rev. Proc. 2022-38, section 3.06). Federal EITC 6,604 − 0.2106 × 6,880 = 5,155.07; IL EIC 20% = 1,031.01. Without netting the old helper gives 820.41 (earned income 40,000). It fails on main and passes here.

The IL, CO, DC and IN tests pass (2,442). I will add the axiom: line separately.

@DTrim99

DTrim99 commented Oct 23, 2026

Copy link
Copy Markdown
Collaborator

PR Review: Net spouses' self-employment losses in state EITC helper earned income (IL, CO, DC, IN)

Summary

The PR switches calculate_eitc_amount_from_parameters in policyengine_us/tools/state_eitc_helpers.py, and the Indiana decoupled branch of in_eitc, from filer_adjusted_earnings to eitc_earned_income. filer_adjusted_earnings floors each spouse's earnings at zero before adding them. eitc_earned_income is what the federal eitc already uses: both spouses' wages and net self-employment earnings, with only the total floored at zero. So a joint couple where one spouse has a Schedule C loss now gets the same earned income in the IL EIC, the CO EITC (ITIN and under-25 paths), the DC EITC with a qualifying child, Indiana eligibility from 2023, and the Indiana decoupled credit for 2011–2022 as in PolicyEngine's own federal EITC.

Critical (must fix)

None.

Should address

1. Add the axiom: line to the PR body.

The body has no line starting with axiom in any form. On 2026-10-08 the author wrote "I will add the axiom: line separately", and hua7450's review of 03e3718 asked for it too. CLAUDE.md requires the line on any PR that fixes policy, and axiom: needed isn't available to staff.

Recommended line. rulespec-us already encodes the provision being fixed. In us/statutes/26/32/c/2.yaml, earned_income_before_section_112_election is a TaxUnit amount: max(0, employee_compensation_includible_in_gross_income + net_earnings_from_self_employment_after_self_employment_tax_deduction - …). That floors the tax-unit total once, which is the netting this PR adopts. The state modules take the federal credit as their base: us-il/statutes/35/5/212.yaml (federal_earned_income_credit_base_for_illinois_credit), us-in/statutes/6-3/1-21-6.yaml (federal_earned_income_tax_credit_claimed_for_taxable_year) and us-co/statutes/39/39-22-123.5.yaml. So this line fits:

axiom: us:statutes/26/32/c/2 encoded-correct

Two optional additions. The IL "as if" bases (age and ITIN routes) are caller-supplied inputs in rulespec, and composing them is already queued in rulespec-us#1699 (IL1; OPEN, pe-parity). Pavel could note that issue. He could also ask for a 32(c)(2) companion case with a negative self-employment amount, since none of the module's four cases has one.

Suggestions

  1. The same per-spouse floor remains in other readers of filer_adjusted_earnings; file a follow-up issue. Issue State EITC helper floors each spouse's earnings at zero instead of netting self-employment losses (IL, CO, DC, IN) #9819 covers only the helper and the Indiana branch, so the PR closes it as scoped. But these formulas on main still read the per-person-floored variable:

    • Oklahoma: ok_federal_eitc_phased_in.py:39 and ok_federal_eitc_reduction.py:39 (the federal-style credit "frozen at 2020 values").
    • Washington: wa_working_families_tax_credit.py:83 and wa_working_families_tax_credit_age_expansion_eligible.py:59 (the phase-out and the maximum-qualifying-income test).
    • The NY WFTC contributed reform: reforms/states/ny/wftc/ny_working_families_tax_credit.py:120, 164, 301, 349.

    Where those credits follow federal earned income, a joint couple with a self-employment loss gets an overstated credit, as IL did before this PR. The body's line "The Washington credit imports other helper functions, not this one" is accurate, but it could leave readers thinking WA is unaffected.

  2. Say in the body and changelog that the change also adds farm and partnership earnings. eitc_earned_income includes farm_operations_income and partnership_self_employment_net_earnings. filer_adjusted_earnings (wages, self_employment_income, sstb_self_employment_income, disability pensions) does not. So the four state credits now count farm profit and partnership self-employment earnings too. That is correct: 32(c)(2)(A)(ii) counts net earnings from self-employment "within the meaning of section 1402(a)", which includes both. But the body and changelog describe only the netting. One sentence, plus an optional farm-income case, would record the change.

Verified correct

  • Statute, IL. 35 ILCS 5/212(a): "With respect to the federal earned income tax credit allowed for the taxable year under Section 32 … (v) 18% of the federal tax credit for each taxable year beginning on or after January 1, 2018 and beginning prior to January 1, 2023, and (vi) 20% … on or after January 1, 2023."
    • (b-5) covers ages 18–24, (b-10) covers "the age of 65 or older" and (b-15) covers ITIN filers. Each grants the credit "based on the federal tax credit for which the taxpayer would have been eligible", waiving only the age requirement in 32(c)(1)(A)(ii) or the SSN restriction in 32(m).
    • Nothing in § 212 changes the earned-income definition, and the 65+ test's "(b-10)" citation is correct.
  • Statute, the other states. CO pays a percentage of the federal IRC 32 credit (C.R.S. 39-22-123.5), including for ITIN and under-25 filers computed as if federally eligible. DC matches the federal credit (D.C. Code 47-1806.04(f)(1)(B-1), 70% for 2022–2024), with the ITIN rule from 2023 in (f)(1)(D)(ii). Indiana's credit is a percentage of the federal credit (IC 6-3.1-21-6), and its 2011–2022 decoupled branch only freezes the schedule parameters. None of these redefines earned income.
  • Federal netting. 26 U.S.C. 32(c)(2)(A)(ii) counts "the amount of the taxpayer's net earnings from self-employment". The 2023 Form 1040 instructions, Worksheet B (PDF p. 45), say "If you are married filing a joint return, include your spouse's amounts … with yours" and, at line 4b, "Combine lines 1e, 2c, 3, and 4a. This is your total earned income." A spouse's loss therefore reduces the couple's earned income, and only a total of zero or less ends the credit.
  • Variable equivalence on the merged tree. On main, both variables use federal taxable wages (irs_employment_income, or employment_income minus the excluded wages), add earned_disability_benefits, subtract half of SE tax (percent_deductible 0.5 = (1 − self_emp_tax_adj 0) × employer_share 0.5), and exclude dependents. The only differences are the per-person floor and the farm and partnership sources (Suggestion 2). Single filers' results don't change, because a single person's wages and losses already net before that person's floor.
  • Hand-checked expectations (8 new, plus 4 renamed inputs). In every case the SE loss carries no SE tax, so AGI equals earned income.
    • IL 2021, 2 children, wages 10,000, spouse SE −4,000: earned income 6,000; 40% × 6,000 = 2,400 (under the 5,980 maximum); AGI 6,000 is below the phase-out; 18% gives 432.
    • Same household in IL 2023: 2,400 (under the 6,604 maximum); 20% gives 480.
    • IL 2023, 65+ couple, SE −2,000 and wages 7,000: earned income 5,000; childless 7.65% × 5,000 = 382.50 (under 600); joint childless phase-out starts at 16,370; 20% gives 76.50.
    • IL 2023 phase-out case, wages 40,000 and SE −5,000: earned income and AGI 35,000; reduction 0.2106 × (35,000 − 28,120) = 1,448.93; 6,604 − 1,448.93 = 5,155.07; 20% gives 1,031.01. Without netting it would be 0.2 × (6,604 − 0.2106 × 11,880) = 820.41. This is the case hua7450 asked for.
    • CO 2023, under-25 couple aged 22, no children: the federal age floor (25) fails, so the under-25 path applies; 7.65% × 6,000 = 459; the 2023 match is 0.5, giving 229.50.
    • DC 2023, 1 child: 34% × 6,000 = 2,040 (under 3,995; phase-out starts at 28,130 joint); 70% gives 1,428.
    • IN 2022, decoupled branch, 2 children (cap 2): 40% × 6,000 = 2,400; AGI is below the 2-child phase-out start without the joint bonus; the match is 0.10, giving 240. Eligibility holds because the federal eitc (2,400) is above 0, the return is joint and there is no investment income.
    • IN 2021: 2,400 × 0.09 = 216.
    • Renamed inputs (DC 294.12, IL 2,941.18 twice, IN eligibility 10,000): each sets eitc_earned_income to the old filer_adjusted_earnings value, so the outputs stay the same.
  • Callers. The helper's only reader of calculate_eitc_amount_from_parameters is calculate_eitc_like_amount, which il_eitc, co_eitc, dc_eitc_with_qualifying_child and in_eitc_eligible (2023+ static-conformity path) call. The WA files import only eitc_filing_requirement_met and similar helpers. dc_eitc_without_qualifying_child uses the federal eitc_phased_in and tax_unit_earned_income, so it isn't affected.
  • Main interactions. Since the merge base, main changed the helper (section 911 gate), eitc_earned_income (Exclude pretax payroll deductions from EITC and ACTC earnings #10030, Count taxable employment disability benefits in federal gross income (IRC 105(a)) #10185), dc_eitc_without_qualifying_child and in_refundable_credits. None of them overlaps the swapped line. No IL, CO, DC or IN tax test on the merged tree supplies a spouse SE loss, farm income or partnership earnings apart from this PR's cases, and every remaining filer_adjusted_earnings reference in tests is an output of the still-existing variable.
  • Code. The change is vectorized (a variable swap) and makes no new state-gated key lookups, so the NH Add New Hampshire state supplementation for 2026 #10156 pattern doesn't apply.
  • Changelog. changelog.d/state-eitc-helper-earned-income.fixed.md is a top-level fragment with the fixed type.
  • Source-conflict ratchet (Tie source-conflict markers to the register shared with Axiom #10287). The PR changes no comments in variables/, parameters/ or reforms/ (the two .py edits are code-only), so test_source_conflicts.py is unaffected.
  • Partner tests. No files under tests/policy/baseline/partners/** are touched.

Axiom line assessment

There is no axiom: line in the body (checked in every format). That is a SHOULD for a staff policy fix (see Should 1). The recommended line is axiom: us:statutes/26/32/c/2 encoded-correct. rulespec-us has no issue that references #9820.

CI status

All 28 checks pass at 6232ba053b (gh pr checks 9820), including the four Baseline states shards and Quick Feedback. None is pending. That run is from 2026-10-08, before main's 320 newer commits. I tried running the IL and IN YAML on the merged tree locally, but the local policyengine-core is too old to import current main (_uprating_index_value ImportError). The merged-tree conclusions above therefore come from static tracing and the hand checks.

Branch status

The branch is 3 commits ahead of main and 320 behind. git merge-tree --write-tree PolicyEngine/main 6232ba053b merges cleanly, with no conflicts.

Sibling notes:

Verdict: REQUEST_CHANGES

@DTrim99 DTrim99 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.

The fix is correct for IL, CO, DC and IN in all years: a spouse's SE loss nets on joint returns under 32(c)(2) and Worksheet B line 4b. All 8 new expectations hand-check, and the merged tree is clean. One should-address item: there's no axiom line; us:statutes/26/32/c/2 encoded-correct fits (IL composition is already queued in #1699). Two suggestions, including a follow-up for OK, WA and the NY WFTC reform. Full report in the comment above.

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.

State EITC helper floors each spouse's earnings at zero instead of netting self-employment losses (IL, CO, DC, IN)

3 participants