Skip to content

Fix Arkansas tax indexing, Kentucky 2021 CDCC, and WV 529 coordination - #10324

Open
MaxGhenis wants to merge 8 commits into
mainfrom
statute-bugs-ar-ky-wv
Open

MaxGhenis wants to merge 8 commits into
mainfrom
statute-bugs-ar-ky-wv

Conversation

@MaxGhenis

@MaxGhenis MaxGhenis commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

WIP: the three source corrections and targeted validation are complete. Full affected-folder checks remain incomplete: 56 YAML files and one Python file are unrun. No microsimulation ran here; the hub will run the impact.

Plan:

  • Commit regression YAML witnesses before the production corrections.
  • Fix Arkansas's projected index, Kentucky's 2021 CDCC conformity, and West Virginia's settled 529 coordination issue.
  • Complete affected tests one file per foreground process with thread caps. Preserve published history and unrelated years.

Arkansas — us-ar-income-tax-index-series

Source: Act 1459 of 2013, §2, PDF p3; Act 532 of 2023, PDF p4; Act 1 of 2026, PDF pp2–3.

What changed: added a dedicated unchained CPI-U index using September–August averages, annual increases floored at zero and capped at 3%, applied to the four indexed threshold families. Keep the shared IRS index, published history, nearest-$100 rounding, formulas, and fixed bracket adjustments.

The statute requires rounding to the nearest $100 but leaves exact $50 ties unspecified: half-up and ties-to-even give different boundaries. This PR retains Core's existing ties-to-even convention. The projected-schedule reference had used half-up; its helper is corrected to preserve the implemented convention. For example, a synthetic 3% increase takes $95,000 to $97,850, which Core rounds to $97,800. The tie-breaking interpretation remains open; this synthetic example asserts no actual 2027 coefficient.

Witness: complete synthetic 4% CPI-U / 1% chained windows imply a 3% Arkansas increase and $5,468.40 tax at $150,000 taxable income; 1% growth and deflation witnesses each produce $5,470.10. These demonstrate the mechanism, not an actual 2027 estimate. October 2025's missing CPI observation remains unresolved; no actual 2027 coefficient is asserted.

Years: projected 2027+.

Kentucky — us-ky-arpa-2021-cdcc-static-conformity

Source: 2021 Ky. Acts ch31 §1, PDF p3, KRS 141.067, 2021 Form 2441-K, PDF pp1–3, and 2020 IRC §21, PDF pp1,3.

What changed: added a 2021-only computation under the December 31, 2018 Code, using 2020 federal parameters for expense caps, rates, and section129 benefits, earned-income/filing limits, and federal liability limitation before Kentucky's existing 20% match. Preserve live federal 2021 and other Kentucky years.

Witness: $50,000 AGI, two qualifying individuals, $10,000 care expenses and sufficient liability produces $240 Kentucky potential credit (baseline $1,000). Zero federal credit liability produces zero; $450,000 AGI retains $120 because the conformed law has no ARPA second phaseout.

Years: 2021 only.

West Virginia — us-wv-senior-modification-base-529

Source: W. Va. Code §11-21-12(c)(9), §11-21-12a, 2000 HB4679, PDF p3, and 2025 Schedule M, PDF pp5–6.

What changed: removed 529 contribution payments from the senior/disability excluded-income list. Keep the separate 529 deduction and all other exclusions and modifications. Only the settled 529 classification is changed.

The income-base question has two defensible readings. The literal statutory reading allows the lesser of federal AGI and the $8,000 allowance remaining after the enumerated interest, retirement, and Social Security modifications. The Schedule M reading first removes the person's other excluded income, including taxable state or local refunds and military service pay, caps the remainder at $8,000, and then subtracts the enumerated modifications. For low-income seniors, the literal reading can deduct income already covered by another modification. Max's d1744.2 ruling retains the existing Schedule M computation to avoid that duplicate deduction; this PR preserves that base reading.

Witness: a senior with $6,000 personal AGI and $2,000 529 contributions receives a $6,000 senior modification plus the separate $2,000 529 deduction. With a $40,000 ineligible spouse, subtractions total $8,000, WV AGI is $38,000, and taxable income is $34,000 (baseline $36,000).

Years: deduction variable 2014+; integrated subtraction list retains its existing 2021 start.

Validation

Formatting and lint (make format), Python syntax, and changed parameter/test YAML parsing pass. All 13 future-year Arkansas YAML cases use complete synthetic CPI windows. Current head is 811d94de43901d6cdad443cc5516bd69011abd4a (eight commits). bfe below means bfe165ff288994facb146b5af441640aac2ddd70, before the AR reference-helper correction; d7 means d7fd2b508f531a9e50eeb5131b75a8b536dec2d7, before the KY fixture correction. Both later corrections change tests only; production source and earlier YAML results remain applicable.

