Skip to content

Materialize Medicaid and CHIP take-up via anchored count-calibration (ACA stage pattern) #331

Description

@daphnehanse11

Context

The #315 take-up contract marks takes_up_medicaid_if_eligible and takes_up_chip_if_eligible as rate_unsourced: us-data's state rates (0.53–0.99) are model-relative ratios (MACPAC enrollment over modeled eligibility) that fail the provenance rule, and no administrative participation rate clears the bar. A fixed-rate seed stage (the #294 SNAP pattern) is therefore doctrine-blocked for these programs.

Meanwhile the all-True defaults are actively harmful:

The doctrine-compliant path already exists in-repo: the native ACA stage (aca_marketplace_inputs in source_stages.json) anchors on reported coverage and fills via assign_binary_from_rate + calibrate_binary_assignment to CMS count facts — no participation rate cited. Those ops are generic in source_runtime.py (parameterized output/anchor/eligibility/domain/weight), just cosmetically labeled ACA. This is also how Urban's HIPSM works: survey-reported coverage anchors, and take-up fills the gap to a CMS point-in-time enrollment snapshot.

Goal

A person-grain source stage materializing both flags: reported-coverage anchored, count-calibrated to the cms_medicaid state monthly-snapshot facts, with release diagnostics and a degeneracy gate — delivering the follow-up #170's acceptance criteria anticipate.

Suggested implementation

  • Builder frame prep: engine simulation computes person-level is_medicaid_eligible / is_chip_eligible, mirroring the ACA _calculate_array pattern in build_us_fiscal_refresh_release.py (~line 1785).
  • Anchor: has_medicaid_health_coverage_at_interview (already carried in cps_carried.py). Reported recipients who are model-eligible always take up; document the reported-but-model-ineligible decision explicitly (ACA masks the anchor by eligibility; SNAP anchors unconditionally).
  • Fill: assign_binary_from_rate with an in-build state rate (CMS snapshot over weighted modeled eligibles, mirroring the ACA rate derivation) on stable person draws, then calibrate_binary_assignment to state enrollment facts with preserve_true_anchors, domain: is_medicaid_eligible, person weights. Generalize the ACA-specific labels/salts of the binary ops as needed.
  • CHIP: blocked in M-CHIP states until CHIP enrollment targets are concept-mismatched: CMS total_chip_enrollment includes M-CHIP; model materializes separate CHIP only (20 states zero-support) #321's concept mapping lands — either calibrate CHIP fill only where separate-CHIP concept support exists, or sequence behind the M-CHIP/separate-CHIP ledger split.
  • Contract: move Medicaid/CHIP from rate_unsourced to a new treatment value (e.g. count_calibrated: anchored assignment calibrated to administrative counts, no participation rate cited). This is a doctrine amendment to the Seed TANF and EITC take-up from administrative rates; engine-asserted take-up contract (#312) #315 enum and needs contract-owner review.
  • Gate + diagnostics (per Add Medicaid and CHIP eligibility-to-enrollment diagnostics #170): eligible count, enrolled count, ratio, nationally and by state. Fail on the all-True landmine; distinguish legitimate saturation where modeled eligibles < CMS target (combined eligibles 77.28M < CMS 79.15M means some states saturate by eligibility undercount, not by flag degeneracy).

Acceptance criteria

  • Both flags materialized and non-degenerate nationally and per state, except documented saturated states.
  • Anchored reporters preserved through calibration; stable identity across repeated builds.
  • Contract records the new treatment with doctrine text; take-up contract test passes against the pinned engine.
  • Add Medicaid and CHIP eligibility-to-enrollment diagnostics #170 diagnostics emitted; the gate distinguishes landmine from saturation.
  • Weight calibration on medicaid_enrolled runs against take-up-materialized enrollment rather than raw eligibility.

Enrollment-concept semantics (point-in-time vs annual) are declared in the companion doctrine issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions