Skip to content

Fix SNAP income standards for households over eight and half-up net income rounding - #9587

Open
hua7450 wants to merge 5 commits into
PolicyEngine:mainfrom
hua7450:fix-snap-income-standard-rounding
Open

hua7450 wants to merge 5 commits into
PolicyEngine:mainfrom
hua7450:fix-snap-income-standard-rounding

Conversation

@hua7450

@hua7450 hua7450 commented Sep 24, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Fixes two SNAP rounding errors found while auditing the model's rounding against 7 CFR 273.9 and 273.10:

  1. Income standards for households larger than eight were $1–$3 too low. 7 CFR 273.9(a)(3) builds these standards from the eight-person standard plus a per-person increment that is itself rounded up. The model rounded up the whole product instead.
  2. Net income ending in exactly 50 cents could round down. snap_net_income applies half-up rounding with np.floor(x + 0.5), but single-precision error stores some exact $X.50 amounts as $X.4999, which then rounded down.

Legal basis

  • 7 CFR 273.9(a)(3)(i): "For households greater than eight persons, the increment in the Federal income poverty guidelines is multiplied by 130 percent, divided by 12, and the results rounded upward if necessary." Paragraph (a)(3)(ii) does the same for the net standard, and (a)(4) makes the FNS-published tables the standards.
  • USDA FNS FY 2026 income limits: eight-person limits of $5,867 gross and $4,513 net, plus $596 and $459 for each additional member.
  • 7 CFR 273.10(e)(1)(ii)(A): amounts ending in 50 through 99 cents round up.

The statute (7 U.S.C. 2014(c)) sets the standards at the poverty line and 130 percent of it without a monthly conversion or rounding rule; the regulation fills that gap, and the published FNS tables follow it.

Changes

  • New snap_income_standard_helpers.py with:
    • snap_monthly_fpg_amounts: the October 1 poverty-guideline lookup, moved out of snap_fpg (behavior unchanged).
    • snap_monthly_income_standard: the 7 CFR 273.9(a)(3) standard. It still reads snap_fpg, so inputs that override snap_fpg keep setting the standard.
  • New parameter gov.usda.snap.income.limit.increment_household_size_threshold (8).
  • meets_snap_gross_income_test, meets_snap_net_income_test, and meets_tanf_non_cash_net_income_test use the shared standard.
  • snap_net_income rounds to cents before the half-up step, matching the guard snap_expected_contribution already uses.

FY 2026 standards (before → after)

Size Gross Net
1–8 unchanged unchanged
9 $6,463 → $6,463 $4,971 → $4,972
10 $7,058 → $7,059 $5,430 → $5,431
11 $7,654 → $7,655 $5,888 → $5,890
12 $8,250 → $8,251 $6,346 → $6,349

Impact

  • Households of nine or more at the boundary become eligible where the published standard says they are.
  • Net income that is exactly $X.50 now rounds up by $1, as the regulation requires. In an income sweep for a single elderly Pennsylvania renter, 319 of 1,513 incomes landed on exactly $X.50 and all had rounded down; after the fix, none do. One of them sat on the $1,305 net standard: $1,305.50 now rounds to $1,306 and fails, as it should.
  • This mostly affects household calculations with round-number inputs; microsimulation impact is negligible.

Tests

New YAML cases. The large-household cases each use a different state; every one of these states uses the 48-state guideline, so the limits are the same in all of them.

  • meets_snap_net_income_test:
    • Nine-person household at $4,972 passes (MO) and at $4,973 fails (TX).
    • Twelve-person household at $6,349 passes (IL) and at $6,350 fails (CO).
    • One-person household with $2,048.65 gross income minus $743.15 in deductions (MO): net income is $1,305.50, which rounds up to $1,306 and fails.
  • meets_snap_gross_income_test:
    • Ten-person household at $7,059 passes (KS) and at $7,060 fails (WA).
    • Twelve-person household at $8,251 passes (NC).
  • meets_tanf_non_cash_net_income_test: nine-person household at $4,972 passes (CA). The case stays in California because it is the only one of these states that applies the TANF non-cash net income test in 2026.
  • snap_net_income: $1,305.50 rounds to $1,306; $1,305.49 rounds to $1,305.

Every passing large-household case would fail on main, whose limits are $1 to $3 lower.

Partner contract tests (updated with approval)

Three SNAP pins under tests/policy/baseline/partners/ had net income of exactly $X.50 in January–September 2026. The two analytics-coverage comments recorded the single-precision artifact ("686.4998 unrounded, so it rounds to 686"). With half-up rounding, net income rounds up, the 30 percent contribution rises by $1, and each annual total falls by $9:

File Case Jan–Sep net income Monthly SNAP 2026 total
analytics_coverage/edge_cases/federal/nutrition/snap/federal.yaml snap_limited_utility_allowance_two_utilities $686.50 → $687 $579 → $578 $7,052.17 → $7,043.17
analytics_coverage/edge_cases/federal/nutrition/snap/il.yaml snap_il_sua_shelter_deduction_20k $540.50 → $541 $623 → $622 $7,568.17 → $7,559.17
amplifi/2026.yaml amplifi_2026_case_b exact $X.50 rounds up $1 lower $1,940.17 → $1,931.17

The team and each affected API partner, including Amplifi, were notified before these pins were updated. The full partner test folder (make test-yaml-no-structural-other-partners, 620 tests) passes locally on this branch.

Test plan

  • Model loads with the new helper module; FY 2026 standards for sizes 1–12 match the FNS table at the limit and fail $1 above it (local sanity script, not the test suite)
  • ruff format and ruff check pass
  • CI passes (test suite not run locally)

🤖 Generated with Claude Code

… rounding

Build the gross and net income standards for households larger than eight
from the eight-person standard plus a separately rounded-up per-person
increment, per 7 CFR 273.9(a)(3), matching the USDA FNS tables. Previously
the model rounded up the whole product, leaving the standards $1-$3 low for
households of nine or more.

Round SNAP net income to cents before the half-up step so single-precision
error cannot round an exact 50-cent amount down (7 CFR 273.10(e)(1)(ii)(A)).

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

codecov Bot commented Sep 24, 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 (d03cf30).
⚠️ Report is 37 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff            @@
##              main     #9587   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files            4         6    +2     
  Lines           76        95   +19     
  Branches         2         1    -1     
=========================================
+ Hits            76        95   +19     
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 and others added 4 commits September 24, 2026 00:01
Both cases have net income of exactly $X.50 in January-September 2026
($686.50 and $540.50). The pins recorded the single-precision artifact that
rounded these down; with half-up rounding they round up, the 30 percent
contribution rises by $1, and the annual SNAP total falls by $9.

Updated with user confirmation after team and partner notification.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
amplifi_2026_case_b has net income of exactly $X.50 in January-September
2026. With half-up rounding it rounds up, the 30 percent contribution rises
by $1, and the annual SNAP total falls by $9 ($1,940.17 to $1,931.17).

Updated with user confirmation after team and Amplifi notification. The full
partner test folder passes locally.

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

Move the size-9-and-up SNAP gross and net income test cases off Missouri so
each case uses a different contiguous state (MO, TX, IL, CO, KS, WA, NC; the
TANF non-cash case stays in CA, the only one of these states that applies the
net test). Add a twelve-person net case $1 above the limit and a
twelve-person gross case at the $8,251 limit. Drop the leading "- " from the
changelog fragment so towncrier does not render a double bullet.

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