Skip to content

Implement Wisconsin Shares Child Care Subsidy Program (CCAP) - #9062

Open
hua7450 wants to merge 12 commits into
PolicyEngine:mainfrom
hua7450:wi-ccap
Open

Implement Wisconsin Shares Child Care Subsidy Program (CCAP)#9062
hua7450 wants to merge 12 commits into
PolicyEngine:mainfrom
hua7450:wi-ccap

Conversation

@hua7450

@hua7450 hua7450 commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator

Implement Wisconsin Shares Child Care Subsidy Program (WI CCAP)

Summary

Implements the Wisconsin Shares Child Care Subsidy Program (Wisconsin's CCDF child care assistance program, administered by the Department of Children and Families) in PolicyEngine: eligibility (residency, child age/immigration, approved activity, income, assets), the full 72-county × provider-type × age-group maximum rate matrix, and the hours-based copayment schedule, netting to a per-child monthly subsidy aggregated in wi_shares / wi_child_care_subsidies.

Closes #9060

Regulatory Authority

Income Eligibility Tests

Wisconsin Shares applies two different gross-income limits depending on whether the assistance group (AG) is already enrolled. The model switches between them with the boolean input is_wi_shares_enrolled (SPMUnit, MONTH, default false), following the ND/NJ two-tier pattern:

Tier Limit Source How modeled
Initial (applicants, and AGs closed for more than one calendar month) Gross monthly income ≤ 200% FPL Handbook § 6.1.1; Wis. Stat. § 49.155(1m)(c)1.; LFB #211 income/limit/initial_fpg_rate.yaml (2.0) × spm_unit_fpg
Ongoing (enrolled) Gross monthly income ≤ 85% of State Median Income for the AG size Handbook § 6.1.2; Wis. Stat. § 49.155(1m)(c)1d.b. income/limit/ongoing_smi_rate.yaml (0.85) × hhs_smi

Enrolled families between 200% FPL and 85% SMI remain eligible during the "Exit period": eligibility only ends when income exceeds 85% SMI or the copayment reduces the subsidy to $0 (Handbook §§ 18.2.2, 18.4.2). This emerges naturally in the model: wi_shares_income_eligible gates enrolled families only on the SMI test, and wi_shares_child_subsidy floors at $0 without affecting eligibility.

Income Deductions & Exemptions

wi_shares_countable_income sums 12 gross income sources (income/sources.yaml: employment, self-employment, dividends, interest, rental, Social Security, pensions, unemployment compensation, workers' compensation, alimony, veterans benefits, capital gains) plus formula-level handling per Handbook §§ 6.2–6.3:

Provision Source How modeled
Child/family support ≤ $1,250/month fully disregarded; if the total exceeds $1,250/month the entire amount counts (a cliff, not a deduction) Handbook § 6.3 where(cs > cap, cs, 0) with income/child_support_disregard_cap.yaml ($1,250)
Earned income and SSI of minor dependents disregarded; adults' SSI counts Handbook §§ 6.2–6.3 Exclude earnings + ssi for persons with age < 18 who are not tax-unit head/spouse (income/minor_income_disregard_age.yaml)
W-2 (Wisconsin Works) payments, foster care, Kinship Care, subsidized guardianship, and adoption assistance payments excluded Handbook § 6.3 Omitted from sources.yaml by design (also avoids the CCAP↔TANF income cycle)
Self-employment = net IRS earnings plus statutory add-backs (depreciation, personal business expenses, capital purchases, loan principal) Handbook §§ 6.2, 6.4.4 Net self_employment_income only; add-backs have no PolicyEngine inputs (documented in the variable); total income floored at 0

There is no living-expense deduction — the test uses gross income.

Benefit Calculation

Per eligible child with positive care hours, per month (Handbook § 18.5; verified against the Appendix II worked examples):

time_category    = PART_TIME if weekly care hours ≤ 20 else FULL_TIME        (§ 16.1.1)
subsidized_hours = 131 (PT) | 153 (FT)                                       (§ 18.5)
                   # fixed conversions: ceil(30 × 4.348125), ceil(35 × 4.348125)
                   # — not the child's actual hours
hourly_max       = rate[county][provider type][age group]                    (§ 18.5.1)
                   # certified = 90% of licensed-family hourly, ceiling-
                   # rounded to the cent (§ 49.155(6)(b)–(c))
monthly_max      = PT: hourly × 131 (exact) | FT: transcribed FT-monthly cell
                   # certified providers capped at the licensed-family monthly max
subsidy          = min(hourly_max × subsidized_hours, provider price, monthly_max)
above_ft_add_on  = min(max(weekly hours − 50, 0), 25) × 4.348125 × hourly_max
                   # for care needs above 50 up to 75 weekly hours,
                   # added AFTER the min() cap (§§ 16.1.1, 18.5)

The AG copayment (Handbook § 18.2; Copayment Schedule eff. 2/1/2026; Wis. Stat. § 49.155(5)(a)):

FPL band       = AG gross monthly income / FPG, floored to the LOWER 5% line,
                 65%–200% (bracket thresholds shifted −1e-4 for float boundaries)
copay per hour = schedule[FPL band][number of children with authorizations, capped at 5]
                 # $0.00 for all bands at or below 100% FPL
copay hours    = per child: 131 (PT) | 152 (FT), AG total capped at 760
                 # the 153rd FT subsidized hour is not charged a copay
AG copay       = copay per hour × AG copay hours + exit add-on
exit add-on    = $1 × floor((income − 200% FPL) / $5), enrolled AGs only
                 (§ 18.2.1; § 49.155(1m)(c)1d.a.)
child share    = child's capped hours / AG capped hours × AG copay
wi_shares      = Σ over children of max(subsidy + above_ft_add_on − child share, 0)

If the copayment equals or exceeds the subsidy, the family receives $0 but remains eligible (§ 18.2.2). Children with a $0 copayment type — Foster (is_in_foster_care) and W-2 Participant (is_tanf_enrolled) — are excluded from the copay hours pool (§ 18.3).

Worked example (Appendix II Example 1, reproduced as integration test case 1): two part-time children at 115% FPL → copay per hour $0.65 (two-children column) × 262 copay hours (2 × 131) = $170.30.

Rate Structure

Maximum rates are a 72-county × provider-type (Licensed Group / Licensed Family / Certified) × age-group (0–1, 2–3, 4–5, 6+) × form (Hourly / PT Monthly / FT Monthly) matrix from the statewide table, pp. 26–40 (effective 10/1/2025), following the NC SCCA county-keyed precedent:

  • Transcribed: Hourly and FT Monthly cells for Licensed Group and Licensed Family (FT Monthly is a whole-dollar weekly rate × 4.348125, not a multiple of the hourly rate, so each cell is transcribed).
  • Derived exactly: PT Monthly = Hourly × 131 (verified exact across the table); Certified hourly = 90% of the Licensed Family hourly, ceiling-rounded to the cent (rates/certified_licensed_rate_ratio.yaml; Handbook § 18.5.1; § 49.155(6)(b)–(c)). Certified providers have no monthly maximum of their own; monthly payments are capped at the Licensed Family monthly maximum.
  • County lookups mask non-WI counties before indexing (defined_for does not short-circuit vectorized execution).
  • Tribal-agency rate rows are not modeled (no tribal geography in PolicyEngine).

Requirements Coverage

30 in-scope requirements, all covered; every parameter file is read by at least one formula (no orphans). Condensed mapping (grouped where requirements share files):

REQ Description Param Variable Test
001 WI residency wi_shares_eligible (defined_for chain) integration case 7 (MN family gets $0)
002, 003 Eligible child: under 13, or under 19 disabled; child must be citizen/qualified immigrant eligibility/child_age_limit (13), disabled_child_age_limit (19) wi_shares_eligible_child (reuses is_ccdf_immigration_eligible_child) wi_shares_eligible_child.yaml (9 cases)
004, 006 All parents in approved activity (employment, education, W-2), incl. Learnfare/teen-parent via student path; meets_ccdf_activity_test fallback wi_shares_activity_eligible, wi_shares_parent_in_approved_activity both YAMLs (12 cases)
007–009 Initial ≤200% FPL; ongoing ≤85% SMI; exit-period retention until copay ≥ subsidy income/limit/initial_fpg_rate (2.0), ongoing_smi_rate (0.85) wi_shares_income_eligible wi_shares_income_eligible.yaml (8 cases); integration cases 3, 5, 6, 8
010–012 Counted sources; child-support cliff; minor-dependent disregard; self-employment income/sources, child_support_disregard_cap ($1,250), minor_income_disregard_age (18) wi_shares_countable_income wi_shares_countable_income.yaml (10 cases)
014, 017 Liquid assets ≤ $25,000; foster exemption eligibility/asset_limit wi_shares_asset_eligible wi_shares_asset_eligible.yaml (5 cases)
018, 019 PT ≤ 20 weekly hours / FT > 20; fixed 30/35-hour conversions → 131/153 monthly hours hours/part_time_max_weekly_hours (20), part_time_weekly_conversion (30), full_time_weekly_conversion (35), weeks_per_month (4.348125) wi_shares_time_category, wi_shares_monthly_subsidized_hours time_category (4 cases, 20/21 boundary), monthly_subsidized_hours (2 cases)
020 Above-full-time add-on (hours over 50, up to 75), added after cap hours/above_full_time_threshold (50), above_full_time_cap (75) wi_shares_child_subsidy child_subsidy cases 4, 5, 7
023, 024 72-county rate matrix; certified = 90% of licensed family (ceil to cent), LF monthly cap rates/licensed_group/*, licensed_family/*, certified_licensed_rate_ratio (0.9), age_group wi_shares_hourly_max_rate, monthly_max_rate, age_group, provider_type (input) hourly_max_rate (8), monthly_max_rate (5), age_group (8)
025 Subsidy = min(hourly × hours, provider price, monthly max) wi_shares_child_subsidy child_subsidy cases 3, 8
030–032 FPL band 65–200% in 5% steps (floor to lower line); per-hour table [band × 1–5+ children]; $0 at ≤100% FPL copay/per_hour/{one…five_or_more}_children (20 brackets each) wi_shares_copay_per_hour copay_per_hour.yaml (10 cases, all 5 columns + boundaries)
033, 034 Copay hours 131 PT / 152 FT per child, AG cap 760; AG copay = hours × rate; proportional child share copay/hours/per_child_cap (152), assistance_group_cap (760) wi_shares_copay_hours, wi_shares_copay copay_hours (4 cases), copay cases 1, 2, 7
035 Exit period: 200% band rate + $1 per $5 over 200% FPL copay/exit/phase_out_rate (0.2) wi_shares_copay copay cases 4, 9; integration cases 3, 5
036 Copay ≥ subsidy → $0 paid, still eligible wi_shares_child_subsidy (max_(…, 0)) child_subsidy case 1; integration case 4 (Ebony)
037 $0-copay types: Foster, W-2 Participant wi_shares_copay, wi_shares_copay_hours copay cases 5, 6, 8; copay_hours case 4
043 Top-level variable + aggregator + both registries gov/hhs/ccdf/child_care_subsidy_programs.yaml, programs.yaml wi_shares, wi_child_care_subsidies wi_shares.yaml; integration case 2 asserts wi_child_care_subsidies
044 Enrollment input for two-tier tests + exit copay is_wi_shares_enrolled (input) used across income, copay, integration tests
045 True effective dates rates 2025-10-01, copay 2026-02-01 all 125 cases at period 2027-01, incomes derived from FPL/SMI ratios

Not Modeled

REQ Provision Source Why excluded
005 Temporary break ≤ 3 months preserves eligibility Wis. Stat. § 49.155(1m)(a)6. Month-to-month continuity is not simulatable; the meets_ccdf_activity_test input covers it if needed
013 Weekly income × 4.3 → monthly conversion Handbook § 6.4 PolicyEngine income inputs are annual and auto-converted; no raw-frequency input exists
015 Home value ≤ 200% of statewide median Wis. Stat. § 49.155(1m)(cr)1. The operational Handbook § 6.5 tests liquid assets only; documented in the asset variable
016 Combined vehicle equity ≤ $20,000 Wis. Stat. § 49.155(1m)(cr)2. Same — the operational asset test is liquid-only
021 Max 12 hours of care per 24-hour period Handbook § 16.1.2 No sub-daily scheduling in PolicyEngine
022 School-closed hours added to part-time authorizations Handbook §§ 16.1.1.4.2, 18.5 No school-calendar tracking
026 Tribal-agency rate rows Max rates pp. 26–40 No tribal geography in PolicyEngine; county rows only
027 Out-of-state accredited provider +10% Handbook § 18.5 Provider location is not modeled
028 YoungStar 4/5-star quality adjustment (8%/16% from Feb 2026) https://dcf.wisconsin.gov/youngstar/providers/quality-adjustment Provider-side bonus on subsidy authorization dollars; does not change the family's subsidy or out-of-pocket cost
029 Rate-setting mechanics (≥75% slot purchasability, market survey, freeze authority) Wis. Stat. § 49.155(6)(a) Informational — rates are transcribed from the published schedule, not derived
038 Minimal (65%-FPL-based) copay types: Non-Court-Ordered Kinship, Teen High School, W-2 Emp End Handbook § 18.3 The 65% FPL row is $0.00 on the current schedule, so the modeled $0 outcome coincides; documented
039 Copayment stabilization across the certification period Handbook §§ 18.4–18.4.3 Requires month-to-month certification history; model is point-in-time
040 Federal 7%-of-income copay cap; 150% FPL waiver 45 CFR 98.45; LFB #211 The 2/1/2026 schedule already complies below 200% FPL; the waiver/ceiling were 2025–27 budget proposals, not verified as enacted; a defensive cap would corrupt the legitimate exit-period add-on
041 Parent Share / EBT delivery mechanics Handbook § 18.1 Payment plumbing; the family's residual expense is implicit in provider price − subsidy
042 Registration/enrollment fees (≤ 2 per child per 12 months) DCF 201 rulemaking Provider-side fee; no registration-fee input

Historical Notes

  • Current-era coverage only. Parameters start at their true effective dates: maximum rates 2025-10-01, copayment schedule 2026-02-01. Income limits are encoded as rates (2.0 × FPG, 0.85 × SMI) rather than transcribed dollar tables, so they track FPG/SMI updates automatically.
  • Pre-era months do not return $0. wi_shares carries no effective-date gate, so policyengine-us parameter backdating (system.py, first_instant="2015-01-01") applies the current-era schedules to earlier periods. A household modeled in any month from 2021-01 through 2025-09 receives the same subsidy it would in 2027, and that amount also flows into the federal child_care_subsidies aggregate. The same mechanism applies the 2026-02-01 copayment schedule from 2025-10-01 onward, four months before it took effect. Treat pre-2025-10-01 Wisconsin Shares results as unmodeled rather than as a statement of prior law; backdating the true historical rate and copayment tables is planned. This is documented in wi_shares_child_subsidy.
  • Initial income limit history not backdated (per scope decision): before ~2021 the initial limit was 185% FPL; 2021 Wis. Act 58-era changes raised it to 200% FPL. Backdating would require verifying the exact effective date.
  • Exit-period add-on rate changed in FY 2024-25: $1 per $3 before, $1 per $5 beginning FY 2024-25 (Wis. Stat. § 49.155(1m)(c)1d.a.). Only the current $1-per-$5 rate is encoded, consistent with the coverage window.
  • DCF 201 proposed copay simplification NOT adopted: the proposed rule would have dropped authorized hours and number of children from the copay formula, but the operational 2/1/2026 schedule and Handbook § 18.2 (updated 7/1/2026) still use hours × number of children. The published schedule governs this implementation.
  • Maximum rates are not indexed annually — they remain frozen until DCF republishes.

Files Added

policyengine_us/parameters/gov/states/wi/dcf/shares/          28 files
├── age_group.yaml                                            (age thresholds 2, 4, 6)
├── eligibility/{child_age_limit, disabled_child_age_limit, asset_limit}.yaml
├── income/
│   ├── limit/{initial_fpg_rate, ongoing_smi_rate}.yaml
│   └── {sources, child_support_disregard_cap, minor_income_disregard_age}.yaml
├── hours/{part_time_max_weekly_hours, part_time_weekly_conversion,
│          full_time_weekly_conversion, weeks_per_month,
│          above_full_time_threshold, above_full_time_cap}.yaml
├── copay/
│   ├── per_hour/{one_child, two_children, three_children,
│   │             four_children, five_or_more_children}.yaml  (FPL-band brackets)
│   ├── hours/{per_child_cap, assistance_group_cap}.yaml
│   └── exit/phase_out_rate.yaml
└── rates/
    ├── licensed_group/{hourly, full_time_monthly}.yaml       (72 counties × 4 age groups)
    ├── licensed_family/{hourly, full_time_monthly}.yaml      (72 counties × 4 age groups)
    └── certified_licensed_rate_ratio.yaml

policyengine_us/variables/gov/states/wi/dcf/shares/           20 files
├── wi_shares.py  wi_child_care_subsidies.py  wi_shares_child_subsidy.py
├── eligibility/  wi_shares_eligible, wi_shares_eligible_child,
│                 wi_shares_income_eligible, wi_shares_asset_eligible,
│                 wi_shares_activity_eligible, wi_shares_parent_in_approved_activity,
│                 is_wi_shares_enrolled (input)
├── income/       wi_shares_countable_income
├── hours/        wi_shares_time_category, wi_shares_monthly_subsidized_hours,
│                 wi_shares_copay_hours
├── rates/        wi_shares_provider_type (input), wi_shares_age_group,
│                 wi_shares_hourly_max_rate, wi_shares_monthly_max_rate
└── copay/        wi_shares_copay_per_hour, wi_shares_copay

policyengine_us/tests/policy/baseline/gov/states/wi/dcf/shares/   18 files, 125 cases
├── integration.yaml (9 cases)  wi_shares.yaml  wi_shares_child_subsidy.yaml
├── eligibility/ (6 files)  income/ (1)  hours/ (3)  rates/ (3)  copay/ (2)

Registry edits (2):
├── policyengine_us/parameters/gov/hhs/ccdf/child_care_subsidy_programs.yaml
│                                            (adds wi_child_care_subsidies)
└── policyengine_us/programs.yaml            (WI state implementation under CCDF)

changelog.d/wi-ccap.added.md

Test plan

  • 125 test cases across 18 YAML files pass locally (policyengine-core test policyengine_us/tests/policy/baseline/gov/states/wi/dcf/shares -c policyengine_us), including all 5 Handbook Appendix II worked examples reproduced as integration tests (Juniper $170.30 copay, Monique $197.60 copay, Renee exit-period $31 add-on, Ebony copay ≥ subsidy → $0 while eligible, Sarafina $15.24 — the Handbook prose's "$13.25" is a typo; the printed inputs yield $15.24)
  • make format clean (ruff format and ruff check pass)
  • CI passes

hua7450 and others added 10 commits July 16, 2026 12:19
Scaffolds the branch for PolicyEngine#9060 (Wisconsin Shares Child Care Subsidy
Program). Implementation to follow.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ne#9060)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Add farm_operations_income, partnership_s_corp_income, farm_rent_income,
  estate_income to countable income sources (Handbook 6.2)
- Extend minor-dependent earned income disregard to farm/partnership SE income
- Deep-link statute citations to subsections (/155/5, /155/6)
- Fix DCF-201 citation page and title; Appendix II titles; comment corrections
- Tests: federal aggregator assertion, 760-hour-cap per-child allocation,
  decisive SE-loss activity cases, new-sources coverage (129 passing)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The five copay schedules shifted every band edge down by 0.0001 as a
float32 workaround, which charged the higher band to income marginally
below a legal boundary. Restore the exact thresholds and instead compute
the FPL ratio in float64 rounded to 5 decimals before the bracket
lookup, so exact-edge incomes stay in their band per Handbook 18.2.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…, citation polish

- Add sstb_self_employment_income to countable income sources, the
  minor-dependent earned-income disregard, and the approved-activity
  self-employment evidence check (3 symmetric sites) + 2 pinning tests
- Mirror the float64 band-lookup guard on the exit-copay floor
- Ceil above-full-time add-on hours per the handbook rounding convention
  (2 test expectations recomputed)
- Deepen Wis. Stat. 49.155 references to exact subsections; note the
  pp. 26-40 span on the county rate matrices; document the copay
  column-count and band-lookup interpretations

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
breakdown: [county, ...] made core homogenize the four rate tables
across all 3,236 County enum values (+64,727 nodes, +52% whole-tree),
inflating reform-test deepcopies from 736 MB to 1,163 MB and OOM-killing
the congress and Rest CI legs (the 'runner shutdown' failures).

Adopt the MN CCAP layout: breakdown lists only wi_shares_age_group,
county names are literal nested keys (not homogenized), and the rate
variables index p[age_group][county] with the existing non-WI masking.
All county/age/date values byte-identical (round-trip verified); tree
back to 127,566 descendants vs 126,042 on main.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@hua7450
hua7450 marked this pull request as ready for review July 18, 2026 23:55
hua7450 and others added 2 commits August 11, 2026 10:25
wi_shares carries no effective-date gate, so parameter backdating applies
the 2025-10-01 maximum rates and the 2026-02-01 copayment schedule to
earlier periods rather than returning zero. Record the coverage window and
the planned backdating in wi_shares_child_subsidy so pre-2025-10-01 results
read as unmodeled rather than as a statement of prior law.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…into wi-ccap

# Conflicts:
#	policyengine_us/programs.yaml
@hua7450
hua7450 requested a review from DTrim99 August 12, 2026 13:31
@DTrim99

DTrim99 commented Aug 12, 2026

Copy link
Copy Markdown
Collaborator

Program Review — Wisconsin Shares (new program)

PR #9062 — Wisconsin Shares Child Care Subsidy (WI CCAP / CCDF). Tree: gov.states.wi.dcf.shares. Agency: Wisconsin DCF.

Scope

A large, well-executed NEW-program PR implementing Wisconsin's Shares child care subsidy: 20 variables and ~30 parameters plus the federal CCDF registry hookup. It covers the two-tier income test (initial applicants ≤200% FPG; enrolled/ongoing ≤85% SMI), the eligibility gates (age <13 / disabled <19, $25k liquid-asset limit, approved-activity, per-child CCDF immigration, WI residency), a 72-county × 4-age-group × provider-type max-rate matrix, an hours-based copay schedule (5 child-count columns × FPG-share brackets, per-child 152-hr / AG 760-hr caps, exit-period phase-out), and the subsidy formula (min(hourly_max × hours, provider price, monthly_max) + above-full-time add-on − per-child copay share, floored at 0 but retaining eligibility). Aggregation runs Person → SPMUnit(MONTH) → SPMUnit(YEAR) into the federal child_care_subsidies, matching the xx_child_care_subsidies peer convention.

  • CI: 31/31 passing.
  • Branch: 12 ahead, 54 behind main — rebase recommended before merge.
  • Effective-date eras: rates 2025-10-01; copay + exit phase-out 2026-02-01; handbook July 2026. No pre-2025-10 date gate — backdating carries current-era values back, disclosed in wi_shares_child_subsidy.
  • Source docs: DCF Handbook (July 2026), max-rates-statewide.pdf (pp. 26–40), wishares-copay-schedule.pdf, DCF 201 rulemaking, LFB Budget Paper 211, Wis. Stat. § 49.155.
  • IMPORTANT: the rate-matrix value audit is a SAMPLE (~8% of 1,152 cells), not a full-matrix verification. See Full-matrix caveat.

Verified correct

Rate / copay value audit — 0 mismatches (sample). 96 rate cells across 6 counties (Adams, Ashland, Dane, Milwaukee, Menominee, Wood — spanning first/last alphabetical, high-cost Dane/Milwaukee, low-cost rural) × 2 provider types × {hourly, FT-monthly} × 4 age groups: 96 match / 0 mismatch (all deltas $0.00). Copay schedule: 95 cells (19 non-zero FPL bands × 5 child columns): 95 match / 0 mismatch. Edge claims confirmed against the PDFs: ≤100% FPG = $0; 200% row == 195% row; per-child cap 152 / AG cap 760 (760 = 5×152); exit phase-out rate 0.2 ($1 per $5 over 200% FPG). Derivations confirmed: FT-monthly = hourly × 152.18 (transcribed per-cell), PT-monthly = hourly × 131 (derived), Certified = 0.9 × licensed-family. Tribal-agency rows correctly excluded. The copay PDF's own embedded worked example (AG of 3, $2,618 = 115% FPG, 2 children → $0.65/hr) cross-checks the row/column alignment.

Tests — thorough, no critical gaps. Every formula-bearing variable and both new Enums (wi_shares_time_category, wi_shares_age_group) have a direct unit test. Both income tiers and the tier switch are exercised with threshold−1 / threshold / threshold+1 triplets; all five copay child-columns covered; certified-cap, 152/760 caps, and the above-full-time add-on (>50 wk, 75-hr cap, exactly-50 no-add-on) tested; copay≥subsidy → $0-but-eligible covered. integration.yaml reproduces five handbook Appendix II worked examples end to end. Period format uniformly 2027-01 (valid, after both effective dates). No boolean output asserted with absolute_error_margin ≥ 1; currency files use 0.01.

Code — clean. No hard-coded policy values — every threshold/rate/derivation factor reads from a parameter (131/152/153 monthly hours appear only in comments; code derives via np.ceil(conversion × weeks_per_month)). Enum + breakdown metadata uses the supported enum-index pattern (avoids boolean-key / integer-output traps). Entity/period chain, defined_for residency gating, reference format, changelog fragment (wi-ccap.added.md, correct added type), and programs.yaml entry all well-formed. No TODO/FIXME/stub. Aggregation matches the ks_child_care_subsidies / ks_ccap peer convention.

Regulatory — 6 items confirmed correct against Wis. Stat. § 49.155 and DCF Handbook July 2026:

  1. Two-tier income test — initial ≤200% FPG (§ 49.155(1m)(c)1.) and enrolled ≤85% SMI (§ 49.155(1m)(c)1d.b.), with the where(enrolled, …) switch mirroring ND's nd_ccap_income_eligible.
  2. Eligibility gates — age <13 / disabled <19 (§ 49.155(1m)(a)), $25k liquid-asset limit (§ 49.155(1m)(cm)), per-child CCDF immigration gate (Handbook §4.5), WI residency.
  3. Copay structure — hours-based, 5 columns × FPG brackets; ≤100% FPG = $0; FPL floored to lower 5% line; TANF/W-2 → $0; caps 152/760 (§18.2/§18.3).
  4. Subsidy formula — min(...) cap + above-full-time add-on − per-child copay share, floored at 0 but eligibility retained (Handbook §18.5, §18.2.2); part/full-time hours conversion (131/153 monthly) confirmed against Appendix II.
  5. Certified provider rate = 90% of licensed-family hourly, capped at licensed-family monthly (Handbook §14.4.2).
  6. No reinvented variables — correctly reuses spm_unit_fpg, hhs_smi, is_ccdf_immigration_eligible_child, spm_unit_cash_assets, is_tanf_enrolled, meets_ccdf_activity_test, and the ND two-tier "enrolled" pattern + xx_child_care_subsidies wrapper convention.

Critical (must fix)

None.

Should address

  1. Approved-activity model is over-inclusive vs. the statutewi_shares_parent_in_approved_activity treats any of {employment, self-employment income ≠ 0, >0 hours, full-time student, TANF} as an approved activity, and wi_shares_activity_eligible further OR's in meets_ccdf_activity_test. The statute (§ 49.155(1m)(a)1.–6.) / Handbook §5.1 enumerate a closed list; is_full_time_student is broader than the handbook's schedule-tied education activities. Modeling approximation, not a misread — document the over-inclusion bias in the variable, or tighten the student pathway. Not blocking.
  2. Child-turning-13 grandfather rule not modeled (wi_shares_eligible_child, hard age < 13) — Handbook §4.3 keeps a child who turns 13 mid-period eligible until renewal. Disclosed in a code comment. Slightly under-inclusive; acceptable documented limitation.
  3. is_disabled proxies "verified disability AND cannot self-care" — Handbook §4.3 requires a verified disability and inability to self-care to extend to <19. Disclosed. Potentially over-inclusive for capable disabled 13–18-year-olds; acceptable approximation.
  4. Above-full-time add-on monthly round-up is inferred, not sourcedwi_shares_child_subsidy computes the >50-hr add-on as ceil(addon_weekly_hours × weeks_per_month) × hourly_max; the handbook has no worked add-on example, so the rounding is inferred (the 50-hr threshold and 75-hr cap themselves are confirmed, §16.1.1 / §18.5). Low risk; noted.
  5. Bare 100 cents literalvariables/gov/states/wi/dcf/shares/rates/wi_shares_hourly_max_rate.py:47-48 uses literal 100 for the round-up-to-the-cent certified-rate conversion (np.round(... * 100, 2) then np.ceil(...) / 100). It is a units constant, not a policy value, so defensible — but consider a named local (e.g. CENTS_PER_DOLLAR) or a comment tying it to the "rounded up to the cent" rule.
  6. Non-canonical parameter description verbs — several descriptions use verbs slightly outside the canonical limits/provides/sets/excludes/deducts/uses set: copay/exit/phase_out_rate.yaml:1 ("increases … by this share"), copay/hours/assistance_group_cap.yaml:1 and per_child_cap.yaml:1 ("caps … at this amount"), income/child_support_disregard_cap.yaml:1 ("disregards … and counts"), hours/weeks_per_month.yaml:1 ("multiplies … by this factor"). Low-priority style nit; each reads clearly and ends in a period with the full program name.

Suggestions

  1. Exit-period copay commentwi_shares_copay_per_hour relies implicitly on the top per-hour bracket being the 200% level (per Handbook §18.2.1); the dependency is only stated in the parameter file. Add a one-line pointer in the variable. (Value confirmed: 200% row == 195% row.)
  2. Test polish (append to existing files, period: 2027-01): (a) 5 full-time children = exactly 760 hrs (at-cap, not over) companion to the current 6-children/912-over case → copay/wi_shares_copay.yaml; (b) child-support just-above-cap edge, 1,251 (currently 1,000/1,250/1,500 tested) → income/wi_shares_countable_income.yaml; (c) one mid-schedule exact copay band edge (e.g. 150%) → copay/wi_shares_copay_per_hour.yaml.
  3. Annual-vs-monthly aggregation notewi_child_care_subsidies (YEAR) adds wi_shares (MONTH), and the integration test asserts the annual equals the single monthly value (matching the KS convention). Whether the annual should be ~12× the monthly figure is a regulatory-accuracy question worth confirming; a one-line comment on the YEAR wrapper would make the test expectation self-explanatory.
  4. County / breakdown-key completeness — confirm every county key in the four 604-line rate matrices resolves to a valid *_COUNTY_WI enum member and that age_group.yaml's indices line up with the four wi_shares_age_group members (a single mismatched key would raise a breakdown ValueError). Out of scope for the read-only code pass; recommend a structural check.
  5. wi_shares_countable_income self-employment add-backs unmodeled (Handbook §6.4.4 depreciation / personal business expenses have no PolicyEngine inputs). Disclosed; understates countable income for self-employed filers.
  6. Label paritywi_shares_copay_per_hour is SPMUnit-level; consider "… assistance group copayment per hour" for parity with wi_shares_copay.
  7. Minor Enum coveragewi_shares_provider_type (input-only) and is_wi_shares_enrolled (input bool) have no standalone default-pinning tests; both are covered indirectly. Acceptable per convention.

Full-matrix caveat

The rate-matrix audit verified 96 of 1,152 cells (~8%) — the sample deliberately spans first/last county alphabetically, high-cost (Dane, Milwaukee) and low-cost rural (Ashland) counties, all four age groups, and both provider types, and found 0 mismatches. But the remaining ~66 counties were not individually checked. Recommendation: before merge, the author should confirm the full-matrix transcription against max-rates-statewide.pdf (pp. 26–40), ideally with a scripted PDF-vs-YAML diff over all cells. The copay schedule, by contrast, was audited in full (95/95 cells).

Separately: the branch is 54 commits behind main — rebase onto main before merge.

Validation summary

Area Result
Regulatory 0 critical, 4 should, 2 suggestion; 6 items confirmed correct
Rate/copay value audit (SAMPLE) Rates 96/96 cells (~8% of 1,152); copay 95/95 (full). 0 mismatch. Edge claims + derivations confirmed
Code 0 critical, 2 should, 6 suggestion; no hard-coded values, peer-convention aggregation
Tests Thorough; no critical gaps; every formula var + both Enums tested; 5 Appendix II integration examples
CI 31/31 passing

Review severity: APPROVE

0 criticals, a sample-clean rate/copay audit, faithful regulatory implementation, and an unusually thorough test suite justify APPROVE — the one item to close before merge is the full-matrix rate transcription confirmation (scripted PDF diff over all 1,152 cells), plus a routine rebase (54 behind main); the six should-address items are documented approximations and style nits, none blocking.

Next steps

/fix-pr 9062

🤖 Generated by /review-program (Claude Code)

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement Wisconsin Shares Child Care Subsidy Program (CCAP)

2 participants