Skip to content

Pay Colorado's child care assistance only for eligible children - #10699

Open
MaxGhenis wants to merge 1 commit into
mainfrom
co-ccap-eligible-children
Open

MaxGhenis wants to merge 1 commit into
mainfrom
co-ccap-eligible-children

Conversation

@MaxGhenis

@MaxGhenis MaxGhenis commented Nov 7, 2026 •

Copy link
Copy Markdown
Contributor

What this changes

Colorado's counties pay providers for the care of eligible children under the Child Care Assistance Program, and the Department of Early Childhood sets the children's age limits in 8 CCR 1403-1:

  • Under 3.132(D), counties pay for the care of children from birth to age 13. Under 3.132(E), a child up to age 19 with additional care needs, who can't care for themselves or whom a court supervises, may also qualify.
  • The department defines an eligible child the same way in 3.103(UU) and 3.111(F).

co_ccap_child_eligible already applies those limits and takes a disability or court supervision as the additional care need, and co_ccap_parent_fee counts only eligible children in care. On main, though, co_ccap_subsidy sums the child care and after-school charges of every SPM unit member, a teenager's among them.

For example, take a parent with a 3-year-old and a 15-year-old, $1,000 a month in charges for each child and a $200 parent fee. On main, the family receives $1,800 a month: $800 toward the 3-year-old's care and the 15-year-old's whole $1,000. On this branch, it receives $800.

  • We sum the child care and after-school charges of eligible children, subtract the parent fee and floor the result at zero.
  • We cite 3.103(UU), 3.111(F) and 3.132(D) and (E) in the variable, on PDF pages 9, 35 and 126 of ruleVersionId 12658.

Under 3.125(FFF), the county pays the lesser of the provider's private pay rate and the county reimbursement rate that the department sets. The model has no county rates yet, so nothing caps a child's charge until #10723 adds them.

Under 3.114(B)(1), a county ends care for a child who passes the age limits only at the family's re-determination. co_ccap_is_in_entry_process defaults to true, so the model applies the age limits as a county does when a family applies. The model has no record of when a family last applied, so it stops counting a child's care in the month the child ages out, while a county pays until re-determination.

Tests

co_ccap_subsidy.yaml:

  • Cases 1 and 2 put the charges on a person with no age, who defaults to 40, so we move them onto a 4-year-old in a two-person Colorado unit with the same expected values.
  • We add Cases 3 to 8, and main fails three of them: it counts the 15-year-old's $1,000 of charges in Cases 3 and 8 and the 13-year-old's $500 of after-school care in Case 6. Cases 4, 5 and 7 pass on both, since a teenager with a disability or under court supervision and a 12-year-old all count as eligible children.

test_co_ccap_eligible_children_properties.py adds two Hypothesis properties, with 15 and 20 examples. They draw ages, disabilities, court supervision and charges, which YAML can't draw, and set eligibility and the parent fee as inputs:

  1. A member outside the age limits, such as a 15-year-old without additional care needs or a 19-year-old, adds nothing to the payment, whatever the member's charges, the eligible child's charges or the parent fee.
  2. The payment equals the eligible children's charges less the parent fee, floored at zero.

main fails both, paying $1,000 instead of $500 for a 12-year-old and a 13-year-old with $500 of after-school care each. When a $200 fee exceeds a 3-year-old's $100 charge and a 15-year-old's charge comes to $1,000, it pays $900 instead of nothing.

In CI at 2eeea71, the Rest Python group remaining-2 ran the two properties in 7.5 and 10.4 seconds. They add about 18 seconds to a group that ran for 29:32 and peaked at 7.5 GiB of resident memory. CI measures memory for the whole group, and we didn't measure the file's own peak. Locally, on macOS with one process, the file takes 13 seconds of test time.

Invariants

For every SPM unit in Colorado and every month:

  1. The payment is at least zero.
  2. The payment never exceeds the eligible children's child care and after-school charges.
  3. Given the unit's eligibility, the parent fee and each member's charges, a member outside the age limits never changes the payment.
  4. For a unit that meets co_ccap_eligible, and until the model adds county rates, the payment equals the eligible children's charges less the parent fee, floored at zero.

The two properties check 3 and 4, and 1 and 2 follow from 4 and from co_ccap_subsidy's defined_for, which pays an ineligible unit nothing.

Impact

