Skip to content

Fix SNAP expected contribution rounding per 7 CFR 273.10(e) - #9318

Draft
hua7450 wants to merge 1 commit into
mainfrom
fix/snap-expected-contribution-rounding
Draft

Fix SNAP expected contribution rounding per 7 CFR 273.10(e)#9318
hua7450 wants to merge 1 commit into
mainfrom
fix/snap-expected-contribution-rounding

Conversation

@hua7450

@hua7450 hua7450 commented Aug 19, 2026

Copy link
Copy Markdown
Collaborator

Summary

Fixes the rounding in snap_expected_contribution, which previously computed floor(net_income) * 0.3 with no rounding of the product.

Fixes #9312

Legal basis

  • 7 CFR 273.10(e)(1)(ii)(A): net income is rounded to the nearest dollar — 1–49 cents down, 50–99 cents up (half-up, so np.floor(x + 0.5) rather than np.round's half-to-even).
  • 7 CFR 273.10(e)(2)(ii)(A)(1): 30 percent of net income is rounded up to the next higher dollar — equivalent to rounding the allotment down to the nearest lower whole dollar (7 U.S.C. 2017(a)).
  • The product is rounded to cents before np.ceil so float32 noise (e.g. 50 * 0.3 = 15.0000009) cannot push an exact dollar amount up to the next dollar.

Tests

  • New snap_normal_allotment_basis_of_issuance.yaml (13 cases): 3-person allotments at net-income boundaries validated against the FNS Basis of Coupon/EBT Issuance table (Oct 1, 2025), including net income $3.49 vs $3.50 half-up boundary and the exact-multiple $50/$51 rows.
  • New snap_categorical_eligibility_ceiling.yaml (3 cases): categorically eligible units above the issuance-table maximum (2-person gets the minimum allotment, 3-person gets $0 but stays flagged eligible per 7 CFR 273.10(e)(2)(iii) not converting to denial in the model).
  • Updated 16 existing expectations whose old values carried fractional cents (e.g. 230.40 → 230, 288.9 → 288) — artifacts of the missing rounding.

Known CI failures (intentional)

~30 SNAP pins in tests/policy/baseline/partners/** shift by $1–$11/year under the corrected rounding. Per repo policy those partner contract files are not edited in this PR; the partner shard will fail until that change is separately approved.

Test plan

  • 16 new tests pass locally; the 4 updated files pass locally (policyengine-core test ... -c policyengine_us)
  • CI (partner shard expected to fail, see above)

🤖 Generated with Claude Code

Round net income to the nearest dollar (1-49 cents down, 50-99 cents up,
7 CFR 273.10(e)(1)(ii)(A)) and round 30 percent of net income up to the
next higher dollar (7 CFR 273.10(e)(2)(ii)(A)(1)), replacing the prior
floor-then-multiply formula. Add boundary tests against the FNS Basis of
Issuance table and categorical-eligibility ceiling tests.

Fixes #9312

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@codecov

codecov Bot commented Aug 19, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (57743a2) to head (8df8c50).
⚠️ Report is 15 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff            @@
##              main     #9318   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files            3         1    -2     
  Lines           65        14   -51     
=========================================
- Hits            65        14   -51     
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.

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.

SNAP expected contribution: round net income to nearest and 30% product up per 7 CFR 273.10(e)

1 participant