Skip to content

Implement Oregon Employment Related Day Care - #8993

Open
hua7450 wants to merge 10 commits into
PolicyEngine:mainfrom
hua7450:or-ccap
Open

Implement Oregon Employment Related Day Care#8993
hua7450 wants to merge 10 commits into
PolicyEngine:mainfrom
hua7450:or-ccap

Conversation

@hua7450

@hua7450 hua7450 commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator

Closes #8991.

Summary

  • implements Oregon Employment Related Day Care (ERDC) eligibility, countable income, copays, and benefits
  • encodes all 2026 provider reimbursement rates for Areas A, B, and C
  • uses Enum-indexed area, provider-type, age-group, and billing-tier dimensions, consolidating rates into three parameter files
  • registers ERDC in Oregon and federal CCDF child care subsidy aggregators

Modeling notes

  • or_erdc_provider_area and or_erdc_provider_type are direct inputs; the model does not track provider location or license type at the moment, so it defaults to AREA_C and CERTIFIED_CENTER. Because Areas B and C share the same rates, the AREA_C default understates benefits for Area A (metro ZIP) families; supply the input or populate it from data to override.
  • a disabled second caretaker who cannot provide care is now excused from the need-hours minimum per OAR 414-175-0023(1)(b)(A), so a two-caretaker family is no longer denied when one caretaker is unable to work; a lone non-working caretaker still yields zero need hours
  • TANF is listed but commented out of ERDC countable income because adding calculated tanf would create a circular dependency through child care expenses and TANF deductions
  • administrative eligibility requirements that cannot be inferred from household inputs remain out of scope

Review fixes (round 5)

Criticals:

  • add the CCDF immigration eligibility check (is_ccdf_immigration_eligible_child) to or_erdc_eligible_child, matching sibling state child care programs (45 CFR 98.20(a)(1)(ii))
  • add pre-increase 2024-01-01 entries for the FAM/QFM license-exempt rates (Areas A/B/C × five age groups × two provider types, in both the hourly and monthly rate files) from the archived DELC 7492i (01/24) provider guide insert, so January–February 2026 and 2024–2025 no longer backward-extrapolate the March 1, 2026 rate increase
  • read expanded child welfare (EXP-CW) eligibility at the month period in or_erdc_income_eligible instead of period.this_year, matching or_erdc_categorically_eligible

Should-address:

  • exclude an excused (disabled) second caretaker from the need-hours min() per OAR 414-175-0023(1)(b)(A), guarded to multi-caretaker units so a lone non-working caretaker still yields zero hours
  • corroborate the 215-hour monthly cap against the DELC rate chart's monthly billing range
  • standardize all OAR references to rule-specific URLs (view.action?ruleNumber=414-175-00XX) in place of the division landing page
  • document the provider area and provider type data limitations in the variable comments
  • add 7 YAML test cases: multi-caretaker need-hours minimum, 20-hour weekly band edge, excused caretaker, unearned income in countable income, sub-bracket copay, non-categorical eligibility false, and per-business self-employment flooring

Sources

Validation

  • 54 focused ERDC YAML cases (7 added in round 5); CI pending
  • 12 parameter syntax, Enum breakdown, system import, and parameter code-health tests pass
  • round-5 fixes verified statically (py_compile 10/10, YAML load 23/23) and confirmed clean by the implementation validator
  • make format and Ruff checks pass
  • official provider-rate PDF audit found no value or effective-date mismatches

The broad make test-yaml-structural target was stopped while it was spending several minutes in an unrelated existing contributed-policy batch; the direct parameter structural/import checks and all Oregon tests passed.

@codecov

codecov Bot commented Jul 10, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (ff39625) to head (51ff644).
⚠️ Report is 16 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##              main     #8993    +/-   ##
==========================================
  Coverage   100.00%   100.00%            
==========================================
  Files            1        31    +30     
  Lines           18       432   +414     
==========================================
+ Hits            18       432   +414     
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.

hua7450 and others added 7 commits July 11, 2026 14:24
- Floor self-employment losses at zero per OAR 414-175-0035(81)(e)
- Authorized care hours: 20/40/75 weekly bands, 20h categorical default,
  25% travel allowance, 4.3 weekly-to-monthly conversion per OAR 414-175-0023(5)
- Part-time billing tier now requires provider part-time billing input
  per OAR 414-175-0075(3)(b),(c),(e)
- Cap hourly billing at the monthly maximum per OAR 414-175-0075
- Add job-loss and at-application copay waivers per OAR 414-175-0023(3)(d),(f)
- Restrict supervised-contact exception to multiple-caretaker units
- Parameterize education activity age limit; add GED pathway input
- Age-13-17 pathway now requires OAR 414-175-0076 high-needs eligibility;
  add high-needs supplemental payment ($5 hourly / $840 monthly per factor)
- Point variable/parameter references at controlling OAR subsections
- Document microsim default bias and CNT infant-boundary ambiguity
- Untrack sources/working_references.md; fix trailing whitespace
- Update/add tests: 88 cases passing

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…rlap rule

Per OAR 414-175-0076(1) and the OPEN manual (07/2026, pp. 428, 448-449):
- High-needs eligibility implies the special-needs rate category, so the
  supplement adds to the special-needs base rate rather than the ordinary
  age-based rate.
- Monthly authorized hours round up before the 215-hour cap (the worker
  guide publishes the 20-hour band as 108 hours, not 107.5).
