Skip to content

Implement North Dakota Child Care Assistance Program (CCAP)#8709

Draft
hua7450 wants to merge 4 commits into
PolicyEngine:mainfrom
hua7450:nd-ccap
Draft

Implement North Dakota Child Care Assistance Program (CCAP)#8709
hua7450 wants to merge 4 commits into
PolicyEngine:mainfrom
hua7450:nd-ccap

Conversation

@hua7450

@hua7450 hua7450 commented Jun 22, 2026

Copy link
Copy Markdown
Collaborator

Summary

Implements North Dakota's Child Care Assistance Program (CCAP) in PolicyEngine. CCAP is a provider-reimbursement childcare subsidy administered by the North Dakota Department of Health and Human Services (ND DHHS) under the federal Child Care and Development Fund (CCDF). The program reimburses providers up to a state maximum rate for eligible children in working or training families, net of an income-based family copay.

The implementation covers two-tier income eligibility (75% SMI at application / 85% SMI for enrolled families), the full 32-cell state maximum rate table (4 provider types x 4 age groups x full-time/part-time), an income-based copay with a 7% cap, and three provider-payment components: the special-needs +10% rate add-on and the additive QRIS-step and infant/toddler bonuses.

Closes #8708

Regulatory Authority

Program Overview

  • Administration: North Dakota Department of Health and Human Services (ND DHHS), Economic Assistance Policy Division, under the federal CCDF.
  • Agency directory: gov/states/nd/dhs/ccap (matches the existing nd/dhs/tanf convention).
  • Type: provider-reimbursement childcare subsidy. The benefit is paid to the provider; the family pays an income-based copay plus any charge above the state maximum rate.
  • Definition periods: all ND CCAP variables are MONTH-defined except the YEAR aggregator nd_child_care_subsidies, which feeds the federal YEAR child_care_subsidies.

Eligibility

Requirement Source How Modeled
Child under 13 (through 2026-03-31), under 12 (eff. 2026-04-01) §400-28-35-02; HHS 2026 update eligibility/child_age_limit.yaml ({2020-01-01: 13, 2026-04-01: 12}), compared via age * MONTHS_IN_YEAR in nd_ccap_eligible_child
Special-needs/court-ordered child eligible to under 19 §400-28-35-02 eligibility/disabled_child_age_limit.yaml (19), gated on is_disabled; court-ordered pathway not modeled (no input)
Child is US citizen or LPR (caretaker not subject) §400-28-50-25 (immigration_status == CITIZEN) | (immigration_status == LEGAL_PERMANENT_RESIDENT) — narrower than CCDF, so is_ccdf_immigration_eligible_child is not reused
At least one eligible child §400-28-35-02 nd_ccap_eligible requires add(spm_unit, ..., [nd_ccap_eligible_child]) > 0
Income ≤ 75% SMI (applicant) / 85% SMI (enrolled) §400-28-25-15 nd_ccap_income_eligible: where(is_nd_ccap_enrolled, 0.85, 0.75) * hhs_smi; rates in income/initial_smi_rate.yaml, income/continuing_smi_rate.yaml; new input is_nd_ccap_enrolled
Assets ≤ $1,000,000 (self-certified) §400-28-65-05 Reuses federal is_ccdf_asset_eligible (gov.hhs.ccdf.asset_limit = $1M); no ND asset parameter created
All caretakers in an allowable activity (no minimum hours) §400-28-55-05 nd_ccap_parent_in_eligible_activity (work/self-employment/student/training/incapacity/TANF) aggregated over head/spouse in nd_ccap_activity_eligible
Two-caretaker availability rule NDAC 75-02-01.3-11(1) Modeled implicitly by requiring all caretakers to be in activity; explicit "availability" not separately tracked
Family resides in North Dakota §400-28-50-05; NDCC 50-33-05 defined_for = StateCode.ND chain on all top-level variables

