Skip to content

Fix ignored uprating rounding rules in state tax parameters - #9371

Merged
anth-volk merged 5 commits into
mainfrom
fix-uprating-rounding-metadata
Sep 4, 2026
Merged

Fix ignored uprating rounding rules in state tax parameters#9371
anth-volk merged 5 commits into
mainfrom
fix-uprating-rounding-metadata

Conversation

@anth-volk

@anth-volk anth-volk commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Fixes #9370

Summary

  • nest 175 rounding mappings inside their corresponding uprating mappings
  • cover 29 parameter files across 12 state tax programs
  • preserve every applicable uprating parameter, rounding direction, and interval
  • apply South Carolina's rounding to income thresholds without changing its tax rates
  • add published Oregon 2025 and Wisconsin 2026 values
  • apply Washington's millionaires tax deduction adjustment only in the tax years required by statute

This change must merge before PolicyEngine/policyengine-core#216 starts rejecting the previous structure during parameter loading.

Validation

  • make format
  • 21 parameter-level regression cases covering the affected projected values
  • parameter placement check
  • 50 existing Washington calculation cases
  • parsed all 5,956 parameter YAML files with PolicyEngine Core: no parse errors and no misplaced rounding mappings
  • initialized the complete US tax-benefit system: 132,440 parameter descendants loaded
  • loaded the corrected US parameter tree through the proposed Core validation

No calculation/integration tests were added as part of the follow-up audit.

@anth-volk
anth-volk force-pushed the fix-uprating-rounding-metadata branch from c75fed7 to 8d50c52 Compare September 1, 2026 17:33
@anth-volk

Copy link
Copy Markdown
Contributor Author

@DTrim99 @hua7450 — while resolving the rebase conflict with #9351, I found a separate Washington WFTC uprating limitation worth recording.

RCW 82.08.0206(3)(d)-(e) requires the inflation-adjusted WFTC refund amounts to use the Seattle-Tacoma-Bellevue CPI-W and round the results to the nearest $5. This PR correctly activates the previously ignored $5 rounding, but the underlying parameter currently uses gov.irs.uprating, which is based on national Chained CPI-U rather than the Seattle-area CPI-W. The DOR-published amounts through tax year 2025 are explicit in the parameter and unaffected; the concern applies to projected years beginning in 2026.

The relevant BLS local series is CWURS49DSA0. It is not seasonally adjusted and is normally published every two months. October 2025 is unavailable because BLS did not collect that observation during the federal funding interruption. A direct substitution is therefore not sufficient: Washington specifies a 12-month average using information published by November 15 of the preceding year, while raw use of the BLS series would introduce values at each observation date. A complete follow-up would need to reproduce DOR's averaging and effective-year convention, define treatment of the missing October observation, and document a future projection method because BLS publishes observations rather than forecasts.

For this PR, I retained the existing gov.irs.uprating projection and combined it with #9351's current-year EITC income ceilings. The focused Washington tests and partner contract tests pass after the rebase.

@DTrim99

DTrim99 commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator

