Prorate income and expenses of SNAP-ineligible household members (7 CFR 273.11(c))#8892
Conversation
…11(c) Implements the treatment of income and deductible expenses of ineligible household members: proration for ineligible aliens (with state count-all and gross-test-only options), full exclusion of ineligible students' income under 273.11(d), and person-level income counting that also fixes the excluded child earner leak. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #8892 +/- ##
==========================================
Coverage 100.00% 100.00%
==========================================
Files 3 17 +14
Lines 55 258 +203
==========================================
+ Hits 55 258 +203
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
…rence Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… unit level person.spm_unit projections inside the person-level earned income formula produced MicroSeries with mismatched weights under Microsimulation. Keep snap_earned_income_person as a pure person-level adds variable and perform the self-employment attribution inside the SPM unit formulas. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…into snap-ineligible-member-income
… expense shares, and gross test - Split 7 CFR 273.11(c)(1)/(c)(2): members sanctioned under the general work requirements have income and expenses counted in full; only ABAWD time-limit-ineligible members are prorated, and count-all state elections govern aliens who also fail work requirements. - Attribute unit-level self-employment income by signed gross SE with the countable-earner mask in the numerator only, so excluded earners' SE income is dropped rather than reattributed and losses offset other income at the member's counted share. - Prorate shared expenses as (n-i)(n+i)/(size*n) per the 273.11(c)(2)(iii) even-payment reading. - Count full-count aliens' child support in full under the gross test in states deducting child support from gross income. - Revert snap_gross_income_fpg_ratio to plain gross income so the TANF BBCE test is unaffected; the SNAP gross test reads snap_gross_test_income. - Restore parameter paths gov.usda.snap.income.sources.earned/.unearned, add unit metadata to share variables, extract shared is_snap_state_discretion_ineligible_alien, and add self-employment and work-requirement-regime test coverage. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…into snap-ineligible-member-income
…atus conferral, and gross-test consistency - Floor non-farm self-employment losses at zero per 7 CFR 273.11(a)(2)(iii) (only farm losses offset other income), bounding the unit-net SE attribution ratio to [0, 1] and preventing one member's loss from wiping out another's income. - Rebuild snap_gross_test_income as a direct mirror of snap_gross_income with the full-count share substituted, returning snap_gross_income exactly for households without full-count aliens. - Route both the SNAP gross income test and the BBCE/TANF non-cash gross screen through a new snap_gross_test_income_fpg_ratio so hybrid states' full-count election cannot be bypassed via categorical eligibility; restore the ratio-form comparison. - Rewrite snap_expense_counted_share as the mean of members' income counted shares, applying one reading of 273.11(c)(2) across income, expense, and child support proration; stop prorating standard utility allowances, which are not expenses paid by or billed to an ineligible member. - Add is_snap_excluded_member and has_snap_elderly_disabled_member so excluded members no longer confer household-wide elderly/disabled status for the gross test, shelter cap, and BBCE screens. - Reuse snap_gross_self_employment_income_person in the SE expense deduction; document the 273.11(c)(1)/(c)(2) work-requirement split; fix USC-vs-CFR citation titles; add hybrid-state SE, sanctioned- member expense share, and elderly-status tests. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…into snap-ineligible-member-income # Conflicts: # policyengine_us/variables/gov/usda/snap/income/deductions/snap_dependent_care_deduction.py
Compute the share as one minus the uncounted portions of actual members' per capita payments, so a spm_unit_size input exceeding the modeled member count leaves expenses fully counted. Give the second member explicit work-requirement inputs in the counted-share tests, since providing the variables for one member makes them input arrays with false defaults for the rest. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…, and direct unit tests - Correct the farm-loss-offset citation to 7 CFR 273.11(a)(2)(ii) in the gross self-employment variable, changelog, and test comments. - Select the SNAP resource limit with has_snap_elderly_disabled_member: ineligible members' resources continue to count in their entirety (273.11(c)(1)(i), (c)(2)(i), (c)(3)) but the members are excluded when comparing resources with the resource limits ((c)(1)(ii)(D), (c)(2)(iv)(D)), so an excluded elderly or disabled member no longer confers the higher limit. - Add direct unit tests for is_snap_state_discretion_ineligible_alien (covering DACA, TPS, and conditional entrants), is_snap_excluded_member, has_snap_elderly_disabled_member, snap_gross_self_employment_income_person (per-enterprise loss flooring), and snap_countable_child_support_expense. - Add behavior tests: unprorated standard utility allowance, medical expense exclusion for prorated members, unearned income proration, unit-level TANF full counting, and the NC BBCE gross-screen divergence for full-count aliens. - Read YEAR-defined booleans and counts with period.this_year in the new MONTH formulas; reground the elderly/disabled conferral on the 7 CFR 271.2 member definition; replace the self-employment expense deduction blog reference with 273.9(c)(9) and 273.11(b); regroup unearned source comments under their 273.9(b)(2) subsections. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
PR review — regulatory, reference, code-pattern, and test-coverage validationFour-validator review of the full diff (56 files) from a clean checkout, with the regulation researched independently before reading the code. No critical issues found. The implementation is a faithful encoding of 7 CFR 273.11(c)/(d), including the subtle points: the plural-possessive proration reading of (c)(2)(ii) was verified against the verbatim CFR text, the state-election lists match the SNAP State Options Report 16th ed. p. 15 exactly (9 count-all, 4 hybrid, 40 prorate), the (c)(1) full-count vs (c)(2) prorate split for work requirements is correct, and the self-employment attribution ratio is genuinely bounded to [0, 1] with safe zero-denominator handling. 🔴 Critical (must fix)None. 🟡 Should address
🟢 Suggestions
Validation summary
Verified correct (highlights)
Recommendation: no blocking issues — the should-address items are test hardening and cleanup, well within the scope of the PR's existing pre-merge TODO list. 🤖 Generated with Claude Code |
daphnehanse11
left a comment
There was a problem hiding this comment.
overall good, claude nits below
… citation - Add end-to-end tests using real excluded members: shelter deduction cap with an excluded elderly member, asset limits on both sides of the elderly/disabled threshold, post-delay California refugee proration (2027) and pre-OBBBA baseline (2025), a household combining a student, prorated alien, and sanctioned member, a multi-member all-ineligible unit, and the student-only zero-denominator branch. - Add a direct unit test for snap_gross_test_income_fpg_ratio; rename dead has_usda_elderly_disabled inputs in the net income and expected contribution tests. - Reground the medical expense exclusion on 7 CFR 273.9(d)(3) and 271.2 and read elderly/disabled status with period.this_year. - Update partner contract expectations for 273.11(c) proration: TX refugee/undocumented cases rise to 4,147.92, CA CFAP and CalWORKs cases to 2,162.22 and 3,002.22, and the amplifi household flips from ineligible to a 2,114.10 (2025) / 2,360.52 (2026) benefit. Add count-all (MA), hybrid gross-test (NC), and student-income edge cases. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Thanks for the thorough review — all should-address items except the backdating research are resolved in b031fe8, and most suggestions are folded in too. Should address
Suggestions
Partner contract testsAlso updated in the same push (team and partner notified): the TX refugee/undocumented cases rise to 4,147.92, the CA CFAP/CalWORKs cases to 2,162.22 and 3,002.22, and the amplifi household flips from ineligible to a 2,114.10 (2025) / 2,360.52 (2026) benefit — that eligibility flip is the headline for the partner notification. New edge cases pin the MA count-all election, the NC hybrid gross-test denial and prorated benefit, and the student-income exclusion. Local runs: SNAP + TANF non-cash folders 492/492; partner SNAP edge cases, signatures, and fixtures 134/134. 🤖 Generated with Claude Code |
Re-review of b031fe8 ("Address review: boundary tests, partner contract updates, and medical citation")Re-reviewed the new commit from a clean checkout, hand-verified the arithmetic in every new test case, and ran all 14 changed test files locally against the PR code: 106/106 pass (36 partner edge-case tests + 70 unit/integration/contract tests), so every committed expected value is confirmed to be what the model produces. Findings from the previous review — status
The partner contract updates (amplifi, analytics_coverage federal/CA/MA/NC) are also now in, including two well-constructed new NC hybrid-state cases (gross-test full-count denial vs. net-side proration benefit) and a new MA count-all case. 🟡 New should-address items (introduced by this commit)
Local verification
Recommendation: unchanged — no blocking issues. Outstanding before merge: the two stale 🤖 Generated with Claude Code |
The TX refugee and undocumented cases' calculation comments still described full income counting with the pre-proration 2,546.82 math; rewrite them to walk through the 2/3 prorated share arithmetic that produces the committed 4,147.92 values. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
daphnehanse11
left a comment
There was a problem hiding this comment.
all review comments addressed, lgtm
Summary
Implements 7 CFR 273.11(c) and (d): the treatment of income, deductible expenses, and resources of household members who are ineligible for SNAP. Previously the model removed ineligible members from the household size but counted 100% of their income, and prorated only the employment income of work-requirement-failing members.
Addresses #6531; supersedes closed PR #6526.
Regulatory authority
What this implements
snap_unit_size(documented assumption)snap_earned_income).has_snap_elderly_disabled_member(7 CFR 271.2 defines an elderly or disabled member as a member of a household).snap_unit_size) was already correct and is unchanged (exclusion mask extracted intois_snap_excluded_member).is_snap_immigration_status_eligible.Structural changes
snap_earned_income_personbecomes a true Person-level variable (was SPMUnit with a unit-leveldefined_forgate). This fixes a pre-existing bug: an excluded K-12 child earner's income was counted whenever any countable earner existed in the unit.snap_unearned_income_person; unearned sources split intosources/unearned.yaml(person-level) +sources/unearned_spm_unit.yaml(tanf stays fully counted at the unit level — cannot be attributed to a member).sources/earned.yamlnow lists person-level employment income only; newsnap_gross_self_employment_income_person(floored per enterprise) feeds both the SE expense deduction and the unit-net attribution insnap_earned_income/snap_gross_test_income.snap_gross_test_incomemirrorssnap_gross_income's composition with the full-count share substituted, and returnssnap_gross_incomeexactly for households without full-count aliens. Newsnap_gross_test_income_fpg_ratiofeeds bothmeets_snap_gross_income_test(ratio-form comparison) and the TANF non-cash (BBCE) gross screen, so the hybrid states' full-count election cannot be bypassed via categorical eligibility.is_snap_excluded_member(273.11(c)/(d) exclusion mask, shared bysnap_unit_size,has_snap_elderly_disabled_member, and the asset test limit selection).snap_work_requirement_income_proration_fractionremoved; replaced bysnap_prorated_income_fraction+snap_income_counted_share(only internal consumers).Behavior changes (all intentional)
Not modeled (by design)
snap_unit_sizeconvention, now documented inis_snap_prorated_income_member)The partner contract tests under
tests/policy/baseline/partners/are updated in this PR (team and partner notified). All changes raise SNAP for mixed-status households; LPR cases are unchanged, andsignatures/,my_friend_ben, andimpacticaare unaffected (no mixed-status households). The headline for partners is the amplifi eligibility flip: that household was previously denied outright and now receives a benefit.edge_cases/.../snap/federal.yaml)federal.yaml)ca.yaml)ca.yaml)New partner edge cases pinning the state elections: MA count-all (3,815.82 — full counting yields less than TX's prorated 4,147.92 despite MA's SUA), NC hybrid gross-test denial at $48k (full income fails the gross and BBCE screens where prorated income would pass) and prorated benefit at $20k (4,147.92, matching TX), and an ineligible student whose excluded earnings are the only reason the household passes the gross test (287.68 minimum allotment).
Verification TODO
immigration_status(microsim aggregate impact) — default is CITIZENhas_all_usda_elderly_disabled(the AL/WV requires-all BBCE branch) should also exclude ineligible membersTest plan
🤖 Generated with Claude Code