Income & Copay

  • Two-tier SMI test. Income eligibility uses hhs_smi (federal State Median Income by state and family size, read with the bare monthly period). Applicants must be at or below 75% SMI; enrolled families (via is_nd_ccap_enrolled) at or below 85% SMI, reflecting the graduated-eligibility provision in §400-28-25-15.
  • Countable income = gross monthly income (income/sources.yaml, a positive list of counted PolicyEngine variables mirroring the 46 income exclusions in §400-28-65-15), less children's earned income (excluded per §400-28-65-15 item 6), less court-ordered child and spousal support paid (§400-28-65-30, NDAC 75-02-01.3-09; modeled in nd_ccap_child_support_deduction from child_support_expense + alimony_expense). TANF cash is deliberately omitted from sources.yaml to avoid the CCAP→TANF circular dependency.
  • Copay (nd_ccap_copay) is a stepped percentage of countable income by % SMI band (copay/rate.yaml), waived at or below 30% SMI (copay/waiver_smi_threshold.yaml) and for TANF-enrolled families (is_tanf_enrolled, the only one of TANF/Diversion/Crossroads that is tracked), and capped at 7% of income (copay/max_rate.yaml, consistent with 45 CFR 98.45).
  • Copay percentages pending validation. The percentage schedule (≤30% → 0%, 30–40% → 6%, >40% → 7%) is reconstructed from the published DN 241 (10/2022) sliding-fee schedule, which lists 2%/3%/4%/6%/7%/7%/7% by SMI band capped at 7%, with the ≤30% bands superseded by the statutory waiver. North Dakota no longer publishes a static copay table; the current schedule lives only in the HHS Power BI "Worksheet for Calculating Copay." The bracket structure is in place so exact percentages can be dropped in once confirmed. See Verification TODO.

Provider Rate Table & Bonuses

  • State maximum rate table (rates/full_time.yaml, rates/part_time.yaml), effective 2026-01-01, keyed by breakdown: [nd_ccap_provider_type, nd_ccap_age_group]:
    • Provider types: Center (codes C,E,K,M), Licensed Family/Group (F,G,H), Self-Declared/Tribal Registered (S,R), Approved Relative (Q).
    • Age groups: Infant (birth–17 mo), Toddler (18–35 mo), Preschool (3–5 yr), Other/School-age (6 up to 13), classified in nd_ccap_age_group from age * MONTHS_IN_YEAR and is_in_k12_school.
    • Level of care: full-time (25+ hrs/wk) vs part-time (<25 hrs/wk), from nd_ccap_time_category (time_category/full_time_min_hours.yaml = 25).
    • All 32 rate cells were independently re-verified against the live HHS provider page (HTTP 200, browser UA) on 2026-06-21 — zero mismatches. Part-time values are independently sourced (not full-time/2), and full-time/part-time are not swapped.
  • Base subsidy (nd_ccap_base_subsidy) = max(min(state_max_rate, billed/expenses) − copay, 0), capped at spm_unit_pre_subsidy_childcare_expenses. Copay is subtracted only from the base subsidy.
  • Special-needs +10% (rates/special_needs_multiplier.yaml = 1.10): raises the per-child state maximum rate ceiling inside the min(rate, expenses) cap, gated on is_disabled AND nd_ccap_provider_qris_step >= STEP_2 (§400-28-100-30). is_disabled proxies the required written special-needs verification (the specific documentation type is not tracked). Cited to ND §400-28-100-30 — the manual text here carries stray Kentucky KRS citations that are a copy/paste artifact and are NOT treated as ND authority (a code comment flags this).
  • QRIS provider-step bonus (rates/qris_step_bonus_rate.yaml; nd_ccap_qris_step_bonus): date-varying % of the base SMR by provider QRIS step — 7/1/2025 era Step 2/3/4 = +5%/+10%/+15%, eff. 1/1/2026 = +0%/+5%/+10% (Step 2 eliminated).
  • Infant/toddler provider bonus (rates/infant_toddler_bonus.yaml; nd_ccap_infant_toddler_bonus): flat $200/infant-month and $115/toddler-month, eff. 2026-01-01, for children attending 40+ hrs/mo (approximated from childcare_hours_per_week via rates/infant_toddler_bonus_min_weekly_hours.yaml). Provider licensure jurisdiction (ND/tribal/military) is not tracked and is assumed met for non-approved-relative providers.
  • Both bonuses are modeled as ADDITIVE provider payments on top of the base subsidy — NOT capped at billed expenses and NOT reduced by copay — per §400-28-100-30, which states they "are separate from the service month payments ... and are not intended to be used for a child's billed amount."
  • New input variable: nd_ccap_provider_qris_step (Person, MONTH, Enum NDCCAPProviderQRISStep: STEP_1, STEP_2, STEP_3, STEP_4, UNRATED [default, placed last]). Read by both the QRIS-step bonus and the special-needs +10% gate.