Guidance on this one, from digging into it alongside the WA WFTC verification issue (#9373):

The nesting transform is correct and it's the right shape. Moving rounding from a sibling of uprating into uprating: {parameter, rounding} is exactly what policyengine-core#216 will require, and the sibling form was being silently ignored — so this is also a real behavior fix, not just a schema move. The WA WFTC test updates are correct too: nesting makes the rounding actually apply to the 2026+ projections, so those amounts legitimately shift.

One check before un-drafting: the other 10 programs (WI/VT/NM/SC/OR/AR) also get rounding newly-applied to their 2026+ projected values. CI being green suggests none moved a tested value, but it's worth a quick confirm that no projected amount silently changed without a test covering it. Once that's clear, I think this is ready to come out of draft.

Sequencing with #9373: please land this first. I've opened #9391 for the WA WFTC model bugs (phase-out rate, effective year), and it deliberately does not touch amount.yaml rounding — that's yours. Both PRs edit the WA WFTC test files, so #9391 will rebase on top of this once it merges and reconcile the shared expected values (my phase-out-rate fix supersedes a few of the rounding-updated in-band numbers here). Landing this first keeps that clean and unblocks core#216.

@anth-volk

Copy link
Copy Markdown
Contributor Author

Completed the projected-value audit requested above.

  • Added parameter-level regression coverage for every affected group in Arkansas, New Mexico, Oregon, South Carolina, Vermont, Washington, and Wisconsin. This directly records the projected values produced after the rounding metadata becomes active.
  • Corrected South Carolina's metadata placement. At bracket level, PolicyEngine Core applies the metadata to the rate component, so the 5.21% and 6% rates would have been rounded as if they were dollar amounts. The rounding metadata now applies to the thresholds; the 2027 second-bracket threshold is $30,890 and both rates remain unchanged.
  • Added Oregon's published 2025 dependent minimum deduction of $1,350 from the 2025 Form OR-40 instructions, before projections resume.
  • Added Wisconsin's published 2026 bracket thresholds from the 2026 Form 1-ES instructions, before projections resume.
  • Corrected the separate Washington millionaires tax deduction schedule. ESSB 6346 section 316 requires adjustments each odd-numbered October beginning in 2029, effective the following tax year. Generic CPI-W metadata would change it annually, so the parameter now uses the statutory two-year schedule and remains unchanged in intervening years.

Validation completed: 21 new parameter-level cases, the parameter-metadata placement check, and 50 existing Washington calculation cases all pass. No calculation/integration tests were added in this follow-up.

@DTrim99

DTrim99 commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator

Reviewed the follow-up — the projected-value audit is exactly what was needed, and it caught two real bugs the mechanical nest would have shipped. Nicely done. Verification summary:

Metadata-placement bug class — fully clean. Every bracket-scale param (AR, SC, VT ×5, WI rates ×4, WI phase-out ×4) attaches the uprating/rounding metadata to the threshold component only; no rate block carries rounding, so tax rates can never be rounded/uprated. Your SC rates test (test_sc_income_tax_rounding_applies_to_threshold_not_rates, pinning 0.0521/0.06 at 2027) is mutation-confirmed to protect the rates — good guard.

Published values — all four CONFIRMED against source:

  • OR dependent minimum standard deduction $1,350 (2025 Form OR-40 instr. p.16) ✅
  • WI 2026 thresholds — all four statuses match the 2026 Form 1-ES schedules ✅
  • SC 2027 second-bracket $30,890 with rates unchanged ✅ (see note below — it's a projection, not a published figure)
  • WA millionaires §316 biennial schedule ✅ — uprating_extensions.py correctly does odd-October adjustment, effective the following tax year, nearest $1,000, no-decrease ratchet; the regression pins the 2028→2035 two-year steps exactly. Removing the generic annual CPI-W uprating from the YAML was the right call.

Core nest — faithful. Every removed type:/interval: reappears one-for-one (matched counts across all intervals); only the WA millionaires line is a deliberate change. The 21-case regression file is genuine (mutation-tested, not tautological), and NM is really covered (6 rebate files, len == 121 structurally requires the nesting).

One should-address:

  • WI 2026 Form 1-ES reference URL 404s in all four wi/.../rates/*.yaml — the Tax%20Forms%202026 spaced path doesn't exist. Use https://www.revenue.wi.gov/TaxForms2026/2026-Form1-ES-Inst.pdf#page=7 (matches your sibling TaxForms2023/2024/2025 links). Values are correct; just the link.

Minor / optional:

  • SC 2027 $30,890 is a CPI projection (proxy for the §12-6-520 index), not a published statutory value — worth a one-word comment so it doesn't read as published.
  • The NM all(value == round(value)) assertion is tautological under interval: 1 — the real guards are the concrete pins + len == 121; consider a couple more magnitude pins instead.
  • The rate-not-rounded placement check is SC-only; a small structural test walking AR/VT/WI/SC rate blocks would make "rates are never rounded" a durable invariant rather than a spot check.

Coordinate before un-draft: this now re-pins the WA WFTC partner contract files (partners/analytics_coverage/signatures/wa.yaml, edge_cases/state/wa/working_families_tax_credit.yaml) to the newly $5-rounded values — a partner-facing output change. Worth flagging through the partner gate/notification before merge.

Heads-up on my #9373 PR (#9391): it also touches wa_working_families_tax_credit.yaml (baseline) and changes some of the same in-band phase-out values (the corrected max/band rate). Since your PR lands first, I'll rebase #9391 on top and reconcile — the A1 rate fix supersedes a few of your rounding-updated in-band numbers (e.g. the mid-phase-out cases), which I'll recompute post-merge.

Net: I think this is ready to come out of draft once the WI link is fixed and the partner change is coordinated. 🤖 /review-program

@anth-volk
anth-volk marked this pull request as ready for review September 3, 2026 19:50
@DTrim99

DTrim99 commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator

Program Review (final) — PR #9371 (uprating→{parameter,rounding} nesting + rounding metadata)

Reviewed at head cd4d3396 — the follow-up after the projected-value audit. Scope: the structural nest of uprating/rounding metadata into the core-compliant uprating: {parameter, rounding} form across AR/NM/OR/SC/VT/WA/WI, the new uprating_extensions.py (WA millionaires §316 schedule), and the 21-case regression file. No dollar-table PDF; verified against statute + published forms.

Source

  • policyengine-core#216 (the nested uprating: {parameter, rounding} structure this migrates to)
  • OR: 2025 Form OR-40 instructions p.16 · WI: 2026 Form 1-ES rate schedules · SC: H.4216 §1 / §12-6-510, indexed per §12-6-520 · WA: ESSB 6346 §314/§316

Response to the requested audit

The projected-value audit surfaced and fixed two real bugs the mechanical nest would otherwise have shipped:

  • SC bracket-level metadata was landing on the rate component (core applies bracket metadata to the rate) — 5.21%/6% would have been rounded as dollars. Now correctly on the threshold; rates unchanged.
  • WA millionaires deduction was being uprated annually by generic CPI-W; ESSB 6346 §316 requires a biennial (odd-October, effective following year) schedule. Now delegated to uprating_extensions.py.

Critical (Must Fix)

None.

  • Metadata-placement bug class — fully clean. Every bracket-scale param (AR, SC, VT ×5, WI rates ×4, WI phase-out ×4) attaches uprating/rounding to the threshold only; no rate block carries rounding, so tax rates can never be rounded/uprated. Mutation-confirmed: the SC rates test protects 0.0521/0.06 (mutating the rate fails the test).
  • All four published values CONFIRMED against source: OR dependent-min standard deduction $1,350 (Form OR-40 p.16); WI 2026 thresholds all four statuses (Form 1-ES Schedules A/B/C); SC 2027 second-bracket $30,890 with rates unchanged; WA millionaires biennial schedule ($1.000M 2028/29 → $1.023M 2030/31 → $1.046M → $1.070M), uprating_extensions.py matching §316 exactly (odd-Oct determination, nearest $1,000, no-decrease ratchet, effective following tax year, CPI-W).
  • Core nest is faithful — every removed type:/interval: reappears one-for-one (matched counts across all intervals); the only intentional change is the WA millionaires line.
  • Regression file is genuine — 21 cases, mutation-tested (not tautological); NM is really covered (6 rebate files; len == 121 structurally requires the nesting).

Should Address

  1. WI 2026 Form 1-ES reference URL 404spolicyengine_us/parameters/gov/states/wi/tax/income/rates/{single,joint,separate,head_of_household}.yaml (line ~20) cite https://www.revenue.wi.gov/Tax%20Forms%202026/2026-Form1-ES-Inst.pdf#page=7; the spaced Tax%20Forms%202026 path does not exist (SharePoint 404). Use https://www.revenue.wi.gov/TaxForms2026/2026-Form1-ES-Inst.pdf#page=7 (matches the sibling TaxForms2023/2024/2025 links already in these files). Values are confirmed correct; only the link is broken.

Suggestions

  1. SC 2027 $30,890 is a CPI projection (proxy for the §12-6-520 index), not a published statutory figure — a one-word comment would prevent it reading as published.
  2. NM assert all(value == round(value)) is tautological under interval: 1; the real guards are the concrete pins + len == 121. Consider a couple more magnitude pins instead.
  3. The "rates are never rounded" check is SC-only; a small structural test walking AR/VT/WI/SC rate blocks would make it a durable invariant rather than a spot check.
  4. Cosmetic: OR claimable_as_dependent/min.yaml over-indentation (still parses); AR bracket-0 zero-threshold rounding metadata is a harmless no-op.

Partner-facing change (coordinate before merge)

This PR re-pins the WA WFTC partner contract files (partners/analytics_coverage/signatures/wa.yaml, partners/analytics_coverage/edge_cases/state/wa/working_families_tax_credit.yaml) to the newly $5-rounded WFTC outputs — a genuine partner-facing output change. Route it through the partner gate / notification before merge rather than merging as a routine snapshot update.

Cross-PR note

My WA WFTC bug-fix PR (#9391, for issue #9373) also edits wa_working_families_tax_credit.yaml (baseline) and changes some of the same in-band phase-out values via the corrected max/band rate. Plan is unchanged: land #9371 first; I rebase #9391 on top and reconcile — the A1 rate fix supersedes a few of this PR's rounding-updated in-band numbers.

Validation Summary

Check Result
Regulatory (published values) PASS — all 4 confirmed against source
Metadata placement (rate vs threshold) PASS — clean across all bracket params
Core nest fidelity PASS — one-for-one rounding-rule preservation
Regression tests PASS — 21 cases, mutation-verified genuine
References 1 should-address (WI 404 link)
CI Status Passing

Branch Status

⚠ PR branch is behind main (large gap). Consider rebasing before merge. Review was scoped to the PR's actual changes (merge-base diff) — staleness did not affect findings.

Review Severity: REQUEST_CHANGES

No critical issues — the audit was thorough and caught two real bugs; the nest, published values, WA millionaires schedule, and regression coverage all check out. Requesting changes only for the one should-address (the broken WI 2026 Form 1-ES URL, replicated in four files) and to flag the WA WFTC partner-contract change for coordination. Ready to un-draft/merge once those are handled.

🤖 /review-program

@DTrim99 DTrim99 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Final review posted above. No critical issues — the projected-value audit was thorough and caught two real bugs (SC rate-rounding, WA millionaires annual-vs-biennial), the published values all confirm against source, and the regression coverage is genuine. Requesting changes only for the one should-address: the WI 2026 Form 1-ES reference URL 404s in all four wi/.../rates/*.yaml (use TaxForms2026 not Tax%20Forms%202026). Also please route the WA WFTC partner-contract re-pin through the partner gate before merge. Ready to un-draft once those are handled. 🤖 /review-program

@anth-volk
anth-volk merged commit a2ae335 into main Sep 4, 2026
33 checks passed
@anth-volk
anth-volk deleted the fix-uprating-rounding-metadata branch September 4, 2026 16:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Correct ignored uprating rounding rules in state tax parameters

2 participants