Skip to content

Add Montana Child Care Assistance Program (Best Beginnings Child Care Scholarship)#8662

Draft
hua7450 wants to merge 3 commits into
PolicyEngine:mainfrom
hua7450:mt-ccap
Draft

Add Montana Child Care Assistance Program (Best Beginnings Child Care Scholarship)#8662
hua7450 wants to merge 3 commits into
PolicyEngine:mainfrom
hua7450:mt-ccap

Conversation

@hua7450

@hua7450 hua7450 commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator

Summary

Implements Montana's Child Care Assistance Program (Best Beginnings Child Care Scholarship) in PolicyEngine. The program is administered by Montana DPHHS, Early Childhood Services Bureau (ECSB), and is CCDF-funded. Subsidy = lesser of the provider's charge or the state maximum rate, minus the parent's sliding-scale copayment, floored at $0.

Closes #8661

Regulatory Authority

Eligibility

Requirement Source How modeled
Standard income limit (operational ceiling) Sliding Fee Scale (eff. 07-01-2025) mt_ccap_income_eligible — countable income <= 200% FPG (graduated tier; standard tier runs to 185%); see Regulatory Note
Over 85% SMI => not eligible Sliding Fee Scale footnote mt_ccap_income_eligiblecountable_income <= hhs_smi * 0.85 (param income/income_limit_smi_rate.yaml = 0.85)
Activity hours ARM 37.80.201; CC 2-3 mt_ccap_activity_eligible — two-parent 120/mo combined; single-parent 60/mo or full-time school/training
CCDF asset test ARM 37.80.202 (= 42 USC 9858n(4)(B)) reuses federal is_ccdf_asset_eligible
Immigration (child) landing page; 45 CFR 98.20 reuses federal is_ccdf_immigration_eligible_child
Montana residency + parent/child cohabitation ARM 37.80.201; CC 2-2 defined_for = StateCode.MT on mt_ccap_eligible; SPM-unit grouping co-locates parent and child
At least one eligible child ARM 37.80.202 add(spm_unit, period, ["mt_ccap_eligible_child"]) > 0
Eligible child age ARM 37.80.201; CC 2-1 (CCDF default) mt_ccap_eligible_child — age < 13, or < 19 if special needs (params eligibility/child_age_limit.yaml = 13, eligibility/special_needs_child_age_limit.yaml = 19)
Eligibility categories CC 1-7 non-TANF income pathway AND TANF categorical pathway via is_tanf_enrolled

Income Standards

  • FPG threshold: countable income at or below 200% FPG (operational Sliding Fee Scale ceiling — graduated tier). The standard tier runs to 185% FPG and the graduated tier (non-TANF over-income, continuation) extends to 200% FPG. Param income/fpg_limit.yaml = 2.
  • SMI ceiling: countable income above 85% of state median income (SMI) is a hard ineligibility overlay regardless of the FPG bracket (hhs_smi * 0.85).

Benefit Calculation

