PolicyEngine / PolicyEngine/microcosm

Export CPS parent pointers (PEPAR1/PEPAR2) as person-level parent ids

Open
#884 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
0
Forks
4
Avg merge
1d 3h
Merged PRs (30d)
94

Description

Summary

Export the CPS ASEC parent pointers (PEPAR1/PEPAR2) as two person-level columns that resolve to the parent's person_id within the same household. The build already reads and resolves these pointers to compute own_children_in_household (eligibility_inputs.py, _own_children_in_household), but only the count is exported. Downstream models therefore know that someone has children in the household, not whose children they are.

Why

PolicyEngine US infers parent relationships from the count. is_parent is own_children_in_household > 0, and the Medicaid MAGI "child living with both parents" exception (medicaid_tax_dependent_exception_living_with_both_parents.py) fires when the family contains more than one person with own children. In a three-generation household the grandparent counts as a second parent for every grandchild, so all children are evaluated under non-filer rules with a household that pools every adult's income.

Reproduced on Build P (populace_us_2024, build populace-us-2024-buildp-sparse-rmloss100-cae8640-20260728T011454Z, policyengine-us 1.764.6), household 1009324 (OH, 10 persons, 3 tax units, one family):

TCJA-expiration baseline after OBBBA standard deduction
17-year-old dependent ($13,774 wages) required to file yes ($8,300 threshold) no ($16,100 threshold)
children's Medicaid household income $141,848 (grandfather + two parents + teen) $128,075
household size used 10 10
percent of poverty vs Ohio child limit (211%) 211.46% 190.9%
children on Medicaid 0 7 (+$55,655)

Under 42 CFR 435.603(f)(2) the four children claimed by the 30-year-old parent would use that parent's tax household (60% of poverty) and the 3-year-old the 27-year-old's (88%); they are eligible in both worlds and the standard deduction moves nothing. The record is live at https://www.policyengine.org/us/obbba-household-explorer/?household=1009324&baseline=tcja-expiration as a $57,715 gain attributed to the standard deduction.

Aggregate impact in the OBBBA paper frames is negligible (2 records, weight ≈0.007), but the same proxy shapes every MAGI household determination for multigenerational families, and the Axiom encoding of 42 CFR 435.603 needs a real parent_of relation as a dataset input.

Proposal

  1. In eligibility_inputs.py, alongside own_children_in_household, emit parent_1_id and parent_2_id: the person_id of the household member at A_LINENO == PEPAR1 / PEPAR2 within the same PH_SEQ, and 0 when the pointer is absent or unresolved. Names should match the input variables added on the policyengine-us side (issue linked below); adjust both together if a different name is chosen there.
  2. Add the columns to US_ELIGIBILITY_INPUTS_OUTPUT_COLUMNS, the operator_boundary.py person allowlist, and the stage documentation in source_stages.json / spec/sources.yaml.
  3. Consistency check in the release gates: for every person, own_children_in_household equals the number of persons whose parent_1_id or parent_2_id points at them.
  4. ACS-transferred records: acs_pums.py synthesizes PEPAR1/PEPAR2 from the reference person and spouse lines (lines ~472–547). Confirm that path yields the same person_id resolution or leaves the ids at 0 rather than pointing at a non-parent.

A new certified data release is a separate step and is not in scope here.

Related observation (separate question)

Two weighted records in the same channel carry adult "dependents" whose earnings exceed the qualifying-relative gross-income test: household 1108166 (non-disabled 38-year-old, $13,638 wages, weight 18,661) and household 7428 (19-year-old non-student, $11,480 wages, weight 10,618). If the tax-unit builder places adult earners as dependents, that also feeds the other-dependent credit. Worth a look, but it is a different construction than the parent pointers.

Downstream

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with packages/microcosm-build/src/microcosm/build/us_runtime/eligibility_inputs.py and its existing _own_children_in_household resolution, then inspect acs_pums.py around lines 472–547. Trace the output columns, operator_boundary.py allowlist, and source_stages.json/spec/sources.yaml documentation. Done means parent_1_id and parent_2_id resolve same-household PEPAR pointers, unresolved values are 0, ACS-transferred records behave consistently, and the stated count consistency check is covered.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
data-engineering
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
58/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.