Use shared childcare inputs and derive the child category in DC CCSP - #9285
Open
hua7450 wants to merge 6 commits into
Open
Use shared childcare inputs and derive the child category in DC CCSP#9285hua7450 wants to merge 6 commits into
hua7450 wants to merge 6 commits into
Conversation
DC CCSP was the only state child care program that defined its own attending-days input rather than using the shared childcare_attending_days_per_month that 17 other states read, and the only one whose reimbursement age category was a pure input instead of a formula over age. - Replace dc_ccsp_attending_days_per_month with the shared childcare_attending_days_per_month, read as period.this_year to match the convention in the other states. - Derive dc_ccsp_child_category from age: infants and toddlers under 36 months, preschoolers from 36 to under 60 months, school-age at 60 months and over, per 5-A DCMR 199 and the CCSP policy manual. The two special needs categories and the school-age Before or After part-time rate turn on the service authorized rather than the child's age, so the variable stays overridable. Previously every DC child was priced at the preschool rate by default, which understated an infant's daily rate at a child development center by 36 percent ($63.00 against $98.65) and overstated a school-ager's by 71 percent. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #9285 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 1 6 +5
Lines 22 115 +93
=========================================
+ Hits 22 115 +93
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Replaces the ad-hoc select over two scalar month thresholds with the pattern the rest of the repo uses. 31 of the 52 state child care age variables derive their band with .calc() on a months-keyed single_amount bracket, and Alabama is a direct template for DC: a clean three-member age enum with thresholds at 0, 36 and 60 months, the same boundaries DC uses, with the other rate dimensions kept in their own enums rather than fused into the age one. - Add dc_ccsp_age_category (INFANT_AND_TODDLER / PRESCHOOL / SCHOOL_AGE) and age_category/months.yaml, mirroring al_ccsp_age_category. - Derive dc_ccsp_child_category, the fused rate-table key, from that age category instead of from raw month comparisons. This also removes the fragile mapping onto non-contiguous enum indices that a bracket over the seven-member category enum would have needed. Rewrites the tests around real households rather than the mechanics. The previous child-category file included a case that fed in a category and asserted the same value back, which tested the input override rather than any DC rule. Every case now starts from age and asserts the daily rate the band reaches, including a disabled infant holding the ordinary $98.65 infant rate rather than the $118.38 special needs rate. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Care on a single end of the school day is the more common out-of-school-time placement, and the rate sheet publishes no plain school-age row because school-age children may participate only for OST care. Also documents which rows the formula never produces from household inputs. The two special needs rows are authorized at the facility rather than by the child: under the Level I subsidy agreement a provider files a Special Needs Rate Request Form per facility and renews it annually, so no household characteristic implies the rate and it is deliberately not derived from is_disabled. Preschool Before and After and School-Age Before and After turn on wraparound care that the household data does not record. Note that School-Age Before or After is priced only in the two traditional columns, so a school-age child on an extended day or nontraditional schedule reaches no published rate and needs School-Age Before and After set directly. That case is pinned in a test. The schedule type defaults to full-time traditional, where both school-age rows carry the same amount, so microsimulation output is unchanged. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
hua7450
marked this pull request as ready for review
August 14, 2026 17:19
…r caregiver test dc_ccsp sums dc_ccsp_maximum_subsidy_amount over every SPM unit member while the variable was gated only on StateCode.DC, so an adult or an over-age child with authorized days of care added to the subsidy. It is now gated on dc_ccsp_eligible_child, matching the copay side, which already ranks only eligible children. dc_ccsp_qualified_need_eligible counted any household member's SSDI or SSI, including a child's own benefits. Policy manual 2.4.2.6 conditions the elder caregiver classification on an individual with responsibility for the day-to-day care of the child who is "age 62 or older or receive[s] Social Security disability benefits or Supplemental Security Income payments", so both prongs now sit inside the head-or-spouse mask, as the age prong already did. Corrects the child development home Preschool Before and After full-time traditional rate from $53.03 to $53.04, matching the FY25 rate sheet. Two other suspected defects were checked against the sources and are not defects, so nothing changed: - The non-monotonic second-child copay amounts are printed that way in the OSSE sliding fee scale, including $0.60 at 231-240% of poverty between $1.90 and $2.59. Added a note so they are not "corrected" later. - assessed_property_value belongs in the asset sources: policy manual 2.5 counts assets "including cash, money in bank accounts, investments, and real estate". Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…into dc-ccsp-shared-inputs-age-category
Both cases in dc_ccsp_maximum_subsidy_amount.yaml set no age, so the person defaulted to 40. Once the payment was gated on dc_ccsp_eligible_child that person was an adult, over the age limit and the head of the tax unit rather than a dependent, so the rate lookup returned zero. Each case now includes the parent the child lives with and states the child's age, matching what the case names already described. The asserted daily rates are unchanged at $98.65 and $39.78. Adds a case for a child over the age limit who has authorized days of care, so the new gate cannot regress silently. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A sweep of all 48 state child care subsidy programs found DC CCSP to be the outlier on two counts. This PR fixes both.
DC defined its own attending-days input.
dc_ccsp_attending_days_per_monthduplicated the sharedchildcare_attending_days_per_monththat 17 other state programs read (AK, AR, AZ, FL, KY, MA, MN, MO, NE, OK, PA, TX, VA, WV, WY and others). DC now reads the shared variable asperiod.this_year, matching the convention in those states (int⇒STOCK, so no monthly division).DC's reimbursement age category was a pure input.
dc_ccsp_child_categorydefaulted toPRESCHOOLfor every child. Of the 48 programs, 45 derive the age band in a named variable and CA derives it inline — DC was the only pure input.Following the established pattern
31 of the 52 state child care age variables derive the band with
.calc()on a months-keyedsingle_amountbracket, andage, period.this_year * MONTHS_IN_YEARis the dominant age source. Alabama is a direct template:al_ccsp_age_categoryis a clean three-member enum with thresholds at 0, 36 and 60 months — the same boundaries DC uses — and AL keeps provider type, region and quality tier in their own enums rather than fusing them into the age one.So DC now has a clean age enum, and the fused rate-table row is derived from it:
Going through a three-member enum also avoids mapping onto non-contiguous indices of the seven-member category enum, which would break silently if anyone reordered it.
Age bands
The FY25 rate sheet names three bands but does not define them; the definitions come from the licensing regulations and the policy manual.
Which rate rows the formula produces
The rate sheet fuses the age band with the service authorized, so only three of the seven rows follow from age:
INFANT_AND_TODDLERPRESCHOOLSCHOOL_AGE_BEFORE_OR_AFTERThe other four are reachable only by setting
dc_ccsp_child_categorydirectly, and the formula documents why:INFANT_AND_TODDLER_SPECIAL_NEEDS,PRESCHOOL_AND_SCHOOL_AGE_SPECIAL_NEEDS— the special needs rate is authorized at the facility, not the child. Per the FY26 Level I Subsidy Agreement §(4), "in order to receive the special needs rate, the Provider shall complete the Special Needs Rate Request Form by facility," renewed annually. No household characteristic implies it, so it is deliberately not derived fromis_disabled.PRESCHOOL_BEFORE_AND_AFTER— wraparound care around a public pre-K day is not in the household data, and it carries the same rate asPRESCHOOLwherever both are published.SCHOOL_AGE_BEFORE_AND_AFTER— care on both ends of the school day. Care on a single end is the more common placement.There is no plain school-age row on the sheet, because school-age children may participate only for out-of-school-time care — every school-age placement is before or after school care by definition.
Known limitation:
SCHOOL_AGE_BEFORE_OR_AFTERis priced only in the two traditional columns, so a school-age child whosedc_ccsp_schedule_typeis set to an extended day or nontraditional column reaches no published rate and needsSCHOOL_AGE_BEFORE_AND_AFTERset directly. That case is pinned in a test.dc_ccsp_schedule_typedefaults toFULL_TIME_TRADITIONAL, where both school-age rows carry the same amount.Impact
Under the old
PRESCHOOLdefault, a child development center full-time traditional day was priced at $63.00 regardless of age — 36% below the $98.65 infant rate and 41% above the $36.74 school-age rate. Microsimulation output is unchanged, becausechildcare_attending_days_per_monthis 0 for everyone in the Populace microdata, as with every other attending-days state.Files
Not addressed here
Left for separate PRs so this one stays reviewable:
dc_ccsp_maximum_subsidy_amountis gated only onStateCode.DC, anddc_ccspsums it over every SPM unit member — an adult or over-age child with nonzero attending days inflates the subsidy. The copay side correctly gates on the two youngest eligible children.reimbursement_rates.yamlencodes only the Developing/Progressing quality tier; OSSE publishes five designations (Developing, Progressing, Quality, High-Quality, Preliminary), and there is no facility-quality dimension in the breakdown.CHILD_HOME_AND_EXPANDED_HOMEPRESCHOOL_BEFORE_AND_AFTERfull-time traditional is encoded as $53.03; the FY25 rate sheet says $53.04.Test plan
dc_ccsp_age_categorycases covering a four-child family and both band boundaries at exact months (36 and 60)dc_ccsp_child_categorycases assert the daily rate each band reaches, including the school-age part-time rate ($18.37/day) and the unpriced nontraditional cellpolicyengine-core test .../states/dc— 332 passedgov/hhs/ccdf,household_state_benefits.yamlandtests/policy/baseline/partners— 699 passedmake formatclean