- Two-caretaker units count only overlapping work or school hours; the
  lowest caretaker's hours remain as the maximum-possible-overlap proxy
  since schedules are not tracked, now documented with the OPEN citation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
OAR 414-175-0035(21)(a) excludes the earned income of a child, and the
OAR 414-175-0015(2)(d) filing group counts earned income only from
caretakers. Sum earned sources per person and zero them out for
non-caretakers (tax unit heads and spouses).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Replace 14 program-specific input variables with existing repo
variables or documented simplifications:
- Special needs rate, 13-17 child eligibility, and the second-caretaker
  exception key on is_disabled, is_incapable_of_self_care, and
  is_in_foster_care; Expanded Child Welfare is now a formula over
  is_in_foster_care.
- GED study is covered by is_in_secondary_school.
- Part-time billing, the high needs supplement, copay waivers, medical
  leave, and supervised contact are unmodeled, each noted in a formula
  comment; billing collapses to hourly-vs-monthly full-time thresholds
  (158 standard, 136 enhanced/licensed).
- Reorganize variables into eligibility, income, rates, hours, and
  copay folders.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Criticals:
- Add CCDF immigration eligibility check to or_erdc_eligible_child
- Add pre-increase 2024-01-01 FAM/QFM rates from the DELC 7492i (01/24)
  insert so Jan-Feb 2026 and 2024-2025 no longer backfill the 3/1/2026
  increase
- Read EXP-CW eligibility at the month period in or_erdc_income_eligible

Should-address:
- Exclude excused (disabled) second caretakers from the need-hours min()
  so OAR 414-175-0023(1)(b)(A) families are not denied
- Corroborate the 215-hour cap with the rate chart; standardize all OAR
  references to rule-specific URLs
- Document provider area/type data limitations
- Add 7 test cases: multi-caretaker min, 20-hour band edge, excused
  caretaker, unearned income, sub-bracket copay, categorical false, and
  per-business self-employment flooring

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
PolicyEngine's age-based headship assigns an 18-year-old child as the
tax-unit spouse when no real spouse exists, so the head-or-spouse
caretaker filter counted their wages. Per OAR 414-175-0015(2)(d), the
filing group's children include those under 18 or age 18 attending
secondary school, so their earned income stays excluded under OAR
414-175-0035(21)(a). Narrow the filter with a parameterized
filing-group child definition.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@hua7450
hua7450 marked this pull request as ready for review July 14, 2026 00:59
@hua7450
hua7450 requested a review from PavelMakarchuk July 15, 2026 17:26
@PavelMakarchuk

Copy link
Copy Markdown
Collaborator

Program Review — PR #8993 "Implement Oregon Employment Related Day Care" (ERDC)

Consolidated report from 8 review passes: regulatory review, reference validation, code-pattern
audit, test-coverage review, three PDF/OAR audits (rates, copay/income, eligibility/hours), and
an empirical verification pass that ran the PR branch.

Scope: 31 new parameters and 20 new variables under gov/states/or/delc/erdc/, 11 test files
(integration.yaml with 13 cases + 10 unit files), plus edits to
gov/hhs/ccdf/child_care_subsidy_programs.yaml, programs.yaml, and
changelog.d/or-ccap.added.md. CI: passing.


Source Documents

Source Vintage Used for
DELC 7492i Provider Guide Insert, Phase 2 (2/27/2026), oregon.gov Rates eff. 1/1 & 3/1/2026 2026 rate tables, age categories, provider-type codes, billing-hour tiers
DELC 7492i Provider Guide Insert (01/24), web.archive.org Rates eff. 1/1/2024 2024 rate tables (full 7-type matrix)
DE 2818 ERDC Program Policy Manual (rev 07/2026), 1,322 pp current Authorized hours (p. 428), categorical ERDC, student rules
OAR 414-175-0015, -0022, -0023, -0030, -0035 (partial), -0050, -0075 (secure.sos.state.or.us) current (0050 amend eff. 3/1/2026) Age thresholds, activity/hours rules, income limits, copay schedule, payment rates
Not obtained: OAR 414-175-0025 full text; OAR 414-175-0035 full text (truncated ~§70); insert page 2 image See External follow-ups

Critical

None confirmed. The one CRITICAL claimed by three reviewers was empirically refuted — see
"Investigated and Cleared" below.


Should Address

S1. Missing part-time monthly rate tier (63–135 monthly hours) for enhanced/licensed providers

Flagged independently by the regulatory review, the rates PDF audit, and the eligibility audit.
Both DELC inserts show three billing tiers for QFM/QEC/RFM/CFM/CNT: 1–62 hourly | 63–135 part-time monthly | 136–215 full-time monthly. The PR parameterizes only hourly and full-time
monthly; or_erdc_maximum_monthly_rate.py prices the entire sub-136-hour range as
min(hourly × hours, full_time_monthly).

  • Demonstrated wrong output: integration Case 9 (108 monthly hours, Area A CNT preschool)
    pays min(11 × 108, 1_563) = 1_188 vs the published part-time monthly maximum of 1,172
    a ~$16/month overpay that grows toward 135 hours (135 × 11 = 1,485 vs 1,172) and flips to
    underpay below ~107 hours. The default provider type is CERTIFIED_CENTER (licensed), so this
    band is hit by a meaningful share of modeled cases.
  • Mitigating reading: the code comment cites OAR 414-175-0075(3)(c) — the part-time monthly
    rate applies when a provider "customarily bills all families at a part-time monthly rate", a
    billing practice the model does not track. The rates auditor (who had the OAR 0075 text)
    confirms this citation is accurate and calls the simplification reasonable; the regulatory
    reviewer could not confirm it and reads the PDF as presenting part-time as a standard tier.
  • Recommendation: add the part-time monthly rate parameters and a middle band (or, at
    minimum, expand the code/YAML documentation of the (3)(c) assumption and reconcile Case 9's
    inline comment with the published 1,172 cell).