We ran Populace US 2024, the default dataset, for 2026 at 040fe5686c and again with this change cherry-picked onto it (391422a907). Between 040fe5686c and this branch's base, 7acea8ee63, main changed no Colorado CCAP variable or parameter, no child care expense variable and no CCDF variable or parameter.

We estimate that Colorado's program pays $269.3 million in 2026, down from $270.7 million, a fall of $1.3 million. Nineteen records, with a combined weight of 31,425 SPM units, receive a payment before and after the change. Nine of them change, with a combined weight of 2,710 units. In each, a member under 18 who fails the eligible-child test held a share of the bill, and the parent fee comes to zero, so the payment falls by that share. Two records carry almost all the weight: the new formula pays one share in three for one and three shares in four for the other.

Nationally, we estimate that household net income falls by $484,811, less than the cut in the subsidy. Families now pay more of their own bills, and SNAP's dependent care deduction counts those bills, so SNAP rises by $463,490. The federal child and dependent care credit rises by $44,070. SPM poverty rates stay the same, and no other state's results move.

axiom: TheAxiomFoundation/rulespec-us#2073 queued

🤖 Generated with Claude Code

8 CCR 1403-1 3.132(D) and (E) pay for the care of children under 13, and of
children under 19 who can't care for themselves or who are under court
supervision. co_ccap_subsidy summed every SPM unit member's child care and
after-school charges, a teenager's among them; it now sums the charges of
members who pass co_ccap_child_eligible, as co_ccap_parent_fee already does.

Adds YAML cases at the age boundaries, two Hypothesis properties and a
towncrier fragment.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis added a commit that referenced this pull request Nov 8, 2026
Add YAML cases, recomputed by hand from CDEC's rate tables and the county
rate plans, for the full-time rate, care units, days of care, age bands,
quality tiers, provider types, the monthly cap and the reimbursement.

Add Hypothesis tests for four invariants:
1. Every cell of every table, on every effective date, matches the
   full-time rate the model reads.
2. Each care unit pays its share of the full-time rate, rounded half up
   to the cent: 55% for part time, twice the rate for two full-time units.
3. The payment equals the eligible children's charges, each capped at the
   county rate, less the fee. So it never exceeds the county rates or the
   charges less the fee, and the capped fee never exceeds the
   reimbursement.
4. More charges never lower the payment, and a higher fee never raises it.

Read Denver's rates for a household with no Colorado county. The tables'
county breakdown fills them with every county in the country at zero, so
such a household read $0; co_ccap_fpg_eligible already falls back to
Denver.

Update #10699's subsidy cases and court supervision case 5 for the cap.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaxGhenis
MaxGhenis marked this pull request as ready for review November 9, 2026 09:40
MaxGhenis added a commit that referenced this pull request Nov 11, 2026
Add YAML cases, recomputed by hand from CDEC's rate tables and the county
rate plans, for the full-time rate, care units, days of care, age bands,
quality tiers, provider types, the monthly cap and the reimbursement.

Add Hypothesis tests for four invariants:
1. Every cell of every table, on every effective date, matches the
   full-time rate the model reads.
2. Each care unit pays its share of the full-time rate, rounded half up
   to the cent: 55% for part time, twice the rate for two full-time units.
3. The payment equals the eligible children's charges, each capped at the
   county rate, less the fee. So it never exceeds the county rates or the
   charges less the fee, and the capped fee never exceeds the
   reimbursement.
4. More charges never lower the payment, and a higher fee never raises it.

Read Denver's rates for a household with no Colorado county. The tables'
county breakdown fills them with every county in the country at zero, so
such a household read $0; co_ccap_fpg_eligible already falls back to
Denver.

Update #10699's subsidy cases and court supervision case 5 for the cap.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@DTrim99

DTrim99 commented Nov 13, 2026

Copy link
Copy Markdown
Collaborator

PR Review: Pay Colorado's child care assistance only for eligible children

Summary

I read the rule before the code. 8 CCR 1403-1 has counties buy care child by child (3.132(A)). They pay only for an eligible child: under 13, or under 19 for a child who can't care for themselves or is under court supervision (3.103(UU), 3.111(F), 3.132(D) and (E)). The household's single parent fee pays the first dollars of that care (3.124(A), (K) and (L)). The new formula does this. It sums the child care and after-school charges of members who pass co_ccap_child_eligible, subtracts the unchanged parent fee and floors the result at zero. The PR changes neither household eligibility nor the parent fee. All 8 YAML expectations and the 5 Hypothesis @examples check out by hand. CI is green at the head, and the head merges cleanly into current main.

