Skip to content

Pay South Dakota CCA from the July 2024 hourly county rates - #10815

Merged
MaxGhenis merged 3 commits into
mainfrom
sd-cca-hourly-rates
Nov 14, 2026
Merged

MaxGhenis merged 3 commits into
mainfrom
sd-cca-hourly-rates

Conversation

@MaxGhenis

@MaxGhenis MaxGhenis commented Nov 11, 2026 •

Copy link
Copy Markdown
Contributor

Add South Dakota CCA payments from July 2024 through July 2026, when the model previously returned zero. DSS publishes separate hourly schedules for family care, centers, before-and-after-school programs, and informal, in-home and relative care.

Convert authorized weekly need to monthly hours under Section 8 of the June 2025 manual: multiply it by 4.3 and round up, as DSS does when it turns 45 weekly hours into 194 monthly hours. Multiply in float64, so 50 weekly hours give 215 monthly hours, where float32 arithmetic gives 216. Apply the published special-needs ceiling after DSS approval under Section 19. Cap reimbursement at billed expenses before subtracting the copayment under ARSD 67:47:01:15 and 67:47:01:16.

Update South Dakota's coverage note to name the hourly schedule, record the remaining limits, and say that the hourly special-needs ceiling needs the approval input. Add a changelog fragment and record the private-charge source conflict in source_conflicts/candidates.yaml.

Closes #10712

Invariants

  • For nonnegative billed expenses, sd_cca remains nonnegative and does not exceed those expenses. test_hourly_bounds_monotonicity_and_positive_payment checks these bounds; sd_cca.yaml checks expense caps, zero inputs and copayments that exceed allowed costs.
  • During the hourly era, increasing care hours or billed expenses cannot reduce the benefit when other inputs stay fixed. test_hourly_bounds_monotonicity_and_positive_payment compares separate simulations after each increase.
  • An eligible family receives a positive hourly benefit when its billed expenses and hourly reimbursement ceiling both exceed its copayment. The property test includes a low-income family with care hours, expenses and no copayment; sd_cca.yaml also checks covered hourly months.
  • In the hourly era, the model converts q quarter hours of weekly care to ceil(43q / 40) monthly hours. test_monthly_hours_round_exact_products_up checks every quarter hour from 0 to 100 weekly hours against integer arithmetic, and sd_cca.yaml pins 15, 40, 45, 50, 90 and 100 weekly hours.
  • From August 2026 onward, sd_cca retains main's weekly formula. test_weekly_formula_matches_main independently aggregates weekly ceilings and samples periods from August 2026 through December 2030. sd_cca_weekly_rate.yaml also checks the school-program mapping.
  • Both new approval or qualification inputs default to false. Those defaults select ordinary hourly rates. Positive hourly payments before August 2026 intentionally change main's zero result; the new inputs do not change weekly payments.

See policyengine_us/tests/core/test_sd_cca_hourly_rates_invariants.py for the property tests. The YAML cases under policyengine_us/tests/policy/baseline/gov/states/sd/dss/cca/ check benefits and rates; rates/sd_cca_hourly_rate.yaml pins county rates, age boundaries, provider categories, enhancements and county defaults.

Methodology choices

  • Apply the benefit bounds to nonnegative billed expenses and test positive payments for a family with no copayment. Eligibility, care hours and bills can still produce zero when the copayment exhausts allowable costs.
  • Use reported care hours as DSS-authorized weekly need. The model does not derive that need from work, class, travel, between-class or school-vacation hours.
  • Multiply weekly need by 4.3 and round monthly hours up. DSS converts 45 × 4.3 = 193.5 into 194 monthly hours in its manual example. DSS gives no general monthly rounding instruction; upward rounding follows that example.
  • Apply no universal monthly hours cap. DSS limits CPS coupons to 210 hours per month and uses 45 hours per week for its optional TANF arrangement. Those provisions do not cap ordinary CCA authorization.
  • Carry the existing non-rate eligibility, income and copayment conventions back to July 2024 using the June 2025 manual and older regulations. We did not verify each convention's original effective date.
  • Reuse sd_cca_provider_type. Family care uses the family sheet; licensed centers use the center sheet; informal, in-home and relative providers use the flat informal sheet. Add a separate before-and-after-school value for the hourly school-program sheet; weekly payments use the licensed-center table.
  • Use hourly age bands of under three, three through five, and six or older for family and center care. School programs use their all-age county rate. Keep the weekly age and school-enrollment classification unchanged.
  • Retain Aurora County when callers omit county. That default can overstate family infant rates or understate other county rates. Use the minimum published rate for each provider type and age band when callers supply an unrecognized county; that fallback can understate payments.
  • Require the specialized-rate input to record completed family-provider registration and a capacity of six or fewer children. Apply the 25% enhancement only to family care for children under three. Preserve the published differences between age-band rates.
  • Require separate DSS approval for the $6.80 special-needs ceiling. Apply it to all provider types using the state plan's broad provider language and the informal guide's approval process. Do not stack the infant enhancement onto that ceiling. Leave negotiated rates above $6.80 unmodeled. Retain the weekly disability-based special-needs proxy to preserve main's weekly results.
  • Pool per-child reimbursement ceilings against the SPM unit's billed expenses. The expense input does not separate child or provider bills, so the model cannot reproduce every provider-level cap or copayment allocation.
  • Pay zero before July 2024 because we could not confirm an earlier complete schedule.
  • Retain the monthly transition on August 1, 2026 for DSS's August 3 weekly effective date. Do not split August between hourly and weekly calculations.
  • Follow the public-charge and actual-cost limits in ARSD 67:47:01:15–16 and the operational provider guide. Both the original state plan and Amendment 1 contain a conflicting checkbox. Record that reading as us-sd:cca-hourly-private-pay-cap without adding a source-conflict marker.
  • Normalize the sheets' spelling of Mellette County to the existing county key. Keep the per-person self-employment input limit and other existing eligibility proxies unchanged. Retain South Dakota's partial coverage status.

