From 1b5112518e34769471d3df18164378c776f5738e Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Fri, 25 Sep 2026 07:20:53 -0400 Subject: [PATCH 1/3] Fix Arkansas 2025 and 2024 minus-adjustment schedules against DFA cards 2025: the reduction scale jumped from the $26,400 row ($420) straight to $95,001, skipping DFA's $94,701-$94,800 ($399.30), $94,801-$94,900 ($389.30) and $94,901-$95,000 ($379.30) rows, so taxable income in that band was undertaxed by $20.70-$40.70. The column also carried rounded amounts (112/224/288/420, 369...89) instead of DFA's published cents (111.98/223.97/287.97/419.96, 369.30...89.30). Re-keyed the whole 2025 column to the 2025 Indexed Tax Brackets card; its rows now line up with the 2026 Act 1 rows, and the two newly finite 2025 rows keep their explicit 2026 .inf, so 2026 is unchanged. 2024: the column ignored the card's asterisked $94,301-$94,500 row, so $94,401-$95,500 each took the next $10 step down ($10 overtax). Verified every integer taxable income 0-110,000 for 2021-2025 against the DFA TaxBrackets cards and 2026 against Act 1 of 2026: 0 mismatches (upstream/main: 1,100 in 2024, 104,403 in 2025). Loaded rate and reduction scales for 2015-2035 are otherwise identical. Also points the 2025 booklet reference at the Regular Income Tax Table (PDF page 30; #page=26 was the printed page number) and cites the 2025 TaxBrackets card in rate.yaml and reduction.yaml. Co-Authored-By: Claude Opus 5.5 --- .../fix-ar-2025-reduction-schedule.fixed.md | 1 + .../states/ar/tax/income/rates/main/rate.yaml | 6 +- .../ar/tax/income/rates/main/reduction.yaml | 198 ++++++++-------- ...x_before_non_refundable_credits_indiv.yaml | 219 +++++++++++++++++- ...x_before_non_refundable_credits_joint.yaml | 10 +- 5 files changed, 317 insertions(+), 117 deletions(-) create mode 100644 changelog.d/fix-ar-2025-reduction-schedule.fixed.md diff --git a/changelog.d/fix-ar-2025-reduction-schedule.fixed.md b/changelog.d/fix-ar-2025-reduction-schedule.fixed.md new file mode 100644 index 00000000000..fc3becccd2d --- /dev/null +++ b/changelog.d/fix-ar-2025-reduction-schedule.fixed.md @@ -0,0 +1 @@ +Fix Arkansas 2025 and 2024 income tax minus-adjustment schedules to match the DFA Indexed Tax Brackets: add the missing 2025 $94,701-$95,000 rows (previously taxed with the $419.96 adjustment), use DFA's exact cents for 2025, and honor the 2024 asterisked $94,301-$94,500 row. diff --git a/policyengine_us/parameters/gov/states/ar/tax/income/rates/main/rate.yaml b/policyengine_us/parameters/gov/states/ar/tax/income/rates/main/rate.yaml index b90beb0ff0a..2ad57034002 100644 --- a/policyengine_us/parameters/gov/states/ar/tax/income/rates/main/rate.yaml +++ b/policyengine_us/parameters/gov/states/ar/tax/income/rates/main/rate.yaml @@ -26,8 +26,10 @@ metadata: href: https://www.dfa.arkansas.gov/wp-content/uploads/TaxBrackets_2023.pdf#page=1 - title: 2024 Indexed Tax Brackets href: https://www.dfa.arkansas.gov/wp-content/uploads/2024_TaxBrackets.pdf#page=1 - - title: Arkansas 2025 Individual Income Tax Forms and Instructions - href: https://www.dfa.arkansas.gov/wp-content/uploads/2025_AR1000F_and_AR1000NR_Instructions.pdf#page=26 + - title: 2025 Indexed Tax Brackets + href: https://www.dfa.arkansas.gov/wp-content/uploads/2025_TaxBrackets.pdf#page=1 + - title: Arkansas 2025 Individual Income Tax Forms and Instructions (2025 Regular Income Tax Table) + href: https://www.dfa.arkansas.gov/wp-content/uploads/2025_AR1000F_and_AR1000NR_Instructions.pdf#page=30 - title: Arkansas Act 1 of 2026 (HB1001, 1st Extraordinary Session), Section 1 amending A.C.A. § 26-51-201(a)(4) href: https://www.arkleg.state.ar.us/Home/FTPDocument?path=%2FBills%2F2026S1%2FPublic%2FHB1001.pdf#page=2 - title: Arkansas Legislature HB1001 status page (enacted as Act 1, 2026 1st Extraordinary Session) diff --git a/policyengine_us/parameters/gov/states/ar/tax/income/rates/main/reduction.yaml b/policyengine_us/parameters/gov/states/ar/tax/income/rates/main/reduction.yaml index 3a25a6b4f85..17187b1d993 100644 --- a/policyengine_us/parameters/gov/states/ar/tax/income/rates/main/reduction.yaml +++ b/policyengine_us/parameters/gov/states/ar/tax/income/rates/main/reduction.yaml @@ -15,8 +15,10 @@ metadata: href: https://www.dfa.arkansas.gov/wp-content/uploads/TaxBrackets_2023.pdf#page=1 - title: 2024 Indexed Tax Brackets href: https://www.dfa.arkansas.gov/wp-content/uploads/2024_TaxBrackets.pdf#page=1 - - title: Arkansas 2025 Individual Income Tax Forms and Instructions - href: https://www.dfa.arkansas.gov/wp-content/uploads/2025_AR1000F_and_AR1000NR_Instructions.pdf#page=26 + - title: 2025 Indexed Tax Brackets + href: https://www.dfa.arkansas.gov/wp-content/uploads/2025_TaxBrackets.pdf#page=1 + - title: Arkansas 2025 Individual Income Tax Forms and Instructions (2025 Regular Income Tax Table) + href: https://www.dfa.arkansas.gov/wp-content/uploads/2025_AR1000F_and_AR1000NR_Instructions.pdf#page=30 - title: Arkansas Act 1 of 2026 (HB1001, 1st Extraordinary Session), Section 1 amending A.C.A. § 26-51-201(a)(4)(C) href: https://www.arkleg.state.ar.us/Home/FTPDocument?path=%2FBills%2F2026S1%2FPublic%2FHB1001.pdf#page=2 - title: Arkansas Legislature HB1001 status page (enacted as Act 1, 2026 1st Extraordinary Session) @@ -40,7 +42,7 @@ brackets: 2022-01-01: 101.98 2023-01-01: 105.98 2024-01-01: 109.98 - 2025-01-01: 112 + 2025-01-01: 111.98 2026-01-01: 112 - threshold: 2021-01-01: 9_500 @@ -54,7 +56,7 @@ brackets: 2022-01-01: 204.97 2023-01-01: 211.97 2024-01-01: 218.97 - 2025-01-01: 224 + 2025-01-01: 223.97 2026-01-01: 224 - threshold: 2021-01-01: 14_300 @@ -68,7 +70,7 @@ brackets: 2022-01-01: 263.77 2023-01-01: 272.37 2024-01-01: 281.37 - 2025-01-01: 288 + 2025-01-01: 287.97 2026-01-01: 288 - threshold: 2021-01-01: 23_600 @@ -82,461 +84,461 @@ brackets: 2022-01-01: 628.25 2023-01-01: 597.35 2024-01-01: 409.86 - 2025-01-01: 420 + 2025-01-01: 419.96 2026-01-01: 367.20 - threshold: 2021-01-01: 39_700 2022-01-01: 87_001 2023-01-01: 89_601 2024-01-01: 92_301 - 2025-01-01: 95_001 + 2025-01-01: 94_701 2026-01-01: 94_701 amount: 2021-01-01: 797.25 2022-01-01: 627.20 2023-01-01: 583.7 2024-01-01: 397.40 - 2025-01-01: 369 + 2025-01-01: 399.30 2026-01-01: 369.90 - threshold: 2021-01-01: 84_501 2022-01-01: 87_101 2023-01-01: 89_701 2024-01-01: 92_401 - 2025-01-01: 95_101 + 2025-01-01: 94_801 2026-01-01: 94_801 amount: 2021-01-01: 687.5 2022-01-01: 617.20 2023-01-01: 573.7 2024-01-01: 387.40 - 2025-01-01: 359 + 2025-01-01: 389.30 2026-01-01: 359.90 - threshold: 2021-01-01: 85_501 2022-01-01: 87_201 2023-01-01: 89_801 2024-01-01: 92_501 - 2025-01-01: 95_201 + 2025-01-01: 94_901 2026-01-01: 94_901 amount: 2021-01-01: 587.5 2022-01-01: 607.20 2023-01-01: 563.7 2024-01-01: 377.40 - 2025-01-01: 349 + 2025-01-01: 379.30 2026-01-01: 349.90 - threshold: 2021-01-01: 86_501 2022-01-01: 87_301 2023-01-01: 89_901 2024-01-01: 92_601 - 2025-01-01: 95_301 + 2025-01-01: 95_001 2026-01-01: 95_001 amount: 2021-01-01: 487.5 2022-01-01: 597.20 2023-01-01: 553.7 2024-01-01: 367.40 - 2025-01-01: 339 + 2025-01-01: 369.30 2026-01-01: 339.90 - threshold: 2021-01-01: 87_901 2022-01-01: 87_401 2023-01-01: 90_001 2024-01-01: 92_701 - 2025-01-01: 95_401 + 2025-01-01: 95_101 2026-01-01: 95_101 amount: 2021-01-01: 387.5 2022-01-01: 587.20 2023-01-01: 543.7 2024-01-01: 357.40 - 2025-01-01: 329 + 2025-01-01: 359.30 2026-01-01: 329.90 - threshold: 2021-01-01: 89_001 2022-01-01: 87_601 2023-01-01: 90_201 2024-01-01: 92_801 - 2025-01-01: 95_501 + 2025-01-01: 95_201 2026-01-01: 95_201 amount: 2021-01-01: 287.5 2022-01-01: 577.20 2023-01-01: 533.7 2024-01-01: 347.40 - 2025-01-01: 319 + 2025-01-01: 349.30 2026-01-01: 319.90 - threshold: 2021-01-01: 90_101 2022-01-01: 87_701 2023-01-01: 90_301 2024-01-01: 92_901 - 2025-01-01: 95_601 + 2025-01-01: 95_301 2026-01-01: 95_301 amount: 2021-01-01: 247.5 2022-01-01: 567.20 2023-01-01: 523.7 2024-01-01: 337.40 - 2025-01-01: 309 + 2025-01-01: 339.30 2026-01-01: 309.90 - threshold: 2021-01-01: .inf 2022-01-01: 87_801 2023-01-01: 90_401 2024-01-01: 93_001 - 2025-01-01: 95_701 + 2025-01-01: 95_401 2026-01-01: 95_401 amount: 2021-01-01: 247.5 2022-01-01: 557.20 2023-01-01: 513.7 2024-01-01: 327.40 - 2025-01-01: 299 + 2025-01-01: 329.30 2026-01-01: 299.90 - threshold: 2021-01-01: .inf 2022-01-01: 87_901 2023-01-01: 90_501 2024-01-01: 93_101 - 2025-01-01: 95_801 + 2025-01-01: 95_501 2026-01-01: 95_501 amount: 2021-01-01: 247.5 2022-01-01: 547.20 2023-01-01: 503.7 2024-01-01: 317.40 - 2025-01-01: 289 + 2025-01-01: 319.30 2026-01-01: 289.90 - threshold: 2021-01-01: .inf 2022-01-01: 88_001 2023-01-01: 90_601 2024-01-01: 93_201 - 2025-01-01: 95_901 + 2025-01-01: 95_601 2026-01-01: 95_601 amount: 2021-01-01: 247.5 2022-01-01: 537.20 2023-01-01: 493.7 2024-01-01: 307.40 - 2025-01-01: 279 + 2025-01-01: 309.30 2026-01-01: 279.90 - threshold: 2021-01-01: .inf 2022-01-01: 88_101 2023-01-01: 90_701 2024-01-01: 93_301 - 2025-01-01: 96_001 + 2025-01-01: 95_701 2026-01-01: 95_701 amount: 2021-01-01: 247.5 2022-01-01: 527.20 2023-01-01: 483.7 2024-01-01: 297.40 - 2025-01-01: 269 + 2025-01-01: 299.30 2026-01-01: 269.90 - threshold: 2021-01-01: .inf 2022-01-01: 88_201 2023-01-01: 90_801 2024-01-01: 93_401 - 2025-01-01: 96_101 + 2025-01-01: 95_801 2026-01-01: 95_801 amount: 2021-01-01: 247.5 2022-01-01: 517.20 2023-01-01: 473.7 2024-01-01: 287.40 - 2025-01-01: 259 + 2025-01-01: 289.30 2026-01-01: 259.90 - threshold: 2021-01-01: .inf 2022-01-01: 88_301 2023-01-01: 90_901 2024-01-01: 93_501 - 2025-01-01: 96_201 + 2025-01-01: 95_901 2026-01-01: 95_901 amount: 2021-01-01: 247.5 2022-01-01: 507.20 2023-01-01: 463.7 2024-01-01: 277.40 - 2025-01-01: 249 + 2025-01-01: 279.30 2026-01-01: 249.90 - threshold: 2021-01-01: .inf 2022-01-01: 88_401 2023-01-01: 91_101 2024-01-01: 93_601 - 2025-01-01: 96_301 + 2025-01-01: 96_001 2026-01-01: 96_001 amount: 2021-01-01: 247.5 2022-01-01: 497.20 2023-01-01: 453.7 2024-01-01: 267.40 - 2025-01-01: 239 + 2025-01-01: 269.30 2026-01-01: 239.90 - threshold: 2021-01-01: .inf 2022-01-01: 88_501 2023-01-01: 91_201 2024-01-01: 93_701 - 2025-01-01: 96_401 + 2025-01-01: 96_101 2026-01-01: 96_101 amount: 2021-01-01: 247.5 2022-01-01: 487.20 2023-01-01: 443.7 2024-01-01: 257.40 - 2025-01-01: 229 + 2025-01-01: 259.30 2026-01-01: 229.90 - threshold: 2021-01-01: .inf 2022-01-01: 88_601 2023-01-01: 91_301 2024-01-01: 93_801 - 2025-01-01: 96_501 + 2025-01-01: 96_201 2026-01-01: 96_201 amount: 2021-01-01: 247.5 2022-01-01: 477.20 2023-01-01: 433.7 2024-01-01: 247.40 - 2025-01-01: 219 + 2025-01-01: 249.30 2026-01-01: 219.90 - threshold: 2021-01-01: .inf 2022-01-01: 88_701 2023-01-01: 91_401 2024-01-01: 93_901 - 2025-01-01: 96_601 + 2025-01-01: 96_301 2026-01-01: 96_301 amount: 2021-01-01: 247.5 2022-01-01: 467.20 2023-01-01: 423.7 2024-01-01: 237.40 - 2025-01-01: 209 + 2025-01-01: 239.30 2026-01-01: 209.90 - threshold: 2021-01-01: .inf 2022-01-01: 88_801 2023-01-01: 91_501 2024-01-01: 94_001 - 2025-01-01: 96_701 + 2025-01-01: 96_401 2026-01-01: 96_401 amount: 2021-01-01: 247.5 2022-01-01: 457.20 2023-01-01: 413.7 2024-01-01: 227.40 - 2025-01-01: 199 + 2025-01-01: 229.30 2026-01-01: 199.90 - threshold: 2021-01-01: .inf 2022-01-01: 88_901 2023-01-01: 91_601 2024-01-01: 94_101 - 2025-01-01: 96_801 + 2025-01-01: 96_501 2026-01-01: 96_501 amount: 2021-01-01: 247.5 2022-01-01: 447.20 2023-01-01: 403.7 2024-01-01: 217.40 - 2025-01-01: 189 + 2025-01-01: 219.30 2026-01-01: 189.90 - threshold: 2021-01-01: .inf 2022-01-01: 89_001 2023-01-01: 91_701 2024-01-01: 94_201 - 2025-01-01: 96_901 + 2025-01-01: 96_601 2026-01-01: 96_601 amount: 2021-01-01: 247.5 2022-01-01: 437.20 2023-01-01: 393.7 2024-01-01: 207.40 - 2025-01-01: 179 + 2025-01-01: 209.30 2026-01-01: 179.90 - threshold: 2021-01-01: .inf 2022-01-01: 89_101 2023-01-01: 91_801 2024-01-01: 94_301 - 2025-01-01: 97_001 + 2025-01-01: 96_701 2026-01-01: 96_701 amount: 2021-01-01: 247.5 2022-01-01: 427.20 2023-01-01: 383.7 2024-01-01: 197.40 - 2025-01-01: 169 + 2025-01-01: 199.30 2026-01-01: 169.90 - threshold: 2021-01-01: .inf 2022-01-01: 89_201 2023-01-01: 91_901 - 2024-01-01: 94_401 - 2025-01-01: 97_101 + 2024-01-01: 94_501 + 2025-01-01: 96_801 2026-01-01: 96_801 amount: 2021-01-01: 247.5 2022-01-01: 417.20 2023-01-01: 373.7 2024-01-01: 187.40 - 2025-01-01: 159 + 2025-01-01: 189.30 2026-01-01: 159.90 - threshold: 2021-01-01: .inf 2022-01-01: 89_301 2023-01-01: 92_001 - 2024-01-01: 94_501 - 2025-01-01: 97_201 + 2024-01-01: 94_601 + 2025-01-01: 96_901 2026-01-01: 96_901 amount: 2021-01-01: 247.5 2022-01-01: 407.20 2023-01-01: 363.7 2024-01-01: 177.40 - 2025-01-01: 149 + 2025-01-01: 179.30 2026-01-01: 149.90 - threshold: 2021-01-01: .inf 2022-01-01: 89_401 2023-01-01: 92_101 - 2024-01-01: 94_601 - 2025-01-01: 97_301 + 2024-01-01: 94_701 + 2025-01-01: 97_001 2026-01-01: 97_001 amount: 2021-01-01: 247.5 2022-01-01: 397.20 2023-01-01: 353.7 2024-01-01: 167.40 - 2025-01-01: 139 + 2025-01-01: 169.30 2026-01-01: 139.90 - threshold: 2021-01-01: .inf 2022-01-01: 89_501 2023-01-01: 92_201 - 2024-01-01: 94_701 - 2025-01-01: 97_401 + 2024-01-01: 94_801 + 2025-01-01: 97_101 2026-01-01: 97_101 amount: 2021-01-01: 247.5 2022-01-01: 387.20 2023-01-01: 343.7 2024-01-01: 157.40 - 2025-01-01: 129 + 2025-01-01: 159.30 2026-01-01: 129.90 - threshold: 2021-01-01: .inf 2022-01-01: 89_601 2023-01-01: 92_301 - 2024-01-01: 94_801 - 2025-01-01: 97_501 + 2024-01-01: 94_901 + 2025-01-01: 97_201 2026-01-01: 97_201 amount: 2021-01-01: 247.5 2022-01-01: 377.20 2023-01-01: 333.7 2024-01-01: 147.40 - 2025-01-01: 119 + 2025-01-01: 149.30 2026-01-01: 119.90 - threshold: 2021-01-01: .inf 2022-01-01: 89_701 2023-01-01: 92_401 - 2024-01-01: 94_901 - 2025-01-01: 97_601 + 2024-01-01: 95_001 + 2025-01-01: 97_301 2026-01-01: 97_301 amount: 2021-01-01: 247.5 2022-01-01: 367.20 2023-01-01: 323.7 2024-01-01: 137.40 - 2025-01-01: 109 + 2025-01-01: 139.30 2026-01-01: 109.90 - threshold: 2021-01-01: .inf 2022-01-01: 89_801 2023-01-01: 92_501 - 2024-01-01: 95_001 - 2025-01-01: 97_701 + 2024-01-01: 95_101 + 2025-01-01: 97_401 2026-01-01: 97_401 amount: 2021-01-01: 247.5 2022-01-01: 357.20 2023-01-01: 313.7 2024-01-01: 127.40 - 2025-01-01: 99 + 2025-01-01: 129.30 2026-01-01: 99.90 - threshold: 2021-01-01: .inf 2022-01-01: 89_901 2023-01-01: 92_601 - 2024-01-01: 95_101 - 2025-01-01: 97_801 + 2024-01-01: 95_201 + 2025-01-01: 97_501 2026-01-01: 97_501 amount: 2021-01-01: 247.5 2022-01-01: 347.20 2023-01-01: 303.7 2024-01-01: 117.40 - 2025-01-01: 89 + 2025-01-01: 119.30 2026-01-01: 89.90 - threshold: 2021-01-01: .inf 2022-01-01: 90_001 2023-01-01: 92_701 - 2024-01-01: 95_201 - 2025-01-01: 97_901 + 2024-01-01: 95_301 + 2025-01-01: 97_601 2026-01-01: 97_601 amount: 2021-01-01: 247.5 2022-01-01: 337.20 2023-01-01: 293.7 2024-01-01: 107.40 - 2025-01-01: 89 + 2025-01-01: 109.30 2026-01-01: 79.90 - threshold: 2021-01-01: .inf 2022-01-01: 90_101 2023-01-01: 92_801 - 2024-01-01: 95_301 - 2025-01-01: .inf + 2024-01-01: 95_401 + 2025-01-01: 97_701 2026-01-01: .inf amount: 2021-01-01: 247.5 2022-01-01: 327.20 2023-01-01: 283.7 2024-01-01: 97.40 - 2025-01-01: 89 + 2025-01-01: 99.30 2026-01-01: 79.90 - threshold: 2021-01-01: .inf 2022-01-01: 90_201 2023-01-01: 92_901 - 2024-01-01: 95_401 - 2025-01-01: .inf + 2024-01-01: 95_501 + 2025-01-01: 97_801 2026-01-01: .inf amount: 2021-01-01: 247.5 2022-01-01: 317.20 2023-01-01: 273.7 2024-01-01: 87.40 - 2025-01-01: 89 + 2025-01-01: 89.30 2026-01-01: 79.90 - threshold: 2021-01-01: .inf 2022-01-01: 90_301 2023-01-01: 93_001 - 2024-01-01: 95_501 + 2024-01-01: .inf 2025-01-01: .inf 2026-01-01: .inf amount: @@ -544,7 +546,7 @@ brackets: 2022-01-01: 307.20 2023-01-01: 263.7 2024-01-01: 87.40 - 2025-01-01: 89 + 2025-01-01: 89.30 2026-01-01: 79.90 - threshold: 2021-01-01: .inf @@ -557,7 +559,7 @@ brackets: 2022-01-01: 297.20 2023-01-01: 253.7 2024-01-01: 87.40 - 2025-01-01: 89 + 2025-01-01: 89.30 2026-01-01: 79.90 - threshold: 2021-01-01: .inf @@ -570,7 +572,7 @@ brackets: 2022-01-01: 287.20 2023-01-01: 243.7 2024-01-01: 87.40 - 2025-01-01: 89 + 2025-01-01: 89.30 2026-01-01: 79.90 - threshold: 2021-01-01: .inf @@ -583,7 +585,7 @@ brackets: 2022-01-01: 277.20 2023-01-01: 233.7 2024-01-01: 87.40 - 2025-01-01: 89 + 2025-01-01: 89.30 2026-01-01: 79.90 - threshold: 2021-01-01: .inf @@ -596,7 +598,7 @@ brackets: 2022-01-01: 267.20 2023-01-01: 223.7 2024-01-01: 87.40 - 2025-01-01: 89 + 2025-01-01: 89.30 2026-01-01: 79.90 - threshold: 2021-01-01: .inf @@ -609,7 +611,7 @@ brackets: 2022-01-01: 257.20 2023-01-01: 213.7 2024-01-01: 87.40 - 2025-01-01: 89 + 2025-01-01: 89.30 2026-01-01: 79.90 - threshold: 2021-01-01: .inf @@ -622,7 +624,7 @@ brackets: 2022-01-01: 247.20 2023-01-01: 203.7 2024-01-01: 87.40 - 2025-01-01: 89 + 2025-01-01: 89.30 2026-01-01: 79.90 - threshold: 2021-01-01: .inf @@ -635,7 +637,7 @@ brackets: 2022-01-01: 237.20 2023-01-01: 193.7 2024-01-01: 87.40 - 2025-01-01: 89 + 2025-01-01: 89.30 2026-01-01: 79.90 - threshold: 2021-01-01: .inf @@ -648,7 +650,7 @@ brackets: 2022-01-01: 227.20 2023-01-01: 183.7 2024-01-01: 87.40 - 2025-01-01: 89 + 2025-01-01: 89.30 2026-01-01: 79.90 - threshold: 2021-01-01: .inf @@ -661,7 +663,7 @@ brackets: 2022-01-01: 217.20 2023-01-01: 173.7 2024-01-01: 87.40 - 2025-01-01: 89 + 2025-01-01: 89.30 2026-01-01: 79.90 - threshold: 2021-01-01: .inf @@ -674,7 +676,7 @@ brackets: 2022-01-01: 207.20 2023-01-01: 163.7 2024-01-01: 87.40 - 2025-01-01: 89 + 2025-01-01: 89.30 2026-01-01: 79.90 - threshold: 2021-01-01: .inf @@ -687,7 +689,7 @@ brackets: 2022-01-01: 197.20 2023-01-01: 153.7 2024-01-01: 87.40 - 2025-01-01: 89 + 2025-01-01: 89.30 2026-01-01: 79.90 - threshold: 2021-01-01: .inf @@ -700,7 +702,7 @@ brackets: 2022-01-01: 187.20 2023-01-01: 153.7 2024-01-01: 87.40 - 2025-01-01: 89 + 2025-01-01: 89.30 2026-01-01: 79.90 - threshold: 2021-01-01: .inf @@ -713,7 +715,7 @@ brackets: 2022-01-01: 177.20 2023-01-01: 153.70 2024-01-01: 87.40 - 2025-01-01: 89 + 2025-01-01: 89.30 2026-01-01: 79.90 - threshold: 2021-01-01: .inf @@ -726,7 +728,7 @@ brackets: 2022-01-01: 167.20 2023-01-01: 153.70 2024-01-01: 87.40 - 2025-01-01: 89 + 2025-01-01: 89.30 2026-01-01: 79.90 - threshold: 2022-01-01: .inf @@ -737,5 +739,5 @@ brackets: 2022-01-01: 167.20 2023-01-01: 153.70 2024-01-01: 87.40 - 2025-01-01: 89 + 2025-01-01: 89.30 2026-01-01: 79.90 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ar/tax/income/ar_income_tax_before_non_refundable_credits_indiv.yaml b/policyengine_us/tests/policy/baseline/gov/states/ar/tax/income/ar_income_tax_before_non_refundable_credits_indiv.yaml index f510ab505ad..4e28a6e37c1 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ar/tax/income/ar_income_tax_before_non_refundable_credits_indiv.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ar/tax/income/ar_income_tax_before_non_refundable_credits_indiv.yaml @@ -90,43 +90,43 @@ - name: Case 10, 2025 taxable income in 2% bracket. period: 2025 - absolute_error_margin: 1 + absolute_error_margin: 0.01 input: ar_taxable_income_indiv: 10_000 state_code: AR output: - # 10_000 * 0.02 - 112 = 88 - ar_income_tax_before_non_refundable_credits_indiv: 88 + # DFA 2025 bracket: 10_000 * 0.02 - 111.98 = 88.02 + ar_income_tax_before_non_refundable_credits_indiv: 88.02 - name: Case 11, 2025 taxable income in 3.4% bracket. period: 2025 - absolute_error_margin: 1 + absolute_error_margin: 0.01 input: ar_taxable_income_indiv: 20_000 state_code: AR output: - # 20_000 * 0.034 - 288 = 392 - ar_income_tax_before_non_refundable_credits_indiv: 392 + # DFA 2025 bracket: 20_000 * 0.034 - 287.97 = 392.03 + ar_income_tax_before_non_refundable_credits_indiv: 392.03 - name: Case 12, 2025 taxable income in 3.9% bracket. period: 2025 - absolute_error_margin: 1 + absolute_error_margin: 0.01 input: ar_taxable_income_indiv: 50_000 state_code: AR output: - # 50_000 * 0.039 - 420 = 1_530 - ar_income_tax_before_non_refundable_credits_indiv: 1_530 + # DFA 2025 bracket: 50_000 * 0.039 - 419.96 = 1_530.04 + ar_income_tax_before_non_refundable_credits_indiv: 1_530.04 - name: Case 13, 2025 taxable income at $100,000. period: 2025 - absolute_error_margin: 1 + absolute_error_margin: 0.01 input: ar_taxable_income_indiv: 100_000 state_code: AR output: - # 100_000 * 0.039 - 89 = 3_811 - ar_income_tax_before_non_refundable_credits_indiv: 3_811 + # DFA 2025 bracket "$97,801 and over": 100_000 * 0.039 - 89.30 = 3_810.70 + ar_income_tax_before_non_refundable_credits_indiv: 3_810.70 # 2026 tests follow A.C.A. § 26-51-201(a)(4) as amended by HB1001 (2026 1st Extraordinary Session). # Bill schedules: (a)(4)(A) for net income <= $94,700, (a)(4)(B) for > $94,700, plus @@ -299,3 +299,198 @@ # 0.047 x 91,750 - 393.70 = 3,918.55 (previously the two duplicated # thresholds summed to a 787.40 reduction -> 3,524.85) ar_income_tax_before_non_refundable_credits_indiv: 3_918.55 + +# 2025 and 2024 bracket adjustments, keyed to the DFA Indexed Tax Brackets cards +# (2025_TaxBrackets.pdf and 2024_TaxBrackets.pdf, p1-2). Tax = 3.9% x net taxable +# income - the row's minus adjustment. +- name: AR 2025 bracket adjustment - top of the $26,400-$94,700 row + period: 2025 + absolute_error_margin: 0.01 + input: + ar_taxable_income_indiv: 94_700 + state_code: AR + output: + # DFA 2025 Indexed Tax Brackets row "$26,400 $94,700 3.90% $419.96": + # 0.039 x 94,700 - 419.96 = 3,273.34 + ar_income_tax_before_non_refundable_credits_indiv: 3_273.34 + +- name: AR 2025 bracket adjustment - first $94,701-$94,800 row PE previously skipped + period: 2025 + absolute_error_margin: 0.01 + input: + ar_taxable_income_indiv: 94_701 + state_code: AR + output: + # DFA 2025 Indexed Tax Brackets row "$94,701 $94,800 3.90% $399.30": + # 0.039 x 94,701 - 399.30 = 3,294.04 + # (PE previously applied the $419.96-row amount, 420, here -> 3,273.34) + ar_income_tax_before_non_refundable_credits_indiv: 3_294.04 + +- name: AR 2025 bracket adjustment - midpoint of the $94,701-$94,800 row + period: 2025 + absolute_error_margin: 0.01 + input: + ar_taxable_income_indiv: 94_751 + state_code: AR + output: + # DFA 2025 Indexed Tax Brackets row "$94,701 $94,800 3.90% $399.30": + # 0.039 x 94,751 - 399.30 = 3,295.99 + # (2025 Regular Income Tax Table, $94,701-$94,801: $3,296) + ar_income_tax_before_non_refundable_credits_indiv: 3_295.99 + +- name: AR 2025 bracket adjustment - top of the $94,701-$94,800 row + period: 2025 + absolute_error_margin: 0.01 + input: + ar_taxable_income_indiv: 94_800 + state_code: AR + output: + # DFA 2025 Indexed Tax Brackets row "$94,701 $94,800 3.90% $399.30": + # 0.039 x 94,800 - 399.30 = 3,297.90 + ar_income_tax_before_non_refundable_credits_indiv: 3_297.90 + +- name: AR 2025 bracket adjustment - first income in the $94,801-$94,900 row + period: 2025 + absolute_error_margin: 0.01 + input: + ar_taxable_income_indiv: 94_801 + state_code: AR + output: + # DFA 2025 Indexed Tax Brackets row "$94,801 $94,900 3.90% $389.30": + # 0.039 x 94,801 - 389.30 = 3,307.94 + ar_income_tax_before_non_refundable_credits_indiv: 3_307.94 + +- name: AR 2025 bracket adjustment - midpoint of the $94,801-$94,900 row + period: 2025 + absolute_error_margin: 0.01 + input: + ar_taxable_income_indiv: 94_851 + state_code: AR + output: + # DFA 2025 Indexed Tax Brackets row "$94,801 $94,900 3.90% $389.30": + # 0.039 x 94,851 - 389.30 = 3,309.89 + # (2025 Regular Income Tax Table, $94,801-$94,901: $3,310) + ar_income_tax_before_non_refundable_credits_indiv: 3_309.89 + +- name: AR 2025 bracket adjustment - first income in the $94,901-$95,000 row + period: 2025 + absolute_error_margin: 0.01 + input: + ar_taxable_income_indiv: 94_901 + state_code: AR + output: + # DFA 2025 Indexed Tax Brackets row "$94,901 $95,000 3.90% $379.30": + # 0.039 x 94,901 - 379.30 = 3,321.84 + ar_income_tax_before_non_refundable_credits_indiv: 3_321.84 + +- name: AR 2025 bracket adjustment - midpoint of the $94,901-$95,000 row + period: 2025 + absolute_error_margin: 0.01 + input: + ar_taxable_income_indiv: 94_951 + state_code: AR + output: + # DFA 2025 Indexed Tax Brackets row "$94,901 $95,000 3.90% $379.30": + # 0.039 x 94,951 - 379.30 = 3,323.79 + # (2025 Regular Income Tax Table, $94,901-$95,001: $3,324) + ar_income_tax_before_non_refundable_credits_indiv: 3_323.79 + +- name: AR 2025 bracket adjustment - top of the $94,901-$95,000 row + period: 2025 + absolute_error_margin: 0.01 + input: + ar_taxable_income_indiv: 95_000 + state_code: AR + output: + # DFA 2025 Indexed Tax Brackets row "$94,901 $95,000 3.90% $379.30": + # 0.039 x 95,000 - 379.30 = 3,325.70 + ar_income_tax_before_non_refundable_credits_indiv: 3_325.70 + +- name: AR 2025 bracket adjustment - first income in the $95,001-$95,100 row + period: 2025 + absolute_error_margin: 0.01 + input: + ar_taxable_income_indiv: 95_001 + state_code: AR + output: + # DFA 2025 Indexed Tax Brackets row "$95,001 $95,100 3.90% $369.30": + # 0.039 x 95,001 - 369.30 = 3,335.74 + ar_income_tax_before_non_refundable_credits_indiv: 3_335.74 + +- name: AR 2025 bracket adjustment - top of the last $10-step row + period: 2025 + absolute_error_margin: 0.01 + input: + ar_taxable_income_indiv: 97_800 + state_code: AR + output: + # DFA 2025 Indexed Tax Brackets row "$97,701 $97,800 3.90% $99.30": + # 0.039 x 97,800 - 99.30 = 3,714.90 + ar_income_tax_before_non_refundable_credits_indiv: 3_714.90 + +- name: AR 2025 bracket adjustment - first income in the and-over row + period: 2025 + absolute_error_margin: 0.01 + input: + ar_taxable_income_indiv: 97_801 + state_code: AR + output: + # DFA 2025 Indexed Tax Brackets row "$97,801 and over 3.90% $89.30": + # 0.039 x 97,801 - 89.30 = 3,724.94 + ar_income_tax_before_non_refundable_credits_indiv: 3_724.94 + +- name: AR 2024 bracket adjustment - inside the asterisked $94,301-$94,500 row + period: 2024 + absolute_error_margin: 0.01 + input: + ar_taxable_income_indiv: 94_450 + state_code: AR + output: + # DFA 2024 Indexed Tax Brackets row "*$94,301 *$94,500 3.90% $197.40" (asterisked, $200 wide): + # 0.039 x 94,450 - 197.40 = 3,486.15 + # (2024 Regular Income Tax Table, $94,401-$94,501: $3,486; PE previously applied $187.40 here -> 3,496.15) + ar_income_tax_before_non_refundable_credits_indiv: 3_486.15 + +- name: AR 2024 bracket adjustment - top of the asterisked $94,301-$94,500 row + period: 2024 + absolute_error_margin: 0.01 + input: + ar_taxable_income_indiv: 94_500 + state_code: AR + output: + # DFA 2024 Indexed Tax Brackets row "*$94,301 *$94,500 3.90% $197.40": + # 0.039 x 94,500 - 197.40 = 3,488.10 + ar_income_tax_before_non_refundable_credits_indiv: 3_488.10 + +- name: AR 2024 bracket adjustment - first income after the asterisked row + period: 2024 + absolute_error_margin: 0.01 + input: + ar_taxable_income_indiv: 94_501 + state_code: AR + output: + # DFA 2024 Indexed Tax Brackets row "$94,501 $94,600 3.90% $187.40": + # 0.039 x 94,501 - 187.40 = 3,498.14 + ar_income_tax_before_non_refundable_credits_indiv: 3_498.14 + +- name: AR 2024 bracket adjustment - top of the last $10-step row + period: 2024 + absolute_error_margin: 0.01 + input: + ar_taxable_income_indiv: 95_500 + state_code: AR + output: + # DFA 2024 Indexed Tax Brackets row "$95,401 $95,500 3.90% $97.40": + # 0.039 x 95,500 - 97.40 = 3,627.10 + ar_income_tax_before_non_refundable_credits_indiv: 3_627.10 + +- name: AR 2024 bracket adjustment - first income in the and-over row + period: 2024 + absolute_error_margin: 0.01 + input: + ar_taxable_income_indiv: 95_501 + state_code: AR + output: + # DFA 2024 Indexed Tax Brackets row "$95,501 and over 3.90% $87.40": + # 0.039 x 95,501 - 87.40 = 3,637.14 + ar_income_tax_before_non_refundable_credits_indiv: 3_637.14 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ar/tax/income/ar_income_tax_before_non_refundable_credits_joint.yaml b/policyengine_us/tests/policy/baseline/gov/states/ar/tax/income/ar_income_tax_before_non_refundable_credits_joint.yaml index 5dc32d59210..96d1a5f83b0 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ar/tax/income/ar_income_tax_before_non_refundable_credits_joint.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ar/tax/income/ar_income_tax_before_non_refundable_credits_joint.yaml @@ -104,9 +104,9 @@ ar_low_income_tax_joint: 300 state_code: AR output: - # Regular: 20_000 * 0.034 - 288 = 392 + # Regular: 20_000 * 0.034 - 287.97 = 392.03 # Low income cap: 300 - # min(392, 300) = 300 + # min(392.03, 300) = 300 ar_income_tax_before_non_refundable_credits_joint: 300 - name: Case 11, 2025 joint taxable income in 3.9% bracket, no low income cap. @@ -117,10 +117,10 @@ ar_low_income_tax_joint: 5_000 state_code: AR output: - # Regular: 50_000 * 0.039 - 420 = 1_530 + # Regular: 50_000 * 0.039 - 419.96 = 1_530.04 # Low income cap: 5_000 - # min(1_530, 5_000) = 1_530 - ar_income_tax_before_non_refundable_credits_joint: 1_530 + # min(1_530.04, 5_000) = 1_530.04 + ar_income_tax_before_non_refundable_credits_joint: 1_530.04 - name: AR 2021 MFJ with two dependents just above the low-income table cutoff uses the regular table (pe-us 9024) period: 2021 From de24b32e01d3f21813565404d70b19939c0d7c33 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Fri, 25 Sep 2026 12:53:39 -0400 Subject: [PATCH 2/3] Add AR schedule differential and invariant tests for 2021-2026 Compares rate.calc(ti) * ti - reduction.calc(ti) at every integer taxable income 0-150,000 against an independent transcription of each DFA Indexed Tax Brackets card (2021-2025) and Act 1 of 2026, and checks that tax is non-negative, never falls except the statutory $2.66 drop Act 1 of 2026 writes at $94,700 -> $94,701, and that reduction thresholds strictly increase. On upstream/main the 2024 and 2025 differential cases fail. Co-Authored-By: Claude Opus 5.5 --- .../tests/test_ar_income_tax_schedule.py | 173 ++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 policyengine_us/tests/test_ar_income_tax_schedule.py diff --git a/policyengine_us/tests/test_ar_income_tax_schedule.py b/policyengine_us/tests/test_ar_income_tax_schedule.py new file mode 100644 index 00000000000..b0a36ffbcf1 --- /dev/null +++ b/policyengine_us/tests/test_ar_income_tax_schedule.py @@ -0,0 +1,173 @@ +"""Arkansas regular income tax schedule: differential and invariant tests. + +`ar_income_tax_before_non_refundable_credits_indiv` computes +`rate.calc(ti) * ti - reduction.calc(ti)` from two single_amount scales whose +rows are shared across years, so a mis-keyed row in one year's column (a +skipped DFA row, an ignored asterisked two-row range, a duplicated +threshold) silently shifts every later bracket. These tests compare every +integer taxable income against an independent transcription of each year's +source: + +- 2021-2025: DFA Indexed Tax Brackets cards, e.g. + https://www.dfa.arkansas.gov/wp-content/uploads/2025_TaxBrackets.pdf#page=1 + Rows from the top of the flat rate bracket upward form a $100 ladder whose + minus adjustment falls $10 per row. Asterisked rows span $200, so the next + row's start is skipped. +- 2026: Act 1 of 2026 (1st Extraordinary Session), A.C.A. 26-51-201(a)(4). + +Invariants (every integer taxable income, 2021-2026): tax is non-negative; +reduction thresholds are strictly increasing; tax never falls as taxable +income rises, except the one drop Act 1 of 2026 writes into the statute: +(a)(4)(A) taxes $94,700 at $3,136.70, while (a)(4)(B) less the $290 +(a)(4)(C) adjustment taxes $94,701 at $3,134.04. +""" + +import numpy as np +import pytest + +from policyengine_us.system import system + +P = system.parameters.gov.states.ar.tax.income.rates.main +YEARS = range(2021, 2027) +TAXABLE_INCOME = np.concatenate( + [np.arange(0, 150_001, dtype=float), [250_000.0, 1_000_000.0]] +) + + +def ladder(first_threshold, last_threshold, first_adjustment, wide_rows=()): + """$100 rows from first to last threshold, $10 less adjustment per row. + + `wide_rows` are the starts of asterisked rows that span $200. + """ + skipped = {start + 100 for start in wide_rows} + starts = [ + t for t in range(first_threshold, last_threshold + 1, 100) if t not in skipped + ] + return [(t, first_adjustment - 10 * k) for k, t in enumerate(starts)] + + +# (From, rate, minus adjustment) as printed on each DFA card. +DFA_CARDS = { + 2021: [ + (0, 0, 0), + (4_800, 0.02, 95.98), + (9_500, 0.03, 190.97), + (14_300, 0.034, 248.17), + (23_600, 0.05, 439.96), + (39_700, 0.059, 797.25), + (84_501, 0.059, 687.50), + (85_501, 0.059, 587.50), + (86_501, 0.059, 487.50), + (87_901, 0.059, 387.50), + (89_001, 0.059, 287.50), + (90_101, 0.059, 247.50), + ], + 2022: [ + (0, 0, 0), + (5_100, 0.02, 101.98), + (10_300, 0.03, 204.97), + (14_700, 0.034, 263.77), + (24_300, 0.049, 628.25), + ] + + [ + (t, 0.049, a) + for t, a in ladder(87_001, 91_801, 627.20, wide_rows=(87_401, 90_901)) + ], + 2023: [ + (0, 0, 0), + (5_300, 0.02, 105.98), + (10_600, 0.03, 211.97), + (15_100, 0.034, 272.37), + (25_000, 0.047, 597.35), + ] + + [ + (t, 0.047, a) + for t, a in ladder(89_601, 94_201, 583.70, wide_rows=(90_001, 90_901, 93_601)) + ], + 2024: [ + (0, 0, 0), + (5_500, 0.02, 109.98), + (10_900, 0.03, 218.97), + (15_600, 0.034, 281.37), + (25_700, 0.039, 409.86), + ] + + [(t, 0.039, a) for t, a in ladder(92_301, 95_501, 397.40, wide_rows=(94_301,))], + 2025: [ + (0, 0, 0), + (5_600, 0.02, 111.98), + (11_200, 0.03, 223.97), + (16_000, 0.034, 287.97), + (26_400, 0.039, 419.96), + ] + + [(t, 0.039, a) for t, a in ladder(94_701, 97_801, 399.30)], +} + + +def card_tax(year, ti): + rows = DFA_CARDS[year] + starts = np.array([r[0] for r in rows]) + i = np.searchsorted(starts, ti, side="right") - 1 + rate = np.array([r[1] for r in rows])[i] + adjustment = np.array([r[2] for r in rows])[i] + return rate * ti - adjustment + + +def act_1_of_2026_tax(ti): + # (a)(4)(A), net income <= $94,700: marginal rates from each row's "From". + low = sum( + rate * np.clip(ti - start, 0, end - start) + for start, end, rate in [ + (5_600, 11_200, 0.02), + (11_200, 16_000, 0.03), + (16_000, 26_400, 0.034), + (26_400, np.inf, 0.037), + ] + ) + # (a)(4)(B), net income > $94,700: 2% on the first $4,700, 3.7% above. + high = 0.02 * 4_700 + 0.037 * (ti - 4_700) + # (a)(4)(C): $290 at $94,701-$94,800, $10 less per $100, $0 from $97,601. + step = np.floor((np.ceil(ti) - 94_701) / 100) + high -= np.where(ti <= 97_600, 290 - 10 * step, 0) + return np.where(ti <= 94_700, low, high) + + +def model_tax(year, ti): + instant = f"{year}-01-01" + return P.rate(instant).calc(ti) * ti - P.reduction(instant).calc(ti) + + +def source_tax(year, ti): + return act_1_of_2026_tax(ti) if year == 2026 else card_tax(year, ti) + + +@pytest.mark.parametrize("year", YEARS) +def test_ar_schedule_matches_source_at_every_integer_income(year): + diff = model_tax(year, TAXABLE_INCOME) - source_tax(year, TAXABLE_INCOME) + bad = np.flatnonzero(np.abs(diff) > 0.005) + assert bad.size == 0, ( + f"{year}: {bad.size} incomes differ from the source, first at " + f"{TAXABLE_INCOME[bad[0]]:,.0f} (model - source = {diff[bad[0]]:+.2f})" + ) + + +# {income: change in tax from income to income + 1} where the statute itself +# makes tax fall: A.C.A. 26-51-201(a)(4)(A) vs (a)(4)(B)-(C), Act 1 of 2026. +STATUTORY_DROPS = {2026: {94_700: -2.66}} + + +@pytest.mark.parametrize("year", YEARS) +def test_ar_schedule_tax_is_nonnegative_and_nondecreasing(year): + tax = model_tax(year, TAXABLE_INCOME) + assert tax.min() >= -1e-9 + change = np.diff(tax) + falls = { + int(TAXABLE_INCOME[i]): round(float(change[i]), 2) + for i in np.flatnonzero(change < -1e-9) + } + assert falls == STATUTORY_DROPS.get(year, {}) + + +@pytest.mark.parametrize("year", YEARS) +def test_ar_reduction_thresholds_strictly_increase(year): + thresholds = [t for t in P.reduction(f"{year}-01-01").thresholds if t < np.inf] + assert all(a < b for a, b in zip(thresholds, thresholds[1:])), thresholds From 304550618b6179f8b06f8572cd30305c57fe6c7c Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Fri, 25 Sep 2026 13:05:13 -0400 Subject: [PATCH 3/3] Check reduction.yaml row thresholds directly, not the merged loaded scale The loaded scale can't show a duplicated or out-of-order row: add_bracket sorts thresholds and sums duplicate amounts. Reading each bracket's own threshold flags the pre-#9026 2023 duplicates (91,701 and 91,801), which the previous check passed. Caught in independent review. Co-Authored-By: Claude Opus 5.5 --- .../tests/test_ar_income_tax_schedule.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/policyengine_us/tests/test_ar_income_tax_schedule.py b/policyengine_us/tests/test_ar_income_tax_schedule.py index b0a36ffbcf1..3e77abb8779 100644 --- a/policyengine_us/tests/test_ar_income_tax_schedule.py +++ b/policyengine_us/tests/test_ar_income_tax_schedule.py @@ -15,9 +15,10 @@ row's start is skipped. - 2026: Act 1 of 2026 (1st Extraordinary Session), A.C.A. 26-51-201(a)(4). -Invariants (every integer taxable income, 2021-2026): tax is non-negative; -reduction thresholds are strictly increasing; tax never falls as taxable -income rises, except the one drop Act 1 of 2026 writes into the statute: +Invariants (2021-2026): reduction.yaml rows carry strictly increasing +finite thresholds, with every .inf row after them. At every integer taxable +income, tax is non-negative and never falls as income rises, except the one +drop Act 1 of 2026 writes into the statute: (a)(4)(A) taxes $94,700 at $3,136.70, while (a)(4)(B) less the $290 (a)(4)(C) adjustment taxes $94,701 at $3,134.04. """ @@ -168,6 +169,12 @@ def test_ar_schedule_tax_is_nonnegative_and_nondecreasing(year): @pytest.mark.parametrize("year", YEARS) -def test_ar_reduction_thresholds_strictly_increase(year): - thresholds = [t for t in P.reduction(f"{year}-01-01").thresholds if t < np.inf] - assert all(a < b for a, b in zip(thresholds, thresholds[1:])), thresholds +def test_ar_reduction_rows_have_strictly_increasing_thresholds(year): + # Read each YAML row's own threshold: the loaded scale can't show a + # mis-keyed row, because add_bracket sorts thresholds and sums the amounts + # of duplicates. + instant = f"{year}-01-01" + thresholds = [bracket.threshold(instant) for bracket in P.reduction.brackets] + finite = [t for t in thresholds if t < np.inf] + assert thresholds[: len(finite)] == finite, thresholds + assert all(a < b for a, b in zip(finite, finite[1:])), finite