Skip to content

Make only an infant's own mother WIC postpartum or breastfeeding - #9923

Merged
PavelMakarchuk merged 3 commits into
mainfrom
wic-postpartum-own-infant
Oct 8, 2026
Merged

PavelMakarchuk merged 3 commits into
mainfrom
wic-postpartum-own-infant

Conversation

@PavelMakarchuk

@PavelMakarchuk PavelMakarchuk commented Oct 6, 2026 •

Copy link
Copy Markdown
Collaborator

Fixes #9874.

Change

wic_category made every mother in a family with an infant postpartum (and every breastfeeding mother in a family with an infant under one breastfeeding): is_mother & (family min age < 0.5). is_mother is any woman with her own child in the household, so a grandmother living with her daughter's baby was postpartum too and got the $899 postpartum food package.

The formula now matches each infant to one mother:

  1. Breastfeeding women first: a woman flagged is_breastfeeding is matched to an infant under one in her tax unit, else to any remaining infant in her family (youngest breastfeeding women first). She is BREASTFEEDING. The infants she takes leave the pools, oldest first, so she counts against an infant aged six months to one year before a younger one; at family level, infants in tax units without a mother are taken first.
  2. Then postpartum women: each remaining infant under six months is matched to one other mother in its tax unit (youngest first), and an infant whose tax unit has no mother (for example, a child put in its own tax unit) to one of the family's remaining mothers. A tax unit with n such infants has at most n postpartum women.

PolicyEngine has no parent-child links (own_children_in_household is a count, and is_mother / is_parent only test that count). The tax unit is the closest link the model has: in the CPS ASEC, 1,129 of the 1,148 infants (2023) and 1,163 of 1,177 (2022) whose mother lives in the household share her tax unit (TAX_ID); only 1,094 and 1,126 share her CPS family. In a three-generation tax unit, the youngest mother is usually the infant's mother. A woman reported as breastfeeding is matched first, because she is feeding an infant. is_pregnant, the infant and child categories, and the food package logic do not change. wic_category also cites 7 CFR 246.2 now.

Evidence

  • 7 CFR 246.2: "Postpartum women means women up to six months after termination of pregnancy." "Breastfeeding women means women up to one year postpartum who are breastfeeding their infants." The same definitions are in 42 U.S.C. 1786(b)(10) and (b)(1). Both categories depend on the woman's own pregnancy, so one birth makes one woman postpartum or breastfeeding.

  • Check against CPS parent pointers. The CPS ASEC records each person's parents (PEPAR1, PEPAR2), which PolicyEngine does not import. I ran the new formula on the raw CPS ASEC person records (PolicyEngine-US-data census_cps_{year}.h5, with the CPS tax units, families, ages, sex, and own_children_in_household built the same way as in cps.py) and compared the postpartum women with the women whom an infant's parent pointer names:

    CPS ASEC Mothers of infants (pointers) main: postpartum / wrong / missed This PR: postpartum / wrong / missed Households with more postpartum women than infants (main → this PR)
    2023 1,132 (2.47m weighted) 1,217 / 138 / 53 1,140 / 17 / 9 116 → 0
    2022 1,164 (2.42m weighted) 1,223 / 110 / 51 1,175 / 15 / 4 87 → 0

    Most remaining "wrong" cases are infants with no parent pointer in the household (for example, a foster child or a grandchild whose mother lives elsewhere) in a tax unit with a mother. Eight of the nine 2023 "missed" cases and all four 2022 cases are the second woman in a couple where both women are the infant's parents; only one of them can be postpartum. A rule that uses only the tax unit (no family step) missed 27 and 18 mothers; a rule that takes the youngest mothers in the family missed 67 and 61, because the CPS sometimes puts the mother and the infant in different families but the same tax unit.

Impact (Populace US 2024 file, 2025)

main This PR
Postpartum women 2.828m 2.484m
Infants (wic_category INFANT) 2.776m 2.776m
Households with more postpartum women than infants under six months (records) 150 of 1,640 0 of 1,640
WIC, postpartum women $1.200b $1.020b
WIC, total $11.687b $11.506b

