Populate reported TANF, SNAP, and WIC enrollment from CPS admin-linkage fields (#591) - #600
Conversation
# Conflicts: # packages/populace-build/tests/test_us_multispine_pool.py
PAW_VAL > 0 conflates TANF with other cash welfare: the official ASEC
dictionaries split the program with PAW_TYP (1 TANF/AFDC, 2 other,
3 both), and in the 2023 ASEC 271 of 682 PAW-positive SPM units (39.7%
unweighted, 42.6% SPM-weighted) report no TANF type. The engine's
is_tanf_enrolled feeds TANF-specific cycle-safe helpers, so those units
must not be marked enrolled.
Restore PAW_TYP from the pinned official Census ASEC person archives —
the ED_VAL sidecar repair class, sharing its per-income-year archive
pins — carry it through the raw-stage checkpoint (schema v3, exact
integer composition audits per year), and gate the SPM-unit predicate
on any member reporting PAW_VAL > 0 with PAW_TYP in {1, 3}. Callers
deriving from frames without PAW_TYP must pass the pinned sidecar;
falling back to PAW_VAL alone is refused loudly.
Regenerated raw-stage checkpoint receipts: all 183 pre-existing columns
byte-identical, person.PAW_TYP the only addition; reported-TANF units
1,997 -> 1,191 across the pooled years (2022: 682 -> 411).
Fixes round-1 review finding on #600 (populace#591).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Round-1 finding addressed in c219b6f: |
Three of the five never-populated engine inputs from the #591 audit are class-1 admin-linkage facts the CPS actually reports. This wires them from the raw ASEC checkpoint through the pre-clone CPS-carried producer and the ACS transfer:
is_tanf_enrolledPAW_VAL(SPM-unit max > 0)receives_snapSPM_SNAPSUB(shared max-positive path with SNAP take-up seeding)receives_wicWICYN == 1WIC follows the carrier convention adjudicated on #591: Census asks adult women (possibly reporting for a child beneficiary), so the flag on the reporting adult IS the SPM unit's receipt fact, and unit-level aggregation is the only supported consumption grain. The consumer-existence guard now enforces that mechanically — every engine consumer of
receives_wicmust consume it atspm_unitgrain (both current consumers do: VAspm_unit.any, MDadd(spm_unit, …)); a synthetic person-grain consumer injected into the AST index fails CI by name with the adjudication link.All three document the annual-positive → all-12-month broadcast (unknown entry/exit timing; TANF's zero-dollar sanctioned-case limitation), with January and December live-engine tests. Transfer plan: 115 → 118 targets, surface 139, hash recomputed from the live registry at each step.
Medicaid stays unpopulated pending upstream policyengine-us#9206 (consumers read enrollment where eligibility is meant);
previous_year_income_available/qualified_bdc_incomeremain the two adjudicated gate-consumed exceptions.Verification: focused 12 + guards 190 + broader 308; full workspace 4,949 passed / 59 skipped; ruff + format +
git diff --checkclean; #583 guard unchanged at 495.Part of #591.
🤖 Generated with Claude Code