Compile USDA SNAP state and national caseload targets from FNS average-monthly facts#371
Compile USDA SNAP state and national caseload targets from FNS average-monthly facts#371daphnehanse11 wants to merge 3 commits into
Conversation
…e-monthly facts The ledger usda-snap-fy69-to-current package already ships average_monthly_households and average_monthly_persons record sets at national and per-state grain alongside the total_benefits facts populace compiles today, but only the dollar measures were mapped. That leaves the SNAP surface dollars-only: a build can hit a state's benefit total with an unrepresentative recipient set, and nothing pins caseload or average benefit per household. Map both caseload measures as indicator_sum targets over the simulated taker set: SPM units with positive annual snap (households) and their members via indicator_map_to person (persons). The take-up assignment (#294) seeds takers to reproduce the FNS participation rate, so the taker set is the model counterpart of the average monthly caseload. FNS caseload facts carry aggregation 'mean' (a fiscal-year mean of monthly stock counts), which the ledger compile guard rejected wholesale. Add an explicit per-mapping fact_aggregation=time_mean contract: a time-mean of a stock count is still a linear level target, while per-unit ratios (e.g. average_monthly_benefit_per_person) remain rejected by default. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…cipants ~50% Previewing both indicator targets against the buildi-sparse release showed the household mapping lands at -1.4% of the FY2024 FNS national average (21.89M vs 22.20M) with no calibration pressure, while the person mapping overcounts by +48% (61.8M vs 41.7M): the real SNAP assistance unit is often a subset of the SPM unit (FNS persons per household 1.88 vs 2.82 members per simulated taker unit) and PolicyEngine-US does not model sub-unit participation. Calibrating to the person counts would fight the household target, so the persons measure stays unmapped, with a test pinning that it does not compile. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Preview of the compiled household-caseload targets evaluated against National: 21.89M weighted taker units vs 22.20M FNS (−1.4%). Feasibility ceiling under the 5× weight cap: 3.75× the target. States (largest household-count errors, current weights):
Two observations:
The persons measure was dropped from the mapping after the same preview showed a structural +48% overcount (see second commit); the per-state persons errors ranged +11% to +398% with the bias always positive, confirming it is a unit-definition mismatch rather than noise. |
Implements #370.
What
Maps the FNS household-caseload measure the ledger
usda-snap-fy69-to-currentpackage already ships (national + per-state, alongside thetotal_benefitsfacts populace compiles today) into calibration targets:("usda_snap", "average_monthly_households")→indicator_sumover SPM units with positive annualsnap(target_rolesnap_households)It flows through the existing
INDICATOR_LEDGER_TARGETS→_direct_reference_from_factmachinery, so state facts compile per state withstate_fipsmetadata automatically, exactly like the benefit-dollar targets.average_monthly_personsis deliberately not mapped (second commit): previewed against the buildi-sparse release, a person indicator over taker-unit members overcounts FNS participants by +48% (61.8M vs 41.7M) because the real SNAP assistance unit is often a subset of the SPM unit (FNS persons per household 1.88 vs 2.82 members per simulated taker unit) and PolicyEngine-US does not model sub-unit participation. A test pins that the persons measure does not compile.Aggregation contract change
FNS caseload facts carry
aggregation: mean(a fiscal-year mean of 12 monthly stock counts), andtarget_spec_from_ledger_referencerejected every non-sum fact. This PR adds a scoped opt-in: a mapping may declarefact_aggregation: time_mean, asserting the mean is taken over time periods on a stock count — still a linear level target. Per-unit ratios (e.g.average_monthly_benefit_per_person) remain rejected by default, and a new test pins the rejection of mean facts without the contract.Concept mapping and validation
The compiled counts are of the simulated taker set. The take-up assignment (#294) seeds takers to reproduce the FNS participation rate, so the taker set is the model counterpart of the average monthly caseload rather than an annual-ever count. Previewed on
populace-us-2024-buildi-sparse-rmloss100with shipped weights: 21.89M weighted taker units vs the 22.20M FY2024 FNS national average (−1.4%) with no calibration pressure on counts. Per-state preview in the PR comment below.Why
The SNAP surface is currently dollars-only. In the default release, 10 states undershoot their benefit targets by 7–43% while a feasibility audit shows all but CA are reachable within the 5× weight cap — the dollar targets lose loss-weight trades (the
usda_snapfamily holds ~0.9% of total loss weight under sqrt-value weighting). Caseload counts land in the count basis, which holds its own half of the 50/50 loss budget, raising SNAP's effective share within the standard scheme; and dollars + caseload jointly pin average benefit per household, anchoring recipient composition for downstream reform work. Full audit numbers in #370.Dependency
Targets compile only for facts present in the consumer feed. If the current
consumer_facts_buildh_v8.jsonlfilters out the caseload measures, the consumer bundle needs regeneration before these targets appear in a build.Tests
test_snap_household_caseload_fact_maps_to_snap_indicator(national, household grain)test_state_snap_household_caseload_fact_compiles_with_state_fips(state grain,state_fips)test_snap_person_caseload_fact_is_not_compiled(persons stays unmapped)test__given_mean_fact_without_time_mean_contract__then_compilation_fails(doctrine guard)test_us_fiscal_targets.pyandtest_ledger_targets.pypass.🤖 Generated with Claude Code