S2. Flat 215-hour cap makes the 75-hour weekly bracket unreachable (216–323-hour band)

Eligibility audit mismatch 1. or_erdc_monthly_care_hours.py caps all results at
max_monthly (215), but OAR 414-175-0023(5)(a)(C) allows up to 75 weekly hours (≈323 monthly),
manual p. 428 explicitly authorizes "more than full-time (216–323 hours)", and OAR
414-175-0075(9)–(10) permit payment up to 1.5 × 215 for special circumstances (including
consistently >40 hrs/week workers, 0075(10)(e)). As written, the 75-hour bracket in
hours/authorized/weekly.yaml is dead weight: any need >40 hrs/week computes 75 × 1.25 × 4.3 =
403 and is always clipped to 215, so 50+-hr/week households get full-time instead of up to 323
hours. If the 215 cap is an intentional conservative choice (special-circumstances
determination not modeled), document the assumption in max_monthly.yaml and/or the variable;
otherwise add the >215 band.

S3. Incomplete 2024 backdating of rates; 2026-03 eligibility/copay values silently active back to 2015

The verifier established that policyengine-us backdates every parameter's earliest value to
2015-01-01 at load (backdate_parameters in system.py), so nothing crashes — but that makes
historical accuracy a silent-substitution question:

  • Rates: the PR backdates only 2 of 7 provider types. STANDARD_FAMILY/ENHANCED_FAMILY carry
    explicit 2024-01-01 rows, but the 2024 insert publishes full tables for the other five types
    (STANDARD_CENTER, ENHANCED_CENTER, REGISTERED_FAMILY, CERTIFIED_FAMILY, CERTIFIED_CENTER) —
    150 cells present in the source PDF but absent from the repo. Those five types (including
    the CERTIFIED_CENTER default) therefore use backdated 2026 values for 2024–2025 periods, e.g.
    in the default enhanced_cps_2024 microsim.
  • Eligibility/copay: income/fpl_rate/*, income/smi_rate/ongoing, max_group_size,
    countable_income/*, and all copay/size_*.yaml start 2026-03-01, though the rule history
    shows earlier schedules (2025-03-01, 2024-03-01, 2023-07-01) and the 200%/250%/85% structure
    predates 2026. The 2026-03 brackets apply to all years ≥ 2015 via backdating.
  • Hours thresholds: full_time_threshold/* (158/136) and max_monthly (215) start
    2026-01-01 though the identical bracket structure appears in the 2024 insert.
  • FAM/QFM Jan–Feb 2026 gap: these types jump from 2024 rates to 2026-03-01, so Jan–Feb 2026
    evaluates at 2024 levels; the Phase-2 insert implies a Phase-1 1/1/2026 schedule existed.
  • Recommendation: backdate the real 2024 rate values (all in the archived 2024 insert) and
    the hours thresholds to 2024-01-01; where genuine pre-2026 copay/limit schedules are not
    encoded, note the historical-accuracy limitation. Cross-reference the DELC Phase-1 Jan-2026
    insert for FAM/QFM interim rates.

S4. Test gaps: 2024 rate vintage untested; categorical positive paths only in integration

  • Every rate test (25 cases) and every integration case runs at 2027-01/2027, so the
    2024-01-01 vintage the PR explicitly adds has zero coverage; a future edit to the 2024 column
    cannot be caught. Add 1–2 2024-period rate assertions (more once S3 backfills the matrix).
  • or_erdc_categorically_eligible.yaml has only a negative case; TANF→true and foster-care→true
    are exercised only via integration Cases 4 and 9, and
    or_erdc_expanded_child_welfare_eligible has no dedicated unit file. Add positive unit cases.

S5. age_group effective-date inconsistency among siblings citing the same source

age_group/license_exempt_infant_max_months.yaml is dated 2026-03-01 while its three siblings
(licensed_infant, toddler, preschool) are 2026-01-01 — all four cite the same insert
page 1. The rates audit confirmed the 2026-01 vs 2026-03 rate date split is exactly what the
PDF states (only FAM/QFM rates increase 3/1/2026), but found no PDF evidence the
license-exempt infant boundary changed on 3/1/2026
; materially identical definitions appear in
the 2024 insert. Align the sibling to 2026-01-01 (or earlier — the definitions are longstanding;
see S6).

S6. Reference hygiene: add OAR citation for age groups; page-anchor the archived insert

  • The age-band definitions are corroborated by OAR 414-175-0075(1)(a)–(d) (and this OAR cite is
    what resolves the certified-center 24-month infant question — see Verified Correct). Add
    OAR 414-175-0075(1) as a reference to all four age_group/*.yaml files, which currently
    cite only the rate insert.
  • The archived 2024 insert URL in rates/hourly.yaml/rates/monthly.yaml has no #page=
    anchor; add file-page anchors to the rate-table pages (2024 insert pp. 3–6).

Suggestions

  1. Two-caretaker both-disabled edge (eligibility audit mismatch 2): a unit where both
    caretakers are non-working and disabled passes or_erdc_activity_eligible, but under OAR
    414-175-0023(1)(a)+(1)(b) at least one caretaker must still meet (1)(a). Practical impact is
    nil (need hours fall to 0, so no benefit pays), but the eligibility flag is wrong for that cell.
  2. Undocumented unmodeled provisions: study-hours allowance (+5/+10 weekly hours, OAR
    414-175-0023(5)(a)(D)); below-minimum-wage 125%-of-earnings/172-hour payable cap (OAR
    414-175-0075(8)(b)); 125% payable-hours limit distinct from the travel allowance (0075(8)(a)(A)).
    Add at least code/YAML comments (many other gaps — medical leave, court supervision,
    copay waivers — are already documented).
  3. Min group size 2 hard-coded in or_erdc_copay.py and or_erdc_income_eligible.py
    (upper bound is parameterized as max_group_size); consider a min_group_size parameter.
  4. Copay schedule split across 7 sibling files forces the 7-way select(size == n, ...)
    in or_erdc_copay.py; a single breakdown/scale parameter indexed by capped group size would
    remove the enumerated literals. Optional refactor.
  5. Description verbs/placeholders deviate from the canonical set in several parameters
    ("adds", "multiplies ... factor", "pays ... this many hours", "under this age"). Cosmetic.
  6. Underscore formatting in rates/monthly.yaml: 1233.33, 1133.33, 1033.33,
    1477.33 lack the thousands underscore used elsewhere (1_041, 1_110).
  7. Changelog filename changelog.d/or-ccap.added.md names the program "CCAP" though it is
    ERDC (structure/type are correct). Cosmetic.
  8. Minor test/robustness additions (from tests + regulatory reviews): a case where the 250%
    FPL ongoing term binds (85% SMI binds in all current tests); infant-cutoff month boundaries
    (11/12, 23/24); size-2 first-paid-bracket edge (1,803/1,804) and a size-3 bracket case; an
    18-year-old non-student caretaker case; a single no-activity caretaker case; an explicit
    7%-of-income copay cap guard (OAR 414-175-0050 / federal CCDF); treating positive
    self-employment income as a qualifying activity when weekly hours are 0.
  9. EXTERNAL follow-ups (sources not collected): full text of OAR 414-175-0035 (needed to
    fully corroborate countable_income/sources.yaml/earned_sources.yaml, the child
    earned-income exclusion (21)(a), TANF countability (56)(g), self-employment (81)); OAR
    414-175-0025 full text (TANF-at-request extension; exact EXP-CW criteria vs foster-care
    proxy); 2026 insert page 2 image (reference-hygiene check for the 136/158/215 anchors — OAR
    0075(3) independently corroborates the values); DELC Phase-1 Jan-2026 insert (FAM/QFM
    Jan–Feb 2026 rates).

Investigated and Cleared

  1. CRITICAL claim: "2026-01 income-eligibility tests error / 2024 microsim crashes because
    parameters start 2026-03-01 and resolve to None"
    — claimed independently by the code
    validator (C1), test analyzer (C1), and regulatory reviewer (S2).
    FALSE POSITIVE — parameter backdating. The verifier checked out the PR branch and ran it:
    all 4 tests in or_erdc_income_eligible.yaml pass at period 2026-01, and a 2024 Oregon
    single-household calculation of or_child_care_subsidies returns 0.0 without exception.
    Mechanism: policyengine_us/system.py calls
    backdate_parameters(self.parameters, first_instant="2015-01-01")
    (policyengine_us/tools/parameters.py), copying every leaf parameter's earliest value back
    to 2015-01-01 at load, so the raw policyengine-core None-before-first-instant semantics
    never apply in policyengine-us. Green CI is genuine. The surviving residue of this claim is
    the historical-accuracy observation in S3, not a crash.
  2. "Ongoing limit should be lesser of 250% FPL / 85% SMI" (review-task premise) — cleared.
    OAR 414-175-0050(1)(b)(B) says "whichever is higher", corroborated by the DE 2818 manual;
    the repo's max_(250% FPL, 85% SMI) is correct.
  3. Copay schedule corroboration risk ("dollar brackets may live in an external notice, not
    the rule") — cleared. All 37 brackets appear verbatim in OAR 414-175-0050(3)(b)(A)–(G); the
    repo even correctly handles the rule's "$34,057.99" typo (reads as $4,057.99).
  4. 2026-01-01 vs 2026-03-01 rate date split (references SHOULD 2) — cleared in the PR's
    favor. Insert page 1 states only FAM/QFM rates increase 3/1/2026; centers/licensed remain
    effective 1/1/2026. Repo dates match exactly. (The unresolved sliver is the age-group
    sibling, S5.)
  5. "Insert page 1 may not print exact age cutoffs" (references CRITICAL item) — cleared.
    Page 1 contains the "Child age categories" table with all four cutoffs.
  6. de2818.pdf#page=428 anchor — cleared. File page 428 = printed page 428; the cited
    travel-time/authorized-hours/hour-band content is on that page.
  7. Area C rate table duplicating Area B — cleared. The PDF's Area B and Area C tables are
    numerically identical.

PDF Audit Summary

  • Rates: 270/270 populated cells match (tolerance 0.001) — 210/210 for the 2026 vintage
    (3 areas × 7 provider types × 5 age groups × {hourly, monthly}) and 60/60 for the 2024
    vintage (the two family-exempt types encoded), including cent-level values (1,233.33 etc.).
    Provider-type enum maps one-for-one to the PDF codes (FAM/NQC/QFM/QEC/RFM/CFM/CNT).
  • Copay: all 37 brackets match OAR 414-175-0050(3)(b) verbatim across sizes 2–8+;
    effective date 2026-03-01 matches the rule history (DELC 2-2026); higher-of (not lesser-of)
    ongoing income standard confirmed; ceil(FPG × rate) arithmetic reproduces both published
    200% and 250% dollar tables exactly.
  • Eligibility: age cutoffs (13/18/20/18-student), age-group months (12/24/36 mo, 6 yr),
    hours bands (20/40/75, 25% travel, ×4.3, 136/158/215) all corroborated
    against OAR
    0015/0022/0023/0075 and manual p. 428.
  • 2 structural mismatches: (a) the flat 215 cap suppresses the 216–323-hour band, leaving
    the 75-hour bracket unreachable (S2); (b) the both-caretakers-disabled activity edge
    (Suggestion 1). Plus the deliberate, documented part-time-tier omission (S1) and 150 missing
    2024 rate cells (S3).

Verified Correct

  • Child age <13, special circumstances <18; initial limit 200% FPG; ongoing
    max(250% FPG, 85% SMI) keyed on is_enrolled_in_ccdf; strict < matches the rule's
    "equals or exceeds → ineligible".
  • Categorical eligibility (TANF or Expanded Child Welfare/foster care) bypasses income and
    activity tests and waives the copay ($0), per OAR 414-175-0023(2)/-0025.
  • Activity test structure: employment / post-secondary (no age limit — correctly applied) /
    HS-GED ≤20 / excused second caretaker; two-caretaker overlap proxied by min-of-caretakers
    (manual p. 428).
  • Authorized-hours pipeline: 20/40/75 bands with correct bracket edges, +25% travel, ×4.3,
    ceil, 215 cap, 20-hour categorical floor (reproduces the manual's 108-hour default).
  • Certified-center 24-month infant window: supported by OAR 414-175-0075(1)(a) ("licensed
    care" includes certified centers), documented in or_erdc_age_group.py.
  • Self-employment floored at $0 per business (loss cannot offset other income); child earned
    income excluded; both-spouse earnings counted.
  • No dependency cycle: uses pre_subsidy_childcare_expenses and deliberately excludes tanf
    from countable income (documented deviation; low impact since TANF families are categorical
    with $0 copay). No reinvented variables — shared FPG/SMI/CCDF helpers reused.
  • Code patterns: naming, enums, adds vs formula, add() > 0, period handling
    (period.this_year for YEAR vars, MONTHS_IN_YEAR conversion), spm_unit.project/sum
    vectorization, breakdown enum indexing, defined_for gating, reference formats, programs.yaml
    schema — all conform. or_child_care_subsidies wrapper mirrors nv_child_care_subsidies and
    is correctly wired into the federal aggregator. Partner test files untouched.
  • Metadata: all 31 parameters have complete unit/period/label/reference; all Oregon-jurisdiction
    sources; labels follow "Oregon ERDC ..."; OAR titles carry full subsection paths; dual OAR+PDF
    sourcing on hours thresholds.
  • Test coverage exceeds the usual bar: exact income boundaries at both regimes, full 3×7×5 rate
    matrix (25 cases), full-time-hour boundaries (135/136, 157/158), copay bracket edges,
    group-size clip at 8, 13-case integration file with verified intermediate values.

Validation Summary

Pass Result
Regulatory review (OAR 414-175 vs code) Core rules faithful; S1 tier + date question raised
Reference validation (31 params) 0 missing refs, 0 jurisdiction errors; hygiene items S5/S6
Code-pattern audit (20 vars) High quality; claimed C1 refuted; S/G items folded above
Test review (11 files) Coverage exceeds bar; claimed C1 refuted; S4 gaps
PDF rates audit 270/270 match; 150-cell 2024 backfill gap
OAR copay/income audit 37/37 brackets match verbatim; higher-of confirmed
Eligibility/hours audit All values corroborated; 2 structural mismatches (S2, Sugg. 1)
Empirical verification Tests pass at 2026-01; 2024 microsim returns 0; backdating mechanism identified

Review Severity

Recommendation: COMMENT (with S1–S3 called out as pre-merge-worthy fixes).

Reasoning both ways:

  • For REQUEST_CHANGES: S1 is a value-accuracy issue with demonstrably wrong output against
    the source document — integration Case 9 pays 1,188 where the published part-time cell is
    1,172, and the 63–135-hour band covers common part-time arrangements including the default
    provider type. S2 similarly zeroes out a whole authorized-hours band the rule provides.
  • For COMMENT: there are no confirmed criticals (the crash claim was a false positive); every
    one of the 270 rate cells, 37 copay brackets, and all eligibility values matches its
    authoritative source exactly; the S1 omission is documented in code with an OAR
    414-175-0075(3)(c) citation that the rates auditor — who had the rule text — confirms is an
    accurate reading (part-time monthly applies to providers who customarily bill part-time, a
    fact the model cannot observe); and S2/S3 are conservative-modeling and historical-vintage
    completeness issues, not wrong current-law values.

On balance the implementation is accurate to its sources with defensible, mostly documented
simplifications, so COMMENT is appropriate — but if the maintainers consider the 63–135-hour
band pricing a must-fix before merge (reasonable given Case 9), REQUEST_CHANGES is defensible.


Next Steps — /fix-pr 8993

Priority order for the fixer:

  1. S1 — add part-time monthly rate parameters (values in both inserts) and a 63–135-hour
    band to or_erdc_maximum_monthly_rate.py, or explicitly document the (3)(c) assumption in
    the YAML/variable and fix integration Case 9's expected value/comment.
  2. S3 — backdate the 150 missing 2024 rate cells (2024 insert pp. 3–6) and the hours
    thresholds to 2024-01-01; document historical limits of the 2026-03 eligibility/copay values.
  3. S2 — either add the 216–323-hour band (OAR 0075(9)–(10)) or document the 215-cap
    assumption in max_monthly.yaml.
  4. S5/S6 — align license_exempt_infant_max_months to 2026-01-01; add OAR
    414-175-0075(1) references to age_group/*.yaml; add #page= anchors to the archived 2024
    insert URLs.
  5. S4 — add 2024-vintage rate tests and positive categorical unit cases.
  6. Suggestions as time permits (both-disabled edge, unmodeled-provision comments,
    min_group_size parameter, underscores, changelog rename, boundary tests).
  7. External source collection: OAR 414-175-0025 and -0035 full text, insert page 2, Phase-1
    Jan-2026 insert.

@PavelMakarchuk PavelMakarchuk 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.

Automated /review-program pass complete — no confirmed criticals; see the missing 63–135-hour part-time rate tier and related items. Detailed findings: #8993 (comment)

hua7450 and others added 2 commits July 23, 2026 14:48
…tions

Adds the 150 published 2024 rate cells from DELC 7492i (01/24) for the five
provider types missing them, backdates the hours thresholds and age-group
definitions to 2024-01-01 with OAR 414-175-0075(1) citations, documents the
unmodeled part-time monthly tier, the 215-hour cap, and the 2026-03
copay/limit backdating, adds page anchors, and covers the 2024 vintage and
categorical paths with new tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@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 — Oregon ERDC (new program)

PR #8993 introduces a NEW state program: Oregon Employment Related Day Care (ERDC), the state's CCDF-funded child care subsidy. This is a polished, well-parameterized implementation: the sampled rate/copay audit found 0 mismatches, tests are thorough with no critical gaps, and the code is clean with no hard-coded policy values. There are no critical findings. The two items most worth weighing before merge are (1) the branch is 301 commits behind main (VERY STALE) and must be rebased and re-tested, and (2) the documented AREA_C / CERTIFIED_CENTER default-input bias, reported below per the microsim rule.

Scope

  • Program: Oregon ERDC — child care subsidy (CCDF/ERDC), agency dir gov.states.or.delc.erdc. New program (~20 variables + ~25 parameter files + tests).
  • What it implements: three consolidated Enum-breakdown rate/copay parameter families (rates/hourly.yaml, rates/monthly.yaml keyed area × provider_type × age_group; 7 copay/size_2..size_8.yaml schedules), two-tier income eligibility (initial 200% FPG; ongoing max(250% FPG, 85% SMI)), categorical + expanded-child-welfare pathways, activity test, authorized-hours logic (20/40/75 bands, +25% travel, ×4.3, 215-hr cap), countable income (earned/unearned/self-employment), per-child allowable cost = min(expense, max rate), copay, subsidy = max(allowable − copay, 0), and a or_child_care_subsidies state wrapper wired into the federal CCDF aggregator.
  • CI: 31/31 passing.
  • Branch status (PROMINENT): 10 commits ahead, 301 behind main — VERY STALE. Merge conflicts are likely; the branch must be rebased on main and re-tested before merge.
  • Sources (all reachable and machine-read): 2026 Phase-2 Provider Rate Insert (DELC 7492i, oregon.gov); archived 7492i 01/24 insert (web.archive.org) for the 2024 vintage; OAR 414-175-0015/-0022/-0023/-0025/-0035/-0050/-0075 (SOS oard); OPEN worker guide de2818.pdf#page=428 (overlap hours).

Verified correct

Rate/copay value audit — 0 mismatch (SAMPLE for rates; FULL for copay):

  • 25 sampled rate cells (hourly + monthly) spanning all 3 areas × all 7 provider types × all 5 age groups × both 2024 and 2026 vintages — 25 MATCH, 0 MISMATCH (threshold > $0.30). Odd fractional figures reproduced correctly (Registered Family .33 cents 1233.33/1133.33/1033.33/933.33; Area A Certified Family Preschool 2026 = 1477.33).
  • All 7 copay schedules (size_2..size_8) checked in full against OAR 414-175-0050(3)(b) — 7/7 MATCH on every breakpoint and amount.
  • Area B == Area C confirmed correct (insert tables are identical cell-for-cell; repo mirrors this — not an error).
  • Special needs == Infant rate mirrored in every cell — confirmed.
  • Effective-date split correct: license-exempt Standard Family (FAM) and Enhanced Family (QFM) carry 2026-03-01; all centers and licensed family (NQC/QEC/RFM/CFM/CNT) carry 2026-01-01, matching the Phase-2 insert's explicit note. Copay schedule carries 2026-03-01 matching OAR. 2024-01-01 baseline matches archived 7492i.

Test thoroughness (no critical gaps): all 7 requested mechanics covered — two-tier income (initial + ongoing boundary pairs), 3-level rate breakdown (21 systematic cases across all areas/providers/ages), copay (sizes 2..8 + >8 clamp + categorical→$0 + below-first-bracket), countable-income exclusions (child earned income, per-business SE floor), hours (all bands, travel, ×4.3, cap, categorical floor, two-caretaker overlap), subsidy + per-child→unit aggregation + federal roll-up (Case 8: or_child_care_subsidies == child_care_subsidies == 17,880), and both categorical and expanded-child-welfare bypass pathways. Every core formula is asserted by name in ≥1 test.

Code cleanliness: no hard-coded policy values (every literal traces to a parameter; only 0/1/+1 offsets remain); 3-level Enum breakdown complete and correctly typed (string Enum keys, currency-float outputs — avoids the boolean-key and integer-output breakdown traps); entity/period usage idiomatic (YEAR flows auto-÷12 in MONTH formulas, stocks use period.this_year); references correctly formatted; changelog present (or-ccap.added.md, added type correct for a new program); all referenced dependency variables exist; no reinvented federal helpers (reuses fpg, smi, is_ccdf_asset_eligible, is_ccdf_immigration_eligible_child, activity-test scope, is_tanf_enrolled, is_in_foster_care).

Regulatory confirmations: income limits exact (200% FPG initial; max(250% FPG, 85% SMI) ongoing; group size capped at 8) per OAR 414-175-0050(1)(b); eligible-child age thresholds (<13 standard, <18 special-circumstances/filing-group) per OARs -0022/-0015; child earned-income exclusion per -0035(21)(a); hours logic per -0023(5) incl. the OPEN worker guide's 108-hr figure; activity test (work/post-secondary/secondary≤20/two-caretaker disability proxy) per -0023(1); subsidy mechanic (lesser of charge or state max, minus copay) per -0075.

Critical (must fix)

None.

Should address

  1. AREA_C / CERTIFIED_CENTER default-input bias (MICROSIM — direction/magnitude reported, not prescribed). or_erdc_provider_area defaults AREA_C and or_erdc_provider_type defaults CERTIFIED_CENTER. Direction/magnitude:

    • AREA_C default UNDERSTATES the max rate for metro Area A families (Area A rates are materially higher — e.g. STANDARD_FAMILY infant $1,110 vs $855 in 2026). Exact for the B/C share (B==C), downward bias for the Area-A subset only.
    • CERTIFIED_CENTER default OVERSTATES (it is the highest-rate provider type) for every family whose true provider is cheaper (the large majority — standard/family providers pay far less).
    • The two push in opposite directions but do not cleanly cancel: the type-default upward bias is broad (all defaulting families) while the area-default downward bias hits only Area A, so the net expected direction is an upward bias on aggregate modeled ERDC max-rate/benefit, concentrated where actual care is cheaper than a certified center. The min(max_rate, actual expenses) cap dampens (but does not remove) the type effect. Both defaults are honestly documented on the variables. Per the microsim rule, this reports direction/magnitude only — it does not prescribe a specific default. Recommend one of: (a) populate area/type from data, (b) document the residual, or (c) accept if the aggregate ERDC-cost sensitivity is quantified. Do not merely rely on "they offset." (or_erdc_provider_area.py, or_erdc_provider_type.py; regulatory S3.)
  2. TANF excluded from countable income — understates income, overstates eligibility/benefit. OAR 414-175-0035(56)(g) counts TANF as unearned income, but income/countable_income/sources.yaml comments out tanf to break a real circular dependency (tanf → child care deduction → child care expense → ERDC). Honestly documented; the circular-dep is real. Direction: excluding a countable source understates or_erdc_countable_income, which can push families under the income limit and lowers the copay — both bias eligibility/benefit upward for TANF families. Mitigation: TANF families are usually or_erdc_categorically_eligible (income test bypassed, copay→$0 via is_tanf_enrolled), so residual bias is limited to TANF families not flagged enrolled. Recommend quantifying the residual population or resolving the circularity with a lagged/gross TANF input; keep documented if small. (regulatory S1.)

  3. Ongoing income test keys off is_enrolled_in_ccdf — verify it is populated in microdata. or_erdc_income_eligible applies the ongoing limit when is_enrolled_in_ccdf, else the initial 200% FPG limit. This is the correct two-tier structure per OAR 414-175-0050(1)(b)(A)/(B), but if is_enrolled_in_ccdf is uniformly false at simulation time, ALL households are held to the stricter 200% limit, understating ongoing-eligible caseload. Modeling dependency to verify, not a formula error. (regulatory S4.)

  4. Self-employment nets business costs; OAR counts GROSS receipts. or_erdc_countable_self_employment_income correctly floors each of three sources at zero per business (OAR -0035(81)(a), preventing a loss from offsetting other income), but OAR (81)(e) counts GROSS receipts for the income test. PolicyEngine only stores tax-net SE earnings, so the floored-net figure understates countable income for self-employed applicants (→ overstates eligibility/benefit). Documented data limitation; no fix available without a gross-receipts input. Flagging direction. (regulatory S2.)

  5. No activity-only failure case for or_erdc_eligible. The formula ANDs five conditions (has_eligible_child, activity, income, resource, copay<allowable). Integration covers income-fail, asset-fail, no-child, and the copay-gate equality edge, but there is no case where or_erdc_activity_eligible is the sole failing condition (Case 12 has no caretaker activity but also no eligible child). Add a single-condition activity-fail-only case to harden the gate. (tests HIGH.)

  6. or_erdc_countable_income.yaml is thin (1 case). Only Social Security (one unearned source) is asserted; the sources list has ~15 unearned entries and none of the others (SSI, child support, unemployment, rental, veterans, etc.) is pinned, and there is no mixed earned+unearned SPM-unit case. Add a mixed earned+unearned case and at least one more unearned source to guard the adds list against silent removal. (tests HIGH.)

Suggestions

  1. Expanded Child Welfare pathway narrower than the OAR. or_erdc_expanded_child_welfare_eligible returns true only on is_in_foster_care; OAR 414-175-0025(1)(b)(B) also grants EXP CW for Child Abuse Prevention, Family Reunification (within a year), Subsidized Guardianship, and Family Support Services. Documented data-availability limitation; understates categorical eligibility for non-foster CW subpopulations. (regulatory G1.)

  2. Copay categorical waiver correct; broader at-application waivers omitted. or_erdc_copay forces $0 when categorically eligible; OAR 414-175-0023(3)(d)-(f) also waives copays after permanent job loss / military transition / medical leave at application (documented, not tracked). Minor undercount of $0-copay cases. (regulatory S5, downgraded.)

  3. programs.yaml OR entry status: complete while its own notes say automatic provider ZIP→area mapping is deferred and area/type are inputs. Consider whether partial is more accurate. Metadata judgment call. (code SUGGESTION 5.)

  4. Direct unit tests for the four integration-only variables. or_erdc_caretaker_weekly_need_hours and or_erdc_allowable_child_care_cost have no dedicated file (each is asserted only inside integration). A direct file for each (e.g. lone-disabled-caretaker need-hours fallback; mixed expense-above/below-rate per-child cap in one unit) would pin currently-implicit branches. (tests MEDIUM.)

  5. Exact infant-cutoff boundary tests. age_group.yaml proves the licensed (24mo) vs license-exempt (12mo) params differ via an 18-month split, but does not pin each cutoff at threshold−ε / threshold. Add boundary pairs (11mo vs 12mo license-exempt; 23mo vs 24mo licensed). Also: or_erdc_age_group applies the 24-month licensed-infant cutoff to CERTIFIED_CENTER pending DELC confirmation (~$96/mo impact, documented). (tests MEDIUM; code SUGGESTION 3.)

  6. Optional month-varying roll-up case. or_child_care_subsidies is a declarative adds=["or_erdc"] wrapper; every case uses a steady-state month, so the MONTH→YEAR annualization is only ever 12× a constant. A month-varying case would harden the roll-up. (tests MEDIUM.)

  7. or_erdc_monthly_care_hours proxies care need with weekly_hours_worked_before_lsr and ignores the child-level childcare_hours_per_week input that integration tests set (inert in those tests). Documented modeling-scope choice; the potentially-misleading test inputs are a test-quality note. (code SUGGESTION 4.)

Caveats

  • Rate audit is a SAMPLE. ~25 of ~210 rate cells were checked (0 mismatch); all 7 copay schedules were checked in full (0 mismatch). A full cell-by-cell sweep of every area × provider × age × date × (hourly+monthly) was NOT performed. pdftotext -layout collapses the licensed-rate (RFM/CFM/CNT) columns; sampled licensed cells reconciled cleanly by age order, but this is the least-verified block.
  • Branch is 301 commits behind main — VERY STALE (EMPHASIZED). Merge conflicts are likely. The branch MUST be rebased on main and the full test suite re-run before merge; CI 31/31 was measured on the stale tree.

Validation summary table

Dimension Result Notes
CI 31/31 pass measured on stale branch
Rate values 0 mismatch SAMPLE (~25 of ~210 cells)
Copay values 0 mismatch FULL (all 7 size schedules vs OAR -0050(3)(b))
Structure (B==C, special-needs==infant, effective-date split) Confirmed correct matches insert + OAR
Regulatory accuracy 0 critical 5 should / documented directional biases
Code patterns 0 critical clean; 2 borderline (both defensible)
Test coverage 0 critical gaps 2 HIGH, several MEDIUM
Branch freshness STALE 301 behind main — rebase required
Consolidated 0 CRITICAL / 6 SHOULD / 7 SUGGESTION

Review severity: APPROVE

Recommend APPROVE. Zero criticals across all four reviews, a sample-clean rate audit and a full-clean copay audit, thorough tests, and clean code justify approval; the two things to weigh are the 301-behind staleness (a mechanical rebase-and-retest gate, not a defect) and the AREA_C/CERTIFIED_CENTER default bias (a documented, directional microsim caveat, dampened by the min(rate, expenses) cap and categorical gates) — neither rises to a blocking defect, so approve conditional on a clean rebase + re-test.

Next steps

  • Rebase on main and re-run the full suite (301-behind — do this first).
  • /fix-pr 8993 to address the 6 should-items (starting with the two HIGH test additions and documenting/quantifying the AREA_C/type default bias and TANF-exclusion residual).

🤖 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 Oregon Employment Related Day Care (ERDC)

3 participants