Pregnant, infant, and child counts do not change. No record in this file has is_breastfeeding, so the breastfeeding count is zero in both runs.

Tests

New wic_category cases (2025):

  • Three generations in separate tax units (grandmother 50 alone; mother 25 with infant 0.2): [NONE, POSTPARTUM, INFANT]. main gives [POSTPARTUM, POSTPARTUM, INFANT].
  • Three generations in one tax unit: [NONE, POSTPARTUM, INFANT]. main gives [POSTPARTUM, POSTPARTUM, INFANT].
  • Infant in its own tax unit, grandmother 47 and mother 22 in another: the family step matches the infant to the mother, [NONE, POSTPARTUM, INFANT]. main gives [POSTPARTUM, POSTPARTUM, INFANT].
  • Breastfeeding mother 25 with an infant aged 0.2 and a grandmother: [NONE, BREASTFEEDING, INFANT]. main makes the grandmother postpartum.
  • Mother alone with an infant aged 0.2: [POSTPARTUM, INFANT] (no change).
  • Breastfeeding mother with an infant aged 0.8 and a grandmother: [NONE, BREASTFEEDING, INFANT] (no change).

Added after review:

  • A breastfeeding grandmother 38 (own infant 0.8) and a teen mother 17 (infant 0.2) in one tax unit: the teen is POSTPARTUM. An earlier version of this PR let the breastfeeding woman take the six-month match and left the teen NONE.
  • Two mothers with their own infants in one tax unit: both POSTPARTUM.
  • A father with an infant: no postpartum woman.
  • A mother of an infant aged 0.6 who is not breastfeeding: NONE.

Added after the second review:

  • A breastfeeding mother 20 in her own tax unit whose infant (0.3) is claimed by the grandmother 45: [NONE, BREASTFEEDING, INFANT]. The previous commit gave [POSTPARTUM, NONE, INFANT] (main gives the mother BREASTFEEDING and the grandmother POSTPARTUM).
  • Limitations pinned: a pregnant younger mother takes the match and stays PREGNANT ([NONE, PREGNANT, INFANT]); two breastfeeding women and one infant (the younger is BREASTFEEDING); two mothers and one infant in one tax unit (the younger is POSTPARTUM).

The first four in the first list fail on main and pass with this change. Results:

  • policyengine-core test policyengine_us/tests/policy/baseline/gov/usda/wic -c policyengine_us: 90 passed (86 before the second review). With the main formula, the four new cases above fail and the other 11 wic_category cases pass.
  • The 107 other YAML files that use wic_category, wic, wic_food_package, wic_if_takes_up, is_wic_eligible or meets_wic_categorical_eligibility (partner signatures, My Friend Ben, CCHIP, state tax integrations): 783 passed.
  • The issue repro (grandmother 45 alone, mother 22 with a newborn, TX 2025) now gives [NONE, POSTPARTUM, INFANT] and WIC of $0 for the grandmother.
  • ruff format and ruff check pass.

