Conversation
ARS 43-1072(B)(2) and Form 140PTC Schedule 2 (2021-2025) give the bands for a claimant living with others as $0-2,500 -> $502, 2,501-2,650 -> $479, ..., 5,351-5,500 -> $56, 5,501 and up -> $0. The single_amount scale stored each band's lower bound one dollar low (2,500, 2,650, ..., 5,500), so incomes of exactly 2,500, 2,650, ..., 5,500 got the next band's amount and 5,500 got nothing. Each threshold after zero is now one dollar higher, as Schedule 1 already is. Both schedule files document how cents between whole-dollar bands are treated (the lower band, matching the (A)(3) "less than" limits), cite each year's form PDF directly, and Schedule 1's 2022 reference no longer points at the 2021 form. Tests: YAML cases at every band edge of both schedules, the (A)(3) limits, cents between bands and the household path; a differential test of every whole-dollar income and of cents around every edge against a transcription of the statute, 2021-2026, through the scales and a vectorised simulation; monotonicity and bounds invariants. The existing case at $5,500 expected $0 and now expects $56. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Arizona's property tax credit table for a claimant who lived with a spouse or other persons (ARS 43-1072(B)(2), Form 140PTC Schedule 2) had every band threshold one dollar low.
cohabitating.yamlstored 2,500, 2,650, ..., 5,500 as the lower bounds of the second through last bands, but the statute and the 2021-2025 forms start those bands at 2,501, 2,651, ..., 5,501:A household with income of exactly $2,500, $2,650, ..., $5,500 therefore got the next band's amount, $22-23 less, and one at $5,500 got nothing instead of $56. ARS 43-1072(A)(3)(b) limits the credit to combined income "less than five thousand five hundred one dollars", so $5,500 qualifies. Every threshold after zero is now one dollar higher, matching Schedule 1 (
living_alone.yaml), which already used 1,751, 1,851, ..., 3,751.Law
Incomes with cents
SingleAmountTaxScale.calcusesnumpy.digitizewithright=False. A band therefore covers its lower bound up to, but not including, the next band's lower bound, and $2,500.50 gets the $0-2,500 amount ($502), as if the cents were dropped. The statute lists whole-dollar bands and leaves the gap between, say, $2,500 and $2,501 unassigned. It does state the income limit as "less than" $5,501 (or $3,751), one dollar above the last band's upper bound, so the last band covers every income below the limit. Reading every band the same way gives this result, and it needs no formula change.The alternative is to round to the nearest dollar. Form 140PTC line 10 takes whole dollars, and the 2025 Form 140 instructions (page 4) say to round to the nearest whole dollar. The 140PTC instructions have no rounding rule. Rounding would move an income with 50 cents or more into the next band, for example $2,500.50 to $479 and $5,500.50 to $0, which contradicts (A)(3)(b) at the top edge. A comment in both parameter files records this choice, and the tests pin it.
Changes
cohabitating.yaml: thresholds after zero become 2_501, 2_651, ..., 5_501.az_property_tax_credit.yaml: the existing "filer at 79 meets criteria" case had household income of $5,500 on Schedule 2 and expected $0. It now expects $56: taxes paid are 100 + 0.15 × 1,500 = 325, so the credit is the table amount.Tests
az_property_tax_credit_schedules.yaml(new, 142 cases), generated from the statute table. For each schedule it covers:It also has six household-path cases where income and schedule are computed rather than input: a married couple at $2,500 and $2,501, a single claimant living with an adult child at $5,500 and $5,501, and a single claimant living alone at $3,750 and $3,751.
test_az_property_tax_credit_schedules.py(new, 65 tests): a differential test against an independent transcription of the statute tables, for every whole-dollar income from $0 to $7,000 and cents around every edge, in each year from 2021 to 2026. It runs through the parameter scales and throughaz_property_tax_creditin one vectorisedSimulationper schedule.On main, 48 of the 153 YAML cases in the two credit test files fail: every Schedule 2 upper edge and the cents cases, the 2021 repeats, the household cases at $2,500 and $5,500, and the corrected $5,500 case. Every Schedule 1 case passes on main, as it should. 19 of the 65 Python tests fail on main, all of them Schedule 2.
On this branch, all 625 YAML tests under
states/azpass, as dotest_parameter_files.py,test_parameter_scale_thresholds.pyand thecode_healthfolder.Invariants
These hold for every income, in every year from 2021 to 2026, on both schedules, and are tested:
Microsimulation impact
I ran a real microsimulation on the default dataset (
populace_us_2024.h5@populace-us-2024-spm-20260909) on policyengine-core 3.32.15. It compared main at 6b0e773 with this branch, one period per process, under the shared heavy-run lock with a 24 GB footprint watchdog. Peak footprints were 9.1-9.4 GB.az_property_tax_credit, weighted total (both sides)The fix changes the credit only for Schedule 2 incomes in those $1 windows, and the dataset has none. No aggregate moves.
Interaction with #9762 and #9770
Neither PR touches either schedule file. Both edit
az_property_tax_credit.yaml, appending cases at the end; this PR changes one case in the middle, and git merges both heads with this branch cleanly.az_property_tax_credit_income.yaml("A dependent's capital loss offsets the dependent's wages", "A dependent's capital loss with a claimant's pension", "A dependent's rental loss offsets the dependent's wages") and all 3 tests intest_az_property_tax_credit_income.pyfail. They fail the same way when Count capital gains once in Arizona property tax credit income #9762 is merged with current main alone, without this branch. Bisected: Count capital gains once in Arizona property tax credit income #9762 merged with 4e78791^ passes, and merged with 4e78791 (Keep dependents' losses off the filer's AGI #9647, "Keep dependents' losses off the filer's AGI") fails. So Keep dependents' losses off the filer's AGI #9647 on main causes these failures, not this change.No test in either PR depends on the old one-dollar-low thresholds.
axiom: us-az:statutes/43-1072#shared_household_credit_band encoded-correct
rulespec-us
us-az/statutes/43-1072.yaml(main at 9f38330fb) encodes the Schedule 2 bounds as lower 0, 2501, 2651, ..., 5351 and upper 2500, 2650, ..., 5500, andshared_household_income_limitas 5501. Its companion tests inus-az/statutes/43-1072.test.yamlcover:eligible_under_shared_household_income_pathdoes not hold, credit $0.Two related gaps, neither in this PR's scope:
a_subdivision_a_credit_amount). This PR does not change Schedule 1's values.🤖 Generated with Claude Code