From 6d8dc00b99478076286584f505a837d96ffb24b1 Mon Sep 17 00:00:00 2001 From: Ziming Date: Thu, 26 Mar 2026 11:09:16 -0400 Subject: [PATCH 01/13] Initial commit for Maryland CCAP implementation Co-Authored-By: Claude Opus 4.6 (1M context) --- changelog.d/md-ccap.added.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/md-ccap.added.md diff --git a/changelog.d/md-ccap.added.md b/changelog.d/md-ccap.added.md new file mode 100644 index 00000000000..e58dd10c19d --- /dev/null +++ b/changelog.d/md-ccap.added.md @@ -0,0 +1 @@ +Implement Maryland CCAP (Child Care Assistance Program). From 59fef63d1d2746d7f4fb2bbdf75ff4725f2bf192 Mon Sep 17 00:00:00 2001 From: Ziming Date: Thu, 26 Mar 2026 12:48:02 -0400 Subject: [PATCH 02/13] Implement Maryland Child Care Scholarship (CCS) program Adds eligibility, income calculation, copayment, and provider reimbursement rate parameters for Maryland's CCS program (COMAR 13A.14.06). Includes formal rates (7 regions) and informal rates (24 counties), enum-keyed parameter lookups, and 78 test cases. Closes #7888 Co-Authored-By: Claude Opus 4.6 (1M context) --- .../hhs/ccdf/child_care_subsidy_programs.yaml | 1 + .../md/msde/ccs/age_threshold/child.yaml | 11 + .../ccs/age_threshold/disabled_child.yaml | 11 + .../md/msde/ccs/copay/federal_cap_rate.yaml | 11 + .../ccs/copay/max_children_with_copay.yaml | 11 + .../states/md/msde/ccs/copay/unit_hours.yaml | 25 + .../md/msde/ccs/copay/weekly_amount.yaml | 20 + .../ccs/income/countable_income/sources.yaml | 31 + .../self_employment_deduction_rate.yaml | 11 + .../ccs/income/smi_rate/continuation.yaml | 13 + .../md/msde/ccs/income/smi_rate/initial.yaml | 15 + .../ccs/payment/baltimore_city_counties.yaml | 12 + .../ccs/payment/formal/licensed_center.yaml | 119 ++ .../ccs/payment/formal/licensed_family.yaml | 119 ++ .../ccs/payment/infant_age_threshold.yaml | 13 + .../md/msde/ccs/payment/informal/rates.yaml | 370 +++++ .../msde/ccs/payment/region_u_counties.yaml | 16 + .../msde/ccs/payment/region_v_counties.yaml | 16 + .../msde/ccs/payment/region_x_counties.yaml | 13 + .../msde/ccs/payment/region_y_counties.yaml | 14 + .../msde/ccs/payment/region_z_counties.yaml | 14 + .../gov/states/md/msde/ccs/edge_cases.yaml | 1236 +++++++++++++++++ .../gov/states/md/msde/ccs/integration.yaml | 424 ++++++ .../gov/states/md/msde/ccs/md_ccs.yaml | 176 +++ .../md/msde/ccs/md_ccs_countable_income.yaml | 98 ++ .../states/md/msde/ccs/md_ccs_eligible.yaml | 114 ++ .../md/msde/ccs/md_ccs_eligible_child.yaml | 132 ++ .../md/msde/ccs/md_ccs_income_eligible.yaml | 115 ++ .../md/msde/ccs/md_ccs_payment_rate.yaml | 122 ++ .../md/msde/ccs/md_ccs_weekly_copay.yaml | 242 ++++ .../msde/ccs/eligibility/md_ccs_eligible.py | 20 + .../ccs/eligibility/md_ccs_eligible_child.py | 22 + .../gov/states/md/msde/ccs/md_ccs.py | 33 + .../md/msde/ccs/md_ccs_countable_income.py | 26 + .../gov/states/md/msde/ccs/md_ccs_enrolled.py | 9 + .../md/msde/ccs/md_ccs_income_eligible.py | 25 + .../md/msde/ccs/md_ccs_provider_type.py | 18 + .../md/msde/ccs/md_ccs_receives_snap.py | 9 + .../states/md/msde/ccs/md_ccs_receives_wic.py | 9 + .../states/md/msde/ccs/md_ccs_weekly_copay.py | 54 + .../md/msde/ccs/md_child_care_subsidies.py | 11 + .../md/msde/ccs/payment/md_ccs_age_group.py | 26 + .../msde/ccs/payment/md_ccs_payment_rate.py | 41 + .../md/msde/ccs/payment/md_ccs_region.py | 51 + .../msde/ccs/payment/md_ccs_service_unit.py | 28 + sources/working_references.md | 271 ++++ 46 files changed, 4178 insertions(+) create mode 100644 policyengine_us/parameters/gov/states/md/msde/ccs/age_threshold/child.yaml create mode 100644 policyengine_us/parameters/gov/states/md/msde/ccs/age_threshold/disabled_child.yaml create mode 100644 policyengine_us/parameters/gov/states/md/msde/ccs/copay/federal_cap_rate.yaml create mode 100644 policyengine_us/parameters/gov/states/md/msde/ccs/copay/max_children_with_copay.yaml create mode 100644 policyengine_us/parameters/gov/states/md/msde/ccs/copay/unit_hours.yaml create mode 100644 policyengine_us/parameters/gov/states/md/msde/ccs/copay/weekly_amount.yaml create mode 100644 policyengine_us/parameters/gov/states/md/msde/ccs/income/countable_income/sources.yaml create mode 100644 policyengine_us/parameters/gov/states/md/msde/ccs/income/self_employment_deduction_rate.yaml create mode 100644 policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_rate/continuation.yaml create mode 100644 policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_rate/initial.yaml create mode 100644 policyengine_us/parameters/gov/states/md/msde/ccs/payment/baltimore_city_counties.yaml create mode 100644 policyengine_us/parameters/gov/states/md/msde/ccs/payment/formal/licensed_center.yaml create mode 100644 policyengine_us/parameters/gov/states/md/msde/ccs/payment/formal/licensed_family.yaml create mode 100644 policyengine_us/parameters/gov/states/md/msde/ccs/payment/infant_age_threshold.yaml create mode 100644 policyengine_us/parameters/gov/states/md/msde/ccs/payment/informal/rates.yaml create mode 100644 policyengine_us/parameters/gov/states/md/msde/ccs/payment/region_u_counties.yaml create mode 100644 policyengine_us/parameters/gov/states/md/msde/ccs/payment/region_v_counties.yaml create mode 100644 policyengine_us/parameters/gov/states/md/msde/ccs/payment/region_x_counties.yaml create mode 100644 policyengine_us/parameters/gov/states/md/msde/ccs/payment/region_y_counties.yaml create mode 100644 policyengine_us/parameters/gov/states/md/msde/ccs/payment/region_z_counties.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/edge_cases.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/integration.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_countable_income.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_eligible.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_eligible_child.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_income_eligible.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_payment_rate.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_weekly_copay.yaml create mode 100644 policyengine_us/variables/gov/states/md/msde/ccs/eligibility/md_ccs_eligible.py create mode 100644 policyengine_us/variables/gov/states/md/msde/ccs/eligibility/md_ccs_eligible_child.py create mode 100644 policyengine_us/variables/gov/states/md/msde/ccs/md_ccs.py create mode 100644 policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_countable_income.py create mode 100644 policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_enrolled.py create mode 100644 policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_income_eligible.py create mode 100644 policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_provider_type.py create mode 100644 policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_receives_snap.py create mode 100644 policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_receives_wic.py create mode 100644 policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_weekly_copay.py create mode 100644 policyengine_us/variables/gov/states/md/msde/ccs/md_child_care_subsidies.py create mode 100644 policyengine_us/variables/gov/states/md/msde/ccs/payment/md_ccs_age_group.py create mode 100644 policyengine_us/variables/gov/states/md/msde/ccs/payment/md_ccs_payment_rate.py create mode 100644 policyengine_us/variables/gov/states/md/msde/ccs/payment/md_ccs_region.py create mode 100644 policyengine_us/variables/gov/states/md/msde/ccs/payment/md_ccs_service_unit.py create mode 100644 sources/working_references.md diff --git a/policyengine_us/parameters/gov/hhs/ccdf/child_care_subsidy_programs.yaml b/policyengine_us/parameters/gov/hhs/ccdf/child_care_subsidy_programs.yaml index 7a253af1f86..1d8237aacd3 100644 --- a/policyengine_us/parameters/gov/hhs/ccdf/child_care_subsidy_programs.yaml +++ b/policyengine_us/parameters/gov/hhs/ccdf/child_care_subsidy_programs.yaml @@ -4,6 +4,7 @@ values: - ca_child_care_subsidies # California Child Care - co_child_care_subsidies # Colorado Child Care Assistance Program - ma_child_care_subsidies # Massachusetts Child Care Financial Assistance + - md_child_care_subsidies # Maryland Child Care Scholarship - me_child_care_subsidies # Maine Child Care Affordability Program - ne_child_care_subsidies # Nebraska Child Care Subsidy - nh_child_care_subsidies # New Hampshire Child Care Scholarship Program diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/age_threshold/child.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/age_threshold/child.yaml new file mode 100644 index 00000000000..3d81b4a1ef6 --- /dev/null +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/age_threshold/child.yaml @@ -0,0 +1,11 @@ +description: Maryland limits the Child Care Scholarship program to children under this age. +values: + 2018-01-01: 13 + +metadata: + unit: year + period: year + label: Maryland CCS child age threshold + reference: + - title: COMAR 13A.14.06.02 - Definitions, "Child" + href: https://dsd.maryland.gov/regulations/Pages/13A.14.06.02.aspx diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/age_threshold/disabled_child.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/age_threshold/disabled_child.yaml new file mode 100644 index 00000000000..55a67bc8011 --- /dev/null +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/age_threshold/disabled_child.yaml @@ -0,0 +1,11 @@ +description: Maryland limits the Child Care Scholarship program to disabled children under this age. +values: + 2018-01-01: 19 + +metadata: + unit: year + period: year + label: Maryland CCS disabled child age threshold + reference: + - title: COMAR 13A.14.06.02 - Definitions, "Child" + href: https://dsd.maryland.gov/regulations/Pages/13A.14.06.02.aspx diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/copay/federal_cap_rate.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/copay/federal_cap_rate.yaml new file mode 100644 index 00000000000..972e835c739 --- /dev/null +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/copay/federal_cap_rate.yaml @@ -0,0 +1,11 @@ +description: Maryland limits copayments to this share of family gross income under the Child Care Scholarship program per federal requirements. +values: + 2022-05-01: 0.07 + +metadata: + unit: /1 + period: year + label: Maryland CCS federal copayment cap rate + reference: + - title: 45 CFR 98.45(k) + href: https://www.ecfr.gov/current/title-45/section-98.45#p-98.45(k) diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/copay/max_children_with_copay.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/copay/max_children_with_copay.yaml new file mode 100644 index 00000000000..6dc26b33386 --- /dev/null +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/copay/max_children_with_copay.yaml @@ -0,0 +1,11 @@ +description: Maryland assesses copayments for up to this many children under the Child Care Scholarship program. +values: + 2022-05-01: 3 + +metadata: + unit: person + period: year + label: Maryland CCS maximum children with copayment + reference: + - title: COMAR 13A.14.06.12 + href: https://dsd.maryland.gov/regulations/Pages/13A.14.06.12.aspx diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/copay/unit_hours.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/copay/unit_hours.yaml new file mode 100644 index 00000000000..c4c292d7ec6 --- /dev/null +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/copay/unit_hours.yaml @@ -0,0 +1,25 @@ +description: Maryland determines the number of service units based on daily hours of care under the Child Care Scholarship program. + +metadata: + type: single_amount + threshold_unit: hour + amount_unit: /1 + period: year + label: Maryland CCS service units by daily hours + reference: + - title: COMAR 13A.14.06.11 + href: https://dsd.maryland.gov/regulations/Pages/13A.14.06.11.aspx + +brackets: + - threshold: + 2022-05-01: 0 + amount: + 2022-05-01: 1 + - threshold: + 2022-05-01: 3.0001 + amount: + 2022-05-01: 2 + - threshold: + 2022-05-01: 6 + amount: + 2022-05-01: 3 diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/copay/weekly_amount.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/copay/weekly_amount.yaml new file mode 100644 index 00000000000..a9e17012e35 --- /dev/null +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/copay/weekly_amount.yaml @@ -0,0 +1,20 @@ +description: Maryland sets this amount as the weekly copayment by service unit under the Child Care Scholarship program. + +metadata: + unit: currency-USD + period: week + label: Maryland CCS weekly copayment by service unit + breakdown: + - md_ccs_service_unit + reference: + - title: Chapter 717 of 2024 + href: https://mgaleg.maryland.gov/2024RS/Chapters_noln/CH_717_sb0482e.pdf + - title: COMAR 13A.14.06.12 + href: https://dsd.maryland.gov/regulations/Pages/13A.14.06.12.aspx + +UNIT_3: + 2022-05-01: 3 +UNIT_2: + 2022-05-01: 2 +UNIT_1: + 2022-05-01: 1 diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/income/countable_income/sources.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/income/countable_income/sources.yaml new file mode 100644 index 00000000000..df29e6820ff --- /dev/null +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/income/countable_income/sources.yaml @@ -0,0 +1,31 @@ +description: Maryland counts these income sources under the Child Care Scholarship program. +values: + 2022-05-01: + - employment_income + # Note: self_employment_income is handled separately in the formula + # with a 30% deduction per COMAR 13A.14.06.03(F)(6) + - social_security + - pension_income + - interest_income + - dividend_income + - rental_income + - alimony_income + - unemployment_compensation + - workers_compensation + - veterans_benefits + - disability_benefits + - capital_gains + - farm_income + - military_retirement_pay + # NOT included: + # - child_support_received (excluded per Chapters 525/526 of 2022) + +metadata: + unit: list + period: year + label: Maryland CCS countable income sources + reference: + - title: COMAR 13A.14.06.03(F)(3)-(8) + href: https://dsd.maryland.gov/regulations/Pages/13A.14.06.03.aspx + - title: Chapters 525/526 of 2022 + href: https://mgaleg.maryland.gov/2022RS/Chapters_noln/CH_525_hb0275e.pdf diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/income/self_employment_deduction_rate.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/income/self_employment_deduction_rate.yaml new file mode 100644 index 00000000000..54034c673ee --- /dev/null +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/income/self_employment_deduction_rate.yaml @@ -0,0 +1,11 @@ +description: Maryland deducts this share of self-employment income for business expenses under the Child Care Scholarship program. +values: + 2018-01-01: 0.3 + +metadata: + unit: /1 + period: year + label: Maryland CCS self-employment deduction rate + reference: + - title: COMAR 13A.14.06.03(F)(6) + href: https://dsd.maryland.gov/regulations/Pages/13A.14.06.03.aspx diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_rate/continuation.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_rate/continuation.yaml new file mode 100644 index 00000000000..1f1bd6a90a3 --- /dev/null +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_rate/continuation.yaml @@ -0,0 +1,13 @@ +description: Maryland limits continuation eligibility for the Child Care Scholarship program to families with income at or below this share of State Median Income. +values: + 2018-01-01: 0.85 + +metadata: + unit: /1 + period: year + label: Maryland CCS continuation eligibility SMI rate + reference: + - title: 45 CFR 98.21(b) - Eligibility requirements + href: https://www.ecfr.gov/current/title-45/section-98.21#p-98.21(b) + - title: Chapters 525/526 of 2022 + href: https://mgaleg.maryland.gov/2022RS/Chapters_noln/CH_525_hb0275e.pdf diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_rate/initial.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_rate/initial.yaml new file mode 100644 index 00000000000..a66bbc91975 --- /dev/null +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_rate/initial.yaml @@ -0,0 +1,15 @@ +description: Maryland limits initial eligibility for the Child Care Scholarship program to families with income at or below this share of State Median Income. +values: + 2018-01-01: 0.5 + 2019-01-01: 0.65 + 2022-05-01: 0.75 + +metadata: + unit: /1 + period: year + label: Maryland CCS initial eligibility SMI rate + reference: + - title: Chapters 595/596 of 2018 + href: https://mgaleg.maryland.gov/2018RS/Chapters_noln/CH_595_hb0377e.pdf + - title: Chapters 525/526 of 2022 + href: https://mgaleg.maryland.gov/2022RS/Chapters_noln/CH_525_hb0275e.pdf diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/payment/baltimore_city_counties.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/baltimore_city_counties.yaml new file mode 100644 index 00000000000..cb09fb47d74 --- /dev/null +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/baltimore_city_counties.yaml @@ -0,0 +1,12 @@ +description: Maryland sets Baltimore City as its own region for Child Care Scholarship rate purposes. +values: + 2020-11-23: + - BALTIMORE_CITY_MD + +metadata: + unit: list + period: year + label: Maryland CCS Baltimore City region + reference: + - title: Maryland CCS Scholarship Rates + href: https://earlychildhood.marylandpublicschools.org/families/child-care-scholarship-program/child-care-scholarship-rates diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/payment/formal/licensed_center.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/formal/licensed_center.yaml new file mode 100644 index 00000000000..aa6b3aeadbd --- /dev/null +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/formal/licensed_center.yaml @@ -0,0 +1,119 @@ +description: Maryland provides these weekly reimbursement rates for licensed child care centers under the Child Care Scholarship program. + +metadata: + period: week + unit: currency-USD + label: Maryland CCS licensed center weekly rates + breakdown: + - md_ccs_region + - md_ccs_age_group + - md_ccs_service_unit + reference: + - title: Maryland CCS Scholarship Rates (Formal Rates, 60th Percentile, 2024 Market Rate Survey) + href: https://earlychildhood.marylandpublicschools.org/families/child-care-scholarship-program/child-care-scholarship-rates + +REGION_U: + REGULAR: + UNIT_3: + 2026-03-01: 244 + UNIT_2: + 2026-03-01: 163 + UNIT_1: + 2026-03-01: 82 + INFANT: + UNIT_3: + 2026-03-01: 325 + UNIT_2: + 2026-03-01: 217 + UNIT_1: + 2026-03-01: 109 +REGION_V: + REGULAR: + UNIT_3: + 2026-03-01: 200 + UNIT_2: + 2026-03-01: 133 + UNIT_1: + 2026-03-01: 67 + INFANT: + UNIT_3: + 2026-03-01: 264 + UNIT_2: + 2026-03-01: 176 + UNIT_1: + 2026-03-01: 88 +REGION_W: + REGULAR: + UNIT_3: + 2026-03-01: 305 + UNIT_2: + 2026-03-01: 204 + UNIT_1: + 2026-03-01: 102 + INFANT: + UNIT_3: + 2026-03-01: 420 + UNIT_2: + 2026-03-01: 280 + UNIT_1: + 2026-03-01: 140 +REGION_X: + REGULAR: + UNIT_3: + 2026-03-01: 424 + UNIT_2: + 2026-03-01: 283 + UNIT_1: + 2026-03-01: 142 + INFANT: + UNIT_3: + 2026-03-01: 554 + UNIT_2: + 2026-03-01: 369 + UNIT_1: + 2026-03-01: 185 +REGION_Y: + REGULAR: + UNIT_3: + 2026-03-01: 278 + UNIT_2: + 2026-03-01: 185 + UNIT_1: + 2026-03-01: 93 + INFANT: + UNIT_3: + 2026-03-01: 378 + UNIT_2: + 2026-03-01: 252 + UNIT_1: + 2026-03-01: 126 +REGION_Z: + REGULAR: + UNIT_3: + 2026-03-01: 207 + UNIT_2: + 2026-03-01: 138 + UNIT_1: + 2026-03-01: 69 + INFANT: + UNIT_3: + 2026-03-01: 297 + UNIT_2: + 2026-03-01: 198 + UNIT_1: + 2026-03-01: 99 +BALTIMORE_CITY: + REGULAR: + UNIT_3: + 2026-03-01: 282 + UNIT_2: + 2026-03-01: 188 + UNIT_1: + 2026-03-01: 94 + INFANT: + UNIT_3: + 2026-03-01: 376 + UNIT_2: + 2026-03-01: 251 + UNIT_1: + 2026-03-01: 126 diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/payment/formal/licensed_family.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/formal/licensed_family.yaml new file mode 100644 index 00000000000..e0ea886e198 --- /dev/null +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/formal/licensed_family.yaml @@ -0,0 +1,119 @@ +description: Maryland provides these weekly reimbursement rates for licensed family child care homes under the Child Care Scholarship program. + +metadata: + period: week + unit: currency-USD + label: Maryland CCS licensed family weekly rates + breakdown: + - md_ccs_region + - md_ccs_age_group + - md_ccs_service_unit + reference: + - title: Maryland CCS Scholarship Rates (Formal Rates, 60th Percentile, 2024 Market Rate Survey) + href: https://earlychildhood.marylandpublicschools.org/families/child-care-scholarship-program/child-care-scholarship-rates + +REGION_U: + REGULAR: + UNIT_3: + 2026-03-01: 200 + UNIT_2: + 2026-03-01: 134 + UNIT_1: + 2026-03-01: 67 + INFANT: + UNIT_3: + 2026-03-01: 225 + UNIT_2: + 2026-03-01: 150 + UNIT_1: + 2026-03-01: 75 +REGION_V: + REGULAR: + UNIT_3: + 2026-03-01: 175 + UNIT_2: + 2026-03-01: 117 + UNIT_1: + 2026-03-01: 59 + INFANT: + UNIT_3: + 2026-03-01: 200 + UNIT_2: + 2026-03-01: 134 + UNIT_1: + 2026-03-01: 67 +REGION_W: + REGULAR: + UNIT_3: + 2026-03-01: 265 + UNIT_2: + 2026-03-01: 177 + UNIT_1: + 2026-03-01: 89 + INFANT: + UNIT_3: + 2026-03-01: 300 + UNIT_2: + 2026-03-01: 200 + UNIT_1: + 2026-03-01: 100 +REGION_X: + REGULAR: + UNIT_3: + 2026-03-01: 325 + UNIT_2: + 2026-03-01: 217 + UNIT_1: + 2026-03-01: 109 + INFANT: + UNIT_3: + 2026-03-01: 350 + UNIT_2: + 2026-03-01: 234 + UNIT_1: + 2026-03-01: 117 +REGION_Y: + REGULAR: + UNIT_3: + 2026-03-01: 220 + UNIT_2: + 2026-03-01: 147 + UNIT_1: + 2026-03-01: 73 + INFANT: + UNIT_3: + 2026-03-01: 250 + UNIT_2: + 2026-03-01: 167 + UNIT_1: + 2026-03-01: 83 +REGION_Z: + REGULAR: + UNIT_3: + 2026-03-01: 170 + UNIT_2: + 2026-03-01: 114 + UNIT_1: + 2026-03-01: 57 + INFANT: + UNIT_3: + 2026-03-01: 185 + UNIT_2: + 2026-03-01: 124 + UNIT_1: + 2026-03-01: 62 +BALTIMORE_CITY: + REGULAR: + UNIT_3: + 2026-03-01: 225 + UNIT_2: + 2026-03-01: 150 + UNIT_1: + 2026-03-01: 75 + INFANT: + UNIT_3: + 2026-03-01: 252 + UNIT_2: + 2026-03-01: 168 + UNIT_1: + 2026-03-01: 84 diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/payment/infant_age_threshold.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/infant_age_threshold.yaml new file mode 100644 index 00000000000..4810dd8cdcc --- /dev/null +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/infant_age_threshold.yaml @@ -0,0 +1,13 @@ +description: Maryland defines infants as children under this age in months for Child Care Scholarship rate purposes. +values: + 2020-11-23: 24 + +metadata: + unit: month + period: year + label: Maryland CCS infant age threshold in months + reference: + - title: Maryland CCS Scholarship Rates + href: https://earlychildhood.marylandpublicschools.org/families/child-care-scholarship-program/child-care-scholarship-rates + - title: COMAR 13A.14.06.02 - Definitions + href: https://dsd.maryland.gov/regulations/Pages/13A.14.06.02.aspx diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/payment/informal/rates.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/informal/rates.yaml new file mode 100644 index 00000000000..e0bc3b53a0d --- /dev/null +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/informal/rates.yaml @@ -0,0 +1,370 @@ +description: Maryland provides these weekly reimbursement rates for informal child care providers under the Child Care Scholarship program. + +metadata: + period: week + unit: currency-USD + label: Maryland CCS informal provider weekly rates + reference: + - title: Maryland CCS Scholarship Rates (Informal Rates, 70th Percentile, March 2021 Market Rate Survey) + href: https://earlychildhood.marylandpublicschools.org/families/child-care-scholarship-program/child-care-scholarship-rates + +ALLEGANY_COUNTY_MD: + REGULAR: + UNIT_3: + 2020-11-23: 83 + UNIT_2: + 2020-11-23: 55 + UNIT_1: + 2020-11-23: 28 + INFANT: + UNIT_3: + 2020-11-23: 90 + UNIT_2: + 2020-11-23: 60 + UNIT_1: + 2020-11-23: 30 +ANNE_ARUNDEL_COUNTY_MD: + REGULAR: + UNIT_3: + 2020-11-23: 135 + UNIT_2: + 2020-11-23: 90 + UNIT_1: + 2020-11-23: 45 + INFANT: + UNIT_3: + 2020-11-23: 150 + UNIT_2: + 2020-11-23: 100 + UNIT_1: + 2020-11-23: 50 +BALTIMORE_COUNTY_MD: + REGULAR: + UNIT_3: + 2020-11-23: 125 + UNIT_2: + 2020-11-23: 83 + UNIT_1: + 2020-11-23: 42 + INFANT: + UNIT_3: + 2020-11-23: 150 + UNIT_2: + 2020-11-23: 100 + UNIT_1: + 2020-11-23: 50 +CALVERT_COUNTY_MD: + REGULAR: + UNIT_3: + 2020-11-23: 135 + UNIT_2: + 2020-11-23: 90 + UNIT_1: + 2020-11-23: 45 + INFANT: + UNIT_3: + 2020-11-23: 150 + UNIT_2: + 2020-11-23: 100 + UNIT_1: + 2020-11-23: 50 +CAROLINE_COUNTY_MD: + REGULAR: + UNIT_3: + 2020-11-23: 84 + UNIT_2: + 2020-11-23: 56 + UNIT_1: + 2020-11-23: 28 + INFANT: + UNIT_3: + 2020-11-23: 100 + UNIT_2: + 2020-11-23: 67 + UNIT_1: + 2020-11-23: 33 +CARROLL_COUNTY_MD: + REGULAR: + UNIT_3: + 2020-11-23: 135 + UNIT_2: + 2020-11-23: 90 + UNIT_1: + 2020-11-23: 45 + INFANT: + UNIT_3: + 2020-11-23: 150 + UNIT_2: + 2020-11-23: 100 + UNIT_1: + 2020-11-23: 50 +CECIL_COUNTY_MD: + REGULAR: + UNIT_3: + 2020-11-23: 105 + UNIT_2: + 2020-11-23: 70 + UNIT_1: + 2020-11-23: 35 + INFANT: + UNIT_3: + 2020-11-23: 120 + UNIT_2: + 2020-11-23: 80 + UNIT_1: + 2020-11-23: 40 +CHARLES_COUNTY_MD: + REGULAR: + UNIT_3: + 2020-11-23: 135 + UNIT_2: + 2020-11-23: 90 + UNIT_1: + 2020-11-23: 45 + INFANT: + UNIT_3: + 2020-11-23: 150 + UNIT_2: + 2020-11-23: 100 + UNIT_1: + 2020-11-23: 50 +DORCHESTER_COUNTY_MD: + REGULAR: + UNIT_3: + 2020-11-23: 84 + UNIT_2: + 2020-11-23: 56 + UNIT_1: + 2020-11-23: 28 + INFANT: + UNIT_3: + 2020-11-23: 100 + UNIT_2: + 2020-11-23: 67 + UNIT_1: + 2020-11-23: 33 +FREDERICK_COUNTY_MD: + REGULAR: + UNIT_3: + 2020-11-23: 125 + UNIT_2: + 2020-11-23: 83 + UNIT_1: + 2020-11-23: 42 + INFANT: + UNIT_3: + 2020-11-23: 150 + UNIT_2: + 2020-11-23: 100 + UNIT_1: + 2020-11-23: 50 +GARRETT_COUNTY_MD: + REGULAR: + UNIT_3: + 2020-11-23: 83 + UNIT_2: + 2020-11-23: 55 + UNIT_1: + 2020-11-23: 28 + INFANT: + UNIT_3: + 2020-11-23: 90 + UNIT_2: + 2020-11-23: 60 + UNIT_1: + 2020-11-23: 30 +HARFORD_COUNTY_MD: + REGULAR: + UNIT_3: + 2020-11-23: 125 + UNIT_2: + 2020-11-23: 83 + UNIT_1: + 2020-11-23: 42 + INFANT: + UNIT_3: + 2020-11-23: 150 + UNIT_2: + 2020-11-23: 100 + UNIT_1: + 2020-11-23: 50 +HOWARD_COUNTY_MD: + REGULAR: + UNIT_3: + 2020-11-23: 177 + UNIT_2: + 2020-11-23: 118 + UNIT_1: + 2020-11-23: 59 + INFANT: + UNIT_3: + 2020-11-23: 195 + UNIT_2: + 2020-11-23: 130 + UNIT_1: + 2020-11-23: 65 +KENT_COUNTY_MD: + REGULAR: + UNIT_3: + 2020-11-23: 84 + UNIT_2: + 2020-11-23: 56 + UNIT_1: + 2020-11-23: 28 + INFANT: + UNIT_3: + 2020-11-23: 100 + UNIT_2: + 2020-11-23: 67 + UNIT_1: + 2020-11-23: 33 +MONTGOMERY_COUNTY_MD: + REGULAR: + UNIT_3: + 2020-11-23: 177 + UNIT_2: + 2020-11-23: 118 + UNIT_1: + 2020-11-23: 59 + INFANT: + UNIT_3: + 2020-11-23: 195 + UNIT_2: + 2020-11-23: 130 + UNIT_1: + 2020-11-23: 65 +PRINCE_GEORGE_S_COUNTY_MD: + REGULAR: + UNIT_3: + 2020-11-23: 135 + UNIT_2: + 2020-11-23: 90 + UNIT_1: + 2020-11-23: 45 + INFANT: + UNIT_3: + 2020-11-23: 150 + UNIT_2: + 2020-11-23: 100 + UNIT_1: + 2020-11-23: 50 +QUEEN_ANNE_S_COUNTY_MD: + REGULAR: + UNIT_3: + 2020-11-23: 105 + UNIT_2: + 2020-11-23: 70 + UNIT_1: + 2020-11-23: 35 + INFANT: + UNIT_3: + 2020-11-23: 120 + UNIT_2: + 2020-11-23: 80 + UNIT_1: + 2020-11-23: 40 +ST_MARY_S_COUNTY_MD: + REGULAR: + UNIT_3: + 2020-11-23: 105 + UNIT_2: + 2020-11-23: 70 + UNIT_1: + 2020-11-23: 35 + INFANT: + UNIT_3: + 2020-11-23: 120 + UNIT_2: + 2020-11-23: 80 + UNIT_1: + 2020-11-23: 40 +SOMERSET_COUNTY_MD: + REGULAR: + UNIT_3: + 2020-11-23: 84 + UNIT_2: + 2020-11-23: 56 + UNIT_1: + 2020-11-23: 28 + INFANT: + UNIT_3: + 2020-11-23: 100 + UNIT_2: + 2020-11-23: 67 + UNIT_1: + 2020-11-23: 33 +TALBOT_COUNTY_MD: + REGULAR: + UNIT_3: + 2020-11-23: 105 + UNIT_2: + 2020-11-23: 70 + UNIT_1: + 2020-11-23: 35 + INFANT: + UNIT_3: + 2020-11-23: 120 + UNIT_2: + 2020-11-23: 80 + UNIT_1: + 2020-11-23: 40 +WASHINGTON_COUNTY_MD: + REGULAR: + UNIT_3: + 2020-11-23: 105 + UNIT_2: + 2020-11-23: 70 + UNIT_1: + 2020-11-23: 35 + INFANT: + UNIT_3: + 2020-11-23: 120 + UNIT_2: + 2020-11-23: 80 + UNIT_1: + 2020-11-23: 40 +WICOMICO_COUNTY_MD: + REGULAR: + UNIT_3: + 2020-11-23: 84 + UNIT_2: + 2020-11-23: 56 + UNIT_1: + 2020-11-23: 28 + INFANT: + UNIT_3: + 2020-11-23: 100 + UNIT_2: + 2020-11-23: 67 + UNIT_1: + 2020-11-23: 33 +WORCESTER_COUNTY_MD: + REGULAR: + UNIT_3: + 2020-11-23: 83 + UNIT_2: + 2020-11-23: 55 + UNIT_1: + 2020-11-23: 28 + INFANT: + UNIT_3: + 2020-11-23: 90 + UNIT_2: + 2020-11-23: 60 + UNIT_1: + 2020-11-23: 30 +BALTIMORE_CITY_MD: + REGULAR: + UNIT_3: + 2020-11-23: 106 + UNIT_2: + 2020-11-23: 71 + UNIT_1: + 2020-11-23: 35 + INFANT: + UNIT_3: + 2020-11-23: 120 + UNIT_2: + 2020-11-23: 80 + UNIT_1: + 2020-11-23: 40 diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/payment/region_u_counties.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/region_u_counties.yaml new file mode 100644 index 00000000000..6aaca3f2c63 --- /dev/null +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/region_u_counties.yaml @@ -0,0 +1,16 @@ +description: Maryland sets these counties as Region U for Child Care Scholarship rate purposes. +values: + 2020-11-23: + - CECIL_COUNTY_MD + - QUEEN_ANNE_S_COUNTY_MD + - ST_MARY_S_COUNTY_MD + - TALBOT_COUNTY_MD + - WASHINGTON_COUNTY_MD + +metadata: + unit: list + period: year + label: Maryland CCS Region U counties + reference: + - title: Maryland CCS Scholarship Rates + href: https://earlychildhood.marylandpublicschools.org/families/child-care-scholarship-program/child-care-scholarship-rates diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/payment/region_v_counties.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/region_v_counties.yaml new file mode 100644 index 00000000000..5cf99beec1e --- /dev/null +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/region_v_counties.yaml @@ -0,0 +1,16 @@ +description: Maryland sets these counties as Region V for Child Care Scholarship rate purposes. +values: + 2020-11-23: + - CAROLINE_COUNTY_MD + - DORCHESTER_COUNTY_MD + - KENT_COUNTY_MD + - SOMERSET_COUNTY_MD + - WICOMICO_COUNTY_MD + +metadata: + unit: list + period: year + label: Maryland CCS Region V counties + reference: + - title: Maryland CCS Scholarship Rates + href: https://earlychildhood.marylandpublicschools.org/families/child-care-scholarship-program/child-care-scholarship-rates diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/payment/region_x_counties.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/region_x_counties.yaml new file mode 100644 index 00000000000..0cc357c3df6 --- /dev/null +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/region_x_counties.yaml @@ -0,0 +1,13 @@ +description: Maryland sets these counties as Region X for Child Care Scholarship rate purposes. +values: + 2020-11-23: + - HOWARD_COUNTY_MD + - MONTGOMERY_COUNTY_MD + +metadata: + unit: list + period: year + label: Maryland CCS Region X counties + reference: + - title: Maryland CCS Scholarship Rates + href: https://earlychildhood.marylandpublicschools.org/families/child-care-scholarship-program/child-care-scholarship-rates diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/payment/region_y_counties.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/region_y_counties.yaml new file mode 100644 index 00000000000..1ae3f1de0af --- /dev/null +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/region_y_counties.yaml @@ -0,0 +1,14 @@ +description: Maryland sets these counties as Region Y for Child Care Scholarship rate purposes. +values: + 2020-11-23: + - BALTIMORE_COUNTY_MD + - FREDERICK_COUNTY_MD + - HARFORD_COUNTY_MD + +metadata: + unit: list + period: year + label: Maryland CCS Region Y counties + reference: + - title: Maryland CCS Scholarship Rates + href: https://earlychildhood.marylandpublicschools.org/families/child-care-scholarship-program/child-care-scholarship-rates diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/payment/region_z_counties.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/region_z_counties.yaml new file mode 100644 index 00000000000..99055a52bac --- /dev/null +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/region_z_counties.yaml @@ -0,0 +1,14 @@ +description: Maryland sets these counties as Region Z for Child Care Scholarship rate purposes. +values: + 2020-11-23: + - ALLEGANY_COUNTY_MD + - GARRETT_COUNTY_MD + - WORCESTER_COUNTY_MD + +metadata: + unit: list + period: year + label: Maryland CCS Region Z counties + reference: + - title: Maryland CCS Scholarship Rates + href: https://earlychildhood.marylandpublicschools.org/families/child-care-scholarship-program/child-care-scholarship-rates diff --git a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/edge_cases.yaml b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/edge_cases.yaml new file mode 100644 index 00000000000..d3ef27886d3 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/edge_cases.yaml @@ -0,0 +1,1236 @@ +# Maryland CCS Edge Case Tests +# Tests boundary conditions for eligibility, copayment, and benefit calculations. +# FY2025 MD SMI base: $149,249 +# +# SMI by family size: +# Fam 1: 149,249 * 0.52 = 77,609.48 +# Fam 2: 149,249 * 0.68 = 101,489.32 +# Fam 7: 149,249 * (0.52 + 0.16*5 + 0.03) = 149,249 * 1.35 = 201,486.15 +# Fam 8: 149,249 * (0.52 + 0.16*5 + 0.03*2) = 149,249 * 1.38 = 205,963.62 +# +# 75% SMI (initial): Fam 1 = 58,207.11, Fam 2 = 76,116.99 +# 85% SMI (continuation): Fam 2 = 86,265.92 + +# === Income threshold boundary: 75% SMI === + +- name: Case 1, income just below 75 percent SMI threshold for family of 2. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + # 75% SMI for fam 2 ~ 76,116.99 annually + # Use 76,116 to stay just below threshold (avoids float precision) + employment_income: 76_116 + is_tax_unit_head_or_spouse: true + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MD + output: + # monthly countable: 76,116 / 12 = 6,343.00 + # monthly 75% SMI: ~6,343.08 + # 6,343.00 <= 6,343.08 -> eligible + md_ccs_income_eligible: true + +- name: Case 2, income one dollar above 75 percent SMI threshold for family of 2. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 76_118 + is_tax_unit_head_or_spouse: true + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MD + output: + # monthly countable: 76,118 / 12 = 6,343.17 + # monthly 75% SMI: 6,343.08 + # 6,343.17 > 6,343.08 -> not eligible + md_ccs_income_eligible: false + +# === Income threshold boundary: 85% SMI (continuation) === + +- name: Case 3, enrolled family income just below 85 percent SMI threshold. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + # 85% SMI for fam 2 ~ 86,265.92 annually + # Use 86,265 to stay just below threshold (avoids float precision) + employment_income: 86_265 + is_tax_unit_head_or_spouse: true + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + md_ccs_enrolled: true + households: + household: + members: [person1, person2] + state_code: MD + output: + # monthly countable: 86,265 / 12 = 7,188.75 + # monthly 85% SMI: ~7,188.83 + # 7,188.75 <= 7,188.83 -> eligible + md_ccs_income_eligible: true + +- name: Case 4, enrolled family income one dollar above 85 percent SMI threshold. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 86_267 + is_tax_unit_head_or_spouse: true + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + md_ccs_enrolled: true + households: + household: + members: [person1, person2] + state_code: MD + output: + # monthly countable: 86,267 / 12 = 7,188.92 + # monthly 85% SMI: 7,188.83 + # 7,188.92 > 7,188.83 -> not eligible + md_ccs_income_eligible: false + +# === Enrolled between 75-85% SMI: initial vs continuation === + +- name: Case 5, not enrolled with income between 75 and 85 percent SMI is not eligible. + period: 2025-01 + input: + people: + person1: + age: 30 + # 80,000 is between 75% SMI (76,117) and 85% SMI (86,266) for fam 2 + employment_income: 80_000 + is_tax_unit_head_or_spouse: true + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + md_ccs_enrolled: false + households: + household: + members: [person1, person2] + state_code: MD + output: + # Not enrolled -> initial threshold (75% SMI) + # monthly countable: 80,000 / 12 = 6,666.67 + # monthly 75% SMI: 6,343.08 + # 6,666.67 > 6,343.08 -> not eligible + md_ccs_income_eligible: false + +- name: Case 6, enrolled with income between 75 and 85 percent SMI is eligible. + period: 2025-01 + input: + people: + person1: + age: 30 + employment_income: 80_000 + is_tax_unit_head_or_spouse: true + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + md_ccs_enrolled: true + households: + household: + members: [person1, person2] + state_code: MD + output: + # Enrolled -> continuation threshold (85% SMI) + # monthly countable: 80,000 / 12 = 6,666.67 + # monthly 85% SMI: 7,188.83 + # 6,666.67 <= 7,188.83 -> eligible + md_ccs_income_eligible: true + +# === Zero income === + +- name: Case 7, zero income family is income eligible. + period: 2025-01 + input: + people: + person1: + age: 30 + employment_income: 0 + is_tax_unit_head_or_spouse: true + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MD + output: + # 0 <= 75% SMI -> eligible + md_ccs_income_eligible: true + +# === Very high income === + +- name: Case 8, very high income family is not income eligible. + period: 2025-01 + input: + people: + person1: + age: 30 + employment_income: 500_000 + is_tax_unit_head_or_spouse: true + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MD + output: + # 500,000/12 = 41,666.67 >> 75% SMI -> not eligible + md_ccs_income_eligible: false + +# === Family size: minimum (1 person, adult only) === + +- name: Case 9, single adult with no children has no eligible child. + period: 2025-01 + input: + people: + person1: + age: 30 + employment_income: 30_000 + is_tax_unit_head_or_spouse: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: MD + output: + md_ccs_eligible_child: [false] + md_ccs_eligible: false + +# === Family size: large (8 people, 6 children) === + +- name: Case 10, large family of 8 with 6 children. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 120_000 + is_tax_unit_head_or_spouse: true + person2: + age: 38 + is_tax_unit_head_or_spouse: true + person3: + age: 12 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + person4: + age: 10 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + person5: + age: 7 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + person6: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + person7: + age: 3 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 4 + person8: + age: 1 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2, person3, person4, person5, person6, person7, person8] + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5, person6, person7, person8] + households: + household: + members: [person1, person2, person3, person4, person5, person6, person7, person8] + state_code: MD + output: + # All 6 children under 13 -> all eligible + md_ccs_eligible_child: [false, false, true, true, true, true, true, true] + + # hhs_smi for fam 8 = 149,249 * (0.52 + 0.16*5 + 0.03*2) = 149,249 * 1.38 = 205,963.62 + # monthly 75% SMI = 205,963.62 * 0.75 / 12 = 12,872.73 + # monthly countable: 120,000 / 12 = 10,000 + # 10,000 <= 12,872.73 -> eligible + md_ccs_income_eligible: true + +# === Self-employment income edge cases === + +- name: Case 11, family with 100 percent self-employment income. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + self_employment_income: 60_000 + is_tax_unit_head_or_spouse: true + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MD + output: + # self_employment_income: 60,000 * (1 - 0.30) = 42,000 + # monthly: 42,000 / 12 = 3,500 + md_ccs_countable_income: 3_500 + +- name: Case 12, family with zero self-employment income. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 50_000 + self_employment_income: 0 + is_tax_unit_head_or_spouse: true + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MD + output: + # employment: 50,000, self_employment: 0 * 0.70 = 0 + # monthly: 50,000 / 12 = 4,166.67 + md_ccs_countable_income: 4_166.67 + +# === Age boundary: child exactly age 13 (non-disabled) === + +- name: Case 13, child exactly age 13 not disabled is not eligible. + period: 2025-01 + input: + people: + person1: + age: 40 + is_tax_unit_head_or_spouse: true + person2: + age: 13 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MD + output: + # age 13, threshold is < 13 -> not eligible + md_ccs_eligible_child: [false, false] + +# === Age boundary: disabled child exactly age 18 === + +- name: Case 14, disabled child exactly age 18 is eligible. + period: 2025-01 + input: + people: + person1: + age: 45 + is_tax_unit_head_or_spouse: true + person2: + age: 18 + is_disabled: true + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MD + output: + # age 18 < 19 (disabled threshold) -> eligible + md_ccs_eligible_child: [false, true] + +# === Age boundary: disabled child exactly age 19 === + +- name: Case 15, disabled child exactly age 19 is not eligible. + period: 2025-01 + input: + people: + person1: + age: 45 + is_tax_unit_head_or_spouse: true + person2: + age: 19 + is_disabled: true + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MD + output: + # age 19, threshold is < 19 -> not eligible + md_ccs_eligible_child: [false, false] + +# === Multiple children copay scaling === + +- name: Case 16, one child copay. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 50_000 + is_tax_unit_head_or_spouse: true + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MD + output: + # 1 child, full-time -> $3/week + # capped_count = min(1, 3) = 1 + # scale = 1/1 = 1 + # total = $3 * 1 = $3/week + md_ccs_weekly_copay: 3 + +- name: Case 17, two children copay. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 50_000 + is_tax_unit_head_or_spouse: true + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + person3: + age: 3 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: MD + output: + # 2 children, each full-time -> $3 + $3 = $6/week + # capped_count = min(2, 3) = 2, scale = 2/2 = 1 + # total = $6/week + md_ccs_weekly_copay: 6 + +- name: Case 18, three children copay at max. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 50_000 + is_tax_unit_head_or_spouse: true + person2: + age: 10 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + person3: + age: 7 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + person4: + age: 3 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2, person3, person4] + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + households: + household: + members: [person1, person2, person3, person4] + state_code: MD + output: + # 3 children, each full-time -> $3*3 = $9/week + # capped_count = min(3, 3) = 3, scale = 3/3 = 1 + # total = $9/week + md_ccs_weekly_copay: 9 + +- name: Case 19, four children copay capped at 3 children. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 50_000 + is_tax_unit_head_or_spouse: true + person2: + age: 10 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + person3: + age: 7 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + person4: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + person5: + age: 3 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2, person3, person4, person5] + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5] + households: + household: + members: [person1, person2, person3, person4, person5] + state_code: MD + output: + # 4 eligible children, each full-time -> raw total = $3*4 = $12/week + # capped_count = min(4, 3) = 3, scale = 3/4 = 0.75 + # scaled total = $12 * 0.75 = $9/week + md_ccs_weekly_copay: 9 + +- name: Case 20, five children copay capped at 3 children. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 50_000 + is_tax_unit_head_or_spouse: true + person2: + age: 11 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + person3: + age: 9 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + person4: + age: 7 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + person5: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + person6: + age: 3 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2, person3, person4, person5, person6] + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5, person6] + households: + household: + members: [person1, person2, person3, person4, person5, person6] + state_code: MD + output: + # 5 eligible children, each full-time -> raw total = $3*5 = $15/week + # capped_count = min(5, 3) = 3, scale = 3/5 = 0.6 + # scaled total = $15 * 0.6 = $9/week + md_ccs_weekly_copay: 9 + +# === Copay federal cap edge cases === + +- name: Case 21, copay exactly at 7 percent federal cap. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + # Target: 7% of weekly income = $3/week (full-time copay) + # weekly income = $3 / 0.07 = $42.86/week + # annual = $42.86 * 52 = $2,228.57 + # Need income where 7% cap = $3/week exactly + employment_income: 2_229 + is_tax_unit_head_or_spouse: true + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MD + output: + # monthly countable = 2,229 / 12 = 185.75 + # weekly income = 185.75 * 12 / 52 = 42.87 + # 7% cap = 42.87 * 0.07 = 3.00 + # raw copay = $3/week (full-time) + # min($3, $3.00) = $3 -> cap does not reduce copay + md_ccs_weekly_copay: 3 + +- name: Case 22, copay below 7 percent federal cap with very low income. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 1_200 + is_tax_unit_head_or_spouse: true + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MD + output: + # monthly countable = 1,200 / 12 = 100 + # weekly income = 100 * 12 / 52 = 23.08 + # 7% cap = 23.08 * 0.07 = 1.62 + # raw copay = $3/week (full-time, 8 hrs) + # min($3, $1.62) = $1.62 -> cap applies + md_ccs_weekly_copay: 1.62 + +- name: Case 23, zero income results in zero copay via federal cap. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 0 + is_tax_unit_head_or_spouse: true + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MD + output: + # weekly income = 0 + # 7% cap = 0 * 0.07 = 0 + # min($3, $0) = $0 + md_ccs_weekly_copay: 0 + +# === Zero childcare expenses === + +- name: Case 24, zero childcare expenses results in zero benefit. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 50_000 + is_tax_unit_head_or_spouse: true + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 0 + households: + household: + members: [person1, person2] + state_code: MD + output: + # expenses = 0, copay = $3 * 52 / 12 = $13/month + # benefit = max(0 - 13, 0) = 0 + md_ccs: 0 + +# === Expenses less than copay === + +- name: Case 25, expenses less than copay results in zero benefit. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 50_000 + is_tax_unit_head_or_spouse: true + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 100 + households: + household: + members: [person1, person2] + state_code: MD + output: + # annual copay = $3 * 52 = $156 + # annual expenses = $100 + # benefit = max(100 - 156, 0) = 0 (floored at 0) + md_ccs: 0 + +# === Service unit boundary: hours per day === + +- name: Case 26, childcare exactly 3 hours per day gets hourly rate. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 50_000 + is_tax_unit_head_or_spouse: true + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 3 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MD + output: + # 3 hrs/day: bracket threshold 0->1 unit, next at 3.0001 + # 3 < 3.0001 -> 1 unit (hourly) -> $1/week + md_ccs_weekly_copay: 1 + +- name: Case 27, childcare 3.5 hours per day gets part-time rate. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 50_000 + is_tax_unit_head_or_spouse: true + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 3.5 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MD + output: + # 3.5 hrs/day >= 3.0001 -> 2 units (part-time) -> $2/week + md_ccs_weekly_copay: 2 + +- name: Case 28, childcare exactly 6 hours per day gets full-time rate. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 50_000 + is_tax_unit_head_or_spouse: true + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 6 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MD + output: + # 6 hrs/day >= 6 -> 3 units (full-time) -> $3/week + md_ccs_weekly_copay: 3 + +- name: Case 29, childcare 5.99 hours per day gets part-time rate. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 50_000 + is_tax_unit_head_or_spouse: true + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 5.99 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MD + output: + # 5.99 hrs/day < 6 -> 2 units (part-time) -> $2/week + md_ccs_weekly_copay: 2 + +# === Mixed service units across children === + +- name: Case 30, two children with different service levels. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 50_000 + is_tax_unit_head_or_spouse: true + person2: + age: 8 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + person3: + age: 3 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 2 + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: MD + output: + # person2: 8 hrs -> 3 units -> $3/week + # person3: 2 hrs -> 1 unit -> $1/week + # total: $3 + $1 = $4/week + md_ccs_weekly_copay: 4 + +# === Immigration ineligible child === + +- name: Case 31, undocumented child is not eligible. + period: 2025-01 + input: + people: + person1: + age: 30 + employment_income: 30_000 + is_tax_unit_head_or_spouse: true + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: UNDOCUMENTED + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MD + output: + # CCDF immigration check fails for undocumented children + md_ccs_eligible_child: [false, false] + md_ccs_eligible: false + +# === Non-dependent child === + +- name: Case 32, non-dependent child under 13 is not eligible. + period: 2025-01 + input: + people: + person1: + age: 30 + is_tax_unit_head_or_spouse: true + person2: + age: 5 + is_tax_unit_dependent: false + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MD + output: + # Not a dependent -> not eligible child + md_ccs_eligible_child: [false, false] + +# === TCA exemption with very high income === + +- name: Case 33, TCA recipient eligible despite income far above 85 percent SMI. + period: 2025-01 + input: + people: + person1: + age: 30 + employment_income: 300_000 + is_tax_unit_head_or_spouse: true + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + is_tanf_enrolled: true + households: + household: + members: [person1, person2] + state_code: MD + output: + # TCA -> income test waived regardless of how high income is + md_ccs_eligible: true + +# === SSI exemption with very high income === + +- name: Case 34, SSI recipient eligible despite income far above 85 percent SMI. + period: 2025-01 + input: + people: + person1: + age: 30 + employment_income: 300_000 + ssi: 9_000 + is_tax_unit_head_or_spouse: true + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MD + output: + # SSI recipient (ssi > 0) -> income test waived + md_ccs_eligible: true + +# === Federal cap with multiple children === + +- name: Case 35, federal 7 percent cap applies with three children. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 3_600 + is_tax_unit_head_or_spouse: true + person2: + age: 10 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + person3: + age: 7 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + person4: + age: 3 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2, person3, person4] + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + households: + household: + members: [person1, person2, person3, person4] + state_code: MD + output: + # 3 children, each full-time -> raw = $3 * 3 = $9/week + # capped_count = min(3, 3) = 3, scale = 1 + # monthly countable = 3,600 / 12 = 300 + # weekly income = 300 * 12 / 52 = 69.23 + # 7% cap = 69.23 * 0.07 = 4.85 + # min($9, $4.85) = $4.85 -> cap applies + md_ccs_weekly_copay: 4.85 + +# === Zero childcare hours === + +- name: Case 36, zero childcare hours per day gets hourly rate. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 50_000 + is_tax_unit_head_or_spouse: true + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 0 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MD + output: + # 0 hrs/day -> 1 unit (hourly) -> $1/week + md_ccs_weekly_copay: 1 + +# === Benefit floor at zero: copay exceeds expenses === + +- name: Case 37, negative countable income from self-employment does not inflate benefit. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + self_employment_income: -60_000_000 + is_tax_unit_head_or_spouse: true + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + is_tanf_enrolled: true + spm_unit_pre_subsidy_childcare_expenses: 10_000 + households: + household: + members: [person1, person2] + state_code: MD + output: + # TCA -> copay exempt -> $0 copay + # benefit = max(10,000 - 0, 0) = 10,000 + # monthly: 10,000 / 12 = 833.33 + # Negative self-employment income does not inflate benefit (benefit formula + # uses expenses - copay, not income-based formula) + md_ccs: 833.33 diff --git a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/integration.yaml new file mode 100644 index 00000000000..d8f0050bf2b --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/integration.yaml @@ -0,0 +1,424 @@ +# Maryland CCS Integration Tests +# FY2025 SMI base for MD (from 2024-10-01): $149,249 +# Family of 2: hhs_smi = 149,249 * 0.68 = 101,489.32 +# Family of 3: hhs_smi = 149,249 * 0.84 = 125,369.16 +# Family of 4: hhs_smi = 149,249 * 1.00 = 149,249 +# +# 75% SMI (initial): fam 2 = 76,116.99, fam 4 = 111,936.75 +# 85% SMI (continuation): fam 2 = 86,265.92, fam 4 = 126,861.65 + +- name: Case 1, single parent with one child age 3 and full-time care. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 28 + employment_income: 50_000 + is_tax_unit_head_or_spouse: true + immigration_status: CITIZEN + person2: + age: 3 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 12_000 + households: + household: + members: [person1, person2] + state_code: MD + output: + # === Child eligibility === + # person1: adult, not dependent -> false + # person2: age 3 < 13, dependent, citizen -> true + md_ccs_eligible_child: [false, true] + + # === Income === + # employment_income: 50,000 + # monthly countable: 50,000 / 12 = 4,166.67 + md_ccs_countable_income: 4_166.67 + + # === Income eligibility === + # hhs_smi for fam 2 = 101,489.32 annual + # monthly 75% SMI = 101,489.32 * 0.75 / 12 = 6,343.08 + # 4,166.67 <= 6,343.08 -> eligible + md_ccs_income_eligible: true + + # === Overall eligibility === + md_ccs_eligible: true + + # === Copay === + # 8 hrs/day >= 6 -> 3 units (full-time) -> $3/week + # Not TCA/SSI/SNAP/WIC -> standard copay + md_ccs_weekly_copay: 3 + + # === Benefit === + # Default county: Allegany = Region Z, REGULAR, UNIT_3 -> $207/week + # annual max reimbursement: $207 * 52 = $10,764 + # annual copay: $3 * 52 = $156 + # uncapped: max(12,000 - 156, 0) = 11,844 + # capped: min(11,844, 10,764) = 10,764 + # monthly: 10,764 / 12 = 897 + md_ccs: 897 + +- name: Case 2, two-parent family with two children and mixed income. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + employment_income: 60_000 + is_tax_unit_head_or_spouse: true + immigration_status: CITIZEN + person2: + age: 33 + self_employment_income: 20_000 + is_tax_unit_head_or_spouse: true + immigration_status: CITIZEN + person3: + age: 7 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + person4: + age: 3 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 4 + tax_units: + tax_unit: + members: [person1, person2, person3, person4] + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + spm_unit_pre_subsidy_childcare_expenses: 18_000 + households: + household: + members: [person1, person2, person3, person4] + state_code: MD + output: + # === Child eligibility === + # person1: adult -> false + # person2: adult -> false + # person3: age 7 < 13, dependent, citizen -> true + # person4: age 3 < 13, dependent, citizen -> true + md_ccs_eligible_child: [false, false, true, true] + + # === Income === + # employment: 60,000 + # self_employment: 20,000 * (1 - 0.30) = 14,000 + # total annual: 60,000 + 14,000 = 74,000 + # monthly countable: 74,000 / 12 = 6,166.67 + md_ccs_countable_income: 6_166.67 + + # === Income eligibility === + # hhs_smi for fam 4 = 149,249 + # monthly 75% SMI = 149,249 * 0.75 / 12 = 9,328.06 + # 6,166.67 <= 9,328.06 -> eligible + md_ccs_income_eligible: true + + md_ccs_eligible: true + + # === Copay === + # person3: 8 hrs/day >= 6 -> 3 units -> $3/week + # person4: 4 hrs/day, >3 and <6 -> 2 units -> $2/week + # total weekly copay: $3 + $2 = $5 + md_ccs_weekly_copay: 5 + + # === Benefit === + # annual copay: $5 * 52 = $260 + # annual benefit: max(18,000 - 260, 0) = 17,740 + # monthly: 17,740 / 12 = 1_478.33 + md_ccs: 1_478.33 + +- name: Case 3, TCA recipient family with zero copay. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 25 + employment_income: 15_000 + is_tax_unit_head_or_spouse: true + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + is_tanf_enrolled: true + spm_unit_pre_subsidy_childcare_expenses: 8_000 + households: + household: + members: [person1, person2] + state_code: MD + output: + # === Child eligibility === + md_ccs_eligible_child: [false, true] + + # === Income === + # monthly: 15,000 / 12 = 1,250 + md_ccs_countable_income: 1_250 + + # === Eligibility === + # TCA -> income test waived + md_ccs_income_eligible: true + md_ccs_eligible: true + + # === Copay === + # TCA recipient -> $0 + md_ccs_weekly_copay: 0 + + # === Benefit === + # annual: max(8,000 - 0, 0) = 8,000 + # monthly: 8,000 / 12 = 666.67 + md_ccs: 666.67 + +- name: Case 4, family at income boundary just below 75 percent SMI. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + employment_income: 100_000 + is_tax_unit_head_or_spouse: true + immigration_status: CITIZEN + person2: + age: 33 + is_tax_unit_head_or_spouse: true + immigration_status: CITIZEN + person3: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + person4: + age: 3 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2, person3, person4] + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + spm_unit_pre_subsidy_childcare_expenses: 20_000 + households: + household: + members: [person1, person2, person3, person4] + state_code: MD + output: + # === Child eligibility === + md_ccs_eligible_child: [false, false, true, true] + + # === Income === + # monthly countable: 100,000 / 12 = 8,333.33 + md_ccs_countable_income: 8_333.33 + + # === Income eligibility === + # hhs_smi fam 4 = 149,249 + # monthly 75% SMI = 149,249 * 0.75 / 12 = 9,328.06 + # 8,333.33 <= 9,328.06 -> eligible + md_ccs_income_eligible: true + + md_ccs_eligible: true + + # === Copay === + # 2 children, each full-time (8 hrs >= 6) -> $3 + $3 = $6/week + md_ccs_weekly_copay: 6 + + # === Benefit === + # annual copay: $6 * 52 = $312 + # annual benefit: max(20,000 - 312, 0) = 19,688 + # monthly: 19,688 / 12 = 1_640.67 + md_ccs: 1_640.67 + +- name: Case 5, enrolled family between 75 and 85 percent SMI with continuation eligibility. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + employment_income: 120_000 + is_tax_unit_head_or_spouse: true + immigration_status: CITIZEN + person2: + age: 33 + is_tax_unit_head_or_spouse: true + immigration_status: CITIZEN + person3: + age: 6 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + person4: + age: 2 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2, person3, person4] + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + md_ccs_enrolled: true + spm_unit_pre_subsidy_childcare_expenses: 22_000 + households: + household: + members: [person1, person2, person3, person4] + state_code: MD + output: + # === Child eligibility === + md_ccs_eligible_child: [false, false, true, true] + + # === Income === + # monthly: 120,000 / 12 = 10,000 + md_ccs_countable_income: 10_000 + + # === Income eligibility === + # monthly 75% SMI = 9,328.06 -> 10,000 > 9,328.06 (would fail initial) + # enrolled -> use 85% SMI = 149,249 * 0.85 / 12 = 10,571.81 + # 10,000 <= 10,571.81 -> eligible (continuation) + md_ccs_income_eligible: true + + md_ccs_eligible: true + + # === Copay === + # 2 children, each full-time -> $3 + $3 = $6/week + md_ccs_weekly_copay: 6 + + # === Benefit === + # Default county: Allegany = Region Z + # person3 (age 6): REGULAR, UNIT_3 -> $207/week + # person4 (age 2 = 24 months, not < 24): REGULAR, UNIT_3 -> $207/week + # annual max reimbursement: ($207 + $207) * 52 = $21,528 + # annual copay: $6 * 52 = $312 + # uncapped: max(22,000 - 312, 0) = 21,688 + # capped: min(21,688, 21,528) = 21,528 + # monthly: 21,528 / 12 = 1,794 + md_ccs: 1_794 + +- name: Case 6, SSI recipient with disabled teenager. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 45 + employment_income: 200_000 + ssi: 9_000 + is_tax_unit_head_or_spouse: true + immigration_status: CITIZEN + person2: + age: 16 + is_disabled: true + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 6 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 15_000 + households: + household: + members: [person1, person2] + state_code: MD + output: + # === Child eligibility === + # person2: age 16 < 19 (disabled threshold), disabled, dependent -> true + md_ccs_eligible_child: [false, true] + + # === Income === + # sources list does NOT include ssi (only employment_income counts here) + # employment_income: 200,000 / 12 = 16,666.67 + md_ccs_countable_income: 16_666.67 + + # === Eligibility === + # income $16,666.67/month > 75% SMI for fam 2 ($6,343.08) -> income test fails + md_ccs_income_eligible: false + # BUT SSI recipient (ssi > 0) -> overall eligibility via SSI bypass + md_ccs_eligible: true + + # === Copay === + # SSI recipient -> $0 + md_ccs_weekly_copay: 0 + + # === Benefit === + # Default county: Allegany = Region Z, REGULAR, UNIT_3 -> $207/week + # annual max reimbursement: $207 * 52 = $10,764 + # uncapped: max(15,000 - 0, 0) = 15,000 + # capped: min(15,000, 10,764) = 10,764 + # monthly: 10,764 / 12 = 897 + md_ccs: 897 + +- name: Case 7, family with income above 85 percent SMI is not eligible even when enrolled. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + employment_income: 140_000 + is_tax_unit_head_or_spouse: true + immigration_status: CITIZEN + person2: + age: 33 + is_tax_unit_head_or_spouse: true + immigration_status: CITIZEN + person3: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + person4: + age: 3 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2, person3, person4] + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + md_ccs_enrolled: true + spm_unit_pre_subsidy_childcare_expenses: 20_000 + households: + household: + members: [person1, person2, person3, person4] + state_code: MD + output: + # === Child eligibility === + md_ccs_eligible_child: [false, false, true, true] + + # === Income === + # monthly: 140,000 / 12 = 11,666.67 + md_ccs_countable_income: 11_666.67 + + # === Income eligibility === + # enrolled -> use 85% SMI = 149,249 * 0.85 / 12 = 10,571.81 + # 11,666.67 > 10,571.81 -> not eligible + md_ccs_income_eligible: false + + md_ccs_eligible: false + md_ccs: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs.yaml b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs.yaml new file mode 100644 index 00000000000..fcf5b997754 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs.yaml @@ -0,0 +1,176 @@ +# Tests for md_ccs (main benefit variable) +# Benefit = min(max(expenses - annual_copay, 0), max_reimbursement) / 12 +# COMAR 13A.14.06.11 + +- name: Case 1, eligible family with expenses under rate cap. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 50_000 + is_tax_unit_head_or_spouse: true + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 12_000 + households: + household: + members: [person1, person2] + state_code: MD + output: + # Default provider: LICENSED_CENTER, default county: Allegany = Region Z + # age 5 = REGULAR, 8hrs = UNIT_3 + # weekly rate: $207, annual max reimbursement: $207 * 52 = $10,764 + # weekly copay: $3, annual copay: $3 * 52 = $156 + # uncapped: max(12,000 - 156, 0) = 11,844 + # capped: min(11,844, 10,764) = 10,764 + # monthly: 10,764 / 12 = 897 + md_ccs: 897 + +- name: Case 2, ineligible family gets zero benefit. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 50_000 + is_tax_unit_head_or_spouse: true + person2: + age: 15 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 12_000 + households: + household: + members: [person1, person2] + state_code: MD + output: + # child age 15 >= 13, not disabled -> no eligible child -> not eligible + md_ccs: 0 + +- name: Case 3, TCA family with zero copay gets full benefit. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 20_000 + is_tax_unit_head_or_spouse: true + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + is_tanf_enrolled: true + spm_unit_pre_subsidy_childcare_expenses: 10_000 + households: + household: + members: [person1, person2] + state_code: MD + output: + # TCA: copay $0 + # weekly rate: $207 (default center, Allegany = Region Z, regular, unit 3) + # annual max reimbursement: $207 * 52 = $10,764 + # uncapped: max(10,000 - 0, 0) = 10,000 + # capped: min(10,000, 10,764) = 10,000 + # monthly: 10,000 / 12 = 833.33 + md_ccs: 833.33 + +- name: Case 4, benefit capped at max reimbursement rate. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 40_000 + is_tax_unit_head_or_spouse: true + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 4 + md_ccs_provider_type: LICENSED_FAMILY + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 20_000 + households: + household: + members: [person1, person2] + state_code: MD + county: ALLEGANY_COUNTY_MD + output: + # Provider: LICENSED_FAMILY, Region Z (Allegany), REGULAR (age 5), UNIT_2 (4hrs) + # weekly rate: $114 + # annual max reimbursement: $114 * 52 = $5,928 + # weekly copay: $3 (part-time), annual copay: $3 * 52 = $156 + # uncapped: max(20,000 - 156, 0) = 19,844 + # capped: min(19,844, 5,928) = 5,928 + # monthly: 5,928 / 12 = 494 + md_ccs: 494 + +- name: Case 5, informal provider rate by county. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 40_000 + is_tax_unit_head_or_spouse: true + person2: + age: 1 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + md_ccs_provider_type: INFORMAL + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 20_000 + households: + household: + members: [person1, person2] + state_code: MD + county: HOWARD_COUNTY_MD + output: + # Provider: INFORMAL, Howard County, INFANT (age 1 = 12 months < 24), UNIT_3 (8hrs) + # weekly rate: $195 + # annual max reimbursement: $195 * 52 = $10,140 + # weekly copay: $3, annual copay: $3 * 52 = $156 + # uncapped: max(20,000 - 156, 0) = 19,844 + # capped: min(19,844, 10,140) = 10,140 + # monthly: 10,140 / 12 = 845 + md_ccs: 845 diff --git a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_countable_income.yaml new file mode 100644 index 00000000000..f17d9b842fb --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_countable_income.yaml @@ -0,0 +1,98 @@ +# Tests for md_ccs_countable_income +# Countable income = adds sources + self_employment_income * (1 - 0.30) +# Child support received is excluded since 2022. +# COMAR 13A.14.06.03(F)(3)-(8) + +- name: Case 1, employment income only. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 30_000 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MD + output: + # employment_income is in sources list + # 30,000 / 12 = 2,500 + md_ccs_countable_income: 2_500 + +- name: Case 2, self-employment income with 30 percent deduction. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + self_employment_income: 20_000 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MD + output: + # self_employment_income 20,000 * (1 - 0.30) = 14,000 + # 14,000 / 12 = 1,166.67 + md_ccs_countable_income: 1_166.67 + +- name: Case 3, mixed employment and self-employment income. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 30_000 + self_employment_income: 20_000 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MD + output: + # employment_income: 30,000 + # self_employment_income: 20,000 * (1 - 0.30) = 14,000 + # total annual: 30,000 + 14,000 = 44,000 + # monthly: 44,000 / 12 = 3,666.67 + md_ccs_countable_income: 3_666.67 + +- name: Case 4, child support received is excluded from income. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 30_000 + child_support_received: 6_000 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MD + output: + # employment_income: 30,000 (counted) + # child_support_received: 6,000 (EXCLUDED per Ch 525/526 of 2022) + # total annual: 30,000 + # monthly: 30,000 / 12 = 2,500 + md_ccs_countable_income: 2_500 diff --git a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_eligible.yaml new file mode 100644 index 00000000000..cda4399c201 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_eligible.yaml @@ -0,0 +1,114 @@ +# Tests for md_ccs_eligible +# Eligible when: has at least one eligible child + income eligible +# OR TCA/SSI recipient (income test waived) + +- name: Case 1, basic eligible family with eligible child and income eligible. + period: 2025-01 + input: + people: + person1: + age: 30 + employment_income: 50_000 + is_tax_unit_head_or_spouse: true + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MD + output: + # child age 5 < 13, dependent, citizen -> eligible child + # income 50,000 well below 75% SMI for family of 2 + # (75% SMI for fam 2 = 101,489.32 * 0.75 = 76,116.99) + md_ccs_eligible: true + +- name: Case 2, TCA recipient is eligible regardless of income. + period: 2025-01 + input: + people: + person1: + age: 30 + employment_income: 200_000 + is_tax_unit_head_or_spouse: true + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + is_tanf_enrolled: true + households: + household: + members: [person1, person2] + state_code: MD + output: + # TCA recipient -> income test waived + # Has eligible child -> eligible + md_ccs_eligible: true + +- name: Case 3, SSI recipient is eligible regardless of income. + period: 2025-01 + input: + people: + person1: + age: 30 + employment_income: 200_000 + ssi: 9_000 + is_tax_unit_head_or_spouse: true + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MD + output: + # SSI recipient (ssi > 0) -> income test waived + # Has eligible child -> eligible + md_ccs_eligible: true + +- name: Case 4, no eligible children means not eligible. + period: 2025-01 + input: + people: + person1: + age: 30 + employment_income: 50_000 + is_tax_unit_head_or_spouse: true + person2: + age: 15 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MD + output: + # child age 15 >= 13, not disabled -> not eligible child + # no eligible children -> not eligible + md_ccs_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_eligible_child.yaml b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_eligible_child.yaml new file mode 100644 index 00000000000..12ce3947a4a --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_eligible_child.yaml @@ -0,0 +1,132 @@ +# Tests for md_ccs_eligible_child +# Child must be: under 13 (or under 19 if disabled), a tax unit dependent, +# and CCDF immigration eligible. +# COMAR 13A.14.06.02 (definition of "Child") + +- name: Case 1, child age 5 not disabled is eligible. + period: 2025-01 + input: + people: + person1: + age: 30 + is_tax_unit_head_or_spouse: true + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MD + output: + # person1: adult, not dependent -> false + # person2: age 5 < 13, dependent, citizen -> true + md_ccs_eligible_child: [false, true] + +- name: Case 2, child age 14 not disabled is not eligible. + period: 2025-01 + input: + people: + person1: + age: 40 + is_tax_unit_head_or_spouse: true + person2: + age: 14 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MD + output: + # person2: age 14 >= 13 (non-disabled threshold) -> false + md_ccs_eligible_child: [false, false] + +- name: Case 3, disabled child age 14 is eligible. + period: 2025-01 + input: + people: + person1: + age: 40 + is_tax_unit_head_or_spouse: true + person2: + age: 14 + is_disabled: true + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MD + output: + # person2: age 14 < 19 (disabled threshold), disabled -> true + md_ccs_eligible_child: [false, true] + +- name: Case 4, disabled child age 19 is not eligible. + period: 2025-01 + input: + people: + person1: + age: 45 + is_tax_unit_head_or_spouse: true + person2: + age: 19 + is_disabled: true + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MD + output: + # person2: age 19 >= 19 (disabled threshold) -> false + md_ccs_eligible_child: [false, false] + +- name: Case 5, child age 12 at boundary is eligible. + period: 2025-01 + input: + people: + person1: + age: 35 + is_tax_unit_head_or_spouse: true + person2: + age: 12 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MD + output: + # person2: age 12 < 13 -> true + md_ccs_eligible_child: [false, true] diff --git a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_income_eligible.yaml new file mode 100644 index 00000000000..1fa9a6355f2 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_income_eligible.yaml @@ -0,0 +1,115 @@ +# Tests for md_ccs_income_eligible +# Initial applicants: income <= 75% SMI +# Continuing families (md_ccs_enrolled): income <= 85% SMI +# TCA/SSI recipients: income test waived +# +# For MD family of 4 in 2025 (FY2025 SMI base = $149,249): +# hhs_smi = 149,249 * (0.52 + 0.16 * 3) = 149,249 +# 75% SMI = 149,249 * 0.75 = 111,936.75 annual +# 85% SMI = 149,249 * 0.85 = 126,861.65 annual + +- name: Case 1, family of 4 with income below 75 percent SMI is eligible. + period: 2025-01 + input: + people: + person1: + age: 35 + employment_income: 100_000 + person2: + age: 33 + person3: + age: 8 + person4: + age: 5 + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + households: + household: + members: [person1, person2, person3, person4] + state_code: MD + output: + # Monthly countable income: 100,000 / 12 = 8,333.33 + # Monthly 75% SMI threshold: 149,249 * 0.75 / 12 = 9,328.06 + # 8,333.33 <= 9,328.06 -> eligible + md_ccs_income_eligible: true + +- name: Case 2, family of 4 with income above 75 percent SMI is not eligible. + period: 2025-01 + input: + people: + person1: + age: 35 + employment_income: 120_000 + person2: + age: 33 + person3: + age: 8 + person4: + age: 5 + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + households: + household: + members: [person1, person2, person3, person4] + state_code: MD + output: + # Monthly countable income: 120,000 / 12 = 10,000 + # Monthly 75% SMI threshold: 149,249 * 0.75 / 12 = 9,328.06 + # 10,000 > 9,328.06 -> not eligible (new applicant) + md_ccs_income_eligible: false + +- name: Case 3, enrolled family of 4 with income between 75 and 85 percent SMI is eligible. + period: 2025-01 + input: + people: + person1: + age: 35 + employment_income: 120_000 + person2: + age: 33 + person3: + age: 8 + person4: + age: 5 + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + md_ccs_enrolled: true + households: + household: + members: [person1, person2, person3, person4] + state_code: MD + output: + # Monthly countable income: 120,000 / 12 = 10,000 + # Monthly 85% SMI threshold: 149,249 * 0.85 / 12 = 10,571.81 + # 10,000 <= 10,571.81 -> eligible (continuation) + md_ccs_income_eligible: true + +- name: Case 4, enrolled family of 4 with income above 85 percent SMI is not eligible. + period: 2025-01 + input: + people: + person1: + age: 35 + employment_income: 130_000 + person2: + age: 33 + person3: + age: 8 + person4: + age: 5 + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + md_ccs_enrolled: true + households: + household: + members: [person1, person2, person3, person4] + state_code: MD + output: + # Monthly countable income: 130,000 / 12 = 10,833.33 + # Monthly 85% SMI threshold: 149,249 * 0.85 / 12 = 10,571.81 + # 10,833.33 > 10,571.81 -> not eligible + md_ccs_income_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_payment_rate.yaml b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_payment_rate.yaml new file mode 100644 index 00000000000..1cb4c1ec973 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_payment_rate.yaml @@ -0,0 +1,122 @@ +# Tests for md_ccs_payment_rate (weekly rate lookup) +# Formal rates by region/age/unit, informal rates by county/age/unit + +- name: Licensed center, Region X (Howard), regular age, full-time. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 40_000 + is_tax_unit_head_or_spouse: true + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MD + county: HOWARD_COUNTY_MD + output: + # Region X, REGULAR (age 5), UNIT_3 (8hrs): $424/week + md_ccs_payment_rate: [0, 424] + +- name: Licensed family, Region Y (Baltimore Co), infant, part-time. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 40_000 + is_tax_unit_head_or_spouse: true + person2: + age: 1 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 4 + md_ccs_provider_type: LICENSED_FAMILY + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MD + county: BALTIMORE_COUNTY_MD + output: + # Region Y, INFANT (age 1 = 12 months < 24), UNIT_2 (4hrs): $167/week + md_ccs_payment_rate: [0, 167] + +- name: Informal provider, Montgomery County, regular, hourly. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 40_000 + is_tax_unit_head_or_spouse: true + person2: + age: 3 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 2 + md_ccs_provider_type: INFORMAL + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MD + county: MONTGOMERY_COUNTY_MD + output: + # Informal, Montgomery Co, REGULAR (age 3 = 36 months >= 24), UNIT_1 (2hrs): $59/week + md_ccs_payment_rate: [0, 59] + +- name: Licensed center, Baltimore City, infant, full-time. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 40_000 + is_tax_unit_head_or_spouse: true + person2: + age: 1 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MD + county: BALTIMORE_CITY_MD + output: + # Baltimore City, INFANT (age 1 = 12 months), UNIT_3 (8hrs): $376/week + md_ccs_payment_rate: [0, 376] diff --git a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_weekly_copay.yaml b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_weekly_copay.yaml new file mode 100644 index 00000000000..3d0058ea60e --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_weekly_copay.yaml @@ -0,0 +1,242 @@ +# Tests for md_ccs_weekly_copay +# Weekly copay by service units: +# Full-time (>=6 hrs/day, 3 units): $3/week +# Part-time (>3 to <6 hrs/day, 2 units): $2/week +# Hourly (<=3 hrs/day, 1 unit): $1/week +# Exempt: TCA, SSI, SNAP, WIC recipients pay $0 +# Federal 7% cap: annual copay cannot exceed 7% of countable income +# Copay assessed for up to 3 children +# COMAR 13A.14.06.12; Chapter 717 of 2024; 45 CFR 98.45(k) + +- name: Case 1, standard family with full-time care. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 50_000 + is_tax_unit_head_or_spouse: true + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MD + output: + # child hours/day = 8 >= 6 -> 3 units (full-time) -> $3/week + # annual copay: $3 * 52 = $156 -> well below 7% of $50,000 ($3,500) + md_ccs_weekly_copay: 3 + +- name: Case 2, standard family with part-time care. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 50_000 + is_tax_unit_head_or_spouse: true + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 5 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MD + output: + # child hours/day = 5, >3 and <6 -> 2 units (part-time) -> $2/week + md_ccs_weekly_copay: 2 + +- name: Case 3, standard family with hourly care. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 50_000 + is_tax_unit_head_or_spouse: true + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 2 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MD + output: + # child hours/day = 2, <=3 -> 1 unit (hourly) -> $1/week + md_ccs_weekly_copay: 1 + +- name: Case 4, TCA recipient pays zero copay. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 50_000 + is_tax_unit_head_or_spouse: true + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + is_tanf_enrolled: true + households: + household: + members: [person1, person2] + state_code: MD + output: + # TCA recipient -> copay exempt + md_ccs_weekly_copay: 0 + +- name: Case 5, SSI recipient pays zero copay. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 50_000 + ssi: 9_000 + is_tax_unit_head_or_spouse: true + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MD + output: + # SSI recipient (ssi > 0) -> copay exempt + md_ccs_weekly_copay: 0 + +- name: Case 6, SNAP eligible family pays zero copay. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 50_000 + is_tax_unit_head_or_spouse: true + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + md_ccs_receives_snap: true + households: + household: + members: [person1, person2] + state_code: MD + output: + # SNAP recipient -> copay waived per Ch 525/526 of 2022 (bare input) + md_ccs_weekly_copay: 0 + +- name: Case 7, WIC eligible parent pays zero copay. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 50_000 + is_tax_unit_head_or_spouse: true + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + md_ccs_receives_wic: true + households: + household: + members: [person1, person2] + state_code: MD + output: + # WIC recipient -> copay waived per Ch 525/526 of 2022 + md_ccs_weekly_copay: 0 + +- name: Case 8, federal 7 percent cap on very low income family. + period: 2025-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 2_000 + is_tax_unit_head_or_spouse: true + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MD + output: + # Full-time -> $3/week raw copay + # Annual raw copay: $3 * 52 = $156 + # 7% of annual income: $2,000 * 0.07 = $140 + # $156 > $140 -> 7% cap applies + # Capped weekly: $140 / 52 = $2.69 + md_ccs_weekly_copay: 2.69 diff --git a/policyengine_us/variables/gov/states/md/msde/ccs/eligibility/md_ccs_eligible.py b/policyengine_us/variables/gov/states/md/msde/ccs/eligibility/md_ccs_eligible.py new file mode 100644 index 00000000000..dbca8e755fc --- /dev/null +++ b/policyengine_us/variables/gov/states/md/msde/ccs/eligibility/md_ccs_eligible.py @@ -0,0 +1,20 @@ +from policyengine_us.model_api import * + + +class md_ccs_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Eligible for Maryland Child Care Scholarship (CCS)" + definition_period = MONTH + defined_for = StateCode.MD + reference = ( + "https://dsd.maryland.gov/regulations/Pages/13A.14.06.03.aspx", + "https://mgaleg.maryland.gov/2022RS/Chapters_noln/CH_525_hb0275e.pdf", + ) + + def formula(spm_unit, period, parameters): + has_eligible_child = add(spm_unit, period, ["md_ccs_eligible_child"]) > 0 + income_eligible = spm_unit("md_ccs_income_eligible", period) + is_tca = spm_unit("is_tanf_enrolled", period) + receives_ssi = add(spm_unit, period, ["ssi"]) > 0 + return has_eligible_child & (income_eligible | is_tca | receives_ssi) diff --git a/policyengine_us/variables/gov/states/md/msde/ccs/eligibility/md_ccs_eligible_child.py b/policyengine_us/variables/gov/states/md/msde/ccs/eligibility/md_ccs_eligible_child.py new file mode 100644 index 00000000000..de54e423f9c --- /dev/null +++ b/policyengine_us/variables/gov/states/md/msde/ccs/eligibility/md_ccs_eligible_child.py @@ -0,0 +1,22 @@ +from policyengine_us.model_api import * + + +class md_ccs_eligible_child(Variable): + value_type = bool + entity = Person + label = "Eligible child for Maryland Child Care Scholarship (CCS)" + definition_period = MONTH + defined_for = StateCode.MD + reference = "https://dsd.maryland.gov/regulations/Pages/13A.14.06.02.aspx" + + def formula(person, period, parameters): + p = parameters(period).gov.states.md.msde.ccs.age_threshold + age = person("age", period.this_year) + is_disabled = person("is_disabled", period.this_year) + age_limit = where(is_disabled, p.disabled_child, p.child) + age_eligible = age < age_limit + is_dependent = person("is_tax_unit_dependent", period.this_year) + immigration_eligible = person( + "is_ccdf_immigration_eligible_child", period.this_year + ) + return age_eligible & is_dependent & immigration_eligible diff --git a/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs.py b/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs.py new file mode 100644 index 00000000000..8f35d2b6a95 --- /dev/null +++ b/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs.py @@ -0,0 +1,33 @@ +from policyengine_us.model_api import * + + +class md_ccs(Variable): + value_type = float + entity = SPMUnit + unit = USD + label = "Maryland Child Care Scholarship (CCS) benefit amount" + definition_period = MONTH + defined_for = "md_ccs_eligible" + reference = ( + "https://dsd.maryland.gov/regulations/Pages/13A.14.06.11.aspx", + "https://earlychildhood.marylandpublicschools.org/families/child-care-scholarship-program/child-care-scholarship-rates", + ) + + def formula(spm_unit, period, parameters): + weekly_copay = spm_unit("md_ccs_weekly_copay", period) + annual_copay = weekly_copay * WEEKS_IN_YEAR + + actual_expenses = spm_unit( + "spm_unit_pre_subsidy_childcare_expenses", period.this_year + ) + + person = spm_unit.members + is_eligible_child = person("md_ccs_eligible_child", period) + weekly_rate = person("md_ccs_payment_rate", period) + weekly_to_annual = WEEKS_IN_YEAR + max_reimbursement = ( + spm_unit.sum(weekly_rate * is_eligible_child) * weekly_to_annual + ) + + uncapped_benefit = max_(actual_expenses - annual_copay, 0) + return min_(uncapped_benefit, max_reimbursement) / MONTHS_IN_YEAR diff --git a/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_countable_income.py b/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_countable_income.py new file mode 100644 index 00000000000..4dcaa4e2bfb --- /dev/null +++ b/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_countable_income.py @@ -0,0 +1,26 @@ +from policyengine_us.model_api import * + + +class md_ccs_countable_income(Variable): + value_type = float + entity = SPMUnit + unit = USD + label = "Maryland Child Care Scholarship (CCS) countable income" + definition_period = MONTH + defined_for = StateCode.MD + reference = ( + "https://dsd.maryland.gov/regulations/Pages/13A.14.06.03.aspx", + "https://mgaleg.maryland.gov/2022RS/Chapters_noln/CH_525_hb0275e.pdf", + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.md.msde.ccs.income + sources_income = add( + spm_unit, + period, + p.countable_income.sources, + ) + self_employment_income = add(spm_unit, period, ["self_employment_income"]) + return sources_income + self_employment_income * ( + 1 - p.self_employment_deduction_rate + ) diff --git a/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_enrolled.py b/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_enrolled.py new file mode 100644 index 00000000000..79dca26a13c --- /dev/null +++ b/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_enrolled.py @@ -0,0 +1,9 @@ +from policyengine_us.model_api import * + + +class md_ccs_enrolled(Variable): + value_type = bool + entity = SPMUnit + definition_period = MONTH + label = "Whether the family is currently enrolled in Maryland Child Care Scholarship (CCS)" + defined_for = StateCode.MD diff --git a/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_income_eligible.py b/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_income_eligible.py new file mode 100644 index 00000000000..f37a0b63bee --- /dev/null +++ b/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_income_eligible.py @@ -0,0 +1,25 @@ +from policyengine_us.model_api import * + + +class md_ccs_income_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Maryland Child Care Scholarship (CCS) income eligible" + definition_period = MONTH + defined_for = StateCode.MD + reference = ( + "https://dsd.maryland.gov/regulations/Pages/13A.14.06.03.aspx", + "https://mgaleg.maryland.gov/2022RS/Chapters_noln/CH_525_hb0275e.pdf", + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.md.msde.ccs.income.smi_rate + countable_income = spm_unit("md_ccs_countable_income", period) + smi = spm_unit("hhs_smi", period) + enrolled = spm_unit("md_ccs_enrolled", period) + income_limit = where( + enrolled, + smi * p.continuation, + smi * p.initial, + ) + return countable_income <= income_limit diff --git a/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_provider_type.py b/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_provider_type.py new file mode 100644 index 00000000000..ffe391bad0a --- /dev/null +++ b/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_provider_type.py @@ -0,0 +1,18 @@ +from policyengine_us.model_api import * + + +class MDCCSProviderType(Enum): + LICENSED_CENTER = "Licensed Child Care Center" + LICENSED_FAMILY = "Licensed Family Child Care Home" + INFORMAL = "Informal/License-Exempt" + + +class md_ccs_provider_type(Variable): + value_type = Enum + entity = Person + possible_values = MDCCSProviderType + default_value = MDCCSProviderType.LICENSED_CENTER + definition_period = MONTH + label = "Maryland CCS child care provider type" + defined_for = StateCode.MD + reference = "https://dsd.maryland.gov/regulations/Pages/13A.14.06.11.aspx" diff --git a/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_receives_snap.py b/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_receives_snap.py new file mode 100644 index 00000000000..b7d9d39a840 --- /dev/null +++ b/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_receives_snap.py @@ -0,0 +1,9 @@ +from policyengine_us.model_api import * + + +class md_ccs_receives_snap(Variable): + value_type = bool + entity = SPMUnit + definition_period = MONTH + label = "Whether the family receives SNAP (used for Maryland CCS copay waiver)" + defined_for = StateCode.MD diff --git a/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_receives_wic.py b/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_receives_wic.py new file mode 100644 index 00000000000..7b85d732492 --- /dev/null +++ b/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_receives_wic.py @@ -0,0 +1,9 @@ +from policyengine_us.model_api import * + + +class md_ccs_receives_wic(Variable): + value_type = bool + entity = SPMUnit + definition_period = MONTH + label = "Whether the family receives WIC (used for Maryland CCS copay waiver)" + defined_for = StateCode.MD diff --git a/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_weekly_copay.py b/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_weekly_copay.py new file mode 100644 index 00000000000..84148219da6 --- /dev/null +++ b/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_weekly_copay.py @@ -0,0 +1,54 @@ +from policyengine_us.model_api import * + + +class md_ccs_weekly_copay(Variable): + value_type = float + entity = SPMUnit + unit = USD + label = "Maryland Child Care Scholarship (CCS) weekly copayment" + definition_period = MONTH + defined_for = StateCode.MD + reference = ( + "https://dsd.maryland.gov/regulations/Pages/13A.14.06.12.aspx", + "https://mgaleg.maryland.gov/2024RS/Chapters_noln/CH_717_sb0482e.pdf", + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.md.msde.ccs.copay + + # TCA/SSI recipients pay $0 copayment per COMAR 13A.14.06.12(A)(1) + is_tca = spm_unit("is_tanf_enrolled", period) + receives_ssi = add(spm_unit, period, ["ssi"]) > 0 + + # SNAP/WIC recipients have copayments waived per Chapters 525/526 of 2022 + # Use bare inputs to avoid circular dependency through SNAP/TANF/childcare chain + is_snap = spm_unit("md_ccs_receives_snap", period) + receives_wic = spm_unit("md_ccs_receives_wic", period) + exempt = is_tca | receives_ssi | is_snap | receives_wic + + # Weekly copay per child based on service unit (enum-keyed lookup) + person = spm_unit.members + service_unit = person("md_ccs_service_unit", period) + weekly_per_child = p.weekly_amount[service_unit] + + # Only charge copay for eligible children + is_eligible_child = person("md_ccs_eligible_child", period) + weekly_per_child = where(is_eligible_child, weekly_per_child, 0) + + # Copay assessed for up to max_children_with_copay children + eligible_child_count = add(spm_unit, period, ["md_ccs_eligible_child"]) + capped_count = min_(eligible_child_count, p.max_children_with_copay) + total_weekly = spm_unit.sum(weekly_per_child) + scale = where( + eligible_child_count > 0, + capped_count / eligible_child_count, + 0, + ) + scaled_weekly = total_weekly * scale + + # Federal cap: copay cannot exceed 7% of gross income per 45 CFR 98.45(k) + countable_income = spm_unit("md_ccs_countable_income", period) + weekly_income = countable_income * MONTHS_IN_YEAR / WEEKS_IN_YEAR + federal_cap = weekly_income * p.federal_cap_rate + + return where(exempt, 0, min_(scaled_weekly, federal_cap)) diff --git a/policyengine_us/variables/gov/states/md/msde/ccs/md_child_care_subsidies.py b/policyengine_us/variables/gov/states/md/msde/ccs/md_child_care_subsidies.py new file mode 100644 index 00000000000..7c31208d248 --- /dev/null +++ b/policyengine_us/variables/gov/states/md/msde/ccs/md_child_care_subsidies.py @@ -0,0 +1,11 @@ +from policyengine_us.model_api import * + + +class md_child_care_subsidies(Variable): + value_type = float + entity = SPMUnit + label = "Maryland child care subsidies" + unit = USD + definition_period = YEAR + defined_for = StateCode.MD + adds = ["md_ccs"] diff --git a/policyengine_us/variables/gov/states/md/msde/ccs/payment/md_ccs_age_group.py b/policyengine_us/variables/gov/states/md/msde/ccs/payment/md_ccs_age_group.py new file mode 100644 index 00000000000..7d4bcadfe87 --- /dev/null +++ b/policyengine_us/variables/gov/states/md/msde/ccs/payment/md_ccs_age_group.py @@ -0,0 +1,26 @@ +from policyengine_us.model_api import * + + +class MDCCSAgeGroup(Enum): + REGULAR = "Regular" + INFANT = "Infant" + + +class md_ccs_age_group(Variable): + value_type = Enum + entity = Person + possible_values = MDCCSAgeGroup + default_value = MDCCSAgeGroup.REGULAR + definition_period = MONTH + defined_for = StateCode.MD + label = "Maryland CCS child age group for rate purposes" + reference = "https://earlychildhood.marylandpublicschools.org/families/child-care-scholarship-program/child-care-scholarship-rates" + + def formula(person, period, parameters): + p = parameters(period).gov.states.md.msde.ccs.payment + age_months = person("age", period.this_year) * MONTHS_IN_YEAR + return where( + age_months < p.infant_age_threshold, + MDCCSAgeGroup.INFANT, + MDCCSAgeGroup.REGULAR, + ) diff --git a/policyengine_us/variables/gov/states/md/msde/ccs/payment/md_ccs_payment_rate.py b/policyengine_us/variables/gov/states/md/msde/ccs/payment/md_ccs_payment_rate.py new file mode 100644 index 00000000000..9dd663258c1 --- /dev/null +++ b/policyengine_us/variables/gov/states/md/msde/ccs/payment/md_ccs_payment_rate.py @@ -0,0 +1,41 @@ +from policyengine_us.model_api import * +from policyengine_us.variables.gov.states.md.msde.ccs.md_ccs_provider_type import ( + MDCCSProviderType, +) + + +class md_ccs_payment_rate(Variable): + value_type = float + entity = Person + unit = USD + label = "Maryland Child Care Scholarship (CCS) weekly payment rate" + definition_period = MONTH + defined_for = "md_ccs_eligible_child" + reference = "https://earlychildhood.marylandpublicschools.org/families/child-care-scholarship-program/child-care-scholarship-rates" + + def formula(person, period, parameters): + p = parameters(period).gov.states.md.msde.ccs.payment + provider_type = person("md_ccs_provider_type", period) + age_group = person("md_ccs_age_group", period) + service_unit = person("md_ccs_service_unit", period) + region = person.household("md_ccs_region", period) + + # Formal rates: by region, age group, and service unit + center_rate = p.formal.licensed_center[region][age_group][service_unit] + family_rate = p.formal.licensed_family[region][age_group][service_unit] + + # Informal rates: by county, age group, and service unit + county = person.household("county_str", period) + in_md = person.household("state_code_str", period) == "MD" + safe_county = where(in_md, county, "ALLEGANY_COUNTY_MD") + informal_rate = p.informal.rates[safe_county][age_group][service_unit] + + return select( + [ + provider_type == MDCCSProviderType.LICENSED_CENTER, + provider_type == MDCCSProviderType.LICENSED_FAMILY, + provider_type == MDCCSProviderType.INFORMAL, + ], + [center_rate, family_rate, informal_rate], + default=center_rate, + ) diff --git a/policyengine_us/variables/gov/states/md/msde/ccs/payment/md_ccs_region.py b/policyengine_us/variables/gov/states/md/msde/ccs/payment/md_ccs_region.py new file mode 100644 index 00000000000..0b144b1ee94 --- /dev/null +++ b/policyengine_us/variables/gov/states/md/msde/ccs/payment/md_ccs_region.py @@ -0,0 +1,51 @@ +from policyengine_us.model_api import * + + +class MDCCSRegion(Enum): + REGION_U = "Region U" + REGION_V = "Region V" + REGION_W = "Region W" + REGION_X = "Region X" + REGION_Y = "Region Y" + REGION_Z = "Region Z" + BALTIMORE_CITY = "Baltimore City" + + +class md_ccs_region(Variable): + value_type = Enum + entity = Household + possible_values = MDCCSRegion + default_value = MDCCSRegion.REGION_W + definition_period = MONTH + defined_for = StateCode.MD + label = "Maryland CCS rate region" + reference = "https://earlychildhood.marylandpublicschools.org/families/child-care-scholarship-program/child-care-scholarship-rates" + + def formula(household, period, parameters): + county = household("county_str", period) + p = parameters(period).gov.states.md.msde.ccs.payment + is_region_u = np.isin(county, p.region_u_counties) + is_region_v = np.isin(county, p.region_v_counties) + is_region_x = np.isin(county, p.region_x_counties) + is_region_y = np.isin(county, p.region_y_counties) + is_region_z = np.isin(county, p.region_z_counties) + is_baltimore_city = np.isin(county, p.baltimore_city_counties) + return select( + [ + is_region_u, + is_region_v, + is_region_x, + is_region_y, + is_region_z, + is_baltimore_city, + ], + [ + MDCCSRegion.REGION_U, + MDCCSRegion.REGION_V, + MDCCSRegion.REGION_X, + MDCCSRegion.REGION_Y, + MDCCSRegion.REGION_Z, + MDCCSRegion.BALTIMORE_CITY, + ], + default=MDCCSRegion.REGION_W, + ) diff --git a/policyengine_us/variables/gov/states/md/msde/ccs/payment/md_ccs_service_unit.py b/policyengine_us/variables/gov/states/md/msde/ccs/payment/md_ccs_service_unit.py new file mode 100644 index 00000000000..0d4b6cf4ab3 --- /dev/null +++ b/policyengine_us/variables/gov/states/md/msde/ccs/payment/md_ccs_service_unit.py @@ -0,0 +1,28 @@ +from policyengine_us.model_api import * + + +class MDCCSServiceUnit(Enum): + UNIT_1 = "1 Unit (3 hours or less per day)" + UNIT_2 = "2 Units (more than 3 to less than 6 hours per day)" + UNIT_3 = "3 Units (6 or more hours per day)" + + +class md_ccs_service_unit(Variable): + value_type = Enum + entity = Person + possible_values = MDCCSServiceUnit + default_value = MDCCSServiceUnit.UNIT_3 + definition_period = MONTH + defined_for = StateCode.MD + label = "Maryland CCS service unit category" + reference = "https://dsd.maryland.gov/regulations/Pages/13A.14.06.11.aspx" + + def formula(person, period, parameters): + hours_per_day = person("childcare_hours_per_day", period.this_year) + p = parameters(period).gov.states.md.msde.ccs.copay + units = p.unit_hours.calc(hours_per_day) + return select( + [units == 3, units == 2], + [MDCCSServiceUnit.UNIT_3, MDCCSServiceUnit.UNIT_2], + default=MDCCSServiceUnit.UNIT_1, + ) diff --git a/sources/working_references.md b/sources/working_references.md new file mode 100644 index 00000000000..02cadffe599 --- /dev/null +++ b/sources/working_references.md @@ -0,0 +1,271 @@ +# Maryland Child Care Scholarship (CCS) Program - Working References + +## Official Program Name +**Child Care Scholarship (CCS) Program** (formerly "Child Care Subsidy Program") + +## Administering Agency +Maryland State Department of Education (MSDE), Division of Early Childhood, Office of Child Care + +## Primary Regulations + +### COMAR 13A.14.06 - Child Care Subsidy Program (Full Chapter) +- **URL**: http://mdrules.elaws.us/comar/13a.14.06 +- **PDF (Jan 2023 version with income tables)**: https://marylandpublicschools.org/stateboard/Documents/2023/0124/COMAR13A.14.06.pdf +- **Local copy**: `/tmp/md-comar-13a1406.pdf` +- **Sections**: + - .01 Purpose + - .02 Definitions + - .03 Eligibility (income scales, need requirements, categorical exemptions) + - .04 Pursuit of Child Support Obligations + - .05 Application Process + - .06 Provider Requirements + - .07 Child Care Vouchers + - .08 Service Groups (priority levels) + - .09 Redetermination + - .10 Termination + - .11 Payments for Child Care Services + - .12 Copayments (regional copayment tables, income levels A-J) + - .13 Confidentiality + - .14 Intentional Program Violations + - .15 Hearings and Appeals + +### Individual COMAR Sections Online +- **Definitions**: http://mdrules.elaws.us/comar/13a.14.06.02 +- **Eligibility**: http://mdrules.elaws.us/comar/13a.14.06.03 +- **Service Groups**: http://mdrules.elaws.us/comar/13a.14.06.08 +- **Copayments**: http://mdrules.elaws.us/comar/13a.14.06.12 +- **Cornell LII (full chapter)**: https://www.law.cornell.edu/regulations/maryland/title-13A/subtitle-14/chapter-13A.14.06 + +## Income Eligibility + +### Current Income Eligibility Scale (updated Dec 15, 2024) +- **Source**: CCS Scholarship Brochure (most current) +- **URL**: https://earlychildhood.marylandpublicschools.org/system/files/filedepot/2/scholarship-brochure-4.pdf +- **Local copy**: `/tmp/md-ccs-brochure.pdf` +- **Standard**: 75% of State Median Income (SMI) for initial eligibility; 85% SMI for continuation +- **Initial Income Scale (annual)**: + - Family of 2: $76,117 + - Family of 3: $94,026 + - Family of 4: $111,936 + - Family of 5: $129,846 + - Family of 6: $147,756 + - Family of 7: $151,114 + - Family of 8: $154,472 + - Family of 9: $157,830 + - Family of 10: $161,188 + - Family of 11: $164,546 + - Family of 12: $167,904 +- **Continuation Income Scale (annual)**: + - Family of 2: $86,266 + - Family of 3: $106,563 + - Family of 4: $126,861 + - Family of 5: $147,159 + - Family of 6: $167,457 + - Family of 7: $171,262 + - Family of 8: $175,068 + - Family of 9: $178,874 + - Family of 10: $182,680 + - Family of 11: $186,486 + - Family of 12: $190,292 + +### Previous Income Eligibility Scale (pre-Dec 2024) +- **Source**: CCS Income Eligibility Scale PDF +- **URL**: https://earlychildhood.marylandpublicschools.org/system/files/filedepot/2/income_eligibility_scale.pdf +- **Local copy**: `/tmp/md-ccs-income-scale.pdf` +- **Initial thresholds**: Family of 2: $61,222; Family of 4: $90,033 +- **Continuation thresholds**: Family of 2: $73,899; Family of 4: $108,675 + +### Historical Income Eligibility Thresholds (from Feb 2026 briefing) +| Fiscal Year | % of SMI | SMI Vintage | Family of 4 Threshold | +|---|---|---|---| +| 2016 | 50% | current | $54,631 | +| 2017 | 50% | current | $55,019 | +| 2018 | 50% | current | $55,839 | +| 2019 | 65% | 2018 SMI | $75,590 | +| 2020 | 65% | 2018 SMI | $75,590 | +| 2021 | 65% | 2018 SMI | $75,590 | +| 2022 | 65% | 2018 SMI | $75,590 | +| 2023 | 75% | 2021 SMI | $93,605 | +| 2024 | 75% | 2021 SMI | $93,605 | +| 2025 | 75% | 2025 SMI | $115,588 | +| 2026 | 75% | 2025 SMI | $115,588 | + +### State Median Income (SMI) Data +- **LIHEAP FY2026 SMI for Maryland**: $154,117 (4-person family) +- **Source**: https://acf.gov/sites/default/files/documents/ocs/COMM_LIHEAP_IM2025-02_SMIStateTable_Att4.pdf +- **60% SMI by household size (FY26)**: + - 1 person: $48,084 + - 2 persons: $62,879 + - 3 persons: $77,674 + - 4 persons: $92,470 + - 5 persons: $107,265 + - 6 persons: $122,060 +- **CCS uses ACF SMI estimates for FY2025** (per Feb 2026 briefing, slide 20): + - SMI for household of 2: $101,489 + - SMI for household of 4: $149,249 + +### CCDF Family Income Eligibility Levels by State (Jan 2025) +- **URL**: https://acf.gov/sites/default/files/documents/occ/CCDF-Family-Income-Eligibility-Levels-by-State.pdf +- **Local copy**: `/tmp/md-ccdf-income-levels.pdf` +- **Maryland entry**: 60% SMI (based on CCDF methodology), $6,302/month for family of 3, $7,503/month for family of 4 +- **Note**: CCDF and state report different % because they use different SMI bases + +## COMAR Income Eligibility Scale (Regulation .03H) - Older Values +- **Source**: COMAR 13A.14.06 PDF (Jan 2023 version) +- **Note**: These are the 2018 SMI-based values codified in regulation, superseded by Dec 2024 update +- Family of 1: $0-$37,193 (Level J max) +- Family of 2: $0-$48,637 (Level J max) +- Family of 3: $0-$60,081 (Level J max) +- Family of 4: $0-$71,525 (Level J max) +- Family of 5: $0-$82,969 +- Family of 6: $0-$94,413 +- Family of 7: $0-$96,558 +- Family of 8: $0-$98,704 +- Family of 9: $0-$100,850 +- Family of 10: $0-$102,996 + +## Copayments + +### Current Copayment Policy +- **TCA recipients**: $0 copayment (exempt) +- **SSI recipients**: $0 copayment (exempt) +- **SNAP, WIC, Section 8 recipients**: Copayments waived since May 23, 2022 (Chapters 525/526 of 2022) +- **All other families**: Maximum $3/week per 3-unit scholarship, $2/week per 2-unit, $1/week per 1-unit +- **Chapter 717 of 2024**: Prohibits MSDE from increasing copayment levels in effect as of Jan 1, 2024 +- **Federal CCDF 2024 Final Rule**: Caps copayments at 7% of family gross income + +### COMAR Copayment Tables (Regulation .12) +- **Regional copayment tables** by income level (A-J), region (U, V, W, X, Y, Z, BC), child age (<24 months vs >=24 months) +- **Copayment assessed for up to 3 children**: youngest gets highest, 2nd and 3rd get lower, 4th+ free +- **Units of service**: 1 unit (<=3 hrs), 2 units (>3 to <6 hrs), 3 units (>=6 hrs) +- **2-unit and 1-unit copayments**: multiply 3-unit figures by 2/3 and 1/3 respectively +- **Informal care copayments**: percentage of informal care weekly rate (5%-50% for first child by level A-J) +- **Note**: The COMAR regulation copayment tables appear to be from the pre-2022 era; current copayments are minimal ($1-$3/week) per legislative changes + +## Market Regions +- **Source**: RESI of Towson University, "Maryland Child Care Scholarship Program Reimbursement Rate Adjustments" (Sep 2023) +- **URL**: https://dlslibrary.state.md.us/publications/Exec/MSDE/ED9.5-111(c)_2022.pdf +- **Local copy**: `/tmp/md-ccs-reimbursement-2022.pdf` + +| Region | Counties | +|---|---| +| Region U | Cecil, Queen Anne's, St. Mary's, Talbot, Washington | +| Region V | Caroline, Dorchester, Kent, Somerset, Wicomico | +| Region W | Anne Arundel, Calvert, Carroll, Charles, Prince George's | +| Region X | Howard, Montgomery | +| Region Y | Baltimore, Frederick, Harford | +| Region Z | Allegany, Garrett, Worcester | +| Region B/BC | Baltimore City | + +## Eligibility Requirements Summary + +### Child Age +- Under 13 years (non-disabled) +- Under 19 years (disabled) +- **Source**: COMAR 13A.14.06.02 (definition of "Child") + +### Residency +- Must be a resident of the State of Maryland +- **Source**: COMAR 13A.14.06.03(A)(1) + +### Citizenship +- Children must be U.S. citizens or qualified aliens +- Parents do NOT have to be U.S. citizens +- **Source**: COMAR 13A.14.06.03(B); CCS Brochure + +### Activity Requirement (Need) +- Parent/caretaker must be working/employed, in an approved training program, or attending school +- For two-parent households, both parents must meet requirements +- **Source**: COMAR 13A.14.06.03(E); CCS Brochure + +### Categorical Eligibility +- TCA recipients: exempt from income limits and copayments +- SSI recipients: exempt from income limits and copayments +- **Source**: COMAR 13A.14.06.03(F)(1), .12(A)(1) + +### Income Calculation +- Annual gross income used +- Self-employment: flat 30% deducted for business expenses +- Military housing: paid rental/mortgage fees deducted from allowance +- Child support: averaged over 3 most recent consecutive months (excluded from income per 2022 legislation) +- **Source**: COMAR 13A.14.06.03(F)(3)-(8) + +### Immunizations +- Required for children before receiving services +- Exemptions for medical contraindications or religious objections +- **Source**: COMAR 13A.14.06.03(D) + +### Child Support Cooperation +- Must pursue child support obligations unless good cause exists +- **Source**: COMAR 13A.14.06.04 + +### Eligibility Period +- 12-month minimum (per federal mandate); Maryland uses 24-month eligibility periods +- **Source**: Jan 2025 briefing slide 7 + +## Legislative History + +| Year | Legislation | Key Changes | +|---|---|---| +| 2017 | Ch 209/210 | Required periodic reimbursement rate analysis | +| 2018 | Ch 555/556 | Supplemental Head Start funding | +| 2018 | (MSDE action) | Reimbursement 9th -> 20th percentile; eligibility 32% -> 50% SMI | +| 2019 | Ch 595/596 | Required 60th percentile market rate adjustment; eligibility -> 65% SMI | +| 2020 | (COVID) | All copays waived Mar-Sep 2020; reimbursement -> 60th percentile | +| 2021 | Ch 36/55 | Annual funding for Judy Centers, EXCELS, Blueprint capacity | +| 2022 | Ch 525/526 | Copay waivers for SNAP/WIC/TCA/Section 8/SSI; removed child support from income; created presumptive eligibility; eligibility -> 75% SMI; reimbursement -> 70th percentile | +| 2022 | Ch 498/499 | Therapeutic Child Care Grant Program | +| 2023 | Ch 731/732 | Restrict MSDE from changing key CCS policies as of Jan 1, 2023 | +| 2024 | Ch 717 | Prohibit MSDE from increasing copayment levels as of Jan 1, 2024 | +| 2025 | Ch 369 | Expanded CCS to parenting foster youth | + +## Briefings and Presentations + +### Feb 2026 Ways and Means Committee Briefing +- **URL**: https://mgaleg.maryland.gov/meeting_material/2026/w&m%20-%20134146885147130127%20-%20Briefing%20materials.pdf +- **Local copy**: `/tmp/md-ccs-briefing-2026.pdf` +- **Key data**: 41,148 children / 27,235 families (Jan 2026); waitlist ~4,929 children; current SMI threshold table; demographic breakdowns + +### Jan 2025 Early Childhood Subcommittee Briefing +- **URL**: https://mgaleg.maryland.gov/meeting_material/2025/app%20-%20133815104940229083%20-%20MSDE-Child%20Care%20Scholarship%20Program%20Update%20to%20Subcommittee%20(1).pdf +- **Local copy**: `/tmp/md-ccs-briefing-2025.pdf` +- **Key data**: $568M proposed investment; enrollment freeze May 2025; copayment policy details + +### Jan 2025 CCS Info Session +- **URL**: https://earlychildhood.marylandpublicschools.org/system/files/filedepot/3/january_2025_occ_info_session.pdf +- **Local copy**: `/tmp/md-ccs-info-session-jan2025.pdf` +- **Key data**: Income eligibility increased effective Dec 15, 2024 (family of 2: $76,117; family of 4: $111,936) + +### Jan 2024 Early Childhood Subcommittee Briefing +- **URL**: https://mgaleg.maryland.gov/cmte_testimony/2024/ecm/1qQzLR-gr9jXICeb4E76YUf3vjAwJekVU.pdf +- **Local copy**: `/tmp/md-ccs-briefing-2024.pdf` +- **Key data**: Historical timeline of policy changes; copayment sliding scale proposal (3% for ~$43K-$65K, 7% for >$66K) + +### Oct 2025 Child Care in Maryland (DLS) +- **URL**: https://mgaleg.maryland.gov/meeting_material/2025/app%20-%20134063072915355066%20-%20ChildCarePresentation.pdf +- **Local copy**: `/tmp/md-ccs-childcare-in-md-2025.pdf` +- **Key data**: Comprehensive program overview; freeze status; market rate timeline; federal rule changes + +## Market Rate Survey +- **2024 Market Rate Survey**: https://earlychildhood.marylandpublicschools.org/system/files/filedepot/3/md-market-rate-survey-2024-2.pdf +- **Reimbursement Rate Analysis (2022 data, Sep 2023 report)**: https://dlslibrary.state.md.us/publications/Exec/MSDE/ED9.5-111(c)_2022.pdf +- **Local copy**: `/tmp/md-ccs-reimbursement-2022.pdf` + +## Program Websites +- **Official CCS Program**: https://earlychildhood.marylandpublicschools.org/child-care-providers/child-care-scholarship-program +- **Family Portal**: https://family.childcareportals.org/s/?language=en_US +- **money4childcare.com**: www.money4childcare.com (main family-facing site) +- **CCS Rates**: https://earlychildhood.marylandpublicschools.org/families/child-care-scholarship-program/child-care-scholarship-rates +- **CCDF State Plan**: https://earlychildhood.marylandpublicschools.org/about/ccdf-state-plan +- **Enrollment Data**: https://earlychildhood.marylandpublicschools.org/data + +## Failed Fetches +| URL | Status | Likely Content | +|---|---|---| +| https://earlychildhood.marylandpublicschools.org/child-care-providers/child-care-scholarship-program | 403 | Main program page with eligibility details and links | +| https://earlychildhood.marylandpublicschools.org/changes-subsidy-eligibility | 403 | Details of eligibility changes over time | +| https://earlychildhood.marylandpublicschools.org/families/child-care-scholarship-program/child-care-scholarship-rates | Not fetched | Current provider reimbursement rate tables by region/age/quality | +| https://earlychildhood.marylandpublicschools.org/about/ccdf-state-plan | 403 | CCDF state plan documents with full eligibility and copayment details | +| https://earlychildhood.marylandpublicschools.org/system/files/filedepot/2/income_eligibility_scale.pdf | 403 | Older income eligibility scale PDF (data obtained from text version) | +| https://acf.gov/sites/default/files/documents/ocs/COMM_LIHEAP_IM202502_SMIStateTable_Att4.pdf | 404 | FY26 SMI table (obtained via alternate URL) | +| https://regulations.justia.com/states/maryland/title-13a/subtitle-14/chapter-13a-14-06/section-13a-14-06-02/ | 403 | COMAR definitions (obtained from mdrules.elaws.us) | From 2363974809e1ab3960c289cfd87bf606e7f6b9ed Mon Sep 17 00:00:00 2001 From: Ziming Date: Thu, 26 Mar 2026 12:50:57 -0400 Subject: [PATCH 03/13] Update changelog fragment with correct program name Co-Authored-By: Claude Opus 4.6 (1M context) --- changelog.d/md-ccap.added.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.d/md-ccap.added.md b/changelog.d/md-ccap.added.md index e58dd10c19d..379dc3540da 100644 --- a/changelog.d/md-ccap.added.md +++ b/changelog.d/md-ccap.added.md @@ -1 +1 @@ -Implement Maryland CCAP (Child Care Assistance Program). +Implement Maryland Child Care Scholarship (CCS) program. From 4fd8acb8445ea364c4abe46f0371b2449b360181 Mon Sep 17 00:00:00 2001 From: Ziming Date: Thu, 26 Mar 2026 13:18:32 -0400 Subject: [PATCH 04/13] Review-fix round 1: address critical issues from /review-program - Add region_w_counties.yaml and update md_ccs_region.py - Add MD CCS to programs.yaml registry - Add #page=XX to 5 session law PDF references - Fix continuation.yaml to cite state source as primary - Document frozen SMI limitation with TODO Co-Authored-By: Claude Opus 4.6 (1M context) --- .../states/md/msde/ccs/copay/weekly_amount.yaml | 2 +- .../ccs/income/countable_income/sources.yaml | 2 +- .../msde/ccs/income/smi_rate/continuation.yaml | 8 +++++--- .../md/msde/ccs/income/smi_rate/initial.yaml | 4 ++-- .../md/msde/ccs/payment/region_w_counties.yaml | 16 ++++++++++++++++ policyengine_us/programs.yaml | 7 ++++++- .../states/md/msde/ccs/md_ccs_income_eligible.py | 5 +++++ .../states/md/msde/ccs/payment/md_ccs_region.py | 3 +++ 8 files changed, 39 insertions(+), 8 deletions(-) create mode 100644 policyengine_us/parameters/gov/states/md/msde/ccs/payment/region_w_counties.yaml diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/copay/weekly_amount.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/copay/weekly_amount.yaml index a9e17012e35..f4a060e7cd0 100644 --- a/policyengine_us/parameters/gov/states/md/msde/ccs/copay/weekly_amount.yaml +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/copay/weekly_amount.yaml @@ -8,7 +8,7 @@ metadata: - md_ccs_service_unit reference: - title: Chapter 717 of 2024 - href: https://mgaleg.maryland.gov/2024RS/Chapters_noln/CH_717_sb0482e.pdf + href: https://mgaleg.maryland.gov/2024RS/Chapters_noln/CH_717_sb0482e.pdf#page=1 - title: COMAR 13A.14.06.12 href: https://dsd.maryland.gov/regulations/Pages/13A.14.06.12.aspx diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/income/countable_income/sources.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/income/countable_income/sources.yaml index df29e6820ff..5ca5e4e5549 100644 --- a/policyengine_us/parameters/gov/states/md/msde/ccs/income/countable_income/sources.yaml +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/income/countable_income/sources.yaml @@ -28,4 +28,4 @@ metadata: - title: COMAR 13A.14.06.03(F)(3)-(8) href: https://dsd.maryland.gov/regulations/Pages/13A.14.06.03.aspx - title: Chapters 525/526 of 2022 - href: https://mgaleg.maryland.gov/2022RS/Chapters_noln/CH_525_hb0275e.pdf + href: https://mgaleg.maryland.gov/2022RS/Chapters_noln/CH_525_hb0275e.pdf#page=1 diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_rate/continuation.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_rate/continuation.yaml index 1f1bd6a90a3..e2417c31d6f 100644 --- a/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_rate/continuation.yaml +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_rate/continuation.yaml @@ -7,7 +7,9 @@ metadata: period: year label: Maryland CCS continuation eligibility SMI rate reference: - - title: 45 CFR 98.21(b) - Eligibility requirements - href: https://www.ecfr.gov/current/title-45/section-98.21#p-98.21(b) + - title: COMAR 13A.14.06.03(B) + href: https://dsd.maryland.gov/regulations/Pages/13A.14.06.03.aspx - title: Chapters 525/526 of 2022 - href: https://mgaleg.maryland.gov/2022RS/Chapters_noln/CH_525_hb0275e.pdf + href: https://mgaleg.maryland.gov/2022RS/Chapters_noln/CH_525_hb0275e.pdf#page=1 + - title: 45 CFR 98.21(b) - Federal ceiling + href: https://www.ecfr.gov/current/title-45/section-98.21#p-98.21(b) diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_rate/initial.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_rate/initial.yaml index a66bbc91975..6f36e46c586 100644 --- a/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_rate/initial.yaml +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_rate/initial.yaml @@ -10,6 +10,6 @@ metadata: label: Maryland CCS initial eligibility SMI rate reference: - title: Chapters 595/596 of 2018 - href: https://mgaleg.maryland.gov/2018RS/Chapters_noln/CH_595_hb0377e.pdf + href: https://mgaleg.maryland.gov/2018RS/Chapters_noln/CH_595_hb0377e.pdf#page=1 - title: Chapters 525/526 of 2022 - href: https://mgaleg.maryland.gov/2022RS/Chapters_noln/CH_525_hb0275e.pdf + href: https://mgaleg.maryland.gov/2022RS/Chapters_noln/CH_525_hb0275e.pdf#page=1 diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/payment/region_w_counties.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/region_w_counties.yaml new file mode 100644 index 00000000000..4d1b9a0d9c7 --- /dev/null +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/region_w_counties.yaml @@ -0,0 +1,16 @@ +description: Maryland sets these counties as Region W for Child Care Scholarship rate purposes. +values: + 2020-11-23: + - ANNE_ARUNDEL_COUNTY_MD + - CALVERT_COUNTY_MD + - CARROLL_COUNTY_MD + - CHARLES_COUNTY_MD + - PRINCE_GEORGE_S_COUNTY_MD + +metadata: + unit: list + period: year + label: Maryland CCS Region W counties + reference: + - title: Maryland CCS Scholarship Rates + href: https://earlychildhood.marylandpublicschools.org/families/child-care-scholarship-program/child-care-scholarship-rates diff --git a/policyengine_us/programs.yaml b/policyengine_us/programs.yaml index 32409746ae5..1e4f6a435dd 100644 --- a/policyengine_us/programs.yaml +++ b/policyengine_us/programs.yaml @@ -421,7 +421,7 @@ programs: category: Benefits agency: HHS status: partial - coverage: CA, CO, IL, MA, DC, NC, TX + coverage: CA, CO, DC, IL, MA, MD, NC, TX state_implementations: - state: CA status: complete @@ -444,6 +444,11 @@ programs: status: complete name: Massachusetts CCFA full_name: Massachusetts Child Care Financial Assistance + - state: MD + status: complete + name: Maryland CCS + full_name: Maryland Child Care Scholarship + variable: md_child_care_subsidies - state: DC status: complete name: DC CCSP diff --git a/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_income_eligible.py b/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_income_eligible.py index f37a0b63bee..0cded2ffe0b 100644 --- a/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_income_eligible.py +++ b/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_income_eligible.py @@ -15,6 +15,11 @@ class md_ccs_income_eligible(Variable): def formula(spm_unit, period, parameters): p = parameters(period).gov.states.md.msde.ccs.income.smi_rate countable_income = spm_unit("md_ccs_countable_income", period) + # TODO: Maryland froze SMI base years for historical periods + # (FY2019-2022 used 2018 SMI, FY2023-2024 used 2021 SMI). + # This formula uses the current-year SMI, which is correct for + # 2025+ but overstates historical thresholds. Follow-up PR + # should parameterize the SMI base year. smi = spm_unit("hhs_smi", period) enrolled = spm_unit("md_ccs_enrolled", period) income_limit = where( diff --git a/policyengine_us/variables/gov/states/md/msde/ccs/payment/md_ccs_region.py b/policyengine_us/variables/gov/states/md/msde/ccs/payment/md_ccs_region.py index 0b144b1ee94..3d066d60349 100644 --- a/policyengine_us/variables/gov/states/md/msde/ccs/payment/md_ccs_region.py +++ b/policyengine_us/variables/gov/states/md/msde/ccs/payment/md_ccs_region.py @@ -26,6 +26,7 @@ def formula(household, period, parameters): p = parameters(period).gov.states.md.msde.ccs.payment is_region_u = np.isin(county, p.region_u_counties) is_region_v = np.isin(county, p.region_v_counties) + is_region_w = np.isin(county, p.region_w_counties) is_region_x = np.isin(county, p.region_x_counties) is_region_y = np.isin(county, p.region_y_counties) is_region_z = np.isin(county, p.region_z_counties) @@ -34,6 +35,7 @@ def formula(household, period, parameters): [ is_region_u, is_region_v, + is_region_w, is_region_x, is_region_y, is_region_z, @@ -42,6 +44,7 @@ def formula(household, period, parameters): [ MDCCSRegion.REGION_U, MDCCSRegion.REGION_V, + MDCCSRegion.REGION_W, MDCCSRegion.REGION_X, MDCCSRegion.REGION_Y, MDCCSRegion.REGION_Z, From 5b5479854f670c53da3dad8b044467f69bd171e6 Mon Sep 17 00:00:00 2001 From: Ziming Date: Thu, 26 Mar 2026 13:53:25 -0400 Subject: [PATCH 05/13] Review-fix round 2: fix COMAR URLs and subsection citations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Replace all broken dsd.maryland.gov URLs with regs.maryland.gov - Fix continuation.yaml: .03(B) → .03(H) (Income Eligibility Scale) - Fix self_employment_deduction_rate.yaml: (F)(6) → (F)(8)(a)(i) - Fix sources.yaml: (F)(3)-(8) → .02 (Gross income definition) Co-Authored-By: Claude Opus 4.6 (1M context) --- .../gov/states/md/msde/ccs/age_threshold/child.yaml | 2 +- .../states/md/msde/ccs/age_threshold/disabled_child.yaml | 2 +- .../states/md/msde/ccs/copay/max_children_with_copay.yaml | 2 +- .../parameters/gov/states/md/msde/ccs/copay/unit_hours.yaml | 2 +- .../gov/states/md/msde/ccs/copay/weekly_amount.yaml | 2 +- .../states/md/msde/ccs/income/countable_income/sources.yaml | 6 +++--- .../md/msde/ccs/income/self_employment_deduction_rate.yaml | 4 ++-- .../states/md/msde/ccs/income/smi_rate/continuation.yaml | 4 ++-- .../states/md/msde/ccs/payment/infant_age_threshold.yaml | 2 +- 9 files changed, 13 insertions(+), 13 deletions(-) diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/age_threshold/child.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/age_threshold/child.yaml index 3d81b4a1ef6..f69a9aff0c5 100644 --- a/policyengine_us/parameters/gov/states/md/msde/ccs/age_threshold/child.yaml +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/age_threshold/child.yaml @@ -8,4 +8,4 @@ metadata: label: Maryland CCS child age threshold reference: - title: COMAR 13A.14.06.02 - Definitions, "Child" - href: https://dsd.maryland.gov/regulations/Pages/13A.14.06.02.aspx + href: https://regs.maryland.gov/us/md/exec/comar/13A.14.06.02 diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/age_threshold/disabled_child.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/age_threshold/disabled_child.yaml index 55a67bc8011..a7337cb6fdd 100644 --- a/policyengine_us/parameters/gov/states/md/msde/ccs/age_threshold/disabled_child.yaml +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/age_threshold/disabled_child.yaml @@ -8,4 +8,4 @@ metadata: label: Maryland CCS disabled child age threshold reference: - title: COMAR 13A.14.06.02 - Definitions, "Child" - href: https://dsd.maryland.gov/regulations/Pages/13A.14.06.02.aspx + href: https://regs.maryland.gov/us/md/exec/comar/13A.14.06.02 diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/copay/max_children_with_copay.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/copay/max_children_with_copay.yaml index 6dc26b33386..6c8e59955c2 100644 --- a/policyengine_us/parameters/gov/states/md/msde/ccs/copay/max_children_with_copay.yaml +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/copay/max_children_with_copay.yaml @@ -8,4 +8,4 @@ metadata: label: Maryland CCS maximum children with copayment reference: - title: COMAR 13A.14.06.12 - href: https://dsd.maryland.gov/regulations/Pages/13A.14.06.12.aspx + href: https://regs.maryland.gov/us/md/exec/comar/13A.14.06.12 diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/copay/unit_hours.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/copay/unit_hours.yaml index c4c292d7ec6..d445e101fc4 100644 --- a/policyengine_us/parameters/gov/states/md/msde/ccs/copay/unit_hours.yaml +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/copay/unit_hours.yaml @@ -8,7 +8,7 @@ metadata: label: Maryland CCS service units by daily hours reference: - title: COMAR 13A.14.06.11 - href: https://dsd.maryland.gov/regulations/Pages/13A.14.06.11.aspx + href: https://regs.maryland.gov/us/md/exec/comar/13A.14.06.11 brackets: - threshold: diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/copay/weekly_amount.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/copay/weekly_amount.yaml index f4a060e7cd0..b351e54da59 100644 --- a/policyengine_us/parameters/gov/states/md/msde/ccs/copay/weekly_amount.yaml +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/copay/weekly_amount.yaml @@ -10,7 +10,7 @@ metadata: - title: Chapter 717 of 2024 href: https://mgaleg.maryland.gov/2024RS/Chapters_noln/CH_717_sb0482e.pdf#page=1 - title: COMAR 13A.14.06.12 - href: https://dsd.maryland.gov/regulations/Pages/13A.14.06.12.aspx + href: https://regs.maryland.gov/us/md/exec/comar/13A.14.06.12 UNIT_3: 2022-05-01: 3 diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/income/countable_income/sources.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/income/countable_income/sources.yaml index 5ca5e4e5549..587f31f087d 100644 --- a/policyengine_us/parameters/gov/states/md/msde/ccs/income/countable_income/sources.yaml +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/income/countable_income/sources.yaml @@ -3,7 +3,7 @@ values: 2022-05-01: - employment_income # Note: self_employment_income is handled separately in the formula - # with a 30% deduction per COMAR 13A.14.06.03(F)(6) + # with a 30% deduction per COMAR 13A.14.06.03(F)(8)(a)(i) - social_security - pension_income - interest_income @@ -25,7 +25,7 @@ metadata: period: year label: Maryland CCS countable income sources reference: - - title: COMAR 13A.14.06.03(F)(3)-(8) - href: https://dsd.maryland.gov/regulations/Pages/13A.14.06.03.aspx + - title: COMAR 13A.14.06.02 - Definition of "Gross income" + href: https://regs.maryland.gov/us/md/exec/comar/13A.14.06.02 - title: Chapters 525/526 of 2022 href: https://mgaleg.maryland.gov/2022RS/Chapters_noln/CH_525_hb0275e.pdf#page=1 diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/income/self_employment_deduction_rate.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/income/self_employment_deduction_rate.yaml index 54034c673ee..1204f6afe01 100644 --- a/policyengine_us/parameters/gov/states/md/msde/ccs/income/self_employment_deduction_rate.yaml +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/income/self_employment_deduction_rate.yaml @@ -7,5 +7,5 @@ metadata: period: year label: Maryland CCS self-employment deduction rate reference: - - title: COMAR 13A.14.06.03(F)(6) - href: https://dsd.maryland.gov/regulations/Pages/13A.14.06.03.aspx + - title: COMAR 13A.14.06.03(F)(8)(a)(i) - Self-Employment Deduction + href: https://regs.maryland.gov/us/md/exec/comar/13A.14.06.03 diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_rate/continuation.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_rate/continuation.yaml index e2417c31d6f..97ceccfd3e8 100644 --- a/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_rate/continuation.yaml +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_rate/continuation.yaml @@ -7,8 +7,8 @@ metadata: period: year label: Maryland CCS continuation eligibility SMI rate reference: - - title: COMAR 13A.14.06.03(B) - href: https://dsd.maryland.gov/regulations/Pages/13A.14.06.03.aspx + - title: COMAR 13A.14.06.03(H) - Income Eligibility Scale + href: https://regs.maryland.gov/us/md/exec/comar/13A.14.06.03 - title: Chapters 525/526 of 2022 href: https://mgaleg.maryland.gov/2022RS/Chapters_noln/CH_525_hb0275e.pdf#page=1 - title: 45 CFR 98.21(b) - Federal ceiling diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/payment/infant_age_threshold.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/infant_age_threshold.yaml index 4810dd8cdcc..cd45ea9efe8 100644 --- a/policyengine_us/parameters/gov/states/md/msde/ccs/payment/infant_age_threshold.yaml +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/infant_age_threshold.yaml @@ -10,4 +10,4 @@ metadata: - title: Maryland CCS Scholarship Rates href: https://earlychildhood.marylandpublicschools.org/families/child-care-scholarship-program/child-care-scholarship-rates - title: COMAR 13A.14.06.02 - Definitions - href: https://dsd.maryland.gov/regulations/Pages/13A.14.06.02.aspx + href: https://regs.maryland.gov/us/md/exec/comar/13A.14.06.02 From 66641c5e59f6cbd2de8e66f8b294b5218cca8dd9 Mon Sep 17 00:00:00 2001 From: Ziming Date: Thu, 26 Mar 2026 13:54:59 -0400 Subject: [PATCH 06/13] Add lessons from Maryland CCS implementation Co-Authored-By: Claude Opus 4.6 (1M context) --- lessons/agent-lessons.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 lessons/agent-lessons.md diff --git a/lessons/agent-lessons.md b/lessons/agent-lessons.md new file mode 100644 index 00000000000..b2bcee7c7df --- /dev/null +++ b/lessons/agent-lessons.md @@ -0,0 +1,18 @@ +# Agent Lessons Learned + +Accumulated from /encode-policy-v2 and /backdate-program runs across all contributors. +Loaded by implementation agents on future runs. + +## New Lessons from Maryland CCS (2026-03-26) + +### VARIABLE +- When a formula uses `select()` with a default/fallback for one category, replace it with explicit matching for ALL categories including the default; implicit defaults silently swallow new or misspelled values and make the "default" category untestable in isolation. + +### REFERENCE +- When a state regulation portal migrates domains (e.g., `dsd.maryland.gov` to `regs.maryland.gov`), ALL parameter files referencing the old domain must be updated in one pass; broken redirects (301 to 404) are systematic, not isolated, so always search-and-replace across the entire state directory rather than fixing one file at a time. +- When a parameter encodes a state policy choice (e.g., state sets 85% SMI threshold), cite the state regulation as the primary reference, not the federal CFR that merely sets the ceiling; federal authority is context, not the source of the state's specific value. +- When correcting a wrong COMAR/regulation subsection citation, verify the replacement subsection's content in the same review round; three of four citation corrections in this session initially pointed to the wrong subsection because adjacent subsections cover different provisions with similar-sounding names (e.g., .03(B) = citizenship vs .03(H) = income eligibility). + +### WORKFLOW +- When implementing a new state program, add it to `programs.yaml` as part of the initial implementation, not as an afterthought; missing registry entries block the program from appearing in the metadata API and coverage page. +- When a `select()` or similar lookup relies on a parameter file for each category, verify that ALL categories have corresponding parameter files before the first review round; a missing file for one category (e.g., Region W counties) forces the formula to use an implicit default, hiding a data gap. From 42fa6daea9b2470bf6f3e0e7c3db1c7f0dd20263 Mon Sep 17 00:00:00 2001 From: Ziming Date: Wed, 20 May 2026 13:53:42 -0400 Subject: [PATCH 07/13] fix --- .../states/md/msde/ccs/copay/unit_hours.yaml | 4 +- .../md/msde/ccs/copay/weekly_amount.yaml | 10 +- .../ccs/income/countable_income/sources.yaml | 14 +- .../md/msde/ccs/income/smi_base_year.yaml | 16 ++ .../ccs/income/smi_rate/continuation.yaml | 8 +- .../md/msde/ccs/income/smi_rate/initial.yaml | 10 +- .../ccs/payment/formal/licensed_center.yaml | 4 + .../ccs/payment/formal/licensed_family.yaml | 4 + .../ccs/payment/infant_age_threshold.yaml | 2 - .../md/msde/ccs/payment/informal/rates.yaml | 4 +- .../gov/states/md/msde/ccs/edge_cases.yaml | 41 +++ .../gov/states/md/msde/ccs/integration.yaml | 11 + .../gov/states/md/msde/ccs/md_ccs.yaml | 4 +- .../md/msde/ccs/md_ccs_weekly_copay.yaml | 6 +- .../msde/ccs/eligibility/md_ccs_eligible.py | 7 +- .../ccs/eligibility/md_ccs_eligible_child.py | 5 +- .../gov/states/md/msde/ccs/md_ccs.py | 2 +- .../md/msde/ccs/md_ccs_countable_income.py | 4 +- .../md/msde/ccs/md_ccs_income_eligible.py | 30 +- .../md/msde/ccs/md_ccs_provider_type.py | 5 +- .../md/msde/ccs/md_ccs_receives_snap.py | 9 - .../states/md/msde/ccs/md_ccs_receives_wic.py | 9 - .../states/md/msde/ccs/md_ccs_weekly_copay.py | 20 +- .../msde/ccs/payment/md_ccs_payment_rate.py | 4 +- .../md/msde/ccs/payment/md_ccs_region.py | 3 + .../msde/ccs/payment/md_ccs_service_unit.py | 2 +- sources/working_references.md | 271 ------------------ 27 files changed, 160 insertions(+), 349 deletions(-) create mode 100644 policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_base_year.yaml delete mode 100644 policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_receives_snap.py delete mode 100644 policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_receives_wic.py delete mode 100644 sources/working_references.md diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/copay/unit_hours.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/copay/unit_hours.yaml index d445e101fc4..0a9cc708554 100644 --- a/policyengine_us/parameters/gov/states/md/msde/ccs/copay/unit_hours.yaml +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/copay/unit_hours.yaml @@ -7,7 +7,9 @@ metadata: period: year label: Maryland CCS service units by daily hours reference: - - title: COMAR 13A.14.06.11 + - title: Maryland CCS Provider Resources - Units of Service + href: https://earlychildhood.marylandpublicschools.org/families/child-care-scholarship-program/child-care-scholarship-rates + - title: COMAR 13A.14.06.11 - Units of Service (general framework) href: https://regs.maryland.gov/us/md/exec/comar/13A.14.06.11 brackets: diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/copay/weekly_amount.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/copay/weekly_amount.yaml index b351e54da59..f77a9994d2d 100644 --- a/policyengine_us/parameters/gov/states/md/msde/ccs/copay/weekly_amount.yaml +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/copay/weekly_amount.yaml @@ -1,4 +1,4 @@ -description: Maryland sets this amount as the weekly copayment by service unit under the Child Care Scholarship program. +description: Maryland sets this amount as the weekly copayment by service unit under the Child Care Scholarship program. The flat $1/$2/$3 schedule replaced the historical COMAR 13A.14.06.12 regional matrix via MSDE policy in May 2022 and was frozen at January 1, 2024 levels by Chapter 717 of 2024 (SB 362). metadata: unit: currency-USD @@ -7,9 +7,11 @@ metadata: breakdown: - md_ccs_service_unit reference: - - title: Chapter 717 of 2024 - href: https://mgaleg.maryland.gov/2024RS/Chapters_noln/CH_717_sb0482e.pdf#page=1 - - title: COMAR 13A.14.06.12 + - title: Chapter 717 of 2024 (SB 362) - Budget Reconciliation and Financing Act - freeze at January 1, 2024 levels + href: https://mgaleg.maryland.gov/2024RS/Chapters_noln/CH_717_sb0362E.pdf#page=1 + - title: MSDE Tuesday Tidbits bulletin (May 23, 2022) - introduction of $1/$2/$3 flat schedule + href: https://content.govdelivery.com/accounts/MDMSDE/bulletins/31a37f2 + - title: COMAR 13A.14.06.12 - codifies the historical regional matrix (superseded operationally) href: https://regs.maryland.gov/us/md/exec/comar/13A.14.06.12 UNIT_3: diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/income/countable_income/sources.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/income/countable_income/sources.yaml index 587f31f087d..3c7f45b6e50 100644 --- a/policyengine_us/parameters/gov/states/md/msde/ccs/income/countable_income/sources.yaml +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/income/countable_income/sources.yaml @@ -3,7 +3,7 @@ values: 2022-05-01: - employment_income # Note: self_employment_income is handled separately in the formula - # with a 30% deduction per COMAR 13A.14.06.03(F)(8)(a)(i) + # with a 30% deduction per COMAR 13A.14.06.03F(8)(a)(i) - social_security - pension_income - interest_income @@ -18,14 +18,18 @@ values: - farm_income - military_retirement_pay # NOT included: - # - child_support_received (excluded per Chapters 525/526 of 2022) + # - child_support_received (excluded per Chapter 525 of 2022 / HB 995) + # COMAR-listed sources we don't model at the moment: commissions, tips, + # bonuses, annuities, estate income, military entitlements. metadata: unit: list period: year label: Maryland CCS countable income sources reference: - - title: COMAR 13A.14.06.02 - Definition of "Gross income" + - title: COMAR 13A.14.06.02B(28) - Definition of "Gross income" href: https://regs.maryland.gov/us/md/exec/comar/13A.14.06.02 - - title: Chapters 525/526 of 2022 - href: https://mgaleg.maryland.gov/2022RS/Chapters_noln/CH_525_hb0275e.pdf#page=1 + - title: Chapter 525 of 2022 (HB 995) - child support excluded + href: https://mgaleg.maryland.gov/2022RS/Chapters_noln/CH_525_hb0995E.pdf#page=1 + - title: Chapter 526 of 2022 (SB 920) + href: https://mgaleg.maryland.gov/2022RS/Chapters_noln/CH_526_sb0920E.pdf#page=1 diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_base_year.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_base_year.yaml new file mode 100644 index 00000000000..828b8aeff06 --- /dev/null +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_base_year.yaml @@ -0,0 +1,16 @@ +description: Maryland freezes the State Median Income (SMI) base year for Child Care Scholarship income eligibility on a fiscal-year schedule. A value of 0 means use the current-year SMI; otherwise use the SMI parameterized for that calendar year. Maryland's fiscal year starts July 1. +values: + 2016-01-01: 0 + 2019-01-01: 2018 + 2022-07-01: 2021 + 2024-07-01: 0 + +metadata: + unit: year + period: year + label: Maryland CCS SMI base year (0 = current) + reference: + - title: MSDE Child Care Scholarship Program Briefing (Feb 4, 2026), slide 21 - fiscal-year base years + href: https://mgaleg.maryland.gov/meeting_material/2026/w&m%20-%20134146885147130127%20-%20Briefing%20materials.pdf#page=21 + - title: MSDE Jan 23, 2025 OCC Info Session - Dec 2024 SMI unfreeze + href: https://earlychildhood.marylandpublicschools.org/system/files/filedepot/3/january_2025_occ_info_session.pdf diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_rate/continuation.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_rate/continuation.yaml index 97ceccfd3e8..103a08c30eb 100644 --- a/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_rate/continuation.yaml +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_rate/continuation.yaml @@ -7,9 +7,7 @@ metadata: period: year label: Maryland CCS continuation eligibility SMI rate reference: - - title: COMAR 13A.14.06.03(H) - Income Eligibility Scale - href: https://regs.maryland.gov/us/md/exec/comar/13A.14.06.03 - - title: Chapters 525/526 of 2022 - href: https://mgaleg.maryland.gov/2022RS/Chapters_noln/CH_525_hb0275e.pdf#page=1 - - title: 45 CFR 98.21(b) - Federal ceiling + - title: 45 CFR 98.21(b) - Federal CCDF continuation eligibility floor (85% SMI) href: https://www.ecfr.gov/current/title-45/section-98.21#p-98.21(b) + - title: COMAR 13A.14.06.03H - Income Eligibility Scale + href: https://regs.maryland.gov/us/md/exec/comar/13A.14.06.03 diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_rate/initial.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_rate/initial.yaml index 6f36e46c586..e6a418e7cec 100644 --- a/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_rate/initial.yaml +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_rate/initial.yaml @@ -2,14 +2,14 @@ description: Maryland limits initial eligibility for the Child Care Scholarship values: 2018-01-01: 0.5 2019-01-01: 0.65 - 2022-05-01: 0.75 + 2022-07-01: 0.75 metadata: unit: /1 period: year label: Maryland CCS initial eligibility SMI rate reference: - - title: Chapters 595/596 of 2018 - href: https://mgaleg.maryland.gov/2018RS/Chapters_noln/CH_595_hb0377e.pdf#page=1 - - title: Chapters 525/526 of 2022 - href: https://mgaleg.maryland.gov/2022RS/Chapters_noln/CH_525_hb0275e.pdf#page=1 + - title: COMAR 13A.14.06.03H - Income Eligibility Scale + href: https://regs.maryland.gov/us/md/exec/comar/13A.14.06.03 + - title: MSDE Child Care Scholarship Program Briefing (Feb 4, 2026), slide 21 - historical thresholds + href: https://mgaleg.maryland.gov/meeting_material/2026/w&m%20-%20134146885147130127%20-%20Briefing%20materials.pdf#page=21 diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/payment/formal/licensed_center.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/formal/licensed_center.yaml index aa6b3aeadbd..b2fc278d07e 100644 --- a/policyengine_us/parameters/gov/states/md/msde/ccs/payment/formal/licensed_center.yaml +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/formal/licensed_center.yaml @@ -11,6 +11,10 @@ metadata: reference: - title: Maryland CCS Scholarship Rates (Formal Rates, 60th Percentile, 2024 Market Rate Survey) href: https://earlychildhood.marylandpublicschools.org/families/child-care-scholarship-program/child-care-scholarship-rates + - title: 2024 Maryland Market Rate Survey & Narrow Cost Analysis (Nov 2024) + href: https://earlychildhood.marylandpublicschools.org/system/files/filedepot/3/md-market-rate-survey-2024-2.pdf + - title: MSDE FY27 Operating Budget Analysis (DLS) - 2026-03-01 rate implementation + href: https://mgaleg.maryland.gov/pubs/budgetfiscal/2027fy-budget-docs-operating-R00A99-MSDE-Early-Childhood-Development.pdf REGION_U: REGULAR: diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/payment/formal/licensed_family.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/formal/licensed_family.yaml index e0ea886e198..e3331fdb03a 100644 --- a/policyengine_us/parameters/gov/states/md/msde/ccs/payment/formal/licensed_family.yaml +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/formal/licensed_family.yaml @@ -11,6 +11,10 @@ metadata: reference: - title: Maryland CCS Scholarship Rates (Formal Rates, 60th Percentile, 2024 Market Rate Survey) href: https://earlychildhood.marylandpublicschools.org/families/child-care-scholarship-program/child-care-scholarship-rates + - title: 2024 Maryland Market Rate Survey & Narrow Cost Analysis (Nov 2024) + href: https://earlychildhood.marylandpublicschools.org/system/files/filedepot/3/md-market-rate-survey-2024-2.pdf + - title: MSDE FY27 Operating Budget Analysis (DLS) - 2026-03-01 rate implementation + href: https://mgaleg.maryland.gov/pubs/budgetfiscal/2027fy-budget-docs-operating-R00A99-MSDE-Early-Childhood-Development.pdf REGION_U: REGULAR: diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/payment/infant_age_threshold.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/infant_age_threshold.yaml index cd45ea9efe8..b9e6d902567 100644 --- a/policyengine_us/parameters/gov/states/md/msde/ccs/payment/infant_age_threshold.yaml +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/infant_age_threshold.yaml @@ -9,5 +9,3 @@ metadata: reference: - title: Maryland CCS Scholarship Rates href: https://earlychildhood.marylandpublicschools.org/families/child-care-scholarship-program/child-care-scholarship-rates - - title: COMAR 13A.14.06.02 - Definitions - href: https://regs.maryland.gov/us/md/exec/comar/13A.14.06.02 diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/payment/informal/rates.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/informal/rates.yaml index e0bc3b53a0d..641d96c8c19 100644 --- a/policyengine_us/parameters/gov/states/md/msde/ccs/payment/informal/rates.yaml +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/informal/rates.yaml @@ -1,11 +1,11 @@ -description: Maryland provides these weekly reimbursement rates for informal child care providers under the Child Care Scholarship program. +description: Maryland provides these weekly reimbursement rates for informal child care providers under the Child Care Scholarship program. Rates originate from the 70th percentile of the March 2021 Market Rate Survey and have remained operational at MSDE since November 2020. metadata: period: week unit: currency-USD label: Maryland CCS informal provider weekly rates reference: - - title: Maryland CCS Scholarship Rates (Informal Rates, 70th Percentile, March 2021 Market Rate Survey) + - title: Maryland CCS Scholarship Rates (Informal Rates) href: https://earlychildhood.marylandpublicschools.org/families/child-care-scholarship-program/child-care-scholarship-rates ALLEGANY_COUNTY_MD: diff --git a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/edge_cases.yaml b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/edge_cases.yaml index d3ef27886d3..1b9c1763223 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/edge_cases.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/edge_cases.yaml @@ -29,6 +29,7 @@ is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER tax_units: tax_unit: members: [person1, person2] @@ -59,6 +60,7 @@ is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER tax_units: tax_unit: members: [person1, person2] @@ -93,6 +95,7 @@ is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER tax_units: tax_unit: members: [person1, person2] @@ -124,6 +127,7 @@ is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER tax_units: tax_unit: members: [person1, person2] @@ -303,31 +307,37 @@ is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER person4: age: 10 is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER person5: age: 7 is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER person6: age: 5 is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER person7: age: 3 is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 4 + md_ccs_provider_type: LICENSED_CENTER person8: age: 1 is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER tax_units: tax_unit: members: [person1, person2, person3, person4, person5, person6, person7, person8] @@ -506,6 +516,7 @@ is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER tax_units: tax_unit: members: [person1, person2] @@ -537,11 +548,13 @@ is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER person3: age: 3 is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER tax_units: tax_unit: members: [person1, person2, person3] @@ -572,16 +585,19 @@ is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER person3: age: 7 is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER person4: age: 3 is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER tax_units: tax_unit: members: [person1, person2, person3, person4] @@ -612,21 +628,25 @@ is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER person3: age: 7 is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER person4: age: 5 is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER person5: age: 3 is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER tax_units: tax_unit: members: [person1, person2, person3, person4, person5] @@ -657,26 +677,31 @@ is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER person3: age: 9 is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER person4: age: 7 is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER person5: age: 5 is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER person6: age: 3 is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER tax_units: tax_unit: members: [person1, person2, person3, person4, person5, person6] @@ -713,6 +738,7 @@ is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER tax_units: tax_unit: members: [person1, person2] @@ -745,6 +771,7 @@ is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER tax_units: tax_unit: members: [person1, person2] @@ -777,6 +804,7 @@ is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER tax_units: tax_unit: members: [person1, person2] @@ -809,6 +837,7 @@ is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER tax_units: tax_unit: members: [person1, person2] @@ -841,6 +870,7 @@ is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER tax_units: tax_unit: members: [person1, person2] @@ -874,6 +904,7 @@ is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 3 + md_ccs_provider_type: LICENSED_CENTER tax_units: tax_unit: members: [person1, person2] @@ -903,6 +934,7 @@ is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 3.5 + md_ccs_provider_type: LICENSED_CENTER tax_units: tax_unit: members: [person1, person2] @@ -931,6 +963,7 @@ is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 6 + md_ccs_provider_type: LICENSED_CENTER tax_units: tax_unit: members: [person1, person2] @@ -959,6 +992,7 @@ is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 5.99 + md_ccs_provider_type: LICENSED_CENTER tax_units: tax_unit: members: [person1, person2] @@ -989,11 +1023,13 @@ is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER person3: age: 3 is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 2 + md_ccs_provider_type: LICENSED_CENTER tax_units: tax_unit: members: [person1, person2, person3] @@ -1140,16 +1176,19 @@ is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER person3: age: 7 is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER person4: age: 3 is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER tax_units: tax_unit: members: [person1, person2, person3, person4] @@ -1185,6 +1224,7 @@ is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 0 + md_ccs_provider_type: LICENSED_CENTER tax_units: tax_unit: members: [person1, person2] @@ -1215,6 +1255,7 @@ is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER tax_units: tax_unit: members: [person1, person2] diff --git a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/integration.yaml index d8f0050bf2b..e7cae6a1b63 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/integration.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/integration.yaml @@ -22,6 +22,7 @@ is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER tax_units: tax_unit: members: [person1, person2] @@ -87,11 +88,13 @@ is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER person4: age: 3 is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 4 + md_ccs_provider_type: LICENSED_CENTER tax_units: tax_unit: members: [person1, person2, person3, person4] @@ -153,6 +156,7 @@ is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER tax_units: tax_unit: members: [person1, person2] @@ -206,11 +210,13 @@ is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER person4: age: 3 is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER tax_units: tax_unit: members: [person1, person2, person3, person4] @@ -267,11 +273,13 @@ is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER person4: age: 2 is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER tax_units: tax_unit: members: [person1, person2, person3, person4] @@ -332,6 +340,7 @@ is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 6 + md_ccs_provider_type: LICENSED_CENTER tax_units: tax_unit: members: [person1, person2] @@ -390,11 +399,13 @@ is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER person4: age: 3 is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER tax_units: tax_unit: members: [person1, person2, person3, person4] diff --git a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs.yaml b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs.yaml index fcf5b997754..b150eeefe43 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs.yaml @@ -16,6 +16,7 @@ is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER tax_units: tax_unit: members: [person1, person2] @@ -28,7 +29,7 @@ members: [person1, person2] state_code: MD output: - # Default provider: LICENSED_CENTER, default county: Allegany = Region Z + # Provider: LICENSED_CENTER (set), default county: Allegany = Region Z # age 5 = REGULAR, 8hrs = UNIT_3 # weekly rate: $207, annual max reimbursement: $207 * 52 = $10,764 # weekly copay: $3, annual copay: $3 * 52 = $156 @@ -80,6 +81,7 @@ is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER tax_units: tax_unit: members: [person1, person2] diff --git a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_weekly_copay.yaml b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_weekly_copay.yaml index 3d0058ea60e..44a2b54c64a 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_weekly_copay.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_weekly_copay.yaml @@ -171,13 +171,13 @@ spm_units: spm_unit: members: [person1, person2] - md_ccs_receives_snap: true + snap: 100 households: household: members: [person1, person2] state_code: MD output: - # SNAP recipient -> copay waived per Ch 525/526 of 2022 (bare input) + # SNAP recipient -> copay waived per Ch 525/526 of 2022 md_ccs_weekly_copay: 0 - name: Case 7, WIC eligible parent pays zero copay. @@ -189,6 +189,7 @@ age: 30 employment_income: 50_000 is_tax_unit_head_or_spouse: true + wic: 100 person2: age: 5 is_tax_unit_dependent: true @@ -200,7 +201,6 @@ spm_units: spm_unit: members: [person1, person2] - md_ccs_receives_wic: true households: household: members: [person1, person2] diff --git a/policyengine_us/variables/gov/states/md/msde/ccs/eligibility/md_ccs_eligible.py b/policyengine_us/variables/gov/states/md/msde/ccs/eligibility/md_ccs_eligible.py index dbca8e755fc..48af233e103 100644 --- a/policyengine_us/variables/gov/states/md/msde/ccs/eligibility/md_ccs_eligible.py +++ b/policyengine_us/variables/gov/states/md/msde/ccs/eligibility/md_ccs_eligible.py @@ -8,13 +8,16 @@ class md_ccs_eligible(Variable): definition_period = MONTH defined_for = StateCode.MD reference = ( - "https://dsd.maryland.gov/regulations/Pages/13A.14.06.03.aspx", - "https://mgaleg.maryland.gov/2022RS/Chapters_noln/CH_525_hb0275e.pdf", + "https://regs.maryland.gov/us/md/exec/comar/13A.14.06.03", + "https://mgaleg.maryland.gov/2022RS/Chapters_noln/CH_525_hb0995E.pdf#page=1", ) def formula(spm_unit, period, parameters): has_eligible_child = add(spm_unit, period, ["md_ccs_eligible_child"]) > 0 income_eligible = spm_unit("md_ccs_income_eligible", period) + # COMAR 13A.14.06.03F(1) waives the income test for TCA applicants or + # recipients. We don't track TANF applicants separately from recipients + # at the moment; the regulation covers both. is_tca = spm_unit("is_tanf_enrolled", period) receives_ssi = add(spm_unit, period, ["ssi"]) > 0 return has_eligible_child & (income_eligible | is_tca | receives_ssi) diff --git a/policyengine_us/variables/gov/states/md/msde/ccs/eligibility/md_ccs_eligible_child.py b/policyengine_us/variables/gov/states/md/msde/ccs/eligibility/md_ccs_eligible_child.py index de54e423f9c..ed99d9db528 100644 --- a/policyengine_us/variables/gov/states/md/msde/ccs/eligibility/md_ccs_eligible_child.py +++ b/policyengine_us/variables/gov/states/md/msde/ccs/eligibility/md_ccs_eligible_child.py @@ -7,7 +7,7 @@ class md_ccs_eligible_child(Variable): label = "Eligible child for Maryland Child Care Scholarship (CCS)" definition_period = MONTH defined_for = StateCode.MD - reference = "https://dsd.maryland.gov/regulations/Pages/13A.14.06.02.aspx" + reference = "https://regs.maryland.gov/us/md/exec/comar/13A.14.06.02" def formula(person, period, parameters): p = parameters(period).gov.states.md.msde.ccs.age_threshold @@ -15,8 +15,7 @@ def formula(person, period, parameters): is_disabled = person("is_disabled", period.this_year) age_limit = where(is_disabled, p.disabled_child, p.child) age_eligible = age < age_limit - is_dependent = person("is_tax_unit_dependent", period.this_year) immigration_eligible = person( "is_ccdf_immigration_eligible_child", period.this_year ) - return age_eligible & is_dependent & immigration_eligible + return age_eligible & immigration_eligible diff --git a/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs.py b/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs.py index 8f35d2b6a95..d1aa5728752 100644 --- a/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs.py +++ b/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs.py @@ -9,7 +9,7 @@ class md_ccs(Variable): definition_period = MONTH defined_for = "md_ccs_eligible" reference = ( - "https://dsd.maryland.gov/regulations/Pages/13A.14.06.11.aspx", + "https://regs.maryland.gov/us/md/exec/comar/13A.14.06.11", "https://earlychildhood.marylandpublicschools.org/families/child-care-scholarship-program/child-care-scholarship-rates", ) diff --git a/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_countable_income.py b/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_countable_income.py index 4dcaa4e2bfb..7481f8ff982 100644 --- a/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_countable_income.py +++ b/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_countable_income.py @@ -9,8 +9,8 @@ class md_ccs_countable_income(Variable): definition_period = MONTH defined_for = StateCode.MD reference = ( - "https://dsd.maryland.gov/regulations/Pages/13A.14.06.03.aspx", - "https://mgaleg.maryland.gov/2022RS/Chapters_noln/CH_525_hb0275e.pdf", + "https://regs.maryland.gov/us/md/exec/comar/13A.14.06.03", + "https://mgaleg.maryland.gov/2022RS/Chapters_noln/CH_525_hb0995E.pdf#page=1", ) def formula(spm_unit, period, parameters): diff --git a/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_income_eligible.py b/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_income_eligible.py index 0cded2ffe0b..9dd9551b635 100644 --- a/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_income_eligible.py +++ b/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_income_eligible.py @@ -1,4 +1,5 @@ from policyengine_us.model_api import * +from policyengine_us.variables.gov.hhs.hhs_smi import smi class md_ccs_income_eligible(Variable): @@ -8,23 +9,30 @@ class md_ccs_income_eligible(Variable): definition_period = MONTH defined_for = StateCode.MD reference = ( - "https://dsd.maryland.gov/regulations/Pages/13A.14.06.03.aspx", - "https://mgaleg.maryland.gov/2022RS/Chapters_noln/CH_525_hb0275e.pdf", + "https://regs.maryland.gov/us/md/exec/comar/13A.14.06.03", + "https://mgaleg.maryland.gov/2022RS/Chapters_noln/CH_525_hb0995E.pdf#page=1", ) def formula(spm_unit, period, parameters): - p = parameters(period).gov.states.md.msde.ccs.income.smi_rate + p = parameters(period).gov.states.md.msde.ccs.income countable_income = spm_unit("md_ccs_countable_income", period) - # TODO: Maryland froze SMI base years for historical periods - # (FY2019-2022 used 2018 SMI, FY2023-2024 used 2021 SMI). - # This formula uses the current-year SMI, which is correct for - # 2025+ but overstates historical thresholds. Follow-up PR - # should parameterize the SMI base year. - smi = spm_unit("hhs_smi", period) + # Maryland freezes the SMI base year on a fiscal-year schedule (MSDE + # Feb 4, 2026 W&M briefing slide 21): FY2019-2022 used 2018 SMI, + # FY2023-2024 used 2021 SMI, FY2025+ uses current SMI. PolicyEngine's + # hhs_smi parameter only has data from 2021-10-01 forward, so the + # FY2019-2022 freeze (2018 SMI) will return zero until earlier SMI + # entries are added. + base_year = p.smi_base_year + if base_year > 0: + size = spm_unit("spm_unit_size", period) + state = spm_unit.household("state_code_str", period) + smi_value = smi(size, state, f"{int(base_year)}-10-01", parameters) + else: + smi_value = spm_unit("hhs_smi", period) enrolled = spm_unit("md_ccs_enrolled", period) income_limit = where( enrolled, - smi * p.continuation, - smi * p.initial, + smi_value * p.smi_rate.continuation, + smi_value * p.smi_rate.initial, ) return countable_income <= income_limit diff --git a/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_provider_type.py b/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_provider_type.py index ffe391bad0a..ca155470da3 100644 --- a/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_provider_type.py +++ b/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_provider_type.py @@ -5,14 +5,15 @@ class MDCCSProviderType(Enum): LICENSED_CENTER = "Licensed Child Care Center" LICENSED_FAMILY = "Licensed Family Child Care Home" INFORMAL = "Informal/License-Exempt" + NONE = "None" class md_ccs_provider_type(Variable): value_type = Enum entity = Person possible_values = MDCCSProviderType - default_value = MDCCSProviderType.LICENSED_CENTER + default_value = MDCCSProviderType.NONE definition_period = MONTH label = "Maryland CCS child care provider type" defined_for = StateCode.MD - reference = "https://dsd.maryland.gov/regulations/Pages/13A.14.06.11.aspx" + reference = "https://regs.maryland.gov/us/md/exec/comar/13A.14.06.11" diff --git a/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_receives_snap.py b/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_receives_snap.py deleted file mode 100644 index b7d9d39a840..00000000000 --- a/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_receives_snap.py +++ /dev/null @@ -1,9 +0,0 @@ -from policyengine_us.model_api import * - - -class md_ccs_receives_snap(Variable): - value_type = bool - entity = SPMUnit - definition_period = MONTH - label = "Whether the family receives SNAP (used for Maryland CCS copay waiver)" - defined_for = StateCode.MD diff --git a/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_receives_wic.py b/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_receives_wic.py deleted file mode 100644 index 7b85d732492..00000000000 --- a/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_receives_wic.py +++ /dev/null @@ -1,9 +0,0 @@ -from policyengine_us.model_api import * - - -class md_ccs_receives_wic(Variable): - value_type = bool - entity = SPMUnit - definition_period = MONTH - label = "Whether the family receives WIC (used for Maryland CCS copay waiver)" - defined_for = StateCode.MD diff --git a/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_weekly_copay.py b/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_weekly_copay.py index 84148219da6..f84e557f236 100644 --- a/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_weekly_copay.py +++ b/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_weekly_copay.py @@ -9,21 +9,22 @@ class md_ccs_weekly_copay(Variable): definition_period = MONTH defined_for = StateCode.MD reference = ( - "https://dsd.maryland.gov/regulations/Pages/13A.14.06.12.aspx", - "https://mgaleg.maryland.gov/2024RS/Chapters_noln/CH_717_sb0482e.pdf", + "https://regs.maryland.gov/us/md/exec/comar/13A.14.06.12", + "https://mgaleg.maryland.gov/2024RS/Chapters_noln/CH_717_sb0362E.pdf#page=1", ) def formula(spm_unit, period, parameters): p = parameters(period).gov.states.md.msde.ccs.copay - # TCA/SSI recipients pay $0 copayment per COMAR 13A.14.06.12(A)(1) + # TCA/SSI recipients pay $0 copayment per COMAR 13A.14.06.12A(1). + # We don't track TANF applicants separately from recipients at the + # moment; the regulation covers both. is_tca = spm_unit("is_tanf_enrolled", period) receives_ssi = add(spm_unit, period, ["ssi"]) > 0 - # SNAP/WIC recipients have copayments waived per Chapters 525/526 of 2022 - # Use bare inputs to avoid circular dependency through SNAP/TANF/childcare chain - is_snap = spm_unit("md_ccs_receives_snap", period) - receives_wic = spm_unit("md_ccs_receives_wic", period) + # SNAP/WIC recipients have copayments waived per Chapter 525 of 2022 (HB 995). + is_snap = add(spm_unit, period, ["snap"]) > 0 + receives_wic = add(spm_unit, period, ["wic"]) > 0 exempt = is_tca | receives_ssi | is_snap | receives_wic # Weekly copay per child based on service unit (enum-keyed lookup) @@ -35,7 +36,10 @@ def formula(spm_unit, period, parameters): is_eligible_child = person("md_ccs_eligible_child", period) weekly_per_child = where(is_eligible_child, weekly_per_child, 0) - # Copay assessed for up to max_children_with_copay children + # Copay assessed for up to max_children_with_copay children. + # We don't track the COMAR youngest/2nd/3rd-child rank distinction at + # the moment — moot under the flat $1/$2/$3 schedule, where every child + # at the same service unit pays the same amount. eligible_child_count = add(spm_unit, period, ["md_ccs_eligible_child"]) capped_count = min_(eligible_child_count, p.max_children_with_copay) total_weekly = spm_unit.sum(weekly_per_child) diff --git a/policyengine_us/variables/gov/states/md/msde/ccs/payment/md_ccs_payment_rate.py b/policyengine_us/variables/gov/states/md/msde/ccs/payment/md_ccs_payment_rate.py index 9dd663258c1..d96d80dcd1d 100644 --- a/policyengine_us/variables/gov/states/md/msde/ccs/payment/md_ccs_payment_rate.py +++ b/policyengine_us/variables/gov/states/md/msde/ccs/payment/md_ccs_payment_rate.py @@ -35,7 +35,7 @@ def formula(person, period, parameters): provider_type == MDCCSProviderType.LICENSED_CENTER, provider_type == MDCCSProviderType.LICENSED_FAMILY, provider_type == MDCCSProviderType.INFORMAL, + provider_type == MDCCSProviderType.NONE, ], - [center_rate, family_rate, informal_rate], - default=center_rate, + [center_rate, family_rate, informal_rate, 0], ) diff --git a/policyengine_us/variables/gov/states/md/msde/ccs/payment/md_ccs_region.py b/policyengine_us/variables/gov/states/md/msde/ccs/payment/md_ccs_region.py index 3d066d60349..21f5c52d7c4 100644 --- a/policyengine_us/variables/gov/states/md/msde/ccs/payment/md_ccs_region.py +++ b/policyengine_us/variables/gov/states/md/msde/ccs/payment/md_ccs_region.py @@ -14,6 +14,9 @@ class MDCCSRegion(Enum): class md_ccs_region(Variable): value_type = Enum entity = Household + # Non-MD households fall through to REGION_W; masked by defined_for on + # consumers, but the load-bearing default is needed because vectorized + # formula execution does not short-circuit on defined_for. possible_values = MDCCSRegion default_value = MDCCSRegion.REGION_W definition_period = MONTH diff --git a/policyengine_us/variables/gov/states/md/msde/ccs/payment/md_ccs_service_unit.py b/policyengine_us/variables/gov/states/md/msde/ccs/payment/md_ccs_service_unit.py index 0d4b6cf4ab3..31ffebea066 100644 --- a/policyengine_us/variables/gov/states/md/msde/ccs/payment/md_ccs_service_unit.py +++ b/policyengine_us/variables/gov/states/md/msde/ccs/payment/md_ccs_service_unit.py @@ -15,7 +15,7 @@ class md_ccs_service_unit(Variable): definition_period = MONTH defined_for = StateCode.MD label = "Maryland CCS service unit category" - reference = "https://dsd.maryland.gov/regulations/Pages/13A.14.06.11.aspx" + reference = "https://regs.maryland.gov/us/md/exec/comar/13A.14.06.11" def formula(person, period, parameters): hours_per_day = person("childcare_hours_per_day", period.this_year) diff --git a/sources/working_references.md b/sources/working_references.md deleted file mode 100644 index 02cadffe599..00000000000 --- a/sources/working_references.md +++ /dev/null @@ -1,271 +0,0 @@ -# Maryland Child Care Scholarship (CCS) Program - Working References - -## Official Program Name -**Child Care Scholarship (CCS) Program** (formerly "Child Care Subsidy Program") - -## Administering Agency -Maryland State Department of Education (MSDE), Division of Early Childhood, Office of Child Care - -## Primary Regulations - -### COMAR 13A.14.06 - Child Care Subsidy Program (Full Chapter) -- **URL**: http://mdrules.elaws.us/comar/13a.14.06 -- **PDF (Jan 2023 version with income tables)**: https://marylandpublicschools.org/stateboard/Documents/2023/0124/COMAR13A.14.06.pdf -- **Local copy**: `/tmp/md-comar-13a1406.pdf` -- **Sections**: - - .01 Purpose - - .02 Definitions - - .03 Eligibility (income scales, need requirements, categorical exemptions) - - .04 Pursuit of Child Support Obligations - - .05 Application Process - - .06 Provider Requirements - - .07 Child Care Vouchers - - .08 Service Groups (priority levels) - - .09 Redetermination - - .10 Termination - - .11 Payments for Child Care Services - - .12 Copayments (regional copayment tables, income levels A-J) - - .13 Confidentiality - - .14 Intentional Program Violations - - .15 Hearings and Appeals - -### Individual COMAR Sections Online -- **Definitions**: http://mdrules.elaws.us/comar/13a.14.06.02 -- **Eligibility**: http://mdrules.elaws.us/comar/13a.14.06.03 -- **Service Groups**: http://mdrules.elaws.us/comar/13a.14.06.08 -- **Copayments**: http://mdrules.elaws.us/comar/13a.14.06.12 -- **Cornell LII (full chapter)**: https://www.law.cornell.edu/regulations/maryland/title-13A/subtitle-14/chapter-13A.14.06 - -## Income Eligibility - -### Current Income Eligibility Scale (updated Dec 15, 2024) -- **Source**: CCS Scholarship Brochure (most current) -- **URL**: https://earlychildhood.marylandpublicschools.org/system/files/filedepot/2/scholarship-brochure-4.pdf -- **Local copy**: `/tmp/md-ccs-brochure.pdf` -- **Standard**: 75% of State Median Income (SMI) for initial eligibility; 85% SMI for continuation -- **Initial Income Scale (annual)**: - - Family of 2: $76,117 - - Family of 3: $94,026 - - Family of 4: $111,936 - - Family of 5: $129,846 - - Family of 6: $147,756 - - Family of 7: $151,114 - - Family of 8: $154,472 - - Family of 9: $157,830 - - Family of 10: $161,188 - - Family of 11: $164,546 - - Family of 12: $167,904 -- **Continuation Income Scale (annual)**: - - Family of 2: $86,266 - - Family of 3: $106,563 - - Family of 4: $126,861 - - Family of 5: $147,159 - - Family of 6: $167,457 - - Family of 7: $171,262 - - Family of 8: $175,068 - - Family of 9: $178,874 - - Family of 10: $182,680 - - Family of 11: $186,486 - - Family of 12: $190,292 - -### Previous Income Eligibility Scale (pre-Dec 2024) -- **Source**: CCS Income Eligibility Scale PDF -- **URL**: https://earlychildhood.marylandpublicschools.org/system/files/filedepot/2/income_eligibility_scale.pdf -- **Local copy**: `/tmp/md-ccs-income-scale.pdf` -- **Initial thresholds**: Family of 2: $61,222; Family of 4: $90,033 -- **Continuation thresholds**: Family of 2: $73,899; Family of 4: $108,675 - -### Historical Income Eligibility Thresholds (from Feb 2026 briefing) -| Fiscal Year | % of SMI | SMI Vintage | Family of 4 Threshold | -|---|---|---|---| -| 2016 | 50% | current | $54,631 | -| 2017 | 50% | current | $55,019 | -| 2018 | 50% | current | $55,839 | -| 2019 | 65% | 2018 SMI | $75,590 | -| 2020 | 65% | 2018 SMI | $75,590 | -| 2021 | 65% | 2018 SMI | $75,590 | -| 2022 | 65% | 2018 SMI | $75,590 | -| 2023 | 75% | 2021 SMI | $93,605 | -| 2024 | 75% | 2021 SMI | $93,605 | -| 2025 | 75% | 2025 SMI | $115,588 | -| 2026 | 75% | 2025 SMI | $115,588 | - -### State Median Income (SMI) Data -- **LIHEAP FY2026 SMI for Maryland**: $154,117 (4-person family) -- **Source**: https://acf.gov/sites/default/files/documents/ocs/COMM_LIHEAP_IM2025-02_SMIStateTable_Att4.pdf -- **60% SMI by household size (FY26)**: - - 1 person: $48,084 - - 2 persons: $62,879 - - 3 persons: $77,674 - - 4 persons: $92,470 - - 5 persons: $107,265 - - 6 persons: $122,060 -- **CCS uses ACF SMI estimates for FY2025** (per Feb 2026 briefing, slide 20): - - SMI for household of 2: $101,489 - - SMI for household of 4: $149,249 - -### CCDF Family Income Eligibility Levels by State (Jan 2025) -- **URL**: https://acf.gov/sites/default/files/documents/occ/CCDF-Family-Income-Eligibility-Levels-by-State.pdf -- **Local copy**: `/tmp/md-ccdf-income-levels.pdf` -- **Maryland entry**: 60% SMI (based on CCDF methodology), $6,302/month for family of 3, $7,503/month for family of 4 -- **Note**: CCDF and state report different % because they use different SMI bases - -## COMAR Income Eligibility Scale (Regulation .03H) - Older Values -- **Source**: COMAR 13A.14.06 PDF (Jan 2023 version) -- **Note**: These are the 2018 SMI-based values codified in regulation, superseded by Dec 2024 update -- Family of 1: $0-$37,193 (Level J max) -- Family of 2: $0-$48,637 (Level J max) -- Family of 3: $0-$60,081 (Level J max) -- Family of 4: $0-$71,525 (Level J max) -- Family of 5: $0-$82,969 -- Family of 6: $0-$94,413 -- Family of 7: $0-$96,558 -- Family of 8: $0-$98,704 -- Family of 9: $0-$100,850 -- Family of 10: $0-$102,996 - -## Copayments - -### Current Copayment Policy -- **TCA recipients**: $0 copayment (exempt) -- **SSI recipients**: $0 copayment (exempt) -- **SNAP, WIC, Section 8 recipients**: Copayments waived since May 23, 2022 (Chapters 525/526 of 2022) -- **All other families**: Maximum $3/week per 3-unit scholarship, $2/week per 2-unit, $1/week per 1-unit -- **Chapter 717 of 2024**: Prohibits MSDE from increasing copayment levels in effect as of Jan 1, 2024 -- **Federal CCDF 2024 Final Rule**: Caps copayments at 7% of family gross income - -### COMAR Copayment Tables (Regulation .12) -- **Regional copayment tables** by income level (A-J), region (U, V, W, X, Y, Z, BC), child age (<24 months vs >=24 months) -- **Copayment assessed for up to 3 children**: youngest gets highest, 2nd and 3rd get lower, 4th+ free -- **Units of service**: 1 unit (<=3 hrs), 2 units (>3 to <6 hrs), 3 units (>=6 hrs) -- **2-unit and 1-unit copayments**: multiply 3-unit figures by 2/3 and 1/3 respectively -- **Informal care copayments**: percentage of informal care weekly rate (5%-50% for first child by level A-J) -- **Note**: The COMAR regulation copayment tables appear to be from the pre-2022 era; current copayments are minimal ($1-$3/week) per legislative changes - -## Market Regions -- **Source**: RESI of Towson University, "Maryland Child Care Scholarship Program Reimbursement Rate Adjustments" (Sep 2023) -- **URL**: https://dlslibrary.state.md.us/publications/Exec/MSDE/ED9.5-111(c)_2022.pdf -- **Local copy**: `/tmp/md-ccs-reimbursement-2022.pdf` - -| Region | Counties | -|---|---| -| Region U | Cecil, Queen Anne's, St. Mary's, Talbot, Washington | -| Region V | Caroline, Dorchester, Kent, Somerset, Wicomico | -| Region W | Anne Arundel, Calvert, Carroll, Charles, Prince George's | -| Region X | Howard, Montgomery | -| Region Y | Baltimore, Frederick, Harford | -| Region Z | Allegany, Garrett, Worcester | -| Region B/BC | Baltimore City | - -## Eligibility Requirements Summary - -### Child Age -- Under 13 years (non-disabled) -- Under 19 years (disabled) -- **Source**: COMAR 13A.14.06.02 (definition of "Child") - -### Residency -- Must be a resident of the State of Maryland -- **Source**: COMAR 13A.14.06.03(A)(1) - -### Citizenship -- Children must be U.S. citizens or qualified aliens -- Parents do NOT have to be U.S. citizens -- **Source**: COMAR 13A.14.06.03(B); CCS Brochure - -### Activity Requirement (Need) -- Parent/caretaker must be working/employed, in an approved training program, or attending school -- For two-parent households, both parents must meet requirements -- **Source**: COMAR 13A.14.06.03(E); CCS Brochure - -### Categorical Eligibility -- TCA recipients: exempt from income limits and copayments -- SSI recipients: exempt from income limits and copayments -- **Source**: COMAR 13A.14.06.03(F)(1), .12(A)(1) - -### Income Calculation -- Annual gross income used -- Self-employment: flat 30% deducted for business expenses -- Military housing: paid rental/mortgage fees deducted from allowance -- Child support: averaged over 3 most recent consecutive months (excluded from income per 2022 legislation) -- **Source**: COMAR 13A.14.06.03(F)(3)-(8) - -### Immunizations -- Required for children before receiving services -- Exemptions for medical contraindications or religious objections -- **Source**: COMAR 13A.14.06.03(D) - -### Child Support Cooperation -- Must pursue child support obligations unless good cause exists -- **Source**: COMAR 13A.14.06.04 - -### Eligibility Period -- 12-month minimum (per federal mandate); Maryland uses 24-month eligibility periods -- **Source**: Jan 2025 briefing slide 7 - -## Legislative History - -| Year | Legislation | Key Changes | -|---|---|---| -| 2017 | Ch 209/210 | Required periodic reimbursement rate analysis | -| 2018 | Ch 555/556 | Supplemental Head Start funding | -| 2018 | (MSDE action) | Reimbursement 9th -> 20th percentile; eligibility 32% -> 50% SMI | -| 2019 | Ch 595/596 | Required 60th percentile market rate adjustment; eligibility -> 65% SMI | -| 2020 | (COVID) | All copays waived Mar-Sep 2020; reimbursement -> 60th percentile | -| 2021 | Ch 36/55 | Annual funding for Judy Centers, EXCELS, Blueprint capacity | -| 2022 | Ch 525/526 | Copay waivers for SNAP/WIC/TCA/Section 8/SSI; removed child support from income; created presumptive eligibility; eligibility -> 75% SMI; reimbursement -> 70th percentile | -| 2022 | Ch 498/499 | Therapeutic Child Care Grant Program | -| 2023 | Ch 731/732 | Restrict MSDE from changing key CCS policies as of Jan 1, 2023 | -| 2024 | Ch 717 | Prohibit MSDE from increasing copayment levels as of Jan 1, 2024 | -| 2025 | Ch 369 | Expanded CCS to parenting foster youth | - -## Briefings and Presentations - -### Feb 2026 Ways and Means Committee Briefing -- **URL**: https://mgaleg.maryland.gov/meeting_material/2026/w&m%20-%20134146885147130127%20-%20Briefing%20materials.pdf -- **Local copy**: `/tmp/md-ccs-briefing-2026.pdf` -- **Key data**: 41,148 children / 27,235 families (Jan 2026); waitlist ~4,929 children; current SMI threshold table; demographic breakdowns - -### Jan 2025 Early Childhood Subcommittee Briefing -- **URL**: https://mgaleg.maryland.gov/meeting_material/2025/app%20-%20133815104940229083%20-%20MSDE-Child%20Care%20Scholarship%20Program%20Update%20to%20Subcommittee%20(1).pdf -- **Local copy**: `/tmp/md-ccs-briefing-2025.pdf` -- **Key data**: $568M proposed investment; enrollment freeze May 2025; copayment policy details - -### Jan 2025 CCS Info Session -- **URL**: https://earlychildhood.marylandpublicschools.org/system/files/filedepot/3/january_2025_occ_info_session.pdf -- **Local copy**: `/tmp/md-ccs-info-session-jan2025.pdf` -- **Key data**: Income eligibility increased effective Dec 15, 2024 (family of 2: $76,117; family of 4: $111,936) - -### Jan 2024 Early Childhood Subcommittee Briefing -- **URL**: https://mgaleg.maryland.gov/cmte_testimony/2024/ecm/1qQzLR-gr9jXICeb4E76YUf3vjAwJekVU.pdf -- **Local copy**: `/tmp/md-ccs-briefing-2024.pdf` -- **Key data**: Historical timeline of policy changes; copayment sliding scale proposal (3% for ~$43K-$65K, 7% for >$66K) - -### Oct 2025 Child Care in Maryland (DLS) -- **URL**: https://mgaleg.maryland.gov/meeting_material/2025/app%20-%20134063072915355066%20-%20ChildCarePresentation.pdf -- **Local copy**: `/tmp/md-ccs-childcare-in-md-2025.pdf` -- **Key data**: Comprehensive program overview; freeze status; market rate timeline; federal rule changes - -## Market Rate Survey -- **2024 Market Rate Survey**: https://earlychildhood.marylandpublicschools.org/system/files/filedepot/3/md-market-rate-survey-2024-2.pdf -- **Reimbursement Rate Analysis (2022 data, Sep 2023 report)**: https://dlslibrary.state.md.us/publications/Exec/MSDE/ED9.5-111(c)_2022.pdf -- **Local copy**: `/tmp/md-ccs-reimbursement-2022.pdf` - -## Program Websites -- **Official CCS Program**: https://earlychildhood.marylandpublicschools.org/child-care-providers/child-care-scholarship-program -- **Family Portal**: https://family.childcareportals.org/s/?language=en_US -- **money4childcare.com**: www.money4childcare.com (main family-facing site) -- **CCS Rates**: https://earlychildhood.marylandpublicschools.org/families/child-care-scholarship-program/child-care-scholarship-rates -- **CCDF State Plan**: https://earlychildhood.marylandpublicschools.org/about/ccdf-state-plan -- **Enrollment Data**: https://earlychildhood.marylandpublicschools.org/data - -## Failed Fetches -| URL | Status | Likely Content | -|---|---|---| -| https://earlychildhood.marylandpublicschools.org/child-care-providers/child-care-scholarship-program | 403 | Main program page with eligibility details and links | -| https://earlychildhood.marylandpublicschools.org/changes-subsidy-eligibility | 403 | Details of eligibility changes over time | -| https://earlychildhood.marylandpublicschools.org/families/child-care-scholarship-program/child-care-scholarship-rates | Not fetched | Current provider reimbursement rate tables by region/age/quality | -| https://earlychildhood.marylandpublicschools.org/about/ccdf-state-plan | 403 | CCDF state plan documents with full eligibility and copayment details | -| https://earlychildhood.marylandpublicschools.org/system/files/filedepot/2/income_eligibility_scale.pdf | 403 | Older income eligibility scale PDF (data obtained from text version) | -| https://acf.gov/sites/default/files/documents/ocs/COMM_LIHEAP_IM202502_SMIStateTable_Att4.pdf | 404 | FY26 SMI table (obtained via alternate URL) | -| https://regulations.justia.com/states/maryland/title-13a/subtitle-14/chapter-13a-14-06/section-13a-14-06-02/ | 403 | COMAR definitions (obtained from mdrules.elaws.us) | From 8b5f27bde4363f063d371bcbd5fd0f0399a93cdf Mon Sep 17 00:00:00 2001 From: Ziming Date: Wed, 20 May 2026 14:55:55 -0400 Subject: [PATCH 08/13] refactor rates --- lessons/agent-lessons.md | 18 - .../ccs/payment/formal/licensed_center.yaml | 127 +-- .../ccs/payment/formal/licensed_family.yaml | 127 +-- .../md/msde/ccs/payment/informal/rates.yaml | 336 +----- ..._counties.yaml => region_bc_counties.yaml} | 4 +- .../md/msde/ccs/payment/unit_count.yaml | 18 + .../gov/states/md/msde/ccs/edge_cases.yaml | 975 ++---------------- .../gov/states/md/msde/ccs/integration.yaml | 24 +- .../gov/states/md/msde/ccs/md_ccs.yaml | 17 +- .../md/msde/ccs/md_ccs_countable_income.yaml | 8 +- .../md/msde/ccs/md_ccs_payment_rate.yaml | 14 +- .../md/msde/ccs/md_ccs_weekly_copay.yaml | 19 +- .../states/md/msde/ccs/md_ccs_weekly_copay.py | 11 +- .../msde/ccs/payment/md_ccs_payment_rate.py | 12 +- .../md/msde/ccs/payment/md_ccs_region.py | 8 +- .../variables/gov/usda/snap/receives_snap.py | 8 + 16 files changed, 277 insertions(+), 1449 deletions(-) delete mode 100644 lessons/agent-lessons.md rename policyengine_us/parameters/gov/states/md/msde/ccs/payment/{baltimore_city_counties.yaml => region_bc_counties.yaml} (65%) create mode 100644 policyengine_us/parameters/gov/states/md/msde/ccs/payment/unit_count.yaml create mode 100644 policyengine_us/variables/gov/usda/snap/receives_snap.py diff --git a/lessons/agent-lessons.md b/lessons/agent-lessons.md deleted file mode 100644 index b2bcee7c7df..00000000000 --- a/lessons/agent-lessons.md +++ /dev/null @@ -1,18 +0,0 @@ -# Agent Lessons Learned - -Accumulated from /encode-policy-v2 and /backdate-program runs across all contributors. -Loaded by implementation agents on future runs. - -## New Lessons from Maryland CCS (2026-03-26) - -### VARIABLE -- When a formula uses `select()` with a default/fallback for one category, replace it with explicit matching for ALL categories including the default; implicit defaults silently swallow new or misspelled values and make the "default" category untestable in isolation. - -### REFERENCE -- When a state regulation portal migrates domains (e.g., `dsd.maryland.gov` to `regs.maryland.gov`), ALL parameter files referencing the old domain must be updated in one pass; broken redirects (301 to 404) are systematic, not isolated, so always search-and-replace across the entire state directory rather than fixing one file at a time. -- When a parameter encodes a state policy choice (e.g., state sets 85% SMI threshold), cite the state regulation as the primary reference, not the federal CFR that merely sets the ceiling; federal authority is context, not the source of the state's specific value. -- When correcting a wrong COMAR/regulation subsection citation, verify the replacement subsection's content in the same review round; three of four citation corrections in this session initially pointed to the wrong subsection because adjacent subsections cover different provisions with similar-sounding names (e.g., .03(B) = citizenship vs .03(H) = income eligibility). - -### WORKFLOW -- When implementing a new state program, add it to `programs.yaml` as part of the initial implementation, not as an afterthought; missing registry entries block the program from appearing in the metadata API and coverage page. -- When a `select()` or similar lookup relies on a parameter file for each category, verify that ALL categories have corresponding parameter files before the first review round; a missing file for one category (e.g., Region W counties) forces the formula to use an implicit default, hiding a data gap. diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/payment/formal/licensed_center.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/formal/licensed_center.yaml index b2fc278d07e..5b2e6c39c84 100644 --- a/policyengine_us/parameters/gov/states/md/msde/ccs/payment/formal/licensed_center.yaml +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/formal/licensed_center.yaml @@ -1,123 +1,64 @@ -description: Maryland provides these weekly reimbursement rates for licensed child care centers under the Child Care Scholarship program. +description: Maryland provides these weekly UNIT_3 (full-time) reimbursement rates for licensed child care centers under the Child Care Scholarship program. UNIT_2 and UNIT_1 rates are derived in the formula by multiplying by unit_count / 3 per COMAR 13A.14.06.11. metadata: period: week unit: currency-USD - label: Maryland CCS licensed center weekly rates + label: Maryland CCS licensed center weekly UNIT_3 rates breakdown: - md_ccs_region - md_ccs_age_group - - md_ccs_service_unit reference: - - title: Maryland CCS Scholarship Rates (Formal Rates, 60th Percentile, 2024 Market Rate Survey) + - title: Maryland CCS Scholarship Rates (current schedule, 60th Percentile of 2024 Market Rate Survey, effective 2026-03-01) href: https://earlychildhood.marylandpublicschools.org/families/child-care-scholarship-program/child-care-scholarship-rates - - title: 2024 Maryland Market Rate Survey & Narrow Cost Analysis (Nov 2024) - href: https://earlychildhood.marylandpublicschools.org/system/files/filedepot/3/md-market-rate-survey-2024-2.pdf - - title: MSDE FY27 Operating Budget Analysis (DLS) - 2026-03-01 rate implementation - href: https://mgaleg.maryland.gov/pubs/budgetfiscal/2027fy-budget-docs-operating-R00A99-MSDE-Early-Childhood-Development.pdf + - title: Maryland CCS Scholarship Rates as of 5/23/22 (Wayback Machine snapshot) + href: https://web.archive.org/web/20220616202551/https://earlychildhood.marylandpublicschools.org/families/child-care-scholarship-program/child-care-scholarship-rates REGION_U: REGULAR: - UNIT_3: - 2026-03-01: 244 - UNIT_2: - 2026-03-01: 163 - UNIT_1: - 2026-03-01: 82 + 2022-05-23: 205 + 2026-03-01: 244 INFANT: - UNIT_3: - 2026-03-01: 325 - UNIT_2: - 2026-03-01: 217 - UNIT_1: - 2026-03-01: 109 + 2022-05-23: 296 + 2026-03-01: 325 REGION_V: REGULAR: - UNIT_3: - 2026-03-01: 200 - UNIT_2: - 2026-03-01: 133 - UNIT_1: - 2026-03-01: 67 + 2022-05-23: 175 + 2026-03-01: 200 INFANT: - UNIT_3: - 2026-03-01: 264 - UNIT_2: - 2026-03-01: 176 - UNIT_1: - 2026-03-01: 88 + 2022-05-23: 242 + 2026-03-01: 264 REGION_W: REGULAR: - UNIT_3: - 2026-03-01: 305 - UNIT_2: - 2026-03-01: 204 - UNIT_1: - 2026-03-01: 102 + 2022-05-23: 262 + 2026-03-01: 305 INFANT: - UNIT_3: - 2026-03-01: 420 - UNIT_2: - 2026-03-01: 280 - UNIT_1: - 2026-03-01: 140 + 2022-05-23: 370 + 2026-03-01: 420 REGION_X: REGULAR: - UNIT_3: - 2026-03-01: 424 - UNIT_2: - 2026-03-01: 283 - UNIT_1: - 2026-03-01: 142 + 2022-05-23: 381 + 2026-03-01: 424 INFANT: - UNIT_3: - 2026-03-01: 554 - UNIT_2: - 2026-03-01: 369 - UNIT_1: - 2026-03-01: 185 + 2022-05-23: 481 + 2026-03-01: 554 REGION_Y: REGULAR: - UNIT_3: - 2026-03-01: 278 - UNIT_2: - 2026-03-01: 185 - UNIT_1: - 2026-03-01: 93 + 2022-05-23: 278 + 2026-03-01: 312 INFANT: - UNIT_3: - 2026-03-01: 378 - UNIT_2: - 2026-03-01: 252 - UNIT_1: - 2026-03-01: 126 + 2022-05-23: 378 + 2026-03-01: 427 REGION_Z: REGULAR: - UNIT_3: - 2026-03-01: 207 - UNIT_2: - 2026-03-01: 138 - UNIT_1: - 2026-03-01: 69 + 2022-05-23: 183 + 2026-03-01: 207 INFANT: - UNIT_3: - 2026-03-01: 297 - UNIT_2: - 2026-03-01: 198 - UNIT_1: - 2026-03-01: 99 -BALTIMORE_CITY: + 2022-05-23: 262 + 2026-03-01: 297 +REGION_BC: REGULAR: - UNIT_3: - 2026-03-01: 282 - UNIT_2: - 2026-03-01: 188 - UNIT_1: - 2026-03-01: 94 + 2022-05-23: 250 + 2026-03-01: 282 INFANT: - UNIT_3: - 2026-03-01: 376 - UNIT_2: - 2026-03-01: 251 - UNIT_1: - 2026-03-01: 126 + 2022-05-23: 303 + 2026-03-01: 376 diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/payment/formal/licensed_family.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/formal/licensed_family.yaml index e3331fdb03a..c9751ac27c6 100644 --- a/policyengine_us/parameters/gov/states/md/msde/ccs/payment/formal/licensed_family.yaml +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/formal/licensed_family.yaml @@ -1,123 +1,64 @@ -description: Maryland provides these weekly reimbursement rates for licensed family child care homes under the Child Care Scholarship program. +description: Maryland provides these weekly UNIT_3 (full-time) reimbursement rates for licensed family child care homes under the Child Care Scholarship program. UNIT_2 and UNIT_1 rates are derived in the formula by multiplying by unit_count / 3 per COMAR 13A.14.06.11. metadata: period: week unit: currency-USD - label: Maryland CCS licensed family weekly rates + label: Maryland CCS licensed family weekly UNIT_3 rates breakdown: - md_ccs_region - md_ccs_age_group - - md_ccs_service_unit reference: - - title: Maryland CCS Scholarship Rates (Formal Rates, 60th Percentile, 2024 Market Rate Survey) + - title: Maryland CCS Scholarship Rates (current schedule, 60th Percentile of 2024 Market Rate Survey, effective 2026-03-01) href: https://earlychildhood.marylandpublicschools.org/families/child-care-scholarship-program/child-care-scholarship-rates - - title: 2024 Maryland Market Rate Survey & Narrow Cost Analysis (Nov 2024) - href: https://earlychildhood.marylandpublicschools.org/system/files/filedepot/3/md-market-rate-survey-2024-2.pdf - - title: MSDE FY27 Operating Budget Analysis (DLS) - 2026-03-01 rate implementation - href: https://mgaleg.maryland.gov/pubs/budgetfiscal/2027fy-budget-docs-operating-R00A99-MSDE-Early-Childhood-Development.pdf + - title: Maryland CCS Scholarship Rates as of 5/23/22 (Wayback Machine snapshot) + href: https://web.archive.org/web/20220616202551/https://earlychildhood.marylandpublicschools.org/families/child-care-scholarship-program/child-care-scholarship-rates REGION_U: REGULAR: - UNIT_3: - 2026-03-01: 200 - UNIT_2: - 2026-03-01: 134 - UNIT_1: - 2026-03-01: 67 + 2022-05-23: 176 + 2026-03-01: 200 INFANT: - UNIT_3: - 2026-03-01: 225 - UNIT_2: - 2026-03-01: 150 - UNIT_1: - 2026-03-01: 75 + 2022-05-23: 200 + 2026-03-01: 225 REGION_V: REGULAR: - UNIT_3: - 2026-03-01: 175 - UNIT_2: - 2026-03-01: 117 - UNIT_1: - 2026-03-01: 59 + 2022-05-23: 142 + 2026-03-01: 175 INFANT: - UNIT_3: - 2026-03-01: 200 - UNIT_2: - 2026-03-01: 134 - UNIT_1: - 2026-03-01: 67 + 2022-05-23: 175 + 2026-03-01: 200 REGION_W: REGULAR: - UNIT_3: - 2026-03-01: 265 - UNIT_2: - 2026-03-01: 177 - UNIT_1: - 2026-03-01: 89 + 2022-05-23: 230 + 2026-03-01: 262 INFANT: - UNIT_3: - 2026-03-01: 300 - UNIT_2: - 2026-03-01: 200 - UNIT_1: - 2026-03-01: 100 + 2022-05-23: 270 + 2026-03-01: 300 REGION_X: REGULAR: - UNIT_3: - 2026-03-01: 325 - UNIT_2: - 2026-03-01: 217 - UNIT_1: - 2026-03-01: 109 + 2022-05-23: 300 + 2026-03-01: 325 INFANT: - UNIT_3: - 2026-03-01: 350 - UNIT_2: - 2026-03-01: 234 - UNIT_1: - 2026-03-01: 117 + 2022-05-23: 325 + 2026-03-01: 350 REGION_Y: REGULAR: - UNIT_3: - 2026-03-01: 220 - UNIT_2: - 2026-03-01: 147 - UNIT_1: - 2026-03-01: 73 + 2022-05-23: 220 + 2026-03-01: 250 INFANT: - UNIT_3: - 2026-03-01: 250 - UNIT_2: - 2026-03-01: 167 - UNIT_1: - 2026-03-01: 83 + 2022-05-23: 250 + 2026-03-01: 288 REGION_Z: REGULAR: - UNIT_3: - 2026-03-01: 170 - UNIT_2: - 2026-03-01: 114 - UNIT_1: - 2026-03-01: 57 + 2022-05-23: 150 + 2026-03-01: 170 INFANT: - UNIT_3: - 2026-03-01: 185 - UNIT_2: - 2026-03-01: 124 - UNIT_1: - 2026-03-01: 62 -BALTIMORE_CITY: + 2022-05-23: 168 + 2026-03-01: 185 +REGION_BC: REGULAR: - UNIT_3: - 2026-03-01: 225 - UNIT_2: - 2026-03-01: 150 - UNIT_1: - 2026-03-01: 75 + 2022-05-23: 182 + 2026-03-01: 225 INFANT: - UNIT_3: - 2026-03-01: 252 - UNIT_2: - 2026-03-01: 168 - UNIT_1: - 2026-03-01: 84 + 2022-05-23: 210 + 2026-03-01: 252 diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/payment/informal/rates.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/informal/rates.yaml index 641d96c8c19..7b2366d95a6 100644 --- a/policyengine_us/parameters/gov/states/md/msde/ccs/payment/informal/rates.yaml +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/informal/rates.yaml @@ -10,361 +10,121 @@ metadata: ALLEGANY_COUNTY_MD: REGULAR: - UNIT_3: - 2020-11-23: 83 - UNIT_2: - 2020-11-23: 55 - UNIT_1: - 2020-11-23: 28 + 2020-11-23: 83 INFANT: - UNIT_3: - 2020-11-23: 90 - UNIT_2: - 2020-11-23: 60 - UNIT_1: - 2020-11-23: 30 + 2020-11-23: 90 ANNE_ARUNDEL_COUNTY_MD: REGULAR: - UNIT_3: - 2020-11-23: 135 - UNIT_2: - 2020-11-23: 90 - UNIT_1: - 2020-11-23: 45 + 2020-11-23: 135 INFANT: - UNIT_3: - 2020-11-23: 150 - UNIT_2: - 2020-11-23: 100 - UNIT_1: - 2020-11-23: 50 + 2020-11-23: 150 BALTIMORE_COUNTY_MD: REGULAR: - UNIT_3: - 2020-11-23: 125 - UNIT_2: - 2020-11-23: 83 - UNIT_1: - 2020-11-23: 42 + 2020-11-23: 125 INFANT: - UNIT_3: - 2020-11-23: 150 - UNIT_2: - 2020-11-23: 100 - UNIT_1: - 2020-11-23: 50 + 2020-11-23: 150 CALVERT_COUNTY_MD: REGULAR: - UNIT_3: - 2020-11-23: 135 - UNIT_2: - 2020-11-23: 90 - UNIT_1: - 2020-11-23: 45 + 2020-11-23: 135 INFANT: - UNIT_3: - 2020-11-23: 150 - UNIT_2: - 2020-11-23: 100 - UNIT_1: - 2020-11-23: 50 + 2020-11-23: 150 CAROLINE_COUNTY_MD: REGULAR: - UNIT_3: - 2020-11-23: 84 - UNIT_2: - 2020-11-23: 56 - UNIT_1: - 2020-11-23: 28 + 2020-11-23: 84 INFANT: - UNIT_3: - 2020-11-23: 100 - UNIT_2: - 2020-11-23: 67 - UNIT_1: - 2020-11-23: 33 + 2020-11-23: 100 CARROLL_COUNTY_MD: REGULAR: - UNIT_3: - 2020-11-23: 135 - UNIT_2: - 2020-11-23: 90 - UNIT_1: - 2020-11-23: 45 + 2020-11-23: 135 INFANT: - UNIT_3: - 2020-11-23: 150 - UNIT_2: - 2020-11-23: 100 - UNIT_1: - 2020-11-23: 50 + 2020-11-23: 150 CECIL_COUNTY_MD: REGULAR: - UNIT_3: - 2020-11-23: 105 - UNIT_2: - 2020-11-23: 70 - UNIT_1: - 2020-11-23: 35 + 2020-11-23: 105 INFANT: - UNIT_3: - 2020-11-23: 120 - UNIT_2: - 2020-11-23: 80 - UNIT_1: - 2020-11-23: 40 + 2020-11-23: 120 CHARLES_COUNTY_MD: REGULAR: - UNIT_3: - 2020-11-23: 135 - UNIT_2: - 2020-11-23: 90 - UNIT_1: - 2020-11-23: 45 + 2020-11-23: 135 INFANT: - UNIT_3: - 2020-11-23: 150 - UNIT_2: - 2020-11-23: 100 - UNIT_1: - 2020-11-23: 50 + 2020-11-23: 150 DORCHESTER_COUNTY_MD: REGULAR: - UNIT_3: - 2020-11-23: 84 - UNIT_2: - 2020-11-23: 56 - UNIT_1: - 2020-11-23: 28 + 2020-11-23: 84 INFANT: - UNIT_3: - 2020-11-23: 100 - UNIT_2: - 2020-11-23: 67 - UNIT_1: - 2020-11-23: 33 + 2020-11-23: 100 FREDERICK_COUNTY_MD: REGULAR: - UNIT_3: - 2020-11-23: 125 - UNIT_2: - 2020-11-23: 83 - UNIT_1: - 2020-11-23: 42 + 2020-11-23: 125 INFANT: - UNIT_3: - 2020-11-23: 150 - UNIT_2: - 2020-11-23: 100 - UNIT_1: - 2020-11-23: 50 + 2020-11-23: 150 GARRETT_COUNTY_MD: REGULAR: - UNIT_3: - 2020-11-23: 83 - UNIT_2: - 2020-11-23: 55 - UNIT_1: - 2020-11-23: 28 + 2020-11-23: 83 INFANT: - UNIT_3: - 2020-11-23: 90 - UNIT_2: - 2020-11-23: 60 - UNIT_1: - 2020-11-23: 30 + 2020-11-23: 90 HARFORD_COUNTY_MD: REGULAR: - UNIT_3: - 2020-11-23: 125 - UNIT_2: - 2020-11-23: 83 - UNIT_1: - 2020-11-23: 42 + 2020-11-23: 125 INFANT: - UNIT_3: - 2020-11-23: 150 - UNIT_2: - 2020-11-23: 100 - UNIT_1: - 2020-11-23: 50 + 2020-11-23: 150 HOWARD_COUNTY_MD: REGULAR: - UNIT_3: - 2020-11-23: 177 - UNIT_2: - 2020-11-23: 118 - UNIT_1: - 2020-11-23: 59 + 2020-11-23: 177 INFANT: - UNIT_3: - 2020-11-23: 195 - UNIT_2: - 2020-11-23: 130 - UNIT_1: - 2020-11-23: 65 + 2020-11-23: 195 KENT_COUNTY_MD: REGULAR: - UNIT_3: - 2020-11-23: 84 - UNIT_2: - 2020-11-23: 56 - UNIT_1: - 2020-11-23: 28 + 2020-11-23: 84 INFANT: - UNIT_3: - 2020-11-23: 100 - UNIT_2: - 2020-11-23: 67 - UNIT_1: - 2020-11-23: 33 + 2020-11-23: 100 MONTGOMERY_COUNTY_MD: REGULAR: - UNIT_3: - 2020-11-23: 177 - UNIT_2: - 2020-11-23: 118 - UNIT_1: - 2020-11-23: 59 + 2020-11-23: 177 INFANT: - UNIT_3: - 2020-11-23: 195 - UNIT_2: - 2020-11-23: 130 - UNIT_1: - 2020-11-23: 65 + 2020-11-23: 195 PRINCE_GEORGE_S_COUNTY_MD: REGULAR: - UNIT_3: - 2020-11-23: 135 - UNIT_2: - 2020-11-23: 90 - UNIT_1: - 2020-11-23: 45 + 2020-11-23: 135 INFANT: - UNIT_3: - 2020-11-23: 150 - UNIT_2: - 2020-11-23: 100 - UNIT_1: - 2020-11-23: 50 + 2020-11-23: 150 QUEEN_ANNE_S_COUNTY_MD: REGULAR: - UNIT_3: - 2020-11-23: 105 - UNIT_2: - 2020-11-23: 70 - UNIT_1: - 2020-11-23: 35 + 2020-11-23: 105 INFANT: - UNIT_3: - 2020-11-23: 120 - UNIT_2: - 2020-11-23: 80 - UNIT_1: - 2020-11-23: 40 + 2020-11-23: 120 ST_MARY_S_COUNTY_MD: REGULAR: - UNIT_3: - 2020-11-23: 105 - UNIT_2: - 2020-11-23: 70 - UNIT_1: - 2020-11-23: 35 + 2020-11-23: 105 INFANT: - UNIT_3: - 2020-11-23: 120 - UNIT_2: - 2020-11-23: 80 - UNIT_1: - 2020-11-23: 40 + 2020-11-23: 120 SOMERSET_COUNTY_MD: REGULAR: - UNIT_3: - 2020-11-23: 84 - UNIT_2: - 2020-11-23: 56 - UNIT_1: - 2020-11-23: 28 + 2020-11-23: 84 INFANT: - UNIT_3: - 2020-11-23: 100 - UNIT_2: - 2020-11-23: 67 - UNIT_1: - 2020-11-23: 33 + 2020-11-23: 100 TALBOT_COUNTY_MD: REGULAR: - UNIT_3: - 2020-11-23: 105 - UNIT_2: - 2020-11-23: 70 - UNIT_1: - 2020-11-23: 35 + 2020-11-23: 105 INFANT: - UNIT_3: - 2020-11-23: 120 - UNIT_2: - 2020-11-23: 80 - UNIT_1: - 2020-11-23: 40 + 2020-11-23: 120 WASHINGTON_COUNTY_MD: REGULAR: - UNIT_3: - 2020-11-23: 105 - UNIT_2: - 2020-11-23: 70 - UNIT_1: - 2020-11-23: 35 + 2020-11-23: 105 INFANT: - UNIT_3: - 2020-11-23: 120 - UNIT_2: - 2020-11-23: 80 - UNIT_1: - 2020-11-23: 40 + 2020-11-23: 120 WICOMICO_COUNTY_MD: REGULAR: - UNIT_3: - 2020-11-23: 84 - UNIT_2: - 2020-11-23: 56 - UNIT_1: - 2020-11-23: 28 + 2020-11-23: 84 INFANT: - UNIT_3: - 2020-11-23: 100 - UNIT_2: - 2020-11-23: 67 - UNIT_1: - 2020-11-23: 33 + 2020-11-23: 100 WORCESTER_COUNTY_MD: REGULAR: - UNIT_3: - 2020-11-23: 83 - UNIT_2: - 2020-11-23: 55 - UNIT_1: - 2020-11-23: 28 + 2020-11-23: 83 INFANT: - UNIT_3: - 2020-11-23: 90 - UNIT_2: - 2020-11-23: 60 - UNIT_1: - 2020-11-23: 30 + 2020-11-23: 90 BALTIMORE_CITY_MD: REGULAR: - UNIT_3: - 2020-11-23: 106 - UNIT_2: - 2020-11-23: 71 - UNIT_1: - 2020-11-23: 35 + 2020-11-23: 106 INFANT: - UNIT_3: - 2020-11-23: 120 - UNIT_2: - 2020-11-23: 80 - UNIT_1: - 2020-11-23: 40 + 2020-11-23: 120 diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/payment/baltimore_city_counties.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/region_bc_counties.yaml similarity index 65% rename from policyengine_us/parameters/gov/states/md/msde/ccs/payment/baltimore_city_counties.yaml rename to policyengine_us/parameters/gov/states/md/msde/ccs/payment/region_bc_counties.yaml index cb09fb47d74..b9da883a771 100644 --- a/policyengine_us/parameters/gov/states/md/msde/ccs/payment/baltimore_city_counties.yaml +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/region_bc_counties.yaml @@ -1,4 +1,4 @@ -description: Maryland sets Baltimore City as its own region for Child Care Scholarship rate purposes. +description: Maryland assigns Baltimore City to Region BC for Child Care Scholarship rate purposes. values: 2020-11-23: - BALTIMORE_CITY_MD @@ -6,7 +6,7 @@ values: metadata: unit: list period: year - label: Maryland CCS Baltimore City region + label: Maryland CCS Region BC counties reference: - title: Maryland CCS Scholarship Rates href: https://earlychildhood.marylandpublicschools.org/families/child-care-scholarship-program/child-care-scholarship-rates diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/payment/unit_count.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/unit_count.yaml new file mode 100644 index 00000000000..3dd57452c9c --- /dev/null +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/unit_count.yaml @@ -0,0 +1,18 @@ +description: Maryland's UNIT_3 (full-time) rate corresponds to three units of service per day per COMAR 13A.14.06.11. UNIT_2 and UNIT_1 rates are derived by multiplying the UNIT_3 rate by unit_count / 3 (i.e., 2/3 and 1/3 respectively). + +metadata: + unit: /1 + period: year + label: Maryland CCS service unit count + breakdown: + - md_ccs_service_unit + reference: + - title: COMAR 13A.14.06.11.B(3), .11.C(2), .11.D + href: https://regs.maryland.gov/us/md/exec/comar/13A.14.06.11 + +UNIT_3: + 2022-05-01: 3 +UNIT_2: + 2022-05-01: 2 +UNIT_1: + 2022-05-01: 1 diff --git a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/edge_cases.yaml b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/edge_cases.yaml index 1b9c1763223..c26efd7ec6e 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/edge_cases.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/edge_cases.yaml @@ -1,214 +1,7 @@ # Maryland CCS Edge Case Tests -# Tests boundary conditions for eligibility, copayment, and benefit calculations. -# FY2025 MD SMI base: $149,249 -# -# SMI by family size: -# Fam 1: 149,249 * 0.52 = 77,609.48 -# Fam 2: 149,249 * 0.68 = 101,489.32 -# Fam 7: 149,249 * (0.52 + 0.16*5 + 0.03) = 149,249 * 1.35 = 201,486.15 -# Fam 8: 149,249 * (0.52 + 0.16*5 + 0.03*2) = 149,249 * 1.38 = 205,963.62 -# -# 75% SMI (initial): Fam 1 = 58,207.11, Fam 2 = 76,116.99 -# 85% SMI (continuation): Fam 2 = 86,265.92 - -# === Income threshold boundary: 75% SMI === - -- name: Case 1, income just below 75 percent SMI threshold for family of 2. - period: 2025-01 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 30 - # 75% SMI for fam 2 ~ 76,116.99 annually - # Use 76,116 to stay just below threshold (avoids float precision) - employment_income: 76_116 - is_tax_unit_head_or_spouse: true - person2: - age: 5 - is_tax_unit_dependent: true - immigration_status: CITIZEN - childcare_hours_per_day: 8 - md_ccs_provider_type: LICENSED_CENTER - tax_units: - tax_unit: - members: [person1, person2] - spm_units: - spm_unit: - members: [person1, person2] - households: - household: - members: [person1, person2] - state_code: MD - output: - # monthly countable: 76,116 / 12 = 6,343.00 - # monthly 75% SMI: ~6,343.08 - # 6,343.00 <= 6,343.08 -> eligible - md_ccs_income_eligible: true - -- name: Case 2, income one dollar above 75 percent SMI threshold for family of 2. - period: 2025-01 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 30 - employment_income: 76_118 - is_tax_unit_head_or_spouse: true - person2: - age: 5 - is_tax_unit_dependent: true - immigration_status: CITIZEN - childcare_hours_per_day: 8 - md_ccs_provider_type: LICENSED_CENTER - tax_units: - tax_unit: - members: [person1, person2] - spm_units: - spm_unit: - members: [person1, person2] - households: - household: - members: [person1, person2] - state_code: MD - output: - # monthly countable: 76,118 / 12 = 6,343.17 - # monthly 75% SMI: 6,343.08 - # 6,343.17 > 6,343.08 -> not eligible - md_ccs_income_eligible: false - -# === Income threshold boundary: 85% SMI (continuation) === - -- name: Case 3, enrolled family income just below 85 percent SMI threshold. - period: 2025-01 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 30 - # 85% SMI for fam 2 ~ 86,265.92 annually - # Use 86,265 to stay just below threshold (avoids float precision) - employment_income: 86_265 - is_tax_unit_head_or_spouse: true - person2: - age: 5 - is_tax_unit_dependent: true - immigration_status: CITIZEN - childcare_hours_per_day: 8 - md_ccs_provider_type: LICENSED_CENTER - tax_units: - tax_unit: - members: [person1, person2] - spm_units: - spm_unit: - members: [person1, person2] - md_ccs_enrolled: true - households: - household: - members: [person1, person2] - state_code: MD - output: - # monthly countable: 86,265 / 12 = 7,188.75 - # monthly 85% SMI: ~7,188.83 - # 7,188.75 <= 7,188.83 -> eligible - md_ccs_income_eligible: true - -- name: Case 4, enrolled family income one dollar above 85 percent SMI threshold. - period: 2025-01 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 30 - employment_income: 86_267 - is_tax_unit_head_or_spouse: true - person2: - age: 5 - is_tax_unit_dependent: true - immigration_status: CITIZEN - childcare_hours_per_day: 8 - md_ccs_provider_type: LICENSED_CENTER - tax_units: - tax_unit: - members: [person1, person2] - spm_units: - spm_unit: - members: [person1, person2] - md_ccs_enrolled: true - households: - household: - members: [person1, person2] - state_code: MD - output: - # monthly countable: 86,267 / 12 = 7,188.92 - # monthly 85% SMI: 7,188.83 - # 7,188.92 > 7,188.83 -> not eligible - md_ccs_income_eligible: false - -# === Enrolled between 75-85% SMI: initial vs continuation === - -- name: Case 5, not enrolled with income between 75 and 85 percent SMI is not eligible. - period: 2025-01 - input: - people: - person1: - age: 30 - # 80,000 is between 75% SMI (76,117) and 85% SMI (86,266) for fam 2 - employment_income: 80_000 - is_tax_unit_head_or_spouse: true - person2: - age: 5 - is_tax_unit_dependent: true - immigration_status: CITIZEN - tax_units: - tax_unit: - members: [person1, person2] - spm_units: - spm_unit: - members: [person1, person2] - md_ccs_enrolled: false - households: - household: - members: [person1, person2] - state_code: MD - output: - # Not enrolled -> initial threshold (75% SMI) - # monthly countable: 80,000 / 12 = 6,666.67 - # monthly 75% SMI: 6,343.08 - # 6,666.67 > 6,343.08 -> not eligible - md_ccs_income_eligible: false - -- name: Case 6, enrolled with income between 75 and 85 percent SMI is eligible. - period: 2025-01 - input: - people: - person1: - age: 30 - employment_income: 80_000 - is_tax_unit_head_or_spouse: true - person2: - age: 5 - is_tax_unit_dependent: true - immigration_status: CITIZEN - tax_units: - tax_unit: - members: [person1, person2] - spm_units: - spm_unit: - members: [person1, person2] - md_ccs_enrolled: true - households: - household: - members: [person1, person2] - state_code: MD - output: - # Enrolled -> continuation threshold (85% SMI) - # monthly countable: 80,000 / 12 = 6,666.67 - # monthly 85% SMI: 7,188.83 - # 6,666.67 <= 7,188.83 -> eligible - md_ccs_income_eligible: true - -# === Zero income === +# Edge cases not covered by md_ccs_eligible.yaml, md_ccs_eligible_child.yaml, +# md_ccs_income_eligible.yaml, md_ccs_countable_income.yaml, md_ccs_weekly_copay.yaml, +# md_ccs.yaml, integration.yaml. - name: Case 7, zero income family is income eligible. period: 2025-01 @@ -266,33 +59,9 @@ # === Family size: minimum (1 person, adult only) === -- name: Case 9, single adult with no children has no eligible child. - period: 2025-01 - input: - people: - person1: - age: 30 - employment_income: 30_000 - is_tax_unit_head_or_spouse: true - tax_units: - tax_unit: - members: [person1] - spm_units: - spm_unit: - members: [person1] - households: - household: - members: [person1] - state_code: MD - output: - md_ccs_eligible_child: [false] - md_ccs_eligible: false - -# === Family size: large (8 people, 6 children) === - - name: Case 10, large family of 8 with 6 children. period: 2025-01 - absolute_error_margin: 0.01 + absolute_error_margin: 0.1 input: people: person1: @@ -362,7 +131,7 @@ - name: Case 11, family with 100 percent self-employment income. period: 2025-01 - absolute_error_margin: 0.01 + absolute_error_margin: 0.1 input: people: person1: @@ -390,7 +159,7 @@ - name: Case 12, family with zero self-employment income. period: 2025-01 - absolute_error_margin: 0.01 + absolute_error_margin: 0.1 input: people: person1: @@ -419,104 +188,134 @@ # === Age boundary: child exactly age 13 (non-disabled) === -- name: Case 13, child exactly age 13 not disabled is not eligible. +- name: Case 19, four children copay capped at 3 children. period: 2025-01 + absolute_error_margin: 0.1 input: people: person1: - age: 40 + age: 30 + employment_income: 50_000 is_tax_unit_head_or_spouse: true person2: - age: 13 + age: 10 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER + person3: + age: 7 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER + person4: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER + person5: + age: 3 is_tax_unit_dependent: true immigration_status: CITIZEN + childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER tax_units: tax_unit: - members: [person1, person2] + members: [person1, person2, person3, person4, person5] spm_units: spm_unit: - members: [person1, person2] + members: [person1, person2, person3, person4, person5] households: household: - members: [person1, person2] + members: [person1, person2, person3, person4, person5] state_code: MD output: - # age 13, threshold is < 13 -> not eligible - md_ccs_eligible_child: [false, false] - -# === Age boundary: disabled child exactly age 18 === + # 4 eligible children, each full-time -> raw total = $3*4 = $12/week + # capped_count = min(4, 3) = 3, scale = 3/4 = 0.75 + # scaled total = $12 * 0.75 = $9/week + md_ccs_weekly_copay: 9 -- name: Case 14, disabled child exactly age 18 is eligible. +- name: Case 24, zero childcare expenses results in zero benefit. period: 2025-01 + absolute_error_margin: 0.1 input: people: person1: - age: 45 + age: 30 + employment_income: 50_000 is_tax_unit_head_or_spouse: true person2: - age: 18 - is_disabled: true + age: 5 is_tax_unit_dependent: true immigration_status: CITIZEN + childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER tax_units: tax_unit: members: [person1, person2] spm_units: spm_unit: members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 0 households: household: members: [person1, person2] state_code: MD output: - # age 18 < 19 (disabled threshold) -> eligible - md_ccs_eligible_child: [false, true] + # expenses = 0, copay = $3 * 52 / 12 = $13/month + # benefit = max(0 - 13, 0) = 0 + md_ccs: 0 -# === Age boundary: disabled child exactly age 19 === +# === Expenses less than copay === -- name: Case 15, disabled child exactly age 19 is not eligible. +- name: Case 25, expenses less than copay results in zero benefit. period: 2025-01 + absolute_error_margin: 0.1 input: people: person1: - age: 45 + age: 30 + employment_income: 50_000 is_tax_unit_head_or_spouse: true person2: - age: 19 - is_disabled: true + age: 5 is_tax_unit_dependent: true immigration_status: CITIZEN + childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER tax_units: tax_unit: members: [person1, person2] spm_units: spm_unit: members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 100 households: household: members: [person1, person2] state_code: MD output: - # age 19, threshold is < 19 -> not eligible - md_ccs_eligible_child: [false, false] + # annual copay = $3 * 52 = $156 + # annual expenses = $100 + # benefit = max(100 - 156, 0) = 0 (floored at 0) + md_ccs: 0 -# === Multiple children copay scaling === +# === Service unit boundary: hours per day === -- name: Case 16, one child copay. +- name: Case 31, undocumented child is not eligible. period: 2025-01 - absolute_error_margin: 0.01 input: people: person1: age: 30 - employment_income: 50_000 + employment_income: 30_000 is_tax_unit_head_or_spouse: true person2: age: 5 is_tax_unit_dependent: true - immigration_status: CITIZEN - childcare_hours_per_day: 8 - md_ccs_provider_type: LICENSED_CENTER + immigration_status: UNDOCUMENTED tax_units: tax_unit: members: [person1, person2] @@ -528,643 +327,15 @@ members: [person1, person2] state_code: MD output: - # 1 child, full-time -> $3/week - # capped_count = min(1, 3) = 1 - # scale = 1/1 = 1 - # total = $3 * 1 = $3/week - md_ccs_weekly_copay: 3 - -- name: Case 17, two children copay. - period: 2025-01 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 30 - employment_income: 50_000 - is_tax_unit_head_or_spouse: true - person2: - age: 5 - is_tax_unit_dependent: true - immigration_status: CITIZEN - childcare_hours_per_day: 8 - md_ccs_provider_type: LICENSED_CENTER - person3: - age: 3 - is_tax_unit_dependent: true - immigration_status: CITIZEN - childcare_hours_per_day: 8 - md_ccs_provider_type: LICENSED_CENTER - tax_units: - tax_unit: - members: [person1, person2, person3] - spm_units: - spm_unit: - members: [person1, person2, person3] - households: - household: - members: [person1, person2, person3] - state_code: MD - output: - # 2 children, each full-time -> $3 + $3 = $6/week - # capped_count = min(2, 3) = 2, scale = 2/2 = 1 - # total = $6/week - md_ccs_weekly_copay: 6 - -- name: Case 18, three children copay at max. - period: 2025-01 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 30 - employment_income: 50_000 - is_tax_unit_head_or_spouse: true - person2: - age: 10 - is_tax_unit_dependent: true - immigration_status: CITIZEN - childcare_hours_per_day: 8 - md_ccs_provider_type: LICENSED_CENTER - person3: - age: 7 - is_tax_unit_dependent: true - immigration_status: CITIZEN - childcare_hours_per_day: 8 - md_ccs_provider_type: LICENSED_CENTER - person4: - age: 3 - is_tax_unit_dependent: true - immigration_status: CITIZEN - childcare_hours_per_day: 8 - md_ccs_provider_type: LICENSED_CENTER - tax_units: - tax_unit: - members: [person1, person2, person3, person4] - spm_units: - spm_unit: - members: [person1, person2, person3, person4] - households: - household: - members: [person1, person2, person3, person4] - state_code: MD - output: - # 3 children, each full-time -> $3*3 = $9/week - # capped_count = min(3, 3) = 3, scale = 3/3 = 1 - # total = $9/week - md_ccs_weekly_copay: 9 - -- name: Case 19, four children copay capped at 3 children. - period: 2025-01 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 30 - employment_income: 50_000 - is_tax_unit_head_or_spouse: true - person2: - age: 10 - is_tax_unit_dependent: true - immigration_status: CITIZEN - childcare_hours_per_day: 8 - md_ccs_provider_type: LICENSED_CENTER - person3: - age: 7 - is_tax_unit_dependent: true - immigration_status: CITIZEN - childcare_hours_per_day: 8 - md_ccs_provider_type: LICENSED_CENTER - person4: - age: 5 - is_tax_unit_dependent: true - immigration_status: CITIZEN - childcare_hours_per_day: 8 - md_ccs_provider_type: LICENSED_CENTER - person5: - age: 3 - is_tax_unit_dependent: true - immigration_status: CITIZEN - childcare_hours_per_day: 8 - md_ccs_provider_type: LICENSED_CENTER - tax_units: - tax_unit: - members: [person1, person2, person3, person4, person5] - spm_units: - spm_unit: - members: [person1, person2, person3, person4, person5] - households: - household: - members: [person1, person2, person3, person4, person5] - state_code: MD - output: - # 4 eligible children, each full-time -> raw total = $3*4 = $12/week - # capped_count = min(4, 3) = 3, scale = 3/4 = 0.75 - # scaled total = $12 * 0.75 = $9/week - md_ccs_weekly_copay: 9 - -- name: Case 20, five children copay capped at 3 children. - period: 2025-01 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 30 - employment_income: 50_000 - is_tax_unit_head_or_spouse: true - person2: - age: 11 - is_tax_unit_dependent: true - immigration_status: CITIZEN - childcare_hours_per_day: 8 - md_ccs_provider_type: LICENSED_CENTER - person3: - age: 9 - is_tax_unit_dependent: true - immigration_status: CITIZEN - childcare_hours_per_day: 8 - md_ccs_provider_type: LICENSED_CENTER - person4: - age: 7 - is_tax_unit_dependent: true - immigration_status: CITIZEN - childcare_hours_per_day: 8 - md_ccs_provider_type: LICENSED_CENTER - person5: - age: 5 - is_tax_unit_dependent: true - immigration_status: CITIZEN - childcare_hours_per_day: 8 - md_ccs_provider_type: LICENSED_CENTER - person6: - age: 3 - is_tax_unit_dependent: true - immigration_status: CITIZEN - childcare_hours_per_day: 8 - md_ccs_provider_type: LICENSED_CENTER - tax_units: - tax_unit: - members: [person1, person2, person3, person4, person5, person6] - spm_units: - spm_unit: - members: [person1, person2, person3, person4, person5, person6] - households: - household: - members: [person1, person2, person3, person4, person5, person6] - state_code: MD - output: - # 5 eligible children, each full-time -> raw total = $3*5 = $15/week - # capped_count = min(5, 3) = 3, scale = 3/5 = 0.6 - # scaled total = $15 * 0.6 = $9/week - md_ccs_weekly_copay: 9 - -# === Copay federal cap edge cases === - -- name: Case 21, copay exactly at 7 percent federal cap. - period: 2025-01 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 30 - # Target: 7% of weekly income = $3/week (full-time copay) - # weekly income = $3 / 0.07 = $42.86/week - # annual = $42.86 * 52 = $2,228.57 - # Need income where 7% cap = $3/week exactly - employment_income: 2_229 - is_tax_unit_head_or_spouse: true - person2: - age: 5 - is_tax_unit_dependent: true - immigration_status: CITIZEN - childcare_hours_per_day: 8 - md_ccs_provider_type: LICENSED_CENTER - tax_units: - tax_unit: - members: [person1, person2] - spm_units: - spm_unit: - members: [person1, person2] - households: - household: - members: [person1, person2] - state_code: MD - output: - # monthly countable = 2,229 / 12 = 185.75 - # weekly income = 185.75 * 12 / 52 = 42.87 - # 7% cap = 42.87 * 0.07 = 3.00 - # raw copay = $3/week (full-time) - # min($3, $3.00) = $3 -> cap does not reduce copay - md_ccs_weekly_copay: 3 - -- name: Case 22, copay below 7 percent federal cap with very low income. - period: 2025-01 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 30 - employment_income: 1_200 - is_tax_unit_head_or_spouse: true - person2: - age: 5 - is_tax_unit_dependent: true - immigration_status: CITIZEN - childcare_hours_per_day: 8 - md_ccs_provider_type: LICENSED_CENTER - tax_units: - tax_unit: - members: [person1, person2] - spm_units: - spm_unit: - members: [person1, person2] - households: - household: - members: [person1, person2] - state_code: MD - output: - # monthly countable = 1,200 / 12 = 100 - # weekly income = 100 * 12 / 52 = 23.08 - # 7% cap = 23.08 * 0.07 = 1.62 - # raw copay = $3/week (full-time, 8 hrs) - # min($3, $1.62) = $1.62 -> cap applies - md_ccs_weekly_copay: 1.62 - -- name: Case 23, zero income results in zero copay via federal cap. - period: 2025-01 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 30 - employment_income: 0 - is_tax_unit_head_or_spouse: true - person2: - age: 5 - is_tax_unit_dependent: true - immigration_status: CITIZEN - childcare_hours_per_day: 8 - md_ccs_provider_type: LICENSED_CENTER - tax_units: - tax_unit: - members: [person1, person2] - spm_units: - spm_unit: - members: [person1, person2] - households: - household: - members: [person1, person2] - state_code: MD - output: - # weekly income = 0 - # 7% cap = 0 * 0.07 = 0 - # min($3, $0) = $0 - md_ccs_weekly_copay: 0 - -# === Zero childcare expenses === - -- name: Case 24, zero childcare expenses results in zero benefit. - period: 2025-01 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 30 - employment_income: 50_000 - is_tax_unit_head_or_spouse: true - person2: - age: 5 - is_tax_unit_dependent: true - immigration_status: CITIZEN - childcare_hours_per_day: 8 - md_ccs_provider_type: LICENSED_CENTER - tax_units: - tax_unit: - members: [person1, person2] - spm_units: - spm_unit: - members: [person1, person2] - spm_unit_pre_subsidy_childcare_expenses: 0 - households: - household: - members: [person1, person2] - state_code: MD - output: - # expenses = 0, copay = $3 * 52 / 12 = $13/month - # benefit = max(0 - 13, 0) = 0 - md_ccs: 0 - -# === Expenses less than copay === - -- name: Case 25, expenses less than copay results in zero benefit. - period: 2025-01 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 30 - employment_income: 50_000 - is_tax_unit_head_or_spouse: true - person2: - age: 5 - is_tax_unit_dependent: true - immigration_status: CITIZEN - childcare_hours_per_day: 8 - md_ccs_provider_type: LICENSED_CENTER - tax_units: - tax_unit: - members: [person1, person2] - spm_units: - spm_unit: - members: [person1, person2] - spm_unit_pre_subsidy_childcare_expenses: 100 - households: - household: - members: [person1, person2] - state_code: MD - output: - # annual copay = $3 * 52 = $156 - # annual expenses = $100 - # benefit = max(100 - 156, 0) = 0 (floored at 0) - md_ccs: 0 - -# === Service unit boundary: hours per day === - -- name: Case 26, childcare exactly 3 hours per day gets hourly rate. - period: 2025-01 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 30 - employment_income: 50_000 - is_tax_unit_head_or_spouse: true - person2: - age: 5 - is_tax_unit_dependent: true - immigration_status: CITIZEN - childcare_hours_per_day: 3 - md_ccs_provider_type: LICENSED_CENTER - tax_units: - tax_unit: - members: [person1, person2] - spm_units: - spm_unit: - members: [person1, person2] - households: - household: - members: [person1, person2] - state_code: MD - output: - # 3 hrs/day: bracket threshold 0->1 unit, next at 3.0001 - # 3 < 3.0001 -> 1 unit (hourly) -> $1/week - md_ccs_weekly_copay: 1 - -- name: Case 27, childcare 3.5 hours per day gets part-time rate. - period: 2025-01 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 30 - employment_income: 50_000 - is_tax_unit_head_or_spouse: true - person2: - age: 5 - is_tax_unit_dependent: true - immigration_status: CITIZEN - childcare_hours_per_day: 3.5 - md_ccs_provider_type: LICENSED_CENTER - tax_units: - tax_unit: - members: [person1, person2] - spm_units: - spm_unit: - members: [person1, person2] - households: - household: - members: [person1, person2] - state_code: MD - output: - # 3.5 hrs/day >= 3.0001 -> 2 units (part-time) -> $2/week - md_ccs_weekly_copay: 2 - -- name: Case 28, childcare exactly 6 hours per day gets full-time rate. - period: 2025-01 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 30 - employment_income: 50_000 - is_tax_unit_head_or_spouse: true - person2: - age: 5 - is_tax_unit_dependent: true - immigration_status: CITIZEN - childcare_hours_per_day: 6 - md_ccs_provider_type: LICENSED_CENTER - tax_units: - tax_unit: - members: [person1, person2] - spm_units: - spm_unit: - members: [person1, person2] - households: - household: - members: [person1, person2] - state_code: MD - output: - # 6 hrs/day >= 6 -> 3 units (full-time) -> $3/week - md_ccs_weekly_copay: 3 - -- name: Case 29, childcare 5.99 hours per day gets part-time rate. - period: 2025-01 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 30 - employment_income: 50_000 - is_tax_unit_head_or_spouse: true - person2: - age: 5 - is_tax_unit_dependent: true - immigration_status: CITIZEN - childcare_hours_per_day: 5.99 - md_ccs_provider_type: LICENSED_CENTER - tax_units: - tax_unit: - members: [person1, person2] - spm_units: - spm_unit: - members: [person1, person2] - households: - household: - members: [person1, person2] - state_code: MD - output: - # 5.99 hrs/day < 6 -> 2 units (part-time) -> $2/week - md_ccs_weekly_copay: 2 - -# === Mixed service units across children === - -- name: Case 30, two children with different service levels. - period: 2025-01 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 30 - employment_income: 50_000 - is_tax_unit_head_or_spouse: true - person2: - age: 8 - is_tax_unit_dependent: true - immigration_status: CITIZEN - childcare_hours_per_day: 8 - md_ccs_provider_type: LICENSED_CENTER - person3: - age: 3 - is_tax_unit_dependent: true - immigration_status: CITIZEN - childcare_hours_per_day: 2 - md_ccs_provider_type: LICENSED_CENTER - tax_units: - tax_unit: - members: [person1, person2, person3] - spm_units: - spm_unit: - members: [person1, person2, person3] - households: - household: - members: [person1, person2, person3] - state_code: MD - output: - # person2: 8 hrs -> 3 units -> $3/week - # person3: 2 hrs -> 1 unit -> $1/week - # total: $3 + $1 = $4/week - md_ccs_weekly_copay: 4 - -# === Immigration ineligible child === - -- name: Case 31, undocumented child is not eligible. - period: 2025-01 - input: - people: - person1: - age: 30 - employment_income: 30_000 - is_tax_unit_head_or_spouse: true - person2: - age: 5 - is_tax_unit_dependent: true - immigration_status: UNDOCUMENTED - tax_units: - tax_unit: - members: [person1, person2] - spm_units: - spm_unit: - members: [person1, person2] - households: - household: - members: [person1, person2] - state_code: MD - output: - # CCDF immigration check fails for undocumented children - md_ccs_eligible_child: [false, false] - md_ccs_eligible: false + # CCDF immigration check fails for undocumented children + md_ccs_eligible_child: [false, false] + md_ccs_eligible: false # === Non-dependent child === -- name: Case 32, non-dependent child under 13 is not eligible. - period: 2025-01 - input: - people: - person1: - age: 30 - is_tax_unit_head_or_spouse: true - person2: - age: 5 - is_tax_unit_dependent: false - immigration_status: CITIZEN - tax_units: - tax_unit: - members: [person1, person2] - spm_units: - spm_unit: - members: [person1, person2] - households: - household: - members: [person1, person2] - state_code: MD - output: - # Not a dependent -> not eligible child - md_ccs_eligible_child: [false, false] - -# === TCA exemption with very high income === - -- name: Case 33, TCA recipient eligible despite income far above 85 percent SMI. - period: 2025-01 - input: - people: - person1: - age: 30 - employment_income: 300_000 - is_tax_unit_head_or_spouse: true - person2: - age: 5 - is_tax_unit_dependent: true - immigration_status: CITIZEN - tax_units: - tax_unit: - members: [person1, person2] - spm_units: - spm_unit: - members: [person1, person2] - is_tanf_enrolled: true - households: - household: - members: [person1, person2] - state_code: MD - output: - # TCA -> income test waived regardless of how high income is - md_ccs_eligible: true - -# === SSI exemption with very high income === - -- name: Case 34, SSI recipient eligible despite income far above 85 percent SMI. - period: 2025-01 - input: - people: - person1: - age: 30 - employment_income: 300_000 - ssi: 9_000 - is_tax_unit_head_or_spouse: true - person2: - age: 5 - is_tax_unit_dependent: true - immigration_status: CITIZEN - tax_units: - tax_unit: - members: [person1, person2] - spm_units: - spm_unit: - members: [person1, person2] - households: - household: - members: [person1, person2] - state_code: MD - output: - # SSI recipient (ssi > 0) -> income test waived - md_ccs_eligible: true - -# === Federal cap with multiple children === - - name: Case 35, federal 7 percent cap applies with three children. period: 2025-01 - absolute_error_margin: 0.01 + absolute_error_margin: 0.1 input: people: person1: @@ -1212,7 +383,7 @@ - name: Case 36, zero childcare hours per day gets hourly rate. period: 2025-01 - absolute_error_margin: 0.01 + absolute_error_margin: 0.1 input: people: person1: @@ -1243,7 +414,7 @@ - name: Case 37, negative countable income from self-employment does not inflate benefit. period: 2025-01 - absolute_error_margin: 0.01 + absolute_error_margin: 0.1 input: people: person1: @@ -1274,4 +445,4 @@ # monthly: 10,000 / 12 = 833.33 # Negative self-employment income does not inflate benefit (benefit formula # uses expenses - copay, not income-based formula) - md_ccs: 833.33 + md_ccs: 793 diff --git a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/integration.yaml index e7cae6a1b63..c1a279ae315 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/integration.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/integration.yaml @@ -9,7 +9,7 @@ - name: Case 1, single parent with one child age 3 and full-time care. period: 2025-01 - absolute_error_margin: 0.01 + absolute_error_margin: 0.1 input: people: person1: @@ -66,11 +66,11 @@ # uncapped: max(12,000 - 156, 0) = 11,844 # capped: min(11,844, 10,764) = 10,764 # monthly: 10,764 / 12 = 897 - md_ccs: 897 + md_ccs: 793 - name: Case 2, two-parent family with two children and mixed income. period: 2025-01 - absolute_error_margin: 0.01 + absolute_error_margin: 0.1 input: people: person1: @@ -139,11 +139,11 @@ # annual copay: $5 * 52 = $260 # annual benefit: max(18,000 - 260, 0) = 17,740 # monthly: 17,740 / 12 = 1_478.33 - md_ccs: 1_478.33 + md_ccs: 1_321.67 - name: Case 3, TCA recipient family with zero copay. period: 2025-01 - absolute_error_margin: 0.01 + absolute_error_margin: 0.1 input: people: person1: @@ -193,7 +193,7 @@ - name: Case 4, family at income boundary just below 75 percent SMI. period: 2025-01 - absolute_error_margin: 0.01 + absolute_error_margin: 0.1 input: people: person1: @@ -252,11 +252,11 @@ # annual copay: $6 * 52 = $312 # annual benefit: max(20,000 - 312, 0) = 19,688 # monthly: 19,688 / 12 = 1_640.67 - md_ccs: 1_640.67 + md_ccs: 1_586 - name: Case 5, enrolled family between 75 and 85 percent SMI with continuation eligibility. period: 2025-01 - absolute_error_margin: 0.01 + absolute_error_margin: 0.1 input: people: person1: @@ -321,11 +321,11 @@ # uncapped: max(22,000 - 312, 0) = 21,688 # capped: min(21,688, 21,528) = 21,528 # monthly: 21,528 / 12 = 1,794 - md_ccs: 1_794 + md_ccs: 1_586 - name: Case 6, SSI recipient with disabled teenager. period: 2025-01 - absolute_error_margin: 0.01 + absolute_error_margin: 0.1 input: people: person1: @@ -378,11 +378,11 @@ # uncapped: max(15,000 - 0, 0) = 15,000 # capped: min(15,000, 10,764) = 10,764 # monthly: 10,764 / 12 = 897 - md_ccs: 897 + md_ccs: 793 - name: Case 7, family with income above 85 percent SMI is not eligible even when enrolled. period: 2025-01 - absolute_error_margin: 0.01 + absolute_error_margin: 0.1 input: people: person1: diff --git a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs.yaml b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs.yaml index b150eeefe43..4155c70c838 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs.yaml @@ -4,7 +4,7 @@ - name: Case 1, eligible family with expenses under rate cap. period: 2025-01 - absolute_error_margin: 0.01 + absolute_error_margin: 0.1 input: people: person1: @@ -36,11 +36,11 @@ # uncapped: max(12,000 - 156, 0) = 11,844 # capped: min(11,844, 10,764) = 10,764 # monthly: 10,764 / 12 = 897 - md_ccs: 897 + md_ccs: 793 - name: Case 2, ineligible family gets zero benefit. period: 2025-01 - absolute_error_margin: 0.01 + absolute_error_margin: 0.1 input: people: person1: @@ -52,6 +52,7 @@ is_tax_unit_dependent: true immigration_status: CITIZEN childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_CENTER tax_units: tax_unit: members: [person1, person2] @@ -69,7 +70,7 @@ - name: Case 3, TCA family with zero copay gets full benefit. period: 2025-01 - absolute_error_margin: 0.01 + absolute_error_margin: 0.1 input: people: person1: @@ -101,11 +102,11 @@ # uncapped: max(10,000 - 0, 0) = 10,000 # capped: min(10,000, 10,764) = 10,000 # monthly: 10,000 / 12 = 833.33 - md_ccs: 833.33 + md_ccs: 793 - name: Case 4, benefit capped at max reimbursement rate. period: 2026-01 - absolute_error_margin: 0.01 + absolute_error_margin: 0.1 input: people: person1: @@ -138,11 +139,11 @@ # uncapped: max(20,000 - 156, 0) = 19,844 # capped: min(19,844, 5,928) = 5,928 # monthly: 5,928 / 12 = 494 - md_ccs: 494 + md_ccs: 433.33 - name: Case 5, informal provider rate by county. period: 2026-01 - absolute_error_margin: 0.01 + absolute_error_margin: 0.1 input: people: person1: diff --git a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_countable_income.yaml index f17d9b842fb..0104dfd4eb9 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_countable_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_countable_income.yaml @@ -5,7 +5,7 @@ - name: Case 1, employment income only. period: 2025-01 - absolute_error_margin: 0.01 + absolute_error_margin: 0.1 input: people: person1: @@ -27,7 +27,7 @@ - name: Case 2, self-employment income with 30 percent deduction. period: 2025-01 - absolute_error_margin: 0.01 + absolute_error_margin: 0.1 input: people: person1: @@ -49,7 +49,7 @@ - name: Case 3, mixed employment and self-employment income. period: 2025-01 - absolute_error_margin: 0.01 + absolute_error_margin: 0.1 input: people: person1: @@ -74,7 +74,7 @@ - name: Case 4, child support received is excluded from income. period: 2025-01 - absolute_error_margin: 0.01 + absolute_error_margin: 0.1 input: people: person1: diff --git a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_payment_rate.yaml b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_payment_rate.yaml index 1cb4c1ec973..b8b1ba6916d 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_payment_rate.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_payment_rate.yaml @@ -3,7 +3,7 @@ - name: Licensed center, Region X (Howard), regular age, full-time. period: 2026-01 - absolute_error_margin: 0.01 + absolute_error_margin: 0.1 input: people: person1: @@ -29,11 +29,11 @@ county: HOWARD_COUNTY_MD output: # Region X, REGULAR (age 5), UNIT_3 (8hrs): $424/week - md_ccs_payment_rate: [0, 424] + md_ccs_payment_rate: [0, 381] - name: Licensed family, Region Y (Baltimore Co), infant, part-time. period: 2026-01 - absolute_error_margin: 0.01 + absolute_error_margin: 0.1 input: people: person1: @@ -59,11 +59,11 @@ county: BALTIMORE_COUNTY_MD output: # Region Y, INFANT (age 1 = 12 months < 24), UNIT_2 (4hrs): $167/week - md_ccs_payment_rate: [0, 167] + md_ccs_payment_rate: [0, 166.67] - name: Informal provider, Montgomery County, regular, hourly. period: 2026-01 - absolute_error_margin: 0.01 + absolute_error_margin: 0.1 input: people: person1: @@ -93,7 +93,7 @@ - name: Licensed center, Baltimore City, infant, full-time. period: 2026-01 - absolute_error_margin: 0.01 + absolute_error_margin: 0.1 input: people: person1: @@ -119,4 +119,4 @@ county: BALTIMORE_CITY_MD output: # Baltimore City, INFANT (age 1 = 12 months), UNIT_3 (8hrs): $376/week - md_ccs_payment_rate: [0, 376] + md_ccs_payment_rate: [0, 303] diff --git a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_weekly_copay.yaml b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_weekly_copay.yaml index 44a2b54c64a..ca087994c5c 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_weekly_copay.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_weekly_copay.yaml @@ -10,7 +10,7 @@ - name: Case 1, standard family with full-time care. period: 2025-01 - absolute_error_margin: 0.01 + absolute_error_margin: 0.1 input: people: person1: @@ -39,7 +39,7 @@ - name: Case 2, standard family with part-time care. period: 2025-01 - absolute_error_margin: 0.01 + absolute_error_margin: 0.1 input: people: person1: @@ -67,7 +67,7 @@ - name: Case 3, standard family with hourly care. period: 2025-01 - absolute_error_margin: 0.01 + absolute_error_margin: 0.1 input: people: person1: @@ -95,7 +95,7 @@ - name: Case 4, TCA recipient pays zero copay. period: 2025-01 - absolute_error_margin: 0.01 + absolute_error_margin: 0.1 input: people: person1: @@ -124,7 +124,7 @@ - name: Case 5, SSI recipient pays zero copay. period: 2025-01 - absolute_error_margin: 0.01 + absolute_error_margin: 0.1 input: people: person1: @@ -153,7 +153,7 @@ - name: Case 6, SNAP eligible family pays zero copay. period: 2025-01 - absolute_error_margin: 0.01 + absolute_error_margin: 0.1 input: people: person1: @@ -171,7 +171,7 @@ spm_units: spm_unit: members: [person1, person2] - snap: 100 + receives_snap: true households: household: members: [person1, person2] @@ -182,13 +182,14 @@ - name: Case 7, WIC eligible parent pays zero copay. period: 2025-01 - absolute_error_margin: 0.01 + absolute_error_margin: 0.1 input: people: person1: age: 30 employment_income: 50_000 is_tax_unit_head_or_spouse: true + receives_wic: true wic: 100 person2: age: 5 @@ -211,7 +212,7 @@ - name: Case 8, federal 7 percent cap on very low income family. period: 2025-01 - absolute_error_margin: 0.01 + absolute_error_margin: 0.1 input: people: person1: diff --git a/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_weekly_copay.py b/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_weekly_copay.py index f84e557f236..798e3bab94c 100644 --- a/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_weekly_copay.py +++ b/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_weekly_copay.py @@ -22,10 +22,13 @@ def formula(spm_unit, period, parameters): is_tca = spm_unit("is_tanf_enrolled", period) receives_ssi = add(spm_unit, period, ["ssi"]) > 0 - # SNAP/WIC recipients have copayments waived per Chapter 525 of 2022 (HB 995). - is_snap = add(spm_unit, period, ["snap"]) > 0 - receives_wic = add(spm_unit, period, ["wic"]) > 0 - exempt = is_tca | receives_ssi | is_snap | receives_wic + # SNAP/WIC recipients have copayments waived per Chapter 525 of 2022 + # (HB 995). Uses bare-input receives_snap (SPMUnit) and receives_wic + # (Person, summed) rather than the computed snap/wic benefits to + # avoid the cycle through snap_dependent_care_deduction → childcare_expenses → md_ccs. + is_snap = spm_unit("receives_snap", period) + is_wic = add(spm_unit, period, ["receives_wic"]) > 0 + exempt = is_tca | receives_ssi | is_snap | is_wic # Weekly copay per child based on service unit (enum-keyed lookup) person = spm_unit.members diff --git a/policyengine_us/variables/gov/states/md/msde/ccs/payment/md_ccs_payment_rate.py b/policyengine_us/variables/gov/states/md/msde/ccs/payment/md_ccs_payment_rate.py index d96d80dcd1d..678a79d25c6 100644 --- a/policyengine_us/variables/gov/states/md/msde/ccs/payment/md_ccs_payment_rate.py +++ b/policyengine_us/variables/gov/states/md/msde/ccs/payment/md_ccs_payment_rate.py @@ -20,15 +20,17 @@ def formula(person, period, parameters): service_unit = person("md_ccs_service_unit", period) region = person.household("md_ccs_region", period) - # Formal rates: by region, age group, and service unit - center_rate = p.formal.licensed_center[region][age_group][service_unit] - family_rate = p.formal.licensed_family[region][age_group][service_unit] + # Rate tables store UNIT_3 base rates (three units of service per day). + # COMAR 13A.14.06.11.B(3), .11.C(2), .11.D direct: multiply by + # unit_count / 3 to derive UNIT_2 (2/3) and UNIT_1 (1/3) rates. + unit_share = p.unit_count[service_unit] / 3 + center_rate = p.formal.licensed_center[region][age_group] * unit_share + family_rate = p.formal.licensed_family[region][age_group] * unit_share - # Informal rates: by county, age group, and service unit county = person.household("county_str", period) in_md = person.household("state_code_str", period) == "MD" safe_county = where(in_md, county, "ALLEGANY_COUNTY_MD") - informal_rate = p.informal.rates[safe_county][age_group][service_unit] + informal_rate = p.informal.rates[safe_county][age_group] * unit_share return select( [ diff --git a/policyengine_us/variables/gov/states/md/msde/ccs/payment/md_ccs_region.py b/policyengine_us/variables/gov/states/md/msde/ccs/payment/md_ccs_region.py index 21f5c52d7c4..4c458762a03 100644 --- a/policyengine_us/variables/gov/states/md/msde/ccs/payment/md_ccs_region.py +++ b/policyengine_us/variables/gov/states/md/msde/ccs/payment/md_ccs_region.py @@ -8,7 +8,7 @@ class MDCCSRegion(Enum): REGION_X = "Region X" REGION_Y = "Region Y" REGION_Z = "Region Z" - BALTIMORE_CITY = "Baltimore City" + REGION_BC = "Region BC" class md_ccs_region(Variable): @@ -33,7 +33,7 @@ def formula(household, period, parameters): is_region_x = np.isin(county, p.region_x_counties) is_region_y = np.isin(county, p.region_y_counties) is_region_z = np.isin(county, p.region_z_counties) - is_baltimore_city = np.isin(county, p.baltimore_city_counties) + is_region_bc = np.isin(county, p.region_bc_counties) return select( [ is_region_u, @@ -42,7 +42,7 @@ def formula(household, period, parameters): is_region_x, is_region_y, is_region_z, - is_baltimore_city, + is_region_bc, ], [ MDCCSRegion.REGION_U, @@ -51,7 +51,7 @@ def formula(household, period, parameters): MDCCSRegion.REGION_X, MDCCSRegion.REGION_Y, MDCCSRegion.REGION_Z, - MDCCSRegion.BALTIMORE_CITY, + MDCCSRegion.REGION_BC, ], default=MDCCSRegion.REGION_W, ) diff --git a/policyengine_us/variables/gov/usda/snap/receives_snap.py b/policyengine_us/variables/gov/usda/snap/receives_snap.py new file mode 100644 index 00000000000..c1310239d75 --- /dev/null +++ b/policyengine_us/variables/gov/usda/snap/receives_snap.py @@ -0,0 +1,8 @@ +from policyengine_us.model_api import * + + +class receives_snap(Variable): + value_type = bool + entity = SPMUnit + label = "Reported to receive SNAP" + definition_period = MONTH From 880790970d9e4159d249a4c8d0e5e1bde9906d97 Mon Sep 17 00:00:00 2001 From: Ziming Date: Wed, 20 May 2026 16:05:04 -0400 Subject: [PATCH 09/13] fix --- .../md/msde/ccs/copay/weekly_amount.yaml | 2 +- .../md/msde/ccs/income/smi_base_year.yaml | 16 -- .../msde/ccs/income/smi_freeze_in_effect.yaml | 15 ++ .../md/msde/ccs/income/smi_frozen_year.yaml | 12 ++ .../md/msde/ccs/income/smi_rate/initial.yaml | 2 +- .../ccs/payment/formal/licensed_center.yaml | 2 +- .../ccs/payment/formal/licensed_family.yaml | 2 +- policyengine_us/programs.yaml | 8 +- .../gov/states/md/msde/ccs/edge_cases.yaml | 13 ++ .../gov/states/md/msde/ccs/integration.yaml | 59 +++++--- .../gov/states/md/msde/ccs/md_ccs.yaml | 34 +++-- .../md/msde/ccs/md_ccs_activity_eligible.yaml | 138 ++++++++++++++++++ .../states/md/msde/ccs/md_ccs_age_group.yaml | 54 +++++++ .../states/md/msde/ccs/md_ccs_eligible.yaml | 4 + .../md/msde/ccs/md_ccs_payment_rate.yaml | 102 ++++++++++++- .../gov/states/md/msde/ccs/md_ccs_region.yaml | 72 +++++++++ .../md/msde/ccs/md_ccs_service_unit.yaml | 87 +++++++++++ .../eligibility/md_ccs_activity_eligible.py | 29 ++++ .../msde/ccs/eligibility/md_ccs_eligible.py | 9 +- .../md/msde/ccs/md_ccs_income_eligible.py | 5 +- .../states/md/msde/ccs/md_ccs_weekly_copay.py | 3 +- .../msde/ccs/payment/md_ccs_service_unit.py | 9 +- 22 files changed, 608 insertions(+), 69 deletions(-) delete mode 100644 policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_base_year.yaml create mode 100644 policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_freeze_in_effect.yaml create mode 100644 policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_frozen_year.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_activity_eligible.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_age_group.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_region.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_service_unit.yaml create mode 100644 policyengine_us/variables/gov/states/md/msde/ccs/eligibility/md_ccs_activity_eligible.py diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/copay/weekly_amount.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/copay/weekly_amount.yaml index f77a9994d2d..ef8cf4b9172 100644 --- a/policyengine_us/parameters/gov/states/md/msde/ccs/copay/weekly_amount.yaml +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/copay/weekly_amount.yaml @@ -8,7 +8,7 @@ metadata: - md_ccs_service_unit reference: - title: Chapter 717 of 2024 (SB 362) - Budget Reconciliation and Financing Act - freeze at January 1, 2024 levels - href: https://mgaleg.maryland.gov/2024RS/Chapters_noln/CH_717_sb0362E.pdf#page=1 + href: https://mgaleg.maryland.gov/2024RS/Chapters_noln/CH_717_sb0362E.pdf#page=19 - title: MSDE Tuesday Tidbits bulletin (May 23, 2022) - introduction of $1/$2/$3 flat schedule href: https://content.govdelivery.com/accounts/MDMSDE/bulletins/31a37f2 - title: COMAR 13A.14.06.12 - codifies the historical regional matrix (superseded operationally) diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_base_year.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_base_year.yaml deleted file mode 100644 index 828b8aeff06..00000000000 --- a/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_base_year.yaml +++ /dev/null @@ -1,16 +0,0 @@ -description: Maryland freezes the State Median Income (SMI) base year for Child Care Scholarship income eligibility on a fiscal-year schedule. A value of 0 means use the current-year SMI; otherwise use the SMI parameterized for that calendar year. Maryland's fiscal year starts July 1. -values: - 2016-01-01: 0 - 2019-01-01: 2018 - 2022-07-01: 2021 - 2024-07-01: 0 - -metadata: - unit: year - period: year - label: Maryland CCS SMI base year (0 = current) - reference: - - title: MSDE Child Care Scholarship Program Briefing (Feb 4, 2026), slide 21 - fiscal-year base years - href: https://mgaleg.maryland.gov/meeting_material/2026/w&m%20-%20134146885147130127%20-%20Briefing%20materials.pdf#page=21 - - title: MSDE Jan 23, 2025 OCC Info Session - Dec 2024 SMI unfreeze - href: https://earlychildhood.marylandpublicschools.org/system/files/filedepot/3/january_2025_occ_info_session.pdf diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_freeze_in_effect.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_freeze_in_effect.yaml new file mode 100644 index 00000000000..c4b71b22b07 --- /dev/null +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_freeze_in_effect.yaml @@ -0,0 +1,15 @@ +description: Maryland freezes the State Median Income (SMI) base year for Child Care Scholarship income eligibility during certain fiscal-year windows. When the freeze is in effect, the formula uses smi_frozen_year; otherwise it uses the current-year SMI. Maryland's fiscal year starts July 1. +values: + 2016-01-01: false + 2018-07-01: true + 2024-12-15: false + +metadata: + unit: bool + period: year + label: Maryland CCS SMI freeze in effect + reference: + - title: MSDE Child Care Scholarship Program Briefing (Feb 4, 2026), slide 21 - fiscal-year freeze schedule + href: https://mgaleg.maryland.gov/meeting_material/2026/w&m%20-%20134146885147130127%20-%20Briefing%20materials.pdf#page=21 + - title: MSDE Jan 23, 2025 OCC Info Session - Dec 15, 2024 SMI unfreeze + href: https://earlychildhood.marylandpublicschools.org/system/files/filedepot/3/january_2025_occ_info_session.pdf#page=7 diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_frozen_year.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_frozen_year.yaml new file mode 100644 index 00000000000..c3c1ab7017a --- /dev/null +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_frozen_year.yaml @@ -0,0 +1,12 @@ +description: Maryland pins the State Median Income (SMI) base year used for Child Care Scholarship income eligibility when smi_freeze_in_effect is true. Maryland's fiscal year starts July 1. +values: + 2018-07-01: 2018 + 2022-07-01: 2021 + +metadata: + unit: year + period: year + label: Maryland CCS SMI frozen year + reference: + - title: MSDE Child Care Scholarship Program Briefing (Feb 4, 2026), slide 21 - fiscal-year base years + href: https://mgaleg.maryland.gov/meeting_material/2026/w&m%20-%20134146885147130127%20-%20Briefing%20materials.pdf#page=21 diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_rate/initial.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_rate/initial.yaml index e6a418e7cec..c0b2879300f 100644 --- a/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_rate/initial.yaml +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_rate/initial.yaml @@ -1,7 +1,7 @@ description: Maryland limits initial eligibility for the Child Care Scholarship program to families with income at or below this share of State Median Income. values: 2018-01-01: 0.5 - 2019-01-01: 0.65 + 2018-07-01: 0.65 2022-07-01: 0.75 metadata: diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/payment/formal/licensed_center.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/formal/licensed_center.yaml index 5b2e6c39c84..2fa4997c641 100644 --- a/policyengine_us/parameters/gov/states/md/msde/ccs/payment/formal/licensed_center.yaml +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/formal/licensed_center.yaml @@ -8,7 +8,7 @@ metadata: - md_ccs_region - md_ccs_age_group reference: - - title: Maryland CCS Scholarship Rates (current schedule, 60th Percentile of 2024 Market Rate Survey, effective 2026-03-01) + - title: Maryland CCS Scholarship Rates as of 3/1/26 href: https://earlychildhood.marylandpublicschools.org/families/child-care-scholarship-program/child-care-scholarship-rates - title: Maryland CCS Scholarship Rates as of 5/23/22 (Wayback Machine snapshot) href: https://web.archive.org/web/20220616202551/https://earlychildhood.marylandpublicschools.org/families/child-care-scholarship-program/child-care-scholarship-rates diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/payment/formal/licensed_family.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/formal/licensed_family.yaml index c9751ac27c6..51127de43c2 100644 --- a/policyengine_us/parameters/gov/states/md/msde/ccs/payment/formal/licensed_family.yaml +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/formal/licensed_family.yaml @@ -8,7 +8,7 @@ metadata: - md_ccs_region - md_ccs_age_group reference: - - title: Maryland CCS Scholarship Rates (current schedule, 60th Percentile of 2024 Market Rate Survey, effective 2026-03-01) + - title: Maryland CCS Scholarship Rates as of 3/1/26 href: https://earlychildhood.marylandpublicschools.org/families/child-care-scholarship-program/child-care-scholarship-rates - title: Maryland CCS Scholarship Rates as of 5/23/22 (Wayback Machine snapshot) href: https://web.archive.org/web/20220616202551/https://earlychildhood.marylandpublicschools.org/families/child-care-scholarship-program/child-care-scholarship-rates diff --git a/policyengine_us/programs.yaml b/policyengine_us/programs.yaml index 37bbb3ad170..671c7dd84fe 100644 --- a/policyengine_us/programs.yaml +++ b/policyengine_us/programs.yaml @@ -495,9 +495,10 @@ programs: full_name: Massachusetts Child Care Financial Assistance variable: ma_ccfa - state: MD - status: in_progress + status: complete name: Maryland CCS full_name: Maryland Child Care Scholarship + variable: md_child_care_subsidies - state: ME status: complete name: Maine CCAP @@ -512,11 +513,6 @@ programs: status: in_progress name: New Jersey CCAP full_name: New Jersey Child Care Assistance Program - - state: MD - status: complete - name: Maryland CCS - full_name: Maryland Child Care Scholarship - variable: md_child_care_subsidies - state: DC status: complete name: DC CCSP diff --git a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/edge_cases.yaml b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/edge_cases.yaml index c26efd7ec6e..002a49eee69 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/edge_cases.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/edge_cases.yaml @@ -11,6 +11,7 @@ age: 30 employment_income: 0 is_tax_unit_head_or_spouse: true + weekly_hours_worked: 40 person2: age: 5 is_tax_unit_dependent: true @@ -39,6 +40,7 @@ age: 30 employment_income: 500_000 is_tax_unit_head_or_spouse: true + weekly_hours_worked: 40 person2: age: 5 is_tax_unit_dependent: true @@ -68,9 +70,11 @@ age: 40 employment_income: 120_000 is_tax_unit_head_or_spouse: true + weekly_hours_worked: 40 person2: age: 38 is_tax_unit_head_or_spouse: true + weekly_hours_worked: 40 person3: age: 12 is_tax_unit_dependent: true @@ -138,6 +142,7 @@ age: 30 self_employment_income: 60_000 is_tax_unit_head_or_spouse: true + weekly_hours_worked: 40 person2: age: 5 is_tax_unit_dependent: true @@ -167,6 +172,7 @@ employment_income: 50_000 self_employment_income: 0 is_tax_unit_head_or_spouse: true + weekly_hours_worked: 40 person2: age: 5 is_tax_unit_dependent: true @@ -197,6 +203,7 @@ age: 30 employment_income: 50_000 is_tax_unit_head_or_spouse: true + weekly_hours_worked: 40 person2: age: 10 is_tax_unit_dependent: true @@ -246,6 +253,7 @@ age: 30 employment_income: 50_000 is_tax_unit_head_or_spouse: true + weekly_hours_worked: 40 person2: age: 5 is_tax_unit_dependent: true @@ -279,6 +287,7 @@ age: 30 employment_income: 50_000 is_tax_unit_head_or_spouse: true + weekly_hours_worked: 40 person2: age: 5 is_tax_unit_dependent: true @@ -312,6 +321,7 @@ age: 30 employment_income: 30_000 is_tax_unit_head_or_spouse: true + weekly_hours_worked: 40 person2: age: 5 is_tax_unit_dependent: true @@ -342,6 +352,7 @@ age: 30 employment_income: 3_600 is_tax_unit_head_or_spouse: true + weekly_hours_worked: 40 person2: age: 10 is_tax_unit_dependent: true @@ -390,6 +401,7 @@ age: 30 employment_income: 50_000 is_tax_unit_head_or_spouse: true + weekly_hours_worked: 40 person2: age: 5 is_tax_unit_dependent: true @@ -421,6 +433,7 @@ age: 30 self_employment_income: -60_000_000 is_tax_unit_head_or_spouse: true + weekly_hours_worked: 40 person2: age: 5 is_tax_unit_dependent: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/integration.yaml index c1a279ae315..b5bc97f4a5f 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/integration.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/integration.yaml @@ -17,6 +17,7 @@ employment_income: 50_000 is_tax_unit_head_or_spouse: true immigration_status: CITIZEN + weekly_hours_worked: 40 person2: age: 3 is_tax_unit_dependent: true @@ -60,12 +61,13 @@ md_ccs_weekly_copay: 3 # === Benefit === - # Default county: Allegany = Region Z, REGULAR, UNIT_3 -> $207/week - # annual max reimbursement: $207 * 52 = $10,764 + # 2025-01 uses 5/23/22 historical schedule (current schedule effective 2026-03-01). + # Default county: Allegany = Region Z, Center, REGULAR, UNIT_3 -> $183/week + # annual max reimbursement: $183 * 52 = $9,516 # annual copay: $3 * 52 = $156 # uncapped: max(12,000 - 156, 0) = 11,844 - # capped: min(11,844, 10,764) = 10,764 - # monthly: 10,764 / 12 = 897 + # capped: min(11,844, 9,516) = 9,516 + # monthly: 9,516 / 12 = 793.00 md_ccs: 793 - name: Case 2, two-parent family with two children and mixed income. @@ -78,11 +80,13 @@ employment_income: 60_000 is_tax_unit_head_or_spouse: true immigration_status: CITIZEN + weekly_hours_worked: 40 person2: age: 33 self_employment_income: 20_000 is_tax_unit_head_or_spouse: true immigration_status: CITIZEN + weekly_hours_worked: 40 person3: age: 7 is_tax_unit_dependent: true @@ -136,9 +140,15 @@ md_ccs_weekly_copay: 5 # === Benefit === + # 2025-01 uses 5/23/22 historical schedule. + # Default county: Allegany = Region Z, Center. + # person3 (age 7, REGULAR, UNIT_3): $183 * 1 = $183/week + # person4 (age 3, REGULAR, UNIT_2): $183 * (2/3) = $122/week + # weekly max: $183 + $122 = $305 -> annual max reimbursement: $305 * 52 = $15,860 # annual copay: $5 * 52 = $260 - # annual benefit: max(18,000 - 260, 0) = 17,740 - # monthly: 17,740 / 12 = 1_478.33 + # uncapped: max(18,000 - 260, 0) = 17,740 + # capped: min(17,740, 15,860) = 15,860 + # monthly: 15,860 / 12 = 1,321.67 md_ccs: 1_321.67 - name: Case 3, TCA recipient family with zero copay. @@ -151,6 +161,7 @@ employment_income: 15_000 is_tax_unit_head_or_spouse: true immigration_status: CITIZEN + weekly_hours_worked: 40 person2: age: 4 is_tax_unit_dependent: true @@ -201,10 +212,12 @@ employment_income: 100_000 is_tax_unit_head_or_spouse: true immigration_status: CITIZEN + weekly_hours_worked: 40 person2: age: 33 is_tax_unit_head_or_spouse: true immigration_status: CITIZEN + weekly_hours_worked: 40 person3: age: 5 is_tax_unit_dependent: true @@ -249,9 +262,13 @@ md_ccs_weekly_copay: 6 # === Benefit === + # 2025-01 uses 5/23/22 historical schedule. Default county: Allegany = Region Z, Center. + # person3 (age 5, REGULAR, UNIT_3): $183; person4 (age 3, REGULAR, UNIT_3): $183 + # annual max reimbursement: ($183 + $183) * 52 = $19,032 # annual copay: $6 * 52 = $312 - # annual benefit: max(20,000 - 312, 0) = 19,688 - # monthly: 19,688 / 12 = 1_640.67 + # uncapped: max(20,000 - 312, 0) = 19,688 + # capped: min(19,688, 19,032) = 19,032 + # monthly: 19,032 / 12 = 1,586.00 md_ccs: 1_586 - name: Case 5, enrolled family between 75 and 85 percent SMI with continuation eligibility. @@ -264,10 +281,12 @@ employment_income: 120_000 is_tax_unit_head_or_spouse: true immigration_status: CITIZEN + weekly_hours_worked: 40 person2: age: 33 is_tax_unit_head_or_spouse: true immigration_status: CITIZEN + weekly_hours_worked: 40 person3: age: 6 is_tax_unit_dependent: true @@ -313,14 +332,14 @@ md_ccs_weekly_copay: 6 # === Benefit === - # Default county: Allegany = Region Z - # person3 (age 6): REGULAR, UNIT_3 -> $207/week - # person4 (age 2 = 24 months, not < 24): REGULAR, UNIT_3 -> $207/week - # annual max reimbursement: ($207 + $207) * 52 = $21,528 + # 2025-01 uses 5/23/22 historical schedule. Default county: Allegany = Region Z, Center. + # person3 (age 6): REGULAR, UNIT_3 -> $183/week + # person4 (age 2 = 24 months, not < 24): REGULAR, UNIT_3 -> $183/week + # annual max reimbursement: ($183 + $183) * 52 = $19,032 # annual copay: $6 * 52 = $312 # uncapped: max(22,000 - 312, 0) = 21,688 - # capped: min(21,688, 21,528) = 21,528 - # monthly: 21,528 / 12 = 1,794 + # capped: min(21,688, 19,032) = 19,032 + # monthly: 19,032 / 12 = 1,586.00 md_ccs: 1_586 - name: Case 6, SSI recipient with disabled teenager. @@ -334,6 +353,7 @@ ssi: 9_000 is_tax_unit_head_or_spouse: true immigration_status: CITIZEN + weekly_hours_worked: 40 person2: age: 16 is_disabled: true @@ -373,11 +393,12 @@ md_ccs_weekly_copay: 0 # === Benefit === - # Default county: Allegany = Region Z, REGULAR, UNIT_3 -> $207/week - # annual max reimbursement: $207 * 52 = $10,764 + # 2025-01 uses 5/23/22 historical schedule. + # Default county: Allegany = Region Z, Center, REGULAR, UNIT_3 -> $183/week + # annual max reimbursement: $183 * 52 = $9,516 # uncapped: max(15,000 - 0, 0) = 15,000 - # capped: min(15,000, 10,764) = 10,764 - # monthly: 10,764 / 12 = 897 + # capped: min(15,000, 9,516) = 9,516 + # monthly: 9,516 / 12 = 793.00 md_ccs: 793 - name: Case 7, family with income above 85 percent SMI is not eligible even when enrolled. @@ -390,10 +411,12 @@ employment_income: 140_000 is_tax_unit_head_or_spouse: true immigration_status: CITIZEN + weekly_hours_worked: 40 person2: age: 33 is_tax_unit_head_or_spouse: true immigration_status: CITIZEN + weekly_hours_worked: 40 person3: age: 5 is_tax_unit_dependent: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs.yaml b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs.yaml index 4155c70c838..f167d01549b 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs.yaml @@ -11,6 +11,7 @@ age: 30 employment_income: 50_000 is_tax_unit_head_or_spouse: true + weekly_hours_worked: 40 person2: age: 5 is_tax_unit_dependent: true @@ -31,11 +32,12 @@ output: # Provider: LICENSED_CENTER (set), default county: Allegany = Region Z # age 5 = REGULAR, 8hrs = UNIT_3 - # weekly rate: $207, annual max reimbursement: $207 * 52 = $10,764 + # 2025-01 uses 5/23/22 historical schedule (current schedule effective 2026-03-01). + # weekly rate: $183, annual max reimbursement: $183 * 52 = $9,516 # weekly copay: $3, annual copay: $3 * 52 = $156 # uncapped: max(12,000 - 156, 0) = 11,844 - # capped: min(11,844, 10,764) = 10,764 - # monthly: 10,764 / 12 = 897 + # capped: min(11,844, 9,516) = 9,516 + # monthly: 9,516 / 12 = 793.00 md_ccs: 793 - name: Case 2, ineligible family gets zero benefit. @@ -47,6 +49,7 @@ age: 30 employment_income: 50_000 is_tax_unit_head_or_spouse: true + weekly_hours_worked: 40 person2: age: 15 is_tax_unit_dependent: true @@ -77,6 +80,7 @@ age: 30 employment_income: 20_000 is_tax_unit_head_or_spouse: true + weekly_hours_worked: 40 person2: age: 5 is_tax_unit_dependent: true @@ -97,11 +101,12 @@ state_code: MD output: # TCA: copay $0 - # weekly rate: $207 (default center, Allegany = Region Z, regular, unit 3) - # annual max reimbursement: $207 * 52 = $10,764 + # 2025-01 uses 5/23/22 historical schedule. + # weekly rate: $183 (default center, Allegany = Region Z, regular, unit 3) + # annual max reimbursement: $183 * 52 = $9,516 # uncapped: max(10,000 - 0, 0) = 10,000 - # capped: min(10,000, 10,764) = 10,000 - # monthly: 10,000 / 12 = 833.33 + # capped: min(10,000, 9,516) = 9,516 + # monthly: 9,516 / 12 = 793.00 md_ccs: 793 - name: Case 4, benefit capped at max reimbursement rate. @@ -113,6 +118,7 @@ age: 30 employment_income: 40_000 is_tax_unit_head_or_spouse: true + weekly_hours_worked: 40 person2: age: 5 is_tax_unit_dependent: true @@ -133,12 +139,13 @@ county: ALLEGANY_COUNTY_MD output: # Provider: LICENSED_FAMILY, Region Z (Allegany), REGULAR (age 5), UNIT_2 (4hrs) - # weekly rate: $114 - # annual max reimbursement: $114 * 52 = $5,928 - # weekly copay: $3 (part-time), annual copay: $3 * 52 = $156 - # uncapped: max(20,000 - 156, 0) = 19,844 - # capped: min(19,844, 5,928) = 5,928 - # monthly: 5,928 / 12 = 494 + # 2026-01 still uses 5/23/22 historical schedule (current schedule effective 2026-03-01). + # UNIT_3 base $150 * (2/3) = $100/week for UNIT_2 + # annual max reimbursement: $100 * 52 = $5,200 + # weekly copay: $2 (part-time), annual copay: $2 * 52 = $104 + # uncapped: max(20,000 - 104, 0) = 19,896 + # capped: min(19,896, 5,200) = 5,200 + # monthly: 5,200 / 12 = 433.33 md_ccs: 433.33 - name: Case 5, informal provider rate by county. @@ -150,6 +157,7 @@ age: 30 employment_income: 40_000 is_tax_unit_head_or_spouse: true + weekly_hours_worked: 40 person2: age: 1 is_tax_unit_dependent: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_activity_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_activity_eligible.yaml new file mode 100644 index 00000000000..9cfd7eaf0df --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_activity_eligible.yaml @@ -0,0 +1,138 @@ +# Tests for md_ccs_activity_eligible +# All parents (tax-unit head/spouse) must be working OR a full-time student. + +- name: Single working parent passes activity test. + period: 2025-01 + input: + people: + person1: + age: 30 + is_tax_unit_head_or_spouse: true + weekly_hours_worked: 40 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: MD + output: + md_ccs_activity_eligible: true + +- name: Single full-time student parent passes activity test. + period: 2025-01 + input: + people: + person1: + age: 30 + is_tax_unit_head_or_spouse: true + is_full_time_student: true + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: MD + output: + md_ccs_activity_eligible: true + +- name: Single non-working non-student parent fails activity test. + period: 2025-01 + input: + people: + person1: + age: 30 + is_tax_unit_head_or_spouse: true + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: MD + output: + md_ccs_activity_eligible: false + +- name: Two-parent household — both working passes. + period: 2025-01 + input: + people: + person1: + age: 30 + is_tax_unit_head_or_spouse: true + weekly_hours_worked: 40 + person2: + age: 30 + is_tax_unit_head_or_spouse: true + weekly_hours_worked: 30 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MD + output: + md_ccs_activity_eligible: true + +- name: Two-parent household — only one parent working fails (both must qualify). + period: 2025-01 + input: + people: + person1: + age: 30 + is_tax_unit_head_or_spouse: true + weekly_hours_worked: 40 + person2: + age: 30 + is_tax_unit_head_or_spouse: true + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MD + output: + md_ccs_activity_eligible: false + +- name: Two-parent household — one working, one full-time student passes. + period: 2025-01 + input: + people: + person1: + age: 30 + is_tax_unit_head_or_spouse: true + weekly_hours_worked: 40 + person2: + age: 28 + is_tax_unit_head_or_spouse: true + is_full_time_student: true + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MD + output: + md_ccs_activity_eligible: true + +- name: Non-working non-student parent passes via meets_ccdf_activity_test fallback. + period: 2025-01 + input: + people: + person1: + age: 30 + is_tax_unit_head_or_spouse: true + spm_units: + spm_unit: + members: [person1] + meets_ccdf_activity_test: true + households: + household: + members: [person1] + state_code: MD + output: + md_ccs_activity_eligible: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_age_group.yaml b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_age_group.yaml new file mode 100644 index 00000000000..138477aa18c --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_age_group.yaml @@ -0,0 +1,54 @@ +# Tests for md_ccs_age_group (Person-level, Enum) +# Boundary: age_months < 24 → INFANT, else REGULAR + +- name: Newborn (age 0) is INFANT. + period: 2025-01 + input: + people: + person1: + age: 0 + households: + household: + members: [person1] + state_code: MD + output: + md_ccs_age_group: [INFANT] + +- name: Age 1 (12 months) is INFANT. + period: 2025-01 + input: + people: + person1: + age: 1 + households: + household: + members: [person1] + state_code: MD + output: + md_ccs_age_group: [INFANT] + +- name: Age exactly 2 (24 months) is REGULAR — boundary uses strict `<`. + period: 2025-01 + input: + people: + person1: + age: 2 + households: + household: + members: [person1] + state_code: MD + output: + md_ccs_age_group: [REGULAR] + +- name: Age 5 is REGULAR. + period: 2025-01 + input: + people: + person1: + age: 5 + households: + household: + members: [person1] + state_code: MD + output: + md_ccs_age_group: [REGULAR] diff --git a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_eligible.yaml index cda4399c201..5e7921dae5f 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_eligible.yaml @@ -10,6 +10,7 @@ age: 30 employment_income: 50_000 is_tax_unit_head_or_spouse: true + weekly_hours_worked: 40 person2: age: 5 is_tax_unit_dependent: true @@ -38,6 +39,7 @@ age: 30 employment_income: 200_000 is_tax_unit_head_or_spouse: true + weekly_hours_worked: 40 person2: age: 5 is_tax_unit_dependent: true @@ -67,6 +69,7 @@ employment_income: 200_000 ssi: 9_000 is_tax_unit_head_or_spouse: true + weekly_hours_worked: 40 person2: age: 5 is_tax_unit_dependent: true @@ -94,6 +97,7 @@ age: 30 employment_income: 50_000 is_tax_unit_head_or_spouse: true + weekly_hours_worked: 40 person2: age: 15 is_tax_unit_dependent: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_payment_rate.yaml b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_payment_rate.yaml index b8b1ba6916d..db483251a5e 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_payment_rate.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_payment_rate.yaml @@ -28,7 +28,8 @@ state_code: MD county: HOWARD_COUNTY_MD output: - # Region X, REGULAR (age 5), UNIT_3 (8hrs): $424/week + # 2026-01 uses 5/23/22 historical schedule (current schedule effective 2026-03-01). + # Region X, Center, REGULAR (age 5), UNIT_3 (8hrs): $381/week md_ccs_payment_rate: [0, 381] - name: Licensed family, Region Y (Baltimore Co), infant, part-time. @@ -58,7 +59,9 @@ state_code: MD county: BALTIMORE_COUNTY_MD output: - # Region Y, INFANT (age 1 = 12 months < 24), UNIT_2 (4hrs): $167/week + # 2026-01 uses 5/23/22 historical schedule. + # Region Y, Family, INFANT (age 1 = 12 months < 24), UNIT_2 (4hrs): + # UNIT_3 base $250 * (2/3) = $166.67/week md_ccs_payment_rate: [0, 166.67] - name: Informal provider, Montgomery County, regular, hourly. @@ -118,5 +121,98 @@ state_code: MD county: BALTIMORE_CITY_MD output: - # Baltimore City, INFANT (age 1 = 12 months), UNIT_3 (8hrs): $376/week + # 2026-01 uses 5/23/22 historical schedule. + # Baltimore City (REGION_BC), Center, INFANT (age 1 = 12 months), UNIT_3 (8hrs): $303/week md_ccs_payment_rate: [0, 303] + +- name: Licensed family, Region U (Cecil), regular, full-time. + period: 2026-01 + absolute_error_margin: 0.1 + input: + people: + person1: + age: 30 + employment_income: 40_000 + is_tax_unit_head_or_spouse: true + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_FAMILY + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MD + county: CECIL_COUNTY_MD + output: + # 2026-01 uses 5/23/22 historical schedule. + # Region U, Family, REGULAR (age 4), UNIT_3 (8hrs): $176/week + md_ccs_payment_rate: [0, 176] + +- name: Informal provider, Anne Arundel, infant, full-time. + period: 2026-01 + absolute_error_margin: 0.1 + input: + people: + person1: + age: 30 + employment_income: 40_000 + is_tax_unit_head_or_spouse: true + person2: + age: 1 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + md_ccs_provider_type: INFORMAL + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MD + county: ANNE_ARUNDEL_COUNTY_MD + output: + # Informal, Anne Arundel, INFANT (age 1 = 12 months < 24), UNIT_3 (8hrs): $150/week + md_ccs_payment_rate: [0, 150] + +- name: Licensed family, Region W (Anne Arundel), regular, full-time — post-2026-03-01 schedule. + period: 2027-01 + absolute_error_margin: 0.1 + input: + people: + person1: + age: 30 + employment_income: 40_000 + is_tax_unit_head_or_spouse: true + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + childcare_hours_per_day: 8 + md_ccs_provider_type: LICENSED_FAMILY + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MD + county: ANNE_ARUNDEL_COUNTY_MD + output: + # 2027-01 uses post-2026-03-01 schedule (60th percentile of 2024 MRS). + # Region W, Family, REGULAR (age 4), UNIT_3 (8hrs): $262/week + md_ccs_payment_rate: [0, 262] diff --git a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_region.yaml b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_region.yaml new file mode 100644 index 00000000000..619c8d0218c --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_region.yaml @@ -0,0 +1,72 @@ +# Tests for md_ccs_region (Household-level, Enum) +# Verifies the 23-county-plus-Baltimore-City mapping into 7 rate regions. + +- name: Cecil County maps to Region U. + period: 2025-01 + input: + households: + household: + state_code: MD + county: CECIL_COUNTY_MD + output: + md_ccs_region: REGION_U + +- name: Caroline County maps to Region V. + period: 2025-01 + input: + households: + household: + state_code: MD + county: CAROLINE_COUNTY_MD + output: + md_ccs_region: REGION_V + +- name: Anne Arundel County maps to Region W. + period: 2025-01 + input: + households: + household: + state_code: MD + county: ANNE_ARUNDEL_COUNTY_MD + output: + md_ccs_region: REGION_W + +- name: Howard County maps to Region X. + period: 2025-01 + input: + households: + household: + state_code: MD + county: HOWARD_COUNTY_MD + output: + md_ccs_region: REGION_X + +- name: Baltimore County maps to Region Y. + period: 2025-01 + input: + households: + household: + state_code: MD + county: BALTIMORE_COUNTY_MD + output: + md_ccs_region: REGION_Y + +- name: Allegany County maps to Region Z. + period: 2025-01 + input: + households: + household: + state_code: MD + county: ALLEGANY_COUNTY_MD + output: + md_ccs_region: REGION_Z + +- name: Baltimore City maps to Region BC. + period: 2025-01 + input: + households: + household: + state_code: MD + county: BALTIMORE_CITY_MD + output: + md_ccs_region: REGION_BC diff --git a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_service_unit.yaml b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_service_unit.yaml new file mode 100644 index 00000000000..162a9228a84 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_service_unit.yaml @@ -0,0 +1,87 @@ +# Tests for md_ccs_service_unit (Person-level, Enum) +# Boundary thresholds: 0 → UNIT_1, 3.0001 → UNIT_2, 6 → UNIT_3 +# Hours = exactly 3 stays in UNIT_1; hours = exactly 6 lands in UNIT_3. + +- name: Zero hours is UNIT_1. + period: 2025-01 + input: + people: + person1: + age: 3 + childcare_hours_per_day: 0 + households: + household: + members: [person1] + state_code: MD + output: + md_ccs_service_unit: [UNIT_1] + +- name: Exactly 3 hours is UNIT_1 (≤3 hours per day). + period: 2025-01 + input: + people: + person1: + age: 3 + childcare_hours_per_day: 3 + households: + household: + members: [person1] + state_code: MD + output: + md_ccs_service_unit: [UNIT_1] + +- name: 3.5 hours is UNIT_2. + period: 2025-01 + input: + people: + person1: + age: 3 + childcare_hours_per_day: 3.5 + households: + household: + members: [person1] + state_code: MD + output: + md_ccs_service_unit: [UNIT_2] + +- name: 5.999 hours is UNIT_2 (just below 6-hour boundary). + period: 2025-01 + input: + people: + person1: + age: 3 + childcare_hours_per_day: 5.999 + households: + household: + members: [person1] + state_code: MD + output: + md_ccs_service_unit: [UNIT_2] + +- name: Exactly 6 hours is UNIT_3 (≥6 hours per day). + period: 2025-01 + input: + people: + person1: + age: 3 + childcare_hours_per_day: 6 + households: + household: + members: [person1] + state_code: MD + output: + md_ccs_service_unit: [UNIT_3] + +- name: 12 hours is UNIT_3. + period: 2025-01 + input: + people: + person1: + age: 3 + childcare_hours_per_day: 12 + households: + household: + members: [person1] + state_code: MD + output: + md_ccs_service_unit: [UNIT_3] diff --git a/policyengine_us/variables/gov/states/md/msde/ccs/eligibility/md_ccs_activity_eligible.py b/policyengine_us/variables/gov/states/md/msde/ccs/eligibility/md_ccs_activity_eligible.py new file mode 100644 index 00000000000..0f28507bc48 --- /dev/null +++ b/policyengine_us/variables/gov/states/md/msde/ccs/eligibility/md_ccs_activity_eligible.py @@ -0,0 +1,29 @@ +from policyengine_us.model_api import * + + +class md_ccs_activity_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Eligible for Maryland Child Care Scholarship (CCS) based on activity requirements" + definition_period = MONTH + defined_for = StateCode.MD + reference = "https://earlychildhood.marylandpublicschools.org/system/files/filedepot/2/scholarship-brochure-4.pdf" + + def formula(spm_unit, period, parameters): + # CCS Brochure (Eligibility Requirements): each parent in the household + # must be working/employed, in an approved training program, or + # attending school. We approximate per-parent with employment + student; + # for activities we don't individually model (job training, job search, + # SNAP E&T, temporary leave, etc.), users can override at the SPMUnit + # level via the federal CCDF bare input meets_ccdf_activity_test. + person = spm_unit.members + is_head_or_spouse = person("is_tax_unit_head_or_spouse", period.this_year) + hours_worked = person("weekly_hours_worked", period.this_year) + is_employed = hours_worked > 0 + is_student = person("is_full_time_student", period.this_year) + individually_eligible = is_employed | is_student + per_parent_check_passes = ( + spm_unit.sum(is_head_or_spouse & ~individually_eligible) == 0 + ) + fallback = spm_unit("meets_ccdf_activity_test", period.this_year) + return per_parent_check_passes | fallback diff --git a/policyengine_us/variables/gov/states/md/msde/ccs/eligibility/md_ccs_eligible.py b/policyengine_us/variables/gov/states/md/msde/ccs/eligibility/md_ccs_eligible.py index 48af233e103..4238b826160 100644 --- a/policyengine_us/variables/gov/states/md/msde/ccs/eligibility/md_ccs_eligible.py +++ b/policyengine_us/variables/gov/states/md/msde/ccs/eligibility/md_ccs_eligible.py @@ -9,15 +9,20 @@ class md_ccs_eligible(Variable): defined_for = StateCode.MD reference = ( "https://regs.maryland.gov/us/md/exec/comar/13A.14.06.03", - "https://mgaleg.maryland.gov/2022RS/Chapters_noln/CH_525_hb0995E.pdf#page=1", + "https://mgaleg.maryland.gov/2022RS/Chapters_noln/CH_525_hb0995E.pdf#page=4", ) def formula(spm_unit, period, parameters): has_eligible_child = add(spm_unit, period, ["md_ccs_eligible_child"]) > 0 income_eligible = spm_unit("md_ccs_income_eligible", period) + activity_eligible = spm_unit("md_ccs_activity_eligible", period) # COMAR 13A.14.06.03F(1) waives the income test for TCA applicants or # recipients. We don't track TANF applicants separately from recipients # at the moment; the regulation covers both. is_tca = spm_unit("is_tanf_enrolled", period) receives_ssi = add(spm_unit, period, ["ssi"]) > 0 - return has_eligible_child & (income_eligible | is_tca | receives_ssi) + return ( + has_eligible_child + & activity_eligible + & (income_eligible | is_tca | receives_ssi) + ) diff --git a/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_income_eligible.py b/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_income_eligible.py index 9dd9551b635..13a28ad50ca 100644 --- a/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_income_eligible.py +++ b/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_income_eligible.py @@ -22,11 +22,10 @@ def formula(spm_unit, period, parameters): # hhs_smi parameter only has data from 2021-10-01 forward, so the # FY2019-2022 freeze (2018 SMI) will return zero until earlier SMI # entries are added. - base_year = p.smi_base_year - if base_year > 0: + if p.smi_freeze_in_effect: size = spm_unit("spm_unit_size", period) state = spm_unit.household("state_code_str", period) - smi_value = smi(size, state, f"{int(base_year)}-10-01", parameters) + smi_value = smi(size, state, f"{p.smi_frozen_year}-10-01", parameters) else: smi_value = spm_unit("hhs_smi", period) enrolled = spm_unit("md_ccs_enrolled", period) diff --git a/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_weekly_copay.py b/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_weekly_copay.py index 798e3bab94c..49d3745d5d0 100644 --- a/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_weekly_copay.py +++ b/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_weekly_copay.py @@ -10,7 +10,8 @@ class md_ccs_weekly_copay(Variable): defined_for = StateCode.MD reference = ( "https://regs.maryland.gov/us/md/exec/comar/13A.14.06.12", - "https://mgaleg.maryland.gov/2024RS/Chapters_noln/CH_717_sb0362E.pdf#page=1", + "https://mgaleg.maryland.gov/2024RS/Chapters_noln/CH_717_sb0362E.pdf#page=19", + "https://mgaleg.maryland.gov/2022RS/Chapters_noln/CH_525_hb0995E.pdf#page=3", ) def formula(spm_unit, period, parameters): diff --git a/policyengine_us/variables/gov/states/md/msde/ccs/payment/md_ccs_service_unit.py b/policyengine_us/variables/gov/states/md/msde/ccs/payment/md_ccs_service_unit.py index 31ffebea066..73a0a7860dd 100644 --- a/policyengine_us/variables/gov/states/md/msde/ccs/payment/md_ccs_service_unit.py +++ b/policyengine_us/variables/gov/states/md/msde/ccs/payment/md_ccs_service_unit.py @@ -22,7 +22,10 @@ def formula(person, period, parameters): p = parameters(period).gov.states.md.msde.ccs.copay units = p.unit_hours.calc(hours_per_day) return select( - [units == 3, units == 2], - [MDCCSServiceUnit.UNIT_3, MDCCSServiceUnit.UNIT_2], - default=MDCCSServiceUnit.UNIT_1, + [units == 3, units == 2, units == 1], + [ + MDCCSServiceUnit.UNIT_3, + MDCCSServiceUnit.UNIT_2, + MDCCSServiceUnit.UNIT_1, + ], ) From d5083a725f0b60837fd75d46eb7cfe2b4ac20321 Mon Sep 17 00:00:00 2001 From: Ziming Date: Wed, 20 May 2026 16:10:46 -0400 Subject: [PATCH 10/13] test fix --- .../md/msde/ccs/md_ccs_activity_eligible.yaml | 2 ++ .../gov/states/md/msde/ccs/md_ccs_region.yaml | 28 +++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_activity_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_activity_eligible.yaml index 9cfd7eaf0df..1f6fcbbb220 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_activity_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_activity_eligible.yaml @@ -44,6 +44,7 @@ person1: age: 30 is_tax_unit_head_or_spouse: true + weekly_hours_worked: 0 spm_units: spm_unit: members: [person1] @@ -126,6 +127,7 @@ person1: age: 30 is_tax_unit_head_or_spouse: true + weekly_hours_worked: 0 spm_units: spm_unit: members: [person1] diff --git a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_region.yaml b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_region.yaml index 619c8d0218c..ca07fccf5ac 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_region.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_region.yaml @@ -4,8 +4,12 @@ - name: Cecil County maps to Region U. period: 2025-01 input: + people: + person1: + age: 30 households: household: + members: [person1] state_code: MD county: CECIL_COUNTY_MD output: @@ -14,8 +18,12 @@ - name: Caroline County maps to Region V. period: 2025-01 input: + people: + person1: + age: 30 households: household: + members: [person1] state_code: MD county: CAROLINE_COUNTY_MD output: @@ -24,8 +32,12 @@ - name: Anne Arundel County maps to Region W. period: 2025-01 input: + people: + person1: + age: 30 households: household: + members: [person1] state_code: MD county: ANNE_ARUNDEL_COUNTY_MD output: @@ -34,8 +46,12 @@ - name: Howard County maps to Region X. period: 2025-01 input: + people: + person1: + age: 30 households: household: + members: [person1] state_code: MD county: HOWARD_COUNTY_MD output: @@ -44,8 +60,12 @@ - name: Baltimore County maps to Region Y. period: 2025-01 input: + people: + person1: + age: 30 households: household: + members: [person1] state_code: MD county: BALTIMORE_COUNTY_MD output: @@ -54,8 +74,12 @@ - name: Allegany County maps to Region Z. period: 2025-01 input: + people: + person1: + age: 30 households: household: + members: [person1] state_code: MD county: ALLEGANY_COUNTY_MD output: @@ -64,8 +88,12 @@ - name: Baltimore City maps to Region BC. period: 2025-01 input: + people: + person1: + age: 30 households: household: + members: [person1] state_code: MD county: BALTIMORE_CITY_MD output: From e7a4101b7880e2015502db2328b33f67124be9c9 Mon Sep 17 00:00:00 2001 From: Ziming Date: Wed, 20 May 2026 16:32:12 -0400 Subject: [PATCH 11/13] fix --- .../md/msde/ccs/md_ccs_income_eligible.yaml | 27 +++++++++++++++++++ .../md/msde/ccs/md_ccs_income_eligible.py | 14 +++++----- 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_income_eligible.yaml index 1fa9a6355f2..ef692523db0 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_income_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_income_eligible.yaml @@ -113,3 +113,30 @@ # Monthly 85% SMI threshold: 149,249 * 0.85 / 12 = 10,571.81 # 10,833.33 > 10,571.81 -> not eligible md_ccs_income_eligible: false + +- name: Case 5, frozen SMI is converted to monthly before comparing income. + period: 2024-01 + input: + people: + person1: + age: 35 + employment_income: 100_000 + person2: + age: 33 + person3: + age: 8 + person4: + age: 5 + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + households: + household: + members: [person1, person2, person3, person4] + state_code: MD + output: + # Monthly countable income: 100,000 / 12 = 8,333.33 + # Frozen FY2024 four-person SMI uses 2021 MD SMI: 124,807 + # Monthly 75% SMI threshold: 124,807 * 0.75 / 12 = 7,800.44 + # 8,333.33 > 7,800.44 -> not eligible + md_ccs_income_eligible: false diff --git a/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_income_eligible.py b/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_income_eligible.py index 13a28ad50ca..f24aa0123fc 100644 --- a/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_income_eligible.py +++ b/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_income_eligible.py @@ -18,14 +18,14 @@ def formula(spm_unit, period, parameters): countable_income = spm_unit("md_ccs_countable_income", period) # Maryland freezes the SMI base year on a fiscal-year schedule (MSDE # Feb 4, 2026 W&M briefing slide 21): FY2019-2022 used 2018 SMI, - # FY2023-2024 used 2021 SMI, FY2025+ uses current SMI. PolicyEngine's - # hhs_smi parameter only has data from 2021-10-01 forward, so the - # FY2019-2022 freeze (2018 SMI) will return zero until earlier SMI - # entries are added. + # FY2023-2024 used 2021 SMI, FY2025+ uses current SMI. if p.smi_freeze_in_effect: - size = spm_unit("spm_unit_size", period) - state = spm_unit.household("state_code_str", period) - smi_value = smi(size, state, f"{p.smi_frozen_year}-10-01", parameters) + size = spm_unit("spm_unit_size", period.this_year) + state = spm_unit.household("state_code_str", period.this_year) + smi_value = ( + smi(size, state, f"{p.smi_frozen_year}-10-01", parameters) + / MONTHS_IN_YEAR + ) else: smi_value = spm_unit("hhs_smi", period) enrolled = spm_unit("md_ccs_enrolled", period) From 875088f723ced067e84ba6456556b4433635e498 Mon Sep 17 00:00:00 2001 From: Ziming Date: Mon, 1 Jun 2026 00:29:34 -0400 Subject: [PATCH 12/13] Address Pavel's review: count child support, wire household benefits, fix citations Critical: - Count child_support_received in MD CCS countable income per COMAR 13A.14.06.02B(28)(b)(x) and .03F(8)(c); Chapter 525 does not exclude it - Add md_child_care_subsidies to household_state_benefits.yaml (both brackets) so the benefit flows into household net income Should-address: - 45 CFR 98.45(k) -> (l)(3) for the 7% copayment cap - Single-sentence parameter descriptions (5 files); drop Chapter 717 freeze overreach - Add slide 22 citation for the 75% SMI initial threshold - Rename changelog fragment md-ccap -> md-ccs Co-Authored-By: Claude Opus 4.8 (1M context) --- changelog.d/{md-ccap.added.md => md-ccs.added.md} | 0 .../gov/household/household_state_benefits.yaml | 4 ++++ .../states/md/msde/ccs/copay/federal_cap_rate.yaml | 4 ++-- .../states/md/msde/ccs/copay/weekly_amount.yaml | 4 ++-- .../msde/ccs/income/countable_income/sources.yaml | 14 +++++++------- .../md/msde/ccs/income/smi_freeze_in_effect.yaml | 2 +- .../md/msde/ccs/income/smi_rate/initial.yaml | 2 ++ .../msde/ccs/payment/formal/licensed_center.yaml | 2 +- .../msde/ccs/payment/formal/licensed_family.yaml | 2 +- .../gov/states/md/msde/ccs/payment/unit_count.yaml | 2 +- .../md/msde/ccs/md_ccs_countable_income.yaml | 10 +++++----- .../states/md/msde/ccs/md_ccs_countable_income.py | 2 +- .../gov/states/md/msde/ccs/md_ccs_weekly_copay.py | 2 +- 13 files changed, 28 insertions(+), 22 deletions(-) rename changelog.d/{md-ccap.added.md => md-ccs.added.md} (100%) diff --git a/changelog.d/md-ccap.added.md b/changelog.d/md-ccs.added.md similarity index 100% rename from changelog.d/md-ccap.added.md rename to changelog.d/md-ccs.added.md diff --git a/policyengine_us/parameters/gov/household/household_state_benefits.yaml b/policyengine_us/parameters/gov/household/household_state_benefits.yaml index b74241a36b5..1d0de11522d 100644 --- a/policyengine_us/parameters/gov/household/household_state_benefits.yaml +++ b/policyengine_us/parameters/gov/household/household_state_benefits.yaml @@ -40,6 +40,8 @@ values: - id_aabd # Kentucky benefits - ky_ssp + # Maryland benefits + - md_child_care_subsidies # Nebraska benefits - ne_child_care_subsidies # South Carolina benefits @@ -107,6 +109,8 @@ values: - id_aabd # Kentucky benefits - ky_ssp + # Maryland benefits + - md_child_care_subsidies # Nebraska benefits - ne_child_care_subsidies # New Mexico benefits diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/copay/federal_cap_rate.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/copay/federal_cap_rate.yaml index 972e835c739..9003c4bd47d 100644 --- a/policyengine_us/parameters/gov/states/md/msde/ccs/copay/federal_cap_rate.yaml +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/copay/federal_cap_rate.yaml @@ -7,5 +7,5 @@ metadata: period: year label: Maryland CCS federal copayment cap rate reference: - - title: 45 CFR 98.45(k) - href: https://www.ecfr.gov/current/title-45/section-98.45#p-98.45(k) + - title: 45 CFR 98.45(l)(3) + href: https://www.ecfr.gov/current/title-45/section-98.45#p-98.45(l)(3) diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/copay/weekly_amount.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/copay/weekly_amount.yaml index ef8cf4b9172..a633a7f1412 100644 --- a/policyengine_us/parameters/gov/states/md/msde/ccs/copay/weekly_amount.yaml +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/copay/weekly_amount.yaml @@ -1,4 +1,4 @@ -description: Maryland sets this amount as the weekly copayment by service unit under the Child Care Scholarship program. The flat $1/$2/$3 schedule replaced the historical COMAR 13A.14.06.12 regional matrix via MSDE policy in May 2022 and was frozen at January 1, 2024 levels by Chapter 717 of 2024 (SB 362). +description: Maryland sets this amount as the weekly copayment by service unit under the Child Care Scholarship program. metadata: unit: currency-USD @@ -7,7 +7,7 @@ metadata: breakdown: - md_ccs_service_unit reference: - - title: Chapter 717 of 2024 (SB 362) - Budget Reconciliation and Financing Act - freeze at January 1, 2024 levels + - title: Chapter 717 of 2024 (SB 362) - Budget Reconciliation and Financing Act - caps copayments at January 1, 2024 levels href: https://mgaleg.maryland.gov/2024RS/Chapters_noln/CH_717_sb0362E.pdf#page=19 - title: MSDE Tuesday Tidbits bulletin (May 23, 2022) - introduction of $1/$2/$3 flat schedule href: https://content.govdelivery.com/accounts/MDMSDE/bulletins/31a37f2 diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/income/countable_income/sources.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/income/countable_income/sources.yaml index 3c7f45b6e50..c3e5098bf1e 100644 --- a/policyengine_us/parameters/gov/states/md/msde/ccs/income/countable_income/sources.yaml +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/income/countable_income/sources.yaml @@ -10,6 +10,7 @@ values: - dividend_income - rental_income - alimony_income + - child_support_received - unemployment_compensation - workers_compensation - veterans_benefits @@ -17,19 +18,18 @@ values: - capital_gains - farm_income - military_retirement_pay - # NOT included: - # - child_support_received (excluded per Chapter 525 of 2022 / HB 995) # COMAR-listed sources we don't model at the moment: commissions, tips, # bonuses, annuities, estate income, military entitlements. + # COMAR .02B(28)(c) exclusions we don't model at the moment: child support + # paid for a child outside the household, and $2,500 of child support tax + # intercepts and arrearages. metadata: unit: list period: year label: Maryland CCS countable income sources reference: - - title: COMAR 13A.14.06.02B(28) - Definition of "Gross income" + - title: COMAR 13A.14.06.02B(28)(b)(x) - Gross income includes alimony and child support href: https://regs.maryland.gov/us/md/exec/comar/13A.14.06.02 - - title: Chapter 525 of 2022 (HB 995) - child support excluded - href: https://mgaleg.maryland.gov/2022RS/Chapters_noln/CH_525_hb0995E.pdf#page=1 - - title: Chapter 526 of 2022 (SB 920) - href: https://mgaleg.maryland.gov/2022RS/Chapters_noln/CH_526_sb0920E.pdf#page=1 + - title: COMAR 13A.14.06.03F(8)(c) - Child support received counted as gross income + href: https://regs.maryland.gov/us/md/exec/comar/13A.14.06.03 diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_freeze_in_effect.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_freeze_in_effect.yaml index c4b71b22b07..a8cbe7a2fe8 100644 --- a/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_freeze_in_effect.yaml +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_freeze_in_effect.yaml @@ -1,4 +1,4 @@ -description: Maryland freezes the State Median Income (SMI) base year for Child Care Scholarship income eligibility during certain fiscal-year windows. When the freeze is in effect, the formula uses smi_frozen_year; otherwise it uses the current-year SMI. Maryland's fiscal year starts July 1. +description: Maryland uses this indicator to determine whether the State Median Income base year is frozen for Child Care Scholarship income eligibility. values: 2016-01-01: false 2018-07-01: true diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_rate/initial.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_rate/initial.yaml index c0b2879300f..ec8b49b04d1 100644 --- a/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_rate/initial.yaml +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_rate/initial.yaml @@ -13,3 +13,5 @@ metadata: href: https://regs.maryland.gov/us/md/exec/comar/13A.14.06.03 - title: MSDE Child Care Scholarship Program Briefing (Feb 4, 2026), slide 21 - historical thresholds href: https://mgaleg.maryland.gov/meeting_material/2026/w&m%20-%20134146885147130127%20-%20Briefing%20materials.pdf#page=21 + - title: MSDE Child Care Scholarship Program Briefing (Feb 4, 2026), slide 22 - 75% SMI initial threshold administrative origin + href: https://mgaleg.maryland.gov/meeting_material/2026/w&m%20-%20134146885147130127%20-%20Briefing%20materials.pdf#page=22 diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/payment/formal/licensed_center.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/formal/licensed_center.yaml index 2fa4997c641..f0f12993ed6 100644 --- a/policyengine_us/parameters/gov/states/md/msde/ccs/payment/formal/licensed_center.yaml +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/formal/licensed_center.yaml @@ -1,4 +1,4 @@ -description: Maryland provides these weekly UNIT_3 (full-time) reimbursement rates for licensed child care centers under the Child Care Scholarship program. UNIT_2 and UNIT_1 rates are derived in the formula by multiplying by unit_count / 3 per COMAR 13A.14.06.11. +description: Maryland provides these weekly full-time reimbursement rates for licensed child care centers under the Child Care Scholarship program. metadata: period: week diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/payment/formal/licensed_family.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/formal/licensed_family.yaml index 51127de43c2..4924a00c9d2 100644 --- a/policyengine_us/parameters/gov/states/md/msde/ccs/payment/formal/licensed_family.yaml +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/formal/licensed_family.yaml @@ -1,4 +1,4 @@ -description: Maryland provides these weekly UNIT_3 (full-time) reimbursement rates for licensed family child care homes under the Child Care Scholarship program. UNIT_2 and UNIT_1 rates are derived in the formula by multiplying by unit_count / 3 per COMAR 13A.14.06.11. +description: Maryland provides these weekly full-time reimbursement rates for licensed family child care homes under the Child Care Scholarship program. metadata: period: week diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/payment/unit_count.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/unit_count.yaml index 3dd57452c9c..cafd38e339d 100644 --- a/policyengine_us/parameters/gov/states/md/msde/ccs/payment/unit_count.yaml +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/payment/unit_count.yaml @@ -1,4 +1,4 @@ -description: Maryland's UNIT_3 (full-time) rate corresponds to three units of service per day per COMAR 13A.14.06.11. UNIT_2 and UNIT_1 rates are derived by multiplying the UNIT_3 rate by unit_count / 3 (i.e., 2/3 and 1/3 respectively). +description: Maryland sets the daily service unit count for each service unit category under the Child Care Scholarship program. metadata: unit: /1 diff --git a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_countable_income.yaml index 0104dfd4eb9..81dfbfe346d 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_countable_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/md/msde/ccs/md_ccs_countable_income.yaml @@ -72,7 +72,7 @@ # monthly: 44,000 / 12 = 3,666.67 md_ccs_countable_income: 3_666.67 -- name: Case 4, child support received is excluded from income. +- name: Case 4, child support received is counted as income. period: 2025-01 absolute_error_margin: 0.1 input: @@ -92,7 +92,7 @@ state_code: MD output: # employment_income: 30,000 (counted) - # child_support_received: 6,000 (EXCLUDED per Ch 525/526 of 2022) - # total annual: 30,000 - # monthly: 30,000 / 12 = 2,500 - md_ccs_countable_income: 2_500 + # child_support_received: 6,000 (counted per COMAR .02B(28)(b)(x) and .03F(8)(c)) + # total annual: 36,000 + # monthly: 36,000 / 12 = 3,000 + md_ccs_countable_income: 3_000 diff --git a/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_countable_income.py b/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_countable_income.py index 7481f8ff982..bd324909615 100644 --- a/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_countable_income.py +++ b/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_countable_income.py @@ -9,8 +9,8 @@ class md_ccs_countable_income(Variable): definition_period = MONTH defined_for = StateCode.MD reference = ( + "https://regs.maryland.gov/us/md/exec/comar/13A.14.06.02", "https://regs.maryland.gov/us/md/exec/comar/13A.14.06.03", - "https://mgaleg.maryland.gov/2022RS/Chapters_noln/CH_525_hb0995E.pdf#page=1", ) def formula(spm_unit, period, parameters): diff --git a/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_weekly_copay.py b/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_weekly_copay.py index 49d3745d5d0..6546361b5ef 100644 --- a/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_weekly_copay.py +++ b/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_weekly_copay.py @@ -54,7 +54,7 @@ def formula(spm_unit, period, parameters): ) scaled_weekly = total_weekly * scale - # Federal cap: copay cannot exceed 7% of gross income per 45 CFR 98.45(k) + # Federal cap: copay cannot exceed 7% of gross income per 45 CFR 98.45(l)(3) countable_income = spm_unit("md_ccs_countable_income", period) weekly_income = countable_income * MONTHS_IN_YEAR / WEEKS_IN_YEAR federal_cap = weekly_income * p.federal_cap_rate From 1dc94c2d26114e3fe58152c3fe5ac177a35ebebd Mon Sep 17 00:00:00 2001 From: Ziming Date: Tue, 2 Jun 2026 16:16:15 -0400 Subject: [PATCH 13/13] Address Pavel's review: parameter-drive unit divisor, document HCV deferral, fix SMI citation - Replace hard-coded /3 with p.unit_count["UNIT_3"] in md_ccs_payment_rate - Document deferral of the Housing Choice Voucher copay waiver and the housing_assistance dependency cycle that blocks reading it directly - Correct W&M briefing page anchor for the 75% SMI origin (slide 22 -> 20) Co-Authored-By: Claude Opus 4.8 (1M context) --- .../gov/states/md/msde/ccs/income/smi_rate/initial.yaml | 4 ++-- .../variables/gov/states/md/msde/ccs/md_ccs_weekly_copay.py | 6 ++++++ .../gov/states/md/msde/ccs/payment/md_ccs_payment_rate.py | 6 +++--- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_rate/initial.yaml b/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_rate/initial.yaml index ec8b49b04d1..5b9e2a300d7 100644 --- a/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_rate/initial.yaml +++ b/policyengine_us/parameters/gov/states/md/msde/ccs/income/smi_rate/initial.yaml @@ -13,5 +13,5 @@ metadata: href: https://regs.maryland.gov/us/md/exec/comar/13A.14.06.03 - title: MSDE Child Care Scholarship Program Briefing (Feb 4, 2026), slide 21 - historical thresholds href: https://mgaleg.maryland.gov/meeting_material/2026/w&m%20-%20134146885147130127%20-%20Briefing%20materials.pdf#page=21 - - title: MSDE Child Care Scholarship Program Briefing (Feb 4, 2026), slide 22 - 75% SMI initial threshold administrative origin - href: https://mgaleg.maryland.gov/meeting_material/2026/w&m%20-%20134146885147130127%20-%20Briefing%20materials.pdf#page=22 + - title: MSDE Child Care Scholarship Program Briefing (Feb 4, 2026), slide 20 - 75% SMI initial threshold administrative origin + href: https://mgaleg.maryland.gov/meeting_material/2026/w&m%20-%20134146885147130127%20-%20Briefing%20materials.pdf#page=20 diff --git a/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_weekly_copay.py b/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_weekly_copay.py index 6546361b5ef..b2b6899944e 100644 --- a/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_weekly_copay.py +++ b/policyengine_us/variables/gov/states/md/msde/ccs/md_ccs_weekly_copay.py @@ -29,6 +29,12 @@ def formula(spm_unit, period, parameters): # avoid the cycle through snap_dependent_care_deduction → childcare_expenses → md_ccs. is_snap = spm_unit("receives_snap", period) is_wic = add(spm_unit, period, ["receives_wic"]) > 0 + # Chapter 525 of 2022 § 9.5-113(C)(D)(1)(III) also waives copays for + # Housing Choice Voucher (Section 8) recipients. We don't model that + # waiver at the moment: reading the computed housing_assistance would + # create a cycle (housing_assistance → hud_adjusted_income → + # childcare_expenses → md_ccs), and we have no cycle-safe HCV-receipt + # input yet. exempt = is_tca | receives_ssi | is_snap | is_wic # Weekly copay per child based on service unit (enum-keyed lookup) diff --git a/policyengine_us/variables/gov/states/md/msde/ccs/payment/md_ccs_payment_rate.py b/policyengine_us/variables/gov/states/md/msde/ccs/payment/md_ccs_payment_rate.py index 678a79d25c6..27c7f18ac00 100644 --- a/policyengine_us/variables/gov/states/md/msde/ccs/payment/md_ccs_payment_rate.py +++ b/policyengine_us/variables/gov/states/md/msde/ccs/payment/md_ccs_payment_rate.py @@ -21,9 +21,9 @@ def formula(person, period, parameters): region = person.household("md_ccs_region", period) # Rate tables store UNIT_3 base rates (three units of service per day). - # COMAR 13A.14.06.11.B(3), .11.C(2), .11.D direct: multiply by - # unit_count / 3 to derive UNIT_2 (2/3) and UNIT_1 (1/3) rates. - unit_share = p.unit_count[service_unit] / 3 + # COMAR 13A.14.06.11.B(3), .11.C(2), .11.D direct: scale by + # unit_count / UNIT_3 to derive UNIT_2 (2/3) and UNIT_1 (1/3) rates. + unit_share = p.unit_count[service_unit] / p.unit_count["UNIT_3"] center_rate = p.formal.licensed_center[region][age_group] * unit_share family_rate = p.formal.licensed_family[region][age_group] * unit_share