Skip to content

Fix Arkansas 2025 and 2024 income tax minus-adjustment schedules against the DFA cards - #9624

Merged
MaxGhenis merged 3 commits into
mainfrom
fix-ar-2025-reduction-schedule
Sep 26, 2026
Merged

MaxGhenis merged 3 commits into
mainfrom
fix-ar-2025-reduction-schedule

Conversation

@MaxGhenis

@MaxGhenis MaxGhenis commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • 2025: rates/main/reduction.yaml jumped from the $26,400 row ($420) straight to $95,001. It skipped the three DFA rows for $94,701–$95,000, so taxable income in that band got the $420 reduction instead of $399.30, $389.30 or $379.30 and was undertaxed by $20.70–$40.70. The 2025 column also used whole-dollar amounts instead of DFA's published cents: 112, 224, 288, 420, then 369, 359, … 89 instead of 111.98, 223.97, 287.97, 419.96, then 369.30, 359.30, … 89.30. This PR re-keys the whole 2025 column to the 2025 Indexed Tax Brackets card.
  • 2024 (found while verifying the other years): the card's asterisked row "*$94,301 *$94,500 3.90% $197.40" is intentionally $200 wide. The 2024 column started the next row at $94,401, so every income from $94,401 to $95,500 took the next $10 step down and was overtaxed by $10. This is the same defect AR 2023 bracket-adjustment column mistranscribed: missing $89,901 row, un-encoded asterisked $200 ranges, duplicate 91,701/91,801 thresholds (40/44 rows off) #9026 fixed for 2023.
  • Moves the 2025 booklet reference in reduction.yaml and rate.yaml from #page=26 to #page=30. #page=26 matched the printed page number, but PDF page 26 is "For Taxpayers' Information". The Regular Income Tax Table starts at PDF page 30. Both files now also cite the 2025 TaxBrackets card.
  • Tests added or updated:
    • 17 YAML tests covering 2025's $94,701–$95,000 band and its boundaries, the 2025 ladder ends, and the 2024 asterisked row.
    • 4 existing 2025 tests move from rounded amounts to DFA cents, with the margin tightened from 1 to 0.01. The joint test file gets the same cents correction in its comments and in one expected value.
    • A new pytest, policyengine_us/tests/test_ar_income_tax_schedule.py; see "Invariants" below.

Before and after

ar_income_tax_before_non_refundable_credits_indiv, computed as 3.9% × taxable income − the row's minus adjustment:

Year Taxable income DFA row upstream/main This PR
2025 94,700 $26,400–$94,700, $419.96 3,273.30 3,273.34
2025 94,751 $94,701–$94,800, $399.30 3,275.29 3,295.99 (table: $3,296)
2025 94,851 $94,801–$94,900, $389.30 3,279.19 3,309.89 (table: $3,310)
2025 94,951 $94,901–$95,000, $379.30 3,283.09 3,323.79 (table: $3,324)
2025 95,001 $95,001–$95,100, $369.30 3,336.04 3,335.74
2024 94,450 $94,301–$94,500, $197.40 3,496.15 3,486.15 (table: $3,486)
2024 95,500 $95,401–$95,500, $97.40 3,637.10 3,627.10

"Table" is DFA's Regular Income Tax Table value for the $100 band. DFA computes it at the band's midpoint and rounds to the dollar: 2025, 2024.

Why DFA's cents, not whole dollars

The rounded 2025 amounts weren't a documented choice. #7362 cited the booklet's whole-dollar tax table, not the TaxBrackets card. The 2021–2024 columns all carry DFA's cents. The card says "If you use a formula to calculate Arkansas income tax, the results must match the table exactly", and its worked examples subtract the cents amount ($75,950 x .039 = $2,962.05 - $419.96).

The rounded amounts don't reproduce DFA's table either. I parsed all 949 bands of the 2025 Regular Income Tax Table (PDF pages 30–34) and evaluated the model at each band's midpoint, rounding half up:

2025 Regular Income Tax Table upstream/main This PR
Bands missed because of the three skipped rows 3 0
Bands missed by $1 because of rounding (between $75,501 and $99,501) 35 0
Total missed of 949 38 0

The same check on 2024: upstream/main misses the 11 bands from $94,401 to $95,501; this PR misses none.

Rows are shared across years

After the fix, 2025 rows 5–36 hold $94,701 + $100k with amount $399.30 − $10k. They line up exactly with the 2026 rows from Act 1 of 2026 ($94,701 + $100k, amount $369.90 − $10k). The two rows that became finite in 2025 ($97,701 and $97,801) already had explicit 2026-01-01: .inf, so 2026 inherits nothing new.

