Skip to content

Implement Alabama Unemployment Insurance (al_ui) (ref #8282) - #8283

Open
daphnehanse11 wants to merge 13 commits into
PolicyEngine:mainfrom
daphnehanse11:al-ui
Open

Implement Alabama Unemployment Insurance (al_ui) (ref #8282)#8283
daphnehanse11 wants to merge 13 commits into
PolicyEngine:mainfrom
daphnehanse11:al-ui

Conversation

@daphnehanse11

@daphnehanse11 daphnehanse11 commented May 13, 2026

Copy link
Copy Markdown
Collaborator

Summary

Implements the Alabama Unemployment Insurance program (Code of Alabama Title 25, Chapter 4).
Closes #8282.

Regulatory Authority

Monetary Eligibility (§ 25-4-77(a)(4))

A claimant is monetarily eligible if ALL of the following are true:

  1. Wages reported in at least 2 quarters of the base period
  2. Total base-period wages ≥ 1.5 × the high-quarter wages
  3. Unrounded weekly benefit amount > $44.50

Weekly Benefit Amount (§ 25-4-72(b))

  • Formula: WBA = (High Quarter Wages + 2nd-High Quarter Wages) / 52
  • Rounding: Nearest $1; ties round DOWN (Alabama-specific; implemented via np.ceil(x - 0.5))
  • Min: $0 if unrounded ≤ $44.50; otherwise rounded amount
  • Max: $275 (effective 2020-01-01; Act 2019-204)

Maximum Benefit Amount and Duration (§ 25-4-74(a))

  • Duration: Sliding-scale tied to the state's unemployment rate (Act 2019-204):
State unemployment rate Maximum weeks
≤ 6.5% 14
> 6.5% to ≤ 7.0% 15
> 7.0% to ≤ 7.5% 16
> 7.5% to ≤ 8.0% 17
> 8.0% to ≤ 8.5% 18
> 8.5% to ≤ 9.0% 19
> 9.0% 20
  • MBA dual-cap: min(max_weeks × WBA, ¼ × base-period wages), rounded to nearest $1
  • State unemployment rate is sourced from FRED ALUR (monthly values stored as a parameter)

Partial-Benefit Provisions (§ 25-4-72; NELP 2015 reform)

  • A claimant is on partial unemployment if weekly earnings < WBA
  • Earnings disregard: 1/3 × WBA (effective 2015-06-13 onward)
  • Partial weekly benefit = max(WBA - max(weekly_earnings - WBA/3, 0), 0)

Waiting Week

  • 1 non-compensable week subtracted from the duration of payable benefits
  • Effective 2012-08-01 per BRR handbook p. 6 and Admin Code 480-4-3

Requirements Coverage

REQ Description Param Variable Test
REQ-001 ≥2 base-period quarters eligibility/quarters_with_wages.yaml al_ui_monetarily_eligible.py al_ui_monetarily_eligible.yaml
REQ-002 BPW ≥ 1.5 × HQW eligibility/bpw_to_hqw_multiplier.yaml al_ui_monetarily_eligible.py al_ui_monetarily_eligible.yaml
REQ-003 Unrounded WBA > $44.50 wba/min_threshold.yaml al_ui_monetarily_eligible.py, al_ui_weekly_benefit_amount.py al_ui_weekly_benefit_amount.yaml
REQ-004 WBA = (HQW + 2HQW) / 52 al_ui_unrounded_wba.py al_ui_unrounded_wba.yaml
REQ-005 Ties-down rounding al_ui_weekly_benefit_amount.py al_ui_weekly_benefit_amount.yaml
REQ-006 WBA = 0 when ≤ threshold wba/min_threshold.yaml al_ui_weekly_benefit_amount.py al_ui_weekly_benefit_amount.yaml
REQ-007 WBA cap $275 wba/max.yaml al_ui_weekly_benefit_amount.py al_ui_weekly_benefit_amount.yaml
REQ-008 UR-bracket 14-20 weeks mba/duration_weeks.yaml, state_unemployment_rate.yaml al_ui_max_weeks.py al_ui_max_weeks.yaml
REQ-010 MBA dual-cap mba/bpw_fraction.yaml al_ui_maximum_benefit_amount.py al_ui_maximum_benefit_amount.yaml
REQ-011 MBA rounded to $1 al_ui_maximum_benefit_amount.py al_ui_maximum_benefit_amount.yaml
REQ-012 Partial-week threshold al_ui_partial_weekly_benefit.py al_ui_partial_weekly_benefit.yaml
REQ-013 1/3 WBA disregard partial/disregard_rate.yaml al_ui_partial_weekly_benefit.py al_ui_partial_weekly_benefit.yaml
REQ-014 1 waiting week waiting_weeks.yaml al_ui.py al_ui.yaml, integration.yaml

Not Modeled

  • Training-program +5-week extension (§ 25-4-74(b)) — opt-in, requires participation data not in CPS
  • Extended Benefits (§ 25-4-75) — federally-triggered, transient
  • Non-monetary eligibility (able/available/seeking work) — not simulatable
  • Disqualifications (voluntary quit, misconduct, refusal, labor dispute) — requires reason-for-unemployment data
  • Federal-conformity escalator on WBA max — programmatic, not in claimant calculations
  • Alternative base period — Alabama has none
  • Dependents' allowance — Alabama has none
  • Pre-2020 history (uniform 26-week cap, pre-2015 $15 partial disregard) — out of scope per scope decision

Historical Notes

All AL UI parameters in this PR start at 2020-01-01, matching the effective date of Act 2019-204 which introduced:

  • The current $275 WBA cap (previous: $265 from 2009; $255 from 2008)
  • The unemployment-rate-tied duration bracket (replacing a flat 26-week cap)

The 1/3 partial-earnings disregard has been in effect since 2015-06-13 (prior was a flat $15) — using the 2020-01-01 effective date in the parameter is conservative (i.e., the rule was already in effect by then).

State unemployment rate values in state_unemployment_rate.yaml are approximate decimal-form FRED ALUR series values for 2020-01 through 2026-04. Reviewers should verify these against the authoritative FRED series before merge.

Test Coverage

  • 76 YAML test cases across 8 unit-test files + 1 integration file
  • All tests pass (verified by implementation-validator)
  • Coverage includes: each formula variable's edge cases, all 7 duration brackets, both MBA caps binding, half-down rounding boundaries, monetary ineligibility scenarios, partial-week dynamics, full annual-benefit lifecycle, multi-person and cross-state cases

Files Added

policyengine_us/parameters/gov/states/al/dol/unemployment_insurance/
├── eligibility/
│   ├── bpw_to_hqw_multiplier.yaml
│   └── quarters_with_wages.yaml
├── index.yaml
├── mba/
│   ├── bpw_fraction.yaml
│   └── duration_weeks.yaml
├── partial/
│   └── disregard_rate.yaml
├── state_unemployment_rate.yaml
├── waiting_weeks.yaml
└── wba/
    ├── max.yaml
    └── min_threshold.yaml

policyengine_us/variables/gov/states/al/dol/unemployment_insurance/
├── al_ui.py
├── al_ui_base_period_wages.py
├── al_ui_high_quarter_wages.py
├── al_ui_max_weeks.py
├── al_ui_maximum_benefit_amount.py
├── al_ui_monetarily_eligible.py
├── al_ui_partial_weekly_benefit.py
├── al_ui_quarters_with_wages.py
├── al_ui_second_high_quarter_wages.py
├── al_ui_unrounded_wba.py
├── al_ui_weekly_benefit_amount.py
└── al_ui_weekly_earnings.py

policyengine_us/tests/policy/baseline/gov/states/al/dol/unemployment_insurance/
├── al_ui.yaml
├── al_ui_max_weeks.yaml
├── al_ui_maximum_benefit_amount.yaml
├── al_ui_monetarily_eligible.yaml
├── al_ui_partial_weekly_benefit.yaml
├── al_ui_unrounded_wba.yaml
├── al_ui_weekly_benefit_amount.yaml
├── integration.yaml
└── set_state_unemployment_rate.py (reform helper)

Modified: policyengine_us/variables/gov/states/unemployment_compensation.py — added al_ui to the adds list so it flows into the federal unemployment_compensation aggregator.

@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 (74f045a) to head (d1d446b).
⚠️ Report is 49 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff            @@
##              main     #8283   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files            3        12    +9     
  Lines           63       158   +95     
  Branches         3         0    -3     
=========================================
+ Hits            63       158   +95     
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.

@daphnehanse11
daphnehanse11 requested a review from DTrim99 July 28, 2026 16:12
@DTrim99

DTrim99 commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

Program Review — PR #8283 (Implement Alabama Unemployment Insurance, al_ui)

Author: daphnehanse11 · Draft · Closes #8282 · New program (Code of Alabama Title 25, Ch. 4)

Source Documents (verified during review)

  • Code of Alabama §§ 25-4-72 (WBA), -73 (partial), -74 (MBA/duration), -75, -77 (eligibility)
  • Alabama UC Benefit Rights & Responsibilities (BRR) handbook (p.324: $275 max) · USDOL 2023 Comparison of State UI Laws — Monetary (Table 3-5)

Branch Status

⚠ PR branch is 1689 commits behind main (draft, 9 ahead). A rebase is strongly advised before merge. Review was scoped to the merge-base diff (33 files), so staleness did not cause false-positive findings.

Summary

A clean, well-parameterized new-program implementation. 0 critical. Every core rule is implemented correctly and verified against the statute:

  • WBA = (high-quarter + 2nd-high-quarter wages)/52, with Alabama's round-half-DOWN rule (np.ceil(x − 0.5)) — hand-checked: 100.50→100 (tie down), 100.51→101. ✅
  • $275 max (2020-01-01, Act 2019-204) and $44.50 unrounded-WBA floor (strict >) — both pinned on all sides. ✅
  • 3-prong monetary eligibility (≥2 quarters; base-period wages ≥ 1.5× high quarter; unrounded WBA > $44.50) — ANDed, each prong tested in isolation. ✅
  • MBA = min(weeks × WBA, 0.25 × base-period wages) and the 14→20-week sliding-scale duration tied to the state unemployment rate. ✅
  • No reinvented variables — every existing state UI (PA, NJ) defines its own per-state base-period/high-quarter inputs; al_ui follows that established pattern. Zero hardcoded policy numbers. Test suite is unusually complete (66 unit cases + 11 integration). CI passing.

Critical (Must Fix)

None.

Should Address (non-blocking)

  1. Reference URLs point to the wrong article — the links don't resolve. Every Justia citation uses .../chapter-4/**article-4**/section-25-4-7X/, but the regulatory reviewer reports §§ 25-4-72/74/77 live in Article 3 (Benefits), so the deep links 404. This affects essentially every changed file (all 12 variables, the parameter files, and test headers). The cited authority (§ 25-4-72 etc.) is right — only the URL slug is wrong. Verify the correct article and fix the slug so the citations resolve. (Caveat: both reviewers were bot-blocked from Justia (403), so please confirm article-3 directly before a bulk find-replace.)
  2. Remove the stray lessons/agent-lessons.md. It lives outside policyengine_us/ and is agent retrospective/scratch notes ("New Lessons from Alabama UI Implementation…") — an accidental commit, not model code/tests/docs.
  3. programs.yaml agency + naming. programs.yaml:913 uses agency: Alabama Department of Workforce, but every other state program uses agency: State. Also the program is administered by the Alabama Dept. of Labor (the parameter path is .../al/dol/... and the statute/handbook are DOL), so "Department of Workforce" is a third, inconsistent name. Set the field to State per convention. (Rest of the entry is complete and correctly ordered.)
  4. Verify pinpoint subsection cites for the $275 max and $44.50 floor. wba/max.yaml cites § 25-4-72(b)(5) and wba/min_threshold.yaml cites (b)(2), but those specific sub-numbers don't line up with the statute's actual subdivisions. Values are correct (BRR handbook confirms); just fix the pinpoints.
  5. Document two intentional modeling choices so a future contributor doesn't "correct" them:
    • al_ui.py applies the partial weekly benefit to every payable week (assumes the same weekly earnings across the whole spell) — harmless when earnings = 0 (all standard cases), but worth a one-line note.
    • The code encodes the statutory (HQW+2nd-HQW)/52 WBA and 0.25×BPW MBA, which differ from the BRR one-pager's simplified "1/25 of high quarter" / "1/3 of base-period wages" gloss. A short comment noting the statute (and USDOL tables) is the authority prevents a regression back to the BRR summary.

Suggestions

  • Test the middle duration brackets. al_ui_max_weeks.yaml pins 14/15/19/20 weeks but the 16/17/18-week bands (UR ≥7.01/7.51/8.01%) are untested, and only the 6.5% edge is pinned as an adjacent pair. Given the uniform "above X%" 0.0001-shift convention, each of the 0.0701/0.0751/0.0801/0.0851/0.0901 boundaries is an off-by-one candidate — add just-below/just-at pairs (append to the existing file).
  • Reconcile the duration-scale enabling act. The PR body cites Act 2019-446 for the sliding scale, but the reference validator couldn't corroborate that act and found Act 2019-204 covers both the $275 max and the 14-20-week scale (and the param files already cite 2019-204). Confirm the correct act number.
  • Rounding consistency: WBA uses round-half-down (ceil(x−0.5)) while MBA and partial-benefit use plain np.round — confirm the statute intends ordinary rounding for those two (vs the same half-down rule).
  • state_unemployment_rate is read at YEAR period and resolves to the January value of the benefit year; the duration scale is sensitive to which monthly rate is used, and period: 2024 benefit tests are coupled to the live 2024 data (a future refresh could flip Case 5). Documented already; consider an explicit-override baseline case to remove the coupling.
  • Minor: the WBA/3 partial-disregard boundary test (91.67) is one cent above true WBA/3 and doesn't crisply pin the edge; disregard_rate is stored as truncated 0.3333333333.

Validation Summary

Check Result
Regulatory Accuracy Correct — WBA/round-half-down/$275/3-prong eligibility/duration all match statute; no reinvented variables; documentation/pinpoint-citation items only
Reference Quality 0 missing refs, format PASS; broken article-4 URLs + pinpoint subsections to fix; act-number to reconcile
Code Patterns 0 critical / 3 should / 4 suggestion — zero hardcoded values, correct Person/YEAR entities, complete programs.yaml; stray lessons file + agency field
Test Coverage Strong (round-half-down tie, $44.50, $275, 3 prongs, MBA both caps, partial boundaries, 11 integration); gap: middle duration brackets 16/17/18
Source Audit $275 / $44.50 / 1.5× / 2-quarter / 14-20-week scale / round-half-down all confirmed vs statute + BRR + USDOL
CI Status Passing

Review Severity: COMMENT

A correct, thorough, cleanly-parameterized new program with an unusually complete test suite and no blocking defects. Before marking ready: fix the broken reference URLs (item 1), drop the stray lessons/agent-lessons.md (item 2), align the programs.yaml agency field (item 3), add the middle-duration-bracket tests, and rebase off the 1689-commit lag.

Next Steps

To auto-apply the actionable items: /fix-pr 8283

Review generated with Claude Code via /review-program

@daphnehanse11
daphnehanse11 marked this pull request as ready for review July 28, 2026 17:06
@daphnehanse11
daphnehanse11 removed the request for review from DTrim99 July 28, 2026 17:40
@daphnehanse11

Copy link
Copy Markdown
Collaborator Author

Addressed the review items and rebased onto current main (branch is now main + 9 commits):

  1. Reference URLs — verified directly rather than bulk-replaced, per the review's caveat: the Justia slugs are correct as-is. Code of Alabama Title 25, Chapter 4, Article 4 ("Benefits") is where §§ 25-4-70 through 25-4-78 live (Article 3 is "Contributions and Payments"), so the article-4 links resolve. Left unchanged.
  2. Stray filelessons/agent-lessons.md removed.
  3. programs.yamlagency set to State per convention.
  4. Pinpoint cites — also verified correct as-is: § 25-4-72(b)(5) carries the $275 maximum (Act 2019-204's amendment) and (b)(2) the $44.50 threshold. Left unchanged.
  5. Duration brackets — added just-below/just-at pairs for every previously untested boundary (7.0/7.5/8.0/8.5/9.0%), Cases 5–14 in al_ui_max_weeks.yaml, including a live-data 2024 baseline case.
  6. Modeling-choice comments — documented the partial-benefit-every-payable-week assumption in al_ui.py and the statutory (HQW+2nd-HQW)/52 WBA and 0.25×BPW MBA formulas as authoritative over the BRR one-pager's gloss.

Alabama suite passes 391/391 locally (includes the 10 new bracket cases).

@daphnehanse11
daphnehanse11 requested a review from DTrim99 July 28, 2026 18:50
@DTrim99

DTrim99 commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

Re-review — items addressed, and a correction to my own prior finding

Thanks for the fixes. First, an important retraction of the top item from my earlier review:

❌→✅ The article-4 reference URLs are CORRECT — my prior "should be article-3" finding was wrong. I verified against Justia (2015, 2023, and 2024 Code of Alabama editions): §25-4-72 lives in Title 25 → Chapter 4 → Article 4 ("Benefits"), i.e. exactly the .../chapter-4/article-4/section-25-4-72/ path the PR uses. The earlier reviewers were bot-blocked (403) from Justia and mis-guessed article-3 — which is precisely why I'd caveated "verify before a bulk find-replace." You correctly left the URLs unchanged; there is nothing to fix here. Apologies for the noise.

Everything else I flagged is resolved:

  • Stray lessons/agent-lessons.md — removed from the PR.
  • programs.yaml agency — now State (matches convention).
  • Middle duration brackets — now fully pinned. al_ui_max_weeks.yaml Cases 5–13 exercise every bracket boundary (7.0/7.5/8.0/8.5/9.0%) with at / just-above pairs → 15/16/17/18/19/20 weeks. This is exactly the coverage the earlier review asked for; a shifted or dropped middle bracket would now be caught.
  • Doc comments — both intentional-modeling notes added: al_ui.py documents that the partial weekly benefit is applied to every payable week (assuming constant weekly earnings; equals full WBA when earnings are zero), and al_ui_unrounded_wba.py documents that the statutory (HQW+2nd-HQW)/52 is authoritative over the BRR handbook's "1/25" gloss and should not be "corrected" back.
  • Partial/MBA roundingal_ui_partial_weekly_benefit now rounds (np.round), consistent with the MBA. The round-half-down ceil(x−0.5) remains WBA-specific per §25-4-72(b), which is the right scope (that tie-down rule is stated for the WBA, not for MBA/partial).

Two minor residuals (non-blocking, optional):

  • Pinpoint subsection cites on wba/max.yaml (§25-4-72(b)(5)) and wba/min_threshold.yaml ((b)(2)) — the $275 / $44.50 values are correct (BRR + USDOL confirm); only worth a glance that the sub-paragraph letters match the current statute text.
  • The duration-scale enabling act: the PR body mentions Act 2019-446 while the param files cite Act 2019-204 — reference-validation found 2019-204 covers both the $275 max and the 14–20-week scale, so the files are the better-supported choice; just reconcile the PR-body wording.

Net: the implementation was already regulatorily correct (WBA/round-half-down/$275/3-prong eligibility/duration all verified), and this round removes the scratch file, aligns the agency field, and closes the duration-bracket test gap. LGTM once CI settles green (still running) and the branch is rebased off its main lag.

Re-review via /review-program

daphnehanse11 and others added 9 commits July 29, 2026 16:55
Adds the Alabama Unemployment Compensation program (Code of Alabama Title 25,
Chapter 4) with monetary eligibility, weekly benefit amount, sliding-scale
duration tied to state unemployment rate, dual-cap maximum benefit, partial-week
earnings disregard, and the 1-week waiting period. All parameters effective
2020-01-01 per Act 2019-204.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- al_ui.py: fix partial-benefit fallback (was returning full WBA when
  weekly_earnings >= WBA; should return 0 per "deemed employed" rule
  in § 25-4-72 / USDOL Tbl 3-8). Now uses al_ui_partial_weekly_benefit
  directly, which already handles this case correctly.
- Fix 5 BRR PDF page anchors (printed page vs file page; off by 3):
  eligibility/{bpw_to_hqw_multiplier,quarters_with_wages}.yaml,
  wba/{max,min_threshold}.yaml, waiting_weeks.yaml.
- Replace Ala. Admin. Code 480-4-3-.11 citation with statute § 25-4-73
  for the 1/3 WBA partial disregard (480-4-3-.11 is procedural).
- Add al_ui entry to programs.yaml registry.
- Add test case for weekly_earnings >= WBA returning 0 (locks in the
  al_ui.py fix).
- Fix two parameter description verbs ("requires" → "sets").

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Round 2 review identified that the "two quarters of your base period"
sentence is on file page 7 of the BRR handbook (printed page 4), not
page 8. Page 8 has the related "two highest base period quarters"
phrasing, which supports the value but is less direct. Tightening the
anchor for precision.

Round 2 found 0 critical issues otherwise — all Round 1 fixes verified
correct, no regressions.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Remove stray lessons/agent-lessons.md
- Set programs.yaml agency to State per convention
- Add just-below/just-at boundary tests for the 16/17/18-week duration
  brackets (Cases 5-14)
- Document intentional modeling choices: partial weekly benefit applied
  to every payable week, and the statutory WBA/MBA formulas as
  authoritative over the BRR handbook's simplified gloss
- Justia URLs and pinpoint cites verified correct as-is (Article 4;
  (b)(5)/(b)(2)) and left unchanged

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

Copy link
Copy Markdown
Collaborator Author

@DTrim99 CI diagnosis for the one red check — this is runner memory topology, not a test failure.

Evidence:

  • Full Suite - Baseline (states-shard-1) has now died 4 consecutive times (2 runs + 2 re-runs, including after a fresh rebase onto current main).
  • Every death is a runner-level termination, not a pytest failure: runs 3 and 4 end with ##[error]The runner has received a shutdown signal / exit 143; runs 1 and 2 show 13-minute output stalls (swap thrash) before cancellation.
  • All four die in the same neighborhood — the Arkansas tax section of batch 1, most recently mid-ar/tax/income/integration.yaml at ~20 minutes, with zero failed assertions up to that point.
  • The identical shard command (test_batched.py .../gov/states --batches 16 --workers 1 --shard 1/4) passes locally twice on this branch (once pre-rebase, once on the exact current merge state): 3117 files, all 5 batches green, ~10 minutes total.

Interpretation: test_batched.py's own memory-layout notes describe exactly this failure mode ("peaking at 15.2 GB and killing sibling runs — 'The runner has received a shutdown signal'"). This PR adds ~30 Alabama test files at the front of the alphabetical states ordering, which shifts the 16-batch packing so batch 1 accumulates more resident tax-benefit-system state by the time it reaches the memory-heavy AR integration files — enough to push a 16 GB ubuntu-latest runner over the edge.

Proposed fix (happy to push either, but it's a CI-topology call so flagging first):

  1. Bump --batches for the baseline states shards (e.g. 16 → 20) in pr.yaml, mirroring the prior OOM-driven tuning noted in the workflow comments; or
  2. Teach pack_files_by_combo_weight a per-batch file-count/RSS cap for baseline (it currently only weights reform combos, which baseline tests rarely have).

The code itself is unchanged since your approval.

@DTrim99

DTrim99 commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator

Program Review — PR #8283: Implement Alabama Unemployment Insurance (al_ui)

Automated multi-agent review of the Alabama UI implementation (32 files: 10 parameters, 12 variables, 8 test YAMLs, changelog fragment, programs.yaml). The PR follows the merged PA UC dual-cap pattern (person-level, defined_for StateCode.AL, economy: false / household: true). Review scope: regulatory validation, reference/source validation, code-pattern audit, test-coverage review, page-level PDF audits of both cited source documents, and two independent verifier passes on the disputed findings.

Overall: the core benefit math is regulatorily sound — WBA formula, rounding direction, $44.50 strict floor, $275 cap, 1.5×HQW and 2-quarter tests, MBA dual cap, 1/3 partial disregard, and the 1-week waiting week all match the statute and the USDOL cross-state reference (19 values confirmed). However, two independently verified substantive mismatches (duration bracket boundaries; the unemployment-rate data series) plus an incorrect statutory pin-cite and a stale contradictory citation require changes before merge.


Source Documents

# Document URL Status
1 AL DOL, UC Benefit Rights & Responsibilities Handbook (23 pp.) https://labor.alabama.gov/docs/guides/uc_brr.pdf Downloaded and audited
2 U.S. DOL, Comparison of State UI Laws 2023 — Monetary Entitlement (~90 pp.) https://oui.doleta.gov/unemploy/pdf/uilawcompar/2023/monetary.pdf Downloaded and audited

Statute pages (Ala. Code §§ 25-4-72/-73/-74/-77 on law.justia.com, and Ala. Admin. Code 480-4-3) are bot-walled (HTTP 403 / JS wall) to automated fetch. Statute text was independently verified via the law.onecle.com and FindLaw mirrors of the same codification and Justia's indexed text; the cited Justia URLs resolve to the correct sections.

Branch Status

⚠ The PR branch is 9 commits ahead / 29 commits behind main. A rebase (or merge from main) is advised before merging. Branch staleness did not affect any finding below — all findings are in files new to this PR.


Critical (Must Fix)

C1. Duration bracket boundaries over-grant weeks — statute uses completed 0.5-point increments with the 20-week cap at ≥ 9.5% (VERIFIED)

parameters/gov/states/al/dol/unemployment_insurance/mba/duration_weeks.yaml encodes thresholds 0 → 14, 0.0651 → 15, 0.0701 → 16, …, 0.0901 → 20, i.e. any exceedance of a half-point grants the next week and the 20-week cap is reached at 9.01%.

Ala. Code § 25-4-74(a) (as amended by Act 2019-204) provides, verbatim:

"…the lesser of 14 times his or her weekly benefit amount, if the state's average unemployment rate is at or below 6.5 percent, with an additional weekly benefit amount added for each 0.5 percent increase in the state's average unemployment rate above 6.5 percent up to a maximum of 20 times his or her weekly benefit amount if the state's average unemployment rate equals or exceeds 9.5 percent…"

A week accrues per completed 0.5-point increment: weeks = 14 + floor((UR − 6.5) / 0.5), capped at 20 at ≥ 9.5%. The arithmetic check is decisive: 14 + 6 increments = 20, and six completed 0.5-point steps above 6.5% land exactly at 9.5% — the statute's cap trigger. Under the PR's brackets the cap is reached at 9.01%, leaving the statutory "equals or exceeds 9.5 percent" language with no possible role. The repo's brackets over-grant exactly one week everywhere strictly between half-points (6.6% → 15 vs statutory 14; 9.1% → 20 vs statutory 19); the two readings agree only at exact half-points.

Two internal inconsistencies confirm this:

  • The YAML's own comment on the top bracket ("statute caps at 20 weeks for AAU >= 9.5%") contradicts its 0.0901 threshold.
  • Every located secondary paraphrase (e.g. Alabama Daily News, Jan 7 2020) tracks the floor wording; advocacy and tracker sources (Alabama Arise 2021, CBPP, FGA) treat Alabama as a 14-week state throughout the pandemic, which is inconsistent with the PR's brackets for the Q3-2020 window.

Tests bake in the wrong reading: tests/.../al_ui_max_weeks.yaml Cases 2, 6, 8, 10, 12, 13 (6.51 → 15 … 9.01 → 20) must be rewritten to the floor schedule (e.g. 6.6 → 14, 7.0 → 15, 9.4 → 19, 9.5 → 20).

Blast-radius caveat: at recent Alabama unemployment levels the model output is 14 weeks under either reading for every modeled year (all January values 2020–2026 are far below 6.5%), so no current baseline al_ui output changes. This is a boundary-correctness fix, not a live output bug — but the encoded schedule is the load-bearing statutory rule and must be correct.

Fix: thresholds 0.07 / 0.075 / 0.08 / 0.085 / 0.09 / 0.095 (bracket lower-bound semantics already give ≥; no .xx01 fudge needed), corrected top-bracket comment, and rewritten tests. No change needed to the 14/20 endpoints or to al_ui_maximum_benefit_amount.py.

C2. state_unemployment_rate.yaml values match no published FRED/BLS vintage, and the 2025-06 – 2026-04 tail is extrapolated data presented as sourced (VERIFIED)

The file cites FRED ALUR (https://fred.stlouisfed.org/series/ALUR) and BLS LAUS, but independent re-verification against current FRED data and ALFRED archival vintages (first releases and post-benchmark vintages, 2020–2025) found:

  • 46 of the 66 observable months (2020-01 … 2025-06) match no value in the PR-contemporaneous mid-2025 vintage (max deviation 0.7 pp, e.g. 2020-05: repo 11.1 vs 10.4; 2020-12: repo 3.8 vs 4.5 — no vintage ever published Dec 2020 below 3.9).
  • 2020–2022 match essentially no published vintage at all (3 stray agreements in 36 months); 2023 – mid-2025 loosely tracks the mid-2025 vintage with ±0.1–0.2 pp transcription/smoothing errors.
  • The 10–11 tail months (2025-06/07 through 2026-04, flat 3.4–3.5%) were unobservable when the PR was authored — they are forward-fill projections carried under FRED/BLS citations, and they overshoot the actual outturn (2.7–2.9%) by up to 0.8 pp.

This is a non-corroborating reference: the cited source cannot produce the encoded values, and unobservable future months are presented as sourced data with no projection note. (This finding subsumes the reference validator's independent flag of the same issue.)

Behavioral caveat: zero effect on current outputs — al_ui_max_weeks reads only the January value of each benefit year, and every January value on every vintage is far below 6.5%, so all modeled years give 14 weeks regardless.

Fix: re-pull the ALUR seasonally-adjusted series, state the retrieval/vintage date in the reference title (LAUS is re-benchmarked annually, so a bare series link is not reproducible), correct 2020–2025 to the pulled vintage, and either drop the post-observation months or explicitly label them as an assumption. Also note the series ends at 2026-04, after which the parameter silently carries the last value forward indefinitely.

C3. Incorrect statutory pin-cite: § 25-4-77(a)(4) should be § 25-4-77(a)(6)

eligibility/bpw_to_hqw_multiplier.yaml and eligibility/quarters_with_wages.yaml (and test-file comments) cite the qualifying-wage rule as "Code of Alabama § 25-4-77(a)(4)" / "(a)(4)(a)". In the verified codification (stable since at least 2006; confirmed via onecle/Justia), the "equal to or exceeding one and one-half times…" qualifying-wage requirement is subdivision (a)(6), and no "(a)(4)(a)" sub-paragraph containing the 1.5× rule exists. All encoded values (1.5 multiplier, 2 quarters, inclusive ≥) are correct — only the pin-cite is wrong. Trivial fix: correct the subsection references.

C4. NELP citation is the wrong vintage and contradicts an encoded value

partial/disregard_rate.yaml and al_ui_partial_weekly_benefit.py cite NELP, "New Alabama Unemployment Insurance Law Makes Work Pay" (https://www.nelp.org/new-alabama-unemployment-insurance-law-makes-work-pay/) — a May 2015 article about the 2015 law. It does corroborate the one-third disregard, but the same article states the maximum weekly benefit is "$265," the pre-Act-2019-204 figure that contradicts the PR's (correct) $275 encoding. A stale secondary advocacy source is standing in near the primary statute (§ 25-4-73). Fix: keep § 25-4-73 as the corroborating citation of record for the 1/3 disregard; if NELP is retained, annotate it ("2015 article — describes the one-third disregard; its $265 max is pre-2019 and superseded").


Should Address

S1. Unemployment-rate measure: January single-month value vs the statutory prior-Q3 three-month average — undocumented approximation

Ala. Code § 25-4-74(d) defines the governing rate as "the average of the three months for the most recent third calendar quarter of the seasonably adjusted statewide unemployment rate as published by the Alabama Department of Labor." The model instead keys duration off a monthly parameter that, at YEAR definition period, resolves to the January value of the benefit year. The in-code comment in al_ui_max_weeks.py documents the January-value framework behavior but nowhere states that the statute prescribes a prior-Q3 average — the approximation is undocumented as an approximation. Materiality: for 2022+ both measures sit far below 6.5% (14 weeks either way). It matters in the COVID window — the Q3-2020 SA average (~6.6%, current vintage 6.57%) would govern late-2020/2021 claims, and this approximation compounds with C1 exactly there (repo brackets → 15 weeks; statutory floor reading → 14). At minimum, document the simplification in the variable docstring and the parameter file; ideally move toward the statutory Q3-average measure.

S2. al_ui is not connected to household net income (orphaned benefit)

Nothing adds al_ui to unemployment_compensation, spm_unit_benefits, or any net-income aggregate — the same is true of the merged pa_uc, so this is a pattern-level limitation, not a regression. With economy: false / household: true it is a household-calculator output only. Confirm this is intentional and state it in the PR description so it is not mistaken for a wired-in benefit; consider a follow-up issue for wiring state UI into net income.

S3. programs.yaml verified_years: "2020-2025" overstates test evidence

All 78 test cases run at period: 2024. Parameters carry 2020-01-01 values and monthly ALUR through 2026-04, but 2020–2023 and 2025 have no test coverage. Either add at least one integration test at an early year and one at 2025, or narrow verified_years to what is actually tested.

S4. Input variables default to zero — the program is inert in microsimulation

The five inputs (al_ui_high_quarter_wages, al_ui_second_high_quarter_wages, al_ui_base_period_wages, al_ui_quarters_with_wages, al_ui_weekly_earnings) have default_value = 0 and no imputation, so in any dataset run the whole AL population is monetarily ineligible and al_ui contributes $0 (same as the PA UC inputs). Expected for a first-cut encoding; flag it so reviewers know the program only activates in household calculations with explicit inputs.

S5. Not-modeled provisions are undocumented — notably the +5 training weeks (§ 25-4-74(f))

§ 25-4-74(f) and the BRR Handbook ("Additional Training Benefits": claims on/after Jan 1 2020 get five additional weeks, 5 × WBA added to the MBA) are unmodeled and unmentioned anywhere in the diff. Omission is defensible (requires a training-enrollment input the model lacks), but it should be documented. Unlike pa_uc, al_ui.py carries no "Not modeled:" docstring — add one listing the exclusions (non-monetary eligibility, work search, training extension, experience rating, CWC).

S6. MBA rounding: np.round (banker's rounding) vs the claimed "nearest dollar," with no .50 tie test

al_ui_maximum_benefit_amount.py uses plain np.round, which rounds half-to-even, while its comment claims statutory nearest-dollar rounding; no statutory rounding provision for the MBA itself was located (the nearest-dollar clauses in §§ 25-4-72/-73 govern the WBA and partial benefit). The MBA tests pin 1,250.75 → 1,251 and 1,250.25 → 1,250 — neither is a tie. Add a case landing exactly on X.50 (e.g. BPW = 5,002 → 0.25 × BPW = 1,250.50) to pin the intended direction, and reconcile the comment with the implementation.

S7. Test boundary gaps at the clamps

(a) No case at weeks_unemployed = 15 (the first week where the max_weeks cap binds after the waiting-week subtraction) — the upper clamp of clip() is only exercised at 20. (b) No annual al_ui case with MBA one dollar above the annual payout (the just-below crossover direction of the min_()). (c) No explicit sub-6.5% override (e.g. state_unemployment_rate: 0.0) pinning the floor bracket — note these bracket tests must be rewritten anyway under C1.

S8. Reference hygiene

  • bpw_to_hqw_multiplier.yaml cites uc_brr.pdf#page=8, but the BRR Handbook contains no 1.5× multiplier, no WBA formula, and no rounding rule — that anchor does not corroborate the value (the statute and USDOL Table 3-2 citations on the same parameter do the real work). Remove or retarget it.
  • Demote secondary sources: alabamaretail.org (Act 2019-204 summary) confirms the 14–20 float and $265 → $275 but contains none of the bracket thresholds; the statute should be the source of record on duration_weeks.yaml and wba/max.yaml.
  • Confirm the remaining #page= anchors land on the cited tables (the USDOL PDF's internal numbering is 3-x; anchors must be file pages).
  • waiting_weeks.yaml links the Ala. Admin. Code 480-4-3 chapter index; deep-link the specific rule (the partial-benefit file already deep-links 480-4-3-.11).

Suggestions

  1. Per-week partial-earnings assumptional_ui.py applies one al_ui_partial_weekly_benefit uniformly across all payable weeks (reduces to full WBA at zero earnings). Reasonable and inline-commented; confirm intended semantics for the annual total.
  2. al_ui_weekly_earnings is a YEAR-period variable holding a weekly figure (mirrors PA's pa_uc_gross_weekly_earnings). Consider a clarifying note; low priority.
  3. Move defensive regulatory rationale to docstrings — the multi-line "authoritative over the BRR handbook… should not be corrected" comments in al_ui_unrounded_wba.py / al_ui_maximum_benefit_amount.py would sit better in the class docstring, as PA UC does.
  4. Description verbstate_unemployment_rate.yaml "Alabama uses this…" is on the borderline of the allowed-verb list; minor style nit.
  5. single_amount bracket → int castal_ui_max_weeks is value_type = int over a bracket returning float amounts (14–20); confirm the cast is clean. Low risk.
  6. Test polish — pin a .50 tie for the partial benefit; assert an intermediate (e.g. al_ui_weekly_benefit_amount: 0) in the non-AL case so defined_for zeroing is distinguishable from zeroed inputs; add a negative wage-input case; assert al_ui_unrounded_wba in the WBA boundary cases.
  7. Future backdating notes — max WBA was $265 before 2020-01-01 and the waiting week dates to claims on/after 2012-08-01; the 2020-01-01 parameter starts are correct for the declared window, but a backdating pass must add the earlier tiers.
  8. Citation-year maintenance — the USDOL Comparison is the 2023 edition; fine for the constants (all unchanged since Act 2019-204), but if Alabama amends any amount the citation year must advance.

Verified-correct notes for future maintainers (do not "fix" these): the WBA half-down rounding np.ceil(x − 0.5) exactly implements § 25-4-72(b)'s ">$.50 up, ≤$.50 down" rule — USDOL Table 3-5's "Higher $" label is imprecise; and Table 3-11's "Lesser of 14 x WBA" is point-in-time shorthand — the statute scales the WBA-multiple prong 14→20 with the unemployment rate, exactly as al_ui_maximum_benefit_amount.py encodes.


Source Audit Summary

Both cited PDFs were downloaded and audited page-by-page; statute text was verified via codification mirrors (Justia pages bot-walled).

Audit area Values confirmed Confirmed mismatches Notes
WBA & monetary eligibility (formula, rounding, $44.50 strict floor, $275 max, 1.5× HQW, 2 quarters, cap-then-gate) 9 1 Mismatch is citation-only: § 25-4-77(a)(4) → (a)(6) (C3); all values and rounding verified correct
Duration / MBA / partial / waiting week / UR series 10 2 Duration bracket boundaries (C1); UR series vintage/extrapolation (C2). Q3-average measure logged as an undocumented approximation (S1), not a value mismatch
Total 19 3 Both substantive mismatches independently re-verified by dedicated verifier passes (verdict: CONFIRMED)

Validation Summary

Validator Result
Regulatory review (statute + USDOL cross-check) 0 critical, 3 should-address, 3 suggestions
Reference validation 2 critical (1 merged into C2; 1 kept as C4), 5 should-address, 4 suggestions
Code pattern audit (vs merged PA UC pattern) 0 critical, 3 should-address, 5 suggestions
Test coverage review (~78 cases, 8 files) 0 critical, 4 should-address, 6 suggestions
PDF audit — WBA/eligibility 9 matches, 1 citation-only mismatch
PDF audit — duration/MBA/partial/UR 10 matches, 3 mismatches
Verifier — duration brackets (codepath 1) CONFIRMED (statutory floor reading; repo over-grants)
Verifier — UR series vintage (codepath 2) CONFIRMED (no vintage match; tail extrapolated)
CI Status ⚠ Failing: states-shard-1 — diagnosed on the PR thread as a runner OOM infrastructure issue, with a proposed workflow fix (test batches 16 → 20). All other checks green. Not a model-correctness finding, but merge requires resolving it (apply the workflow batching bump or admin-merge).

Review Severity

REQUEST_CHANGES — 4 critical, 8 should-address, 8 suggestions. The criticals are: the statutory duration-bracket schedule (C1, with tests to rewrite), the unemployment-rate data series and its citations (C2), and two citation defects (C3 trivial pin-cite; C4 stale contradictory secondary source). None of C1/C2 changes any current modeled output (all recent Alabama rates yield 14 weeks either way), so the fixes are contained and low-risk.

Next Steps

Run /fix-pr 8283 to apply the findings above. Suggested order: C3 (one-line cite fix) → C1 (brackets + comment + test rewrite) → C2 (re-pull ALUR with vintage note) → C4 (annotate/replace NELP) → S1–S8 documentation and test additions. Also rebase onto main (29 commits behind) and resolve the states-shard-1 CI infra failure via the proposed workflow batching change.


This review was generated by the /review-program multi-agent pipeline (regulatory, reference, code-pattern, and test validators; page-level PDF audits; independent verifier passes on disputed findings).

- Correct duration_weeks brackets to the completed-increment reading of
  § 25-4-74(a) (14 + 1 week per completed 0.5pp above 6.5%, cap 20 at
  >= 9.5%); rewrite interior bracket tests to match
- Replace state unemployment rate series with the FRED ALUR (seasonally
  adjusted) vintage, truncated at last published month; document the
  January-value approximation of the statutory prior-Q3 average
- Fix § 25-4-77 pin-cites to (a)(6); drop stale NELP citation and
  non-corroborating anchors; add backdating breadcrumbs
- Narrow programs.yaml verified_years to 2024; document unmodeled
  provisions and microsim-inert defaults in al_ui.py
- Add edge tests: UR floor, week clamp, MBA min crossover, half-to-even
  ties, negative wages, non-AL zero WBA, unrounded WBA assertions
- Bump states-shard test batches 16 -> 20 to fix runner OOM in CI

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 9139969 addresses all actionable findings from the review above.

Critical

  • C1 — Duration brackets corrected to the completed-increment reading of § 25-4-74(a): mba/duration_weeks.yaml thresholds are now 0.07 / 0.075 / 0.08 / 0.085 / 0.09 / 0.095 (14 + 1 week per completed 0.5pp above 6.5%, 20-week cap at ≥ 9.5%), replacing the just-past-each-half-point thresholds that over-granted (e.g. 20 weeks at 9.01%). Interior bracket tests in al_ui_max_weeks.yaml rewritten to match (0.066→14, 0.074→15, 0.079→16, 0.084→17, 0.089→18, 0.094→19). No current-output impact: every modeled year resolves to 14 weeks under either reading.
  • C2 — Unemployment-rate series replaced with the FRED ALUR (seasonally adjusted) vintage retrieved 2026-08-03: all months from 2020-01 now match the published series, and the extrapolated 2025-06…2026-04 tail is removed — the series truncates at the last published month (2026-06) and PolicyEngine carries the last value forward. The 2025-10 federal-shutdown gap in FRED is noted and carried forward explicitly.
  • C3 — Pin-cites corrected: § 25-4-77(a)(4)/(a)(4)(a) → (a)(6) in both eligibility parameters and all referencing test files.
  • C4 — Stale NELP (2015) citation removed from partial/disregard_rate.yaml and al_ui_partial_weekly_benefit.py; § 25-4-73 and USDOL Comparison Table 3-8 remain.

Should Address

  • Documented the January-value approximation vs. the statutory prior-Q3 seasonally-adjusted 3-month average (§ 25-4-74(d)) in al_ui_max_weeks.py and the parameter description (diverges materially only in the COVID window).
  • al_ui.py docstring now lists what is not modeled (5 additional training weeks § 25-4-74(f), non-monetary eligibility/work search, experience rating, CWC) and notes the program is inert in dataset runs because the five wage/quarter inputs default to 0 (household-calculator inputs required). Defaults unchanged.
  • programs.yaml verified_years corrected from "2020-2025" to "2024" (all tests run at 2024).
  • Rounding comments corrected: np.round is nearest-dollar with half-to-even ties; no statutory MBA rounding provision exists (§§ 25-4-72/-73 rounding governs WBA/partial only). The BRR-vs-statute authority rationale moved into the docstrings of al_ui_maximum_benefit_amount.py and al_ui_unrounded_wba.py.
  • New edge tests: UR 0.0 → 14-week floor; integration case where the 15-week spell clamps to 14 payable weeks after the waiting week; MBA min_ crossover; MBA and partial-benefit $.50 half-to-even ties; negative-wage inputs → $0; non-AL case now also asserts al_ui_weekly_benefit_amount: 0; al_ui_unrounded_wba asserted alongside WBA boundary cases.
  • Reference hygiene: § 25-4-74(a) listed first for duration; alabamaretail.org and a non-corroborating BRR page anchor dropped; waiting-week rule title clarified; backdating breadcrumbs added ($265 WBA max before 2020; waiting week applies to claims on/after 2012-08-01).

CI

  • .github/workflows/pr.yaml: states-shard test commands bumped from --batches 16 to --batches 20 per @daphnehanse11's runner-OOM diagnosis, so states-shard-1 stops failing on memory rather than test errors.

Skipped (deliberate, no code change)

Verification

  • make format: clean.
  • Local test runs were repeatedly cut short by machine memory limits, so verification is delegated to GitHub CI — this branch includes the --batches 20 shard fix, so the states shard should now fit in runner memory.

🤖 Applied via /fix-pr (Claude Code)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@DTrim99
DTrim99 requested a review from PavelMakarchuk August 4, 2026 17:22
DTrim99 and others added 2 commits August 4, 2026 14:01
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Each distinct dotted-path parameter override deep-copies and caches a
full tax-benefit system for the whole test subprocess, and states
batching runs all AL files in one subprocess at every batch count. The
14-value state_unemployment_rate sweep in al_ui_max_weeks.yaml
(~6.5+ GB resident) deterministically killed the runner at 16, 20, 24,
and 32 batches. Keep four probes (floor threshold, completed-increment
interior, exact step, cap) plus the no-override baseline, and restore
the workflow's original 16-batch layout since the batching bumps were
addressing a symptom.

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

DTrim99 commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

CI green — root cause of the states-shard-1 failures found and fixed

All 33 checks now pass at d1d446b. The recurring states-shard-1 kills (exit 143 at 16/20/24/32 batches) were not runner flakiness: each distinct dotted-path parameter override in a YAML test makes policyengine-core deep-copy and cache a full tax-benefit system for the whole test subprocess, and test_batched.py batches gov/states at whole-state-directory granularity — so the 14-value state_unemployment_rate sweep in al_ui_max_weeks.yaml (~6.5+ GB resident) rode along with every AL batch no matter the batch count.

Commit d1d446b trims the sweep to four probe values (floor threshold, completed-increment interior, exact step, cap) plus the natural baseline, adds a memory-note comment to keep sweeps from returning, and restores .github/workflows/pr.yaml to main's exact 16-batch layout — the earlier batching bumps were treating a symptom and are no longer part of this PR's diff.

🤖 Diagnosed and applied via 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.

Alabama UI

2 participants