Test Revision Pytest result Pytest seconds Outer exit
WV senior deduction person YAML d7; relevant source unchanged 22 passed 177.05 0
KY CDCC, initial file d7 22 passed; 1 malformed input fixture 1,406.40 1, interrupted after summary
KY corrected scalar boundaries, filtered CLI bfe 6 passed 69.41 0
AR individual income-tax YAML, full file bfe 73 passed 373.19 0
AR joint income-tax YAML, full file bfe 15 passed 176.75 0
AR schedule Python, initial full run bfe 377 passed; 1 reference-helper mismatch 77.57 1, natural exit
AR schedule Python, corrected full rerun current 378 passed 18.75 0
WV senior-deduction property tests current 4 passed 128.08 0
State uprating rounding Python, full file current 29 passed 50.58 0
New AR indexing Python file Before final fixture optimization 9 passed 1,128.25 1, timing wrapper failure
AR indexing Python, post-optimization full rerun current 9 passed 67.61 0
Completed run Native wall seconds Native user / sys seconds Plugin peak RSS MiB Plugin user / sys seconds
WV person YAML 2,059.33 50.35 / 10.46 unavailable unavailable
KY initial file 3,311.43 114.27 / 47.88 unavailable unavailable
KY corrected boundaries 1,310.30 55.42 / 10.17 2,024.8 43.81 / 9.78
AR individual YAML 901.47 126.79 / 10.54 5,806.8 85.40 / 9.57
AR joint YAML 910.69 78.37 / 9.03 3,284.7 56.69 / 8.53
AR schedule Python, initial 687.62 28.52 / 6.20 1,001.8 25.07 / 6.05
AR schedule Python, corrected 347.31 23.21 / 4.10 1,033.8 20.25 / 4.00
WV property tests 271.76 40.66 / 7.73 956.3 37.59 / 7.64
State rounding Python 165.53 28.00 / 3.59 1,457.2 23.09 / 3.44
AR indexing Python, before optimization 2,422.27 53.36 / 11.25 unavailable unavailable
AR indexing Python, after optimization 237.39 29.02 / 4.12 1,455.9 23.97 / 3.92

KY boundaries and both AR YAML resource plugins reported pytest status 0; the initial AR schedule plugin reported status 1. Its reference helper used half-up at the $97,850 tie while Core preserved ties-to-even. Only that test helper was corrected to existing round; no production change was made. The corrected full rerun passed all 378 cases with pytest/plugin status 0 and clean outer exit 0. The full WV property-test file passed all four cases with pytest/plugin status 0 and clean outer exit 0. The full state-rounding Python file passed all 29 cases with pytest/plugin status 0 and clean outer exit 0. The final full indexing rerun passed all nine cases with pytest/plugin status 0 and clean outer exit 0. Testing has stopped; no active test processes or further tests remain. Local logs and resource reports are preserved as untracked hub evidence.

KY's initial failure was input construction: six AGI values for one tax unit, before any policy assertion. The fixture now uses six scalar cases. All 28 current cases have successful results across two runs (22 unchanged plus six corrected); the full revised file was not rerun in one process. The initial process was interrupted with terminal Ctrl-C after more than seven minutes of post-summary shutdown and reported abnormal termination; this does not change its recorded pytest results. The earlier pre-fix WV CLI attempt produced no output for more than 47 minutes before interruption (exit 130), so no red-test result was observed.

All four changed YAML files have 138 current case passes across runs (73 AR individual, 15 AR joint, 28 KY, 22 WV). Broader validation remains incomplete: 56 other affected YAML files are unrun. The corrected full AR schedule file passed all 378 cases. WV senior-deduction properties passed all four cases. All four current Python files passed their 420 cases (378 AR schedule, four WV properties, 29 state rounding, nine indexing). AR low-income tables are the one genuinely unrun affected Python file. Full folder validation exceeds the available job window at the observed startup rate. No microsimulation ran; the hub will run impact. Draft CI jobs were skipped by the existing draft condition.

Python coverage uses seven tiny-tree index/window cases and two Core integration cases sharing a read-only fixture based on the package reference model; policy amounts use YAML. Shared fixture setup took 1,091.27 seconds in the pre-optimization Python run. Its tests passed, but the outer timing wrapper failed on sandboxed sysctl kern.clockrate, preventing a peak-RSS measurement. A read-only Core review confirmed parameter cloning before Reform.apply; the fixture now uses that owned clone, removing a redundant full-tree deepcopy. The final indexing rerun passed nine cases in 67.61 pytest seconds, including 59.93 seconds of shared fixture setup, with 237.39 seconds native wall time and 1,455.9 MiB peak RSS. Before optimization those measurements were 1,128.25 pytest seconds, 1,091.27 setup seconds and 2,422.27 native wall seconds; before peak RSS is unavailable. Host load and cache variability prevent attributing the elapsed difference to the optimization. AR's 73-case YAML file also passes after the change. Existing WV property tests classify 529 payments separately without adding a simulation-heavy property test.

CI routing is unchanged: root-level AR Python files use Rest Python's remaining group (shard 1); core state-rounding and WV files use core (shard 2). Makefile historical coarse-group measurements were 14.4 GB / 22:18 for remaining and 13.3 GB / 11:51 for core (run 38141803955), followed by existing sequential isolation splits targeting approximately 10 GB per process. These historical figures and local overloaded-macOS timings are not estimates for this PR's Linux CI cost; incremental Linux CI before/after measurements are unavailable.

axiom: pending: hub files parity

@MaxGhenis
MaxGhenis marked this pull request as ready for review October 21, 2026 02:29
@MaxGhenis MaxGhenis closed this Oct 21, 2026
@MaxGhenis MaxGhenis reopened this Oct 21, 2026
@MaxGhenis MaxGhenis closed this Oct 21, 2026
@MaxGhenis MaxGhenis reopened this Oct 21, 2026
@DTrim99

