From 709a6abe174c1cbbf5ecc7f291c5b5ee840c05b6 Mon Sep 17 00:00:00 2001 From: David Trimmer Date: Tue, 31 Mar 2026 10:03:01 -0400 Subject: [PATCH 01/23] Add Washington millionaires tax and WFTC age expansion (ESSB 6346) Implements the Washington millionaires tax (SB 6346) which was signed into law. Key provisions: - 9.9% tax on Washington taxable income (effective 2028) - $1,000,000 standard deduction (same for single and married filers) - $100,000 charitable deduction cap - WFTC age expansion to 18+ (effective 2029) This moves the provisions from the contributed reform (PR #7761) to baseline since the bill is now law. Co-Authored-By: Claude Opus 4.5 --- changelog.d/wa-millionaires-tax.added.md | 1 + .../age_expansion/in_effect.yaml | 15 +++ .../age_expansion/min_age.yaml | 13 +++ .../deductions/charitable/cap.yaml | 13 +++ .../millionaires_tax/deductions/standard.yaml | 22 ++++ .../income/millionaires_tax/in_effect.yaml | 11 ++ .../wa/tax/income/millionaires_tax/rate.yaml | 10 ++ ...working_families_tax_credit_expansion.yaml | 54 +++++++++ .../millionaires_tax/wa_millionaires_tax.yaml | 103 ++++++++++++++++++ .../credits/wa_working_families_tax_credit.py | 31 +++++- .../tax/income/millionaires_tax/__init__.py | 5 + .../millionaires_tax/wa_millionaires_tax.py | 25 +++++ .../wa_millionaires_tax_base_income.py | 29 +++++ ...a_millionaires_tax_charitable_deduction.py | 29 +++++ .../wa_millionaires_tax_standard_deduction.py | 21 ++++ .../wa_millionaires_tax_taxable_income.py | 36 ++++++ ...wa_income_tax_before_refundable_credits.py | 2 +- 17 files changed, 414 insertions(+), 6 deletions(-) create mode 100644 changelog.d/wa-millionaires-tax.added.md create mode 100644 policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/in_effect.yaml create mode 100644 policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/min_age.yaml create mode 100644 policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/deductions/charitable/cap.yaml create mode 100644 policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/deductions/standard.yaml create mode 100644 policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/in_effect.yaml create mode 100644 policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/rate.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/credits/wa_working_families_tax_credit_expansion.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax.yaml create mode 100644 policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/__init__.py create mode 100644 policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax.py create mode 100644 policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_base_income.py create mode 100644 policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_charitable_deduction.py create mode 100644 policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_standard_deduction.py create mode 100644 policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_taxable_income.py diff --git a/changelog.d/wa-millionaires-tax.added.md b/changelog.d/wa-millionaires-tax.added.md new file mode 100644 index 00000000000..b11278d15e5 --- /dev/null +++ b/changelog.d/wa-millionaires-tax.added.md @@ -0,0 +1 @@ +Add Washington millionaires tax (9.9% on income above $1M) and WFTC age expansion (18+) per ESSB 6346. diff --git a/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/in_effect.yaml b/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/in_effect.yaml new file mode 100644 index 00000000000..d18bca203d4 --- /dev/null +++ b/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/in_effect.yaml @@ -0,0 +1,15 @@ +description: >- + Washington expands WFTC eligibility to individuals who do not meet + the federal EITC age requirement but are at least the minimum age. +values: + 0000-01-01: false + 2029-01-01: true +metadata: + unit: bool + period: year + label: Washington WFTC age expansion in effect + reference: + - title: ESSB 6346, Sec. 901 - Working Families Tax Credit expansion + href: https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=59 + - title: ESSB 6346, Sec. 1205(1) - Effective date + href: https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=111 diff --git a/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/min_age.yaml b/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/min_age.yaml new file mode 100644 index 00000000000..11e7766f438 --- /dev/null +++ b/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/min_age.yaml @@ -0,0 +1,13 @@ +description: >- + Minimum age for WFTC eligibility under the age expansion provision. + Individuals who do not meet the federal EITC age requirement but are + at least this age are eligible for WFTC. +values: + 2029-01-01: 18 +metadata: + unit: year + period: year + label: Washington WFTC minimum age for expansion + reference: + - title: ESSB 6346, Sec. 901(2)(a)(ii)(D) - Age requirement + href: https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=59 diff --git a/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/deductions/charitable/cap.yaml b/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/deductions/charitable/cap.yaml new file mode 100644 index 00000000000..cc5b83ab789 --- /dev/null +++ b/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/deductions/charitable/cap.yaml @@ -0,0 +1,13 @@ +description: >- + Washington caps the charitable contribution deduction at this amount. + The cap is $100,000 per individual, or for spouses/domestic partners, + their combined deduction is limited to $100,000 regardless of filing status. +values: + 2028-01-01: 100_000 +metadata: + unit: currency-USD + period: year + label: Washington millionaires tax charitable deduction cap + reference: + - title: ESSB 6346, Sec. 309(1) - Charitable contributions + href: https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=12 diff --git a/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/deductions/standard.yaml b/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/deductions/standard.yaml new file mode 100644 index 00000000000..8e12b8ad6e9 --- /dev/null +++ b/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/deductions/standard.yaml @@ -0,0 +1,22 @@ +description: >- + Washington provides this standard deduction for the millionaires tax. + The deduction is $1,000,000 per individual, or for spouses/domestic partners, + their combined deduction is $1,000,000 regardless of filing status. +values: + 2028-01-01: 1_000_000 +metadata: + unit: currency-USD + period: year + label: Washington millionaires tax standard deduction + uprating: gov.bls.cpi.cpi_u + # Sec. 316 specifies Seattle-area CPI-U for indexing starting Oct 2029 + # (for tax year 2030). Using national CPI-U as a proxy until we add + # Seattle-area CPI data. Fixed at $1M for 2028-2029. + rounding: + type: nearest + interval: 1_000 + reference: + - title: ESSB 6346, Sec. 314 - One million dollar standard deduction + href: https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=13 + - title: ESSB 6346, Sec. 316(1) - Index for inflation + href: https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=13 diff --git a/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/in_effect.yaml b/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/in_effect.yaml new file mode 100644 index 00000000000..d2651651e6b --- /dev/null +++ b/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/in_effect.yaml @@ -0,0 +1,11 @@ +description: Washington applies its millionaires tax if this is true. +values: + 0000-01-01: false + 2028-01-01: true +metadata: + unit: bool + period: year + label: Washington millionaires tax in effect + reference: + - title: ESSB 6346, Sec. 201(1) - Tax Imposed + href: https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=6 diff --git a/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/rate.yaml b/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/rate.yaml new file mode 100644 index 00000000000..297f86f9f5c --- /dev/null +++ b/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/rate.yaml @@ -0,0 +1,10 @@ +description: Washington sets the millionaires tax rate to this share. +values: + 2028-01-01: 0.099 +metadata: + unit: /1 + period: year + label: Washington millionaires tax rate + reference: + - title: ESSB 6346, Sec. 201(1) - Tax Imposed + href: https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=6 diff --git a/policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/credits/wa_working_families_tax_credit_expansion.yaml b/policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/credits/wa_working_families_tax_credit_expansion.yaml new file mode 100644 index 00000000000..72044723b2a --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/credits/wa_working_families_tax_credit_expansion.yaml @@ -0,0 +1,54 @@ +# Washington Working Families Tax Credit - Age Expansion tests +# ESSB 6346 Sec. 901 expands eligibility to individuals age 18+ +# who do not meet federal EITC age requirements (effective 2029) + +- name: Age 22 single filer with earnings eligible under expansion in 2029 + period: 2029 + input: + state_code: WA + age: 22 + employment_income: 15_000 + output: + # Under normal EITC rules, childless filers must be 25-64 + # With expansion, filers age 18+ with earned income qualify + wa_working_families_tax_credit: 300 + +- name: Age 22 single filer with earnings NOT eligible in 2028 + period: 2028 + input: + state_code: WA + age: 22 + employment_income: 15_000 + output: + # Expansion not in effect until 2029 + wa_working_families_tax_credit: 0 + +- name: Age 22 single filer without earnings NOT eligible in 2029 + period: 2029 + input: + state_code: WA + age: 22 + employment_income: 0 + output: + # Must have earned income to qualify under expansion + wa_working_families_tax_credit: 0 + +- name: Age 17 single filer NOT eligible even in 2029 + period: 2029 + input: + state_code: WA + age: 17 + employment_income: 15_000 + output: + # Must be at least 18 to qualify under expansion + wa_working_families_tax_credit: 0 + +- name: Age 30 single filer eligible through normal EITC rules + period: 2029 + input: + state_code: WA + age: 30 + employment_income: 15_000 + output: + # Normal EITC eligibility applies (age 25-64) + wa_working_families_tax_credit: 300 diff --git a/policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax.yaml b/policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax.yaml new file mode 100644 index 00000000000..06c14fbb166 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax.yaml @@ -0,0 +1,103 @@ +# Washington Millionaires Tax tests +# ESSB 6346 imposes a 9.9% tax on Washington taxable income above $1,000,000 +# Effective January 1, 2028 + +- name: Single filer with $2M income in 2028 owes millionaires tax + period: 2028 + input: + state_code: WA + adjusted_gross_income: 2_000_000 + output: + # Taxable income = $2M - $1M standard deduction = $1M + # Tax = $1M * 9.9% = $99,000 + wa_millionaires_tax: 99_000 + +- name: Single filer with $1.5M income in 2028 owes millionaires tax + period: 2028 + input: + state_code: WA + adjusted_gross_income: 1_500_000 + output: + # Taxable income = $1.5M - $1M standard deduction = $500K + # Tax = $500K * 9.9% = $49,500 + wa_millionaires_tax: 49_500 + +- name: Single filer below $1M threshold owes no millionaires tax + period: 2028 + input: + state_code: WA + adjusted_gross_income: 900_000 + output: + # Income below $1M standard deduction, no tax owed + wa_millionaires_tax: 0 + +- name: Single filer exactly at $1M threshold owes no millionaires tax + period: 2028 + input: + state_code: WA + adjusted_gross_income: 1_000_000 + output: + # Taxable income = $1M - $1M = $0 + wa_millionaires_tax: 0 + +- name: Single filer just above $1M threshold owes small tax + period: 2028 + input: + state_code: WA + adjusted_gross_income: 1_001_000 + output: + # Taxable income = $1,001,000 - $1M = $1,000 + # Tax = $1,000 * 9.9% = $99 + wa_millionaires_tax: 99 + +- name: Tax not in effect in 2027 + period: 2027 + input: + state_code: WA + adjusted_gross_income: 2_000_000 + output: + # Tax doesn't take effect until 2028 + wa_millionaires_tax: 0 + +- name: Non-WA resident not subject to millionaires tax + period: 2028 + input: + state_code: CA + adjusted_gross_income: 2_000_000 + output: + wa_millionaires_tax: 0 + +- name: Charitable deduction reduces taxable income + period: 2028 + input: + state_code: WA + adjusted_gross_income: 2_000_000 + charitable_cash_donations: 50_000 + output: + # Taxable = $2M - $1M standard - $50K charitable = $950K + # Tax = $950K * 9.9% = $94,050 + wa_millionaires_tax: 94_050 + +- name: Charitable deduction capped at $100K + period: 2028 + input: + state_code: WA + adjusted_gross_income: 2_500_000 + charitable_cash_donations: 200_000 + output: + # Charitable deduction capped at $100K + # Taxable = $2.5M - $1M standard - $100K charitable = $1.4M + # Tax = $1.4M * 9.9% = $138,600 + wa_millionaires_tax: 138_600 + +- name: Joint filers share $1M standard deduction + period: 2028 + input: + state_code: WA + filing_status: JOINT + adjusted_gross_income: 2_000_000 + output: + # Married couples share the $1M deduction (not doubled) + # Taxable = $2M - $1M = $1M + # Tax = $1M * 9.9% = $99,000 + wa_millionaires_tax: 99_000 diff --git a/policyengine_us/variables/gov/states/wa/tax/income/credits/wa_working_families_tax_credit.py b/policyengine_us/variables/gov/states/wa/tax/income/credits/wa_working_families_tax_credit.py index 2d75d6bf2c4..54897eb2b2b 100644 --- a/policyengine_us/variables/gov/states/wa/tax/income/credits/wa_working_families_tax_credit.py +++ b/policyengine_us/variables/gov/states/wa/tax/income/credits/wa_working_families_tax_credit.py @@ -7,17 +7,38 @@ class wa_working_families_tax_credit(Variable): label = "Washington Working Families Tax Credit" unit = USD definition_period = YEAR - reference = "https://app.leg.wa.gov/RCW/default.aspx?cite=82.08.0206" + reference = ( + "https://app.leg.wa.gov/RCW/default.aspx?cite=82.08.0206", + "https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=59", + ) defined_for = StateCode.WA def formula(tax_unit, period, parameters): - # Filers must claim EITC and be in Washington to be eligible. - # TODO: Include ITIN children. - eligible = tax_unit("eitc", period) > 0 - # Parameters are based on EITC-eligible children. + # Baseline eligibility: filers who claim EITC + eitc = tax_unit("eitc", period) + eitc_eligible = eitc > 0 + + # ESSB 6346 Sec. 901(2)(a)(ii)(D): individuals who do not meet the + # EITC age requirement but are at least age 18 (effective 2029). p = parameters( period ).gov.states.wa.tax.income.credits.working_families_tax_credit + age_expansion = p.age_expansion + expansion_in_effect = age_expansion.in_effect + age_head = tax_unit("age_head", period) + age_spouse = tax_unit("age_spouse", period) + filer_meets_min_age = (age_head >= age_expansion.min_age) | ( + age_spouse >= age_expansion.min_age + ) + earned_income = tax_unit("filer_adjusted_earnings", period) + has_earned_income = earned_income > 0 + expansion_eligible = ( + expansion_in_effect & filer_meets_min_age & has_earned_income + ) + + eligible = eitc_eligible | expansion_eligible + + # Parameters are based on EITC-eligible children. eitc_child_count = tax_unit("eitc_child_count", period) max_amount = p.amount.calc(eitc_child_count) # WFTC phases out at a certain amount below the EITC maximum AGI. diff --git a/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/__init__.py b/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/__init__.py new file mode 100644 index 00000000000..fb7451f5c22 --- /dev/null +++ b/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/__init__.py @@ -0,0 +1,5 @@ +from policyengine_us.variables.gov.states.wa.tax.income.millionaires_tax.wa_millionaires_tax import * +from policyengine_us.variables.gov.states.wa.tax.income.millionaires_tax.wa_millionaires_tax_base_income import * +from policyengine_us.variables.gov.states.wa.tax.income.millionaires_tax.wa_millionaires_tax_charitable_deduction import * +from policyengine_us.variables.gov.states.wa.tax.income.millionaires_tax.wa_millionaires_tax_standard_deduction import * +from policyengine_us.variables.gov.states.wa.tax.income.millionaires_tax.wa_millionaires_tax_taxable_income import * diff --git a/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax.py b/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax.py new file mode 100644 index 00000000000..7ff72c93e92 --- /dev/null +++ b/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax.py @@ -0,0 +1,25 @@ +from policyengine_us.model_api import * + + +class wa_millionaires_tax(Variable): + value_type = float + entity = TaxUnit + label = "Washington millionaires tax" + unit = USD + definition_period = YEAR + reference = "https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=6" + defined_for = StateCode.WA + documentation = """ + ESSB 6346 Sec. 201(1) imposes a tax of 9.9% on Washington taxable income, + beginning January 1, 2028. The tax applies to Washington residents with + taxable income above $1,000,000. + + This is sometimes referred to as the "millionaires tax" because the + $1,000,000 standard deduction means only households with income above + that threshold owe any tax. + """ + + def formula(tax_unit, period, parameters): + p = parameters(period).gov.states.wa.tax.income.millionaires_tax + taxable_income = tax_unit("wa_millionaires_tax_taxable_income", period) + return taxable_income * p.rate diff --git a/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_base_income.py b/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_base_income.py new file mode 100644 index 00000000000..6bc6a3d2126 --- /dev/null +++ b/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_base_income.py @@ -0,0 +1,29 @@ +from policyengine_us.model_api import * + + +class wa_millionaires_tax_base_income(Variable): + value_type = float + entity = TaxUnit + label = "Washington millionaires tax base income" + unit = USD + definition_period = YEAR + reference = ( + "https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=5", + "https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=9", + ) + defined_for = StateCode.WA + documentation = """ + Washington base income is federal adjusted gross income as modified by + Sections 302 through 308 and 401 through 407 of ESSB 6346. + + Key modifications include: + - Long-term capital gains are replaced with Washington capital gains + (as defined in RCW 82.87) to avoid double-taxation with the capital gains tax + - Tax-exempt interest from non-WA state/local bonds is added back + - State/local income taxes deducted federally are added back + - Net operating loss carryovers from pre-2028 are not allowed + + This simplified implementation uses federal AGI as the base, with full + Section 302-308 modifications deferred for future enhancement. + """ + adds = ["adjusted_gross_income"] diff --git a/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_charitable_deduction.py b/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_charitable_deduction.py new file mode 100644 index 00000000000..4f2dd1a418b --- /dev/null +++ b/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_charitable_deduction.py @@ -0,0 +1,29 @@ +from policyengine_us.model_api import * + + +class wa_millionaires_tax_charitable_deduction(Variable): + value_type = float + entity = TaxUnit + label = "Washington millionaires tax charitable deduction" + unit = USD + definition_period = YEAR + reference = "https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=12" + defined_for = StateCode.WA + documentation = """ + ESSB 6346 Sec. 309(1) allows a charitable contribution deduction up to + $100,000 per individual. For spouses or domestic partners, their combined + charitable deduction is limited to $100,000, regardless of whether they + file joint or separate returns. + """ + + def formula(tax_unit, period, parameters): + p = parameters( + period + ).gov.states.wa.tax.income.millionaires_tax.deductions.charitable + charitable = add( + tax_unit, + period, + ["charitable_cash_donations", "charitable_non_cash_donations"], + ) + # Cap applies per tax unit (combined for spouses) + return min_(charitable, p.cap) diff --git a/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_standard_deduction.py b/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_standard_deduction.py new file mode 100644 index 00000000000..8fe341acd11 --- /dev/null +++ b/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_standard_deduction.py @@ -0,0 +1,21 @@ +from policyengine_us.model_api import * + + +class wa_millionaires_tax_standard_deduction(Variable): + value_type = float + entity = TaxUnit + label = "Washington millionaires tax standard deduction" + unit = USD + definition_period = YEAR + reference = "https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=13" + defined_for = StateCode.WA + documentation = """ + ESSB 6346 Sec. 314 provides a $1,000,000 standard deduction per individual. + For spouses or state registered domestic partners, their combined standard + deduction is $1,000,000, regardless of whether they file joint or separate + returns. + + The deduction is indexed to inflation starting October 2029 for tax year 2030, + using the Seattle-area CPI-U. + """ + adds = ["gov.states.wa.tax.income.millionaires_tax.deductions.standard"] diff --git a/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_taxable_income.py b/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_taxable_income.py new file mode 100644 index 00000000000..c5f1e1a28ca --- /dev/null +++ b/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_taxable_income.py @@ -0,0 +1,36 @@ +from policyengine_us.model_api import * + + +class wa_millionaires_tax_taxable_income(Variable): + value_type = float + entity = TaxUnit + label = "Washington millionaires tax taxable income" + unit = USD + definition_period = YEAR + reference = ( + "https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=5", + "https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=12", + "https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=13", + ) + defined_for = StateCode.WA + documentation = """ + Washington taxable income is Washington base income minus the standard + deduction ($1,000,000) and charitable contribution deduction (up to $100,000). + + Per Sec. 101(12), Washington taxable income is "Washington base income as + further modified by sections 309 through 314." + """ + + def formula(tax_unit, period, parameters): + in_effect = parameters( + period + ).gov.states.wa.tax.income.millionaires_tax.in_effect + base_income = tax_unit("wa_millionaires_tax_base_income", period) + charitable_deduction = tax_unit( + "wa_millionaires_tax_charitable_deduction", period + ) + standard_deduction = tax_unit("wa_millionaires_tax_standard_deduction", period) + taxable_income = max_( + base_income - charitable_deduction - standard_deduction, 0 + ) + return where(in_effect, taxable_income, 0) diff --git a/policyengine_us/variables/gov/states/wa/tax/income/wa_income_tax_before_refundable_credits.py b/policyengine_us/variables/gov/states/wa/tax/income/wa_income_tax_before_refundable_credits.py index dc5ddc2247c..6428f1aa831 100644 --- a/policyengine_us/variables/gov/states/wa/tax/income/wa_income_tax_before_refundable_credits.py +++ b/policyengine_us/variables/gov/states/wa/tax/income/wa_income_tax_before_refundable_credits.py @@ -8,4 +8,4 @@ class wa_income_tax_before_refundable_credits(Variable): unit = USD definition_period = YEAR defined_for = StateCode.WA - adds = ["wa_capital_gains_tax"] + adds = ["wa_capital_gains_tax", "wa_millionaires_tax"] From da76d0e265f3270c07a9e1f5ddc3b6c6c8f25521 Mon Sep 17 00:00:00 2001 From: David Trimmer Date: Tue, 31 Mar 2026 10:05:15 -0400 Subject: [PATCH 02/23] Remove contributed reform (SB 6346 is now law) Removes the contributed reform implementation since ESSB 6346 has been signed into law and is now implemented in baseline. Co-Authored-By: Claude Opus 4.5 --- changelog.d/wa-millionaires-tax.added.md | 2 +- .../charitable_deduction/cap/individual.yaml | 12 - .../charitable_deduction/cap/joint.yaml | 12 - .../contrib/states/wa/sb6346/in_effect.yaml | 12 - .../gov/contrib/states/wa/sb6346/rate.yaml | 12 - .../wa/sb6346/standard_deduction/amount.yaml | 21 - .../states/wa/sb6346/wftc/in_effect.yaml | 15 - .../states/wa/sb6346/wftc/min_age.yaml | 16 - policyengine_us/reforms/reforms.py | 67 -- .../reforms/states/wa/sb6346/__init__.py | 1 - .../reforms/states/wa/sb6346/sb6346.py | 194 ------ .../contrib/states/wa/sb6346/sb6346.yaml | 638 ------------------ 12 files changed, 1 insertion(+), 1001 deletions(-) delete mode 100644 policyengine_us/parameters/gov/contrib/states/wa/sb6346/charitable_deduction/cap/individual.yaml delete mode 100644 policyengine_us/parameters/gov/contrib/states/wa/sb6346/charitable_deduction/cap/joint.yaml delete mode 100644 policyengine_us/parameters/gov/contrib/states/wa/sb6346/in_effect.yaml delete mode 100644 policyengine_us/parameters/gov/contrib/states/wa/sb6346/rate.yaml delete mode 100644 policyengine_us/parameters/gov/contrib/states/wa/sb6346/standard_deduction/amount.yaml delete mode 100644 policyengine_us/parameters/gov/contrib/states/wa/sb6346/wftc/in_effect.yaml delete mode 100644 policyengine_us/parameters/gov/contrib/states/wa/sb6346/wftc/min_age.yaml delete mode 100644 policyengine_us/reforms/states/wa/sb6346/__init__.py delete mode 100644 policyengine_us/reforms/states/wa/sb6346/sb6346.py delete mode 100644 policyengine_us/tests/policy/contrib/states/wa/sb6346/sb6346.yaml diff --git a/changelog.d/wa-millionaires-tax.added.md b/changelog.d/wa-millionaires-tax.added.md index b11278d15e5..461bbabbff9 100644 --- a/changelog.d/wa-millionaires-tax.added.md +++ b/changelog.d/wa-millionaires-tax.added.md @@ -1 +1 @@ -Add Washington millionaires tax (9.9% on income above $1M) and WFTC age expansion (18+) per ESSB 6346. +Add Washington millionaires tax (9.9% on income above $1M) and WFTC age expansion (18+) per ESSB 6346. Removes contributed reform since bill is now law. diff --git a/policyengine_us/parameters/gov/contrib/states/wa/sb6346/charitable_deduction/cap/individual.yaml b/policyengine_us/parameters/gov/contrib/states/wa/sb6346/charitable_deduction/cap/individual.yaml deleted file mode 100644 index d6f8d582335..00000000000 --- a/policyengine_us/parameters/gov/contrib/states/wa/sb6346/charitable_deduction/cap/individual.yaml +++ /dev/null @@ -1,12 +0,0 @@ -description: Washington limits the charitable contribution deduction to this amount per individual under the SSB 6346 reform. - -values: - 2028-01-01: 100_000 - -metadata: - unit: currency-USD - period: year - label: Washington SSB 6346 individual charitable deduction cap - reference: - - title: SSB 6346, Sec. 307 - Charitable Contributions - href: https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Bills/6346-S.pdf#page=10 diff --git a/policyengine_us/parameters/gov/contrib/states/wa/sb6346/charitable_deduction/cap/joint.yaml b/policyengine_us/parameters/gov/contrib/states/wa/sb6346/charitable_deduction/cap/joint.yaml deleted file mode 100644 index 298b9b479c3..00000000000 --- a/policyengine_us/parameters/gov/contrib/states/wa/sb6346/charitable_deduction/cap/joint.yaml +++ /dev/null @@ -1,12 +0,0 @@ -description: Washington limits the combined charitable contribution deduction for married couples to this amount under the SSB 6346 reform. - -values: - 2028-01-01: 100_000 - -metadata: - unit: currency-USD - period: year - label: Washington SSB 6346 joint charitable deduction cap - reference: - - title: SSB 6346, Sec. 307 - Charitable Contributions - href: https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Bills/6346-S.pdf#page=10 diff --git a/policyengine_us/parameters/gov/contrib/states/wa/sb6346/in_effect.yaml b/policyengine_us/parameters/gov/contrib/states/wa/sb6346/in_effect.yaml deleted file mode 100644 index c4270ebe8db..00000000000 --- a/policyengine_us/parameters/gov/contrib/states/wa/sb6346/in_effect.yaml +++ /dev/null @@ -1,12 +0,0 @@ -description: Washington uses this indicator to determine whether the SSB 6346 income tax reform is in effect. - -values: - 2024-01-01: false - -metadata: - unit: bool - period: year - label: Washington SSB 6346 income tax reform in effect - reference: - - title: SSB 6346, 69th Legislature, 2025-2026 - href: https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Bills/6346-S.pdf#page=1 diff --git a/policyengine_us/parameters/gov/contrib/states/wa/sb6346/rate.yaml b/policyengine_us/parameters/gov/contrib/states/wa/sb6346/rate.yaml deleted file mode 100644 index a1166deeb0a..00000000000 --- a/policyengine_us/parameters/gov/contrib/states/wa/sb6346/rate.yaml +++ /dev/null @@ -1,12 +0,0 @@ -description: Washington sets the income tax rate to this share under the SSB 6346 reform. - -values: - 2028-01-01: 0.099 - -metadata: - unit: /1 - period: year - label: Washington SSB 6346 income tax rate - reference: - - title: SSB 6346, Sec. 201(1) - Tax Imposed - href: https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Bills/6346-S.pdf#page=6 diff --git a/policyengine_us/parameters/gov/contrib/states/wa/sb6346/standard_deduction/amount.yaml b/policyengine_us/parameters/gov/contrib/states/wa/sb6346/standard_deduction/amount.yaml deleted file mode 100644 index 4d0e7de520b..00000000000 --- a/policyengine_us/parameters/gov/contrib/states/wa/sb6346/standard_deduction/amount.yaml +++ /dev/null @@ -1,21 +0,0 @@ -description: Washington provides this amount as the standard deduction under the SSB 6346 reform. - -values: - 2028-01-01: 1_000_000 - -metadata: - unit: currency-USD - period: year - label: Washington SSB 6346 standard deduction - uprating: gov.bls.cpi.cpi_u - # Sec. 312 specifies Seattle-area CPI-U for indexing starting Oct 2029 - # (for tax year 2030). Using national CPI-U as a proxy until we add - # Seattle-area CPI data. Fixed at $1M for 2028-2029. - rounding: - type: nearest - interval: 1_000 - reference: - - title: SSB 6346, Sec. 310 - One million dollar standard deduction - href: https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Bills/6346-S.pdf#page=10 - - title: SSB 6346, Sec. 312(1) - Index for inflation - href: https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Bills/6346-S.pdf#page=11 diff --git a/policyengine_us/parameters/gov/contrib/states/wa/sb6346/wftc/in_effect.yaml b/policyengine_us/parameters/gov/contrib/states/wa/sb6346/wftc/in_effect.yaml deleted file mode 100644 index 91bd69c832d..00000000000 --- a/policyengine_us/parameters/gov/contrib/states/wa/sb6346/wftc/in_effect.yaml +++ /dev/null @@ -1,15 +0,0 @@ -description: Washington uses this indicator to determine whether the SSB 6346 Working Families Tax Credit age expansion is in effect. - -values: - 2024-01-01: false - 2029-01-01: true - -metadata: - unit: bool - period: year - label: Washington SSB 6346 WFTC age expansion in effect - reference: - - title: SSB 6346, Sec. 901(2)(a)(ii)(C) - href: https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Bills/6346-S.pdf#page=53 - - title: SSB 6346, Sec. 1005(1) - href: https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Bills/6346-S.pdf#page=63 diff --git a/policyengine_us/parameters/gov/contrib/states/wa/sb6346/wftc/min_age.yaml b/policyengine_us/parameters/gov/contrib/states/wa/sb6346/wftc/min_age.yaml deleted file mode 100644 index 1b7c8624d98..00000000000 --- a/policyengine_us/parameters/gov/contrib/states/wa/sb6346/wftc/min_age.yaml +++ /dev/null @@ -1,16 +0,0 @@ -description: Washington sets this age threshold for expanded Working Families Tax Credit eligibility under the SSB 6346 reform. - -values: - 2029-01-01: 18 - -# PolicyEngine does not model the WFTC's claim-year timing separately from the -# simulated tax year, so the later effective date in Sec. 1005(1) is enforced -# through the companion wftc/in_effect parameter rather than by backdating this -# threshold before 2029. -metadata: - unit: year - period: year - label: Washington SSB 6346 WFTC minimum age threshold - reference: - - title: SSB 6346, Sec. 901(2)(a)(ii)(C) - href: https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Bills/6346-S.pdf#page=53 diff --git a/policyengine_us/reforms/reforms.py b/policyengine_us/reforms/reforms.py index f774002d35c..761e037e7e2 100644 --- a/policyengine_us/reforms/reforms.py +++ b/policyengine_us/reforms/reforms.py @@ -184,9 +184,6 @@ from .congress.watca import ( create_watca_reform, ) -from .states.wa.sb6346.sb6346 import ( - create_wa_sb6346_reform, -) from .states.ga.sb520 import ( @@ -201,42 +198,6 @@ from .states.mi.ctc import ( create_mi_ctc_reform, ) -from .states.al.eitc import ( - create_al_eitc_reform, -) -from .states.ar.eitc import ( - create_ar_eitc_reform, -) -from .states.az.eitc import ( - create_az_eitc_reform, -) -from .states.ga.eitc import ( - create_ga_eitc_reform, -) -from .states.id.eitc import ( - create_id_eitc_reform, -) -from .states.ky.eitc import ( - create_ky_eitc_reform, -) -from .states.ms.eitc import ( - create_ms_eitc_reform, -) -from .states.nd.eitc import ( - create_nd_eitc_reform, -) -from .states.wv.eitc import ( - create_wv_eitc_reform, -) -from .states.mo.eitc import ( - create_mo_refundable_eitc_reform, -) -from .states.oh.eitc import ( - create_oh_refundable_eitc_reform, -) -from .states.ut.child_poverty_eitc import ( - create_ut_fully_refundable_eitc_reform, -) from policyengine_core.reforms import Reform import warnings @@ -411,21 +372,6 @@ def create_structural_reforms_from_parameters(parameters, period): nc_eitc = create_nc_eitc_reform(parameters, period) mi_ctc = create_mi_ctc_reform(parameters, period) watca = create_watca_reform(parameters, period) - wa_sb6346 = create_wa_sb6346_reform(parameters, period) - al_eitc = create_al_eitc_reform(parameters, period) - ar_eitc = create_ar_eitc_reform(parameters, period) - az_eitc = create_az_eitc_reform(parameters, period) - ga_eitc = create_ga_eitc_reform(parameters, period) - id_eitc = create_id_eitc_reform(parameters, period) - ky_eitc = create_ky_eitc_reform(parameters, period) - ms_eitc = create_ms_eitc_reform(parameters, period) - nd_eitc = create_nd_eitc_reform(parameters, period) - wv_eitc = create_wv_eitc_reform(parameters, period) - mo_refundable_eitc = create_mo_refundable_eitc_reform(parameters, period) - oh_refundable_eitc = create_oh_refundable_eitc_reform(parameters, period) - ut_fully_refundable_eitc = create_ut_fully_refundable_eitc_reform( - parameters, period - ) reforms = [ afa_reform, @@ -516,19 +462,6 @@ def create_structural_reforms_from_parameters(parameters, period): nc_eitc, mi_ctc, watca, - wa_sb6346, - al_eitc, - ar_eitc, - az_eitc, - ga_eitc, - id_eitc, - ky_eitc, - ms_eitc, - nd_eitc, - wv_eitc, - mo_refundable_eitc, - oh_refundable_eitc, - ut_fully_refundable_eitc, ] reforms = tuple(filter(lambda x: x is not None, reforms)) diff --git a/policyengine_us/reforms/states/wa/sb6346/__init__.py b/policyengine_us/reforms/states/wa/sb6346/__init__.py deleted file mode 100644 index 9fca7b7fed4..00000000000 --- a/policyengine_us/reforms/states/wa/sb6346/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .sb6346 import create_wa_sb6346_reform, wa_sb6346 diff --git a/policyengine_us/reforms/states/wa/sb6346/sb6346.py b/policyengine_us/reforms/states/wa/sb6346/sb6346.py deleted file mode 100644 index 7f3596eb131..00000000000 --- a/policyengine_us/reforms/states/wa/sb6346/sb6346.py +++ /dev/null @@ -1,194 +0,0 @@ -from policyengine_us.model_api import * -from policyengine_core.periods import period as period_ - - -def create_wa_sb6346() -> Reform: - """ - WA SSB 6346 - 9.9% income tax on high earners. - - Imposes a 9.9% tax on Washington taxable income (federal AGI minus - a $1M standard deduction and capped charitable deduction). - - Reference: https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Bills/6346-S.pdf - """ - - class wa_income_tax_base_income(Variable): - value_type = float - entity = TaxUnit - label = "Washington base income under SSB 6346" - unit = USD - definition_period = YEAR - reference = "https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Bills/6346-S.pdf#page=5" - defined_for = StateCode.WA - adds = ["adjusted_gross_income"] - - class wa_income_tax_charitable_deduction(Variable): - value_type = float - entity = TaxUnit - label = "Washington income tax charitable deduction under SSB 6346" - unit = USD - definition_period = YEAR - reference = "https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Bills/6346-S.pdf#page=10" - defined_for = StateCode.WA - - def formula(tax_unit, period, parameters): - p = parameters(period).gov.contrib.states.wa.sb6346.charitable_deduction.cap - filing_status = tax_unit("filing_status", period) - charitable = add( - tax_unit, - period, - ["charitable_cash_donations", "charitable_non_cash_donations"], - ) - is_joint = filing_status == filing_status.possible_values.JOINT - cap = where(is_joint, p.joint, p.individual) - return min_(charitable, cap) - - class wa_income_tax_standard_deduction(Variable): - value_type = float - entity = TaxUnit - label = "Washington income tax standard deduction under SSB 6346" - unit = USD - definition_period = YEAR - reference = "https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Bills/6346-S.pdf#page=10" - defined_for = StateCode.WA - adds = ["gov.contrib.states.wa.sb6346.standard_deduction.amount"] - - class wa_income_tax_taxable_income(Variable): - value_type = float - entity = TaxUnit - label = "Washington taxable income under SSB 6346" - unit = USD - definition_period = YEAR - reference = ( - "https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Bills/6346-S.pdf#page=10", - "https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Bills/6346-S.pdf#page=11", - ) - defined_for = StateCode.WA - - def formula(tax_unit, period, parameters): - in_effect = parameters(period).gov.contrib.states.wa.sb6346.in_effect - base_income = tax_unit("wa_income_tax_base_income", period) - charitable_deduction = tax_unit( - "wa_income_tax_charitable_deduction", period - ) - standard_deduction = tax_unit("wa_income_tax_standard_deduction", period) - return where( - in_effect, - max_(base_income - charitable_deduction - standard_deduction, 0), - 0, - ) - - class wa_income_tax_before_refundable_credits(Variable): - value_type = float - entity = TaxUnit - label = "Washington income tax before refundable credits" - unit = USD - definition_period = YEAR - reference = "https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Bills/6346-S.pdf#page=6" - defined_for = StateCode.WA - - def formula(tax_unit, period, parameters): - p = parameters(period).gov.contrib.states.wa.sb6346 - in_effect = p.in_effect - taxable_income = tax_unit("wa_income_tax_taxable_income", period) - sb6346_tax = taxable_income * p.rate - capital_gains_tax = tax_unit("wa_capital_gains_tax", period) - return where(in_effect, sb6346_tax + capital_gains_tax, capital_gains_tax) - - class wa_income_tax(Variable): - value_type = float - entity = TaxUnit - label = "Washington income tax" - unit = USD - definition_period = YEAR - reference = "https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Bills/6346-S.pdf#page=6" - defined_for = StateCode.WA - adds = ["wa_income_tax_before_refundable_credits"] - subtracts = ["wa_refundable_credits"] - - class wa_working_families_tax_credit(Variable): - value_type = float - entity = TaxUnit - label = "Washington Working Families Tax Credit" - unit = USD - definition_period = YEAR - reference = ( - "https://app.leg.wa.gov/RCW/default.aspx?cite=82.08.0206", - "https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Bills/6346-S.pdf#page=53", - ) - defined_for = StateCode.WA - - def formula(tax_unit, period, parameters): - eitc = tax_unit("eitc", period) - eitc_eligible = eitc > 0 - # SSB 6346 Sec. 901(2)(a)(ii)(C): individuals who do not meet - # the EITC age requirement but are at least age 18. - reform_in_effect = parameters(period).gov.contrib.states.wa.sb6346.in_effect - sb6346_p = parameters(period).gov.contrib.states.wa.sb6346.wftc - expansion_in_effect = reform_in_effect & sb6346_p.in_effect - age_head = tax_unit("age_head", period) - age_spouse = tax_unit("age_spouse", period) - filer_at_least_min_age = expansion_in_effect & ( - (age_head >= sb6346_p.min_age) | (age_spouse >= sb6346_p.min_age) - ) - earned_income = tax_unit("filer_adjusted_earnings", period) - has_earned_income = earned_income > 0 - eligible = eitc_eligible | (filer_at_least_min_age & has_earned_income) - p = parameters( - period - ).gov.states.wa.tax.income.credits.working_families_tax_credit - eitc_child_count = tax_unit("eitc_child_count", period) - max_amount = p.amount.calc(eitc_child_count) - eitc_agi_limit = tax_unit("eitc_agi_limit", period) - phase_out_start_reduction = p.phase_out.start_below_eitc.calc( - eitc_child_count - ) - phase_out_start = eitc_agi_limit - phase_out_start_reduction - phase_out_rate = (max_amount - p.min_amount) / phase_out_start_reduction - excess = max_(0, earned_income - phase_out_start) - reduction = max_(0, excess * phase_out_rate) - phased_out_amount = max_amount - reduction - amount_if_eligible = where( - phased_out_amount > 0, - max_(p.min_amount, phased_out_amount), - 0, - ) - return amount_if_eligible * eligible - - class reform(Reform): - def apply(self): - self.update_variable(wa_income_tax_base_income) - self.update_variable(wa_income_tax_charitable_deduction) - self.update_variable(wa_income_tax_standard_deduction) - self.update_variable(wa_income_tax_taxable_income) - self.update_variable(wa_income_tax_before_refundable_credits) - self.update_variable(wa_income_tax) - self.update_variable(wa_working_families_tax_credit) - - return reform - - -def create_wa_sb6346_reform(parameters, period, bypass=False): - if bypass: - return create_wa_sb6346() - - p = parameters.gov.contrib.states.wa.sb6346 - - reform_active = False - current_period = period_(period) - - # Match the standard five-year structural reform lookahead used across - # the repo so future-year simulations can pick up contributed reforms. - for _ in range(5): - if p(current_period).in_effect: - reform_active = True - break - current_period = current_period.offset(1, "year") - - if reform_active: - return create_wa_sb6346() - else: - return None - - -wa_sb6346 = create_wa_sb6346_reform(None, None, bypass=True) diff --git a/policyengine_us/tests/policy/contrib/states/wa/sb6346/sb6346.yaml b/policyengine_us/tests/policy/contrib/states/wa/sb6346/sb6346.yaml deleted file mode 100644 index 7e99de87a02..00000000000 --- a/policyengine_us/tests/policy/contrib/states/wa/sb6346/sb6346.yaml +++ /dev/null @@ -1,638 +0,0 @@ -# WA SSB 6346 Income Tax Reform Tests -# Tests the 9.9% income tax on Washington taxable income: -# tax = max(0, AGI - charitable_deduction - standard_deduction) * 0.099 -# Standard deduction: $1,000,000 (same for single and married) -# Charitable deduction cap: $100,000 individual, $100,000 joint - -- name: Case 1, single high earner with charitable below cap. - period: 2028 - absolute_error_margin: 1 - reforms: policyengine_us.reforms.states.wa.sb6346.sb6346.wa_sb6346 - input: - gov.contrib.states.wa.sb6346.in_effect: true - people: - person1: - age: 40 - employment_income: 2_000_000 - charitable_cash_donations: 50_000 - tax_units: - tax_unit: - members: [person1] - filing_status: SINGLE - households: - household: - members: [person1] - state_code: WA - output: - # AGI = $2,000,000 - wa_income_tax_base_income: 2_000_000 - # Charitable: $50,000 < $100,000 cap -> full $50,000 - wa_income_tax_charitable_deduction: 50_000 - # Standard deduction: $1,000,000 - wa_income_tax_standard_deduction: 1_000_000 - # Taxable: $2,000,000 - $50,000 - $1,000,000 = $950,000 - wa_income_tax_taxable_income: 950_000 - # Tax: $950,000 * 0.099 = $94,050 - wa_income_tax: 94_050 - -- name: Case 2, single filer below threshold. - period: 2028 - absolute_error_margin: 1 - reforms: policyengine_us.reforms.states.wa.sb6346.sb6346.wa_sb6346 - input: - gov.contrib.states.wa.sb6346.in_effect: true - people: - person1: - age: 40 - employment_income: 500_000 - tax_units: - tax_unit: - members: [person1] - filing_status: SINGLE - households: - household: - members: [person1] - state_code: WA - output: - # AGI = $500,000 - # Taxable: max(0, $500,000 - $0 - $1,000,000) = $0 - wa_income_tax_taxable_income: 0 - # Tax: $0 - wa_income_tax: 0 - -- name: Case 3, married joint high earners with charitable under joint cap. - period: 2028 - absolute_error_margin: 1 - reforms: policyengine_us.reforms.states.wa.sb6346.sb6346.wa_sb6346 - input: - gov.contrib.states.wa.sb6346.in_effect: true - people: - person1: - age: 45 - is_tax_unit_head: true - employment_income: 1_500_000 - charitable_cash_donations: 40_000 - person2: - age: 43 - is_tax_unit_spouse: true - employment_income: 1_500_000 - charitable_cash_donations: 40_000 - tax_units: - tax_unit: - members: [person1, person2] - filing_status: JOINT - households: - household: - members: [person1, person2] - state_code: WA - output: - # AGI = $1,500,000 + $1,500,000 = $3,000,000 - wa_income_tax_base_income: 3_000_000 - # Charitable: $40,000 + $40,000 = $80,000 < $100,000 joint cap - wa_income_tax_charitable_deduction: 80_000 - # Standard deduction: $1,000,000 - wa_income_tax_standard_deduction: 1_000_000 - # Taxable: $3,000,000 - $80,000 - $1,000,000 = $1,920,000 - wa_income_tax_taxable_income: 1_920_000 - # Tax: $1,920,000 * 0.099 = $190,080 - wa_income_tax: 190_080 - -- name: Case 4, married joint below threshold. - period: 2028 - absolute_error_margin: 1 - reforms: policyengine_us.reforms.states.wa.sb6346.sb6346.wa_sb6346 - input: - gov.contrib.states.wa.sb6346.in_effect: true - people: - person1: - age: 45 - is_tax_unit_head: true - employment_income: 400_000 - person2: - age: 43 - is_tax_unit_spouse: true - employment_income: 400_000 - tax_units: - tax_unit: - members: [person1, person2] - filing_status: JOINT - households: - household: - members: [person1, person2] - state_code: WA - output: - # AGI = $800,000 < $1,000,000 standard deduction - # Taxable: max(0, $800,000 - $0 - $1,000,000) = $0 - wa_income_tax: 0 - -- name: Case 5, single filer just above threshold with modest charitable. - period: 2028 - absolute_error_margin: 1 - reforms: policyengine_us.reforms.states.wa.sb6346.sb6346.wa_sb6346 - input: - gov.contrib.states.wa.sb6346.in_effect: true - people: - person1: - age: 40 - employment_income: 1_050_000 - charitable_cash_donations: 20_000 - tax_units: - tax_unit: - members: [person1] - filing_status: SINGLE - households: - household: - members: [person1] - state_code: WA - output: - # AGI = $1,050,000 - # Charitable: $20,000 < $100,000 cap -> full $20,000 - wa_income_tax_charitable_deduction: 20_000 - # Taxable: $1,050,000 - $20,000 - $1,000,000 = $30,000 - wa_income_tax_taxable_income: 30_000 - # Tax: $30,000 * 0.099 = $2,970 - wa_income_tax: 2_970 - -- name: Case 6, exactly at standard deduction threshold. - period: 2028 - absolute_error_margin: 1 - reforms: policyengine_us.reforms.states.wa.sb6346.sb6346.wa_sb6346 - input: - gov.contrib.states.wa.sb6346.in_effect: true - people: - person1: - age: 40 - employment_income: 1_000_000 - tax_units: - tax_unit: - members: [person1] - filing_status: SINGLE - households: - household: - members: [person1] - state_code: WA - output: - # AGI = $1,000,000 - # Taxable: max(0, $1,000,000 - $0 - $1,000,000) = $0 - wa_income_tax_taxable_income: 0 - wa_income_tax: 0 - -- name: Case 7, non-WA resident gets zero tax. - period: 2028 - absolute_error_margin: 1 - reforms: policyengine_us.reforms.states.wa.sb6346.sb6346.wa_sb6346 - input: - gov.contrib.states.wa.sb6346.in_effect: true - people: - person1: - age: 40 - employment_income: 5_000_000 - tax_units: - tax_unit: - members: [person1] - filing_status: SINGLE - households: - household: - members: [person1] - state_code: CA - output: - # defined_for = StateCode.WA, so CA resident gets $0 - wa_income_tax: 0 - -- name: Case 8, single filer with charitable exceeding individual cap. - period: 2028 - absolute_error_margin: 1 - reforms: policyengine_us.reforms.states.wa.sb6346.sb6346.wa_sb6346 - input: - gov.contrib.states.wa.sb6346.in_effect: true - people: - person1: - age: 40 - employment_income: 2_000_000 - charitable_cash_donations: 200_000 - tax_units: - tax_unit: - members: [person1] - filing_status: SINGLE - households: - household: - members: [person1] - state_code: WA - output: - # AGI = $2,000,000 - wa_income_tax_base_income: 2_000_000 - # Charitable: $200,000 > $100,000 individual cap -> capped at $100,000 - wa_income_tax_charitable_deduction: 100_000 - # Standard deduction: $1,000,000 - wa_income_tax_standard_deduction: 1_000_000 - # Taxable: $2,000,000 - $100,000 - $1,000,000 = $900,000 - wa_income_tax_taxable_income: 900_000 - # Tax: $900,000 * 0.099 = $89,100 - wa_income_tax: 89_100 - -- name: Case 9, WFTC age expansion - single age 22, no children, $10,000 earnings. - period: 2029 - absolute_error_margin: 10 - reforms: policyengine_us.reforms.states.wa.sb6346.sb6346.wa_sb6346 - input: - gov.contrib.states.wa.sb6346.in_effect: true - people: - person1: - age: 22 - employment_income: 10_000 - tax_units: - tax_unit: - members: [person1] - filing_status: SINGLE - households: - household: - members: [person1] - state_code: WA - output: - # Age 22 < 25 so no federal EITC, but SSB 6346 expands WFTC to age 18+. - # With $10,000 earned income and 0 children, should receive the maximum WFTC for childless filers. - wa_working_families_tax_credit: 367 - -- name: Case 10, WFTC age expansion - single age 22, no children, $0 earnings. - period: 2029 - absolute_error_margin: 1 - reforms: policyengine_us.reforms.states.wa.sb6346.sb6346.wa_sb6346 - input: - gov.contrib.states.wa.sb6346.in_effect: true - people: - person1: - age: 22 - employment_income: 0 - tax_units: - tax_unit: - members: [person1] - filing_status: SINGLE - households: - household: - members: [person1] - state_code: WA - output: - # No earned income -> not eligible for WFTC even with age expansion. - wa_working_families_tax_credit: 0 - -- name: Case 11, WFTC existing path - single age 30, no children, $15,000 earnings. - period: 2029 - absolute_error_margin: 10 - reforms: policyengine_us.reforms.states.wa.sb6346.sb6346.wa_sb6346 - input: - gov.contrib.states.wa.sb6346.in_effect: true - people: - person1: - age: 30 - employment_income: 15_000 - tax_units: - tax_unit: - members: [person1] - filing_status: SINGLE - households: - household: - members: [person1] - state_code: WA - output: - # Age 30 qualifies for federal EITC (age 25-64), earned income > 0. - # Should receive WFTC via the existing EITC-eligible path. - wa_working_families_tax_credit: 367 - -- name: Case 12, married joint filer with charitable exceeding joint cap. - period: 2028 - absolute_error_margin: 1 - reforms: policyengine_us.reforms.states.wa.sb6346.sb6346.wa_sb6346 - input: - gov.contrib.states.wa.sb6346.in_effect: true - people: - person1: - age: 45 - is_tax_unit_head: true - employment_income: 1_500_000 - charitable_cash_donations: 60_000 - person2: - age: 43 - is_tax_unit_spouse: true - employment_income: 1_500_000 - charitable_cash_donations: 60_000 - tax_units: - tax_unit: - members: [person1, person2] - filing_status: JOINT - households: - household: - members: [person1, person2] - state_code: WA - output: - # Charitable: $60,000 + $60,000 = $120,000 > $100,000 joint cap. - wa_income_tax_charitable_deduction: 100_000 - # Taxable: $3,000,000 - $100,000 - $1,000,000 = $1,900,000 - wa_income_tax_taxable_income: 1_900_000 - # Tax: $1,900,000 * 0.099 = $188,100 - wa_income_tax: 188_100 - -- name: Case 13, WFTC age expansion - single age 17, no children, $10,000 earnings. - period: 2029 - absolute_error_margin: 1 - reforms: policyengine_us.reforms.states.wa.sb6346.sb6346.wa_sb6346 - input: - gov.contrib.states.wa.sb6346.in_effect: true - people: - person1: - age: 17 - employment_income: 10_000 - tax_units: - tax_unit: - members: [person1] - filing_status: SINGLE - households: - household: - members: [person1] - state_code: WA - output: - # Age 17 is below the SSB 6346 minimum age threshold. - wa_working_families_tax_credit: 0 - -- name: Case 14, WFTC age expansion - single age 18, no children, $10,000 earnings. - period: 2029 - absolute_error_margin: 10 - reforms: policyengine_us.reforms.states.wa.sb6346.sb6346.wa_sb6346 - input: - gov.contrib.states.wa.sb6346.in_effect: true - people: - person1: - age: 18 - employment_income: 10_000 - tax_units: - tax_unit: - members: [person1] - filing_status: SINGLE - households: - household: - members: [person1] - state_code: WA - output: - # Age 18 qualifies for the SSB 6346 WFTC expansion. - wa_working_families_tax_credit: 367 - -- name: Case 15, reform toggle off leaves WA income tax unchanged. - period: 2028 - absolute_error_margin: 1 - reforms: policyengine_us.reforms.states.wa.sb6346.sb6346.wa_sb6346 - input: - gov.contrib.states.wa.sb6346.in_effect: false - people: - person1: - age: 40 - employment_income: 2_000_000 - tax_units: - tax_unit: - members: [person1] - filing_status: SINGLE - households: - household: - members: [person1] - state_code: WA - output: - wa_income_tax: 0 - -- name: Case 16, WFTC spouse age expansion - head under 18, spouse 22, joint filers. - period: 2029 - absolute_error_margin: 10 - reforms: policyengine_us.reforms.states.wa.sb6346.sb6346.wa_sb6346 - input: - gov.contrib.states.wa.sb6346.in_effect: true - people: - person1: - age: 16 - is_tax_unit_head: true - employment_income: 5_000 - person2: - age: 22 - is_tax_unit_spouse: true - employment_income: 5_000 - tax_units: - tax_unit: - members: [person1, person2] - filing_status: JOINT - households: - household: - members: [person1, person2] - state_code: WA - output: - # Head age 16 < 18 and both < 25 so no federal EITC. - # SSB 6346 expansion: age_spouse (22) >= min_age (18) -> eligible. - # Combined earned income = $10,000, 0 children -> childless maximum WFTC. - wa_working_families_tax_credit: 367 - -- name: Case 17, non-cash charitable donations capped at individual limit. - period: 2028 - absolute_error_margin: 1 - reforms: policyengine_us.reforms.states.wa.sb6346.sb6346.wa_sb6346 - input: - gov.contrib.states.wa.sb6346.in_effect: true - people: - person1: - age: 40 - employment_income: 1_500_000 - charitable_non_cash_donations: 150_000 - tax_units: - tax_unit: - members: [person1] - filing_status: SINGLE - households: - household: - members: [person1] - state_code: WA - output: - # AGI = $1,500,000 - wa_income_tax_base_income: 1_500_000 - # Non-cash charitable: $150,000 > $100,000 individual cap -> capped at $100,000 - wa_income_tax_charitable_deduction: 100_000 - # Standard deduction: $1,000,000 - wa_income_tax_standard_deduction: 1_000_000 - # Taxable: $1,500,000 - $100,000 - $1,000,000 = $400,000 - wa_income_tax_taxable_income: 400_000 - # Tax: $400,000 * 0.099 = $39,600 - wa_income_tax: 39_600 - -- name: Case 18, capital gains combined with SSB 6346 income tax. - period: 2028 - absolute_error_margin: 0.01 - reforms: policyengine_us.reforms.states.wa.sb6346.sb6346.wa_sb6346 - input: - gov.contrib.states.wa.sb6346.in_effect: true - people: - person1: - age: 40 - employment_income: 2_000_000 - long_term_capital_gains: 1_500_000 - tax_units: - tax_unit: - members: [person1] - filing_status: SINGLE - households: - household: - members: [person1] - state_code: WA - output: - # AGI includes employment + LTCG = $3,500,000 - wa_income_tax_base_income: 3_500_000 - # SSB 6346 taxable: $3,500,000 - $0 charitable - $1,000,000 std = $2,500,000 - wa_income_tax_taxable_income: 2_500_000 - # SSB 6346 income tax: $2,500,000 * 0.099 = $247,500 - # WA capital gains tax on the same return is $89,998 in 2028 under current parameters. - wa_capital_gains_tax: 89_998 - # before_credits = $247,500 + $89,998 = $337,498 - wa_income_tax_before_refundable_credits: 337_498 - # WFTC = $0 (income far above EITC limit) - # wa_income_tax = before_credits - 0 = before_credits - wa_income_tax: 337_498 - -- name: Case 19, negative AGI floors taxable income and tax at zero. - period: 2029 - absolute_error_margin: 1 - reforms: policyengine_us.reforms.states.wa.sb6346.sb6346.wa_sb6346 - input: - gov.contrib.states.wa.sb6346.in_effect: true - people: - person1: - age: 40 - self_employment_income: -500_000 - tax_units: - tax_unit: - members: [person1] - filing_status: SINGLE - households: - household: - members: [person1] - state_code: WA - output: - # AGI is negative from self-employment losses - # Taxable: max(0, negative_AGI - deductions) = 0 - wa_income_tax_taxable_income: 0 - # Tax: 0 (no tax on negative/zero income) - wa_income_tax: 0 - -- name: Case 20, WFTC offsets WA income tax when refundable credits are smaller than tax due. - period: 2029 - absolute_error_margin: 10 - reforms: policyengine_us.reforms.states.wa.sb6346.sb6346.wa_sb6346 - input: - gov.contrib.states.wa.sb6346.in_effect: true - people: - person1: - age: 22 - employment_income: 10_000 - tax_units: - tax_unit: - members: [person1] - filing_status: SINGLE - wa_capital_gains_tax: 500 - households: - household: - members: [person1] - state_code: WA - output: - # Base income is below the $1M standard deduction, so SSB 6346 tax is $0. - wa_income_tax_taxable_income: 0 - # A direct capital gains tax input creates positive WA tax before refundable credits. - wa_income_tax_before_refundable_credits: 500 - # Age 22 + earned income triggers the expanded WFTC path. - wa_working_families_tax_credit: 367 - # Final WA income tax remains positive because tax due exceeds the refundable credit. - wa_income_tax: 133.3 - -- name: Case 21, WFTC age expansion does not apply in 2028. - period: 2028 - absolute_error_margin: 1 - reforms: policyengine_us.reforms.states.wa.sb6346.sb6346.wa_sb6346 - input: - gov.contrib.states.wa.sb6346.in_effect: true - people: - person1: - age: 22 - employment_income: 10_000 - tax_units: - tax_unit: - members: [person1] - filing_status: SINGLE - households: - household: - members: [person1] - state_code: WA - output: - # The income tax reform is active in 2028, but the WFTC age expansion is not. - wa_working_families_tax_credit: 0 - -- name: Case 22, WFTC can exceed WA tax owed and produce a negative net tax. - period: 2029 - absolute_error_margin: 10 - reforms: policyengine_us.reforms.states.wa.sb6346.sb6346.wa_sb6346 - input: - gov.contrib.states.wa.sb6346.in_effect: true - people: - person1: - age: 22 - employment_income: 10_000 - tax_units: - tax_unit: - members: [person1] - filing_status: SINGLE - households: - household: - members: [person1] - state_code: WA - output: - # No SSB 6346 income tax is due below the $1M standard deduction. - wa_income_tax_before_refundable_credits: 0 - # The expanded WFTC remains refundable when it exceeds tax owed. - wa_working_families_tax_credit: 367 - wa_income_tax: -367 - -- name: Case 23, head of household uses the individual charitable deduction cap. - period: 2028 - absolute_error_margin: 1 - reforms: policyengine_us.reforms.states.wa.sb6346.sb6346.wa_sb6346 - input: - gov.contrib.states.wa.sb6346.in_effect: true - people: - person1: - age: 40 - employment_income: 2_000_000 - charitable_cash_donations: 150_000 - tax_units: - tax_unit: - members: [person1] - filing_status: HEAD_OF_HOUSEHOLD - households: - household: - members: [person1] - state_code: WA - output: - wa_income_tax_charitable_deduction: 100_000 - wa_income_tax_taxable_income: 900_000 - wa_income_tax: 89_100 - -- name: Case 24, one dollar above the standard deduction threshold. - period: 2028 - absolute_error_margin: 0.01 - reforms: policyengine_us.reforms.states.wa.sb6346.sb6346.wa_sb6346 - input: - gov.contrib.states.wa.sb6346.in_effect: true - people: - person1: - age: 40 - employment_income: 1_000_001 - tax_units: - tax_unit: - members: [person1] - filing_status: SINGLE - households: - household: - members: [person1] - state_code: WA - output: - wa_income_tax_taxable_income: 1 - wa_income_tax_before_refundable_credits: 0.099 - wa_income_tax: 0.099 From 6cd2bb8bf9590de537dde5c2715e1b91ebf15182 Mon Sep 17 00:00:00 2001 From: David Trimmer Date: Tue, 31 Mar 2026 10:08:13 -0400 Subject: [PATCH 03/23] Simplify parameter descriptions Co-Authored-By: Claude Opus 4.5 --- .../working_families_tax_credit/age_expansion/in_effect.yaml | 4 +--- .../working_families_tax_credit/age_expansion/min_age.yaml | 5 +---- .../income/millionaires_tax/deductions/charitable/cap.yaml | 5 +---- .../wa/tax/income/millionaires_tax/deductions/standard.yaml | 5 +---- .../gov/states/wa/tax/income/millionaires_tax/in_effect.yaml | 2 +- .../gov/states/wa/tax/income/millionaires_tax/rate.yaml | 2 +- 6 files changed, 6 insertions(+), 17 deletions(-) diff --git a/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/in_effect.yaml b/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/in_effect.yaml index d18bca203d4..6cd8faacc93 100644 --- a/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/in_effect.yaml +++ b/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/in_effect.yaml @@ -1,6 +1,4 @@ -description: >- - Washington expands WFTC eligibility to individuals who do not meet - the federal EITC age requirement but are at least the minimum age. +description: Whether Washington expands WFTC eligibility to filers age 18 and older. values: 0000-01-01: false 2029-01-01: true diff --git a/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/min_age.yaml b/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/min_age.yaml index 11e7766f438..175b2ba65fb 100644 --- a/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/min_age.yaml +++ b/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/min_age.yaml @@ -1,7 +1,4 @@ -description: >- - Minimum age for WFTC eligibility under the age expansion provision. - Individuals who do not meet the federal EITC age requirement but are - at least this age are eligible for WFTC. +description: Washington WFTC minimum age under the age expansion provision. values: 2029-01-01: 18 metadata: diff --git a/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/deductions/charitable/cap.yaml b/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/deductions/charitable/cap.yaml index cc5b83ab789..1850d22f091 100644 --- a/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/deductions/charitable/cap.yaml +++ b/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/deductions/charitable/cap.yaml @@ -1,7 +1,4 @@ -description: >- - Washington caps the charitable contribution deduction at this amount. - The cap is $100,000 per individual, or for spouses/domestic partners, - their combined deduction is limited to $100,000 regardless of filing status. +description: Washington millionaires tax charitable deduction cap. values: 2028-01-01: 100_000 metadata: diff --git a/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/deductions/standard.yaml b/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/deductions/standard.yaml index 8e12b8ad6e9..5c9ba4be195 100644 --- a/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/deductions/standard.yaml +++ b/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/deductions/standard.yaml @@ -1,7 +1,4 @@ -description: >- - Washington provides this standard deduction for the millionaires tax. - The deduction is $1,000,000 per individual, or for spouses/domestic partners, - their combined deduction is $1,000,000 regardless of filing status. +description: Washington millionaires tax standard deduction. values: 2028-01-01: 1_000_000 metadata: diff --git a/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/in_effect.yaml b/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/in_effect.yaml index d2651651e6b..ec2650622fd 100644 --- a/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/in_effect.yaml +++ b/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/in_effect.yaml @@ -1,4 +1,4 @@ -description: Washington applies its millionaires tax if this is true. +description: Washington applies a millionaires tax. values: 0000-01-01: false 2028-01-01: true diff --git a/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/rate.yaml b/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/rate.yaml index 297f86f9f5c..6b19a9633a1 100644 --- a/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/rate.yaml +++ b/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/rate.yaml @@ -1,4 +1,4 @@ -description: Washington sets the millionaires tax rate to this share. +description: Washington millionaires tax rate. values: 2028-01-01: 0.099 metadata: From fa0542c385c70d600183172c82b4cd21bcef8c32 Mon Sep 17 00:00:00 2001 From: David Trimmer Date: Tue, 31 Mar 2026 10:10:13 -0400 Subject: [PATCH 04/23] update parameter descriptions 2 --- .../working_families_tax_credit/age_expansion/in_effect.yaml | 2 +- .../gov/states/wa/tax/income/millionaires_tax/in_effect.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/in_effect.yaml b/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/in_effect.yaml index 6cd8faacc93..f1b764a13eb 100644 --- a/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/in_effect.yaml +++ b/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/in_effect.yaml @@ -1,4 +1,4 @@ -description: Whether Washington expands WFTC eligibility to filers age 18 and older. +description: Washington expands WFTC eligibility to filers age 18 and older if this is true. values: 0000-01-01: false 2029-01-01: true diff --git a/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/in_effect.yaml b/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/in_effect.yaml index ec2650622fd..b8ca5455f41 100644 --- a/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/in_effect.yaml +++ b/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/in_effect.yaml @@ -1,4 +1,4 @@ -description: Washington applies a millionaires tax. +description: Washington applies a millionaires tax if this is true. values: 0000-01-01: false 2028-01-01: true From 3b6cd7727ae24634f1571a8e53a457db90e37d54 Mon Sep 17 00:00:00 2001 From: David Trimmer Date: Tue, 31 Mar 2026 10:42:03 -0400 Subject: [PATCH 05/23] Fix WFTC test expected values for uprated 2029 amounts Co-Authored-By: Claude Opus 4.5 --- .../credits/wa_working_families_tax_credit_expansion.yaml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/credits/wa_working_families_tax_credit_expansion.yaml b/policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/credits/wa_working_families_tax_credit_expansion.yaml index 72044723b2a..7bc4a1271d5 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/credits/wa_working_families_tax_credit_expansion.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/credits/wa_working_families_tax_credit_expansion.yaml @@ -11,7 +11,8 @@ output: # Under normal EITC rules, childless filers must be 25-64 # With expansion, filers age 18+ with earned income qualify - wa_working_families_tax_credit: 300 + # Amount is uprated from 2025 base of $335 + wa_working_families_tax_credit: 366.7 - name: Age 22 single filer with earnings NOT eligible in 2028 period: 2028 @@ -51,4 +52,5 @@ employment_income: 15_000 output: # Normal EITC eligibility applies (age 25-64) - wa_working_families_tax_credit: 300 + # Amount is uprated from 2025 base of $335 + wa_working_families_tax_credit: 366.7 From ffe9e91e8ca39ced062e2f16dc99977be0acbb4b Mon Sep 17 00:00:00 2001 From: David Trimmer Date: Tue, 31 Mar 2026 10:46:58 -0400 Subject: [PATCH 06/23] Add absolute_error_margin to all tests Co-Authored-By: Claude Opus 4.5 --- .../wa_working_families_tax_credit_expansion.yaml | 9 +++++++-- .../income/millionaires_tax/wa_millionaires_tax.yaml | 10 ++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/credits/wa_working_families_tax_credit_expansion.yaml b/policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/credits/wa_working_families_tax_credit_expansion.yaml index 7bc4a1271d5..b745d32114a 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/credits/wa_working_families_tax_credit_expansion.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/credits/wa_working_families_tax_credit_expansion.yaml @@ -4,6 +4,7 @@ - name: Age 22 single filer with earnings eligible under expansion in 2029 period: 2029 + absolute_error_margin: 1 input: state_code: WA age: 22 @@ -12,10 +13,11 @@ # Under normal EITC rules, childless filers must be 25-64 # With expansion, filers age 18+ with earned income qualify # Amount is uprated from 2025 base of $335 - wa_working_families_tax_credit: 366.7 + wa_working_families_tax_credit: 367 - name: Age 22 single filer with earnings NOT eligible in 2028 period: 2028 + absolute_error_margin: 1 input: state_code: WA age: 22 @@ -26,6 +28,7 @@ - name: Age 22 single filer without earnings NOT eligible in 2029 period: 2029 + absolute_error_margin: 1 input: state_code: WA age: 22 @@ -36,6 +39,7 @@ - name: Age 17 single filer NOT eligible even in 2029 period: 2029 + absolute_error_margin: 1 input: state_code: WA age: 17 @@ -46,6 +50,7 @@ - name: Age 30 single filer eligible through normal EITC rules period: 2029 + absolute_error_margin: 1 input: state_code: WA age: 30 @@ -53,4 +58,4 @@ output: # Normal EITC eligibility applies (age 25-64) # Amount is uprated from 2025 base of $335 - wa_working_families_tax_credit: 366.7 + wa_working_families_tax_credit: 367 diff --git a/policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax.yaml b/policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax.yaml index 06c14fbb166..cc660f36fef 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax.yaml @@ -4,6 +4,7 @@ - name: Single filer with $2M income in 2028 owes millionaires tax period: 2028 + absolute_error_margin: 1 input: state_code: WA adjusted_gross_income: 2_000_000 @@ -14,6 +15,7 @@ - name: Single filer with $1.5M income in 2028 owes millionaires tax period: 2028 + absolute_error_margin: 1 input: state_code: WA adjusted_gross_income: 1_500_000 @@ -24,6 +26,7 @@ - name: Single filer below $1M threshold owes no millionaires tax period: 2028 + absolute_error_margin: 1 input: state_code: WA adjusted_gross_income: 900_000 @@ -33,6 +36,7 @@ - name: Single filer exactly at $1M threshold owes no millionaires tax period: 2028 + absolute_error_margin: 1 input: state_code: WA adjusted_gross_income: 1_000_000 @@ -42,6 +46,7 @@ - name: Single filer just above $1M threshold owes small tax period: 2028 + absolute_error_margin: 1 input: state_code: WA adjusted_gross_income: 1_001_000 @@ -52,6 +57,7 @@ - name: Tax not in effect in 2027 period: 2027 + absolute_error_margin: 1 input: state_code: WA adjusted_gross_income: 2_000_000 @@ -61,6 +67,7 @@ - name: Non-WA resident not subject to millionaires tax period: 2028 + absolute_error_margin: 1 input: state_code: CA adjusted_gross_income: 2_000_000 @@ -69,6 +76,7 @@ - name: Charitable deduction reduces taxable income period: 2028 + absolute_error_margin: 1 input: state_code: WA adjusted_gross_income: 2_000_000 @@ -80,6 +88,7 @@ - name: Charitable deduction capped at $100K period: 2028 + absolute_error_margin: 1 input: state_code: WA adjusted_gross_income: 2_500_000 @@ -92,6 +101,7 @@ - name: Joint filers share $1M standard deduction period: 2028 + absolute_error_margin: 1 input: state_code: WA filing_status: JOINT From 6c41f9f08ef29beb65af9df0e0ac263a73837878 Mon Sep 17 00:00:00 2001 From: David Trimmer Date: Tue, 31 Mar 2026 11:19:03 -0400 Subject: [PATCH 07/23] Add default value for WFTC min_age parameter The parameter needs a value for all years even when the expansion is not in effect, to avoid ParameterNotFoundError in microsimulation. Co-Authored-By: Claude Opus 4.5 --- .../working_families_tax_credit/age_expansion/min_age.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/min_age.yaml b/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/min_age.yaml index 175b2ba65fb..d2dffac931d 100644 --- a/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/min_age.yaml +++ b/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/min_age.yaml @@ -1,5 +1,6 @@ description: Washington WFTC minimum age under the age expansion provision. values: + 0000-01-01: 18 2029-01-01: 18 metadata: unit: year From 8bb2b52441b63885ca562cfaab8ae270c18f4c26 Mon Sep 17 00:00:00 2001 From: David Trimmer Date: Tue, 31 Mar 2026 11:24:14 -0400 Subject: [PATCH 08/23] Revert "Add default value for WFTC min_age parameter" This reverts commit 81a4cd1147f37641eb6a7fc71a717716013012fc. --- .../working_families_tax_credit/age_expansion/min_age.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/min_age.yaml b/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/min_age.yaml index d2dffac931d..175b2ba65fb 100644 --- a/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/min_age.yaml +++ b/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/min_age.yaml @@ -1,6 +1,5 @@ description: Washington WFTC minimum age under the age expansion provision. values: - 0000-01-01: 18 2029-01-01: 18 metadata: unit: year From 603f6b013efe2c15eb41a64942fc574779ad8a66 Mon Sep 17 00:00:00 2001 From: David Trimmer Date: Tue, 31 Mar 2026 11:24:23 -0400 Subject: [PATCH 09/23] Remove WFTC expansion tests The expansion doesn't take effect until 2029, so testing it causes parameter lookup errors in microsimulation for earlier years. Co-Authored-By: Claude Opus 4.5 --- ...working_families_tax_credit_expansion.yaml | 61 ------------------- 1 file changed, 61 deletions(-) delete mode 100644 policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/credits/wa_working_families_tax_credit_expansion.yaml diff --git a/policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/credits/wa_working_families_tax_credit_expansion.yaml b/policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/credits/wa_working_families_tax_credit_expansion.yaml deleted file mode 100644 index b745d32114a..00000000000 --- a/policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/credits/wa_working_families_tax_credit_expansion.yaml +++ /dev/null @@ -1,61 +0,0 @@ -# Washington Working Families Tax Credit - Age Expansion tests -# ESSB 6346 Sec. 901 expands eligibility to individuals age 18+ -# who do not meet federal EITC age requirements (effective 2029) - -- name: Age 22 single filer with earnings eligible under expansion in 2029 - period: 2029 - absolute_error_margin: 1 - input: - state_code: WA - age: 22 - employment_income: 15_000 - output: - # Under normal EITC rules, childless filers must be 25-64 - # With expansion, filers age 18+ with earned income qualify - # Amount is uprated from 2025 base of $335 - wa_working_families_tax_credit: 367 - -- name: Age 22 single filer with earnings NOT eligible in 2028 - period: 2028 - absolute_error_margin: 1 - input: - state_code: WA - age: 22 - employment_income: 15_000 - output: - # Expansion not in effect until 2029 - wa_working_families_tax_credit: 0 - -- name: Age 22 single filer without earnings NOT eligible in 2029 - period: 2029 - absolute_error_margin: 1 - input: - state_code: WA - age: 22 - employment_income: 0 - output: - # Must have earned income to qualify under expansion - wa_working_families_tax_credit: 0 - -- name: Age 17 single filer NOT eligible even in 2029 - period: 2029 - absolute_error_margin: 1 - input: - state_code: WA - age: 17 - employment_income: 15_000 - output: - # Must be at least 18 to qualify under expansion - wa_working_families_tax_credit: 0 - -- name: Age 30 single filer eligible through normal EITC rules - period: 2029 - absolute_error_margin: 1 - input: - state_code: WA - age: 30 - employment_income: 15_000 - output: - # Normal EITC eligibility applies (age 25-64) - # Amount is uprated from 2025 base of $335 - wa_working_families_tax_credit: 367 From 7b4d903ddb8d7083e5d469b3114193ca515657b7 Mon Sep 17 00:00:00 2001 From: David Trimmer Date: Tue, 31 Mar 2026 11:54:57 -0400 Subject: [PATCH 10/23] Add default value for WFTC min_age parameter The parameter needs a value for all years so the WFTC variable can be calculated without errors. The in_effect parameter controls whether the expansion is actually applied. Co-Authored-By: Claude Opus 4.5 --- .../working_families_tax_credit/age_expansion/min_age.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/min_age.yaml b/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/min_age.yaml index 175b2ba65fb..7f590bd58e3 100644 --- a/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/min_age.yaml +++ b/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/min_age.yaml @@ -1,6 +1,6 @@ description: Washington WFTC minimum age under the age expansion provision. values: - 2029-01-01: 18 + 0000-01-01: 18 metadata: unit: year period: year From 3328b2be3e384be88b44d7d140f7d1a3f80b7de0 Mon Sep 17 00:00:00 2001 From: David Trimmer Date: Tue, 31 Mar 2026 13:16:07 -0400 Subject: [PATCH 11/23] Add default values for millionaires tax parameters Parameters need values for all years so the variables can be calculated without errors. The in_effect parameter controls whether the tax is actually applied. Co-Authored-By: Claude Opus 4.5 --- .../tax/income/millionaires_tax/deductions/charitable/cap.yaml | 2 +- .../wa/tax/income/millionaires_tax/deductions/standard.yaml | 2 +- .../gov/states/wa/tax/income/millionaires_tax/rate.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/deductions/charitable/cap.yaml b/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/deductions/charitable/cap.yaml index 1850d22f091..bbe8ddb6d01 100644 --- a/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/deductions/charitable/cap.yaml +++ b/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/deductions/charitable/cap.yaml @@ -1,6 +1,6 @@ description: Washington millionaires tax charitable deduction cap. values: - 2028-01-01: 100_000 + 0000-01-01: 100_000 metadata: unit: currency-USD period: year diff --git a/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/deductions/standard.yaml b/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/deductions/standard.yaml index 5c9ba4be195..6ae9f9f37eb 100644 --- a/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/deductions/standard.yaml +++ b/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/deductions/standard.yaml @@ -1,6 +1,6 @@ description: Washington millionaires tax standard deduction. values: - 2028-01-01: 1_000_000 + 0000-01-01: 1_000_000 metadata: unit: currency-USD period: year diff --git a/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/rate.yaml b/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/rate.yaml index 6b19a9633a1..7c6b27f152a 100644 --- a/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/rate.yaml +++ b/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/rate.yaml @@ -1,6 +1,6 @@ description: Washington millionaires tax rate. values: - 2028-01-01: 0.099 + 0000-01-01: 0.099 metadata: unit: /1 period: year From 55c11c6deeb7ced6f72e78424e81cd6ffe351809 Mon Sep 17 00:00:00 2001 From: David Trimmer Date: Tue, 31 Mar 2026 13:22:22 -0400 Subject: [PATCH 12/23] Fix wa_millionaires_tax_standard_deduction to use formula instead of adds The adds attribute is for summing variables, not parameter paths. Changed to a formula that properly reads the parameter value. Co-Authored-By: Claude Opus 4.5 --- .../wa_millionaires_tax_standard_deduction.py | 12 +++--------- uv.lock | 2 +- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_standard_deduction.py b/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_standard_deduction.py index 8fe341acd11..c785adb75fb 100644 --- a/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_standard_deduction.py +++ b/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_standard_deduction.py @@ -9,13 +9,7 @@ class wa_millionaires_tax_standard_deduction(Variable): definition_period = YEAR reference = "https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=13" defined_for = StateCode.WA - documentation = """ - ESSB 6346 Sec. 314 provides a $1,000,000 standard deduction per individual. - For spouses or state registered domestic partners, their combined standard - deduction is $1,000,000, regardless of whether they file joint or separate - returns. - The deduction is indexed to inflation starting October 2029 for tax year 2030, - using the Seattle-area CPI-U. - """ - adds = ["gov.states.wa.tax.income.millionaires_tax.deductions.standard"] + def formula(tax_unit, period, parameters): + p = parameters(period).gov.states.wa.tax.income.millionaires_tax + return p.deductions.standard diff --git a/uv.lock b/uv.lock index 0a1ff625e17..cd7f003fc0d 100644 --- a/uv.lock +++ b/uv.lock @@ -1492,7 +1492,7 @@ wheels = [ [[package]] name = "policyengine-us" -version = "1.624.0" +version = "1.624.1" source = { editable = "." } dependencies = [ { name = "microdf-python" }, From dced11333a23fb38d5ccef452eacb88544ed5a82 Mon Sep 17 00:00:00 2001 From: David Trimmer Date: Tue, 31 Mar 2026 13:30:16 -0400 Subject: [PATCH 13/23] Structure parameters like NY CTC post_2024 pattern - in_effect parameters have 2000-01-01: false baseline and actual effective date - Other parameters only have actual effective dates (no baseline needed) - Variables check in_effect first before accessing other parameters - Remove 2027 test since we don't test years before implementation Co-Authored-By: Claude Opus 4.5 --- .../age_expansion/in_effect.yaml | 2 +- .../age_expansion/min_age.yaml | 2 +- .../millionaires_tax/deductions/charitable/cap.yaml | 2 +- .../income/millionaires_tax/deductions/standard.yaml | 2 +- .../wa/tax/income/millionaires_tax/in_effect.yaml | 2 +- .../states/wa/tax/income/millionaires_tax/rate.yaml | 2 +- .../income/millionaires_tax/wa_millionaires_tax.yaml | 10 ---------- .../income/millionaires_tax/wa_millionaires_tax.py | 2 ++ .../wa_millionaires_tax_charitable_deduction.py | 9 ++++----- .../wa_millionaires_tax_standard_deduction.py | 2 ++ .../wa_millionaires_tax_taxable_income.py | 11 ++++------- 11 files changed, 18 insertions(+), 28 deletions(-) diff --git a/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/in_effect.yaml b/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/in_effect.yaml index f1b764a13eb..111a6799fb6 100644 --- a/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/in_effect.yaml +++ b/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/in_effect.yaml @@ -1,6 +1,6 @@ description: Washington expands WFTC eligibility to filers age 18 and older if this is true. values: - 0000-01-01: false + 2000-01-01: false 2029-01-01: true metadata: unit: bool diff --git a/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/min_age.yaml b/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/min_age.yaml index 7f590bd58e3..175b2ba65fb 100644 --- a/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/min_age.yaml +++ b/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/min_age.yaml @@ -1,6 +1,6 @@ description: Washington WFTC minimum age under the age expansion provision. values: - 0000-01-01: 18 + 2029-01-01: 18 metadata: unit: year period: year diff --git a/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/deductions/charitable/cap.yaml b/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/deductions/charitable/cap.yaml index bbe8ddb6d01..1850d22f091 100644 --- a/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/deductions/charitable/cap.yaml +++ b/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/deductions/charitable/cap.yaml @@ -1,6 +1,6 @@ description: Washington millionaires tax charitable deduction cap. values: - 0000-01-01: 100_000 + 2028-01-01: 100_000 metadata: unit: currency-USD period: year diff --git a/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/deductions/standard.yaml b/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/deductions/standard.yaml index 6ae9f9f37eb..5c9ba4be195 100644 --- a/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/deductions/standard.yaml +++ b/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/deductions/standard.yaml @@ -1,6 +1,6 @@ description: Washington millionaires tax standard deduction. values: - 0000-01-01: 1_000_000 + 2028-01-01: 1_000_000 metadata: unit: currency-USD period: year diff --git a/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/in_effect.yaml b/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/in_effect.yaml index b8ca5455f41..1635654a1eb 100644 --- a/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/in_effect.yaml +++ b/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/in_effect.yaml @@ -1,6 +1,6 @@ description: Washington applies a millionaires tax if this is true. values: - 0000-01-01: false + 2000-01-01: false 2028-01-01: true metadata: unit: bool diff --git a/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/rate.yaml b/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/rate.yaml index 7c6b27f152a..6b19a9633a1 100644 --- a/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/rate.yaml +++ b/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/rate.yaml @@ -1,6 +1,6 @@ description: Washington millionaires tax rate. values: - 0000-01-01: 0.099 + 2028-01-01: 0.099 metadata: unit: /1 period: year diff --git a/policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax.yaml b/policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax.yaml index cc660f36fef..c4c06884e4c 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax.yaml @@ -55,16 +55,6 @@ # Tax = $1,000 * 9.9% = $99 wa_millionaires_tax: 99 -- name: Tax not in effect in 2027 - period: 2027 - absolute_error_margin: 1 - input: - state_code: WA - adjusted_gross_income: 2_000_000 - output: - # Tax doesn't take effect until 2028 - wa_millionaires_tax: 0 - - name: Non-WA resident not subject to millionaires tax period: 2028 absolute_error_margin: 1 diff --git a/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax.py b/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax.py index 7ff72c93e92..2a0e3ee2a30 100644 --- a/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax.py +++ b/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax.py @@ -21,5 +21,7 @@ class wa_millionaires_tax(Variable): def formula(tax_unit, period, parameters): p = parameters(period).gov.states.wa.tax.income.millionaires_tax + if not p.in_effect: + return 0 taxable_income = tax_unit("wa_millionaires_tax_taxable_income", period) return taxable_income * p.rate diff --git a/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_charitable_deduction.py b/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_charitable_deduction.py index 4f2dd1a418b..ecea72a6d8d 100644 --- a/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_charitable_deduction.py +++ b/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_charitable_deduction.py @@ -17,13 +17,12 @@ class wa_millionaires_tax_charitable_deduction(Variable): """ def formula(tax_unit, period, parameters): - p = parameters( - period - ).gov.states.wa.tax.income.millionaires_tax.deductions.charitable + p = parameters(period).gov.states.wa.tax.income.millionaires_tax + if not p.in_effect: + return 0 charitable = add( tax_unit, period, ["charitable_cash_donations", "charitable_non_cash_donations"], ) - # Cap applies per tax unit (combined for spouses) - return min_(charitable, p.cap) + return min_(charitable, p.deductions.charitable.cap) diff --git a/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_standard_deduction.py b/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_standard_deduction.py index c785adb75fb..ed6212a84a5 100644 --- a/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_standard_deduction.py +++ b/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_standard_deduction.py @@ -12,4 +12,6 @@ class wa_millionaires_tax_standard_deduction(Variable): def formula(tax_unit, period, parameters): p = parameters(period).gov.states.wa.tax.income.millionaires_tax + if not p.in_effect: + return 0 return p.deductions.standard diff --git a/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_taxable_income.py b/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_taxable_income.py index c5f1e1a28ca..4cd3ba05eea 100644 --- a/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_taxable_income.py +++ b/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_taxable_income.py @@ -22,15 +22,12 @@ class wa_millionaires_tax_taxable_income(Variable): """ def formula(tax_unit, period, parameters): - in_effect = parameters( - period - ).gov.states.wa.tax.income.millionaires_tax.in_effect + p = parameters(period).gov.states.wa.tax.income.millionaires_tax + if not p.in_effect: + return 0 base_income = tax_unit("wa_millionaires_tax_base_income", period) charitable_deduction = tax_unit( "wa_millionaires_tax_charitable_deduction", period ) standard_deduction = tax_unit("wa_millionaires_tax_standard_deduction", period) - taxable_income = max_( - base_income - charitable_deduction - standard_deduction, 0 - ) - return where(in_effect, taxable_income, 0) + return max_(base_income - charitable_deduction - standard_deduction, 0) From 03f06bb230e059d1c51c98e1cad762facc52d626 Mon Sep 17 00:00:00 2001 From: David Trimmer Date: Tue, 31 Mar 2026 13:34:44 -0400 Subject: [PATCH 14/23] Use defined_for pattern instead of in_effect checks in formulas - Create wa_millionaires_tax_applies variable that reads in_effect parameter - All other variables use defined_for = "wa_millionaires_tax_applies" - Parameter is only accessed in one place, not in every formula - Cleaner separation: parameter controls timing, defined_for controls execution Co-Authored-By: Claude Opus 4.5 --- .../income/millionaires_tax/wa_millionaires_tax.py | 4 +--- .../millionaires_tax/wa_millionaires_tax_applies.py | 12 ++++++++++++ .../wa_millionaires_tax_base_income.py | 2 +- .../wa_millionaires_tax_charitable_deduction.py | 4 +--- .../wa_millionaires_tax_standard_deduction.py | 4 +--- .../wa_millionaires_tax_taxable_income.py | 5 +---- 6 files changed, 17 insertions(+), 14 deletions(-) create mode 100644 policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_applies.py diff --git a/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax.py b/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax.py index 2a0e3ee2a30..8409d6b80a8 100644 --- a/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax.py +++ b/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax.py @@ -8,7 +8,7 @@ class wa_millionaires_tax(Variable): unit = USD definition_period = YEAR reference = "https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=6" - defined_for = StateCode.WA + defined_for = "wa_millionaires_tax_applies" documentation = """ ESSB 6346 Sec. 201(1) imposes a tax of 9.9% on Washington taxable income, beginning January 1, 2028. The tax applies to Washington residents with @@ -21,7 +21,5 @@ class wa_millionaires_tax(Variable): def formula(tax_unit, period, parameters): p = parameters(period).gov.states.wa.tax.income.millionaires_tax - if not p.in_effect: - return 0 taxable_income = tax_unit("wa_millionaires_tax_taxable_income", period) return taxable_income * p.rate diff --git a/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_applies.py b/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_applies.py new file mode 100644 index 00000000000..340c4789f35 --- /dev/null +++ b/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_applies.py @@ -0,0 +1,12 @@ +from policyengine_us.model_api import * + + +class wa_millionaires_tax_applies(Variable): + value_type = bool + entity = TaxUnit + label = "Washington millionaires tax applies" + definition_period = YEAR + defined_for = StateCode.WA + + def formula(tax_unit, period, parameters): + return parameters(period).gov.states.wa.tax.income.millionaires_tax.in_effect diff --git a/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_base_income.py b/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_base_income.py index 6bc6a3d2126..212070630e4 100644 --- a/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_base_income.py +++ b/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_base_income.py @@ -11,7 +11,7 @@ class wa_millionaires_tax_base_income(Variable): "https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=5", "https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=9", ) - defined_for = StateCode.WA + defined_for = "wa_millionaires_tax_applies" documentation = """ Washington base income is federal adjusted gross income as modified by Sections 302 through 308 and 401 through 407 of ESSB 6346. diff --git a/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_charitable_deduction.py b/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_charitable_deduction.py index ecea72a6d8d..1a8e680c219 100644 --- a/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_charitable_deduction.py +++ b/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_charitable_deduction.py @@ -8,7 +8,7 @@ class wa_millionaires_tax_charitable_deduction(Variable): unit = USD definition_period = YEAR reference = "https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=12" - defined_for = StateCode.WA + defined_for = "wa_millionaires_tax_applies" documentation = """ ESSB 6346 Sec. 309(1) allows a charitable contribution deduction up to $100,000 per individual. For spouses or domestic partners, their combined @@ -18,8 +18,6 @@ class wa_millionaires_tax_charitable_deduction(Variable): def formula(tax_unit, period, parameters): p = parameters(period).gov.states.wa.tax.income.millionaires_tax - if not p.in_effect: - return 0 charitable = add( tax_unit, period, diff --git a/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_standard_deduction.py b/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_standard_deduction.py index ed6212a84a5..91ddcf04819 100644 --- a/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_standard_deduction.py +++ b/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_standard_deduction.py @@ -8,10 +8,8 @@ class wa_millionaires_tax_standard_deduction(Variable): unit = USD definition_period = YEAR reference = "https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=13" - defined_for = StateCode.WA + defined_for = "wa_millionaires_tax_applies" def formula(tax_unit, period, parameters): p = parameters(period).gov.states.wa.tax.income.millionaires_tax - if not p.in_effect: - return 0 return p.deductions.standard diff --git a/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_taxable_income.py b/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_taxable_income.py index 4cd3ba05eea..52f0d0c8519 100644 --- a/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_taxable_income.py +++ b/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_taxable_income.py @@ -12,7 +12,7 @@ class wa_millionaires_tax_taxable_income(Variable): "https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=12", "https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=13", ) - defined_for = StateCode.WA + defined_for = "wa_millionaires_tax_applies" documentation = """ Washington taxable income is Washington base income minus the standard deduction ($1,000,000) and charitable contribution deduction (up to $100,000). @@ -22,9 +22,6 @@ class wa_millionaires_tax_taxable_income(Variable): """ def formula(tax_unit, period, parameters): - p = parameters(period).gov.states.wa.tax.income.millionaires_tax - if not p.in_effect: - return 0 base_income = tax_unit("wa_millionaires_tax_base_income", period) charitable_deduction = tax_unit( "wa_millionaires_tax_charitable_deduction", period From c3dd64e052f13ff31c97f59a332ddf558a73362e Mon Sep 17 00:00:00 2001 From: David Trimmer Date: Tue, 31 Mar 2026 14:22:06 -0400 Subject: [PATCH 15/23] Add baseline value to WFTC min_age parameter for microsim compatibility --- .../working_families_tax_credit/age_expansion/min_age.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/min_age.yaml b/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/min_age.yaml index 175b2ba65fb..65d3c8e4f7c 100644 --- a/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/min_age.yaml +++ b/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/min_age.yaml @@ -1,5 +1,6 @@ description: Washington WFTC minimum age under the age expansion provision. values: + 2000-01-01: 0 2029-01-01: 18 metadata: unit: year From 29d014293267d181319602f759a2409ea8d5cad4 Mon Sep 17 00:00:00 2001 From: David Trimmer Date: Tue, 31 Mar 2026 15:13:24 -0400 Subject: [PATCH 16/23] Address PR review: add tests, fix references, remove documentation fields - Add 5 WFTC age expansion tests (2029 scenarios) - Add pre-2028 millionaires tax test - Add missing tests: non-cash donations, edge cases - Add reference field to wa_millionaires_tax_applies.py - Fix PDF page numbers (+2 offset for file vs printed pages) - Remove deprecated documentation fields from 4 variable files Co-Authored-By: Claude Opus 4.5 --- .../age_expansion/in_effect.yaml | 4 +- .../age_expansion/min_age.yaml | 2 +- .../deductions/charitable/cap.yaml | 2 +- .../millionaires_tax/deductions/standard.yaml | 4 +- .../income/millionaires_tax/in_effect.yaml | 2 +- .../wa/tax/income/millionaires_tax/rate.yaml | 2 +- .../wa_working_families_tax_credit.yaml | 63 +++++++++++++++++++ .../millionaires_tax/wa_millionaires_tax.yaml | 60 ++++++++++++++++++ .../millionaires_tax/wa_millionaires_tax.py | 11 +--- .../wa_millionaires_tax_applies.py | 1 + .../wa_millionaires_tax_base_income.py | 18 +----- ...a_millionaires_tax_charitable_deduction.py | 8 +-- .../wa_millionaires_tax_taxable_income.py | 13 +--- 13 files changed, 139 insertions(+), 51 deletions(-) diff --git a/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/in_effect.yaml b/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/in_effect.yaml index 111a6799fb6..557b42d22b8 100644 --- a/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/in_effect.yaml +++ b/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/in_effect.yaml @@ -8,6 +8,6 @@ metadata: label: Washington WFTC age expansion in effect reference: - title: ESSB 6346, Sec. 901 - Working Families Tax Credit expansion - href: https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=59 + href: https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=61 - title: ESSB 6346, Sec. 1205(1) - Effective date - href: https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=111 + href: https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=110 diff --git a/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/min_age.yaml b/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/min_age.yaml index 65d3c8e4f7c..b0fc336ae2e 100644 --- a/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/min_age.yaml +++ b/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/min_age.yaml @@ -8,4 +8,4 @@ metadata: label: Washington WFTC minimum age for expansion reference: - title: ESSB 6346, Sec. 901(2)(a)(ii)(D) - Age requirement - href: https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=59 + href: https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=61 diff --git a/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/deductions/charitable/cap.yaml b/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/deductions/charitable/cap.yaml index 1850d22f091..7aeb792fde3 100644 --- a/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/deductions/charitable/cap.yaml +++ b/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/deductions/charitable/cap.yaml @@ -7,4 +7,4 @@ metadata: label: Washington millionaires tax charitable deduction cap reference: - title: ESSB 6346, Sec. 309(1) - Charitable contributions - href: https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=12 + href: https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=14 diff --git a/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/deductions/standard.yaml b/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/deductions/standard.yaml index 5c9ba4be195..29ea830791b 100644 --- a/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/deductions/standard.yaml +++ b/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/deductions/standard.yaml @@ -14,6 +14,6 @@ metadata: interval: 1_000 reference: - title: ESSB 6346, Sec. 314 - One million dollar standard deduction - href: https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=13 + href: https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=15 - title: ESSB 6346, Sec. 316(1) - Index for inflation - href: https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=13 + href: https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=15 diff --git a/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/in_effect.yaml b/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/in_effect.yaml index 1635654a1eb..5c04ac462f7 100644 --- a/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/in_effect.yaml +++ b/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/in_effect.yaml @@ -8,4 +8,4 @@ metadata: label: Washington millionaires tax in effect reference: - title: ESSB 6346, Sec. 201(1) - Tax Imposed - href: https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=6 + href: https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=8 diff --git a/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/rate.yaml b/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/rate.yaml index 6b19a9633a1..c0cecf3ec04 100644 --- a/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/rate.yaml +++ b/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/rate.yaml @@ -7,4 +7,4 @@ metadata: label: Washington millionaires tax rate reference: - title: ESSB 6346, Sec. 201(1) - Tax Imposed - href: https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=6 + href: https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=8 diff --git a/policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/credits/wa_working_families_tax_credit.yaml b/policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/credits/wa_working_families_tax_credit.yaml index 422d42cf1ec..6c55ca26bb8 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/credits/wa_working_families_tax_credit.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/credits/wa_working_families_tax_credit.yaml @@ -81,3 +81,66 @@ state_code: WA output: wa_working_families_tax_credit: 640 + +# ESSB 6346 Sec. 901 - WFTC Age Expansion tests (effective 2029) + +- name: Age 18+ without EITC gets WFTC under 2029 age expansion. + period: 2029 + absolute_error_margin: 0.01 + input: + state_code: WA + age_head: 20 + eitc: 0 + filer_adjusted_earnings: 10_000 + eitc_child_count: 0 + output: + # Eligible via age expansion: age 18+, has earned income + wa_working_families_tax_credit: 300 + +- name: Age 17 without EITC gets no WFTC in 2029. + period: 2029 + input: + state_code: WA + age_head: 17 + eitc: 0 + filer_adjusted_earnings: 10_000 + eitc_child_count: 0 + output: + # Not EITC eligible and under age 18 minimum + wa_working_families_tax_credit: 0 + +- name: Age 18+ without earned income gets no WFTC in 2029. + period: 2029 + input: + state_code: WA + age_head: 25 + eitc: 0 + filer_adjusted_earnings: 0 + eitc_child_count: 0 + output: + # Age expansion requires earned income + wa_working_families_tax_credit: 0 + +- name: WFTC age expansion not in effect for 2028. + period: 2028 + input: + state_code: WA + age_head: 20 + eitc: 0 + filer_adjusted_earnings: 10_000 + eitc_child_count: 0 + output: + # Age expansion starts 2029, no EITC eligibility + wa_working_families_tax_credit: 0 + +- name: Traditional EITC-eligible filer still works in 2029. + period: 2029 + absolute_error_margin: 0.01 + input: + state_code: WA + eitc: 1 + filer_adjusted_earnings: 0 + eitc_child_count: 0 + output: + # Standard EITC pathway still works + wa_working_families_tax_credit: 300 diff --git a/policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax.yaml b/policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax.yaml index c4c06884e4c..d7b3a0d8b02 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax.yaml @@ -101,3 +101,63 @@ # Taxable = $2M - $1M = $1M # Tax = $1M * 9.9% = $99,000 wa_millionaires_tax: 99_000 + +- name: No millionaires tax before 2028 + period: 2027 + input: + state_code: WA + adjusted_gross_income: 2_000_000 + output: + wa_millionaires_tax: 0 + +- name: Non-cash charitable donations reduce taxable income + period: 2028 + absolute_error_margin: 1 + input: + state_code: WA + adjusted_gross_income: 2_000_000 + charitable_non_cash_donations: 75_000 + output: + # Taxable = $2M - $1M standard - $75K charitable = $925K + # Tax = $925K * 9.9% = $91,575 + wa_millionaires_tax: 91_575 + +- name: Combined cash and non-cash donations capped at $100K + period: 2028 + absolute_error_margin: 1 + input: + state_code: WA + adjusted_gross_income: 2_500_000 + charitable_cash_donations: 80_000 + charitable_non_cash_donations: 60_000 + output: + # Charitable = $80K + $60K = $140K, capped at $100K + # Taxable = $2.5M - $1M standard - $100K charitable = $1.4M + # Tax = $1.4M * 9.9% = $138,600 + wa_millionaires_tax: 138_600 + +- name: Zero income owes no millionaires tax + period: 2028 + input: + state_code: WA + adjusted_gross_income: 0 + output: + wa_millionaires_tax: 0 + +- name: Negative AGI from self-employment losses + period: 2028 + input: + state_code: WA + adjusted_gross_income: -500_000 + output: + wa_millionaires_tax: 0 + +- name: Large charitable deduction zeroes out taxable income + period: 2028 + input: + state_code: WA + adjusted_gross_income: 1_050_000 + charitable_cash_donations: 100_000 + output: + # Taxable = $1.05M - $1M standard - $100K charitable = -$50K = $0 + wa_millionaires_tax: 0 diff --git a/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax.py b/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax.py index 8409d6b80a8..239e71eeb91 100644 --- a/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax.py +++ b/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax.py @@ -7,17 +7,8 @@ class wa_millionaires_tax(Variable): label = "Washington millionaires tax" unit = USD definition_period = YEAR - reference = "https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=6" + reference = "https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=8" defined_for = "wa_millionaires_tax_applies" - documentation = """ - ESSB 6346 Sec. 201(1) imposes a tax of 9.9% on Washington taxable income, - beginning January 1, 2028. The tax applies to Washington residents with - taxable income above $1,000,000. - - This is sometimes referred to as the "millionaires tax" because the - $1,000,000 standard deduction means only households with income above - that threshold owe any tax. - """ def formula(tax_unit, period, parameters): p = parameters(period).gov.states.wa.tax.income.millionaires_tax diff --git a/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_applies.py b/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_applies.py index 340c4789f35..b4876a44716 100644 --- a/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_applies.py +++ b/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_applies.py @@ -6,6 +6,7 @@ class wa_millionaires_tax_applies(Variable): entity = TaxUnit label = "Washington millionaires tax applies" definition_period = YEAR + reference = "https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=8" defined_for = StateCode.WA def formula(tax_unit, period, parameters): diff --git a/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_base_income.py b/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_base_income.py index 212070630e4..86380eae623 100644 --- a/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_base_income.py +++ b/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_base_income.py @@ -8,22 +8,8 @@ class wa_millionaires_tax_base_income(Variable): unit = USD definition_period = YEAR reference = ( - "https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=5", - "https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=9", + "https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=7", + "https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=11", ) defined_for = "wa_millionaires_tax_applies" - documentation = """ - Washington base income is federal adjusted gross income as modified by - Sections 302 through 308 and 401 through 407 of ESSB 6346. - - Key modifications include: - - Long-term capital gains are replaced with Washington capital gains - (as defined in RCW 82.87) to avoid double-taxation with the capital gains tax - - Tax-exempt interest from non-WA state/local bonds is added back - - State/local income taxes deducted federally are added back - - Net operating loss carryovers from pre-2028 are not allowed - - This simplified implementation uses federal AGI as the base, with full - Section 302-308 modifications deferred for future enhancement. - """ adds = ["adjusted_gross_income"] diff --git a/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_charitable_deduction.py b/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_charitable_deduction.py index 1a8e680c219..4987d82daf0 100644 --- a/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_charitable_deduction.py +++ b/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_charitable_deduction.py @@ -7,14 +7,8 @@ class wa_millionaires_tax_charitable_deduction(Variable): label = "Washington millionaires tax charitable deduction" unit = USD definition_period = YEAR - reference = "https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=12" + reference = "https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=14" defined_for = "wa_millionaires_tax_applies" - documentation = """ - ESSB 6346 Sec. 309(1) allows a charitable contribution deduction up to - $100,000 per individual. For spouses or domestic partners, their combined - charitable deduction is limited to $100,000, regardless of whether they - file joint or separate returns. - """ def formula(tax_unit, period, parameters): p = parameters(period).gov.states.wa.tax.income.millionaires_tax diff --git a/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_taxable_income.py b/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_taxable_income.py index 52f0d0c8519..0af55e6618f 100644 --- a/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_taxable_income.py +++ b/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax_taxable_income.py @@ -8,18 +8,11 @@ class wa_millionaires_tax_taxable_income(Variable): unit = USD definition_period = YEAR reference = ( - "https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=5", - "https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=12", - "https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=13", + "https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=7", + "https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=14", + "https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=15", ) defined_for = "wa_millionaires_tax_applies" - documentation = """ - Washington taxable income is Washington base income minus the standard - deduction ($1,000,000) and charitable contribution deduction (up to $100,000). - - Per Sec. 101(12), Washington taxable income is "Washington base income as - further modified by sections 309 through 314." - """ def formula(tax_unit, period, parameters): base_income = tax_unit("wa_millionaires_tax_base_income", period) From d0db9c64ed13050f0a1450ebb087a2b3d093dd08 Mon Sep 17 00:00:00 2001 From: David Trimmer Date: Tue, 31 Mar 2026 15:14:34 -0400 Subject: [PATCH 17/23] Fix parameter descriptions to follow standard format --- .../working_families_tax_credit/age_expansion/in_effect.yaml | 2 +- .../working_families_tax_credit/age_expansion/min_age.yaml | 2 +- .../tax/income/millionaires_tax/deductions/charitable/cap.yaml | 2 +- .../wa/tax/income/millionaires_tax/deductions/standard.yaml | 2 +- .../gov/states/wa/tax/income/millionaires_tax/in_effect.yaml | 2 +- .../gov/states/wa/tax/income/millionaires_tax/rate.yaml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/in_effect.yaml b/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/in_effect.yaml index 557b42d22b8..a4062b81c32 100644 --- a/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/in_effect.yaml +++ b/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/in_effect.yaml @@ -1,4 +1,4 @@ -description: Washington expands WFTC eligibility to filers age 18 and older if this is true. +description: Washington uses this indicator to determine whether the Working Families Tax Credit age expansion applies. values: 2000-01-01: false 2029-01-01: true diff --git a/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/min_age.yaml b/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/min_age.yaml index b0fc336ae2e..e35301f1a39 100644 --- a/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/min_age.yaml +++ b/policyengine_us/parameters/gov/states/wa/tax/income/credits/working_families_tax_credit/age_expansion/min_age.yaml @@ -1,4 +1,4 @@ -description: Washington WFTC minimum age under the age expansion provision. +description: Washington sets this age as the minimum for eligibility under the Working Families Tax Credit age expansion. values: 2000-01-01: 0 2029-01-01: 18 diff --git a/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/deductions/charitable/cap.yaml b/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/deductions/charitable/cap.yaml index 7aeb792fde3..cb257e8d977 100644 --- a/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/deductions/charitable/cap.yaml +++ b/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/deductions/charitable/cap.yaml @@ -1,4 +1,4 @@ -description: Washington millionaires tax charitable deduction cap. +description: Washington limits charitable deductions to this amount under the millionaires tax. values: 2028-01-01: 100_000 metadata: diff --git a/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/deductions/standard.yaml b/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/deductions/standard.yaml index 29ea830791b..62b67830155 100644 --- a/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/deductions/standard.yaml +++ b/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/deductions/standard.yaml @@ -1,4 +1,4 @@ -description: Washington millionaires tax standard deduction. +description: Washington deducts this amount as the standard deduction under the millionaires tax. values: 2028-01-01: 1_000_000 metadata: diff --git a/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/in_effect.yaml b/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/in_effect.yaml index 5c04ac462f7..db1d9e6c299 100644 --- a/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/in_effect.yaml +++ b/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/in_effect.yaml @@ -1,4 +1,4 @@ -description: Washington applies a millionaires tax if this is true. +description: Washington uses this indicator to determine whether the millionaires tax applies. values: 2000-01-01: false 2028-01-01: true diff --git a/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/rate.yaml b/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/rate.yaml index c0cecf3ec04..454f7aaeaef 100644 --- a/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/rate.yaml +++ b/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/rate.yaml @@ -1,4 +1,4 @@ -description: Washington millionaires tax rate. +description: Washington taxes income at this rate under the millionaires tax. values: 2028-01-01: 0.099 metadata: From 043357d719d3471287d25ed1a4592667e2db7dac Mon Sep 17 00:00:00 2001 From: David Trimmer Date: Tue, 31 Mar 2026 15:21:58 -0400 Subject: [PATCH 18/23] Standardize WFTC test naming to Case N format Rename all 11 tests to follow "Case N, description." pattern for consistency with millionaires tax tests. Co-Authored-By: Claude Opus 4.5 --- .../wa_working_families_tax_credit.yaml | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/credits/wa_working_families_tax_credit.yaml b/policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/credits/wa_working_families_tax_credit.yaml index 6c55ca26bb8..6a06fa1a415 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/credits/wa_working_families_tax_credit.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/credits/wa_working_families_tax_credit.yaml @@ -1,4 +1,7 @@ -- name: Ineligible without EITC. +# Washington Working Families Tax Credit tests +# RCW 82.08.0206 and ESSB 6346 Sec. 901 (age expansion) + +- name: Case 1, ineligible without EITC. period: 2022 absolute_error_margin: 0 input: @@ -6,7 +9,7 @@ output: wa_working_families_tax_credit: 0 -- name: Single eligible person with no income will get the maximum credit. +- name: Case 2, single eligible person with no income gets maximum credit. period: 2022 absolute_error_margin: 0 input: @@ -17,7 +20,7 @@ output: wa_working_families_tax_credit: 300 -- name: Family with income over the limit doesn't receive it. +- name: Case 3, family with income over the limit receives no credit. period: 2022 absolute_error_margin: 0 input: @@ -28,7 +31,7 @@ output: wa_working_families_tax_credit: 0 -- name: At EITC AGI limit, credit phases to $50 minimum per RCW 82.08.0206(3)(f). +- name: Case 4, at EITC AGI limit credit phases to $50 minimum. period: 2024 absolute_error_margin: 0.01 input: @@ -38,9 +41,10 @@ eitc_agi_limit: 50_000 filer_adjusted_earnings: 50_000 output: + # Per RCW 82.08.0206(3)(f), minimum credit is $50 wa_working_families_tax_credit: 50 -- name: Mid-phaseout gives correctly reduced credit. +- name: Case 5, mid-phaseout gives correctly reduced credit. period: 2024 absolute_error_margin: 0.01 input: @@ -52,7 +56,7 @@ output: wa_working_families_tax_credit: 345 -- name: Joint filer with 1 child and moderate income receives credit. +- name: Case 6, joint filer with 1 child and moderate income receives credit. period: 2024 absolute_error_margin: 50 input: @@ -84,7 +88,7 @@ # ESSB 6346 Sec. 901 - WFTC Age Expansion tests (effective 2029) -- name: Age 18+ without EITC gets WFTC under 2029 age expansion. +- name: Case 7, age 18+ without EITC gets WFTC under 2029 age expansion. period: 2029 absolute_error_margin: 0.01 input: @@ -97,7 +101,7 @@ # Eligible via age expansion: age 18+, has earned income wa_working_families_tax_credit: 300 -- name: Age 17 without EITC gets no WFTC in 2029. +- name: Case 8, age 17 without EITC gets no WFTC in 2029. period: 2029 input: state_code: WA @@ -109,7 +113,7 @@ # Not EITC eligible and under age 18 minimum wa_working_families_tax_credit: 0 -- name: Age 18+ without earned income gets no WFTC in 2029. +- name: Case 9, age 18+ without earned income gets no WFTC in 2029. period: 2029 input: state_code: WA @@ -121,7 +125,7 @@ # Age expansion requires earned income wa_working_families_tax_credit: 0 -- name: WFTC age expansion not in effect for 2028. +- name: Case 10, WFTC age expansion not in effect before 2029. period: 2028 input: state_code: WA @@ -133,7 +137,7 @@ # Age expansion starts 2029, no EITC eligibility wa_working_families_tax_credit: 0 -- name: Traditional EITC-eligible filer still works in 2029. +- name: Case 11, traditional EITC-eligible filer still works in 2029. period: 2029 absolute_error_margin: 0.01 input: From dbc71a9e633acf5b03025b6c3687c9ac9273ae3b Mon Sep 17 00:00:00 2001 From: David Trimmer Date: Tue, 31 Mar 2026 15:25:11 -0400 Subject: [PATCH 19/23] Standardize millionaires tax test naming to Case N format Rename all 15 tests to follow "Case N, description." pattern for consistency across test files. Co-Authored-By: Claude Opus 4.5 --- .../millionaires_tax/wa_millionaires_tax.yaml | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax.yaml b/policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax.yaml index d7b3a0d8b02..d835eaa33ad 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/millionaires_tax/wa_millionaires_tax.yaml @@ -2,7 +2,7 @@ # ESSB 6346 imposes a 9.9% tax on Washington taxable income above $1,000,000 # Effective January 1, 2028 -- name: Single filer with $2M income in 2028 owes millionaires tax +- name: Case 1, single filer with $2M income. period: 2028 absolute_error_margin: 1 input: @@ -13,7 +13,7 @@ # Tax = $1M * 9.9% = $99,000 wa_millionaires_tax: 99_000 -- name: Single filer with $1.5M income in 2028 owes millionaires tax +- name: Case 2, single filer with $1.5M income. period: 2028 absolute_error_margin: 1 input: @@ -24,7 +24,7 @@ # Tax = $500K * 9.9% = $49,500 wa_millionaires_tax: 49_500 -- name: Single filer below $1M threshold owes no millionaires tax +- name: Case 3, single filer below $1M threshold. period: 2028 absolute_error_margin: 1 input: @@ -34,7 +34,7 @@ # Income below $1M standard deduction, no tax owed wa_millionaires_tax: 0 -- name: Single filer exactly at $1M threshold owes no millionaires tax +- name: Case 4, single filer exactly at $1M threshold. period: 2028 absolute_error_margin: 1 input: @@ -44,7 +44,7 @@ # Taxable income = $1M - $1M = $0 wa_millionaires_tax: 0 -- name: Single filer just above $1M threshold owes small tax +- name: Case 5, single filer just above $1M threshold. period: 2028 absolute_error_margin: 1 input: @@ -55,7 +55,7 @@ # Tax = $1,000 * 9.9% = $99 wa_millionaires_tax: 99 -- name: Non-WA resident not subject to millionaires tax +- name: Case 6, non-WA resident not subject to tax. period: 2028 absolute_error_margin: 1 input: @@ -64,7 +64,7 @@ output: wa_millionaires_tax: 0 -- name: Charitable deduction reduces taxable income +- name: Case 7, charitable deduction reduces taxable income. period: 2028 absolute_error_margin: 1 input: @@ -76,7 +76,7 @@ # Tax = $950K * 9.9% = $94,050 wa_millionaires_tax: 94_050 -- name: Charitable deduction capped at $100K +- name: Case 8, charitable deduction capped at $100K. period: 2028 absolute_error_margin: 1 input: @@ -89,7 +89,7 @@ # Tax = $1.4M * 9.9% = $138,600 wa_millionaires_tax: 138_600 -- name: Joint filers share $1M standard deduction +- name: Case 9, joint filers share $1M standard deduction. period: 2028 absolute_error_margin: 1 input: @@ -102,7 +102,7 @@ # Tax = $1M * 9.9% = $99,000 wa_millionaires_tax: 99_000 -- name: No millionaires tax before 2028 +- name: Case 10, no tax before 2028. period: 2027 input: state_code: WA @@ -110,7 +110,7 @@ output: wa_millionaires_tax: 0 -- name: Non-cash charitable donations reduce taxable income +- name: Case 11, non-cash charitable donations reduce taxable income. period: 2028 absolute_error_margin: 1 input: @@ -122,7 +122,7 @@ # Tax = $925K * 9.9% = $91,575 wa_millionaires_tax: 91_575 -- name: Combined cash and non-cash donations capped at $100K +- name: Case 12, combined cash and non-cash donations capped at $100K. period: 2028 absolute_error_margin: 1 input: @@ -136,7 +136,7 @@ # Tax = $1.4M * 9.9% = $138,600 wa_millionaires_tax: 138_600 -- name: Zero income owes no millionaires tax +- name: Case 13, zero income. period: 2028 input: state_code: WA @@ -144,7 +144,7 @@ output: wa_millionaires_tax: 0 -- name: Negative AGI from self-employment losses +- name: Case 14, negative AGI from self-employment losses. period: 2028 input: state_code: WA @@ -152,7 +152,7 @@ output: wa_millionaires_tax: 0 -- name: Large charitable deduction zeroes out taxable income +- name: Case 15, charitable deduction zeroes out taxable income. period: 2028 input: state_code: WA From 3592f731bfe686ae6556b281202fe97b5434b334 Mon Sep 17 00:00:00 2001 From: David Trimmer Date: Tue, 31 Mar 2026 15:32:55 -0400 Subject: [PATCH 20/23] Fix WFTC 2029 test expected values for inflation adjustment The WFTC maximum credit is inflation-adjusted via uprating. By 2029, the base amount for 0 children will be ~$367 (up from $300 in 2022). Updated expected values in Cases 7 and 11. Co-Authored-By: Claude Opus 4.5 --- .../income/credits/wa_working_families_tax_credit.yaml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/credits/wa_working_families_tax_credit.yaml b/policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/credits/wa_working_families_tax_credit.yaml index 6a06fa1a415..e3b86a448e9 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/credits/wa_working_families_tax_credit.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/credits/wa_working_families_tax_credit.yaml @@ -90,7 +90,7 @@ - name: Case 7, age 18+ without EITC gets WFTC under 2029 age expansion. period: 2029 - absolute_error_margin: 0.01 + absolute_error_margin: 1 input: state_code: WA age_head: 20 @@ -99,7 +99,8 @@ eitc_child_count: 0 output: # Eligible via age expansion: age 18+, has earned income - wa_working_families_tax_credit: 300 + # Amount is inflation-adjusted from $300 (2022) to ~$367 (2029) + wa_working_families_tax_credit: 367 - name: Case 8, age 17 without EITC gets no WFTC in 2029. period: 2029 @@ -139,7 +140,7 @@ - name: Case 11, traditional EITC-eligible filer still works in 2029. period: 2029 - absolute_error_margin: 0.01 + absolute_error_margin: 1 input: state_code: WA eitc: 1 @@ -147,4 +148,5 @@ eitc_child_count: 0 output: # Standard EITC pathway still works - wa_working_families_tax_credit: 300 + # Amount is inflation-adjusted from $300 (2022) to ~$367 (2029) + wa_working_families_tax_credit: 367 From e465fd2723ccc14b920d52c5749d8631c06b698e Mon Sep 17 00:00:00 2001 From: David Trimmer Date: Wed, 1 Apr 2026 09:34:49 -0400 Subject: [PATCH 21/23] Address PR review feedback - Create separate wa_working_families_tax_credit_age_expansion_eligible variable to properly gate the age expansion logic (Pavel comment) - Remove unnecessary __init__.py from millionaires_tax folder - Update in_effect.yaml description per Pavel's suggestion Co-Authored-By: Claude Opus 4.5 --- .../income/millionaires_tax/in_effect.yaml | 2 +- .../credits/wa_working_families_tax_credit.py | 26 ++++++------------- ...ilies_tax_credit_age_expansion_eligible.py | 26 +++++++++++++++++++ .../tax/income/millionaires_tax/__init__.py | 5 ---- 4 files changed, 35 insertions(+), 24 deletions(-) create mode 100644 policyengine_us/variables/gov/states/wa/tax/income/credits/wa_working_families_tax_credit_age_expansion_eligible.py delete mode 100644 policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/__init__.py diff --git a/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/in_effect.yaml b/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/in_effect.yaml index db1d9e6c299..61d6caa895e 100644 --- a/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/in_effect.yaml +++ b/policyengine_us/parameters/gov/states/wa/tax/income/millionaires_tax/in_effect.yaml @@ -1,4 +1,4 @@ -description: Washington uses this indicator to determine whether the millionaires tax applies. +description: Washington applies the millionaires tax if this is true. values: 2000-01-01: false 2028-01-01: true diff --git a/policyengine_us/variables/gov/states/wa/tax/income/credits/wa_working_families_tax_credit.py b/policyengine_us/variables/gov/states/wa/tax/income/credits/wa_working_families_tax_credit.py index 54897eb2b2b..4a4a40d95e6 100644 --- a/policyengine_us/variables/gov/states/wa/tax/income/credits/wa_working_families_tax_credit.py +++ b/policyengine_us/variables/gov/states/wa/tax/income/credits/wa_working_families_tax_credit.py @@ -9,7 +9,7 @@ class wa_working_families_tax_credit(Variable): definition_period = YEAR reference = ( "https://app.leg.wa.gov/RCW/default.aspx?cite=82.08.0206", - "https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=59", + "https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=61", ) defined_for = StateCode.WA @@ -18,27 +18,17 @@ def formula(tax_unit, period, parameters): eitc = tax_unit("eitc", period) eitc_eligible = eitc > 0 - # ESSB 6346 Sec. 901(2)(a)(ii)(D): individuals who do not meet the - # EITC age requirement but are at least age 18 (effective 2029). - p = parameters( - period - ).gov.states.wa.tax.income.credits.working_families_tax_credit - age_expansion = p.age_expansion - expansion_in_effect = age_expansion.in_effect - age_head = tax_unit("age_head", period) - age_spouse = tax_unit("age_spouse", period) - filer_meets_min_age = (age_head >= age_expansion.min_age) | ( - age_spouse >= age_expansion.min_age - ) - earned_income = tax_unit("filer_adjusted_earnings", period) - has_earned_income = earned_income > 0 - expansion_eligible = ( - expansion_in_effect & filer_meets_min_age & has_earned_income + # ESSB 6346 Sec. 901: age expansion eligibility (effective 2029) + age_expansion_eligible = tax_unit( + "wa_working_families_tax_credit_age_expansion_eligible", period ) - eligible = eitc_eligible | expansion_eligible + eligible = eitc_eligible | age_expansion_eligible # Parameters are based on EITC-eligible children. + p = parameters( + period + ).gov.states.wa.tax.income.credits.working_families_tax_credit eitc_child_count = tax_unit("eitc_child_count", period) max_amount = p.amount.calc(eitc_child_count) # WFTC phases out at a certain amount below the EITC maximum AGI. diff --git a/policyengine_us/variables/gov/states/wa/tax/income/credits/wa_working_families_tax_credit_age_expansion_eligible.py b/policyengine_us/variables/gov/states/wa/tax/income/credits/wa_working_families_tax_credit_age_expansion_eligible.py new file mode 100644 index 00000000000..3b64958fdd5 --- /dev/null +++ b/policyengine_us/variables/gov/states/wa/tax/income/credits/wa_working_families_tax_credit_age_expansion_eligible.py @@ -0,0 +1,26 @@ +from policyengine_us.model_api import * + + +class wa_working_families_tax_credit_age_expansion_eligible(Variable): + value_type = bool + entity = TaxUnit + label = "Eligible for Washington Working Families Tax Credit via age expansion" + definition_period = YEAR + reference = "https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/Senate%20Passed%20Legislature/6346-S.PL.pdf#page=61" + defined_for = StateCode.WA + + def formula(tax_unit, period, parameters): + # ESSB 6346 Sec. 901(2)(a)(ii)(D): individuals who do not meet the + # EITC age requirement but are at least age 18 (effective 2029). + p = parameters( + period + ).gov.states.wa.tax.income.credits.working_families_tax_credit.age_expansion + + expansion_in_effect = p.in_effect + age_head = tax_unit("age_head", period) + age_spouse = tax_unit("age_spouse", period) + filer_meets_min_age = (age_head >= p.min_age) | (age_spouse >= p.min_age) + earned_income = tax_unit("filer_adjusted_earnings", period) + has_earned_income = earned_income > 0 + + return expansion_in_effect & filer_meets_min_age & has_earned_income diff --git a/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/__init__.py b/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/__init__.py deleted file mode 100644 index fb7451f5c22..00000000000 --- a/policyengine_us/variables/gov/states/wa/tax/income/millionaires_tax/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -from policyengine_us.variables.gov.states.wa.tax.income.millionaires_tax.wa_millionaires_tax import * -from policyengine_us.variables.gov.states.wa.tax.income.millionaires_tax.wa_millionaires_tax_base_income import * -from policyengine_us.variables.gov.states.wa.tax.income.millionaires_tax.wa_millionaires_tax_charitable_deduction import * -from policyengine_us.variables.gov.states.wa.tax.income.millionaires_tax.wa_millionaires_tax_standard_deduction import * -from policyengine_us.variables.gov.states.wa.tax.income.millionaires_tax.wa_millionaires_tax_taxable_income import * From 538ec954ae0ab82f4c5aa7c0671b54cb4bd12b97 Mon Sep 17 00:00:00 2001 From: David Trimmer Date: Wed, 1 Apr 2026 09:36:51 -0400 Subject: [PATCH 22/23] Revert uv.lock and reforms.py to main versions Remove unrelated changes to uv.lock and resolve reforms.py conflicts by restoring from main. Co-Authored-By: Claude Opus 4.5 --- policyengine_us/reforms/reforms.py | 67 ++++++++++++++++++++++++++++++ uv.lock | 2 +- 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/policyengine_us/reforms/reforms.py b/policyengine_us/reforms/reforms.py index 761e037e7e2..f774002d35c 100644 --- a/policyengine_us/reforms/reforms.py +++ b/policyengine_us/reforms/reforms.py @@ -184,6 +184,9 @@ from .congress.watca import ( create_watca_reform, ) +from .states.wa.sb6346.sb6346 import ( + create_wa_sb6346_reform, +) from .states.ga.sb520 import ( @@ -198,6 +201,42 @@ from .states.mi.ctc import ( create_mi_ctc_reform, ) +from .states.al.eitc import ( + create_al_eitc_reform, +) +from .states.ar.eitc import ( + create_ar_eitc_reform, +) +from .states.az.eitc import ( + create_az_eitc_reform, +) +from .states.ga.eitc import ( + create_ga_eitc_reform, +) +from .states.id.eitc import ( + create_id_eitc_reform, +) +from .states.ky.eitc import ( + create_ky_eitc_reform, +) +from .states.ms.eitc import ( + create_ms_eitc_reform, +) +from .states.nd.eitc import ( + create_nd_eitc_reform, +) +from .states.wv.eitc import ( + create_wv_eitc_reform, +) +from .states.mo.eitc import ( + create_mo_refundable_eitc_reform, +) +from .states.oh.eitc import ( + create_oh_refundable_eitc_reform, +) +from .states.ut.child_poverty_eitc import ( + create_ut_fully_refundable_eitc_reform, +) from policyengine_core.reforms import Reform import warnings @@ -372,6 +411,21 @@ def create_structural_reforms_from_parameters(parameters, period): nc_eitc = create_nc_eitc_reform(parameters, period) mi_ctc = create_mi_ctc_reform(parameters, period) watca = create_watca_reform(parameters, period) + wa_sb6346 = create_wa_sb6346_reform(parameters, period) + al_eitc = create_al_eitc_reform(parameters, period) + ar_eitc = create_ar_eitc_reform(parameters, period) + az_eitc = create_az_eitc_reform(parameters, period) + ga_eitc = create_ga_eitc_reform(parameters, period) + id_eitc = create_id_eitc_reform(parameters, period) + ky_eitc = create_ky_eitc_reform(parameters, period) + ms_eitc = create_ms_eitc_reform(parameters, period) + nd_eitc = create_nd_eitc_reform(parameters, period) + wv_eitc = create_wv_eitc_reform(parameters, period) + mo_refundable_eitc = create_mo_refundable_eitc_reform(parameters, period) + oh_refundable_eitc = create_oh_refundable_eitc_reform(parameters, period) + ut_fully_refundable_eitc = create_ut_fully_refundable_eitc_reform( + parameters, period + ) reforms = [ afa_reform, @@ -462,6 +516,19 @@ def create_structural_reforms_from_parameters(parameters, period): nc_eitc, mi_ctc, watca, + wa_sb6346, + al_eitc, + ar_eitc, + az_eitc, + ga_eitc, + id_eitc, + ky_eitc, + ms_eitc, + nd_eitc, + wv_eitc, + mo_refundable_eitc, + oh_refundable_eitc, + ut_fully_refundable_eitc, ] reforms = tuple(filter(lambda x: x is not None, reforms)) diff --git a/uv.lock b/uv.lock index cd7f003fc0d..0a1ff625e17 100644 --- a/uv.lock +++ b/uv.lock @@ -1492,7 +1492,7 @@ wheels = [ [[package]] name = "policyengine-us" -version = "1.624.1" +version = "1.624.0" source = { editable = "." } dependencies = [ { name = "microdf-python" }, From f26939541e0b05289cc1884743de6f31f11d8ba9 Mon Sep 17 00:00:00 2001 From: David Trimmer Date: Wed, 1 Apr 2026 09:46:54 -0400 Subject: [PATCH 23/23] Remove wa_sb6346 from contrib reforms (now baseline law) SB6346 has been enacted as baseline law, so it should not be in contributed reforms. The millionaires tax and WFTC age expansion are implemented directly in baseline parameters and variables. Co-Authored-By: Claude Opus 4.5 --- policyengine_us/reforms/reforms.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/policyengine_us/reforms/reforms.py b/policyengine_us/reforms/reforms.py index f774002d35c..46f15a2d67b 100644 --- a/policyengine_us/reforms/reforms.py +++ b/policyengine_us/reforms/reforms.py @@ -184,9 +184,6 @@ from .congress.watca import ( create_watca_reform, ) -from .states.wa.sb6346.sb6346 import ( - create_wa_sb6346_reform, -) from .states.ga.sb520 import ( @@ -411,7 +408,6 @@ def create_structural_reforms_from_parameters(parameters, period): nc_eitc = create_nc_eitc_reform(parameters, period) mi_ctc = create_mi_ctc_reform(parameters, period) watca = create_watca_reform(parameters, period) - wa_sb6346 = create_wa_sb6346_reform(parameters, period) al_eitc = create_al_eitc_reform(parameters, period) ar_eitc = create_ar_eitc_reform(parameters, period) az_eitc = create_az_eitc_reform(parameters, period) @@ -516,7 +512,6 @@ def create_structural_reforms_from_parameters(parameters, period): nc_eitc, mi_ctc, watca, - wa_sb6346, al_eitc, ar_eitc, az_eitc,