Skip to content

Implement Utah Unemployment Insurance (ut_ui) - #8281

Open
daphnehanse11 wants to merge 6 commits into
PolicyEngine:mainfrom
daphnehanse11:ut-ui
Open

Implement Utah Unemployment Insurance (ut_ui)#8281
daphnehanse11 wants to merge 6 commits into
PolicyEngine:mainfrom
daphnehanse11:ut-ui

Conversation

@daphnehanse11

@daphnehanse11 daphnehanse11 commented May 13, 2026

Copy link
Copy Markdown
Collaborator

Summary

Implements Utah Unemployment Insurance (UI) in PolicyEngine, administered by the Utah Department of Workforce Services (DWS) under Utah Code Title 35A Chapter 4 and Utah Admin Code R994 series.

Closes #8280

Regulatory Authority

Weekly Benefit Amount (WBA) Formula

Monetary Eligibility Tests

  1. Base-period wages ≥ $5,500 (Utah Code § 35A-4-201(16))
  2. Wages in ≥ 2 base-period quarters (Utah Admin Code R994-401-202)
  3. Base-period wages ≥ 1.5 × high-quarter wages (Utah Code § 35A-4-403(1)(f)(i))

Duration of Benefits

  • weeks = clamp(floor(0.27 × base_period_wages / WBA), 10, 26)
  • Maximum Benefit Amount = WBA × weeks
  • Source: Utah Code § 35A-4-401(4)

Partial Benefits

Requirements Coverage