One item needs a change: the variable lists the same rule PDF three times, which breaks the CLAUDE.md reference rules. The suggestions cover three things: a pre-existing gap (the rule's per-child citizenship test isn't modelled), a code comment for the re-determination limit, and optional trimming of the Python properties.

Basis: I didn't run Python or tests locally. Every claim rests on reading the rule PDFs and the code, on hand traces, or on CI logs, and I say which as I go.

Critical

None.

Should address

1. co_ccap_subsidy.py:11-18: three reference entries for one source document.
All three hrefs point to GenerateRulePdf.do?ruleVersionId=12658&fileName=8 CCR 1403-1 and differ only by #page=9, #page=35 and #page=126. CLAUDE.md, "Parameter and variable references", says: "One reference entry per source document; URLs that differ only by #page= are one source". It also says: "Variable reference tuples have no title: put a # PDF pages 61-62, 67 comment above a multi-page href." The cited pages do corroborate the rule. I read each one: p.9 has 3.103(UU), which runs onto p.10, p.35 has 3.111(F), and p.126 has 3.132(D) and (E). So this is about format only.
Fix: use one entry, for example:

reference = (
    # 8 CCR 1403-1 3.103(UU), 3.111(F), 3.124(K) and (L), 3.132(D) and (E):
    # PDF pages 9-10, 35, 82, 126
    "https://www.sos.state.co.us/CCR/GenerateRulePdf.do?ruleVersionId=12658&fileName=8%20CCR%201403-1#page=9",
)

Adding 3.124(K) is optional, but it is the rule behind the formula's expenses - parent_fee. Its text is "Parent fees are used as the first dollars paid for care" (p.82). The stacked branch of #10723 already uses this one-entry form for the same file.

Suggestions

1. Pre-existing gap: the eligible-child definition the PR cites also requires the child to be a citizen or legal resident, and co_ccap_child_eligible doesn't test it (co_ccap_child_eligible.py:31-32).
The rule says so in three places:

  • 3.103(UU), p.10: "Any child served through the Colorado Works program or the Low-Income Child Care program must be a citizen/legal resident."
  • 3.103(Z), p.6: "Since the child is the beneficiary of child care assistance, the citizen/legal resident requirement only applies to the child who is being considered for assistance."
  • 3.111(F)(1), p.35: "All children who have had an application made on their behalf or are receiving child care assistance shall verify that they are a citizen/legal resident".

Rule version 11042, which governs the earlier test periods, has the same sentences (pp. 4 and 6). On this branch, a family with a citizen 3-year-old and a 5-year-old without lawful status is still paid for both children's care. The rule pays only for the 3-year-old. This PR neither introduces nor worsens the gap: main pays for every member. The PR's Axiom issue also defers the citizenship test on purpose.

  • Follow-up fix: add & person("is_ccdf_immigration_eligible_child", period.this_year) to co_ccap_child_eligible. This existing federal variable covers citizens and 8 USC 1641 qualified noncitizens, and other states' CCAP child tests already use it. The change would also reach household eligibility (through co_ccap_eligible_children) and the fee's count of children in care, as the rule requires.
  • In this PR, at minimum: say in the co_ccap_subsidy comment that the citizenship test isn't modelled yet. That way "eligible children: children under 13, and children under 19 ..." doesn't read as the whole definition.

2. Put the re-determination limit in the code, not only in the PR body.
3.114(B)(1), p.61, says care ends "at re-determination only" when the "Eligible child exceeds age limits". The model has no certification date, so it applies the age limits every month. The PR body explains this, but the formula doesn't. A one-line comment would cover it, for example: "Counties end care for a child who passes the age limits only at re-determination (3.114(B)(1)); without a certification date the model applies the limits each month."

3. Optional: the second Hypothesis property restates the formula.
test_the_payment_equals_the_eligible_childrens_charges_less_the_fee takes eligibility and the fee as inputs and asserts max(sum(eligible charges) - fee, 0), which is the formula line for line. CLAUDE.md, "Test design and CI cost", says: "Do not duplicate a policy formula in Python merely to test it against itself". The first property, that adding an ineligible member changes nothing, is the distinct check YAML can't express. YAML Cases 3-8 already pin each branch.
Dropping the second property, or moving its 18/19 disability boundary into co_ccap_subsidy.yaml, would save about 10.4 s in Rest group remaining-2. This is optional, since the PR body justifies the file and reports its CI timings.