Net-income framing note for reviewers: the QRIS-step and infant/toddler bonuses are paid to the provider and, per the manual, are "not intended for the child's billed amount," so they do not reduce family out-of-pocket childcare cost. Per the implementation decision they are nonetheless counted in nd_ccap and flow into child_care_subsidies. Reviewers and microsimulation users should be aware that these provider-side payments inflate the household benefit total without lowering the family's out-of-pocket cost.

Benefit composition: nd_ccap = base subsidy + QRIS-step bonus + infant/toddler bonus → nd_child_care_subsidies (YEAR) → federal child_care_subsidies.

Requirements Coverage

31 of 31 in-scope requirements are covered (parameter where value-based, variable where logic-based, and at least one test each); 0 missing.

REQ Description Parameter Variable Test
000 Provider QRIS step input (Enum) nd_ccap_provider_qris_step rates/nd_ccap_provider_qris_step.yaml (5)
001/002 Child age limit 13 → 12 eff. 2026-04-01 eligibility/child_age_limit nd_ccap_eligible_child nd_ccap_eligible_child.yaml (11)
003 Special-needs/disabled child to under 19 eligibility/disabled_child_age_limit (19) nd_ccap_eligible_child age 15/19 cases
004 Child citizen or LPR nd_ccap_eligible_child citizen vs non-LPR cases
005 ≥1 eligible child nd_ccap_eligible nd_ccap_eligible.yaml (6)
007–010 Two-tier 75%/85% SMI income income/initial_smi_rate, continuing_smi_rate nd_ccap_income_eligible nd_ccap_income_eligible.yaml (7)
011 Countable income (exclusions, minor earned) income/sources nd_ccap_gross_income, nd_ccap_countable_income nd_ccap_countable_income.yaml (5)
013 Asset test $1M (federal gov.hhs.ccdf.asset_limit) nd_ccap_eligible (reuses is_ccdf_asset_eligible) nd_ccap_eligible.yaml
015/016 Allowable activity, no min hours nd_ccap_parent_in_eligible_activity .yaml (6)
017 Two-caretaker availability proxy nd_ccap_activity_eligible .yaml (5)
018 ND residency defined_for = StateCode.ND chain state_code gating
019 Court-ordered support deduction nd_ccap_child_support_deduction .yaml (3)
020/023/024 Copay stepped % by SMI band, 7% cap copay/rate, copay/max_rate nd_ccap_copay nd_ccap_copay.yaml (10)
021/022 Copay waived ≤30% SMI / TANF copay/waiver_smi_threshold nd_ccap_copay copay cases
025/026 Benefit = base subsidy + bonuses nd_ccap_base_subsidy, nd_ccap nd_ccap_base_subsidy.yaml, integration.yaml (17)
027/028/030 Rate table (provider × age × FT/PT) rates/full_time, part_time nd_ccap_state_max_rate, nd_ccap_provider_type, nd_ccap_age_group nd_ccap_state_max_rate.yaml (17), nd_ccap_age_group.yaml (10)
029 Level of care FT/PT (25 hrs) time_category/full_time_min_hours nd_ccap_time_category nd_ccap_time_category.yaml (4)
031 Special-needs +10% SMR rates/special_needs_multiplier nd_ccap_state_max_rate state_max_rate + integration
034 QRIS-step bonus (additive) rates/qris_step_bonus_rate nd_ccap_qris_step_bonus nd_ccap_qris_step_bonus.yaml (9) + integration
035 Infant/toddler bonus (additive) rates/infant_toddler_bonus, infant_toddler_bonus_min_weekly_hours nd_ccap_infant_toddler_bonus nd_ccap_infant_toddler_bonus.yaml (7) + integration
051 Assistance-unit composition (partial) SPMUnit entity covered by entity structure