Req Statute / Rule Parameter Variable Test
REQ-001 UC § 35A-4-201(1)(a) n/a ut_ui_base_period_wages.py (docstring) documented
REQ-002 UC § 35A-4-201(1)(b) n/a ut_ui_base_period_wages.py (docstring) documented
REQ-003 UC § 35A-4-201(16) eligibility/min_base_period_wages.yaml ($5,500) ut_ui_monetarily_eligible.py ut_ui_monetarily_eligible.yaml Case 2; edge Cases 1-3
REQ-004 R994-401-202 eligibility/min_quarters_with_wages.yaml (2) ut_ui_monetarily_eligible.py ut_ui_monetarily_eligible.yaml Case 3; edge Cases 6-7
REQ-005 UC § 35A-4-403(1)(f)(i) eligibility/base_period_to_high_quarter_ratio.yaml (1.5) ut_ui_monetarily_eligible.py ut_ui_monetarily_eligible.yaml Case 4; edge Cases 4-5
REQ-006 composite n/a ut_ui_monetarily_eligible.py ut_ui_monetarily_eligible.yaml Case 1
REQ-007 UC § 35A-4-401(2)(a)(ii) wba/divisor.yaml (26); wba/subtraction.yaml ($5) ut_ui_weekly_benefit_amount.py ut_ui_weekly_benefit_amount.yaml Case 1
REQ-008 UC § 35A-4-401(2)(b)(ii) wba/max_amount.yaml (712/777/806) ut_ui_weekly_benefit_amount.py ut_ui_weekly_benefit_amount.yaml Cases 2-3; edge Cases 10-13
REQ-009 UC § 35A-4-401 (no min) omitted (no min_amount.yaml) ut_ui_weekly_benefit_amount.py (max_(raw, 0)) edge Case 9
REQ-010 composite n/a ut_ui_weekly_benefit_amount.py (× monetarily_eligible) ut_ui_weekly_benefit_amount.yaml Case 4
REQ-011 UC § 35A-4-401(4)(b) duration/multiplier.yaml, min_weeks.yaml, max_weeks.yaml ut_ui_duration_weeks.py ut_ui_duration_weeks.yaml Cases 1-3
REQ-012 UC § 35A-4-401(4)(b) duration/min_weeks.yaml (10) ut_ui_duration_weeks.py ut_ui_duration_weeks.yaml Case 2; integration Case 4
REQ-013 UC § 35A-4-401(4)(b) duration/max_weeks.yaml (26) ut_ui_duration_weeks.py ut_ui_duration_weeks.yaml Case 1; edge Cases 16-17
REQ-014 UC § 35A-4-401(4)(b) duration/multiplier.yaml (0.27) ut_ui_duration_weeks.py ut_ui_duration_weeks.yaml Cases 1-3
REQ-015 UC § 35A-4-401(4)(a) n/a ut_ui_maximum_benefit_amount.py ut_ui_maximum_benefit_amount.yaml Cases 1-2; integration Cases 2-5
REQ-016 UC § 35A-4-401(3)(a); R994-401-301 partial/earnings_disregard_rate.yaml (0.30) ut_ui_weekly_payable_amount.py ut_ui_weekly_payable_amount.yaml Cases 2-3; edge Cases 19-20
REQ-017 UC § 35A-4-401(3)(a)–(b) n/a ut_ui_weekly_payable_amount.py ut_ui_weekly_payable_amount.yaml Case 3; edge Case 20
REQ-018 UC § 35A-4-401(3)(a) n/a ut_ui_weekly_payable_amount.py (earnings ≥ WBA → 0) ut_ui_weekly_payable_amount.yaml Case 4; edge Case 18
REQ-019 Claimant Guide p. 11 partial/hours_threshold.yaml (40) ut_ui_weekly_payable_amount.py ut_ui_weekly_payable_amount.yaml Case 5; edge Cases 21-23
REQ-020 UC § 35A-4-401(3)(c) n/a ut_ui_gross_weekly_earnings.py (docstring) documented
REQ-021 composite n/a ut_ui.py (defined_for=StateCode.UT) integration Cases 2-6; out-of-state Case 7; edge Cases 26-27
REQ-022 UC § 35A-4-403(1)(d) n/a ut_ui.py + ut_ui_duration_weeks.py (26-week cap absorbs waiting week) integration Case 2
REQ-038 input definition n/a ut_ui_base_period_wages.py (Person/YEAR/USD) integration.yaml
REQ-039 input definition n/a ut_ui_high_quarter_wages.py (Person/YEAR/USD) integration.yaml
REQ-040 input definition n/a ut_ui_quarters_with_wages.py (Person/YEAR/int) integration.yaml
REQ-041 input definition n/a ut_ui_gross_weekly_earnings.py (Person/YEAR/USD) integration Case 5
REQ-042 input definition n/a ut_ui_weekly_hours_worked.py (Person/YEAR/hour) integration Case 6; edge Cases 21-23
REQ-043 input definition n/a ut_ui_weeks_unemployed.py (Person/YEAR/week) integration Cases 2-6; edge Case 25

29 in-scope requirements (22 modeled + 7 input definitions) — all covered.

Not Modeled (14 items)

  • Disqualifications (Utah Code § 35A-4-405): voluntary quit (REQ-024), discharge for just cause (REQ-025), refusal of suitable work (REQ-026), strike/labor dispute (REQ-027), fraud (REQ-028), education between-terms (REQ-029), sport between-seasons (REQ-030), alien status (REQ-031)
  • Able-and-available and active work-search requirements (Utah Code § 35A-4-403(1)(b)–(c)) — REQ-032, REQ-033
  • 100% retirement-income offset from base-period employer pensions (Utah Code § 35A-4-401(2)(c); R994-401-203) — REQ-023 (no base-period employer attribution in PolicyEngine)
  • Dependents allowance — Utah has none (REQ-034)
  • Extended Benefits (Utah Code § 35A-4-402) — REQ-035
  • Voluntary tax withholding and child-support garnishment (administrative, handled federally) — REQ-036, REQ-037

Files Added