Validation

Pull request run 43603230729 at 0eb611de13 passed all 36 jobs on GitHub's merge with main 3ab9b19a11.

Targeted YAML tests pass: sd_cca.yaml (28), sd_cca_hourly_rate.yaml (25), and sd_cca_weekly_rate.yaml (17). The three tests in test_sd_cca_hourly_rates_invariants.py pass, as do 103 source-conflict checks and 872 program-registry checks (10 skipped). Ruff format and lint pass.

Three mutants of the monthly-hours conversion each fail tests. Multiplying in float32 fails Cases 26 to 28 and test_monthly_hours_round_exact_products_up; those cases then pay $820.80, $1,474.40 and $1,637.80 for 216, 388 and 431 hours. Rounding half to even fails Case 25 and the same test. Dropping the rounding fails Cases 22 and 25.

The quarter-hour test adds one 401-household simulation to the core Python group, with a 0.12-second call. On a local macOS run with four numeric threads, the property file took 45 seconds of wall time and peaked at 1.27 GiB. Before the new test, it took 34 seconds and peaked at 1.27 GiB; host load varied between the two runs.

Microsimulation impact

We estimate that this branch changes none of the outputs below in 2025 on the default dataset. We compared main at 75aee22d6d with this branch at 0eb611de13.

Output Main total Change Records changed (weighted)
sd_cca $0 $0 0 (0)
sd_child_care_subsidies $0 $0 0 (0)
child_care_subsidies $1.68bn $0 0 (0)
state_income_tax $548.1bn $0 0 (0)
income_tax $2,422.0bn $0 0 (0)
household_benefits $1,955.3bn $0 0 (0)
household_net_income $16,380.9bn $0 0 (0)

We estimate that this branch changes none of the outputs below in 2026 on the default dataset. We compared the same two commits.

Output Main total Change Records changed (weighted)
sd_cca $0 $0 0 (0)
sd_child_care_subsidies $0 $0 0 (0)
child_care_subsidies $1.72bn $0 0 (0)
state_income_tax $577.2bn $0 0 (0)
income_tax $2,594.9bn $0 0 (0)
household_benefits $2,060.4bn $0 0 (0)
household_net_income $17,199.2bn $0 0 (0)

On that dataset, we estimate $0 of South Dakota child care assistance in 2025 and 2026 at both commits, so the household tests above show what this change does.

axiom: TheAxiomFoundation/rulespec-us#2232 queued (ARSD 67:47:01:10.02, 67:47:01:15 and 67:47:01:16 and DSS's July 2024 hourly rate sheets; the corpus lacks those sheets and the June 2025 manual, so the signed encoder can't run yet)

🤖 Generated with Claude Code

MaxGhenis and others added 2 commits November 11, 2026 18:55
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Set calendar-year inputs for the hourly start and weekly transition cases.
Link the private-charge source conflict to its draft pull request.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Multiply weekly care hours by 4.3 in float64. In float32, 50 weekly
hours times 4.3 gave 215.0000153, and rounding up paid 216 hours
instead of 215. The same error added an hour at 90, 100 and 110
weekly hours.

Add cases at 15, 50, 90 and 100 weekly hours, and check every quarter
hour from 0 to 100 weekly hours against integer arithmetic. Note in the
coverage entry that the hourly special-needs ceiling needs the DSS
approval input.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaxGhenis
MaxGhenis marked this pull request as ready for review November 14, 2026 00:18
@MaxGhenis MaxGhenis closed this Nov 14, 2026
@MaxGhenis MaxGhenis reopened this Nov 14, 2026
@MaxGhenis MaxGhenis closed this Nov 14, 2026
@MaxGhenis MaxGhenis reopened this Nov 14, 2026
@codecov