Limitations

  • When grandparents claim the infant in their tax unit and the mother files alone, the grandmother is matched, unless the mother is flagged is_breastfeeding. The CPS check finds this case rarely.
  • An infant whose mother is not in the household still makes a mother in its tax unit postpartum, as on main.
  • Twins: one mother of twins is one postpartum woman; a second appears only when the tax unit has a second mother (as on main). wic_breastfeeding_infant_count already covers twins for the food package.
  • A pregnant woman who is also a mother can take a postpartum match (she stays PREGNANT, which comes first), so a mother of an infant in the same tax unit can be left NONE. Excluding pregnant women instead would make a grandmother postpartum in the reverse case. Both are rare: no Populace tax unit has this combination.
  • When the father claims the infant and lives with his mother in a different tax unit, the family step can make the grandmother postpartum, as on main. In Populace, 97 women are postpartum through the family step; 89 are under 40 (mostly mothers whose unmarried partner claims the infant), 8 are 40 or older.
  • Matching the youngest mother first can pick a younger mother whose own child is older (e.g. a mother 40 with an infant and her daughter 17 with a toddler). Without parent links this is inherent; the CPS check bounds it.
  • Draft Medicaid MAGI household composition from co-resident parent ids (fixes #9404) #9406 adds optional parent_1_id / parent_2_id inputs. When the data has them, a later change can match infants to mothers through the links. This PR does not depend on Medicaid MAGI household composition from co-resident parent ids (fixes #9404) #9406 and touches different files.

🤖 Generated with Claude Code

PavelMakarchuk and others added 2 commits October 6, 2026 16:23
wic_category made every woman with her own child in the household
postpartum when the family had an infant, so a grandmother living with
her daughter's baby was postpartum too. 7 CFR 246.2 defines postpartum
and breastfeeding women by the time since their own pregnancy, so each
infant can make only one woman postpartum or breastfeeding.

Without parent-child links, match each infant to one mother in its tax
unit (breastfeeding mothers first, then the youngest), and an infant in
a tax unit without a mother to one of the family's remaining mothers.

Fixes #9874.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A breastfeeding mother of a 6-12 month old took the six-month match of
another mother's younger infant and left that mother uncategorized. Match
breastfeeding women first, then give the remaining infants under six months
to the other mothers. Adds regression tests for that case, two mothers in one
tax unit, a father-only household and a 0.6-year-old infant.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@PavelMakarchuk
PavelMakarchuk requested a review from hua7450 October 6, 2026 23:55

@hua7450 hua7450 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Read wic_category.py at f27d5c7 and on main, the new test file, is_mother, is_breastfeeding, is_pregnant and the consumers (is_wic_eligible, meets_wic_categorical_eligibility, wic_food_package), against 7 CFR 246.2 ("Breastfeeding women means women up to one year postpartum who are breastfeeding their infants"; "Postpartum women means women up to six months after termination of pregnancy") and 246.10(e). The direction is right: a pregnancy belongs to one woman, so one infant makes at most one woman postpartum or breastfeeding, and ordering breastfeeding before postpartum in the select matches 246.10(e)(5) to (7). All ten new cases and the nine existing ones recompute by hand, and the consumers are unchanged.

One gap, narrow but a regression from main on an explicit input, so requesting changes:

A woman flagged is_breastfeeding loses her category when the infant is claimed in another tax unit that contains a different is_mother woman. The breastfeeding pass only looks at infants in the woman's own tax unit, and at the family level only at infants in tax units with no mother at all:

bf_tax_unit, bf_family = match(
    mother,
    tax_unit.sum(infant),
    family.sum(infant & in_motherless_tax_unit),
)
breastfeeding_woman = breastfeeding & (bf_tax_unit | bf_family)

Household: grandmother 45 (female, own_children_in_household: 1, so is_mother), daughter 20 with is_breastfeeding: true, infant 0.3; tax units {grandmother, infant} and {daughter}. The infant's unit has a mother, so it is not "motherless" and the daughter's family step sees zero infants; her own unit has none. Result at head: grandmother POSTPARTUM, daughter NONE. Main gave the daughter BREASTFEEDING. Under 246.2 the daughter is the breastfeeding woman (Package V or VII) and the grandmother is nothing, so this configuration ends up worse than before on both rows. The limitations list covers "grandparents claim the infant and the mother files alone", but not that it overrides the one input that directly asserts the mother-infant link; is_breastfeeding is also what is_mother itself reads.

Suggested shape: match women flagged is_breastfeeding to any infant under one in their family first (capped at the family's infant count), take those infants out of the pools, and leave the tax-unit heuristic to the non-breastfeeding mothers. Only the breastfeeding pass changes; the postpartum pass already works from the remaining pools.

Nits, not blocking:

  1. The two-mother tie (breastfeeding mother 22 with infant 0.2 and non-breastfeeding mother 30 with infant 0.8 in one unit) resolves to 30 POSTPARTUM because the breastfeeding woman is assumed to own the older infant; the inputs cannot distinguish it from case 7, so a one-line comment that this is the assumption would help the next reader.
  2. _rank_mothers returns a non-negative rank for ineligible, non-breastfeeding persons; both call sites mask with eligible, so it is correct today, but where(eligible, ..., -1) would make the helper safe on its own.
  3. The limitations in the description (pregnant mother plus grandmother, two breastfeeding women and one infant, two-women couple) are not pinned by tests; one case each would lock the intended behaviour in.

Follow-up, pre-existing: young_infant = age < 0.5 drops an infant at exactly six months, while 246.7(g)(1)(ii) certifies the postpartum woman through the last day of the sixth month; same shape as the age < 1 windows.

A woman flagged is_breastfeeding lost her category when the infant was
claimed in another tax unit that had a different mother. Breastfeeding
women are now matched first: to an infant in their tax unit, else to
any remaining infant in their family. The matched infants (oldest
first; at family level, infants in tax units without a mother first)
leave the pools, and the tax-unit heuristic matches the other mothers
to the remaining infants under six months. Without is_breastfeeding
inputs the results do not change.

Tests: the reviewer's regression case, and one case each for the
pregnant-mother, two-breastfeeding-women and two-women-couple
limitations.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@PavelMakarchuk

Copy link
Copy Markdown
Collaborator Author

Thanks, fixed in 33dad79 as you suggested:

  • Breastfeeding first: a woman flagged is_breastfeeding is matched to an infant in her tax unit, else to any remaining infant in her family (capped at the family's infants). The infants she takes leave the pools (oldest first; at family level, infants in tax units without a mother first), and the tax-unit heuristic matches the other mothers to the remaining infants under six months. Your case (grandmother 45 with the infant 0.3, daughter 20 breastfeeding alone) now gives [NONE, BREASTFEEDING, INFANT]; it is a new test.
  • Nit 1: the comment now states the assumption that a breastfeeding woman and another mother in one tax unit have the older and the younger infant.
  • Nit 2: _rank_mothers is gone; the passes call get_rank with the eligible set as the condition, so ineligible people get its -1.
  • Nit 3: one test each for the pregnant mother plus grandmother, two breastfeeding women and one infant, and the two-women couple.
  • The six-month boundary (age < 0.5) is unchanged; I agree it is a separate follow-up.

Without is_breastfeeding inputs the results are the same as before, so the Populace impact in the description holds. wic tests: 90 passed; the 107 other YAML files that use the WIC variables: 783 passed; ruff passes.

@PavelMakarchuk
PavelMakarchuk requested a review from hua7450 October 7, 2026 18:50

@hua7450 hua7450 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving. Read wic_category.py and the test file at 33dad79 plus is_mother, is_breastfeeding, is_pregnant and the consumers, against 7 CFR 246.2 and 246.10(e).

The gap is fixed in the code: a woman flagged is_breastfeeding is matched first, to an infant in her tax unit or else to any infant left in her family (family.sum(infant) - family.sum(bf_in_tax_unit)), with no motherless-unit filter, and the infants she takes leave both pools (oldest first, motherless units first) before the postpartum pass runs on the remaining under-six-month infants. Walked the grandmother 45 / daughter 20 / infant 0.3 household: the daughter takes the infant at the family step, the grandmother finds no free young infant, result [NONE, BREASTFEEDING, INFANT], which is also the new regression case. The four match sets (bf_in_tax_unit, bf_in_family, pp_in_tax_unit, pp_in_family) are pairwise disjoint and each infant removal is bounded by the matched-woman count, so no woman is matched twice and no infant is counted twice, and without any is_breastfeeding input the formula reduces to the previous head, so the Populace figures in the description still hold. All 23 cases recompute by hand, including the three new pinning cases, the _rank_mothers helper is gone, and the assumption comment is in place.

Optional, not blocking: the where(in_motherless_tax_unit, 0, 2) - age ordering key reads better with a one-line note that 2 is just "larger than any infant age".

Pre-existing follow-ups, as you noted: the six-month boundary (age < 0.5 versus 246.7(g)(1)(ii)), twins beyond wic_breastfeeding_infant_count, and Package VI under 246.10(e)(6).

@PavelMakarchuk
PavelMakarchuk merged commit aa4a520 into main Oct 8, 2026
35 checks passed
@PavelMakarchuk
PavelMakarchuk deleted the wic-postpartum-own-infant branch October 8, 2026 13:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

WIC: wic_category makes every female parent in a family with an infant 'postpartum' (grandmothers included)

2 participants