Repository navigation
Derive Arkansas 2026+ minus adjustments from the indexed statutory tables - #9629
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #9629 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 4 4
Lines 76 67 -9
Branches 2 3 +1
=========================================
- Hits 76 67 -9
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
…bles reduction.yaml had no uprating, so from 2027 its thresholds and amounts stayed at 2026 values while rate.yaml's thresholds uprated, and tax fell by up to $111.98 as income crossed a 2026 bound. From 2026 (no DFA Indexed Tax Brackets card yet), compute the regular tax from A.C.A. 26-51-201(a)(4) as amended by Act 1 of 2026: table (A) at marginal rates up to the high-income threshold; above it, table (B) less the (C) bracket adjustment. The threshold, the (B) 2% row top and each (C) row bound are new parameters indexed like the rate thresholds. The reduction is derived from the same tables, so it moves with them (and with reforms). 2021-2025 keep the published-card schedule behind a new use_published_reduction switch; 2026 results are unchanged. 26-51-201(d)(1) indexes bracket amounts "rounding to the nearest one hundred dollars ($100)", so rounding moves from downwards to nearest. The (C) dollar amounts stay fixed, since (d) indexes only bracket bounds. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…shes - Helper docstring: marginal taxing keeps tax continuous at every (A) and (B) row bound; the statute's (A)/(B)-(C) seam and (C) row steps remain. - (B) and rate-table descriptions say which income each rate applies to. - Changelog: the threshold, (B) top and (C) bounds were not indexed before (not rounded down); the rounding change also moves withholding's bounds. - Drop the four 2027 YAML cases next to the indexed threshold, which sit within ~0.03% of a nearest-$100 flip; the parameter-relative differential and ladder tests cover them. - The AR rounding regression test now derives expected bounds from the loaded index for 2027-2035 and asserts they differ from rounding down. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
f6b111e to
cc053d3
Compare
…ompute The switch started in 2014, so for earlier years it was undefined and the AR tax variables raised ParameterNotFoundError, where main returned $0. Independent review flagged the risk; reproduced for 2012 and 2013 and pinned with a test. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Admin-merged (squash, --match-head-commit e00c01e) 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 on head e00c01e: |
Summary
From 2027, Arkansas income tax projections were internally inconsistent:
rates/main/rate.yamlthresholds uprate (gov.irs.uprating, rounded down to $100).rates/main/reduction.yaml, the minus-adjustment scale intax = rate × TI − reduction, had no uprating, so its thresholds and amounts stayed at their 2026 values.As a result, 2027+ tax fell as income crossed each 2026 bound: −$111.98 at $11,200, −$63.97 at $16,000 and −$79.17 at $26,400 (and −$112 at $5,600 before the $0 floor). Tax was also wrong between the old and uprated bounds.
This PR stops storing the 2026+ minus adjustments and derives them from the tables that A.C.A. § 26-51-201(a)(4) (Act 1 of 2026) sets out and that § 26-51-201(a)(5) and (d) index each year:
rate.yaml, taxed at marginal rates, each from its row's "From" bound.high_income/rate.yaml, 2% to $4,700 and 3.7% above, applied to all of the filer's net income.high_income/bracket_adjustment.yaml, $290 falling $10 per $100 row to $0. It is subtracted from (B).high_income/threshold.yaml, $94,700.ar_main_income_tax(new, inar_income_tax_helpers.py) now computes the schedule forar_income_tax_before_non_refundable_credits_indiv,…_jointandar_uses_low_income_tax_tables, which each used to repeatrate × TI − reduction.use_published_reduction(true through 2025). Results are unchanged.What § 26-51-201(d) indexes, and how it rounds
Quoted from the enacted Acts. Act 1 of 2026 changed only (a)(4) and added (a)(5); it left (d) as amended by Act 532 of 2023.
What that means for each amount, and what this PR does:
Rounding. The statute says nearest $100, but
rate.yamlrounded down, so this PR switches it tonearest. DFA's cards follow the statute. Act 532 of 2023's TY2023 table starts its rows at $5,100 / $10,300 / $14,700 / $24,300 and tops out at $87,000. The 2023 card has $5,300 / $10,600 / $15,100 / $25,000 / $89,600. That is each amount × 1.03 (the COLA cap) rounded to the nearest $100: 5,100 × 1.03 = 5,253 → 5,300. Rounding down would need a 3.9% COLA, above the 3% cap.rate.yamlbrackets 5 and 6, which are.infin every year since 2021/2022, drop their uprating metadata: core roundsnearestwith Python'sround, which overflows on infinity.Row keys. Each (C) row is keyed on the round "Less Than or Equal To" bound of the row before it (94,700, 94,800, …, 97,600) and evaluated with
calc(right=True). Rounding those round numbers to the nearest $100 keeps every row starting exactly one dollar above the prior bound. The first row always shares the high-income threshold's value, and a test checks this for every year.Before and after (2027)
ar_income_tax_before_non_refundable_credits_indiv, 2027:Every integer taxable income from $0 to $200,000:
"Base" is
mainbefore this PR: the 2027+ rate thresholds rounded down, with the minus adjustments frozen at 2026.Invariants
policyengine_us/tests/test_ar_income_tax_schedule.py(extended from #9624) checks, at every integer taxable income:uv.lockis committed, so these use seeded numpy generators instead.The 2027 YAML cases use only incomes whose tax survives a one-step change in the projected uprating factor. The (B)–(C) rows next to the indexed threshold sit within about 0.03% of a nearest-$100 flip, and a routine C-CPI-U refresh could move them. The index-relative Python tests cover those rows instead, and
test_state_uprating_rounding.pynow derives its expected 2027–2035 bounds from the loaded index.Verification
0000-01-01, so years beforerate.yaml's first value still take the published path. An independent reviewer caught that the first version raisedParameterNotFoundErrorthere; a test now pins it.test_ar_income_tax_schedule.pyplustests/core/test_state_uprating_rounding.py: 309 passed.tests/policy/baseline/gov/states/arYAML folder: 718 passed.downwards.right=Falseon the ladder, and<for<=at the threshold.cc053d30ff, then APPROVE on the final head's delta (e00c01eba7, the pre-2014 fix). Both reviews were read-only, so they didn't run anything; the runs above are mine.mainafter Fix Arkansas 2025 and 2024 income tax minus-adjustment schedules against the DFA cards #9624, Fix Arkansas 2014-2020 income tax rate schedules #9611, Give Arkansas 2015-2020 income tax parameters their own values #9615, Use Arkansas's own medical expense deduction floor #9612 and Use Arkansas's own miscellaneous and casualty loss itemized deduction rules #9625 merged. Main's 2025–2027 AR schedule values are the same as Fix Arkansas 2025 and 2024 income tax minus-adjustment schedules against the DFA cards #9624's head, so the before/after tables above describemain.API note. From 2026,
gov.states.ar.tax.income.rates.main.reductionhas no effect: its 2025 values carry forward but go unused. Reformrates.main.rateandrates.main.high_income.*instead.Not changed (follow-ups)
gov.irs.uprating(chained CPI-U). Index IRS parameters to the 12-months-ending-August chained CPI-U, with CBO's tax-year projections #9621 is reworking the CPI projection series, so switching AR to a statutory COLA index is Index Arkansas income tax brackets by the statutory CPI-U COLA, capped at 3% #9638. DFA's 2025 card fits unadjusted CPI-U: 92,300 → 94,700 needs a factor in [1.02546, 1.02654); unadjusted CPI-U gives 1.026531 andgov.irs.upratinggives 1.028831.ar_withheld_income_taxapplies the marginal rate to all of reduced AGI with no minus adjustment. That predates this PR: ar_withheld_income_tax ignores Arkansas's minus adjustments and exemption credit #9640. It readsrate.yaml, so the nearest-$100 rounding does move its 2027+ bounds, e.g. from $5,700 to $5,800.axiom: TheAxiomFoundation/rulespec-us#1418 debt (the rulespec-us AR pilot is bounded to TY2026 "because section 26-51-201(a)(5) provides for later annual adjustment"; TY2027+ indexing under (d) is unencoded)
🤖 Generated with Claude Code