Federal wiring verified: nd_child_care_subsidies is in the adds list of child_care_subsidy_programs.yaml, and nd_ccap is registered in programs.yaml under North Dakota CCAP.

Not Modeled (by design)

What Source Why excluded
Foster-child licensing nuance §400-28-35-02 No foster-licensure input
Court-ordered (non-disability) child pathway to age 19 §400-28-35-02 No court-order input; disability pathway modeled
Income conversion (weekly ×4.3 / biweekly ×2.15) §400-28-70-05 PolicyEngine income is already annualized
Detailed asset exclusions §400-28-65-09 Subsumed by the $1M limit (effectively no test)
Diversion/Crossroads copay waiver §400-28-90-20 Only TANF enrollment is tracked
Whole-dollar rate rounding §400-28-100-30 Rates stored as published whole dollars
Legacy $60/mo state-licensed bonus Legacy guidebook Superseded by current rate tables
Registration fee (max $150/yr) HHS apply page A fee, not a subsidy component
Absence pay (up to 40 hrs/mo) HHS / §400-28 No attendance tracking
Minimum-attendance gate (40+ hrs/mo, eff. 2026-04-01) HHS 2026 update No attendance input; assumed met
Activity/job-search timing (15 hrs/wk, 3-month limit) §400-28-55-05 No job-search-status input
Parental-leave timing §400-28-55-05 No leave-status input
Approved-relative-caretaker activity bar §400-28-55-05 No caretaker-is-provider input
Postsecondary-after-bachelor's bar §400-28-55-05 No degree-held input
Child-hours add-ons (school-age +9 hr/wk, travel/night-shift) §400-28-80-10 Level of care uses childcare_hours_per_week directly
Max-2-providers / no mid-cert level decrease §400-28-80-50 Single childcare-expense input
18-month graduated-period tracking §400-28-25-15 No review-cycle/tenure tracking
Pre-2024-07-01 transitional cohort HHS / §400-28-25-15 Historical-cohort tracking
Payments < $10 not issued §400-28-100-40 De minimis; negligible population
Homeless special handling §400-28-38 Separate processing rules, not a copay waiver
Waitlist (eff. 2025-12-01) §400-28-20-10 Framework limitation — PolicyEngine does not model waitlists
Minor-parent separate-household split §400-28-35-05 Modeled implicitly via the SPMUnit

Verification TODO

  • Validate copay percentages (≤30% → 0%, 30–40% → 6%, >40% → 7%) against the current HHS Power BI "Worksheet for Calculating Copay." They are currently reconstructed from the DN 241 (10/2022) sliding-fee schedule; the bracket structure makes dropping in confirmed percentages trivial.
  • Rate tables reflect the 1/1/2026 HHS schedule; pre-2026 rate eras are not separately modeled (2026 rates backfill earlier periods). Confirm this is acceptable for historical analysis.
  • CI passes.

Test plan

  • 125 tests pass (policyengine-core test policyengine_us/tests/policy/baseline/gov/states/nd/dhs/ccap -c policyengine_us), covering all formula variables plus 17 integration scenarios.
  • Microsimulation chain verified: a single ND household flows nd_ccapnd_child_care_subsidies → federal child_care_subsidies with no circular dependency; a vectorized multi-SPM-unit run (2 ND + 1 TX) computes correctly and the non-ND unit is correctly zeroed by defined_for = StateCode.ND.
  • make format clean (ruff check passes).
  • CI passes.

Files Added