DTrim99 commented Oct 21, 2026

Copy link
Copy Markdown
Collaborator

PR Review: Fix Arkansas tax indexing, Kentucky 2021 CDCC, and WV 529 coordination

PR #10324 (author: MaxGhenis), head 811d94de43. This is a first review. The PR makes three model changes:

  • Arkansas indexing (2027+). A new index, gov.states.ar.tax.income.uprating, replaces gov.irs.uprating for the four indexed bound families: the main rate thresholds, the high-income threshold, the (B) table's 2% bound and the (C) bracket-adjustment rows. It is built in extend_ar_income_tax_uprating from unchained CPI-U averages over September-August windows. The yearly increase is floored at 0 and capped at 3% (uprating_cap). The index is 1 in 2026, so projections start from the Act 1 of 2026 tables.
    • Tests. The schedule test's reference rounding moves from half-up to Python's round (ties to even). A fixture defines three synthetic CPI reforms; 13 Arkansas YAML cases now run under them, and a new Python file tests the index.
  • Kentucky 2021 CDCC. ky_cdcc_potential gets a formula_2021_01_01. It recomputes the federal credit under the pre-ARPA section 21, reading the 2020 IRS parameters:
    • the $3,000/$6,000 expense limits, reduced by a $5,000/$2,500 section 129 exclusion;
    • the 35%-to-20% rate;
    • the federal liability limit;
    • then Kentucky's 20% match.
    • A formula_2022_01_01 restores the ordinary path. There are 20 new YAML cases.
  • West Virginia 529 coordination. From 2014, investment_in_529_plan_indv is no longer one of the person's amounts excluded from the senior/disability income base. Four YAML expectations change, four cases are added, and the property tests drop the 529 source.
  • Changelog: a fixed fragment.

The PR has no comments or reviews yet. It touches no partner test file.

Sources read for this review (all fetched 2026-10-21):

Summary

What is right.

  • Kentucky 2021. The PR's reading is correct, and the computation matches Form 2441-K line for line.
    • The statute. KRS 141.067: "The credit shall be twenty percent (20%) of the federal credit allowed under Section 21 of the Internal Revenue Code."
    • The Code it means. For 2021, 2021 Ky. Acts ch. 31 § 1 defines the Code in KRS 141.010(21)(b): "For taxable years beginning on or after January 1, 2019, the Internal Revenue Code in effect on December 31, 2018, exclusive of any amendments made subsequent to that date". 2022 Ky. Acts ch. 212 § 42 moves the reference date to December 31, 2021 only "for taxable years beginning on or after January 1, 2022". So ARPA's 2021 section 21 is excluded.
    • The form. The 2021 Form 2441-K instructions (file page 3) say: "Kentucky does not conform to Section 9631 of the federal American Rescue Plan (ARP) of 2021 ... Since Kentucky conforms to the Internal Revenue Code as of December 31, 2018, Kentucky did not adopt these federal changes."
    • The form's lines. Line 3 says "Don't enter more than $3,000 for one qualifying person or $6,000 for two or more persons". Line 8 is the .35-to-.20 table on federal AGI. Line 10 is the tax liability limit (Form 1040 line 18 less Schedule 3 line 1). Line 11 is the smaller of lines 9(c) and 10, and line 12 multiplies by .20. Part III line 22 uses "$5,000 ($2,500 if married filing separately ...)".
    • No conflict. Statute and form agree, so no source-conflict entry is needed.
  • West Virginia. Removing the 529 contribution from the excluded amounts follows the statute.
    • § 11-21-12a: "In addition to amounts authorized to be subtracted from federal adjusted gross income pursuant to subsection (c), section twelve of this article, any payment made under a prepaid tuition contract or other college savings plan ... is also an authorized modification".
    • § 11-21-12(c)(9)(ii) limits the senior modification only by "the sum of modifications under subdivisions (1), (2), (5), (6), (7), and (8)".
    • No double count. A contribution is a payment, not income in AGI, so the $8,000 of income and the separate § 12a deduction cannot cover the same dollars.
  • Arkansas mechanics. These parts match the statute: unchained CPI-U, September-August averages, no decrease ("the percentage, if any"), the 3% cap, nearest-$100 rounding and fixed (C) dollar amounts. The CPI-U series is extended to 2100 before the Arkansas index is built.
  • Tests. I hand-checked 21 cases (about 60 expectations), listed under Verified correct. CI passed every changed file.
  • Batch checks.

There is one critical finding and four should-address items:

There are also five suggestions: the standard deduction and low-income tables, the (C) row layout, Kentucky details, West Virginia tests, and the stale PR body.

Status.

Critical (must fix)

