Assign SNAP take-up from state participation rates#375
Conversation
MaxGhenis
left a comment
There was a problem hiding this comment.
Review (draft) — not merging; the code is healthy on main, but the calibration basis is inconsistent with the merged #371, and this overlaps #376.
Reviewing per request while this is a draft. The mechanism is clean and it rebases and tests green on current main (details below), so the blocker is a design/basis question, not code.
Core issue: the seed basis differs from what #371 now calibrates to
This stage calibrates the take-up flag to FY2022 FNS eligible-person participation rates. #371 (merged today) added snap_households weight-calibration targets that pin per-state FY2024 average-monthly household caseloads. Those are different measures (person-rate vs household-count) and different vintages (FY2022 vs FY2024), so on current main the seed and the weight-calibration objective are not pinning the same quantity — the double-pressure the two stages are supposed to avoid. #376 implements the same #372 goal by seeding to the FNS average_monthly_households facts #371's targets compile from, so its seed and #371's calibration agree by construction. As written, this PR would need to move to the household-caseload basis (i.e., converge with #376) — or the team picks one of the two #372 approaches — before it's consistent with the merged surface.
The four scrutiny points
- FY2022-on-2024 vintage — transparently recorded, assumption not stated. The manifest carries
"vintage": "fiscal_year_2022", the notes cite Reaching Those in Need: 2022 Table 1, and the 100%-cap rounding limitation is documented. What's missing is a one-line acknowledgment that FY2022 is the latest published rate applied to the 2024 frame under a rate-stability assumption — worth stating explicitly (as #371 did for its own concept gap). - Take-up contract / register-consistency — verified clean.
takes_up_snap_if_eligiblestaysout_of_scope, so it's outside register-consistency's seed / count_calibrated signal registers and outside the rate-schema validation (which only fires forseed). Removingrate.valuein favor of the state/period/measure block is therefore fine for anout_of_scopeentry. Rebased ontomainit passesassert_take_up_contract_currentand the register-consistency test. - Eligible-person weighting vs SPM-unit flag — documented and coherent, with a marginal caveat. The anchor (reported
SPM_SNAPSUB > 0) and the person-weighted top-up (design weight × modeledsnap_unit_size) are clearly described. The residual is conceptual: matching a person participation rate by flipping whole SPM units is an approximation at the margin (a unit is all-in or all-out at its person weight). Fine as a design choice, but note it — and it is the same reason the caseload-count basis (#376/#371) is a cleaner fit for a unit-grain flag. - Conflict with #371 — the core issue above. No textual conflict (this PR touches
snap_take_up.py/take_up_contract.json/source_stages.json/ the builder; #371 touchedledger_targets.py/fiscal_targets.py, zero overlap), but a semantic one: person-rate seed vs household-count calibration.
Mechanics I verified
Rebases cleanly onto current main (single commit, no conflicts); test_us_snap_take_up.py + test_us_take_up_contract.py (22 tests) and the register-consistency / contract-preflight / snap slices of the builder test all pass on the rebased state. So it is technically healthy — the open question is which #372 basis to standardize on. Since #376 already implements the household-caseload basis consistently with the merged #371, the cleanest path is likely to converge there; flagging now, before more work, rather than after.
|
Closing in favor of #376, which implements #372 on the household-caseload basis: it seeds the taker set to the same FNS Worth salvaging from here: the FY2022 FNS Reaching Those in Need state participation-rate manifest (Table 1, with the 100%-cap and rounding caveats documented) is a good validator — an independent, sourced check that per-state modeled participation among eligibles lands near FNS's estimates — even though it isn't the seeding basis. If someone picks that up, this can be reopened or mined for the manifest, diagnostics, and the eligible-person weighting machinery. The state-grain gate ideas here (missing-rate hard-fail, anchor preservation, collapsed-eligibility and universal-take-up landmine checks) all have counterparts in #376's gate, so nothing release-blocking is lost by closing. |
Summary
snap_unit_size) while preserving reportedSPM_SNAPSUB > 0recipients as an anchoris_snap_eligibleandsnap_unit_sizeSource and semantics
The manifest now carries USDA FNS's Reaching Those in Need: Estimates of State SNAP Participation Rates in 2022, Table 1:
The estimates measure the share of eligible people participating in an average month. FNS publishes whole-percentage estimates and reports estimates at or above 100% as 100%; the manifest and diagnostics document that limitation.
Verification
uv run pytest packages/populace-build/tests -quv run ruff check ...uv run ruff format --check ...git diff --checkCloses #372