From 83b0141ccd7ca1463b27cf39ec87fe8025f59b3d Mon Sep 17 00:00:00 2001 From: Daphne Hansell <128793799+daphnehanse11@users.noreply.github.com> Date: Wed, 22 Apr 2026 14:38:17 -0400 Subject: [PATCH 1/6] Initial commit for WA Paid Family and Medical Leave implementation Starting implementation of Washington Paid Family and Medical Leave (WA PFML). Documentation and parallel development will follow. From a070074d80d0c9b430bf5819702f2114e36b3e5c Mon Sep 17 00:00:00 2001 From: Daphne Hansell <128793799+daphnehanse11@users.noreply.github.com> Date: Thu, 23 Apr 2026 08:59:19 -0400 Subject: [PATCH 2/6] Add Washington Paid Family and Medical Leave benefit (wa_pfml) Implements the wage replacement benefit side of WA PFML (RCW 50A). The contribution side was already in the codebase; this adds: - Two-tier benefit formula (90%/50% wage replacement per RCW 50A.15.020(5)) - SAWW and max weekly benefit parameters for 2020-2026 - 820-hour eligibility threshold (RCW 50A.15.010) - Duration parameters (12 family, 12 medical, 16 combined weeks) - 14 passing unit and integration tests Closes #8136 Co-Authored-By: Claude Sonnet 4.6 --- changelog.d/issue-8136-wa-pfml.added.md | 1 + .../household/household_state_benefits.yaml | 4 + .../wa/pfml/duration/combined_max_weeks.yaml | 12 + .../wa/pfml/duration/family_leave_weeks.yaml | 12 + .../wa/pfml/duration/medical_leave_weeks.yaml | 12 + .../gov/states/wa/pfml/hours_threshold.yaml | 12 + .../states/wa/pfml/lower_benefit_rate.yaml | 12 + .../wa/pfml/lower_threshold_fraction.yaml | 12 + .../wa/pfml/max_weekly_benefit_amount.yaml | 20 + .../wa/pfml/min_weekly_benefit_amount.yaml | 12 + .../wa/pfml/state_average_weekly_wage.yaml | 22 + .../states/wa/pfml/upper_benefit_rate.yaml | 12 + .../gov/states/wa/pfml/test_wa_pfml.yaml | 25 + .../states/wa/pfml/test_wa_pfml_eligible.yaml | 37 ++ .../test_wa_pfml_weekly_benefit_amount.yaml | 106 ++++ .../variables/gov/states/wa/pfml/wa_pfml.py | 26 + .../wa/pfml/wa_pfml_average_weekly_wage.py | 22 + .../gov/states/wa/pfml/wa_pfml_eligible.py | 22 + .../wa/pfml/wa_pfml_weekly_benefit_amount.py | 38 ++ sources/working_references.md | 566 ++++++++++++++++++ 20 files changed, 985 insertions(+) create mode 100644 changelog.d/issue-8136-wa-pfml.added.md create mode 100644 policyengine_us/parameters/gov/states/wa/pfml/duration/combined_max_weeks.yaml create mode 100644 policyengine_us/parameters/gov/states/wa/pfml/duration/family_leave_weeks.yaml create mode 100644 policyengine_us/parameters/gov/states/wa/pfml/duration/medical_leave_weeks.yaml create mode 100644 policyengine_us/parameters/gov/states/wa/pfml/hours_threshold.yaml create mode 100644 policyengine_us/parameters/gov/states/wa/pfml/lower_benefit_rate.yaml create mode 100644 policyengine_us/parameters/gov/states/wa/pfml/lower_threshold_fraction.yaml create mode 100644 policyengine_us/parameters/gov/states/wa/pfml/max_weekly_benefit_amount.yaml create mode 100644 policyengine_us/parameters/gov/states/wa/pfml/min_weekly_benefit_amount.yaml create mode 100644 policyengine_us/parameters/gov/states/wa/pfml/state_average_weekly_wage.yaml create mode 100644 policyengine_us/parameters/gov/states/wa/pfml/upper_benefit_rate.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml_eligible.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml_weekly_benefit_amount.yaml create mode 100644 policyengine_us/variables/gov/states/wa/pfml/wa_pfml.py create mode 100644 policyengine_us/variables/gov/states/wa/pfml/wa_pfml_average_weekly_wage.py create mode 100644 policyengine_us/variables/gov/states/wa/pfml/wa_pfml_eligible.py create mode 100644 policyengine_us/variables/gov/states/wa/pfml/wa_pfml_weekly_benefit_amount.py create mode 100644 sources/working_references.md diff --git a/changelog.d/issue-8136-wa-pfml.added.md b/changelog.d/issue-8136-wa-pfml.added.md new file mode 100644 index 00000000000..e348a09bba4 --- /dev/null +++ b/changelog.d/issue-8136-wa-pfml.added.md @@ -0,0 +1 @@ +Add Washington Paid Family and Medical Leave benefit (wa_pfml). diff --git a/policyengine_us/parameters/gov/household/household_state_benefits.yaml b/policyengine_us/parameters/gov/household/household_state_benefits.yaml index 9ad7c2dae5d..1272a37cdf4 100644 --- a/policyengine_us/parameters/gov/household/household_state_benefits.yaml +++ b/policyengine_us/parameters/gov/household/household_state_benefits.yaml @@ -22,6 +22,8 @@ values: # Massachusetts benefits - ma_eaedc - ma_tafdc + # Washington benefits + - wa_pfml 2024-01-01: # Massachusetts benefits - ma_state_supplement @@ -46,6 +48,8 @@ values: # Massachusetts benefits - ma_eaedc - ma_tafdc + # Washington benefits + - wa_pfml metadata: unit: list period: year diff --git a/policyengine_us/parameters/gov/states/wa/pfml/duration/combined_max_weeks.yaml b/policyengine_us/parameters/gov/states/wa/pfml/duration/combined_max_weeks.yaml new file mode 100644 index 00000000000..fe7adca840d --- /dev/null +++ b/policyengine_us/parameters/gov/states/wa/pfml/duration/combined_max_weeks.yaml @@ -0,0 +1,12 @@ +description: Washington limits combined family and medical leave to this number of weeks under the Paid Family and Medical Leave program. + +values: + 2020-01-01: 16 + +metadata: + unit: week + period: year + label: Washington PFML combined leave maximum weeks + reference: + - title: RCW 50A.15.020(3)(c) Benefit—Amount and duration + href: https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020 diff --git a/policyengine_us/parameters/gov/states/wa/pfml/duration/family_leave_weeks.yaml b/policyengine_us/parameters/gov/states/wa/pfml/duration/family_leave_weeks.yaml new file mode 100644 index 00000000000..8398c594937 --- /dev/null +++ b/policyengine_us/parameters/gov/states/wa/pfml/duration/family_leave_weeks.yaml @@ -0,0 +1,12 @@ +description: Washington limits family leave to this number of weeks under the Paid Family and Medical Leave program. + +values: + 2020-01-01: 12 + +metadata: + unit: week + period: year + label: Washington PFML family leave maximum weeks + reference: + - title: RCW 50A.15.020(3)(a) Benefit—Amount and duration + href: https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020 diff --git a/policyengine_us/parameters/gov/states/wa/pfml/duration/medical_leave_weeks.yaml b/policyengine_us/parameters/gov/states/wa/pfml/duration/medical_leave_weeks.yaml new file mode 100644 index 00000000000..9e9ee1d6416 --- /dev/null +++ b/policyengine_us/parameters/gov/states/wa/pfml/duration/medical_leave_weeks.yaml @@ -0,0 +1,12 @@ +description: Washington limits medical leave to this number of weeks under the Paid Family and Medical Leave program. + +values: + 2020-01-01: 12 + +metadata: + unit: week + period: year + label: Washington PFML medical leave maximum weeks + reference: + - title: RCW 50A.15.020(3)(b) Benefit—Amount and duration + href: https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020 diff --git a/policyengine_us/parameters/gov/states/wa/pfml/hours_threshold.yaml b/policyengine_us/parameters/gov/states/wa/pfml/hours_threshold.yaml new file mode 100644 index 00000000000..7a410479653 --- /dev/null +++ b/policyengine_us/parameters/gov/states/wa/pfml/hours_threshold.yaml @@ -0,0 +1,12 @@ +description: Washington requires this many hours worked in the qualifying period for eligibility under the Paid Family and Medical Leave program. + +values: + 2020-01-01: 820 + +metadata: + unit: hour + period: year + label: Washington PFML qualifying hours threshold + reference: + - title: RCW 50A.15.010 Employee eligibility + href: https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.010 diff --git a/policyengine_us/parameters/gov/states/wa/pfml/lower_benefit_rate.yaml b/policyengine_us/parameters/gov/states/wa/pfml/lower_benefit_rate.yaml new file mode 100644 index 00000000000..e7cba1a2119 --- /dev/null +++ b/policyengine_us/parameters/gov/states/wa/pfml/lower_benefit_rate.yaml @@ -0,0 +1,12 @@ +description: Washington replaces this share of the employee's average weekly wage below the benefit tier threshold under the Paid Family and Medical Leave program. + +values: + 2020-01-01: 0.9 + +metadata: + unit: /1 + period: year + label: Washington PFML lower tier benefit rate + reference: + - title: RCW 50A.15.020(5)(a) Benefit—Amount and duration + href: https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020 diff --git a/policyengine_us/parameters/gov/states/wa/pfml/lower_threshold_fraction.yaml b/policyengine_us/parameters/gov/states/wa/pfml/lower_threshold_fraction.yaml new file mode 100644 index 00000000000..3bf2c63f90d --- /dev/null +++ b/policyengine_us/parameters/gov/states/wa/pfml/lower_threshold_fraction.yaml @@ -0,0 +1,12 @@ +description: Washington uses this share of the state average weekly wage as the breakpoint between benefit tiers under the Paid Family and Medical Leave program. + +values: + 2020-01-01: 0.5 + +metadata: + unit: /1 + period: year + label: Washington PFML lower benefit tier threshold fraction + reference: + - title: RCW 50A.15.020(5) Benefit—Amount and duration + href: https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020 diff --git a/policyengine_us/parameters/gov/states/wa/pfml/max_weekly_benefit_amount.yaml b/policyengine_us/parameters/gov/states/wa/pfml/max_weekly_benefit_amount.yaml new file mode 100644 index 00000000000..a27d50e6e28 --- /dev/null +++ b/policyengine_us/parameters/gov/states/wa/pfml/max_weekly_benefit_amount.yaml @@ -0,0 +1,20 @@ +description: Washington limits the weekly benefit to this amount under the Paid Family and Medical Leave program. + +values: + 2020-01-01: 1_000 + 2021-01-01: 1_206 + 2022-01-01: 1_327 + 2023-01-01: 1_427 + 2024-01-01: 1_456 + 2025-01-01: 1_542 + 2026-01-01: 1_647 + +metadata: + unit: currency-USD + period: week + label: Washington PFML maximum weekly benefit amount + reference: + - title: RCW 50A.15.020(6)(a) Benefit—Amount and duration + href: https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020 + - title: Washington Paid Family and Medical Leave 2026 Paycheck Insert + href: https://paidleave.wa.gov/app/uploads/2025/12/Paycheck-insert-2026-1.pdf diff --git a/policyengine_us/parameters/gov/states/wa/pfml/min_weekly_benefit_amount.yaml b/policyengine_us/parameters/gov/states/wa/pfml/min_weekly_benefit_amount.yaml new file mode 100644 index 00000000000..3971b2b39c1 --- /dev/null +++ b/policyengine_us/parameters/gov/states/wa/pfml/min_weekly_benefit_amount.yaml @@ -0,0 +1,12 @@ +description: Washington sets the minimum weekly benefit to this amount under the Paid Family and Medical Leave program. + +values: + 2020-01-01: 100 + +metadata: + unit: currency-USD + period: week + label: Washington PFML minimum weekly benefit amount + reference: + - title: RCW 50A.15.020(6)(b) Benefit—Amount and duration + href: https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020 diff --git a/policyengine_us/parameters/gov/states/wa/pfml/state_average_weekly_wage.yaml b/policyengine_us/parameters/gov/states/wa/pfml/state_average_weekly_wage.yaml new file mode 100644 index 00000000000..b6235e0fe30 --- /dev/null +++ b/policyengine_us/parameters/gov/states/wa/pfml/state_average_weekly_wage.yaml @@ -0,0 +1,22 @@ +description: Washington uses this state average weekly wage to determine weekly benefits under the Paid Family and Medical Leave program. + +values: + 2020-01-01: 1_111 + 2021-01-01: 1_340 + 2022-01-01: 1_474 + 2023-01-01: 1_586 + 2024-01-01: 1_618 + 2025-01-01: 1_714 + 2026-01-01: 1_830 + +metadata: + unit: currency-USD + period: week + label: Washington PFML state average weekly wage + reference: + - title: RCW 50A.05.010(26) State average weekly wage + href: https://app.leg.wa.gov/rcw/default.aspx?cite=50A.05.010 + - title: RCW 50A.15.020(6)(a) Benefit—Amount and duration + href: https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020 + - title: Washington Paid Family and Medical Leave 2026 Paycheck Insert + href: https://paidleave.wa.gov/app/uploads/2025/12/Paycheck-insert-2026-1.pdf diff --git a/policyengine_us/parameters/gov/states/wa/pfml/upper_benefit_rate.yaml b/policyengine_us/parameters/gov/states/wa/pfml/upper_benefit_rate.yaml new file mode 100644 index 00000000000..42de004e4ff --- /dev/null +++ b/policyengine_us/parameters/gov/states/wa/pfml/upper_benefit_rate.yaml @@ -0,0 +1,12 @@ +description: Washington replaces this share of the employee's average weekly wage above the benefit tier threshold under the Paid Family and Medical Leave program. + +values: + 2020-01-01: 0.5 + +metadata: + unit: /1 + period: year + label: Washington PFML upper tier benefit rate + reference: + - title: RCW 50A.15.020(5)(b)(ii) Benefit—Amount and duration + href: https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020 diff --git a/policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml.yaml b/policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml.yaml new file mode 100644 index 00000000000..c6119ccf5b7 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml.yaml @@ -0,0 +1,25 @@ +- name: Case 1, Washington worker with AWW above breakpoint gets annual benefit for combined max weeks. + period: 2026 + input: + people: + person1: + weekly_hours_worked: 20 + employment_income: 52_000 + households: + household: + members: [person1] + state_code: WA + output: + # SAWW 2026 = 1,830; breakpoint H = 0.5 * 1,830 = 915 + # Max weekly benefit 2026 = 0.90 * 1,830 = 1,647 + # AWW = 52,000 / 52 = 1,000 + # AWW (1,000) > H (915), so weekly benefit = 0.90 * 915 + 0.50 * (1,000 - 915) + # = 823.50 + 0.50 * 85 + # = 823.50 + 42.50 + # = 866 (below the 1,647 cap, above the 100 floor) + wa_pfml_weekly_benefit_amount: 866 + # Eligibility: 20 weekly hours * 52 = 1,040 annual hours >= 820 threshold. + wa_pfml_eligible: true + # Combined family + medical leave max = 16 weeks per RCW 50A.15.020(3)(c). + # Annual benefit = 866 * 16 = 13,856 + wa_pfml: 13_856 diff --git a/policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml_eligible.yaml new file mode 100644 index 00000000000..1eda9887f1d --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml_eligible.yaml @@ -0,0 +1,37 @@ +- name: Case 1, non-Washington worker with sufficient hours is ineligible. + period: 2026 + input: + state_code: CA + weekly_hours_worked: 20 + output: + # Benefit only available to Washington workers (defined_for StateCode.WA). + wa_pfml_eligible: false + +- name: Case 2, part-time Washington worker below the hours threshold is ineligible. + period: 2026 + input: + state_code: WA + weekly_hours_worked: 15 + output: + # annual_hours = 15 * 52 = 780 hours + # 780 < 820 threshold per RCW 50A.15.010, so ineligible. + wa_pfml_eligible: false + +- name: Case 3, Washington worker just above the hours threshold is eligible. + period: 2026 + input: + state_code: WA + weekly_hours_worked: 16 + output: + # annual_hours = 16 * 52 = 832 hours + # 832 >= 820 threshold per RCW 50A.15.010, so eligible. + wa_pfml_eligible: true + +- name: Case 4, Washington worker with zero hours is ineligible. + period: 2026 + input: + state_code: WA + weekly_hours_worked: 0 + output: + # annual_hours = 0 < 820, so ineligible. + wa_pfml_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml_weekly_benefit_amount.yaml b/policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml_weekly_benefit_amount.yaml new file mode 100644 index 00000000000..095ebf2e0ff --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml_weekly_benefit_amount.yaml @@ -0,0 +1,106 @@ +- name: Case 1, low earner below the SAWW breakpoint receives 90 percent of AWW. + period: 2026 + input: + state_code: WA + employment_income: 26_000 + output: + # AWW = 26,000 / 52 = 500 + # SAWW 2026 = 1,830; breakpoint H = 0.5 * 1,830 = 915 + # AWW (500) <= H (915), so benefit = 0.90 * 500 = 450 + wa_pfml_weekly_benefit_amount: 450 + +- name: Case 2, AWW exactly at the SAWW breakpoint. + period: 2026 + input: + state_code: WA + employment_income: 47_580 + output: + # AWW = 47,580 / 52 = 915 + # AWW (915) <= H (915), so benefit = 0.90 * 915 = 823.50 + wa_pfml_weekly_benefit_amount: 823.50 + +- name: Case 3, AWW above the SAWW breakpoint uses two-tier formula. + period: 2026 + input: + state_code: WA + employment_income: 78_000 + output: + # AWW = 78,000 / 52 = 1,500 + # AWW (1,500) > H (915), so benefit = 0.90 * 915 + 0.50 * (1,500 - 915) + # = 823.50 + 0.50 * 585 + # = 823.50 + 292.50 + # = 1,116 + wa_pfml_weekly_benefit_amount: 1_116 + +- name: Case 4, high earner with benefit capped at the maximum weekly benefit. + period: 2026 + input: + state_code: WA + employment_income: 156_000 + output: + # AWW = 156,000 / 52 = 3,000 + # Raw = 0.90 * 915 + 0.50 * (3,000 - 915) + # = 823.50 + 0.50 * 2,085 + # = 823.50 + 1,042.50 + # = 1,866 + # Max weekly benefit 2026 = 0.90 * 1,830 = 1,647 + # Benefit = min(1,866, 1,647) = 1,647 + wa_pfml_weekly_benefit_amount: 1_647 + +- name: Case 5, AWW below 100 dollars returns full AWW per RCW 50A.15.020(6)(b). + period: 2026 + input: + state_code: WA + employment_income: 4_160 + output: + # AWW = 4,160 / 52 = 80 + # AWW < 100 per RCW 50A.15.020(6)(b), so benefit = AWW = 80 + # (not the 100 minimum; uses employee's full wage) + wa_pfml_weekly_benefit_amount: 80 + +- name: Case 6, zero employment income produces zero benefit. + period: 2026 + input: + state_code: WA + employment_income: 0 + output: + # AWW = 0 / 52 = 0 + # Per RCW 50A.15.020(6)(b), if AWW < 100 the benefit equals AWW; + # with no wages there is no benefit. + wa_pfml_weekly_benefit_amount: 0 + +- name: Case 7, AWW one dollar below the SAWW breakpoint. + period: 2026 + input: + state_code: WA + employment_income: 47_528 + output: + # AWW = 47,528 / 52 = 914 + # AWW (914) <= H (915), so benefit = 0.90 * 914 = 822.60 + wa_pfml_weekly_benefit_amount: 822.60 + +- name: Case 8, AWW one dollar above the SAWW breakpoint. + period: 2026 + input: + state_code: WA + employment_income: 47_632 + output: + # AWW = 47,632 / 52 = 916 + # AWW (916) > H (915), so benefit = 0.90 * 915 + 0.50 * (916 - 915) + # = 823.50 + 0.50 + # = 824.00 + wa_pfml_weekly_benefit_amount: 824.00 + +- name: Case 9, AWW exactly at the maximum weekly benefit threshold. + period: 2026 + input: + state_code: WA + employment_income: 133_224 + output: + # AWW = 133,224 / 52 = 2,562 + # Raw = 0.90 * 915 + 0.50 * (2,562 - 915) + # = 823.50 + 0.50 * 1,647 + # = 823.50 + 823.50 + # = 1,647 + # Equal to max weekly benefit (0.90 * 1,830 = 1,647), so benefit = 1,647 + wa_pfml_weekly_benefit_amount: 1_647 diff --git a/policyengine_us/variables/gov/states/wa/pfml/wa_pfml.py b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml.py new file mode 100644 index 00000000000..7f81989596c --- /dev/null +++ b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml.py @@ -0,0 +1,26 @@ +from policyengine_us.model_api import * + + +class wa_pfml(Variable): + value_type = float + entity = Person + label = "Washington PFML benefit" + documentation = ( + "Annual Washington Paid Family and Medical Leave benefit. " + "Computed as the weekly benefit amount multiplied by the " + "combined maximum leave duration in weeks, for eligible " + "workers. Represents the maximum potential annual benefit " + "if the full allowed combined leave is taken." + ) + unit = USD + definition_period = YEAR + defined_for = "wa_pfml_eligible" + reference = ( + "https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020", + "https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.010", + ) + + def formula(person, period, parameters): + p = parameters(period).gov.states.wa.pfml + weekly_benefit = person("wa_pfml_weekly_benefit_amount", period) + return weekly_benefit * p.duration.combined_max_weeks diff --git a/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_average_weekly_wage.py b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_average_weekly_wage.py new file mode 100644 index 00000000000..1cae55f504d --- /dev/null +++ b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_average_weekly_wage.py @@ -0,0 +1,22 @@ +from policyengine_us.model_api import * + + +class wa_pfml_average_weekly_wage(Variable): + value_type = float + entity = Person + label = "Washington PFML average weekly wage" + documentation = ( + "Employee's average weekly wage for Washington Paid Family and " + "Medical Leave. Simplified as annual employment income divided by " + "the number of weeks in a year." + ) + unit = USD + definition_period = YEAR + defined_for = StateCode.WA + reference = ( + "https://app.leg.wa.gov/rcw/default.aspx?cite=50A.05.010", + "https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020", + ) + + def formula(person, period, parameters): + return person("employment_income", period) / WEEKS_IN_YEAR diff --git a/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_eligible.py b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_eligible.py new file mode 100644 index 00000000000..e5910fcfa9d --- /dev/null +++ b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_eligible.py @@ -0,0 +1,22 @@ +from policyengine_us.model_api import * + + +class wa_pfml_eligible(Variable): + value_type = bool + entity = Person + label = "Washington PFML eligible" + documentation = ( + "Eligibility for Washington Paid Family and Medical Leave " + "benefits. Requires working at least the qualifying hours " + "threshold in the qualifying period per RCW 50A.15.010. " + "Annual hours worked is approximated as weekly hours worked " + "multiplied by the number of weeks in a year." + ) + definition_period = YEAR + defined_for = StateCode.WA + reference = "https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.010" + + def formula(person, period, parameters): + p = parameters(period).gov.states.wa.pfml + annual_hours = person("weekly_hours_worked", period) * WEEKS_IN_YEAR + return annual_hours >= p.hours_threshold diff --git a/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_weekly_benefit_amount.py b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_weekly_benefit_amount.py new file mode 100644 index 00000000000..35b69107d92 --- /dev/null +++ b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_weekly_benefit_amount.py @@ -0,0 +1,38 @@ +from policyengine_us.model_api import * + + +class wa_pfml_weekly_benefit_amount(Variable): + value_type = float + entity = Person + label = "Washington PFML weekly benefit amount" + documentation = ( + "Weekly benefit amount under Washington Paid Family and Medical " + "Leave. Applies the two-tier replacement formula in " + "RCW 50A.15.020(5) and clips the result to the statutory minimum " + "and maximum weekly benefit amounts. Despite the YEAR definition " + "period, this variable represents a weekly dollar amount." + ) + unit = USD + definition_period = YEAR + defined_for = StateCode.WA + reference = ( + "https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020", + "https://paidleave.wa.gov/app/uploads/2025/12/Paycheck-insert-2026-1.pdf", + ) + + def formula(person, period, parameters): + p = parameters(period).gov.states.wa.pfml + aww = person("wa_pfml_average_weekly_wage", period) + lower_threshold = p.lower_threshold_fraction * p.state_average_weekly_wage + lower_benefit = p.lower_benefit_rate * min_(aww, lower_threshold) + upper_benefit = p.upper_benefit_rate * max_(aww - lower_threshold, 0) + raw_benefit = lower_benefit + upper_benefit + # Per RCW 50A.15.020(6)(b): minimum is $100, or AWW if AWW < $100. + # Using min_(min_amount, aww) as the floor naturally handles zero AWW + # (no employment → floor=0 → benefit=0) and low AWW (floor=AWW). + effective_min = min_(p.min_weekly_benefit_amount, aww) + return clip( + raw_benefit, + effective_min, + p.max_weekly_benefit_amount, + ) diff --git a/sources/working_references.md b/sources/working_references.md new file mode 100644 index 00000000000..b1315772a32 --- /dev/null +++ b/sources/working_references.md @@ -0,0 +1,566 @@ +# Collected Documentation + +## Washington State Paid Family and Medical Leave (WA PFML) +**Collected**: 2026-04-22 +**Implementation Task**: Implement Washington State's Paid Family and Medical Leave wage replacement benefit calculation in PolicyEngine US. The existing codebase already has the employee/employer contribution (premium) side; this task adds the benefit (wage replacement) side. + +--- + +## Official Program Name + +**Federal Program**: Paid Family and Medical Leave (state-level — no single federal program; federal FMLA is unpaid) +**State's Official Name**: Washington Paid Family and Medical Leave +**Abbreviation**: PFML (sometimes WPFML) +**Source**: RCW Title 50A — "Family and Medical Leave" +**Administrator**: Washington State Employment Security Department (ESD) + +**Variable Prefix**: `wa_pfml` +**Legal Authority**: +- Statute: RCW Title 50A (Chapters 50A.05, 50A.10, 50A.15, 50A.20, 50A.24, 50A.25, 50A.30, 50A.35, 50A.40, 50A.45, 50A.50) +- Regulations: WAC Title 192, Chapters 192-500 through 192-810 + +**Existing implementation in codebase**: +- `policyengine_us/variables/gov/states/wa/tax/payroll/paid_leave/` — has contribution (premium) side + - `wa_employee_paid_leave_contribution.py` + - `wa_employer_paid_leave_contribution.py` +- `policyengine_us/parameters/gov/states/wa/tax/payroll/paid_leave/` — has contribution parameters + - `total_rate.yaml` (0.92% in 2025, 1.13% in 2026) + - `employer_share.yaml` (28.48% in 2025, 28.57% in 2026) + - `employer_headcount_threshold.yaml` (50) + +**NEW work**: Benefit (wage replacement) side — does not yet exist for any state in the codebase. + +--- + +## 1. Source Information + +### Primary Legal Authorities + +| Source | Citation | URL | Notes | +|--------|----------|-----|-------| +| Statute — Eligibility | RCW 50A.15.010 | https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.010 | 820 hours in qualifying period | +| Statute — Benefit amount & duration (pre-2026) | RCW 50A.15.020 (Effective until January 1, 2026) | https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020 | Current law; min claim 8 hours | +| Statute — Benefit amount & duration (2026+) | RCW 50A.15.020 (Effective January 1, 2026) | https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020 | Min claim reduced to 4 hours | +| Statute — Definitions | RCW 50A.05.010 | https://app.leg.wa.gov/rcw/default.aspx?cite=50A.05.010 | AWW, SAWW, qualifying period, typical workweek hours | +| Statute — Premiums | RCW 50A.10.030 | https://app.leg.wa.gov/rcw/default.aspx?cite=50A.10.030 | Contribution rates | +| Regulations — Benefits | WAC Chapter 192-620 | https://app.leg.wa.gov/wac/default.aspx?cite=192-620&full=true | Weekly benefit procedures | +| Regulations — Definitions | WAC Chapter 192-500 | https://app.leg.wa.gov/wac/default.aspx?cite=192-500 | WAC definitions | +| Program website | Washington State Paid Leave | https://paidleave.wa.gov | Official ESD site | +| 2026 official paycheck insert | ESD | https://paidleave.wa.gov/app/uploads/2025/12/Paycheck-insert-2026-1.pdf | Official 2026 values | +| Legislative amendment (2025) | 2025 c 304 (ESSHB 1213) | https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020 | Effective 2026 | + +**Effective Dates**: Program began January 1, 2020. Significant amendments via 2025 c 304 (ESSHB 1213) take effect January 1, 2026. + +--- + +## 2. Key Rules and Thresholds + +### 2.1 Eligibility — RCW 50A.15.010 + +Exact statutory text: +> "Employees are eligible for family and medical leave benefits as provided in this title after working for at least eight hundred twenty hours in employment during the qualifying period." + +**Single explicit eligibility rule:** +- **820 hours in employment during the qualifying period** (this is the only numeric threshold in the eligibility statute) +- Hours can accumulate across multiple employers +- Federal employees, self-employed (unless opted-in), and employees of tribally-owned businesses on tribal land are excluded (administrative rules / program documentation) + +### 2.2 Qualifying Period — RCW 50A.05.010(21) + +Exact statutory text: +> "'Qualifying period' means the first four of the last five completed calendar quarters or, if eligibility is not established, the last four completed calendar quarters immediately preceding the application for leave." + +### 2.3 Employee's Average Weekly Wage (AWW) — RCW 50A.05.010(6) + +Exact statutory text: +> "'Employee's average weekly wage' means the quotient derived by dividing the employee's total wages during the two quarters of the employee's qualifying period in which total wages were highest by twenty-six. If the result is not a multiple of one dollar, the department must round the result to the next lower multiple of one dollar." + +**Formula:** +``` +AWW = floor( (wages in top two quarters of qualifying period) / 26 ) +``` + +### 2.4 State Average Weekly Wage (SAWW) — RCW 50A.05.010(26) + +> "'State average weekly wage' means the most recent average weekly wage calculated under RCW 50.04.355 and available on January 1st of each year." + +Note: This is the official calculation done by ESD annually; values are fixed for PolicyEngine. + +### 2.5 Typical Workweek Hours — RCW 50A.05.010(28) + +> "(a) For an hourly employee, the average number of hours worked per week by an employee within the qualifying period; and +> (b) Forty hours for a salaried employee, regardless of the number of hours the salaried employee typically works." + +**Key implementation note**: For salaried employees, hard value = 40 hours regardless of actual hours. + +--- + +## 3. Weekly Benefit Formula — RCW 50A.15.020(5) + +### Exact Statutory Language + +Both current and 2026-effective versions contain identical formula language (percentages unchanged between versions): + +> "(5) The weekly benefit for family and medical leave shall be determined as follows: If the employee's average weekly wage is: +> (a) Equal to or less than one-half of the state average weekly wage, then the benefit amount is equal to 90 percent of the employee's average weekly wage; or +> (b) greater than one-half of the state average weekly wage, then the benefit amount is the sum of: +> (i) Ninety percent of one-half of the state average weekly wage; and +> (ii) 50 percent of the difference of the employee's average weekly wage and one-half of the state average weekly wage." + +### Formula (Mathematical) + +Let: +- `AWW` = employee's average weekly wage +- `SAWW` = state average weekly wage +- `H` = 0.5 × SAWW (half the state average weekly wage; the breakpoint) + +**Uncapped, unfloored benefit:** +``` +if AWW <= H: + benefit = 0.90 × AWW +else: + benefit = 0.90 × H + 0.50 × (AWW - H) +``` + +Then apply ceiling and floor (see next sections). + +### Minimum and Maximum — RCW 50A.15.020(6) + +**Maximum weekly benefit (RCW 50A.15.020(6)(a)):** +> "The maximum weekly benefit for family and medical leave that occurs on or after January 1, 2020, shall be $1,000. By September 30, 2020, and by each subsequent September 30th, the commissioner shall adjust the maximum weekly benefit amount to 90 percent of the state average weekly wage. The adjusted maximum weekly benefit amount takes effect on the following January 1st." + +So `max_weekly_benefit = 0.90 × SAWW` (rounded; value is set by commissioner and takes effect January 1 each year). + +**Minimum weekly benefit (RCW 50A.15.020(6)(b)):** +> "The minimum weekly benefit shall not be less than $100 per week except that if the employee's average weekly wage at the time of family or medical leave is less than $100 per week, the weekly benefit shall be the employee's full wage." + +### Rounding — RCW 50A.15.020(2)(a) + +> "The benefits in this section, if not a multiple of one dollar, shall be reduced to the next lower multiple of one dollar." + +Apply `floor()` to the final benefit amount (before comparing to min/max). + +### Full Pseudocode + +``` +def weekly_benefit(AWW, SAWW): + H = 0.5 * SAWW + if AWW <= H: + raw = 0.90 * AWW + else: + raw = 0.90 * H + 0.50 * (AWW - H) + raw = floor(raw) # to next lower dollar (RCW 50A.15.020(2)(a)) + max_wb = 0.90 * SAWW # published annually by commissioner + # Apply min/max floor/ceiling: + if AWW < 100: # special case: if AWW < $100, benefit = full AWW + return AWW + return max(100, min(raw, max_wb)) +``` + +### Prorating — RCW 50A.15.020(2) + +> "The weekly benefit shall be prorated by the percentage of hours on leave compared to the number of hours provided as the typical workweek hours as defined in RCW 50A.05.010." + +For implementation at the weekly level (full-week leave), proration is 1.0. Partial-week proration may be out of scope for the simplified implementation. + +### Example Calculations (2026 values) + +With **SAWW = $1,830** (2026), `H = $915`: + +| AWW | Tier | Formula | Result | After min/max | +|-----|------|---------|--------|---------------| +| $500 | Low | 0.90 × $500 | $450 | $450 | +| $915 | At threshold | 0.90 × $915 | $823 (floor of 823.50) | $823 | +| $1,200 | High | 0.90 × $915 + 0.50 × ($1,200 − $915) = $823.50 + $142.50 | $966 (floor of 966) | $966 | +| $1,500 | High | $823.50 + 0.50 × $585 = $823.50 + $292.50 | $1,116 | $1,116 | +| $2,562 | High | $823.50 + 0.50 × ($2,562 − $915) = $823.50 + $823.50 | $1,647 | $1,647 (at cap) | +| $3,000 | High | $823.50 + 0.50 × $2,085 = $823.50 + $1,042.50 | $1,866 (floor) | **$1,647** (capped) | +| $80 | Very low (AWW < $100) | AWW | $80 | $80 (full wage, not the $100 floor) | + +--- + +## 4. Duration Limits — RCW 50A.15.020(3) + +Exact statutory text: +> "(3)(a) The maximum duration of paid family leave may not exceed 12 times the typical workweek hours during a period of 52 consecutive calendar weeks. +> (b) The maximum duration of paid medical leave may not exceed 12 times the typical workweek hours during a period of 52 consecutive calendar weeks. This leave may be extended an additional two times the typical workweek hours if the employee experiences a serious health condition with a pregnancy that results in incapacity. +> (c) An employee is not entitled to paid family and medical leave benefits under this title that exceeds a combined total of 16 times the typical workweek hours. The combined total of family and medical leave may be extended to 18 times the typical workweek hours if the employee experiences a serious health condition with a pregnancy that results in incapacity." + +### Summary Table (durations measured in "typical workweek hours") + +| Leave Type | Standard Maximum | Pregnancy-Extension Maximum | +|------------|-----------------:|----------------------------:| +| Family leave only | 12× typical workweek hours | 12× (no pregnancy extension for family leave alone) | +| Medical leave only | 12× typical workweek hours | 14× typical workweek hours | +| Combined family + medical | 16× typical workweek hours | 18× typical workweek hours | + +**In practical weekly terms** (for full-time workers with a 40-hour typical workweek): +- Family leave: up to 12 weeks +- Medical leave: up to 12 weeks (14 weeks with pregnancy-related incapacity) +- Combined: up to 16 weeks (18 weeks with pregnancy-related incapacity) + +Measurement period: 52 consecutive calendar weeks. + +--- + +## 5. Waiting Period — RCW 50A.15.020(1)(a) + +Exact text: +> "Following a waiting period consisting of the first seven consecutive calendar days, benefits are payable when family or medical leave is required. However, no waiting period is required for leave for the birth or placement of a child, or for leave because of any qualifying exigency as defined under RCW 50A.05.010(10)(c)." + +**Waived for**: birth or placement of a child, qualifying military exigency. Not waived for medical leave or care-for-family-member leave. + +--- + +## 6. Minimum Claim Duration — RCW 50A.15.020(2)(c) + +- **Until January 1, 2026**: "The minimum claim duration payment is for **eight consecutive hours** of leave." +- **Effective January 1, 2026** (per 2025 c 304 / ESSHB 1213): "The minimum claim duration payment is for **four consecutive hours** of leave." + +--- + +## 7. Qualifying Events (from RCW 50A.05.010 definitions) + +Leave is available for a **qualifying event**, which falls under either family leave or medical leave: + +### Family Leave (RCW 50A.05.010(9)) +- Care for a family member with a serious health condition +- Bonding with a new child (birth, adoption, or foster placement) during the first 12 months +- Qualifying military exigency (as defined under federal FMLA — 29 U.S.C. § 2612(a)(1)(E) as of Oct 19, 2017) + +### Medical Leave (RCW 50A.05.010(13)) +- Employee's own serious health condition (including pregnancy-related incapacity) + +### Family Member — RCW 50A.05.010(8) +Includes: child, grandchild, grandparent, parent, sibling, spouse, **plus** any individual who regularly resides in the employee's home and depends on the employee for care. + +### Serious Health Condition — RCW 50A.05.010(23) +Illness, injury, impairment, or physical/mental condition involving: +- Inpatient care; or +- Continuing treatment by a health care provider + +--- + +## 8. Time-Series Values (for parameters) + +### 8.1 Maximum Weekly Benefit (published annually by commissioner) + +| Effective Date | Max Weekly Benefit | Source | +|---------------:|-------------------:|--------| +| 2020-01-01 | $1,000 | RCW 50A.15.020(6)(a) (statutory initial value) | +| 2021-01-01 | $1,206 | Historical published value | +| 2022-01-01 | $1,327 | Historical published value | +| 2023-01-01 | $1,427 | Historical published value | +| 2024-01-01 | $1,456 | Historical published value | +| 2025-01-01 | $1,542 | ESD 2025 announcement | +| 2026-01-01 | $1,647 | ESD 2026 paycheck insert | + +**Derived relationship**: max = 0.90 × SAWW (applied by commissioner each September for following January). + +**Source for 2026 value**: https://paidleave.wa.gov/app/uploads/2025/12/Paycheck-insert-2026-1.pdf + +### 8.2 State Average Weekly Wage (SAWW) used in formula + +The SAWW used in the formula for a given claim year is the SAWW effective January 1 of that year. (Derived from max = 0.90 × SAWW, and confirmed by ESD announcements.) + +| Effective Date | SAWW | Notes | +|---------------:|-----:|-------| +| 2020-01-01 | ~$1,111 | Implied from $1,000 max ÷ 0.9 | +| 2021-01-01 | ~$1,340 | Implied | +| 2022-01-01 | ~$1,474 | Implied | +| 2023-01-01 | ~$1,586 | Implied | +| 2024-01-01 | ~$1,618 | Announced as WA 2022 avg wage; applied 2024 | +| 2025-01-01 | ~$1,714 | Announced as WA 2023 avg wage; applied 2025 | +| 2026-01-01 | $1,830 | Confirmed by ESD; max = 0.90 × $1,830 = $1,647 | + +**Important**: For the purposes of this implementation, the benefit formula needs both **SAWW** (to define the breakpoint `H = 0.5 × SAWW`) and the **max weekly benefit** (which is itself 0.90 × SAWW). So a single `saww` parameter is sufficient; the max can be computed as `0.90 × saww`, OR store both parameters and derive nothing. + +**Recommendation**: Store SAWW as the primary parameter and derive `max = 0.90 × SAWW` in code. This matches how ESD actually operates. + +### 8.3 Minimum Weekly Benefit + +| Effective Date | Min Weekly Benefit | Source | +|---------------:|-------------------:|--------| +| 2020-01-01 | $100 | RCW 50A.15.020(6)(b) — flat $100 from program start | + +Never changed in statute. Special case: if AWW < $100, the benefit = AWW (employee's "full wage"), not the $100 minimum. + +### 8.4 Benefit Formula Percentages (constant since inception) + +| Parameter | Value | Source | +|-----------|------:|--------| +| Low-tier replacement rate | 0.90 (90%) | RCW 50A.15.020(5)(a) | +| High-tier base component | 0.90 of 0.5 × SAWW | RCW 50A.15.020(5)(b)(i) | +| High-tier marginal rate | 0.50 (50%) | RCW 50A.15.020(5)(b)(ii) | +| SAWW breakpoint fraction | 0.50 (1/2 of SAWW) | RCW 50A.15.020(5)(a)(b) | + +### 8.5 Duration Parameters (constant) + +| Parameter | Value | Source | +|-----------|------:|--------| +| Family leave max (× typical workweek hours) | 12 | RCW 50A.15.020(3)(a) | +| Medical leave max (× typical workweek hours) | 12 | RCW 50A.15.020(3)(b) | +| Medical leave max with pregnancy extension | 14 | RCW 50A.15.020(3)(b) | +| Combined max (× typical workweek hours) | 16 | RCW 50A.15.020(3)(c) | +| Combined max with pregnancy extension | 18 | RCW 50A.15.020(3)(c) | +| Measurement period (weeks) | 52 | RCW 50A.15.020(3)(a)(b) | +| Waiting period (days) | 7 | RCW 50A.15.020(1)(a) | + +### 8.6 Eligibility Hours Threshold + +| Parameter | Value | Source | +|-----------|------:|--------| +| Hours in qualifying period | 820 | RCW 50A.15.010 | + +### 8.7 Minimum Claim Duration + +| Effective Date | Value (hours) | Source | +|---------------:|--------------:|--------| +| 2020-01-01 | 8 | RCW 50A.15.020(2)(c) (pre-2026) | +| 2026-01-01 | 4 | RCW 50A.15.020(2)(c) as amended by 2025 c 304 | + +### 8.8 Typical Workweek Hours (salaried) + +| Parameter | Value (hours) | Source | +|-----------|--------------:|--------| +| Hours for salaried employee | 40 | RCW 50A.05.010(28)(b) | + +--- + +## 9. Identifying Derived Values + +### Maximum weekly benefit = 90% of SAWW + +**Legal citation**: RCW 50A.15.020(6)(a) +**Quote**: "By September 30, 2020, and by each subsequent September 30th, the commissioner shall adjust the maximum weekly benefit amount to 90 percent of the state average weekly wage." + +**Implementation implication**: Store SAWW and compute `max = 0.90 * SAWW` in the variable formula. This guarantees the relationship is preserved as SAWW updates. Alternatively, since ESD publishes a specific rounded dollar amount, store both separately. + +**Decision for implementation**: Store **both** SAWW and the published max weekly benefit (as the commissioner's published value may differ slightly due to rounding conventions). Cross-check: `0.9 × 1830 = 1647.00` — exact match, confirms no rounding divergence. + +### Breakpoint = 50% of SAWW + +**Legal citation**: RCW 50A.15.020(5)(a)(b) +**Quote**: "Equal to or less than one-half of the state average weekly wage" / "greater than one-half of the state average weekly wage" + +**Implementation implication**: Compute `H = 0.5 * SAWW` in the variable formula. No separate parameter needed — the fraction is statutorily fixed. + +--- + +## 10. Special Cases and Exceptions + +### 10.1 Low-wage floor exception +- If `AWW < $100/week`, the benefit = `AWW` (not $100 minimum). +- Source: RCW 50A.15.020(6)(b): "if the employee's average weekly wage at the time of family or medical leave is less than one hundred dollars per week, the weekly benefit shall be the employee's full wage." + +### 10.2 Waiting period waivers +- Waived for: birth/placement of a child, qualifying military exigency. +- Not waived for: medical leave (own serious health condition), family leave to care for a family member. +- Source: RCW 50A.15.020(1)(a). + +### 10.3 Rounding rules +- Benefit amount: rounded down to next lower dollar. Source: RCW 50A.15.020(2)(a). +- AWW itself: rounded down to next lower dollar. Source: RCW 50A.05.010(6). +- Hours on leave: rounded down to next lower hour. Source: RCW 50A.15.020(2)(b). + +### 10.4 Non-eligible worker categories +- Federal government employees +- Self-employed individuals (unless opted in via elective coverage — RCW 50A.10.010) +- Employees of tribally-owned businesses on tribal land (unless tribe opts in) + +### 10.5 Prorating for partial-week leave +- Weekly benefit prorated by `(hours on leave) / (typical workweek hours)`. +- Source: RCW 50A.15.020(2). +- **Implementation note**: A simplified annual/weekly implementation can assume full-week leave (proration factor = 1). + +--- + +## 11. Contribution (Premium) Side — Already Implemented + +The contribution side is already present in the codebase. Documenting here for completeness/context only; no changes needed unless values need updating. + +### Current parameters in `policyengine_us/parameters/gov/states/wa/tax/payroll/paid_leave/`: + +**total_rate.yaml** (premium rate — paid by employee + employer combined, as % of wages): +| Effective | Rate | Source | +|-----------|-----:|--------| +| 2025-01-01 | 0.92% | 2025 ESD announcement | +| 2026-01-01 | 1.13% | 2026 ESD paycheck insert | + +**employer_share.yaml** (employer share of total premium): +| Effective | Rate | Source | +|-----------|-----:|--------| +| 2025-01-01 | 28.48% | 2025 ESD announcement | +| 2026-01-01 | 28.57% | 2026 ESD paycheck insert | + +**employer_headcount_threshold.yaml**: 50 (employers with fewer than 50 employees are exempt from the employer share but still collect the employee share) +- Source: RCW 50A.10.030 + +**Taxable wages cap**: Social Security wage base ($184,500 for 2026) +- Source: RCW 50A.10.030; aligns with federal SS wage base. + +--- + +## 12. Implementation Approach for PolicyEngine + +### 12.1 Variables Needed (benefit side — NEW) + +**Design decision**: Since PFML is a wage-replacement benefit that depends on past earnings (during qualifying period) and a leave event, the cleanest implementation models the **maximum potential annual benefit** if the worker took the full allowed leave. This is analogous to how unemployment insurance benefits are modeled in PolicyEngine. + +A more modest implementation: given a user-supplied **leave weeks** input variable, compute the benefit. + +Required variables (recommended set, Person entity, YEAR period, `defined_for = StateCode.WA`): + +1. `wa_pfml_average_weekly_wage` — employee's AWW per RCW 50A.05.010(6). Simplified: `employment_income / 52`. (Note: regulatory definition is more complex; a simplification is acceptable.) +2. `wa_pfml_eligible` — boolean: did employee work 820+ hours in qualifying period? +3. `wa_pfml_weekly_benefit_uncapped` — computes the two-tier formula on AWW without min/max. +4. `wa_pfml_weekly_benefit` — applies floor/ceiling and special low-wage case. +5. `wa_pfml_weeks_of_leave` — user input (default 0): weeks of paid leave taken. +6. `wa_pfml_leave_type` — enum input (default = NONE): FAMILY / MEDICAL / COMBINED / MEDICAL_PREGNANCY / COMBINED_PREGNANCY. +7. `wa_pfml_max_weeks` — based on leave type, returns 12/14/16/18 per leave type. +8. `wa_pfml` — Person-level annual benefit = weekly_benefit × min(weeks_of_leave, max_weeks). + +### 12.2 Parameters Needed (benefit side — NEW) + +Organize under `policyengine_us/parameters/gov/states/wa/esd/pfml/` (Employment Security Department / PFML): + +``` +gov/states/wa/esd/pfml/ +├── eligibility/ +│ └── hours_threshold.yaml # 820 hours +├── benefit/ +│ ├── saww.yaml # SAWW annual values +│ ├── max_weekly_benefit.yaml # Max = 0.9 × SAWW +│ ├── min_weekly_benefit.yaml # $100 +│ ├── low_tier_rate.yaml # 0.90 +│ ├── high_tier_marginal_rate.yaml # 0.50 +│ └── breakpoint_share.yaml # 0.50 of SAWW +└── duration/ + ├── family_leave_weeks.yaml # 12 + ├── medical_leave_weeks.yaml # 12 + ├── medical_leave_weeks_pregnancy.yaml # 14 + ├── combined_weeks.yaml # 16 + └── combined_weeks_pregnancy.yaml # 18 +``` + +Alternative (cleaner): use a single `duration/by_type.yaml` breakdown by leave-type enum, rather than separate files. + +### 12.3 Reference Implementation Note + +No existing state in policyengine-us implements the **benefit** side of a PFML program — only contributions (DC, MA, NY, CT, DE, ME, OR, NJ, WA). So this implementation does not have a direct state analog to follow; model after how other wage-replacement benefits are implemented (e.g., unemployment compensation). + +Suggested analogs to study: +- Unemployment compensation variables (federal and state level) +- `ca_sdi` (California State Disability Insurance) if it exists +- `ny_paid_family_leave` benefit variables if they exist + +--- + +## 13. References for Metadata + +### For Parameters (YAML format) + +**Primary eligibility (820 hours):** +```yaml +reference: + - title: RCW 50A.15.010 Employee eligibility + href: https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.010 +``` + +**Weekly benefit formula & amounts:** +```yaml +reference: + - title: RCW 50A.15.020 Benefit—Amount and duration (Effective January 1, 2026) + href: https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020 + - title: Washington Paid Family and Medical Leave 2026 Paycheck Insert + href: https://paidleave.wa.gov/app/uploads/2025/12/Paycheck-insert-2026-1.pdf +``` + +**Duration limits:** +```yaml +reference: + - title: RCW 50A.15.020(3) Benefit—Amount and duration + href: https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020 +``` + +**AWW definition:** +```yaml +reference: + - title: RCW 50A.05.010(6) Employee's average weekly wage + href: https://app.leg.wa.gov/rcw/default.aspx?cite=50A.05.010 +``` + +**SAWW definition:** +```yaml +reference: + - title: RCW 50A.05.010(26) State average weekly wage + href: https://app.leg.wa.gov/rcw/default.aspx?cite=50A.05.010 +``` + +**Qualifying period:** +```yaml +reference: + - title: RCW 50A.05.010(21) Qualifying period + href: https://app.leg.wa.gov/rcw/default.aspx?cite=50A.05.010 +``` + +### For Variables (Python format) + +```python +reference = ( + "https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020", + "https://app.leg.wa.gov/rcw/default.aspx?cite=50A.05.010", + "https://paidleave.wa.gov/app/uploads/2025/12/Paycheck-insert-2026-1.pdf", +) +``` + +--- + +## 14. Quality Gate Checklist + +- [x] Benefit calculation formula — RCW 50A.15.020(5) with exact statutory text +- [x] Eligibility thresholds — 820 hours in qualifying period (RCW 50A.15.010) +- [x] Maximum weekly benefit amounts — values for 2020–2026 documented +- [x] Minimum weekly benefit — $100 (with low-wage exception) from RCW 50A.15.020(6)(b) +- [x] Duration limits — family (12x), medical (12x or 14x), combined (16x or 18x) from RCW 50A.15.020(3) +- [x] Waiting period — 7 days, with exceptions for birth/placement/military (RCW 50A.15.020(1)(a)) +- [x] Qualifying events — family leave and medical leave definitions (RCW 50A.05.010) +- [x] Authoritative sources — RCW Title 50A, WAC Title 192, ESD official PDF +- [x] Official program name — Washington Paid Family and Medical Leave (WA PFML) +- [x] Legal citations for percentages — confirmed 90%/50%/50% all in RCW 50A.15.020(5) +- [x] Legal citation for max = 90% SAWW — RCW 50A.15.020(6)(a) + +--- + +## 15. Additional Notes for Implementers + +### 15.1 Simplification Guidance + +Given the complexity of the actual program (quarterly wage analysis, leave event types, prorating, waiting periods), PolicyEngine's implementation should focus on what can be modeled from available household variables: + +**Reasonable simplifications:** +- Use annual `employment_income / 52` as a proxy for AWW (exact quarterly calculation requires quarterly wage data not available in PolicyEngine) +- Use hours-worked proxy (e.g., `max_(employment_income, 0) > 0`) or assume eligibility for any worker with positive earnings as a baseline, then refine +- Model at the **Person** entity level (benefits are individual) with YEAR period +- Default leave weeks = 0 (user input activates the benefit) + +### 15.2 Contribution Side Integration + +The existing `wa_employee_paid_leave_contribution` and `wa_employer_paid_leave_contribution` variables should remain as-is. The benefit (new) is a **separate concept** — most people pay in but never collect; the benefit is triggered by a specific leave event. + +### 15.3 Out-of-Scope Items + +The following are documented in the statute but should likely be OUT of a simplified PolicyEngine implementation: +- Voluntary/employer-sponsored equivalent plans (RCW 50A.30) +- Supplemental employer benefit payments (WAC 192-620-030) +- Child support deductions from benefits (WAC 192-620-045) +- Overpayment recovery (RCW 50A.45) +- Appeals procedures (RCW 50A.50) +- Waiting period mechanics within a claim year +- Conditional benefit payments during eligibility disputes + +### 15.4 Values Are Annual / Calendar-Year + +Per RCW 50A.15.020(6)(a), the max weekly benefit "takes effect on the following January 1st." The SAWW "available on January 1st of each year" per RCW 50A.05.010(26). So all parameter effective dates should be `YYYY-01-01`. + +--- From 925d0b31859e781e0d2d81193cb13ab9447fd14b Mon Sep 17 00:00:00 2001 From: Daphne Hansell <128793799+daphnehanse11@users.noreply.github.com> Date: Thu, 23 Apr 2026 13:08:40 -0400 Subject: [PATCH 3/6] Fix WA PFML rounding and duration caps --- ...d_max_weeks_with_pregnancy_incapacity.yaml | 12 +++ ...leave_weeks_with_pregnancy_incapacity.yaml | 12 +++ .../gov/states/wa/pfml/test_wa_pfml.yaml | 85 +++++++++++++++++++ .../test_wa_pfml_weekly_benefit_amount.yaml | 23 +++-- .../variables/gov/states/wa/pfml/wa_pfml.py | 33 ++++++- .../wa/pfml/wa_pfml_average_weekly_wage.py | 5 +- .../gov/states/wa/pfml/wa_pfml_leave_type.py | 21 +++++ .../gov/states/wa/pfml/wa_pfml_leave_weeks.py | 11 +++ .../wa/pfml/wa_pfml_weekly_benefit_amount.py | 9 +- 9 files changed, 195 insertions(+), 16 deletions(-) create mode 100644 policyengine_us/parameters/gov/states/wa/pfml/duration/combined_max_weeks_with_pregnancy_incapacity.yaml create mode 100644 policyengine_us/parameters/gov/states/wa/pfml/duration/medical_leave_weeks_with_pregnancy_incapacity.yaml create mode 100644 policyengine_us/variables/gov/states/wa/pfml/wa_pfml_leave_type.py create mode 100644 policyengine_us/variables/gov/states/wa/pfml/wa_pfml_leave_weeks.py diff --git a/policyengine_us/parameters/gov/states/wa/pfml/duration/combined_max_weeks_with_pregnancy_incapacity.yaml b/policyengine_us/parameters/gov/states/wa/pfml/duration/combined_max_weeks_with_pregnancy_incapacity.yaml new file mode 100644 index 00000000000..775f8858b3b --- /dev/null +++ b/policyengine_us/parameters/gov/states/wa/pfml/duration/combined_max_weeks_with_pregnancy_incapacity.yaml @@ -0,0 +1,12 @@ +description: Washington limits combined family and medical leave to this number of weeks when a serious health condition with pregnancy results in incapacity under the Paid Family and Medical Leave program. + +values: + 2020-01-01: 18 + +metadata: + unit: week + period: year + label: Washington PFML combined leave maximum weeks with pregnancy incapacity + reference: + - title: RCW 50A.15.020(3)(c) Benefit—Amount and duration + href: https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020 diff --git a/policyengine_us/parameters/gov/states/wa/pfml/duration/medical_leave_weeks_with_pregnancy_incapacity.yaml b/policyengine_us/parameters/gov/states/wa/pfml/duration/medical_leave_weeks_with_pregnancy_incapacity.yaml new file mode 100644 index 00000000000..84e76298b05 --- /dev/null +++ b/policyengine_us/parameters/gov/states/wa/pfml/duration/medical_leave_weeks_with_pregnancy_incapacity.yaml @@ -0,0 +1,12 @@ +description: Washington limits medical leave to this number of weeks when a serious health condition with pregnancy results in incapacity under the Paid Family and Medical Leave program. + +values: + 2020-01-01: 14 + +metadata: + unit: week + period: year + label: Washington PFML medical leave maximum weeks with pregnancy incapacity + reference: + - title: RCW 50A.15.020(3)(b) Benefit—Amount and duration + href: https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020 diff --git a/policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml.yaml b/policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml.yaml index c6119ccf5b7..9ae4e573612 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml.yaml @@ -5,6 +5,8 @@ person1: weekly_hours_worked: 20 employment_income: 52_000 + wa_pfml_leave_weeks: 16 + wa_pfml_leave_type: COMBINED households: household: members: [person1] @@ -23,3 +25,86 @@ # Combined family + medical leave max = 16 weeks per RCW 50A.15.020(3)(c). # Annual benefit = 866 * 16 = 13,856 wa_pfml: 13_856 + +- name: Case 2, eligible Washington worker with no leave claim receives no annual benefit. + period: 2026 + input: + people: + person1: + weekly_hours_worked: 20 + employment_income: 52_000 + households: + household: + members: [person1] + state_code: WA + output: + wa_pfml_eligible: true + wa_pfml: 0 + +- name: Case 3, leave weeks above the statutory cap are limited to the combined maximum. + period: 2026 + input: + people: + person1: + weekly_hours_worked: 20 + employment_income: 52_000 + wa_pfml_leave_weeks: 16 + wa_pfml_leave_type: FAMILY + households: + household: + members: [person1] + state_code: WA + output: + # Family leave is capped at 12 weeks under RCW 50A.15.020(3)(a). + wa_pfml: 10_392 + +- name: Case 4, medical leave without pregnancy incapacity is limited to 12 weeks. + period: 2026 + input: + people: + person1: + weekly_hours_worked: 20 + employment_income: 52_000 + wa_pfml_leave_weeks: 16 + wa_pfml_leave_type: MEDICAL + households: + household: + members: [person1] + state_code: WA + output: + # Medical leave is capped at 12 weeks under RCW 50A.15.020(3)(b). + wa_pfml: 10_392 + +- name: Case 5, pregnancy-related medical leave uses the 14 week cap. + period: 2026 + input: + people: + person1: + weekly_hours_worked: 20 + employment_income: 52_000 + wa_pfml_leave_weeks: 16 + wa_pfml_leave_type: MEDICAL_WITH_PREGNANCY_INCAPACITY + households: + household: + members: [person1] + state_code: WA + output: + # Pregnancy-related medical leave is capped at 14 weeks. + wa_pfml: 12_124 + +- name: Case 6, combined leave with pregnancy incapacity uses the 18 week cap. + period: 2026 + input: + people: + person1: + weekly_hours_worked: 20 + employment_income: 52_000 + wa_pfml_leave_weeks: 20 + wa_pfml_leave_type: COMBINED_WITH_PREGNANCY_INCAPACITY + households: + household: + members: [person1] + state_code: WA + output: + # Combined leave with pregnancy incapacity is capped at 18 weeks. + wa_pfml: 15_588 diff --git a/policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml_weekly_benefit_amount.yaml b/policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml_weekly_benefit_amount.yaml index 095ebf2e0ff..d061b2d3570 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml_weekly_benefit_amount.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml_weekly_benefit_amount.yaml @@ -16,8 +16,8 @@ employment_income: 47_580 output: # AWW = 47,580 / 52 = 915 - # AWW (915) <= H (915), so benefit = 0.90 * 915 = 823.50 - wa_pfml_weekly_benefit_amount: 823.50 + # AWW (915) <= H (915), so benefit = 0.90 * 915 = 823.50, rounded down to 823 + wa_pfml_weekly_benefit_amount: 823 - name: Case 3, AWW above the SAWW breakpoint uses two-tier formula. period: 2026 @@ -76,8 +76,8 @@ employment_income: 47_528 output: # AWW = 47,528 / 52 = 914 - # AWW (914) <= H (915), so benefit = 0.90 * 914 = 822.60 - wa_pfml_weekly_benefit_amount: 822.60 + # AWW (914) <= H (915), so benefit = 0.90 * 914 = 822.60, rounded down to 822 + wa_pfml_weekly_benefit_amount: 822 - name: Case 8, AWW one dollar above the SAWW breakpoint. period: 2026 @@ -88,8 +88,8 @@ # AWW = 47,632 / 52 = 916 # AWW (916) > H (915), so benefit = 0.90 * 915 + 0.50 * (916 - 915) # = 823.50 + 0.50 - # = 824.00 - wa_pfml_weekly_benefit_amount: 824.00 + # = 824.00, rounded down to 824 + wa_pfml_weekly_benefit_amount: 824 - name: Case 9, AWW exactly at the maximum weekly benefit threshold. period: 2026 @@ -104,3 +104,14 @@ # = 1,647 # Equal to max weekly benefit (0.90 * 1,830 = 1,647), so benefit = 1,647 wa_pfml_weekly_benefit_amount: 1_647 + +- name: Case 10, non-integer AWW is rounded down before applying the benefit formula. + period: 2026 + input: + state_code: WA + employment_income: 47_579 + output: + # Raw AWW approximation = 47,579 / 52 = 914.98... + # RCW 50A.05.010(6) rounds AWW down to the next lower dollar, so AWW = 914. + # Benefit = 0.90 * 914 = 822.60, rounded down to 822. + wa_pfml_weekly_benefit_amount: 822 diff --git a/policyengine_us/variables/gov/states/wa/pfml/wa_pfml.py b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml.py index 7f81989596c..a18b4f160fe 100644 --- a/policyengine_us/variables/gov/states/wa/pfml/wa_pfml.py +++ b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml.py @@ -8,9 +8,8 @@ class wa_pfml(Variable): documentation = ( "Annual Washington Paid Family and Medical Leave benefit. " "Computed as the weekly benefit amount multiplied by the " - "combined maximum leave duration in weeks, for eligible " - "workers. Represents the maximum potential annual benefit " - "if the full allowed combined leave is taken." + "claimed leave weeks, capped at the maximum duration for the " + "selected leave type." ) unit = USD definition_period = YEAR @@ -23,4 +22,30 @@ class wa_pfml(Variable): def formula(person, period, parameters): p = parameters(period).gov.states.wa.pfml weekly_benefit = person("wa_pfml_weekly_benefit_amount", period) - return weekly_benefit * p.duration.combined_max_weeks + leave_type = person("wa_pfml_leave_type", period) + leave_type_values = leave_type.possible_values + max_leave_weeks = select( + [ + leave_type == leave_type_values.FAMILY, + leave_type == leave_type_values.MEDICAL, + leave_type == leave_type_values.COMBINED, + leave_type + == leave_type_values.MEDICAL_WITH_PREGNANCY_INCAPACITY, + leave_type + == leave_type_values.COMBINED_WITH_PREGNANCY_INCAPACITY, + ], + [ + p.duration.family_leave_weeks, + p.duration.medical_leave_weeks, + p.duration.combined_max_weeks, + p.duration.medical_leave_weeks_with_pregnancy_incapacity, + p.duration.combined_max_weeks_with_pregnancy_incapacity, + ], + default=0, + ) + leave_weeks = clip( + person("wa_pfml_leave_weeks", period), + 0, + max_leave_weeks, + ) + return weekly_benefit * leave_weeks diff --git a/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_average_weekly_wage.py b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_average_weekly_wage.py index 1cae55f504d..228273b10b9 100644 --- a/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_average_weekly_wage.py +++ b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_average_weekly_wage.py @@ -8,7 +8,8 @@ class wa_pfml_average_weekly_wage(Variable): documentation = ( "Employee's average weekly wage for Washington Paid Family and " "Medical Leave. Simplified as annual employment income divided by " - "the number of weeks in a year." + "the number of weeks in a year and rounded down to the next lower " + "dollar." ) unit = USD definition_period = YEAR @@ -19,4 +20,4 @@ class wa_pfml_average_weekly_wage(Variable): ) def formula(person, period, parameters): - return person("employment_income", period) / WEEKS_IN_YEAR + return np.floor(person("employment_income", period) / WEEKS_IN_YEAR) diff --git a/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_leave_type.py b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_leave_type.py new file mode 100644 index 00000000000..ac4ae7f412c --- /dev/null +++ b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_leave_type.py @@ -0,0 +1,21 @@ +from policyengine_us.model_api import * + + +class WAPFMLLeaveType(Enum): + FAMILY = "Family" + MEDICAL = "Medical" + COMBINED = "Combined" + MEDICAL_WITH_PREGNANCY_INCAPACITY = "Medical with pregnancy incapacity" + COMBINED_WITH_PREGNANCY_INCAPACITY = "Combined with pregnancy incapacity" + NONE = "None" + + +class wa_pfml_leave_type(Variable): + value_type = Enum + entity = Person + label = "Washington PFML leave type" + definition_period = YEAR + possible_values = WAPFMLLeaveType + default_value = WAPFMLLeaveType.NONE + defined_for = StateCode.WA + reference = "https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020" diff --git a/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_leave_weeks.py b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_leave_weeks.py new file mode 100644 index 00000000000..baac8329428 --- /dev/null +++ b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_leave_weeks.py @@ -0,0 +1,11 @@ +from policyengine_us.model_api import * + + +class wa_pfml_leave_weeks(Variable): + value_type = float + entity = Person + label = "Washington PFML leave weeks claimed" + definition_period = YEAR + defined_for = StateCode.WA + default_value = 0 + reference = "https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020" diff --git a/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_weekly_benefit_amount.py b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_weekly_benefit_amount.py index 35b69107d92..0d0f77be48b 100644 --- a/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_weekly_benefit_amount.py +++ b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_weekly_benefit_amount.py @@ -8,9 +8,10 @@ class wa_pfml_weekly_benefit_amount(Variable): documentation = ( "Weekly benefit amount under Washington Paid Family and Medical " "Leave. Applies the two-tier replacement formula in " - "RCW 50A.15.020(5) and clips the result to the statutory minimum " - "and maximum weekly benefit amounts. Despite the YEAR definition " - "period, this variable represents a weekly dollar amount." + "RCW 50A.15.020(5), rounds down to the next lower dollar, and clips " + "the result to the statutory minimum and maximum weekly benefit " + "amounts. Despite the YEAR definition period, this variable " + "represents a weekly dollar amount." ) unit = USD definition_period = YEAR @@ -26,7 +27,7 @@ def formula(person, period, parameters): lower_threshold = p.lower_threshold_fraction * p.state_average_weekly_wage lower_benefit = p.lower_benefit_rate * min_(aww, lower_threshold) upper_benefit = p.upper_benefit_rate * max_(aww - lower_threshold, 0) - raw_benefit = lower_benefit + upper_benefit + raw_benefit = np.floor(lower_benefit + upper_benefit) # Per RCW 50A.15.020(6)(b): minimum is $100, or AWW if AWW < $100. # Using min_(min_amount, aww) as the floor naturally handles zero AWW # (no employment → floor=0 → benefit=0) and low AWW (floor=AWW). From e3f59b0fbd49c31d3d27591338efaa5cb804ee0a Mon Sep 17 00:00:00 2001 From: Daphne Hansell <128793799+daphnehanse11@users.noreply.github.com> Date: Thu, 23 Apr 2026 16:14:17 -0400 Subject: [PATCH 4/6] Format WA PFML formula for Ruff --- policyengine_us/variables/gov/states/wa/pfml/wa_pfml.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/policyengine_us/variables/gov/states/wa/pfml/wa_pfml.py b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml.py index a18b4f160fe..c4018a7a537 100644 --- a/policyengine_us/variables/gov/states/wa/pfml/wa_pfml.py +++ b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml.py @@ -29,10 +29,8 @@ def formula(person, period, parameters): leave_type == leave_type_values.FAMILY, leave_type == leave_type_values.MEDICAL, leave_type == leave_type_values.COMBINED, - leave_type - == leave_type_values.MEDICAL_WITH_PREGNANCY_INCAPACITY, - leave_type - == leave_type_values.COMBINED_WITH_PREGNANCY_INCAPACITY, + leave_type == leave_type_values.MEDICAL_WITH_PREGNANCY_INCAPACITY, + leave_type == leave_type_values.COMBINED_WITH_PREGNANCY_INCAPACITY, ], [ p.duration.family_leave_weeks, From c334a0f4ca9c8cdcbb4f4b38a013fcb326953a24 Mon Sep 17 00:00:00 2001 From: Daphne Hansell <128793799+daphnehanse11@users.noreply.github.com> Date: Fri, 24 Apr 2026 13:42:09 -0400 Subject: [PATCH 5/6] Add optional WA PFML accuracy inputs --- .../gov/states/wa/pfml/min_claim_hours.yaml | 13 +++++++ .../gov/states/wa/pfml/test_wa_pfml.yaml | 37 +++++++++++++++++++ .../states/wa/pfml/test_wa_pfml_eligible.yaml | 22 +++++++++++ .../test_wa_pfml_weekly_benefit_amount.yaml | 11 ++++++ .../variables/gov/states/wa/pfml/wa_pfml.py | 24 +++++++++++- .../wa/pfml/wa_pfml_average_weekly_wage.py | 4 +- .../wa_pfml_average_weekly_wage_override.py | 19 ++++++++++ .../gov/states/wa/pfml/wa_pfml_eligible.py | 4 +- .../wa/pfml/wa_pfml_leave_hours_claimed.py | 17 +++++++++ .../wa_pfml_qualifying_period_hours_worked.py | 17 +++++++++ .../wa/pfml/wa_pfml_typical_workweek_hours.py | 16 ++++++++ 11 files changed, 181 insertions(+), 3 deletions(-) create mode 100644 policyengine_us/parameters/gov/states/wa/pfml/min_claim_hours.yaml create mode 100644 policyengine_us/variables/gov/states/wa/pfml/wa_pfml_average_weekly_wage_override.py create mode 100644 policyengine_us/variables/gov/states/wa/pfml/wa_pfml_leave_hours_claimed.py create mode 100644 policyengine_us/variables/gov/states/wa/pfml/wa_pfml_qualifying_period_hours_worked.py create mode 100644 policyengine_us/variables/gov/states/wa/pfml/wa_pfml_typical_workweek_hours.py diff --git a/policyengine_us/parameters/gov/states/wa/pfml/min_claim_hours.yaml b/policyengine_us/parameters/gov/states/wa/pfml/min_claim_hours.yaml new file mode 100644 index 00000000000..9c41a4df45b --- /dev/null +++ b/policyengine_us/parameters/gov/states/wa/pfml/min_claim_hours.yaml @@ -0,0 +1,13 @@ +description: Washington requires at least this many consecutive leave hours for a PFML claim. Before 2026, no minimum claim hours applied. + +values: + 2020-01-01: 0 + 2026-01-01: 4 + +metadata: + unit: hour + period: year + label: Washington PFML minimum claim hours + reference: + - title: RCW 50A.15.020(2) Benefit—Amount and duration + href: https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020 diff --git a/policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml.yaml b/policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml.yaml index 9ae4e573612..dd6a9e5fc86 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml.yaml @@ -108,3 +108,40 @@ output: # Combined leave with pregnancy incapacity is capped at 18 weeks. wa_pfml: 15_588 + +- name: Case 7, leave hours claimed can prorate the benefit using typical workweek hours. + period: 2026 + input: + people: + person1: + weekly_hours_worked: 20 + employment_income: 52_000 + wa_pfml_leave_type: COMBINED + wa_pfml_leave_hours_claimed: 240 + wa_pfml_typical_workweek_hours: 40 + households: + household: + members: [person1] + state_code: WA + output: + # 240 leave hours / 40 typical workweek hours = 6 leave weeks. + # Annual benefit = 866 * 6 = 5,196. + wa_pfml: 5_196 + +- name: Case 8, leave-hour claims below the 2026 minimum claim duration receive no benefit. + period: 2026 + input: + people: + person1: + weekly_hours_worked: 20 + employment_income: 52_000 + wa_pfml_leave_type: COMBINED + wa_pfml_leave_hours_claimed: 3 + wa_pfml_typical_workweek_hours: 40 + households: + household: + members: [person1] + state_code: WA + output: + # RCW 50A.15.020(2) requires at least 4 consecutive leave hours for 2026 claims. + wa_pfml: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml_eligible.yaml index 1eda9887f1d..8a68b7e9219 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml_eligible.yaml @@ -35,3 +35,25 @@ output: # annual_hours = 0 < 820, so ineligible. wa_pfml_eligible: false + +- name: Case 5, qualifying-period hours override can make a worker eligible. + period: 2026 + input: + state_code: WA + weekly_hours_worked: 0 + wa_pfml_qualifying_period_hours_worked: 900 + output: + # Override replaces the weekly-hours proxy for eligibility. + # 900 >= 820 threshold, so eligible. + wa_pfml_eligible: true + +- name: Case 6, qualifying-period hours override takes precedence over weekly-hours proxy. + period: 2026 + input: + state_code: WA + weekly_hours_worked: 20 + wa_pfml_qualifying_period_hours_worked: 800 + output: + # Override replaces the weekly-hours proxy for eligibility. + # 800 < 820 threshold, so ineligible. + wa_pfml_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml_weekly_benefit_amount.yaml b/policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml_weekly_benefit_amount.yaml index d061b2d3570..d3aff64f0e8 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml_weekly_benefit_amount.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml_weekly_benefit_amount.yaml @@ -115,3 +115,14 @@ # RCW 50A.05.010(6) rounds AWW down to the next lower dollar, so AWW = 914. # Benefit = 0.90 * 914 = 822.60, rounded down to 822. wa_pfml_weekly_benefit_amount: 822 + +- name: Case 11, average weekly wage override replaces the annual-income proxy. + period: 2026 + input: + state_code: WA + employment_income: 78_000 + wa_pfml_average_weekly_wage_override: 800.75 + output: + # Override AWW is rounded down to 800 before applying the formula. + # AWW (800) <= H (915), so benefit = 0.90 * 800 = 720. + wa_pfml_weekly_benefit_amount: 720 diff --git a/policyengine_us/variables/gov/states/wa/pfml/wa_pfml.py b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml.py index c4018a7a537..f1f045ed4e2 100644 --- a/policyengine_us/variables/gov/states/wa/pfml/wa_pfml.py +++ b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml.py @@ -41,9 +41,31 @@ def formula(person, period, parameters): ], default=0, ) - leave_weeks = clip( + leave_hours_claimed = np.floor(person("wa_pfml_leave_hours_claimed", period)) + typical_workweek_hours = person("wa_pfml_typical_workweek_hours", period) + leave_hours_meet_minimum = where( + leave_hours_claimed >= p.min_claim_hours, + leave_hours_claimed, + 0, + ) + leave_weeks_from_hours = np.divide( + clip( + leave_hours_meet_minimum, + 0, + max_leave_weeks * typical_workweek_hours, + ), + typical_workweek_hours, + out=np.zeros_like(leave_hours_meet_minimum, dtype=np.float32), + where=typical_workweek_hours > 0, + ) + leave_weeks_from_weeks = clip( person("wa_pfml_leave_weeks", period), 0, max_leave_weeks, ) + leave_weeks = where( + (leave_hours_claimed > 0) & (typical_workweek_hours > 0), + leave_weeks_from_hours, + leave_weeks_from_weeks, + ) return weekly_benefit * leave_weeks diff --git a/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_average_weekly_wage.py b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_average_weekly_wage.py index 228273b10b9..ba99bf46bcb 100644 --- a/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_average_weekly_wage.py +++ b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_average_weekly_wage.py @@ -20,4 +20,6 @@ class wa_pfml_average_weekly_wage(Variable): ) def formula(person, period, parameters): - return np.floor(person("employment_income", period) / WEEKS_IN_YEAR) + override = person("wa_pfml_average_weekly_wage_override", period) + proxy_aww = np.floor(person("employment_income", period) / WEEKS_IN_YEAR) + return where(override >= 0, np.floor(override), proxy_aww) diff --git a/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_average_weekly_wage_override.py b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_average_weekly_wage_override.py new file mode 100644 index 00000000000..52ddc2a0792 --- /dev/null +++ b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_average_weekly_wage_override.py @@ -0,0 +1,19 @@ +from policyengine_us.model_api import * + + +class wa_pfml_average_weekly_wage_override(Variable): + value_type = float + entity = Person + label = "Washington PFML average weekly wage override" + documentation = ( + "Optional override for Washington PFML average weekly wage. Set to a " + "non-negative dollar amount to replace the annual-income proxy." + ) + unit = USD + definition_period = YEAR + defined_for = StateCode.WA + default_value = -1 + reference = ( + "https://app.leg.wa.gov/rcw/default.aspx?cite=50A.05.010", + "https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020", + ) diff --git a/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_eligible.py b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_eligible.py index e5910fcfa9d..36bbd1a5357 100644 --- a/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_eligible.py +++ b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_eligible.py @@ -18,5 +18,7 @@ class wa_pfml_eligible(Variable): def formula(person, period, parameters): p = parameters(period).gov.states.wa.pfml + hours_override = person("wa_pfml_qualifying_period_hours_worked", period) annual_hours = person("weekly_hours_worked", period) * WEEKS_IN_YEAR - return annual_hours >= p.hours_threshold + qualifying_hours = where(hours_override >= 0, hours_override, annual_hours) + return qualifying_hours >= p.hours_threshold diff --git a/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_leave_hours_claimed.py b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_leave_hours_claimed.py new file mode 100644 index 00000000000..c4cb6d094e4 --- /dev/null +++ b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_leave_hours_claimed.py @@ -0,0 +1,17 @@ +from policyengine_us.model_api import * + + +class wa_pfml_leave_hours_claimed(Variable): + value_type = float + entity = Person + label = "Washington PFML leave hours claimed" + documentation = ( + "Optional claimed leave hours for Washington PFML. If positive and " + "paired with typical workweek hours, this takes precedence over " + "leave weeks for annual benefit calculations." + ) + unit = "hour" + definition_period = YEAR + defined_for = StateCode.WA + default_value = 0 + reference = "https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020" diff --git a/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_qualifying_period_hours_worked.py b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_qualifying_period_hours_worked.py new file mode 100644 index 00000000000..e56ea68cca1 --- /dev/null +++ b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_qualifying_period_hours_worked.py @@ -0,0 +1,17 @@ +from policyengine_us.model_api import * + + +class wa_pfml_qualifying_period_hours_worked(Variable): + value_type = float + entity = Person + label = "Washington PFML qualifying-period hours worked override" + documentation = ( + "Optional override for hours worked in the Washington PFML " + "qualifying period. Set to a non-negative number of hours to replace " + "the annualized weekly-hours proxy used for eligibility." + ) + unit = "hour" + definition_period = YEAR + defined_for = StateCode.WA + default_value = -1 + reference = "https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.010" diff --git a/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_typical_workweek_hours.py b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_typical_workweek_hours.py new file mode 100644 index 00000000000..4b89ef2cf0f --- /dev/null +++ b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_typical_workweek_hours.py @@ -0,0 +1,16 @@ +from policyengine_us.model_api import * + + +class wa_pfml_typical_workweek_hours(Variable): + value_type = float + entity = Person + label = "Washington PFML typical workweek hours" + documentation = ( + "Optional typical workweek hours for Washington PFML claim " + "proration. Used only when leave hours claimed are provided." + ) + unit = "hour" + definition_period = YEAR + defined_for = StateCode.WA + default_value = 0 + reference = "https://app.leg.wa.gov/rcw/default.aspx?cite=50A.05.010" From 1212555db8518f6a8c7012a5add8ac723b6e78ce Mon Sep 17 00:00:00 2001 From: Daphne Hansell <128793799+daphnehanse11@users.noreply.github.com> Date: Mon, 27 Apr 2026 11:33:26 -0400 Subject: [PATCH 6/6] Refocus WA PFML on eligibility and max benefit --- changelog.d/issue-8136-wa-pfml.added.md | 2 +- .../household/household_state_benefits.yaml | 4 - .../gov/states/wa/pfml/min_claim_hours.yaml | 13 - .../gov/states/wa/pfml/test_wa_pfml.yaml | 67 +-- .../wa/pfml/test_wa_pfml_max_leave_weeks.yaml | 82 +++ .../variables/gov/states/wa/pfml/wa_pfml.py | 59 +- .../gov/states/wa/pfml/wa_pfml_eligible.py | 5 +- .../wa/pfml/wa_pfml_leave_hours_claimed.py | 17 - .../gov/states/wa/pfml/wa_pfml_leave_type.py | 2 +- .../gov/states/wa/pfml/wa_pfml_leave_weeks.py | 11 - .../states/wa/pfml/wa_pfml_max_leave_weeks.py | 40 ++ .../wa/pfml/wa_pfml_typical_workweek_hours.py | 16 - sources/working_references.md | 566 ------------------ 13 files changed, 150 insertions(+), 734 deletions(-) delete mode 100644 policyengine_us/parameters/gov/states/wa/pfml/min_claim_hours.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml_max_leave_weeks.yaml delete mode 100644 policyengine_us/variables/gov/states/wa/pfml/wa_pfml_leave_hours_claimed.py delete mode 100644 policyengine_us/variables/gov/states/wa/pfml/wa_pfml_leave_weeks.py create mode 100644 policyengine_us/variables/gov/states/wa/pfml/wa_pfml_max_leave_weeks.py delete mode 100644 policyengine_us/variables/gov/states/wa/pfml/wa_pfml_typical_workweek_hours.py delete mode 100644 sources/working_references.md diff --git a/changelog.d/issue-8136-wa-pfml.added.md b/changelog.d/issue-8136-wa-pfml.added.md index e348a09bba4..bee359f9567 100644 --- a/changelog.d/issue-8136-wa-pfml.added.md +++ b/changelog.d/issue-8136-wa-pfml.added.md @@ -1 +1 @@ -Add Washington Paid Family and Medical Leave benefit (wa_pfml). +Add a Washington Paid Family and Medical Leave eligibility and maximum benefit calculator. diff --git a/policyengine_us/parameters/gov/household/household_state_benefits.yaml b/policyengine_us/parameters/gov/household/household_state_benefits.yaml index 36215296240..619bf682302 100644 --- a/policyengine_us/parameters/gov/household/household_state_benefits.yaml +++ b/policyengine_us/parameters/gov/household/household_state_benefits.yaml @@ -55,8 +55,6 @@ values: - ks_sspp # Hawaii benefits - hi_oss - # Washington benefits - - wa_pfml 2024-01-01: # Delaware benefits - de_ssp @@ -114,8 +112,6 @@ values: - ks_sspp # Hawaii benefits - hi_oss - # Washington benefits - - wa_pfml metadata: unit: list period: year diff --git a/policyengine_us/parameters/gov/states/wa/pfml/min_claim_hours.yaml b/policyengine_us/parameters/gov/states/wa/pfml/min_claim_hours.yaml deleted file mode 100644 index 9c41a4df45b..00000000000 --- a/policyengine_us/parameters/gov/states/wa/pfml/min_claim_hours.yaml +++ /dev/null @@ -1,13 +0,0 @@ -description: Washington requires at least this many consecutive leave hours for a PFML claim. Before 2026, no minimum claim hours applied. - -values: - 2020-01-01: 0 - 2026-01-01: 4 - -metadata: - unit: hour - period: year - label: Washington PFML minimum claim hours - reference: - - title: RCW 50A.15.020(2) Benefit—Amount and duration - href: https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020 diff --git a/policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml.yaml b/policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml.yaml index dd6a9e5fc86..09febab4c17 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml.yaml @@ -1,32 +1,22 @@ -- name: Case 1, Washington worker with AWW above breakpoint gets annual benefit for combined max weeks. +- name: Case 1, eligible worker with combined leave facts gets the maximum annual benefit. period: 2026 input: people: person1: weekly_hours_worked: 20 employment_income: 52_000 - wa_pfml_leave_weeks: 16 wa_pfml_leave_type: COMBINED households: household: members: [person1] state_code: WA output: - # SAWW 2026 = 1,830; breakpoint H = 0.5 * 1,830 = 915 - # Max weekly benefit 2026 = 0.90 * 1,830 = 1,647 - # AWW = 52,000 / 52 = 1,000 - # AWW (1,000) > H (915), so weekly benefit = 0.90 * 915 + 0.50 * (1,000 - 915) - # = 823.50 + 0.50 * 85 - # = 823.50 + 42.50 - # = 866 (below the 1,647 cap, above the 100 floor) - wa_pfml_weekly_benefit_amount: 866 - # Eligibility: 20 weekly hours * 52 = 1,040 annual hours >= 820 threshold. wa_pfml_eligible: true - # Combined family + medical leave max = 16 weeks per RCW 50A.15.020(3)(c). - # Annual benefit = 866 * 16 = 13,856 + wa_pfml_weekly_benefit_amount: 866 + wa_pfml_max_leave_weeks: 16 wa_pfml: 13_856 -- name: Case 2, eligible Washington worker with no leave claim receives no annual benefit. +- name: Case 2, no leave type selected produces no maximum benefit estimate. period: 2026 input: people: @@ -39,109 +29,86 @@ state_code: WA output: wa_pfml_eligible: true + wa_pfml_max_leave_weeks: 0 wa_pfml: 0 -- name: Case 3, leave weeks above the statutory cap are limited to the combined maximum. +- name: Case 3, family leave estimate uses the 12 week cap. period: 2026 input: people: person1: weekly_hours_worked: 20 employment_income: 52_000 - wa_pfml_leave_weeks: 16 wa_pfml_leave_type: FAMILY households: household: members: [person1] state_code: WA output: - # Family leave is capped at 12 weeks under RCW 50A.15.020(3)(a). + wa_pfml_max_leave_weeks: 12 wa_pfml: 10_392 -- name: Case 4, medical leave without pregnancy incapacity is limited to 12 weeks. +- name: Case 4, medical leave estimate uses the 12 week cap. period: 2026 input: people: person1: weekly_hours_worked: 20 employment_income: 52_000 - wa_pfml_leave_weeks: 16 wa_pfml_leave_type: MEDICAL households: household: members: [person1] state_code: WA output: - # Medical leave is capped at 12 weeks under RCW 50A.15.020(3)(b). + wa_pfml_max_leave_weeks: 12 wa_pfml: 10_392 -- name: Case 5, pregnancy-related medical leave uses the 14 week cap. +- name: Case 5, pregnancy-related medical leave estimate uses the 14 week cap. period: 2026 input: people: person1: weekly_hours_worked: 20 employment_income: 52_000 - wa_pfml_leave_weeks: 16 wa_pfml_leave_type: MEDICAL_WITH_PREGNANCY_INCAPACITY households: household: members: [person1] state_code: WA output: - # Pregnancy-related medical leave is capped at 14 weeks. + wa_pfml_max_leave_weeks: 14 wa_pfml: 12_124 -- name: Case 6, combined leave with pregnancy incapacity uses the 18 week cap. +- name: Case 6, combined leave with pregnancy incapacity estimate uses the 18 week cap. period: 2026 input: people: person1: weekly_hours_worked: 20 employment_income: 52_000 - wa_pfml_leave_weeks: 20 wa_pfml_leave_type: COMBINED_WITH_PREGNANCY_INCAPACITY households: household: members: [person1] state_code: WA output: - # Combined leave with pregnancy incapacity is capped at 18 weeks. + wa_pfml_max_leave_weeks: 18 wa_pfml: 15_588 -- name: Case 7, leave hours claimed can prorate the benefit using typical workweek hours. - period: 2026 - input: - people: - person1: - weekly_hours_worked: 20 - employment_income: 52_000 - wa_pfml_leave_type: COMBINED - wa_pfml_leave_hours_claimed: 240 - wa_pfml_typical_workweek_hours: 40 - households: - household: - members: [person1] - state_code: WA - output: - # 240 leave hours / 40 typical workweek hours = 6 leave weeks. - # Annual benefit = 866 * 6 = 5,196. - wa_pfml: 5_196 - -- name: Case 8, leave-hour claims below the 2026 minimum claim duration receive no benefit. +- name: Case 7, ineligible workers get no leave or benefit estimate. period: 2026 input: people: person1: - weekly_hours_worked: 20 + weekly_hours_worked: 15 employment_income: 52_000 wa_pfml_leave_type: COMBINED - wa_pfml_leave_hours_claimed: 3 - wa_pfml_typical_workweek_hours: 40 households: household: members: [person1] state_code: WA output: - # RCW 50A.15.020(2) requires at least 4 consecutive leave hours for 2026 claims. + wa_pfml_eligible: false + wa_pfml_max_leave_weeks: 0 wa_pfml: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml_max_leave_weeks.yaml b/policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml_max_leave_weeks.yaml new file mode 100644 index 00000000000..eccb2b21c35 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml_max_leave_weeks.yaml @@ -0,0 +1,82 @@ +- name: Case 1, family leave is limited to 12 weeks. + period: 2026 + input: + people: + person1: + weekly_hours_worked: 20 + wa_pfml_leave_type: FAMILY + households: + household: + members: [person1] + state_code: WA + output: + wa_pfml_max_leave_weeks: 12 + +- name: Case 2, medical leave is limited to 12 weeks. + period: 2026 + input: + people: + person1: + weekly_hours_worked: 20 + wa_pfml_leave_type: MEDICAL + households: + household: + members: [person1] + state_code: WA + output: + wa_pfml_max_leave_weeks: 12 + +- name: Case 3, combined leave is limited to 16 weeks. + period: 2026 + input: + people: + person1: + weekly_hours_worked: 20 + wa_pfml_leave_type: COMBINED + households: + household: + members: [person1] + state_code: WA + output: + wa_pfml_max_leave_weeks: 16 + +- name: Case 4, pregnancy-related medical leave is limited to 14 weeks. + period: 2026 + input: + people: + person1: + weekly_hours_worked: 20 + wa_pfml_leave_type: MEDICAL_WITH_PREGNANCY_INCAPACITY + households: + household: + members: [person1] + state_code: WA + output: + wa_pfml_max_leave_weeks: 14 + +- name: Case 5, combined leave with pregnancy incapacity is limited to 18 weeks. + period: 2026 + input: + people: + person1: + weekly_hours_worked: 20 + wa_pfml_leave_type: COMBINED_WITH_PREGNANCY_INCAPACITY + households: + household: + members: [person1] + state_code: WA + output: + wa_pfml_max_leave_weeks: 18 + +- name: Case 6, no selected leave type returns zero maximum leave weeks. + period: 2026 + input: + people: + person1: + weekly_hours_worked: 20 + households: + household: + members: [person1] + state_code: WA + output: + wa_pfml_max_leave_weeks: 0 diff --git a/policyengine_us/variables/gov/states/wa/pfml/wa_pfml.py b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml.py index f1f045ed4e2..7596da1186f 100644 --- a/policyengine_us/variables/gov/states/wa/pfml/wa_pfml.py +++ b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml.py @@ -4,12 +4,11 @@ class wa_pfml(Variable): value_type = float entity = Person - label = "Washington PFML benefit" + label = "Washington PFML maximum annual benefit" documentation = ( - "Annual Washington Paid Family and Medical Leave benefit. " - "Computed as the weekly benefit amount multiplied by the " - "claimed leave weeks, capped at the maximum duration for the " - "selected leave type." + "Maximum annual Washington Paid Family and Medical Leave benefit for " + "the selected leave type. Computed as the weekly benefit amount " + "multiplied by the maximum eligible leave duration." ) unit = USD definition_period = YEAR @@ -20,52 +19,6 @@ class wa_pfml(Variable): ) def formula(person, period, parameters): - p = parameters(period).gov.states.wa.pfml weekly_benefit = person("wa_pfml_weekly_benefit_amount", period) - leave_type = person("wa_pfml_leave_type", period) - leave_type_values = leave_type.possible_values - max_leave_weeks = select( - [ - leave_type == leave_type_values.FAMILY, - leave_type == leave_type_values.MEDICAL, - leave_type == leave_type_values.COMBINED, - leave_type == leave_type_values.MEDICAL_WITH_PREGNANCY_INCAPACITY, - leave_type == leave_type_values.COMBINED_WITH_PREGNANCY_INCAPACITY, - ], - [ - p.duration.family_leave_weeks, - p.duration.medical_leave_weeks, - p.duration.combined_max_weeks, - p.duration.medical_leave_weeks_with_pregnancy_incapacity, - p.duration.combined_max_weeks_with_pregnancy_incapacity, - ], - default=0, - ) - leave_hours_claimed = np.floor(person("wa_pfml_leave_hours_claimed", period)) - typical_workweek_hours = person("wa_pfml_typical_workweek_hours", period) - leave_hours_meet_minimum = where( - leave_hours_claimed >= p.min_claim_hours, - leave_hours_claimed, - 0, - ) - leave_weeks_from_hours = np.divide( - clip( - leave_hours_meet_minimum, - 0, - max_leave_weeks * typical_workweek_hours, - ), - typical_workweek_hours, - out=np.zeros_like(leave_hours_meet_minimum, dtype=np.float32), - where=typical_workweek_hours > 0, - ) - leave_weeks_from_weeks = clip( - person("wa_pfml_leave_weeks", period), - 0, - max_leave_weeks, - ) - leave_weeks = where( - (leave_hours_claimed > 0) & (typical_workweek_hours > 0), - leave_weeks_from_hours, - leave_weeks_from_weeks, - ) - return weekly_benefit * leave_weeks + max_leave_weeks = person("wa_pfml_max_leave_weeks", period) + return weekly_benefit * max_leave_weeks diff --git a/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_eligible.py b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_eligible.py index 36bbd1a5357..4bb0f7dd8e6 100644 --- a/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_eligible.py +++ b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_eligible.py @@ -9,8 +9,9 @@ class wa_pfml_eligible(Variable): "Eligibility for Washington Paid Family and Medical Leave " "benefits. Requires working at least the qualifying hours " "threshold in the qualifying period per RCW 50A.15.010. " - "Annual hours worked is approximated as weekly hours worked " - "multiplied by the number of weeks in a year." + "If no qualifying-period hours override is provided, annual hours " + "worked are approximated as weekly hours worked multiplied by the " + "number of weeks in a year." ) definition_period = YEAR defined_for = StateCode.WA diff --git a/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_leave_hours_claimed.py b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_leave_hours_claimed.py deleted file mode 100644 index c4cb6d094e4..00000000000 --- a/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_leave_hours_claimed.py +++ /dev/null @@ -1,17 +0,0 @@ -from policyengine_us.model_api import * - - -class wa_pfml_leave_hours_claimed(Variable): - value_type = float - entity = Person - label = "Washington PFML leave hours claimed" - documentation = ( - "Optional claimed leave hours for Washington PFML. If positive and " - "paired with typical workweek hours, this takes precedence over " - "leave weeks for annual benefit calculations." - ) - unit = "hour" - definition_period = YEAR - defined_for = StateCode.WA - default_value = 0 - reference = "https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020" diff --git a/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_leave_type.py b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_leave_type.py index ac4ae7f412c..cee4f9da9e3 100644 --- a/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_leave_type.py +++ b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_leave_type.py @@ -13,7 +13,7 @@ class WAPFMLLeaveType(Enum): class wa_pfml_leave_type(Variable): value_type = Enum entity = Person - label = "Washington PFML leave type" + label = "Washington PFML selected leave type" definition_period = YEAR possible_values = WAPFMLLeaveType default_value = WAPFMLLeaveType.NONE diff --git a/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_leave_weeks.py b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_leave_weeks.py deleted file mode 100644 index baac8329428..00000000000 --- a/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_leave_weeks.py +++ /dev/null @@ -1,11 +0,0 @@ -from policyengine_us.model_api import * - - -class wa_pfml_leave_weeks(Variable): - value_type = float - entity = Person - label = "Washington PFML leave weeks claimed" - definition_period = YEAR - defined_for = StateCode.WA - default_value = 0 - reference = "https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020" diff --git a/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_max_leave_weeks.py b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_max_leave_weeks.py new file mode 100644 index 00000000000..d6f1ee934a3 --- /dev/null +++ b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_max_leave_weeks.py @@ -0,0 +1,40 @@ +from policyengine_us.model_api import * + + +class wa_pfml_max_leave_weeks(Variable): + value_type = float + entity = Person + label = "Washington PFML maximum leave weeks" + documentation = ( + "Maximum Washington Paid Family and Medical Leave duration in weeks " + "for the selected leave type." + ) + unit = "week" + definition_period = YEAR + defined_for = "wa_pfml_eligible" + reference = ( + "https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020", + "https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.010", + ) + + def formula(person, period, parameters): + p = parameters(period).gov.states.wa.pfml + leave_type = person("wa_pfml_leave_type", period) + leave_type_values = leave_type.possible_values + return select( + [ + leave_type == leave_type_values.FAMILY, + leave_type == leave_type_values.MEDICAL, + leave_type == leave_type_values.COMBINED, + leave_type == leave_type_values.MEDICAL_WITH_PREGNANCY_INCAPACITY, + leave_type == leave_type_values.COMBINED_WITH_PREGNANCY_INCAPACITY, + ], + [ + p.duration.family_leave_weeks, + p.duration.medical_leave_weeks, + p.duration.combined_max_weeks, + p.duration.medical_leave_weeks_with_pregnancy_incapacity, + p.duration.combined_max_weeks_with_pregnancy_incapacity, + ], + default=0, + ) diff --git a/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_typical_workweek_hours.py b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_typical_workweek_hours.py deleted file mode 100644 index 4b89ef2cf0f..00000000000 --- a/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_typical_workweek_hours.py +++ /dev/null @@ -1,16 +0,0 @@ -from policyengine_us.model_api import * - - -class wa_pfml_typical_workweek_hours(Variable): - value_type = float - entity = Person - label = "Washington PFML typical workweek hours" - documentation = ( - "Optional typical workweek hours for Washington PFML claim " - "proration. Used only when leave hours claimed are provided." - ) - unit = "hour" - definition_period = YEAR - defined_for = StateCode.WA - default_value = 0 - reference = "https://app.leg.wa.gov/rcw/default.aspx?cite=50A.05.010" diff --git a/sources/working_references.md b/sources/working_references.md deleted file mode 100644 index b1315772a32..00000000000 --- a/sources/working_references.md +++ /dev/null @@ -1,566 +0,0 @@ -# Collected Documentation - -## Washington State Paid Family and Medical Leave (WA PFML) -**Collected**: 2026-04-22 -**Implementation Task**: Implement Washington State's Paid Family and Medical Leave wage replacement benefit calculation in PolicyEngine US. The existing codebase already has the employee/employer contribution (premium) side; this task adds the benefit (wage replacement) side. - ---- - -## Official Program Name - -**Federal Program**: Paid Family and Medical Leave (state-level — no single federal program; federal FMLA is unpaid) -**State's Official Name**: Washington Paid Family and Medical Leave -**Abbreviation**: PFML (sometimes WPFML) -**Source**: RCW Title 50A — "Family and Medical Leave" -**Administrator**: Washington State Employment Security Department (ESD) - -**Variable Prefix**: `wa_pfml` -**Legal Authority**: -- Statute: RCW Title 50A (Chapters 50A.05, 50A.10, 50A.15, 50A.20, 50A.24, 50A.25, 50A.30, 50A.35, 50A.40, 50A.45, 50A.50) -- Regulations: WAC Title 192, Chapters 192-500 through 192-810 - -**Existing implementation in codebase**: -- `policyengine_us/variables/gov/states/wa/tax/payroll/paid_leave/` — has contribution (premium) side - - `wa_employee_paid_leave_contribution.py` - - `wa_employer_paid_leave_contribution.py` -- `policyengine_us/parameters/gov/states/wa/tax/payroll/paid_leave/` — has contribution parameters - - `total_rate.yaml` (0.92% in 2025, 1.13% in 2026) - - `employer_share.yaml` (28.48% in 2025, 28.57% in 2026) - - `employer_headcount_threshold.yaml` (50) - -**NEW work**: Benefit (wage replacement) side — does not yet exist for any state in the codebase. - ---- - -## 1. Source Information - -### Primary Legal Authorities - -| Source | Citation | URL | Notes | -|--------|----------|-----|-------| -| Statute — Eligibility | RCW 50A.15.010 | https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.010 | 820 hours in qualifying period | -| Statute — Benefit amount & duration (pre-2026) | RCW 50A.15.020 (Effective until January 1, 2026) | https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020 | Current law; min claim 8 hours | -| Statute — Benefit amount & duration (2026+) | RCW 50A.15.020 (Effective January 1, 2026) | https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020 | Min claim reduced to 4 hours | -| Statute — Definitions | RCW 50A.05.010 | https://app.leg.wa.gov/rcw/default.aspx?cite=50A.05.010 | AWW, SAWW, qualifying period, typical workweek hours | -| Statute — Premiums | RCW 50A.10.030 | https://app.leg.wa.gov/rcw/default.aspx?cite=50A.10.030 | Contribution rates | -| Regulations — Benefits | WAC Chapter 192-620 | https://app.leg.wa.gov/wac/default.aspx?cite=192-620&full=true | Weekly benefit procedures | -| Regulations — Definitions | WAC Chapter 192-500 | https://app.leg.wa.gov/wac/default.aspx?cite=192-500 | WAC definitions | -| Program website | Washington State Paid Leave | https://paidleave.wa.gov | Official ESD site | -| 2026 official paycheck insert | ESD | https://paidleave.wa.gov/app/uploads/2025/12/Paycheck-insert-2026-1.pdf | Official 2026 values | -| Legislative amendment (2025) | 2025 c 304 (ESSHB 1213) | https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020 | Effective 2026 | - -**Effective Dates**: Program began January 1, 2020. Significant amendments via 2025 c 304 (ESSHB 1213) take effect January 1, 2026. - ---- - -## 2. Key Rules and Thresholds - -### 2.1 Eligibility — RCW 50A.15.010 - -Exact statutory text: -> "Employees are eligible for family and medical leave benefits as provided in this title after working for at least eight hundred twenty hours in employment during the qualifying period." - -**Single explicit eligibility rule:** -- **820 hours in employment during the qualifying period** (this is the only numeric threshold in the eligibility statute) -- Hours can accumulate across multiple employers -- Federal employees, self-employed (unless opted-in), and employees of tribally-owned businesses on tribal land are excluded (administrative rules / program documentation) - -### 2.2 Qualifying Period — RCW 50A.05.010(21) - -Exact statutory text: -> "'Qualifying period' means the first four of the last five completed calendar quarters or, if eligibility is not established, the last four completed calendar quarters immediately preceding the application for leave." - -### 2.3 Employee's Average Weekly Wage (AWW) — RCW 50A.05.010(6) - -Exact statutory text: -> "'Employee's average weekly wage' means the quotient derived by dividing the employee's total wages during the two quarters of the employee's qualifying period in which total wages were highest by twenty-six. If the result is not a multiple of one dollar, the department must round the result to the next lower multiple of one dollar." - -**Formula:** -``` -AWW = floor( (wages in top two quarters of qualifying period) / 26 ) -``` - -### 2.4 State Average Weekly Wage (SAWW) — RCW 50A.05.010(26) - -> "'State average weekly wage' means the most recent average weekly wage calculated under RCW 50.04.355 and available on January 1st of each year." - -Note: This is the official calculation done by ESD annually; values are fixed for PolicyEngine. - -### 2.5 Typical Workweek Hours — RCW 50A.05.010(28) - -> "(a) For an hourly employee, the average number of hours worked per week by an employee within the qualifying period; and -> (b) Forty hours for a salaried employee, regardless of the number of hours the salaried employee typically works." - -**Key implementation note**: For salaried employees, hard value = 40 hours regardless of actual hours. - ---- - -## 3. Weekly Benefit Formula — RCW 50A.15.020(5) - -### Exact Statutory Language - -Both current and 2026-effective versions contain identical formula language (percentages unchanged between versions): - -> "(5) The weekly benefit for family and medical leave shall be determined as follows: If the employee's average weekly wage is: -> (a) Equal to or less than one-half of the state average weekly wage, then the benefit amount is equal to 90 percent of the employee's average weekly wage; or -> (b) greater than one-half of the state average weekly wage, then the benefit amount is the sum of: -> (i) Ninety percent of one-half of the state average weekly wage; and -> (ii) 50 percent of the difference of the employee's average weekly wage and one-half of the state average weekly wage." - -### Formula (Mathematical) - -Let: -- `AWW` = employee's average weekly wage -- `SAWW` = state average weekly wage -- `H` = 0.5 × SAWW (half the state average weekly wage; the breakpoint) - -**Uncapped, unfloored benefit:** -``` -if AWW <= H: - benefit = 0.90 × AWW -else: - benefit = 0.90 × H + 0.50 × (AWW - H) -``` - -Then apply ceiling and floor (see next sections). - -### Minimum and Maximum — RCW 50A.15.020(6) - -**Maximum weekly benefit (RCW 50A.15.020(6)(a)):** -> "The maximum weekly benefit for family and medical leave that occurs on or after January 1, 2020, shall be $1,000. By September 30, 2020, and by each subsequent September 30th, the commissioner shall adjust the maximum weekly benefit amount to 90 percent of the state average weekly wage. The adjusted maximum weekly benefit amount takes effect on the following January 1st." - -So `max_weekly_benefit = 0.90 × SAWW` (rounded; value is set by commissioner and takes effect January 1 each year). - -**Minimum weekly benefit (RCW 50A.15.020(6)(b)):** -> "The minimum weekly benefit shall not be less than $100 per week except that if the employee's average weekly wage at the time of family or medical leave is less than $100 per week, the weekly benefit shall be the employee's full wage." - -### Rounding — RCW 50A.15.020(2)(a) - -> "The benefits in this section, if not a multiple of one dollar, shall be reduced to the next lower multiple of one dollar." - -Apply `floor()` to the final benefit amount (before comparing to min/max). - -### Full Pseudocode - -``` -def weekly_benefit(AWW, SAWW): - H = 0.5 * SAWW - if AWW <= H: - raw = 0.90 * AWW - else: - raw = 0.90 * H + 0.50 * (AWW - H) - raw = floor(raw) # to next lower dollar (RCW 50A.15.020(2)(a)) - max_wb = 0.90 * SAWW # published annually by commissioner - # Apply min/max floor/ceiling: - if AWW < 100: # special case: if AWW < $100, benefit = full AWW - return AWW - return max(100, min(raw, max_wb)) -``` - -### Prorating — RCW 50A.15.020(2) - -> "The weekly benefit shall be prorated by the percentage of hours on leave compared to the number of hours provided as the typical workweek hours as defined in RCW 50A.05.010." - -For implementation at the weekly level (full-week leave), proration is 1.0. Partial-week proration may be out of scope for the simplified implementation. - -### Example Calculations (2026 values) - -With **SAWW = $1,830** (2026), `H = $915`: - -| AWW | Tier | Formula | Result | After min/max | -|-----|------|---------|--------|---------------| -| $500 | Low | 0.90 × $500 | $450 | $450 | -| $915 | At threshold | 0.90 × $915 | $823 (floor of 823.50) | $823 | -| $1,200 | High | 0.90 × $915 + 0.50 × ($1,200 − $915) = $823.50 + $142.50 | $966 (floor of 966) | $966 | -| $1,500 | High | $823.50 + 0.50 × $585 = $823.50 + $292.50 | $1,116 | $1,116 | -| $2,562 | High | $823.50 + 0.50 × ($2,562 − $915) = $823.50 + $823.50 | $1,647 | $1,647 (at cap) | -| $3,000 | High | $823.50 + 0.50 × $2,085 = $823.50 + $1,042.50 | $1,866 (floor) | **$1,647** (capped) | -| $80 | Very low (AWW < $100) | AWW | $80 | $80 (full wage, not the $100 floor) | - ---- - -## 4. Duration Limits — RCW 50A.15.020(3) - -Exact statutory text: -> "(3)(a) The maximum duration of paid family leave may not exceed 12 times the typical workweek hours during a period of 52 consecutive calendar weeks. -> (b) The maximum duration of paid medical leave may not exceed 12 times the typical workweek hours during a period of 52 consecutive calendar weeks. This leave may be extended an additional two times the typical workweek hours if the employee experiences a serious health condition with a pregnancy that results in incapacity. -> (c) An employee is not entitled to paid family and medical leave benefits under this title that exceeds a combined total of 16 times the typical workweek hours. The combined total of family and medical leave may be extended to 18 times the typical workweek hours if the employee experiences a serious health condition with a pregnancy that results in incapacity." - -### Summary Table (durations measured in "typical workweek hours") - -| Leave Type | Standard Maximum | Pregnancy-Extension Maximum | -|------------|-----------------:|----------------------------:| -| Family leave only | 12× typical workweek hours | 12× (no pregnancy extension for family leave alone) | -| Medical leave only | 12× typical workweek hours | 14× typical workweek hours | -| Combined family + medical | 16× typical workweek hours | 18× typical workweek hours | - -**In practical weekly terms** (for full-time workers with a 40-hour typical workweek): -- Family leave: up to 12 weeks -- Medical leave: up to 12 weeks (14 weeks with pregnancy-related incapacity) -- Combined: up to 16 weeks (18 weeks with pregnancy-related incapacity) - -Measurement period: 52 consecutive calendar weeks. - ---- - -## 5. Waiting Period — RCW 50A.15.020(1)(a) - -Exact text: -> "Following a waiting period consisting of the first seven consecutive calendar days, benefits are payable when family or medical leave is required. However, no waiting period is required for leave for the birth or placement of a child, or for leave because of any qualifying exigency as defined under RCW 50A.05.010(10)(c)." - -**Waived for**: birth or placement of a child, qualifying military exigency. Not waived for medical leave or care-for-family-member leave. - ---- - -## 6. Minimum Claim Duration — RCW 50A.15.020(2)(c) - -- **Until January 1, 2026**: "The minimum claim duration payment is for **eight consecutive hours** of leave." -- **Effective January 1, 2026** (per 2025 c 304 / ESSHB 1213): "The minimum claim duration payment is for **four consecutive hours** of leave." - ---- - -## 7. Qualifying Events (from RCW 50A.05.010 definitions) - -Leave is available for a **qualifying event**, which falls under either family leave or medical leave: - -### Family Leave (RCW 50A.05.010(9)) -- Care for a family member with a serious health condition -- Bonding with a new child (birth, adoption, or foster placement) during the first 12 months -- Qualifying military exigency (as defined under federal FMLA — 29 U.S.C. § 2612(a)(1)(E) as of Oct 19, 2017) - -### Medical Leave (RCW 50A.05.010(13)) -- Employee's own serious health condition (including pregnancy-related incapacity) - -### Family Member — RCW 50A.05.010(8) -Includes: child, grandchild, grandparent, parent, sibling, spouse, **plus** any individual who regularly resides in the employee's home and depends on the employee for care. - -### Serious Health Condition — RCW 50A.05.010(23) -Illness, injury, impairment, or physical/mental condition involving: -- Inpatient care; or -- Continuing treatment by a health care provider - ---- - -## 8. Time-Series Values (for parameters) - -### 8.1 Maximum Weekly Benefit (published annually by commissioner) - -| Effective Date | Max Weekly Benefit | Source | -|---------------:|-------------------:|--------| -| 2020-01-01 | $1,000 | RCW 50A.15.020(6)(a) (statutory initial value) | -| 2021-01-01 | $1,206 | Historical published value | -| 2022-01-01 | $1,327 | Historical published value | -| 2023-01-01 | $1,427 | Historical published value | -| 2024-01-01 | $1,456 | Historical published value | -| 2025-01-01 | $1,542 | ESD 2025 announcement | -| 2026-01-01 | $1,647 | ESD 2026 paycheck insert | - -**Derived relationship**: max = 0.90 × SAWW (applied by commissioner each September for following January). - -**Source for 2026 value**: https://paidleave.wa.gov/app/uploads/2025/12/Paycheck-insert-2026-1.pdf - -### 8.2 State Average Weekly Wage (SAWW) used in formula - -The SAWW used in the formula for a given claim year is the SAWW effective January 1 of that year. (Derived from max = 0.90 × SAWW, and confirmed by ESD announcements.) - -| Effective Date | SAWW | Notes | -|---------------:|-----:|-------| -| 2020-01-01 | ~$1,111 | Implied from $1,000 max ÷ 0.9 | -| 2021-01-01 | ~$1,340 | Implied | -| 2022-01-01 | ~$1,474 | Implied | -| 2023-01-01 | ~$1,586 | Implied | -| 2024-01-01 | ~$1,618 | Announced as WA 2022 avg wage; applied 2024 | -| 2025-01-01 | ~$1,714 | Announced as WA 2023 avg wage; applied 2025 | -| 2026-01-01 | $1,830 | Confirmed by ESD; max = 0.90 × $1,830 = $1,647 | - -**Important**: For the purposes of this implementation, the benefit formula needs both **SAWW** (to define the breakpoint `H = 0.5 × SAWW`) and the **max weekly benefit** (which is itself 0.90 × SAWW). So a single `saww` parameter is sufficient; the max can be computed as `0.90 × saww`, OR store both parameters and derive nothing. - -**Recommendation**: Store SAWW as the primary parameter and derive `max = 0.90 × SAWW` in code. This matches how ESD actually operates. - -### 8.3 Minimum Weekly Benefit - -| Effective Date | Min Weekly Benefit | Source | -|---------------:|-------------------:|--------| -| 2020-01-01 | $100 | RCW 50A.15.020(6)(b) — flat $100 from program start | - -Never changed in statute. Special case: if AWW < $100, the benefit = AWW (employee's "full wage"), not the $100 minimum. - -### 8.4 Benefit Formula Percentages (constant since inception) - -| Parameter | Value | Source | -|-----------|------:|--------| -| Low-tier replacement rate | 0.90 (90%) | RCW 50A.15.020(5)(a) | -| High-tier base component | 0.90 of 0.5 × SAWW | RCW 50A.15.020(5)(b)(i) | -| High-tier marginal rate | 0.50 (50%) | RCW 50A.15.020(5)(b)(ii) | -| SAWW breakpoint fraction | 0.50 (1/2 of SAWW) | RCW 50A.15.020(5)(a)(b) | - -### 8.5 Duration Parameters (constant) - -| Parameter | Value | Source | -|-----------|------:|--------| -| Family leave max (× typical workweek hours) | 12 | RCW 50A.15.020(3)(a) | -| Medical leave max (× typical workweek hours) | 12 | RCW 50A.15.020(3)(b) | -| Medical leave max with pregnancy extension | 14 | RCW 50A.15.020(3)(b) | -| Combined max (× typical workweek hours) | 16 | RCW 50A.15.020(3)(c) | -| Combined max with pregnancy extension | 18 | RCW 50A.15.020(3)(c) | -| Measurement period (weeks) | 52 | RCW 50A.15.020(3)(a)(b) | -| Waiting period (days) | 7 | RCW 50A.15.020(1)(a) | - -### 8.6 Eligibility Hours Threshold - -| Parameter | Value | Source | -|-----------|------:|--------| -| Hours in qualifying period | 820 | RCW 50A.15.010 | - -### 8.7 Minimum Claim Duration - -| Effective Date | Value (hours) | Source | -|---------------:|--------------:|--------| -| 2020-01-01 | 8 | RCW 50A.15.020(2)(c) (pre-2026) | -| 2026-01-01 | 4 | RCW 50A.15.020(2)(c) as amended by 2025 c 304 | - -### 8.8 Typical Workweek Hours (salaried) - -| Parameter | Value (hours) | Source | -|-----------|--------------:|--------| -| Hours for salaried employee | 40 | RCW 50A.05.010(28)(b) | - ---- - -## 9. Identifying Derived Values - -### Maximum weekly benefit = 90% of SAWW - -**Legal citation**: RCW 50A.15.020(6)(a) -**Quote**: "By September 30, 2020, and by each subsequent September 30th, the commissioner shall adjust the maximum weekly benefit amount to 90 percent of the state average weekly wage." - -**Implementation implication**: Store SAWW and compute `max = 0.90 * SAWW` in the variable formula. This guarantees the relationship is preserved as SAWW updates. Alternatively, since ESD publishes a specific rounded dollar amount, store both separately. - -**Decision for implementation**: Store **both** SAWW and the published max weekly benefit (as the commissioner's published value may differ slightly due to rounding conventions). Cross-check: `0.9 × 1830 = 1647.00` — exact match, confirms no rounding divergence. - -### Breakpoint = 50% of SAWW - -**Legal citation**: RCW 50A.15.020(5)(a)(b) -**Quote**: "Equal to or less than one-half of the state average weekly wage" / "greater than one-half of the state average weekly wage" - -**Implementation implication**: Compute `H = 0.5 * SAWW` in the variable formula. No separate parameter needed — the fraction is statutorily fixed. - ---- - -## 10. Special Cases and Exceptions - -### 10.1 Low-wage floor exception -- If `AWW < $100/week`, the benefit = `AWW` (not $100 minimum). -- Source: RCW 50A.15.020(6)(b): "if the employee's average weekly wage at the time of family or medical leave is less than one hundred dollars per week, the weekly benefit shall be the employee's full wage." - -### 10.2 Waiting period waivers -- Waived for: birth/placement of a child, qualifying military exigency. -- Not waived for: medical leave (own serious health condition), family leave to care for a family member. -- Source: RCW 50A.15.020(1)(a). - -### 10.3 Rounding rules -- Benefit amount: rounded down to next lower dollar. Source: RCW 50A.15.020(2)(a). -- AWW itself: rounded down to next lower dollar. Source: RCW 50A.05.010(6). -- Hours on leave: rounded down to next lower hour. Source: RCW 50A.15.020(2)(b). - -### 10.4 Non-eligible worker categories -- Federal government employees -- Self-employed individuals (unless opted in via elective coverage — RCW 50A.10.010) -- Employees of tribally-owned businesses on tribal land (unless tribe opts in) - -### 10.5 Prorating for partial-week leave -- Weekly benefit prorated by `(hours on leave) / (typical workweek hours)`. -- Source: RCW 50A.15.020(2). -- **Implementation note**: A simplified annual/weekly implementation can assume full-week leave (proration factor = 1). - ---- - -## 11. Contribution (Premium) Side — Already Implemented - -The contribution side is already present in the codebase. Documenting here for completeness/context only; no changes needed unless values need updating. - -### Current parameters in `policyengine_us/parameters/gov/states/wa/tax/payroll/paid_leave/`: - -**total_rate.yaml** (premium rate — paid by employee + employer combined, as % of wages): -| Effective | Rate | Source | -|-----------|-----:|--------| -| 2025-01-01 | 0.92% | 2025 ESD announcement | -| 2026-01-01 | 1.13% | 2026 ESD paycheck insert | - -**employer_share.yaml** (employer share of total premium): -| Effective | Rate | Source | -|-----------|-----:|--------| -| 2025-01-01 | 28.48% | 2025 ESD announcement | -| 2026-01-01 | 28.57% | 2026 ESD paycheck insert | - -**employer_headcount_threshold.yaml**: 50 (employers with fewer than 50 employees are exempt from the employer share but still collect the employee share) -- Source: RCW 50A.10.030 - -**Taxable wages cap**: Social Security wage base ($184,500 for 2026) -- Source: RCW 50A.10.030; aligns with federal SS wage base. - ---- - -## 12. Implementation Approach for PolicyEngine - -### 12.1 Variables Needed (benefit side — NEW) - -**Design decision**: Since PFML is a wage-replacement benefit that depends on past earnings (during qualifying period) and a leave event, the cleanest implementation models the **maximum potential annual benefit** if the worker took the full allowed leave. This is analogous to how unemployment insurance benefits are modeled in PolicyEngine. - -A more modest implementation: given a user-supplied **leave weeks** input variable, compute the benefit. - -Required variables (recommended set, Person entity, YEAR period, `defined_for = StateCode.WA`): - -1. `wa_pfml_average_weekly_wage` — employee's AWW per RCW 50A.05.010(6). Simplified: `employment_income / 52`. (Note: regulatory definition is more complex; a simplification is acceptable.) -2. `wa_pfml_eligible` — boolean: did employee work 820+ hours in qualifying period? -3. `wa_pfml_weekly_benefit_uncapped` — computes the two-tier formula on AWW without min/max. -4. `wa_pfml_weekly_benefit` — applies floor/ceiling and special low-wage case. -5. `wa_pfml_weeks_of_leave` — user input (default 0): weeks of paid leave taken. -6. `wa_pfml_leave_type` — enum input (default = NONE): FAMILY / MEDICAL / COMBINED / MEDICAL_PREGNANCY / COMBINED_PREGNANCY. -7. `wa_pfml_max_weeks` — based on leave type, returns 12/14/16/18 per leave type. -8. `wa_pfml` — Person-level annual benefit = weekly_benefit × min(weeks_of_leave, max_weeks). - -### 12.2 Parameters Needed (benefit side — NEW) - -Organize under `policyengine_us/parameters/gov/states/wa/esd/pfml/` (Employment Security Department / PFML): - -``` -gov/states/wa/esd/pfml/ -├── eligibility/ -│ └── hours_threshold.yaml # 820 hours -├── benefit/ -│ ├── saww.yaml # SAWW annual values -│ ├── max_weekly_benefit.yaml # Max = 0.9 × SAWW -│ ├── min_weekly_benefit.yaml # $100 -│ ├── low_tier_rate.yaml # 0.90 -│ ├── high_tier_marginal_rate.yaml # 0.50 -│ └── breakpoint_share.yaml # 0.50 of SAWW -└── duration/ - ├── family_leave_weeks.yaml # 12 - ├── medical_leave_weeks.yaml # 12 - ├── medical_leave_weeks_pregnancy.yaml # 14 - ├── combined_weeks.yaml # 16 - └── combined_weeks_pregnancy.yaml # 18 -``` - -Alternative (cleaner): use a single `duration/by_type.yaml` breakdown by leave-type enum, rather than separate files. - -### 12.3 Reference Implementation Note - -No existing state in policyengine-us implements the **benefit** side of a PFML program — only contributions (DC, MA, NY, CT, DE, ME, OR, NJ, WA). So this implementation does not have a direct state analog to follow; model after how other wage-replacement benefits are implemented (e.g., unemployment compensation). - -Suggested analogs to study: -- Unemployment compensation variables (federal and state level) -- `ca_sdi` (California State Disability Insurance) if it exists -- `ny_paid_family_leave` benefit variables if they exist - ---- - -## 13. References for Metadata - -### For Parameters (YAML format) - -**Primary eligibility (820 hours):** -```yaml -reference: - - title: RCW 50A.15.010 Employee eligibility - href: https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.010 -``` - -**Weekly benefit formula & amounts:** -```yaml -reference: - - title: RCW 50A.15.020 Benefit—Amount and duration (Effective January 1, 2026) - href: https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020 - - title: Washington Paid Family and Medical Leave 2026 Paycheck Insert - href: https://paidleave.wa.gov/app/uploads/2025/12/Paycheck-insert-2026-1.pdf -``` - -**Duration limits:** -```yaml -reference: - - title: RCW 50A.15.020(3) Benefit—Amount and duration - href: https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020 -``` - -**AWW definition:** -```yaml -reference: - - title: RCW 50A.05.010(6) Employee's average weekly wage - href: https://app.leg.wa.gov/rcw/default.aspx?cite=50A.05.010 -``` - -**SAWW definition:** -```yaml -reference: - - title: RCW 50A.05.010(26) State average weekly wage - href: https://app.leg.wa.gov/rcw/default.aspx?cite=50A.05.010 -``` - -**Qualifying period:** -```yaml -reference: - - title: RCW 50A.05.010(21) Qualifying period - href: https://app.leg.wa.gov/rcw/default.aspx?cite=50A.05.010 -``` - -### For Variables (Python format) - -```python -reference = ( - "https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020", - "https://app.leg.wa.gov/rcw/default.aspx?cite=50A.05.010", - "https://paidleave.wa.gov/app/uploads/2025/12/Paycheck-insert-2026-1.pdf", -) -``` - ---- - -## 14. Quality Gate Checklist - -- [x] Benefit calculation formula — RCW 50A.15.020(5) with exact statutory text -- [x] Eligibility thresholds — 820 hours in qualifying period (RCW 50A.15.010) -- [x] Maximum weekly benefit amounts — values for 2020–2026 documented -- [x] Minimum weekly benefit — $100 (with low-wage exception) from RCW 50A.15.020(6)(b) -- [x] Duration limits — family (12x), medical (12x or 14x), combined (16x or 18x) from RCW 50A.15.020(3) -- [x] Waiting period — 7 days, with exceptions for birth/placement/military (RCW 50A.15.020(1)(a)) -- [x] Qualifying events — family leave and medical leave definitions (RCW 50A.05.010) -- [x] Authoritative sources — RCW Title 50A, WAC Title 192, ESD official PDF -- [x] Official program name — Washington Paid Family and Medical Leave (WA PFML) -- [x] Legal citations for percentages — confirmed 90%/50%/50% all in RCW 50A.15.020(5) -- [x] Legal citation for max = 90% SAWW — RCW 50A.15.020(6)(a) - ---- - -## 15. Additional Notes for Implementers - -### 15.1 Simplification Guidance - -Given the complexity of the actual program (quarterly wage analysis, leave event types, prorating, waiting periods), PolicyEngine's implementation should focus on what can be modeled from available household variables: - -**Reasonable simplifications:** -- Use annual `employment_income / 52` as a proxy for AWW (exact quarterly calculation requires quarterly wage data not available in PolicyEngine) -- Use hours-worked proxy (e.g., `max_(employment_income, 0) > 0`) or assume eligibility for any worker with positive earnings as a baseline, then refine -- Model at the **Person** entity level (benefits are individual) with YEAR period -- Default leave weeks = 0 (user input activates the benefit) - -### 15.2 Contribution Side Integration - -The existing `wa_employee_paid_leave_contribution` and `wa_employer_paid_leave_contribution` variables should remain as-is. The benefit (new) is a **separate concept** — most people pay in but never collect; the benefit is triggered by a specific leave event. - -### 15.3 Out-of-Scope Items - -The following are documented in the statute but should likely be OUT of a simplified PolicyEngine implementation: -- Voluntary/employer-sponsored equivalent plans (RCW 50A.30) -- Supplemental employer benefit payments (WAC 192-620-030) -- Child support deductions from benefits (WAC 192-620-045) -- Overpayment recovery (RCW 50A.45) -- Appeals procedures (RCW 50A.50) -- Waiting period mechanics within a claim year -- Conditional benefit payments during eligibility disputes - -### 15.4 Values Are Annual / Calendar-Year - -Per RCW 50A.15.020(6)(a), the max weekly benefit "takes effect on the following January 1st." The SAWW "available on January 1st of each year" per RCW 50A.05.010(26). So all parameter effective dates should be `YYYY-01-01`. - ----