parameters/gov/states/nd/dhs/ccap/
  age_group/
    infant_max_months.yaml
    toddler_max_months.yaml
    preschool_min_months.yaml
  copay/
    rate.yaml
    max_rate.yaml
    waiver_smi_threshold.yaml
  eligibility/
    child_age_limit.yaml
    disabled_child_age_limit.yaml
  income/
    initial_smi_rate.yaml
    continuing_smi_rate.yaml
    sources.yaml
  rates/
    full_time.yaml
    part_time.yaml
    special_needs_multiplier.yaml
    qris_step_bonus_rate.yaml
    infant_toddler_bonus.yaml
    infant_toddler_bonus_min_weekly_hours.yaml
  time_category/
    full_time_min_hours.yaml

variables/gov/states/nd/dhs/ccap/
  nd_ccap.py
  nd_child_care_subsidies.py
  is_nd_ccap_enrolled.py
  eligibility/
    nd_ccap_eligible.py
    nd_ccap_eligible_child.py
    nd_ccap_income_eligible.py
    nd_ccap_activity_eligible.py
    nd_ccap_parent_in_eligible_activity.py
  income/
    nd_ccap_gross_income.py
    nd_ccap_countable_income.py
    nd_ccap_child_support_deduction.py
  copay/
    nd_ccap_copay.py
  rates/
    nd_ccap_base_subsidy.py
    nd_ccap_state_max_rate.py
    nd_ccap_provider_type.py
    nd_ccap_provider_qris_step.py
    nd_ccap_age_group.py
    nd_ccap_time_category.py
    nd_ccap_qris_step_bonus.py
    nd_ccap_infant_toddler_bonus.py

tests/policy/baseline/gov/states/nd/dhs/ccap/
  integration.yaml
  eligibility/   (nd_ccap_eligible, nd_ccap_eligible_child, nd_ccap_income_eligible,
                  nd_ccap_activity_eligible, nd_ccap_parent_in_eligible_activity)
  income/        (nd_ccap_countable_income, nd_ccap_child_support_deduction)
  copay/         (nd_ccap_copay)
  rates/         (nd_ccap_state_max_rate, nd_ccap_age_group, nd_ccap_time_category,
                  nd_ccap_base_subsidy, nd_ccap_provider_qris_step,
                  nd_ccap_qris_step_bonus, nd_ccap_infant_toddler_bonus)

Federal wiring edits:

  • parameters/gov/hhs/ccdf/child_care_subsidy_programs.yaml — added nd_child_care_subsidies to the adds list.
  • programs.yaml — registered North Dakota CCAP (variable nd_ccap) as a state implementation under federal CCDF.
  • changelog.d/nd-ccap.added.md — changelog fragment.

🤖 Generated with Claude Code

hua7450 and others added 2 commits June 21, 2026 21:41
Closes PolicyEngine#8708

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Child Care Assistance Program (NDAC 75-02-01.3; Manual Service Chapter
400-28, ML 3930): two-tier SMI income test (75% applicant / 85% enrolled),
provider max-rate table (4 provider types x 4 age groups x FT/PT),
stepped-%SMI copay (waived <=30% SMI, capped 7%), special-needs +10% SMR,
QRIS step bonuses, infant/toddler provider bonus. Wired into federal CCDF
child_care_subsidies and programs.yaml.

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

codecov Bot commented Jun 22, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (47cb26b) to head (2487efd).
⚠️ Report is 13 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##              main     #8709    +/-   ##
==========================================
  Coverage   100.00%   100.00%            
==========================================
  Files            3        20    +17     
  Lines           47       312   +265     
==========================================
+ Hits            47       312   +265     
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.

hua7450 and others added 2 commits June 22, 2026 00:07
- C1: revert child age limit to under-13 (unsourced 2026-04-01 under-12 entry removed)
- C2: infant/toddler bonus gated on QRIS step 2+ and licensed provider; drop unsourced hours gate
- C3: children's earned-income exclusion corrected to under-19 (NDAC 75-02-01.3-08(12))
- A1: document incapacity (400-28-35-15) basis for disabled-caretaker activity
- A2: add top-level nd_ccap unit test

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

- Remove stale '40 hours/month' comment from infant_toddler_bonus.yaml (no hours gate after R1)
- Document child-age grace-month and CCAP Workforce Benefit waiver as not-modeled

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.

Implement North Dakota Child Care Assistance Program (CCAP)

1 participant