Verified correct

Rule research. I read the PDFs.

  • Rule version 12658, effective 2026-08-14:
    • 3.103(UU) (pp. 9-10) and 3.111(F) (p.35) define the eligible child by age, care need and residence or custody, plus citizenship.
    • 3.132(A) (p.125) purchases care "on a child-by-child basis".
    • 3.132(D) (p.126) pays "for children from birth to thirteen (13) years". 3.132(E) adds children "over the age of thirteen (13) but up to age nineteen (19)" who are incapable of self-care or under court supervision.
    • 3.124(A) (p.79) bases one household fee on income, "taking the number of children in care into account".
    • 3.124(K) and (L) (p.82): the fee pays "the first dollars paid for care", may be split between providers, and "shall not exceed the reimbursement rate by CCCAP".
  • Rule version 11042, the earlier periods (Dec 2022, 2023, Jan 2026): the same definition is on p.6, and the same payment rule is 3.115.3(D) and (E) on p.66. So the change holds in every tested period.
  • Conclusion: paying per eligible child while the household fee covers the family matches the rule. Age < 13 and age < 19 match the existing parameters.

Formula (by reading).

  • charge * eligible_child multiplies a person-level monthly amount by a person-level MONTH flag, and spm_unit.sum adds them up. The YEAR expense inputs are read at the month: Case 3's 12,000 a year gives 1,000 a month in CI.
  • The PR doesn't touch co_ccap_parent_fee, co_ccap_eligible, co_ccap_eligible_children or the parameters, so household eligibility and the fee are unchanged.
  • There is no new state-gated int or enum key, so the NH Add New Hampshire state supplementation for 2026 #10156 pattern doesn't arise.
  • On main, co_ccap_child_in_care is eligible & (schedule | expense > 0). Weighting charges by it would give the same result, because a child with zero charges adds zero either way.

Hand checks (monthly unless noted; fee as input):

Case Arithmetic Expected
YAML 1 (year 2023, age 4) (1,000 + 1,200)/12 − 800/12 = 116.67/mo × 12 1,400 ✓
YAML 2 (Dec 2022, age 4) 12,000/12 + 14,400/12 − 800 = 1,000 + 1,200 − 800 1,400 ✓
YAML 3 (3 and 15) 15 ≥ 13, no needs → [F, T, F]; 1,000 − 200 800 ✓ (main: 1,800)
YAML 4 (15 disabled) limit 19, 15 < 19 → eligible; 1,000 + 1,000 − 200 1,800 ✓
YAML 5 (15 court) limit 19 → eligible; 1,000 + 1,000 − 200 1,800 ✓
YAML 6 (4 and 13) 13 not < 13 → ineligible; 1,000 − 200 (6,000/12 = 500 excluded) 800 ✓ (main: 1,300)
YAML 7 (4 and 12) 12 < 13; 1,000 + 500 − 200 1,300 ✓
YAML 8 (3 and 15) 1,200/12 = 100; max(100 − 200, 0) 0 ✓ (main: 900)
Py ex. 1 (3 and 15, fee 200) alone 1,000 − 200 = 800; with the 15-year-old 800 equal ✓
Py ex. 2 (12 and 13 after-school) alone 500; the 13-year-old adds 0 → 500 equal ✓ (main: 1,000)
Py ex. 3 (18 and 19, both disabled) 18 < 19: 900 − 50 = 850; the 19-year-old fails < 19 → 850 equal ✓
Py prop-2 ex. 1 (3, 15 disabled, 15) 1,000 + 1,000 − 0 2,000 ✓
Py prop-2 ex. 2 (3 at 100, 15 at 1,000) max(100 − 200, 0) 0 ✓

Mutation (by reading). Deleting * eligible_child fails YAML Cases 3, 6 and 8 and both properties. Dropping after_school_expenses fails Cases 1, 2 and 7. The zero floor is now pinned by Case 8.

Readers of the changed variable (by grep at the head and on main):

  • co_child_care_subsidies adds co_ccap_subsidy, and it flows into child_care_subsidies through the CCDF program list. From there it reaches childcare_expenses and household_child_care_subsidies. The latter caps subsidies at the SPM unit's whole bill, a cap that can no longer bind for Colorado, since the payment is now at most the eligible children's charges.
  • spm_unit_benefits and four contributed-reform benefit lists name it directly.
  • No other Colorado CCAP variable reads it.
  • co_ccap_child_eligible keeps its existing readers: co_ccap_eligible_children, which feeds entry and re-determination eligibility and the add-on fee, co_ccap_parent_fee, and, on main, co_ccap_child_in_care.