policyengine_us/
├── parameters/gov/states/ut/dwf/unemployment_insurance/
│   ├── index.yaml
│   ├── eligibility/
│   │   ├── min_base_period_wages.yaml
│   │   ├── min_quarters_with_wages.yaml
│   │   └── base_period_to_high_quarter_ratio.yaml
│   ├── wba/
│   │   ├── divisor.yaml
│   │   ├── subtraction.yaml
│   │   └── max_amount.yaml
│   ├── duration/
│   │   ├── multiplier.yaml
│   │   ├── min_weeks.yaml
│   │   └── max_weeks.yaml
│   └── partial/
│       ├── earnings_disregard_rate.yaml
│       └── hours_threshold.yaml
├── variables/gov/states/ut/dwf/unemployment_insurance/
│   ├── ut_ui.py
│   ├── ut_ui_base_period_wages.py
│   ├── ut_ui_high_quarter_wages.py
│   ├── ut_ui_quarters_with_wages.py
│   ├── ut_ui_gross_weekly_earnings.py
│   ├── ut_ui_weekly_hours_worked.py
│   ├── ut_ui_weeks_unemployed.py
│   ├── ut_ui_monetarily_eligible.py
│   ├── ut_ui_weekly_benefit_amount.py
│   ├── ut_ui_duration_weeks.py
│   ├── ut_ui_maximum_benefit_amount.py
│   └── ut_ui_weekly_payable_amount.py
├── tests/policy/baseline/gov/states/ut/dwf/unemployment_insurance/
│   ├── ut_ui_monetarily_eligible.yaml
│   ├── ut_ui_weekly_benefit_amount.yaml
│   ├── ut_ui_duration_weeks.yaml
│   ├── ut_ui_maximum_benefit_amount.yaml
│   ├── ut_ui_weekly_payable_amount.yaml
│   ├── integration.yaml
│   └── ut_ui_edge_cases.yaml
└── programs.yaml  (added `ut_ui` State entry)
  • 12 parameters (+ 1 index.yaml) under policyengine_us/parameters/gov/states/ut/dwf/unemployment_insurance/
  • 12 variables under policyengine_us/variables/gov/states/ut/dwf/unemployment_insurance/
  • 7 test files under policyengine_us/tests/policy/baseline/gov/states/ut/dwf/unemployment_insurance/
  • programs.yaml updated with ut_ui State entry (status=complete, verified_years="2024-2026")

Tests

  • 53 tests passing (6 unit-test files + 1 integration file with 7 scenarios + 1 edge-case file with 27 cases)
  • All values cross-verified against the DWS 2026 Benefit Schedule (form 04-13-0126)
  • Formula floor(HQ/26) − 5 clipped to [0, max_wba] reproduces the published schedule exactly (e.g., HQ $15,054 → WBA $574; HQ ≥ $21,086 → WBA $806 cap)

@codecov

codecov Bot commented May 13, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (4c6ac7e) to head (2ee6840).
⚠️ Report is 44 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff            @@
##              main     #8281   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files            3        12    +9     
  Lines           49       147   +98     
=========================================
+ Hits            49       147   +98     
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.

- Split min_base_period_wages into 2024/2025 ($5,300) and 2026 ($5,500) entries
- Fix Claimant Guide page references (printed p.11 = file p.13)
- Update test boundary cases to match new $5,300 threshold
- Replace misleading 2025 form URL with Wayback Machine archive snapshot
- Clarify Claimant Guide page references (printed p.11 = file p.13)
- Add 2024/2026 boundary tests for min_base_period_wages (Cases 28-32)
- Use canonical verb in base_period_to_high_quarter_ratio description
- Pair statute and admin rule citations on min_quarters_with_wages
Derived from 2024 max WBA ($712) per UC § 35A-4-201(16) + § 35A-4-401(2)(b)(ii):
both values depend on the same insured average fiscal year wage. Working
backward, 8% × annual_IAFY ≈ $4,772, rounded up to next $100 = $4,800.

- Update 2024-01-01 entry from $5,300 to $4,800
- Adjust edge case boundaries (Cases 28-29) to test new $4,800 floor
@daphnehanse11
daphnehanse11 requested a review from hua7450 July 28, 2026 16:12
@daphnehanse11
daphnehanse11 marked this pull request as ready for review July 28, 2026 17:06
@daphnehanse11