codecov Bot commented Nov 14, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (aae7f98) to head (0eb611d).
⚠️ Report is 261 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff            @@
##              main    #10815   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files            1         5    +4     
  Lines           37        89   +52     
  Branches         0         2    +2     
=========================================
+ Hits            37        89   +52     
Flag Coverage Δ
unittests 100.00% <100.00%> (ø)

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

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

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

@MaxGhenis

Copy link
Copy Markdown
Contributor Author

US + core hub merge audit, us#10815 at 0eb611de13a3913ad3234389b49f0c5e5415791e (squash): Pay South Dakota CCA from the July 2024 hourly county rates.

  • Reviews:
    • The PR has no GitHub reviews. Two independent review rounds ran outside GitHub, with a fix round between them.
    • The first round, at 56a6d6d19d, fetched DSS's four hourly rate sheets effective July 1, 2024. A script compared every county's family, center and school-program rates with the YAML, and all matched. It also checked the informal rate, the $6.80 special-needs ceiling and the 25% specialized infant and toddler rate.
    • It read Sections 8, 9, 11 and 19 of DSS's June 2025 manual, Amendment 1 to the 2025-2027 state plan, and ARSD 67:47:01:15 and 67:47:01:16. It computed 18 households by hand and ran them on the head and on the merge base 75aee22d6d. The base paid nothing in every hourly month, and weekly results matched on both.
    • It found that float32 arithmetic added a monthly hour at 50, 90 and 100 weekly hours, so 50 hours paid $820.80 instead of $817.00. A mutant that swapped the round-up for np.round passed every case then in sd_cca.yaml. It also asked for a population estimate and a description without process passages, and suggested a coverage-note clause on the special-needs approval input.
    • The fix round, at 0eb611de13, multiplied in float64 before rounding up. It chose that over round 1's two-decimal rounding, which gives 39 monthly hours at 9.07 weekly hours where the rule gives 40. It added Cases 25 to 28 at 15, 50, 90 and 100 weekly hours, and a test that checks every quarter hour from 0 to 100 against integer arithmetic. It added the coverage-note clause and cut the process passages. Each of three mutants of the conversion failed a case: float32 arithmetic, rounding half to even and no rounding.
    • The second round approved 0eb611de13 with no blocking finding. It showed that, for any input, the float64 product can't land above a whole-number exact product, so the round-up can't add an hour. It matched exact fractions at 10 weekly hour values and re-fetched the family, school-program and informal sheets and the manual capture.
    • All 70 YAML cases in the three South Dakota CCA files passed, as did the three property tests, 103 source-conflict checks and 872 program-registry checks, with 10 skipped. Nine more households, from 9.07 to 110 weekly hours, matched its hand values, including the specialized, school-program, special-needs and informal rates.
    • With the cast removed, Cases 26 to 28 and 3 of 401 quarter-hour inputs failed. With np.round, Case 25 and 195 of 401 inputs failed. git merge-tree against main showed no conflict, and CI passed at the head.
    • It listed two minor findings. On main, South Dakota's work requirement multiplies weekly work hours by 4.3 in float32 before rounding up, in a file this PR doesn't touch. The changelog fragment, typed fixed, starts with "Added". The merge fixes neither, and both stay open under Next.
    • The reviews listed corrections to the description, and the fix round and I made each before merge. The description names three mutants that each fail, gives current test counts and drops the process passages. It says 50 weekly hours give 215 monthly hours where float32 arithmetic gives 216, adds the population estimate and uses an accepted axiom: form.
  • Methodology choices for maintainers:
    • Reported weekly care hours stand in for DSS-authorized need. The model doesn't derive need from work, school or travel hours.
    • DSS's manual multiplies weekly need by 4.3 and gives no general rounding rule. The PR rounds up, as the manual's example turns 45 weekly hours into 194 monthly hours. Without the round-up, Case 25 would pay for 64.5 hours, $245.10 instead of $247.00.
    • The model applies no general monthly hours cap. DSS limits child protection coupons to 210 hours a month and uses 45 hours a week for its optional TANF arrangement. A maintainer who read 210 hours as a general cap would cut Case 28 from $1,634.00 to $798.00.
    • The household's county stands in for the county where the child receives care. When a household gives no county, the model's default county, Aurora, sets the rate: $3.15 an hour for family care under 3, where Minnehaha pays $3.80. An unrecognized county gets the lowest published rate for its provider type and age band.
    • The hourly special-needs ceiling needs a new DSS-approval input, while weekly months keep main's disability proxy. A disabled child without that approval gets the ordinary hourly rate. Amendment 1 to the state plan gives the $6.80 rate "regardless of the age of child or county" and names no provider type, so the model applies it to informal care too.
    • The specialized input records a family provider's completed registration for six or fewer children. It raises the rate 25% for a child under 3 in family care and doesn't stack on the special-needs ceiling. Both new inputs default to false, so population estimates pay ordinary rates in every hourly month.
    • The model pools each child's hourly ceiling against the SPM unit's billed expenses, since the expense input doesn't separate children or providers. Where DSS caps each provider's bill, pooling can pay a family with two providers more than DSS does. Where the copay exceeds the need of the child whose provider carries it, pooling can pay less. In the manual's Section 9 example, DSS denies a $405 need below the $450 copay and certifies the other child's $375 need, where pooling pays $780 less $450, or $330.
    • The PR follows ARSD 67:47:01:15 and 67:47:01:16 and DSS's provider guide over the state plan's private-pay checkbox, and caps payments at billed expenses. It records the conflict as candidate us-sd:cca-hourly-private-pay-cap without a marker.
    • Main's income, eligibility and copay parameters start on August 1, 2026, and the model applies them from July 2024. The June 2025 manual uses the same 209% FPG income limit, 4% earned income disregard and copay rule. Round 1 found that ARSD 67:47:01:03, 67:47:01:05 and 67:47:01:05.01 predate July 2024, but the PR didn't verify each value for the months before June 2025.
    • The model pays nothing before July 2024, since the PR found no earlier complete schedule. It switches to weekly rates on August 1, 2026, two days before DSS's August 3 start, and doesn't split August.
  • Gates checked live at merge:
    • gh pr checks exits 0;
    • the latest Pull request run at the head, 43603230729, passed and tested this head merged into main at 3ab9b19a11;
    • MERGEABLE;
    • not a draft;
    • no reviewer's latest review requests changes;
    • the semantic-overlap guard: since 3ab9b19a11, main has changed no area this PR touches. Main changed nothing under sd/dss/cca, and no line it changed outside tests names childcare_hours_per_week, spm_unit_pre_subsidy_childcare_expenses or county_str, which this PR reads. Among open PRs, Count railroad retirement benefits as income in state and county benefit programs #10764 also changes South Dakota CCA: it adds railroad retirement to the income sources, a file this PR doesn't touch;
    • the merge pins the head.
  • Impact: we estimate no change in 2025 or 2026 on the default dataset. sd_cca and sd_child_care_subsidies total $0 at main 75aee22d6d and at 0eb611de13 in both years, and child_care_subsidies, state and federal income tax, household benefits and household net income don't move. The household tests show the change.
  • Next:
    • On main, sd_cca_parent_in_eligible_activity.py line 21 multiplies weekly work hours by 4.3 with no float64 cast before rounding up. Round 2's offline check gave 216 monthly hours at 50 weekly hours, so the earnings test would ask for one more hour's pay; it ran no model case. A separate PR can add the cast.
    • specialized_infant_toddler_multiplier.yaml cites DSS's family rate sheet. A follow-up can add ARSD 67:47:01:10.02, under which a family provider for infants and toddlers who limits care to six or fewer children may get a rate 25 percent higher.
    • The changelog fragment, typed fixed, starts with "Added", and the release commit after merge will file it under Fixed in CHANGELOG.md. A later PR can start that entry with "Fixed".
    • DSS no longer serves the June 2025 manual at its old dss.sd.gov address, so the code and description cite an Internet Archive capture from October 31, 2025. If DSS posts the manual again, the references can move back.
  • Axiom: Encode South Dakota child care assistance from July 2024 to July 2026: hourly county rates, monthly care hours and the billed-expense cap (ARSD 67:47:01:10.02, 67:47:01:15 and 67:47:01:16; DSS rate sheets effective July 1, 2024) (PE-US #10815) TheAxiomFoundation/rulespec-us#2232 queued, a new pe-parity issue for ARSD 67:47:01:10.02, 67:47:01:15 and 67:47:01:16 and DSS's hourly rate sheets effective July 1, 2024, with companion rows from this PR's YAML. The signed encoder can't run yet: the corpus holds none of the four hourly sheets or the June 2025 manual, and its pinned release carries no South Dakota child care rules.

🤖 Generated with Claude Code

@MaxGhenis
MaxGhenis deleted the sd-cca-hourly-rates branch November 14, 2026 15:27
MaxGhenis added a commit that referenced this pull request Nov 14, 2026
Main now holds South Dakota's hourly child care rates (#10815), whose
source-conflict candidate ends candidates.yaml, where this branch adds
New York's. Keep both candidates, South Dakota's first.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
MaxGhenis added a commit that referenced this pull request Nov 14, 2026
Keep both new source-conflict candidates: South Dakota's hourly child
care cap from #10815 and Minnesota's AMT charitable floor.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

South Dakota CCA: model the hourly county rates before August 2026

1 participant