Subsidy = min(provider charge, state maximum rate) - copay, floored at $0, summed across eligible children.

  • Copay = max(GMI x FPG-bracket %, $10) for non-TANF families. TANF recipients (is_tanf_enrolled) pay a flat $10. The $10 minimum (param copayment/minimum.yaml) is both the non-TANF floor and the TANF flat amount.
  • Copay sliding scale (param copayment/copay_rate.yaml, keyed on the % FPG ratio): 0.5% at entry / 90 / 95 / 100% FPG, stepping up by 5-point FPG brackets to 7.0% at 185-200% FPG (21 standard brackets + 3 graduated brackets at 190/195/200%).
  • Provider maximum rate (param rates/provider_rates.yaml) is a 3-dimensional lookup: provider type (6) x age group (3) x half/full-time (2). Half-time = 5 or fewer hours/day; full-time = more than 5 up to 12 hours/day (ARM 37.80.205). mt_ccap_care_time defaults to FULL_TIME (we don't track per-day care hours at the moment). RCE / School-Age-Provider NA cells are encoded as 0 (not payable).

Requirements Coverage

REQ Description Parameter Variable Test
REQ-001 Eligible child under age limit (13 / special-needs 19) eligibility/child_age_limit.yaml, eligibility/special_needs_child_age_limit.yaml mt_ccap_eligible_child.py mt_ccap_eligible_child.yaml
REQ-002 Child + parent live together in Montana mt_ccap_eligible.py (defined_for=StateCode.MT) mt_ccap_eligible.yaml (Case 2 WY)
REQ-003 Household has >=1 eligible child mt_ccap_eligible.py mt_ccap_eligible.yaml (Case 3)
REQ-004 Activity hours (two-parent 120, single 60) eligibility/activity_hours/{two_parent,single_parent}.yaml mt_ccap_activity_eligible.py mt_ccap_activity_eligible.yaml
REQ-007 CCDF immigration check (federal) mt_ccap_eligible_child.py (is_ccdf_immigration_eligible_child) mt_ccap_eligible_child.yaml (Case 6)
REQ-008 CCDF asset test (federal) mt_ccap_eligible.py (is_ccdf_asset_eligible) mt_ccap_eligible.yaml (Cases 6, 7)
REQ-009 FPG income limit (operational ceiling) income/fpg_limit.yaml (= 2) mt_ccap_income_eligible.py mt_ccap_income_eligible.yaml
REQ-010 >85% SMI => not eligible income/income_limit_smi_rate.yaml (= 0.85) mt_ccap_income_eligible.py (hhs_smi) mt_ccap_income_eligible.yaml (Case 4)
REQ-011 Countable income sources income/countable_income/sources.yaml mt_ccap_countable_income.py mt_ccap_countable_income.yaml
REQ-013 Payment = min(charge, rate) - copay, floor 0 mt_ccap.py mt_ccap.yaml, integration.yaml
REQ-014 State max rates (6 x 3 x 2) rates/provider_rates.yaml mt_ccap_max_rate.py mt_ccap_max_rate.yaml (17 cases)
REQ-015 Half/full-time rate distinction rates/provider_rates.yaml mt_ccap_care_time.py mt_ccap_max_rate.yaml
REQ-019 RCE / School-Age-Provider NA cells = 0 rates/provider_rates.yaml mt_ccap_max_rate.py mt_ccap_max_rate.yaml (Case 12)
REQ-020 Copay = max(GMI x %, $10) copayment/minimum.yaml (= 10) mt_ccap_copay.py mt_ccap_copay.yaml
REQ-021 Copay % sliding scale (0.5% -> 7.0%) copayment/copay_rate.yaml mt_ccap_copay.py mt_ccap_copay.yaml (boundary cases)
REQ-022 TANF recipients flat $10 copay copayment/minimum.yaml mt_ccap_copay.py mt_ccap_copay.yaml (Case 6), integration.yaml (Case 4)
REQ-023 Graduated tier to 200% FPG (non-TANF) income/fpg_limit.yaml, copayment/copay_rate.yaml mt_ccap_income_eligible.py mt_ccap_income_eligible.yaml (Case 6)
REQ-026 Non-TANF + TANF eligibility pathways mt_ccap_income_eligible.py, mt_ccap_eligible.py mt_ccap_eligible.yaml (Case 8)

All 18 in-scope requirements have parameter/variable/test coverage. (REQ-015's day-hour auto-classification is by design not modeled — see Documented Assumptions; the half/full-time rate distinction itself is covered.)

Not Modeled

These features are documented limitations — we don't track the underlying inputs at the moment:

REQ What Why excluded
REQ-005 Teen parent (<=19) in HS/HiSET, no work requirement No teen-parent-in-school input
REQ-006 Disabled parent excluded from family minimum-hour calc No per-parent disability-in-activity input
REQ-012 Entry-level income floor = TANF GMI + $1 Entry-vs-redetermination income floor not tracked; bracket math is driven by % FPG
REQ-016 Full monthly authorization when attendance >=85% No per-day attendance input; assumes full-month authorization
REQ-017 Extended-care multipliers (12-18h = 1.25x, >18h = 1.5x) No daily-hours-in-care input at that granularity
REQ-018 No school-hours care for age 6+ as of Sept 10 No school-hours-care / school-calendar input
REQ-023 (timing) Graduated-tier redetermination timing (12-month / only-at-redet) No per-household redetermination clock
REQ-024 Funding-limited priority / waitlist categories Priority affects waitlist ordering, not benefit calc
REQ-025 Presumptive eligibility (30 days) No application-date / presumptive-period state
REQ-026 (sub-pathways) Tribal / Tribal-TANF / CFSD-referral eligibility categories No tribal-enrollment / CFSD-referral input
REQ-015 (derivation) Auto-classification of half- vs full-time by daily hours No per-day-hours-in-care input; care_time is a bare input defaulting to FULL_TIME

⚠️ Regulatory Note — FPG threshold conflict (reviewers must verify)

The body text of ARM 37.80.202 states the standard income limit is <= 150% FPG, with graduated eligibility from 150-185% FPG. However, the published Sliding Fee Scale (eff. 07-01-2025) runs the standard tier all the way to 185% FPG and the graduated tier to 200% FPG.

Per the user's decision, we encoded the operational Sliding Fee Scale values (standard 185% / graduated 200%), since the scale is the document caseworkers actually apply. Reviewers should confirm which source is authoritative and whether the ARM body text has been superseded by the published scale.

Documented Assumptions

  • Age-group month boundaries (Infant/Toddler 0-35 mo, Preschool 36-59 mo, School Age 60+ mo): the Provider Rates PDF gives no month cutoffs; CC 2-1 defers to a Policy Section 1-6 we couldn't access. Documented in the mt_ccap_child_age_category docstring.
  • Child age limits 13 / special-needs 19: CCDF defaults; ARM defers to the policy manual for the exact figures.
  • care_time defaults to FULL_TIME: there is no per-day-hours-in-care input, so half-time must be set explicitly.
  • tanf excluded from countable-income sources: avoids a childcare <-> TANF circular dependency. TANF families are instead handled via the is_tanf_enrolled categorical pathway plus the flat $10 copay branch.

Test plan

  • 108 tests pass locally (unit + integration + edge cases)
  • CI passes

Files Added

policyengine_us/parameters/gov/states/mt/dphhs/ccap/
├── age_group/months.yaml
├── copayment/copay_rate.yaml
├── copayment/minimum.yaml
├── eligibility/activity_hours/single_parent.yaml
├── eligibility/activity_hours/two_parent.yaml
├── eligibility/child_age_limit.yaml
├── eligibility/special_needs_child_age_limit.yaml
├── income/countable_income/sources.yaml
├── income/fpg_limit.yaml
├── income/income_limit_smi_rate.yaml
└── rates/provider_rates.yaml

policyengine_us/variables/gov/states/mt/dphhs/ccap/
├── mt_ccap.py
├── mt_ccap_care_time.py
├── mt_ccap_child_age_category.py
├── mt_ccap_copay.py
├── mt_ccap_countable_income.py
├── mt_ccap_max_rate.py
├── mt_ccap_provider_type.py
├── mt_child_care_subsidies.py
└── eligibility/
    ├── mt_ccap_activity_eligible.py
    ├── mt_ccap_eligible.py
    ├── mt_ccap_eligible_child.py
    └── mt_ccap_income_eligible.py

policyengine_us/tests/policy/baseline/gov/states/mt/dphhs/ccap/
├── integration.yaml
├── mt_ccap.yaml
├── mt_ccap_activity_eligible.yaml
├── mt_ccap_child_age_category.yaml
├── mt_ccap_copay.yaml
├── mt_ccap_countable_income.yaml
├── mt_ccap_eligible.yaml
├── mt_ccap_eligible_child.yaml
├── mt_ccap_income_eligible.yaml
├── mt_ccap_max_rate.yaml
└── mt_child_care_subsidies.yaml

Federal-registration edits (2 files):

  • policyengine_us/parameters/gov/hhs/ccdf/child_care_subsidy_programs.yaml — added mt_child_care_subsidies to the adds list
  • policyengine_us/programs.yaml — added the MT Best Beginnings state_implementations entry under the federal CCDF program (variable mt_child_care_subsidies, parameter prefix gov.states.mt.dphhs.ccap)

11 parameters, 12 variables, 11 tests.

🤖 Generated with Claude Code

hua7450 and others added 2 commits June 17, 2026 09:23
Scaffolding commit for the Montana Child Care Assistance Program
implementation. Adds changelog fragment.

Issue: PolicyEngine#8661

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…olicyEngine#8661)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@codecov

codecov Bot commented Jun 17, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (fbace93) to head (05650a4).
⚠️ Report is 24 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##              main     #8662    +/-   ##
==========================================
  Coverage   100.00%   100.00%            
==========================================
  Files            1        12    +11     
  Lines           23       188   +165     
==========================================
+ Hits            23       188   +165     
Flag Coverage Δ
unittests 100.00% <100.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Apply two-parent both-full-time-students activity waiver (CC 2-3); add
45 CFR 98.20 child-age citation; fix CC 2-6 page anchor; clean parameter
descriptions; add two-parent FT-student regression test.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

Add Montana Child Care Assistance Program (Best Beginnings Child Care Scholarship)

1 participant