Copy link
Copy Markdown
Collaborator Author

Rebased onto current main (branch is now main + 5 commits). One substantive change during the rebase: the commit wiring ut_ui into the federal unemployment_compensation variable was dropped — newer policyengine-core rejects adds combined with uprating, and that income-flow integration is deferred to the umbrella PR #8303 pending policyengine-us-data support (per @MaxGhenis's guidance there). The PR now implements ut_ui as a standalone program. Utah suite passes 238/238 locally.

@DTrim99

DTrim99 commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

Program Review — Utah Unemployment Insurance (PR #8281)

Program Review — via /review-program (multi-agent audit)

Read-only multi-agent review of PR #8281 (new program: Utah Unemployment Insurance, gov/states/ut/dwf/unemployment_insurance/, 2024–2026 coverage; 12 variables, 13 parameters, 7 test files, programs.yaml entry, changelog fragment). Validators: regulatory reviewer, reference validator, code-pattern auditor (Mode B), test-coverage reviewer, PDF statute audit, PDF schedules audit, and an independent code-path verifier for the flagged 2024 mismatch.

Source Documents

  1. UT DWS Claimant Guide (Jan 2025)https://jobs.utah.gov/ui/jobseeker/claimantguide.pdf (36 pp; wage requirements p.5–6, duration p.6, partial benefits / 40-hour rule p.10–11, waiting week p.16)
  2. DWS Benefit Schedule, Jan 2026 (Form 04-13-0126, current) — https://jobs.utah.gov/ui/UIShared/PDFs/BenefitCalculation.pdf — max WBA $806, max MBA $20,956, min qualifier $5,500
  3. DWS Benefit Schedule, Jan 2025 (Form 04-13-0125, archived) — https://web.archive.org/web/20250304230024/https://jobs.utah.gov/ui/UIShared/PDFs/BenefitCalculation.pdf — max WBA $777, max MBA $20,202, min qualifier $5,300
  4. DWS Benefit Schedule, Jan 2024 (archived, fetched for this review) — https://web.archive.org/web/20240613222926/https://jobs.utah.gov/ui/UIShared/PDFs/BenefitCalculation.pdf — max WBA $746, max MBA $19,396, min qualifier $5,100
  5. DWS Benefit Schedule, Jan 2023 (archived) — https://web.archive.org/web/20231216204910/https://jobs.utah.gov/ui/UIShared/PDFs/BenefitCalculation.pdf — max WBA $712, max MBA $18,512, min qualifier $4,800
  6. Utah Code § 35A-4-401 (WBA, max WBA, partial benefit, duration) — https://le.utah.gov/xcode/Title35A/Chapter4/35A-4-S401.html (text via FindLaw: https://codes.findlaw.com/ut/title-35a-utah-workforce-services-code/ut-code-sect-35a-4-401/)
  7. Utah Code § 35A-4-403 (monetary eligibility, 1.5× ratio) and § 35A-4-201(16) (min base-period wage formula) — via FindLaw mirrors
  8. Utah Admin Code R994-401-301 (partial benefits: 30% disregard, earnings ≥ WBA disqualifier) — via law.cornell.edu
  9. USDOL "Significant Provisions of State UI Laws," July 2024https://oui.doleta.gov/unemploy/content/sigpros/2020-2029/July2024.pdf (p.4, UT row — independent cross-check of 2024 values)

Branch Status

⚠ PR branch is 41 commit(s) behind main. Consider rebasing before merge. Review scoped to merge-base diff; staleness did not affect findings.

Critical (Must Fix)

  1. 2024 max WBA is the 2023 value — 712 should be 746.
    policyengine_us/parameters/gov/states/ut/dwf/unemployment_insurance/benefit/wba/max_amount.yaml, 2024-01-01: 712.
    The January 2024 DWS Benefit Schedule (effective 1/1/2024–12/31/2024) states max WBA $746 / max MBA $19,396. $712 is the January 2023 schedule's max WBA (2023 MBA $18,512 = 26 × $712) — the entire 2024 step was encoded one year late. Independently CONFIRMED by the code-path verifier against two official sources: the archived Jan-2024 schedule and USDOL Significant Provisions July 2024 (UT row: "Max $746"). The 2025 ($777) and 2026 ($806) steps are correct. This parameter drives ut_ui_weekly_benefit_amount (cap applied via min_), which feeds duration, MBA, weekly payable, and ut_ui for every 2024-period calculation.
    Citation: DWS Benefit Schedule Jan 2024 (archive link above); Utah Code § 35A-4-401(2)(b); USDOL July 2024 p.4.

  2. 2024 minimum base-period wages is the 2023 value — 4_800 should be 5_100.
    policyengine_us/parameters/gov/states/ut/dwf/unemployment_insurance/eligibility/min_base_period_wages.yaml, 2024-01-01: 4_800.
    The January 2024 schedule states "you must have earned at least $5,100"; $4,800 is the 2023 qualifier. Same off-by-one-year error, confirmed by both the archived Jan-2024 schedule and USDOL July 2024 ("$5,100 in BP"). The file's derivation comment is doubly wrong: it claims the 2024 value is "derived from the 2024 max WBA ($712)" ($712 is the 2023 max WBA) and that "DWS no longer publishes the 2024 schedule PDF" (it is recoverable from the Wayback Machine and states $5,100 outright). Fix the value AND rewrite the comment; the file's reference also points at the 2025 snapshot, not a 2024 source. Gates ut_ui_monetarily_eligible for all 2024 calculations.
    Citation: DWS Benefit Schedule Jan 2024; Utah Code § 35A-4-201(16); USDOL July 2024 p.4.

  3. 2024 tests, comments, and programs.yaml lock in the wrong values (consequence of Basic prototype #1/Run black formatting on docs #2 — must be updated with the fix). Per the code-path verifier, after correcting the parameters:

    • tests/.../integration.yaml Case 2 (2024): WBA 712 / MBA 18,512 / ut_ui 18,512 → should be WBA 746, duration 26, MBA/ut_ui 19,396 — will fail.
    • tests/.../ut_ui_weekly_benefit_amount.yaml Case 2 (2024, HQ $20,000): cap 712 → 746 — will fail.
    • tests/.../ut_ui_edge_cases.yaml Case 11 (HQ $18,668): expects cap to 712 → correct 2024 result is 713 (uncapped) — will fail; Case 10 passes but its "exact lower boundary of 2024 WBA cap" label becomes wrong (true 2024 cap boundary is HQ $19,526).
    • tests/.../ut_ui_edge_cases.yaml Case 29 (BPW $4,800): expects eligible → ineligible under the correct $5,100 floor — will fail; Case 28 passes but the boundary pair should move to $5,099/$5,100. Header/section comments "($4,800 in 2024…)" also wrong.
    • tests/.../ut_ui_monetarily_eligible.yaml header comment "($5,300 in 2024-2025…" matches neither the correct value ($5,100) nor the PR's own parameter ($4,800).
    • policyengine_us/programs.yaml verified_years: "2024-2026" — 2024 is not correctly verified until Basic prototype #1/Run black formatting on docs #2 are fixed.
      All 2025/2026 tests are unaffected and match the published schedules.

Should Address

  1. hours_threshold.yaml (40) — primary citation § 35A-4-207 does not contain the value. parameters/.../benefit/partial/hours_threshold.yaml. § 35A-4-207 defines "unemployed" functionally (wages-below-WBA test) and contains no 40-hour rule; R994-401-301 also does not. The 40-hour figure is corroborated by the Claimant Guide p.11 ("you work 40 or more hours during the week…") and USDOL — the value is right, the primary cite is not value-bearing. Demote § 35A-4-207 to a supporting "full-time work definition" cite and lead with the Claimant Guide. (Flagged CRITICAL by the reference validator; demoted here because the encoded value and behavior are correct and Guide-corroborated.)
  2. min_quarters_with_wages.yaml (2) — neither cited source states a 2-quarter rule. Cited § 35A-4-403(1)(f) contains only the 1.5× ratio; R994-401-202 covers when wages are paid, not a quarter count; R994-401-201 also lacks it. The value IS corroborated verbatim by the Claimant Guide p.6 ("you must have earned wages in two or more calendar quarters of your base period"). Cite the Guide (and/or locate the actual authority) instead. (Also flagged CRITICAL by the reference validator; demoted on the same value-correct grounds — but this gate is load-bearing for ut_ui_monetarily_eligible, so do fix the citation.)
  3. Admin Code pointer is to the wrong rule number. min_quarters_with_wages.yaml, base_period_to_high_quarter_ratio.yaml, ut_ui_monetarily_eligible.py, and test headers cite R994-401-202; the rule stating the 1.5× ratio and minimum-dollar test is R994-401-201 ("WBA, MBA, and Monetary Determination"). Cite -201 (or both).
  4. Waiting week neither modeled nor documented. Claimant Guide p.16: "Utah law requires that you will not be paid for the first eligible week claimed." ut_ui.py pays weekly_payable × weeks_unemployed with no one-week reduction and the "Not modeled (future work)" block lists only the pension offset (REQ-023) — unlike the Alabama UI sibling, which has waiting_weeks.yaml. Overstates a new claim's annual benefit by one week. Model it or at minimum add it to the not-modeled documentation.
  5. Document the deliberate omission of the § 35A-4-403(1)(f)(ii) 20-weeks alternative. The alternative to the 1.5× test applies only to benefit years "effective on or before January 1, 2011" — omitting it is CORRECT for 2024–2026, but nothing in ut_ui_monetarily_eligible.py or eligibility/base_period_to_high_quarter_ratio.yaml records that the omission is intentional. Add a one-line sunset note so future reviewers don't flag a missing eligibility path. (Classified SHOULD ADDRESS because it is currently undocumented.)
  6. Zero-default wage inputs — add a documentation note (microsim default rule). All six drivers (ut_ui_base_period_wages.py, ut_ui_high_quarter_wages.py, ut_ui_quarters_with_wages.py, ut_ui_gross_weekly_earnings.py, ut_ui_weekly_hours_worked.py, ut_ui_weeks_unemployed.py) are bare inputs defaulting to 0, so ut_ui is uniformly 0 in any population/microsim run. Consistent with the economy: false / household: true programs.yaml entry, but document the limitation explicitly (variable docstrings and/or programs.yaml note) so the population-level zero is a stated design choice.
  7. Agency path segment dwf should be dws. All 25 files sit under gov/states/ut/dwf/unemployment_insurance/; Utah UI is administered by the Department of Workforce Services (DWS) — dwf matches neither the name nor a known abbreviation (cf. al/dol/..., nj/dol/...). This is the establishing PR, so renaming is cheap now: directory segment, parameter_prefix in programs.yaml, and the parameter path in the four formula files.
  8. Reference-link durability for year-stepped values. min_base_period_wages.yaml (and wba/max_amount.yaml) mix a rolling live BenefitCalculation.pdf URL with a single 2025 archive snapshot; the live link drifts annually and cannot corroborate 2024–2026 simultaneously. Add a year-tagged archive.org snapshot per year (2024: web/20240613222926/...; 2025: web/20250304230024/...; 2026: live or a fresh snapshot). Also fix the claimantguide #page=13 anchor after verifying the 40-hour statement location (printed p.11 = file p.13).
  9. Test-coverage gaps on genuine branches/boundaries (no formula variable has zero coverage — these refine boundaries):
    • Duration 10-week floor clamp never binds in any test (ut_ui_duration_weeks.py lower np.clip bound untested); the 1.5× ratio gate makes it nearly unreachable — add a constructed case or a code comment noting it is effectively unreachable.
    • WBA exact zero-crossing of the −$5 subtraction (HQ 130 → WBA 0; HQ 156 → WBA 1) untested.
    • Partial-benefit just-below disqualification boundary (earnings = WBA − 1 → reduced but payable) untested; the >= boundary itself is tested.
    • min_(WBA × weeks, MBA) exact-equality point (weeks == duration) untested.

Suggestions

  1. eligibility/min_quarters_with_wages.yaml uses unit: int; prefer unit: quarter or /1 for consistency with min_weeks/max_weeks (unit: week) and the divisor (/1).
  2. Add a short comment noting the Jan-1 parameter step dates intentionally track the DWS calendar-year schedules (each edition states "EFFECTIVE JANUARY 1 … to DECEMBER 31 …"), preempting fiscal-July questions.
  3. Document the un-modeled payment-side deductions: child-support withholding (up to 50% of WBA, Guide p.19) and voluntary 10%/5% tax withholding (p.19) — arguably out of scope for entitlement modeling, but currently unmentioned.
  4. ut_ui_edge_cases.yaml Case 9 uses BPW $5,500 with HQ $100, which is internally impossible (high quarter must be ≥ BPW/4); it functions only as a guard test — consider consistent inputs or a comment.
  5. Cheap defensive additions: negative base-period/high-quarter wage case (graceful ineligibility), and symmetric just-above floor cases ($5,101 / $5,501 after the 2024 fix).
  6. Statute hrefs point at whole-section pages with subsections only in titles (good precision); add subsection anchors if le.utah.gov supports them. Retirement-offset (REQ-023) future-work note in ut_ui.py is well documented — no action.

Source Audit Summary

Audit Result
Values checked against official sources 25 (23 matches, 2 mismatches)
Mismatches 2 — both 2024-01-01 steps: max WBA $712 (should be $746), min base-period wages $4,800 (should be $5,100); both are the Jan-2023 schedule's values encoded one year late
Independent confirmation Code-path verifier CONFIRMED both mismatches against the archived Jan-2024 DWS schedule AND USDOL Significant Provisions (July 2024)
Formula/structural values (÷26, −$5, 27%, 10–26 wks, 1.5×, 30% disregard, 40-hr, 2 quarters, MBA = WBA × duration, floors per § 401(2)(a)(ii)/(3)(b)/(4)(b)) All match statute + Admin Code + schedules; zero formula mismatches
2025/2026 dollar values ($777/$5,300; $806/$5,500) All match published schedules
Uncorroborated remaining None (both 2024 values resolved via Wayback + USDOL)

Validation Summary

Validator Critical Should Address Suggestions Notes
Regulatory reviewer 2 (+tests) 3 2 Confirmed off-by-one-year 2024 schedule
Reference validator 2* 4 2 *Both demoted to Should Address (values Guide-corroborated)
Code-pattern auditor (Mode B) 0 3 3 No hard-coded values; clean patterns; dwfdws
Test-coverage reviewer 0 5 6 Every formula variable covered; boundary refinements only
PDF statute audit 0 mismatches 16 matches; waiting-week gap; 20-week sunset confirmed
PDF schedules audit 2 mismatches 7 matches; 2024 values are 2023's
Code-path verifier CONFIRMED Both 2024 errors confirmed; 4 tests will fail after fix
CI All 33 checks pass (tests pass because they encode the same wrong 2024 values)

Review Severity: REQUEST_CHANGES

Two confirmed parameter-value errors in a tested year (2024) — both the 2023 schedule's figures encoded one year late — plus the tests that lock them in. Structure, formulas, rounding, boundaries, and 2025/2026 values are otherwise excellent; once the 2024 values, dependent tests, and derivation comment are corrected (and ideally the citation fixes in Should Address 1–3), this is a high-quality implementation.

Next Steps

  1. Run /fix-pr 8281 to apply the fixes: set wba/max_amount.yaml 2024 → 746, min_base_period_wages.yaml 2024 → 5_100, rewrite the derivation comment, update the four failing 2024 test cases + boundary cases/comments, and fix programs.yaml/citations.
  2. Rebase onto main (41 commits behind) before merge.
  3. Re-run the UT YAML suite (policyengine-core test policyengine_us/tests/policy/baseline/gov/states/ut -c policyengine_us) after the fix.
  4. Decide on waiting-week handling (model or document) and the dwfdws rename while the PR is still the establishing change.

🤖 Generated by /review-program (Claude Code multi-agent review)

- Correct 2024 max WBA $712 -> $746 and 2024 minimum base-period wages
  $4,800 -> $5,100 per the archived January 2024 DWS Benefit Schedule;
  recompute the four dependent 2024 test cases
- Rename agency path dwf -> dws (Department of Workforce Services);
  pre-existing dwf/fep left for separate cleanup
- Fix R994-401-202 -> R994-401-201 pin-cites; make the Claimant Guide the
  value-bearing citation for the 2-quarter rule and 40-hour threshold;
  add per-year archive.org references for schedule values
- Document unmodeled provisions (waiting week, 20-week alternative
  sunset, child-support and voluntary tax withholding) and zero-default
  microsim-inert inputs
- Add boundary and defensive tests: WBA floor cases, partial earnings at
  WBA-1, MBA equality, negative wages, just-above-floor eligibility

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@DTrim99

DTrim99 commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

Fixes Applied (from Program Review)

Commit 2ee6840 addresses all actionable findings from the review above.

Critical

  • 2024 max WBA corrected $712 → $746 and 2024 minimum base-period wages $4,800 → $5,100 — both were the 2023 schedule's values. Verified against the archived January 2024 DWS Benefit Schedule (snapshot); the derivation comment claiming the 2024 schedule was unpublished was rewritten.
  • The four dependent 2024 test cases recomputed (integration Case 2 → WBA 746 / 26 weeks / MBA 19,396; WBA Case 2 → 746; edge Case 11 → 713 with the cap no longer binding; the eligibility boundary pair moved to 5,099/5,100), plus stale headers and inline math comments.

Should Address

  • Agency path renamed dwfdws (Utah Department of Workforce Services) across parameters, variables, tests, and programs.yaml. Note: the pre-existing ut/dwf/fep tree keeps the old abbreviation — migrating it is separate cleanup beyond this PR.
  • Admin-code pin-cites fixed R994-401-202 → R994-401-201; the Claimant Guide (p. 6 / p. 11) is now the value-bearing citation for the 2-quarter rule and the 40-hour threshold, with § 35A-4-207 demoted to the full-time-definition support cite.
  • Per-year archive.org references added for the 2024/2025/2026 schedule values so each dated step has a durable, year-matched source.
  • Documented previously silent omissions in the docstrings: the unpaid waiting week (Guide p. 16), the sunset § 35A-4-403(1)(f)(ii) 20-week alternative, child-support withholding (≤ 50% WBA), and voluntary 10%/5% tax withholding; all six wage/hours input variables now note they default to 0 (program is household-calculator only; inert in dataset runs).

Suggestions

  • min_quarters_with_wages unit int/1; comments noting Jan-1 steps track the DWS calendar-year schedule; edge-case files' internally impossible input combos (HQ < BPW/4) fixed; new boundary/defensive tests appended (WBA floor zero-crossing, partial earnings at WBA−1, weeks×WBA == MBA equality, negative wages, just-above-floor eligibility at $5,101/$5,501).

Skipped (deliberate)

Verification

  • All 66 UT UI YAML tests pass locally (policyengine-core test .../ut/dws/unemployment_insurance -c policyengine_us), single run.
  • ruff format + check clean on all touched files.

🤖 Applied via /fix-pr (Claude Code)

@DTrim99
DTrim99 requested a review from PavelMakarchuk August 4, 2026 17:22
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.

Add Utah UI

2 participants