Verification

  • Every integer taxable income, 0–110,000 (plus 150,000 and 1,000,000), compared with the source. 2021–2025 use the DFA Indexed Tax Brackets cards. 2026 uses Act 1 of 2026 § 1 (A.C.A. § 26-51-201(a)(4)(A)–(C)):

    Year 2021 2022 2023 2024 2025 2026
    Source rows 12 52 50 37 37 Act
    Mismatches, upstream/main 0 0 0 1,100 104,403 0
    Mismatches, this PR 0 0 0 0 0 0

    Independent agents re-parsed each year's source with pdfplumber and pdftotext. They found 0 mismatches on this branch for 2021–2025 and the same upstream/main mismatch ranges.

  • Loaded scales, 2015–2035 (Jan 1 and Jul 1 of each year): only the 2024 and 2025 reduction scales change. rate.yaml's loaded values are identical; only its references changed. rate.yaml needs no new rows, because the rate is a flat 3.9% from $26,400 up in both years.

  • Tests:

    • policyengine-core test policyengine_us/tests/policy/baseline/gov/states/ar → 513 passed.
    • The new pytest → 18 passed.
    • Against upstream/main's parameters:
      • 20 of the 46 cases in the indiv YAML file fail: the 4 re-centred 2025 cases, the 12 new 2025 cases, and 4 of the 5 new 2024 cases. The 2024 $95,501 boundary case passes on both, because that row was already correct.
      • The pytest's 2024 and 2025 differential cases fail.
  • Open PRs nearby:

  • Citation check: arkleg's status page says "Notification that HB1001 is now Act 1" (5/6/2026), so the existing Act 1 citation is correct.

Invariants

policyengine_us/tests/test_ar_income_tax_schedule.py checks these for every integer taxable income from 0 to 150,000 (plus 250,000 and 1,000,000) in 2021–2026:

  1. Differential: the model's rate × TI − reduction equals an independent, compact transcription of each DFA card or Act 1 of 2026. The transcription is the base rows plus a $100/$10 ladder with explicit asterisked $200 rows. The check allows at most half a cent. It catches this whole class of bug: skipped rows, ignored asterisked rows, shifted rows.
  2. Tax is non-negative.
  3. Tax never falls as income rises, with one exception labeled as intended. Act 1 of 2026 itself sets $3,136.70 at $94,700 under (a)(4)(A) and $3,134.04 at $94,701 under (a)(4)(B) less the $290 (a)(4)(C) adjustment, a $2.66 drop written into the statute. The test pins that drop exactly.
  4. Row thresholds strictly increase: in each year, the reduction.yaml rows carry strictly increasing finite thresholds, with every .inf row after them. The test reads each row's own threshold. The loaded scale can't reveal a mis-keyed row, because add_bracket sorts thresholds and sums duplicate amounts. This check flags the pre-AR 2023 bracket-adjustment column mistranscribed: missing $89,901 row, un-encoded asterisked $200 ranges, duplicate 91,701/91,801 thresholds (40/44 rows off) #9026 2023 duplicates (91,701 and 91,801), which a loaded-scale check passes. The independent review caught that the first version of this test checked the loaded scale.

Not changed

  • 2026 lower brackets (112 / 224 / 288 / 367.20): Act 1 of 2026 gives marginal rates only, and DFA has not published a 2026 TaxBrackets card. The 2026 amounts follow the Act's "From" bounds. DFA's 2021–2025 cards instead count from the "Less Than or Equal To" bound (111.98 = 2% × 5,599). If DFA's 2026 card keeps that convention, the lower 2026 amounts would become 111.98 / 223.97 / 287.97 / 367.16, a 2–4 cent change. That is left for when the card is published.
  • The booklet's shortcut above $100,000 ("$3,809 + 3.9% of the excess over $100,000" for 2025; "$3,811 + …" for 2024) is $1.70 and $1.60 below the card's bracket formula (0.039 × TI − 89.30 / − 87.40). PolicyEngine follows the bracket formula, as it did before.

axiom: TheAxiomFoundation/rulespec-us#1410 debt. Axiom has Arkansas income tax only for TY2026 (the Act 1 of 2026 pilot, bounded to 2026). #1405 covers TY2014–2020. #1410 records the TY2021–2025 schedule, including these 2024 and 2025 rows.

🤖 Generated with Claude Code

MaxGhenis and others added 2 commits September 25, 2026 07:20
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 <noreply@anthropic.com>
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 <noreply@anthropic.com>
…cale

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 <noreply@anthropic.com>
@MaxGhenis
MaxGhenis merged commit d344d16 into main Sep 26, 2026
35 checks passed
@MaxGhenis
MaxGhenis deleted the fix-ar-2025-reduction-schedule branch September 26, 2026 14:44
@MaxGhenis

Copy link
Copy Markdown
Contributor Author

Admin-merged (squash, --match-head-commit 3045506) under Max's 2026-09-26 ruling (d399: obvious improvements need no permission; admin-merge when the only block is a required review only Max could give). Gates: gh pr checks exit 0 (37 pass), MERGEABLE, no CHANGES_REQUESTED. Approvals: an independent adversarial Opus 5.5 review of the final head (workflow wf_b23156c4), which re-checked the 2025/2024 values against the DFA Indexed Tax Brackets cards and found no blocker or major findings, plus the session-management main session's own diff review. Closes decision d396.

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.

1 participant