C1. The Arkansas index applies the previous calendar year's adjustment, which the 2013 act removed and DFA's tables contradict

  • Where:

    • policyengine_us/parameters/uprating_extensions.py:112-113: current = get_ar_cpi(parameters, year - 1) and prior = get_ar_cpi(parameters, year - 2);
    • its docstring (lines 103-104): "For tax year Y, 26-51-201(d)(2) compares September Y-2 through August Y-1 with September Y-3 through August Y-2";
    • policyengine_us/tests/fixtures/ar_indexing.py:20-21, whose windows of September 2024 and September 2025 feed tax year 2027;
    • the Arkansas YAML and Python comments that restate it.
  • The law today. A.C.A. § 26-51-201(d), as codified after Act 1459 of 2013 § 2 and Act 532 of 2023 § 2:

    • (d)(1): "The secretary shall increase the minimum and maximum dollar amounts for each rate bracket, rounding to the nearest one hundred dollars ($100), for which a tax is imposed under the table by the cost-of-living adjustment for each calendar year".
    • (d)(2): "the cost-of-living adjustment for a calendar year is the percentage, if any, by which the CPI for the current calendar year exceeds the CPI for the preceding calendar year, not to exceed three percent (3%). The CPI for any calendar year is the average of the Consumer Price Index as of the close of the twelve-month period ending on August 31 of such calendar year."
  • The text the 2013 act replaced. The 2012 Code read: "the cost-of-living adjustment for any calendar year is the percentage, if any, by which the CPI for the calendar year preceding the taxable year exceeds the CPI for the calendar year 1997".

    • What changed. Act 1459 § 2 (file page 3), which the PR cites, replaced "the calendar year preceding the taxable year" with "the current calendar year".
    • What the PR does. Its mapping, in which tax year Y uses the CPI of calendar year Y−1, restores the struck language.
  • DFA applies the current-year window. I took each DFA card's bounds and indexed them by one year's adjustment, rounding to the nearest $100. I compared the result with the next card, using the statute's 12-month averages of not-seasonally-adjusted CPI-U:

    • "taxable-year window" means the 12 months ending August of tax year Y;
    • "PR window" means the 12 months ending August of Y−1.
    Tax year Bounds compared Taxable-year window Matches PR window Matches PR's misses (predicted vs published)
    2018 11 (the 2017 card's bounds through $82,600) 2.4193% 11/11 1.9874% 3/11 22,100 vs 22,200; 37,000 vs 37,200; 78,900 vs 79,300
    2019 11 1.9000% 11/11 2.4193% 3/11 38,100 vs 37,900; 81,200 vs 80,800
    2020 11 1.4583% 11/11 1.9000% 1/11 38,600 vs 38,500; 14,000 vs 13,900
    2021 11 2.9977% 11/11 1.4583% 1/11 39,100 vs 39,700; 23,200 vs 23,600
    2025 5 (the 2024 card's $5,500 to $92,300) 2.6531% 5/5 3% (capped from 3.18%) 1/5 5,700 vs 5,600; 16,100 vs 16,000; 26,500 vs 26,400; 95,100 vs 94,700
    • 2022-2024 don't distinguish the two. Both windows exceed 3% in those years and are capped.
    • The standard deduction agrees. It is indexed by identical "current calendar year" language in § 26-51-430(c)(2)(A)(i). In 2025: $2,410 × 1.026531 = $2,473.90, which rounds to the published $2,470. The PR's 3% would give $2,482.30, or $2,480.
    • Axiom has the same evidence. rulespec-us#1418 already records it: "It fits the 2025 DFA card: 1.026531 is in [1.02546, 1.02654)". That 1.026531 is the September 2024-August 2025 window, which the PR assigns to tax year 2026, not 2025.
  • The effect in claimed years. With the model's own CPI-U series, the PR gives 2027 the capped 3%. The taxable-year window gives 2.455%: September 2026-August 2027 averages 337.078 against 329.001.

    2027 bound 2026 (Act 1) PR head Taxable-year window
    2% row start 5,600 5,800 5,700
    3% row start 11,200 11,500 11,500
    3.4% row start 16,000 16,500 16,400
    3.7% row start 26,400 27,200 27,000
    High-income threshold 94,700 97,500 97,000
    (B) table 2% top 4,700 4,800 4,800
    • One household. A single filer with $27,100 of taxable income in 2027 owes $626 at this head and $629 under the statute's window:
      • At this head: 114 + 150 + 3.4% × (27,149.50 − 16,500) = 626.08.
      • Under the statute's window: 116 + 147 + 360.40 + 3.7% × 149.50 = 628.93.
      • Near the threshold the gap is larger, because a $97,200 filer moves from table (A) to table (B).
    • Every year from 2027. The lag carries into each later year.
  • Severity: critical. The results are wrong in years the PR claims (2027+), and the method contradicts the statute as amended by the act the PR cites, and DFA's consistent practice.

  • Fix:

    • The window. Use current = get_ar_cpi(parameters, year) and prior = get_ar_cpi(parameters, year - 1). Then correct the docstrings, move the fixture windows to September 2025 and September 2026, and update the YAML comments.
    • A back-test. Add a tiny-tree case that reproduces DFA's 2025 card from its 2024 card: $92,300 → $94,700, $25,700 → $26,400 and $5,500 → $5,600. Use the CUUR0000SA0 values for September 2023-August 2025 in the tree.
    • Why not the shared series. The shared gov.bls.cpi.cpi_u is seasonally adjusted from January 2024 (its reference is CUSR0000SA0) and not-seasonally-adjusted before that. Across that splice the 2025 window computes to 2.73%, which gives $94,800, not $94,700.
    • October 2025. The missing October 2025 observation then falls in the prior window for 2027.
    • If you keep your reading, record it as a statute-versus-agency-practice candidate, with DFA's cards as the other source and state: open. The model would then compute tables DFA has not published in any year checked.
    • The 2026 anchor. See S4 before choosing it.

Should address

S1. The Axiom line axiom: pending: hub files parity is not a valid form

  • Where: the last line of the PR body.
  • The rule (CLAUDE.md, "Axiom Parity"): a PR that adds, updates or fixes policy needs one of encoded-correct, <rulespec PR> encoded, <rulespec issue> queued or n/a: <reason>. pending is not one of them. We flagged the same form on Fix the 2021 CTC split and surviving-spouse phaseout threshold #10306, Fix pre-2018 AMT child exemption and income base #10308 and Fix Montana disability exclusion repeal, elderly credit receipt timing and occupancy tests #10331.
  • Why n/a doesn't fit. All three provisions are statutory, and the PR changes results in 2014+ (WV), 2021 (KY) and 2027+ (AR).
  • What rulespec-us has (main cea8379e0b):
    • Kentucky. us-ky/statutes/11/141/067.yaml computes 0.20 * max(0, federal_household_and_dependent_care_credit) from 1990-04-11, with the federal credit as a supplied input.
    • West Virginia.
      • The TY2026 pipeline. us-wv/policies/income_tax/resident_core_liability_pipeline.yaml encodes the § 12a payment. It keeps senior facts out of profile (not wv_pit_2026_has_age_disability_or_surviving_spouse_modification_facts).
      • Change NY CTC to use pre-TCJA definition of qualifying children #1503 (open, pe-parity, updated 2026-10-11) targets § 11-21-12(c)(9) per person. It says "Box (c) also leaves out income subtracted on Schedule M lines 35 to 46. The cases below have no such income".
    • Arkansas. The income-tax policies are a 2026 source hold and a 2026-bounded pilot.
  • Severity: should. An invalid Axiom line is a merge blocker, not a model error.
  • Fix: change the line to axiom: us-ky:statutes/11/141/067#household_and_dependent_care_credit encoded-correct; TheAxiomFoundation/rulespec-us#1418 queued; TheAxiomFoundation/rulespec-us#1503 queued; TheAxiomFoundation/rulespec-us#<n> queued. Alternatively, cite an encoder PR as encoded. Before relying on these:
    • fix md non_refundable_eitc childless max parameter #1418. Add the pe-parity label and a module target, for example an Arkansas indexing module that extends the 2026 pilot.
      • Required outputs: the adjustment, the indexed bounds and the threshold.
      • Companion cases from the DFA cards: the 2024-to-2025 back-test above, plus the 2020-to-2021 card ($38,500 → $39,700; $82,000 → $84,500).
      • Also needed: the blocker, and the C1 fix, so that the head matches the issue's own 1.026531 evidence.
    • Change NY CTC to use pre-TCJA definition of qualifying children #1503. Comment with § 12a companion cases from § 12a and Schedule M:
      • TY2025, single: age 66, federal AGI $6,000 and a $2,000 SMART529 contribution. The (c)(9) modification is $6,000, the § 12a modification $2,000, and the total subtractions $8,000.
      • Joint: add a 60-year-old spouse with $40,000 of AGI. The subtractions are $8,000 and WV AGI is $38,000.
    • New issue <n> (or extend Simplify MO pension and social security deduction variables #1793 to TY2021), modelled on Add AMT parameters for 2020-2023 #1467:
      • Target. us-ky/statutes/11/141/010.yaml, subsection (21)(b), for TY2019-2021 under 2021 Ky. Acts ch. 31 § 1. Compose it into 067 with a pre-ARPA section 21 version for 2021.
      • Corpus citations: us-ky/statute/krs/141.010 and us/statute/26/21 (2020 edition).
      • Verbatim law: quoted above.
      • Companion cases from the 2021 Form 2441-K:
        • Single, AGI $50,000, two qualifying persons, $10,000 of expenses: line 3 $6,000, line 8 .20, line 9a $1,200, line 12 $240.
        • AGI $15,001, one person, $3,000: line 8 .34, so $1,020 and $204.
        • A liability limit of $500: line 11 $500, line 12 $100.
        • Joint, $6,000 of employer benefits and $10,000 of expenses: line 26 $5,000, line 30 $1,000, line 12 $40.
      • Why queued: the blocker.

S2. The West Virginia source-conflict records don't reflect the 529 change, and sibling #10352 rewrites them to describe the old behaviour

  • Where: source_conflicts/candidates.yaml, entries us-wv:senior-disability-modification-income-base and us-wv:senior-modification-excluded-line-range (unchanged by this PR).
  • The two sources.
    • The statute (§ 12a and (c)(9)(ii), quoted under Summary) doesn't reduce the senior modification by a 529 payment.
    • The form. The 2025 Schedule M line 47 box (c) reads "Income not included in lines 35 to 46 (NOT TO EXCEED $8000)", and line 39 is "Contributions to the West Virginia Prepaid Tuition/Savings Plan Trust Funds". The instructions' worked example (file page 30) says "He claimed no deductions on lines 35 through 46. He enters the maximum amount of $8,000". That reads as excluding any line 35-46 deduction, which is how main modelled it.
    • Result. The PR now follows the statute for line 39 and the form for lines 36 and 38.
  • The records:
  • The PR body's ruling. It cites a ruling under a decision-queue id (d1744.2). The ratchet test's PRIVATE patterns reject that id in candidates.yaml, so describe the ruling rather than citing the id.
  • Severity: should. The batch rules require these conflicts to be recorded under the source-conflict process, and the records would misstate PE-US in a file shared with Axiom.
  • Fix: in this PR, coordinated with Point the NM-WY source-conflict candidates at their code on main #10352:
    • Record the 529 piece as following the statute (ruled), either in a new candidate or as a split of the income-base entry. Give its statute and form quotes, the code paths and this PR.
    • Keep the refund and military-pay part as conflicting-source, or state the statutory basis for it. One possibility is (c)'s opening "There shall be subtracted from federal adjusted gross income to the extent included therein", which bars subtracting the same income twice.
    • Change the line-range entry to "lines 36 and 38".

S3. The three synthetic reforms add about 2 GB to the Arkansas batch, and the PR body reports no CI cost

  • Where:
    • policyengine_us/tests/fixtures/ar_indexing.py;
    • the 13 reforms: cases in ar_income_tax_before_non_refundable_credits_indiv.yaml and _joint.yaml;
    • policyengine_us/tests/core/test_state_uprating_rounding.py;
    • policyengine_us/tests/test_ar_income_tax_indexing.py.
  • Why it costs. Each distinct reform clones the parameter tree, reruns every uprating extension and uprates the whole tree. The YAML uses three distinct reforms. The first case under each took 19.03 s, 17.37 s and 15.60 s in CI.
  • CI measurements (Linux; different runs, not a controlled before/after):
    • Baseline states-shard-3, Arkansas batch: 345.6 s and a peak RSS of 8,029 MB. The same batch in Fix Montana disability exclusion repeal, elderly credit receipt timing and occupancy tests #10331's run took 157.2 s and 5,845 MB.
    • It overlaps the Kentucky batch. The shard runs two batches at once. In this run the Arkansas batch (15:53:14-15:59:01) overlapped the Kentucky batch (15:50:35-15:55:58, 9,219 MB peak). 8.0 + 9.2 GB leaves no headroom on a 16 GB runner.
    • Rest (Python + variables): test_state_uprating_rounding now takes 18.91 s; it doesn't appear in the sibling run's duration report. In Rest (Python, shard-1), the indexing file's shared fixture took 9.44 s of setup.
  • CLAUDE.md, "Test design and CI cost":
    • No measurement. It asks for "before/after elapsed time (including setup) and peak memory" for additions that build models. The PR body says incremental Linux CI measurements are unavailable. They now are.
    • Memory isolation. "Passing individually does not establish that groups fit together in one process or in parallel."
    • Duplicated coverage. The two YAML cases with their own reforms ("uses synthetic CPI-U growth rather than chained growth" and "does not lower boundaries after a synthetic CPI-U decrease") repeat what the tiny-tree Python tests already check: the parametrised floor and cap (99/100/101/103/104) and test_ar_index_and_irs_index_remain_independent.
  • Severity: should (a violation of the repository's test-cost rules, with a measured memory risk).
  • Fix: delete those two YAML cases, or move their assertions onto the existing tiny trees, so that one reform remains. Then report the CI timing and memory above in the PR body. The C1 fix will move the fixture windows anyway.

S4. Two DFA practices that the projection should follow: first-year indexing and $50 ties

  • Where:
    • policyengine_us/parameters/gov/states/ar/tax/income/uprating.yaml:5: "The published 2026 statutory tables anchor subsequent projections";
    • the nearest rounding of every bound;
    • test_ar_income_tax_schedule.py:188-193, where the helper is now round(amount / 100) * 100.
  • First-year indexing. DFA indexed each newly enacted table in its first year:
    • 2022: the Act 2021 (2nd Ext. Sess.) table's $5,000 and $84,500 became $5,100 and $87,000.
    • 2023: the $5,100 and $87,000 table became $5,300 and $89,600.
    • 2024: the $5,300, $25,000 and $89,600 table became $5,500, $25,700 and $92,300.
    • The repository. It records those indexed values, not the statutory ones.
    • 2026. Act 1 of 2026 sets a TY2026 table equal to DFA's 2025 card ($5,600 to $94,700), and § 26-51-201(a)(5) says it "shall be adjusted annually in accordance with the method set forth in subsection (d)".
    • Unsettled. DFA's 2026 card is not published. The 2026 withholding formula uses the unindexed table, but withholding has lagged the cards: it uses a $2,470 standard deduction, the 2025 value. rulespec-us#1418 records the same doubt: "The TY2026 table may therefore be Act 1 or Act 2 × 1.03."
    • How it interacts with C1. If 2026 is indexed (by 3%: the September 2025-August 2026 window is 3.27% before the cap), the model's 2026 and every later year rise one step. The PR's current 2027 bounds ($5,800 to $97,500) are what DFA's practice predicts for 2026.
  • Ties. DFA has rounded both observed exact $50 ties down:
    • 2022: $5,000 × 1.03 = $5,150, published as $5,100.
    • 2024: $25,000 × 1.03 = $25,750, published as $25,700.
    • The PR's rounding. Python's ties-to-even gives $5,200 and $25,800. Half-up gives the same. The PR body calls the tie rule "open" and changes the test helper to ties-to-even.
    • The likely mechanism. DFA's result is what indexing each row's "Less Than or Equal To" amount gives ($24,999 × 1.03 = $25,748.97, so $25,700), which fix md non_refundable_eitc childless max parameter #1418 also notes for the minus adjustments.
  • Severity: should (rounding and anchoring details with limited reach, where the structure is otherwise right).
  • Fix:
    • The anchor. Either index the Act 1 table for 2026 and say so in uprating.yaml, or keep the anchor and record the first-year question as open, to revisit when DFA publishes its 2026 card.
    • Ties. Adopt a rounding that reproduces DFA's ties. Core offers only nearest, upwards and downwards, so this needs a small helper or the "Less Than or Equal To" formulation. If not, record the tie rule with the 2022 and 2024 cards as evidence, rather than "open".

Suggestions

G1. The standard deduction and low-income tables follow the same statutory adjustment but still use raw CPI-U

  • The statutes use the same adjustment.
    • The standard deduction. § 26-51-430(c) indexes it by "the cost-of-living adjustment for the current calendar year, rounding the amount to the nearest ten dollars ($10.00)". It uses the same September-August average, "if any", "not to exceed three percent (3%)".
    • The low-income tables. § 26-51-301(e) does the same for the low-income thresholds, "rounded to the nearest whole dollar".
  • The parameters don't.
    • deductions/standard.yaml uprates by gov.bls.cpi.cpi_u with rounding: downwards. The low-income tables uprate by raw CPI-U with no cap or rounding.
    • The rounding is wrong as well. In 2022, $2,200 × 1.03 = $2,266 was published as $2,270, so the published values round to the nearest $10, not down.
  • Fix (recommended, since the PR is titled "Fix Arkansas tax indexing"): after C1, point both at the new index with the statutory rounding, or file a linked follow-up issue.

G2. The (C) rows are indexed one by one, while the 2025 card uses uniform $100 rows

At 3%, each row moves by about $103, so some rows step by $200. The 2025 card instead starts $100 rows from the indexed threshold, as #1418 notes. This predates the PR. Consider following the latest card, or note it.

G3. Kentucky details

  • The frozen instant. parameters("2020-01-01") at ky_cdcc_potential.py:51 stands in for the December 31, 2018 Code. The values are right: section 21 and the section 129 cap didn't change between 2018 and 2020. A conformity parameter, like the existing irc_conformity.obbba, would keep the date in the parameter tree.
  • Taxable benefits for 2021. Kentucky taxes 2021 employer dependent-care benefits above $5,000 (Form 2441-K Part IV lines 36-38, carried to Schedule M). The model doesn't add them to Kentucky AGI. This predates the PR; note it in the documentation or file an issue.

G4. West Virginia tests

  • A cap case. Add a case where the 529 change matters at the cap: age 66, AGI $9,000 and a $2,000 contribution give $8,000 (it was $7,000).
  • A known gap. Note that § 12a's five-year carryforward election isn't modelled. A large contribution can make WV AGI negative instead.

G5. The PR body is stale

  • Stale text. It still says "WIP", "56 YAML files and one Python file are unrun" and "Draft CI jobs were skipped". CI has since run everything (see CI status).
  • A private id. It cites a private decision-queue id.
  • Fix (optional): replace the validation tables with the CI result, describe the West Virginia ruling without the id, and fix the Axiom line (S1).

Verified correct

  • Hand-checks (21 cases, about 60 expectations).
    • Arkansas (synthetic 4%/1% fixture: index 1.03, so the bounds are 5,800, 11,500, 16,500 and 27,200, the threshold 97,500 and the (B) top 4,800). The values are right for the window as coded; C1 changes the fixture.
      1. $150,000, the cap case. 2% × 4,800 + 3.7% × 145,200 = 96 + 5,372.40 = 5,468.40.
      2. 1%/4% windows. 4,700 × 1.01 = 4,747, which rounds to 4,700. So 94 + 3.7% × 145,300 = 5,470.10.
      3. −1%/4% windows. The index stays 1, so 5,470.10.
      4. $26,500. Row midpoint 26,549.50, so 264 + 3.4% × 10,049.50 = 605.68, which rounds to 606.
      5. $97,500. Midpoint 97,450.50 is at most 97,500, so table (A): 627.80 + 3.7% × 70,250.50 = 3,227.07, giving 3,227.
      6. Joint, $50,000. 114 + 150 + 363.80 + 3.7% × 22,849.50 = 1,473.23, giving 1,473.
      7. Python index tests.
        • Window: a 124 in August 2026 inside the window gives 102 and an index of 1.02. The poison months outside it are excluded.
        • Floor and cap: 99 → 1, 100 → 1, 101 → 1.01, 103 → 1.03, 104 → 1.03.
        • Compounding: 1.03 × 1.02, flat after the end year.
    • Kentucky (2021 unless noted):
      8. AGI $50,000, two qualifying persons, $10,000 of expenses. Kentucky: 20% × 20% × 6,000 = 240. Federal ARPA: 50% × 10,000 = 5,000.
      9. AGI $10,000, liability limit 0. Kentucky 0. Federal 50% × 3,000 = 1,500 (refundable).
      10. AGI $450,000. Kentucky 20% × 20% × 3,000 = 120. Federal: 20% − 25 points is floored at 0.
      11. Liability limit $500. min(1,200, 500) × 20% = 100.
      12. Joint, benefits $6,000, expenses $10,000. The exclusion is min(6,000, 10,000, 25,000, 5,000) = 5,000. The limit is 1,000, so creditable expenses are min(1,000, 5,000) and 1,000 × 20% × 20% = 40. This matches Form 2441-K lines 26, 29-32.
      13. Benefits $1,000, expenses $3,000. Exclusion 1,000 and limit 5,000, so expenses 2,000 give 80.
      14. Joint, earnings $2,000, benefits $5,000. Exclusion min(5,000, 3,000, 2,000) = 2,000, so 1,000 × 35% × 20% = 70.
      15. Separate filer treated as unmarried. The single $5,000 cap applies, so the exclusion is 4,000, the limit 2,000, and the credit 80. A separate filer not treated as unmarried gets 0.
      16. Rate boundaries. At AGI 15,000, 15,001, 17,000, 17,001, 43,000 and 43,001 the rates are .35, .34, .34, .33, .21 and .20, matching the Form 2441-K line 8 table. That gives 210, 204, 204, 198, 126 and 120.
      17. Other years. 2020 and 2022: federal 20% × 6,000 = 1,200, Kentucky 240.
    • West Virginia (2025 unless noted):
      18. Joint, both 66+, each AGI $6,000, head contributes $2,000. The modifications are [6,000, 6,000], the 529 deduction 2,000 and the subtractions 14,000.
      19. Disabled, age 50, AGI $6,000, $1,000 contribution. 6,000 + 1,000 = 7,000. The 2014 case gives 6,000.
      20. $1,000 refund, $500 of box (d), $2,000 contribution. min(5,000, 8,000) − 500 = 4,500. The "above the cap" case gives min(17,000, 8,000) − 3,000 = 5,000.
      21. Joint, head 66 with $6,000, spouse 60 with $40,000. The modifications are [6,000, 0] and the subtractions 8,000. WV AGI = 46,000 − 8,000 = 38,000, and taxable income = 38,000 − 2 × 2,000 = 34,000.
  • References.
    • Act 1459. File page 3 holds (d), and the rate-file title "#page 1,3" follows CLAUDE.md.
    • Kentucky acts. 2021 ch. 31 file page 3 holds (21)(b), and 2022 ch. 212 file page 62 holds (21).
    • Multi-page hrefs. The govinfo section 21 and Form 2441-K hrefs carry "PDF pages 1-3" comments.
    • HB 4679. File page 3 holds § 12a.
  • Callers at the head.
    • ky_cdcc_potential is read by ky_cdcc and the combined-separate helper.
    • excluded_income_sources is read only by wv_senior_citizen_disability_deduction_person.
    • The new Arkansas index is read only by the four Arkansas bound families, while the Arkansas tuition parameters still use gov.irs.uprating.
    • The formula_2022_01_01 delegation works. CI passed its 2022 case.
  • Changelog. changelog.d/statute-bugs-ar-ky-wv.fixed.md is a top-level fragment, and fixed is the right type.
  • Batch lessons:

Axiom line assessment

Invalid: axiom: pending: hub files parity (S1).

CI status

27 pass, 3 skipping, 0 pending, 0 failed. I re-checked gh pr checks 10324 at the end of this review, and the head is still 811d94de43.

  • The green run. Run 39617736357 (pull_request, created 2026-10-21 14:32 UTC) tested merge commit c9438066, which merges the head into fec98b87c8 (Count the FL and SD LIHEAP comments in the source-conflict ratchet baseline #10334).
  • Where the changed tests ran.
    • Quick Feedback deferred them ("9 files > 8").
    • Baseline states-shard-3 passed the Kentucky batch (ky_cdcc.yaml, 28 cases) and the Arkansas batch (..._indiv.yaml 73 and ..._joint.yaml 15).
    • States-shard-4 passed the West Virginia batch (wv_senior_citizen_disability_deduction_person.yaml, 22).
    • Rest (Python, shard-1) passed the indexing file and the schedule file. Rest (Python + variables) passed test_state_uprating_rounding and the WV property tests.
    • Full suites. Microsimulation and Household API Partners passed.
  • Locally: I ran no tests or model probes. CI is green at the current head. The expectations were checked by hand. The C1 back-test used BLS CPI-U values and the DFA cards, with arithmetic only.

Branch status

1 critical, 4 should and 5 suggestions are open at this head.

Verdict: REQUEST_CHANGES

@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.

KY 2021 is correct (KRS 141.067 with the Dec 31, 2018 Code matches Form 2441-K), and WV's 529 removal follows sections 12a and 12(c)(9) with no double count. One critical: the AR uprating gives tax year Y the CPI-U adjustment for calendar year Y-1, a rule Act 1459 of 2013 struck. Back-tested against DFA's cards, it reproduces 9 of 49 bounds, while the taxable-year window reproduces 49 of 49, so 2027+ runs one adjustment behind. Four should-address items: the invalid axiom line, stale WV candidates, the CI cost of the three synthetic reforms (AR batch 157s/5.8GB to 346s/8.0GB), and the AR anchor and tie rounding. Five suggestions. Full report in the comment above.

This branch has not been deployed

No deployments
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.

2 participants