Housekeeping.

  • The changelog.d/co-ccap-eligible-children.fixed.md fragment is present.
  • Tests are in the variable-named co_ccap_subsidy.yaml. Cases 1-2 correctly move the charges from a default 40-year-old onto a 4-year-old.
  • The PR body's $1,800 to $800 example matches Case 3.
  • No new or edited comment matches the source-conflict ratchet's pattern list, so it passes on the merged tree (checked statically).

Python test cost (CI log). In Rest (Python shard 4), group remaining-2, the two properties ran in 7.45 s and 10.44 s. The PR body says per-file peak memory wasn't measured, as CLAUDE.md requires a PR to say when a measurement is unavailable.

Axiom line assessment

axiom: TheAxiomFoundation/rulespec-us#2073 queued is valid.

  • Status: the issue is OPEN and labelled pe-parity. It was created 2026-11-07 and last updated 2026-11-11.
  • Contents: two new module paths, the corpus citation (us-co/regulation/8-ccr-1403-1-eff-2026-08-14), verbatim text of every provision with PDF pages, the required outputs, 8 companion cases and three properties.
  • Blocker: recorded, as CLAUDE.md requires: the encoder run needs approval, and the pinned corpus release lacks the Colorado scope.
  • Match with the head: it describes co_ccap_child_eligible and co_ccap_subsidy as they are at the head. Companion Cases 1-6 mirror YAML Cases 3-8, which are hand-built from the same rule text, and no external calculator exists for this provision.
  • Deferrals: it explicitly defers the citizenship test, county rates, the fee formula and 3.114(B)(1).

CI status

At head 2eeea71, gh pr checks 10699 shows 36 pass and 3 skipping. The 3 skipping are placeholder jobs from an earlier workflow run. Nothing is pending and nothing failed.

  • New tests: the CI logs show both new properties PASSED in Rest (Python shard 4). The Baseline state shards that run the Colorado YAML all passed.
  • Timing: the run dates from 2026-11-09, before Charge Colorado families one child care parent fee under section 3.124 #10721 merged. A static read of the merged tree finds nothing that should fail (see Branch status). Merging main and re-running before merge would still be good practice, since the branch is 183 behind.

Branch status

The branch is 1 ahead and 183 behind main (merge base 7acea8e). git merge-tree --write-tree PolicyEngine/main 2eeea71ed3 is clean (tree 23117acf37).

  • Charge Colorado families one child care parent fee under section 3.124 #10721 (merged 2026-11-09): the only main commit since the merge base to touch Colorado CCAP. It rewrote the parent fee and court_supervision.yaml but not co_ccap_subsidy.py or co_ccap_subsidy.yaml.
    • This PR's YAML and properties set co_ccap_parent_fee as an input, so the new fee doesn't move them.
    • In main's court_supervision.yaml, Case 5 is an eligible court-supervised child (1,000 − 128 = 872), which this change leaves unchanged. Case 6 is an ineligible household (0), also unchanged.
  • Require an eligible activity for Colorado's child care assistance #10690 (same author, open): no conflict. It changes co_ccap_eligible.py and the activity test files, with no file in common, and merges cleanly with this head (merge-tree 5d828dc786). It narrows household eligibility, while this PR narrows the payment within an eligible household; this PR's tests set co_ccap_eligible as an input. The two can land in either order.
  • Cap Colorado's child care payment at the county reimbursement rate #10723 (open): it carries a rebased copy of this PR's commit (bcd8c28, same content) and then rewrites co_ccap_subsidy.py around county reimbursement. Whichever lands second will need a rebase.

Verdict: REQUEST_CHANGES

@DTrim99 DTrim99 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requesting changes: 0 critical, 1 should address, 3 suggestions (details in the report above).

  • The rule and the model: 8 CCR 1403-1 pays child by child, for children under 13 and for those under 19 who can't care for themselves or are under court supervision, and the household fee pays the first dollars. The new formula matches that and changes neither the fee nor household eligibility. All 8 YAML cases and 5 Hypothesis examples check by hand.
  • The should: co_ccap_subsidy.py:11-18 lists one rule PDF three times, differing only by #page. CLAUDE.md asks for one entry per document, with a # PDF pages ... comment, as the stacked #10723 already does.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants