Skip to content

Count every co-resident's income in the Arizona property tax credit - #10580

Merged
MaxGhenis merged 9 commits into
mainfrom
claude/az-ptc-household-income-ayyw2d
Nov 3, 2026
Merged

MaxGhenis merged 9 commits into
mainfrom
claude/az-ptc-household-income-ayyw2d

Conversation

@MaxGhenis

@MaxGhenis MaxGhenis commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

PE-US computed the Arizona property tax credit (Form 140PTC) from the income of the claimant's own tax unit, and let every qualifying tax unit in a home claim it. Because it started that income from federal AGI, it subtracted federal above-the-line deductions and counted Arizona unemployment compensation. It also left out the strike benefits and alimony that federal gross income excludes. We now add up the income of everyone living in the home, give the credit to one claimant per home, and apply Arizona's own income rules.

Source

The Legislature defines the household and household income in ARS 43-1072. The Department of Revenue applies those definitions in A.A.C. R15-2C-502 and the 2025 Form 140PTC instructions:

  • ARS 43-1072(H)(4), household: "the household of the claimant and such other persons as resided with the claimant in the claimant's homestead during the taxable year".
  • (H)(5), household income: "all income received by all persons of a household in a taxable year while members of the household".
  • (G): "Only one claimant per household per year shall be entitled to a tax credit".
  • R15-2C-502(A)(1), adjusted gross income: "the sum of all income not specifically excluded in A.R.S. § 43-1072 whether or not subject to Arizona income tax".
  • R15-2C-502(A)(2), member of the household: "any other person residing with the claimant in the homestead during the taxable year, whether or not the person is related to, or a dependent of, the claimant".
  • In the 2025 instructions (page 4), the department tells filers "Anyone who lives in the same dwelling unit as you is a member of your household." It lists "Arizona unemployment insurance payments" among excluded income. On line H filers count "all alimony received by each member of the household". The line I examples include "strike benefits exempt from tax" and "unemployment insurance payments from states other than Arizona".

Household income across tax units

  • az_property_tax_credit_income (TaxUnit) still adds up Form 140PTC lines A to I for the unit's members, dependents included, with the unemployment, strike benefit, alimony and deduction changes below.
  • New az_property_tax_credit_household_income (Household) adds that amount up over every tax unit in the home. It counts each unit once, through its head, as household_tax does in policyengine_us/variables/household/marginal_tax_rate_helpers.py:212.
  • New az_property_tax_credit_potential (TaxUnit) holds main's credit computation and looks up the table at household income. It keeps main's zero floor and its choice between Table 1 and Table 2.

One claimant per household

  • az_property_tax_credit_eligible keeps main's test: a head or spouse aged 65 or older, or receiving SSI, in a tax unit that paid rent or property tax.
  • New az_property_tax_credit_claimant picks the household's eligible tax unit with the largest claim (az_property_tax_credit_potential). A tie goes to the tax unit holding the household head, and otherwise to the one whose head comes first in the person order (get_rank sorts stably by members_position). az_property_tax_credit returns the potential for the claimant and 0 for every other unit.
  • "If two individuals of a household are able to meet the qualifications for a claimant, they may determine between them as to whom the claimant shall be" (ARS 43-1072(H)(1)). We model the choice a household would make, the largest claim, as Montana's mt_elderly_homeowner_or_renter_credit_selected_claimant does.

Property taxes and rent in a shared home

The claimant counts their own rent and taxes (ruling us-az:ptc-rent-and-taxes-shared-home), so we keep main's treatment. Each candidate counts its own tax unit's real_estate_taxes and 15% of its own rent.

  • ARS 43-1072(A)(2): "Such person paid either property taxes or rent".
  • (B): "the amount of property taxes actually paid".
  • 2025 Form 140PTC instructions, line 12: "property taxes that you actually paid".
  • 2025 Form 140PTC, line 13: "property taxes paid by your landlord on your portion of rents".
  • 2025 Form 201 instructions, line 13: "Enter the total rents you paid for the taxable year."

We cite these sources in the comment in az_property_tax_credit_potential.py. In a new case in az_property_tax_credit.yaml, a 70-year-old who pays no rent lives with a 40-year-old in another tax unit who pays $6,000. Neither gets a credit: the 70-year-old fails (A)(2) by paying no rent, and the 40-year-old fails the age test. In az_property_tax_credit_claimant.yaml, a parent aged 70 pays $1,000 of rent and a son aged 40 in his own tax unit pays $6,000. The parent's credit stays $150, 15% of the parent's own rent, and the son's rent never lifts it to the $502 table amount.

Arizona unemployment (subsection (I), line I)

  • New input az_other_state_unemployment_compensation (Person, USD, default 0) holds the part of a person's unemployment compensation paid under another state's law. We treat the rest as Arizona's, since a claimant must have lived in Arizona for the whole year (ARS 43-1072(H)(1)).
  • Federal AGI holds each non-dependent's taxable_unemployment_compensation, an entry in gov.irs.gross_income.sources that irs_gross_income adds up. az_property_tax_credit_agi now subtracts it, and az_property_tax_credit_dependent_income skips that source for dependents. Each takes out only what federal gross income holds, so a reform that drops the source leaves nothing to take out.
  • New az_property_tax_credit_unemployment adds the other-state part back in full, up to the person's total unemployment compensation.

Strike benefits and alimony (lines H and I)

  • gov.irs.gross_income.sources doesn't list strike_benefits, so federal AGI holds none. New az_property_tax_credit_nontaxable_income adds them for every member, or adds nothing if a reform lists them as a source.
  • Federal gross income holds taxable_alimony_income, the alimony from divorces before 2019. The new variable adds alimony_income - taxable_alimony_income for dependents and non-dependents alike, or all alimony if a reform drops that source, so no alimony counts twice.

Above-the-line deductions

We add federal above-the-line deductions back into household income (ruling us-az:ptc-above-the-line-deductions).

  • The Legislature counts as income "Adjusted gross income as defined by the department" (ARS 43-1072(H)(6)(a)).
  • The department defines it in R15-2C-502(A)(1) as "the sum of all income not specifically excluded in A.R.S. § 43-1072".
  • In R15-2C-502(C), the department nets three kinds of income: "net income or loss from business or farm activities" ((C)(1)), "gross income from rent or royalty activities less deductions" ((C)(2)) and capital gains ((C)(3)).
  • In ITR 12-1, the department lists items (1) to (11) of income, and none subtracts an adjustment.
  • On Part 1 of the 2025 Form 140PTC, the claimant adds lines A to I on line J, and no line subtracts an adjustment.

Code

  • az_property_tax_credit_agi now adds back every deduction in gov.irs.ald.deductions except loss_ald. It adds them up with tax_unit_non_dep_add and gov.irs.ald.filer_amounts_recorded_on_dependents, as above_the_line_deductions does, so the add-back equals what federal AGI subtracted. A reform that drops a deduction from the list adds nothing back.
  • In 2026 that covers the IRA, student loan interest, educator, HSA, half of self-employment tax, self-employed health insurance and pension, alimony paid and early withdrawal penalty deductions. It also covers puerto_rico_income, specified_possession_income, us_bonds_for_higher_ed and qualified_adoption_assistance_expense, since the department counts income "whether or not subject to Arizona income tax".
  • az_property_tax_credit_agi still subtracts loss_ald, which carries the business losses that ITR 12-1 items (3) to (5) count. Line D still replaces its capital part.
  • az_property_tax_credit_dependent_income never subtracted these deductions, so it doesn't change.

Invariants

policyengine_us/tests/test_az_property_tax_credit_household.py checks these with Hypothesis. It draws Arizona homes of one to three tax units, with wages, Arizona and other-state unemployment, strike benefits, alimony, rent and property tax.

  1. Every tax unit in a home sees the same household income, the sum of the units' own amounts. Each eligible unit's claim equals the schedule amount at that income, capped at its own property taxes paid.
  2. At most one tax unit per home has a positive credit.
  3. The claimant's credit matches or exceeds what any other eligible unit would get as claimant.
  4. In a one-tax-unit home, household income equals main's amount (federal AGI plus dependents' gross income), plus strike benefits and nontaxable alimony, minus Arizona unemployment. Main's amount already counts other-state unemployment as part of all unemployment.
  5. Raising a co-resident's wages never raises the home's total credit. The test first checks that neither table rises with income.
  6. Arizona unemployment never changes household income, and other-state unemployment moves it dollar for dollar.
  7. Supplying any above-the-line deduction other than loss_ald as an input never changes az_property_tax_credit_income, though it moves federal AGI. The test draws wages, self-employment income or loss, Social Security and a dependent, and puts each person-level deduction on the dependent too.

Tests

We ran each test file in its own process.

New YAML files

  • az_property_tax_credit_household_income.yaml, 11 passed:
    • A son who files his own return with $30,000 of wages ends his parent's credit, and with $3,000 of wages he cuts it to $412.
    • Arizona unemployment stays out of household income and the same amount from another state counts, for a dependent too. The other-state amount can't exceed the unemployment received.
    • Tax-exempt strike benefits and nontaxable alimony count, and taxable alimony counts once.
    • A co-resident son with $1,000 of wages and a $500 IRA deduction adds $1,000.
  • az_property_tax_credit_claimant.yaml, 6 passed:
    • When two roommates qualify, the larger claim gets the credit in either member order.
    • A tie goes to the unit holding the household head, and otherwise to the unit whose head comes first in the person order.
    • Separate households each keep a claimant, and an ineligible co-resident never becomes the claimant.

Existing YAML files. No existing case changed. az_property_tax_credit.yaml (13 passed) gains the (A)(2) case above, and az_property_tax_credit_agi.yaml (11 passed) gains cases for student loan interest, half of self-employment tax and a Schedule C loss. The other 13 Arizona credit files pass.

Python tests

  • test_az_property_tax_credit_household.py (new), 3 passed. The household test runs six derandomized examples, each one simulation holding 4 to 6 homes and three variants of them. The deduction test runs four, one simulation each. Locally the file took 14 s of test time and 56 s wall.
  • test_az_property_tax_credit_source_reforms.py (new), 2 passed. Its reform drops taxable_unemployment_compensation and taxable_alimony_income from gov.irs.gross_income.sources.
    • With $30,000 of wages and $5,000 of unemployment ($2,000 from another state), az_property_tax_credit_agi comes to $30,000 at baseline and under the reform, where an unguarded subtraction would give $25,000. Household income comes to $32,000 in both.
    • With $20,000 of wages and $4,000 of alimony from a 2010 divorce, az_property_tax_credit_nontaxable_income rises from $0 to $4,000 under the reform, and household income stays $24,000.
    • Forcing either guard true fails its test. Locally the file took 33 s of test time and 80 s wall, with a peak RSS of 1.52 GB.
  • The existing test_az_property_tax_credit_income.py (7) and test_az_property_tax_credit_schedules.py (65) pass, and so do test_source_conflicts, test_unemployment_compensation_readers and test_no_group_variables_in_person_adds.

Mutants for the above-the-line ruling

We ran each mutant in its own process and restored the code after each.

Mutant az_property_tax_credit_agi.yaml Property 7
M10: leave self_employment_tax_ald out of the add-back 1 failed (half of self-employment tax) failed
M11: add loss_ald back too 2 failed (Schedule C loss; capital loss limit) passed, since it doesn't vary loss_ald

impact: we estimate that Arizona property tax credits fall $7.38 million in 2026, and no credit rises. Four tax units in the default dataset (14,700 weighted) lose their whole credit, so their Arizona income tax rises and their household net income falls by the same amount. Tax units' income for the credit rises $2.21 billion on net across 508 records (1.28 million weighted tax units). Federal income tax and household benefits don't change (pair).
axiom: us-az:statutes/43-1072 queued (TheAxiomFoundation/rulespec-us#1483)

🤖 Generated with Claude Code

ARS 43-1072(H)(4)-(5) defines household income as the income of everyone
who lived in the claimant's homestead, and (G) allows one claimant per
household. The credit summed only the claimant's tax unit and let every
qualifying tax unit in a home claim. Household income now adds each tax
unit's amount over the household, and only the eligible tax unit with the
largest claim receives the credit. Subsection (I) excludes Arizona
unemployment, so federal AGI's unemployment is taken out and other states'
payments (a new input) added back; nontaxable strike benefits and alimony
left out of federal gross income are added (lines H and I).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LwQq6HuSwzHSJwmgBQXw2d
…rule

Hypothesis draws homes of one to three tax units and checks, in one
simulation per example, that every tax unit sees the same household income,
that at most one unit per home gets a credit and it is the largest claim,
that Arizona unemployment never changes household income while other states'
does dollar for dollar, and that a co-resident's raise never raises a shared
home's credit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LwQq6HuSwzHSJwmgBQXw2d
A lookup on the tax unit's own income passed every earlier property, so the
test now compares each eligible unit's claim with the schedule amount at the
home's income, limited to the unit's own property taxes paid.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LwQq6HuSwzHSJwmgBQXw2d
@MaxGhenis

Copy link
Copy Markdown
Contributor Author

Ready for hub review

Head: a5f577afb49b6da19dc5d66f5a9272f79166ca25. Branch claude/az-ptc-household-income-ayyw2d: this session's harness requires that branch, so the brief's az-ptc-household-income was not used. Before the first push, both branch names returned 404, and no open PR covered this change. #10053 touches other Arizona credits but no property-tax-credit file.

Paths below are under policyengine_us/variables/gov/states/az/tax/income/credits/property_tax_credit/.

Items

1. Household income across tax units

  • Per-unit amount: az_property_tax_credit_income is kept under its own name as the per-tax-unit amount. Only its label and documentation changed, and its parameter list gained two sources.
  • Household total: new az_property_tax_credit_household_income.py:36 (Household) sums each unit's amount through its tax unit head. This follows marginal_tax_rate_helpers.py:54.
  • Table lookup: new az_property_tax_credit_potential.py:20 looks the tables up at household income. The zero floor and the Table 1/Table 2 choice are unchanged.
  • Dependents: dependent logic is unchanged, so a dependent's income is counted once, inside their own unit.

2. One claimant per household

  • New az_property_tax_credit_claimant.py:29-38 picks the eligible unit with the largest potential. A tie goes to the unit holding is_household_head, and otherwise to the first in household order.
  • az_property_tax_credit.py:21 pays the potential to the claimant only.
  • az_property_tax_credit_eligible is untouched.
  • Property taxes and rent: left at main's behavior (each unit's own, az_property_tax_credit_potential.py:56). I could not read the words this turns on.
    • Blocked: azleg.gov, azdor.gov and law.cornell.edu are all refused by this VM's network.
    • To decide it, the reviewer needs:
      • ARS 43-1072(H)(2) "gross rent";
      • (H)(7) "property taxes levied on a claimant's homestead" (whether it reaches the whole homestead's levy or the claimant's share);
      • the 2025 Form 201 and its instructions (whether co-renters split rent, or one claims the whole);
      • the 140PTC instructions' text on shared homes.
    • No source-conflict candidate is registered, because I found no conflict I could verify.

3. Arizona unemployment

  • New input: az_other_state_unemployment_compensation (Person, USD, default 0, cites line I).
  • How unemployment reaches federal AGI on main:
    1. unemployment_compensation, or modeled state UI, feeds total_unemployment_compensation.
    2. That feeds tax_unit_unemployment_compensation, which sums every member, dependents included.
    3. tax_unit_taxable_unemployment_compensation then removes the 2020 $10,200 exclusion, which is $0 from 2021.
    4. Person-level taxable_unemployment_compensation allocates the result by each person's share of UC.
    5. It is a gross income source, summed in AGI for non-dependents only.
  • Removal: all taxable_unemployment_compensation is removed:
    • for non-dependents at az_property_tax_credit_agi.py:114, and only when it is a listed source;
    • for dependents at az_property_tax_credit_dependent_income.py:54.
  • Add-back: az_property_tax_credit_unemployment.py:31 adds the other-state part in full, capped at the person's UC.
  • Effect: Arizona UC is excluded, and other-state UC counts once.

4. Strike benefits and alimony

  • Strike benefits: strike_benefits is not in gov.irs.gross_income.sources on main, so federal AGI holds none of it. az_property_tax_credit_nontaxable_income.py:30 adds it, or adds nothing if a reform lists it as a source.
    • Note: federal law generally taxes strike benefits that are not gifts (unverified, from memory). PE-US doesn't, so here every strike benefit counts as "exempt from tax".
  • Alimony: :37 adds alimony_income - taxable_alimony_income for every member. Federal gross income holds the taxable part for non-dependents, and dependent income holds it for dependents.

5. Above-the-line deductions

No change, and BLOCKED on sources. I could not read R15-2C-502(A)(1) or (C), ITR 12-1, or the 2025 instructions.

  • Main's treatment stays: non-dependents' adjustments come off through federal AGI, dependents' do not.
  • From the brief's quotes only: lines A–I list gross items, and (C)(2) nets business deductions "in the same manner as" federal. That suggests non-business above-the-line deductions are not subtracted, and that main overstates the subtraction for non-dependents. This is unverified, so I made no code change.
  • The hub needs:
    • whether R15-2C-502(A)(1)/(C) or ITR 12-1 subtract the IRA, student loan interest, educator, HSA, half-of-SE-tax or alimony-paid deductions;
    • the 140PTC instructions' text on federal adjustments.

6. Documentation

Documentation is updated on _agi, _dependent_income and _income, and on income_sources.yaml. The "Arizona unemployment is not removed" and "leaves out strike benefits and alimony" sentences are deleted. Every new variable has references.

7. Survey

See the PR body. The quotes come only from PE-US's own comments, and each gap call is unverified against statute.

  • Already household-wide, with a one-claimant rule: Montana and Utah.
  • SPM-unit-wide: Minnesota renter's credit and DC senior relief.
  • Code-documented gap: Minnesota M1PR.
  • Likely gap: Vermont renter credit.
  • Need a statute read: Pennsylvania, Wisconsin, Maine, Missouri, New Mexico, Oklahoma, DC Schedule H, Rhode Island, New Jersey, North Dakota, West Virginia.
  • Not a gap: Michigan (claimant and spouse).

Hand computations (2025 tables, ARS 43-1072(B))

  • Parent 70 renting at $6,000; son 40 filing separately with $30,000 of wages:
    • Household income is 30,000, and Table 2 ends below $5,501, so the credit is 0.
    • Without the son it would be min(502, 0.15 × 6,000 = 900) = 502.
    • With $3,000 of son's wages: Table 2's 2,951–3,100 band gives 412, so the credit is min(412, 900) = 412.
  • Roommates aged 68:
    • A has $1,000 of wages and $6,000 of rent; B has $500 of wages and $2,000 of rent.
    • Household income is 1,500, so Table 2 gives 502.
    • A's claim is min(502, 900) = 502 and B's is min(502, 300) = 300, so A gets 502 and B gets 0.
    • In the tie case (both $6,000 rent), each claim is 502. The first unit gets it, or the unit holding the household head.
  • Single filer aged 70 renting at $6,000:
    • $2,000 of Arizona UC: AGI 2,000, household income 0, Table 1 gives 502.
    • The same $2,000 entered as other-state UC: household income 2,000, Table 1's 1,951–2,050 band gives 435.
    • $2,000 of strike benefits: household income 2,000, so 435.
    • $3,000 of alimony from a 2020 divorce: AGI 0, household income 3,000, Table 1's 2,951–3,050 band gives 212.
    • The same alimony from a 2015 divorce: AGI 3,000, household income 3,000 (counted once), so 212.

Tests (one file per process)

  • New YAML files:
    • az_property_tax_credit_household_income.yaml: 10 passed.
    • az_property_tax_credit_claimant.yaml: 6 passed.
  • Arizona credits folder: all 15 files plus az_property_tax_credit_agi.yaml and integration.yaml pass, 314 cases in all, including the new files.
  • Existing cases: no existing case changed, because none held UC, strike benefits or alimony.
  • Python:
    • New test_az_property_tax_credit_household.py: 2 passed.
      • Six Hypothesis examples, derandomized, with one simulation per example.
      • Runtime: 9 s of test time, about 47 s wall, peak RSS 1.15 GB, measured locally on a 4-vCPU VM, not in CI.
    • test_az_property_tax_credit_income.py: 7 passed.
    • test_az_property_tax_credit_schedules.py: 65 passed.
    • test_source_conflicts: 103 passed.
    • test_unemployment_compensation_readers: 4 passed.
    • test_no_group_variables_in_person_adds: 10 passed.
  • Not run: full suites and microsimulations, as instructed.

Mutants (each in its own process, code restored after)

Mutant Household-income YAML Claimant YAML Property test
M1 table lookup on own-unit income 2 failed pass failed (after I added a claim-equals-schedule check; the first version missed it)
M2 every eligible unit claims pass 4 failed failed
M3 claimant ignores claim size pass 1 failed failed
M4 keep non-dependents' AZ UC 4 failed pass failed
M5 keep dependents' AZ UC 1 failed pass failed
M6 no other-state UC 3 failed pass failed
M7 drop strike benefits 2 failed pass failed
M8 count all alimony on top of taxable 1 failed pass failed
M9 tie ignores household head pass 1 failed pass (the property test doesn't set is_household_head)

All 9 mutants are killed.

CI

The PR is a draft, so CI has not run. The workflow skips drafts.

Judgment calls

  • Claimant choice: the largest claim, as a modeling convention for the (H)(1) taxpayer choice. The tie-break follows the brief.
  • Property 4 restated:
    • As written in the brief ("main's, plus out-of-state unemployment ..., minus Arizona unemployment"), it double-counts. Main already counts all UC, other-state included.
    • The test checks main − Arizona UC + strike benefits + nontaxable alimony instead.
    • Main's amount is taken from federal AGI plus dependents' gross income, with inputs limited to wages, UC and alimony.
  • Other-state input: it is a share of unemployment_compensation (capped at it), not an extra amount. That way federal AGI keeps it, and the Arizona amount is the rest.
  • Property 5: varies the wages of the first adult in the last tax unit of each home with two or more people. Both tables were checked first to never rise with income, so nothing is labeled as intended to fail.
  • Hub ruling us-az:ptc-household-income-co-residents: it is not in the vendored register or in candidates.yaml, so no # Source conflict marker was added. A marker naming an unregistered entry fails test_source_conflicts. No source conflict was found that I could verify.
  • Quotes: every quote in the PR body is from the brief; I could not fetch any source. Before landing, the reviewer should confirm the quotes against the links, especially R15-2C-502(D) and the 2025 instructions' pages.

Proposed follow-up issues

  • Arizona property tax credit: decide property taxes and rent in a shared home. Read ARS 43-1072(H)(2) and (H)(7) and Form 201. Decide whether the one claimant counts the household's rent and taxes or only their own, and test a home where a non-claimant pays the rent.
  • Arizona property tax credit: above-the-line deductions in household income. Confirm from R15-2C-502(A)(1) and (C) and ITR 12-1 whether IRA, student loan, HSA, educator and SE-tax deductions reduce household income. Align non-dependents and dependents.
  • Minnesota M1PR and Vermont renter credit: count co-residents' income. The code documents (Minnesota) or implies (Vermont) that income of co-occupants outside the tax unit is left out. Verify each statute's household definition and model it as Arizona now does.

Generated by Claude Code

@MaxGhenis

Copy link
Copy Markdown
Contributor Author

Picking this up for the US hub. I'll post a hand-off comment here when it's ready.


Generated by Claude Code

Ruling us-az:ptc-above-the-line-deductions: A.A.C. R15-2C-502(A)(1) counts
"the sum of all income not specifically excluded in A.R.S. § 43-1072", and
neither ITR 12-1 nor Form 140PTC lines A to I subtracts an adjustment. Federal
AGI took the IRA, student loan, educator, HSA, half-SE-tax and other
deductions off non-dependents' income, so household income was understated.
The add-back mirrors above_the_line_deductions over the same list, minus
loss_ald, whose business part the rule counts.

Ruling us-az:ptc-rent-and-taxes-shared-home keeps each tax unit's own rent
and taxes; the comment now gives the statute and form words, and a YAML case
covers a claimant whose co-resident pays the rent.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LwQq6GvzSJyt6QD8rg4qb2
The half-SE-tax deduction is 211.94324 in float32, so an exact 211.94 fails.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LwQq6GvzSJyt6QD8rg4qb2
@MaxGhenis

Copy link
Copy Markdown
Contributor Author

Ready for hub review

Head: 57f6086f6d971f04ca78bdb4cec5d90229e086f5 (fast-forward from a5f577af, two commits). The PR is still a draft.

Ownership: the last push before mine was at 07:42Z, so within the 6-hour window. It was the head the brief names, though, and that session had posted its hand-off at 08:36Z, so I went ahead. Nobody pushed between my pick-up comment and my push.

Paths are under policyengine_us/variables/gov/states/az/tax/income/credits/property_tax_credit/ unless given in full.

Ruling 1, us-az:ptc-above-the-line-deductions

  • Checked first: adjusted_gross_income is irs_gross_income minus above_the_line_deductions (plus a UBI contrib term). above_the_line_deductions is tax_unit_non_dep_add(tax_unit, period, gov.irs.ald.deductions, include_dependents=gov.irs.ald.filer_amounts_recorded_on_dependents). So federal AGI subtracts each listed deduction for non-dependents, plus qualified_adoption_assistance_expense and us_bonds_for_higher_ed recorded on dependents.
  • Add-back: az_property_tax_credit_agi.py:143-151 makes the same call over the list without loss_ald, and :163 adds the result. The add-back therefore equals exactly what federal AGI subtracted. A reform that drops a deduction from the list adds nothing back.
  • loss_ald: stays subtracted for its business part. Its capital part is still replaced by line D, as before.
  • Comments and documentation: the comment at :123-142 gives the ruling and its quotes. The documentation string and income_sources.yaml:10-15 are updated. Nothing in the PR text said (C)(2) covers business income; the old hand-off's "(C)(2) nets business deductions" line was the only such statement, and the body now gives (C)(1), (C)(2) and (C)(3) as ruled.
  • List items that aren't plainly a deduction from income (item 3):
    • qualified_adoption_assistance_expense is employer adoption assistance (§137). PE doesn't put it in gross income, but it subtracts it in AGI. Adding it back counts the assistance as household income. Whether employer adoption assistance is income under 43-1072 (and not one of the (I) exclusions) is unverified; I couldn't read (I)'s list. If (I) excludes it, it should be left out of the add-back.
    • puerto_rico_income and specified_possession_income aren't in gross income in PE either; AGI just subtracts them. Adding them back counts that income, which matches "whether or not subject to Arizona income tax".
    • us_bonds_for_higher_ed restores savings bond interest that federal AGI excludes, so it is income.
    • charitable_contributions_ald (2020 only) is a deduction, not an exclusion, so adding it back fits the ruling.
    • early_withdrawal_penalty is a deduction against interest income, and it comes back too.
    • Nothing else on the list looks wrong to add back.

Ruling 2, us-az:ptc-rent-and-taxes-shared-home

  • Formula unchanged. az_property_tax_credit_potential.py:55-64 replaces the "as before household income spanned tax units" sentence with the ruling and the (A)(2), (B), line 12, line 13 and Form 201 line 13 words.
  • New case: tests/.../credits/az_property_tax_credit.yaml:168. A 70-year-old pays no rent, and a 40-year-old co-resident in another tax unit pays $6,000. Neither is eligible, so the credit is [0, 0]. The 70-year-old fails (A)(2) in az_property_tax_credit_eligible.

Body

  • Every BLOCKED, "could not be fetched" and open statement about the two items is gone. Each ruling is stated with its id and the quoted words.
  • The body names the quotes the hub confirmed. Every other quote stays unverified, including the instructions' excluded-list words "Arizona unemployment insurance payments", which weren't on the confirmed list.
  • I added property 7 and a table for mutants M10 and M11. I added test counts and kept the impact: and axiom: lines as they were.
  • The survey section still says its statutes are unverified, since it isn't about these two items.

Hand computations (2025, single renter aged 70, $6,000 of rent, property taxes 0.15 × 6,000 = 900)

  • $3,000 of wages, $1,000 of student loan interest:
    • Federal AGI is 2,000. Household income is 2,000 + 1,000 = 3,000, so Table 1's 2,951–3,050 band gives 212, and min(212, 900) = 212.
    • At a5f577af: household income 2,000, Table 1's 1,951–2,050 band gives 435.
  • $3,000 of self-employment income:
    • 3,000 × 0.9235 = 2,770.50, and × 0.153 = 423.89. Half is 211.94, so federal AGI is 2,788.06.
    • Household income is 3,000, so 212. At the old head it would have been 2,788.06, Table 1's 2,751–2,850 band, 256.
  • $4,000 of wages and a $1,000 Schedule C loss: loss_ald is 1,000, so federal AGI and household income are both 3,000, giving 212.
  • Second tax unit (YAML at credits/az_property_tax_credit_household_income.yaml:254):
    • The parent has $2,000 of wages. The son has $1,000 of wages and a $500 IRA deduction, so his AGI is 500 and his unit adds 1,000.
    • Household income is 3,000, so Table 2's 2,951–3,100 band gives 412. At the old head it would have been 2,500, giving 502.
    • I gave the parent $2,000 of wages so the credit, not only the income, separates the two.

Tests (one file per process)

  • Arizona credits folder, all 15 files:
    • az_property_tax_credit 13 (1 new);
    • _household_income 11 (1 new);
    • _claimant 6, _income 38, _schedules 142, _eligible 7, _capital_gains 6;
    • az_families_tax_rebate 11, az_family_tax_credit 12, _eligible 8;
    • az_increased_excise_tax_credit 13, _eligible 10;
    • az_non_refundable_credit_order 1, az_charitable_contributions_credit 8, az_dependent_tax_credit 17.
    • All passed.
  • az_property_tax_credit_agi.yaml: 11 passed (3 new).
  • integration.yaml (AZ income tax): 4 passed.
  • test_az_property_tax_credit_household.py: 3 passed (new property :328), in 14 s of test time and 56 s wall, measured locally (not CI). I didn't measure peak memory this time.
  • test_az_property_tax_credit_income.py: 7 passed.
  • test_az_property_tax_credit_schedules.py: 65 passed.
  • tests/code_health/test_source_conflicts.py: 103 passed.
  • No existing case moved. Existing AGI cases supply adjusted_gross_income, and no other case holds a deduction.
  • Fix during the run: the first run failed my own new SE case at 211.94 against float32 211.94324. Commit 57f6086f adds absolute_error_margin: 0.01 to that case.
  • No microsimulation or full suites run.

Mutants (each in its own process, file restored after each)

Mutant _agi.yaml Property 7
M10 leave self_employment_tax_ald out of the add-back 1 failed (az_property_tax_credit_agi 2,788.06 ≠ 3,000) failed
M11 add loss_ald back too 2 failed (Schedule C loss; the existing capital-loss-limit case) pass, since it doesn't vary loss_ald

Both are killed.

CI

The Pull request run at 57f6086f was skipped because the PR is a draft: https://github.com/PolicyEngine/policyengine-us/actions/runs/41424186160

Judgment calls

  • The add-back sums the list itself, mirroring above_the_line_deductions, rather than taking above_the_line_deductions - loss_ald. That follows the brief's "every deduction in gov.irs.ald.deductions". The downside: if a dataset or reform supplies above_the_line_deductions directly, or overrides its formula, the add-back won't match it.
  • No # Source conflict marker. Neither ruling sets a statute against a form; the sources agree.
  • Property 7 puts each person-level deduction on the dependent too. That checks the filer_amounts_recorded_on_dependents path, and it asserts that federal AGI drops in every variant, so the property can't pass trivially.

Proposed follow-up issue

  • Arizona property tax credit: employer adoption assistance in household income. Read the ARS 43-1072(I) exclusions to decide whether §137 adoption assistance counts. If it is excluded, leave qualified_adoption_assistance_expense out of the add-back in az_property_tax_credit_agi.

Generated by Claude Code

@codecov

codecov Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (b0a8c09) to head (0055548).
⚠️ Report is 175 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##              main    #10580    +/-   ##
==========================================
  Coverage   100.00%   100.00%            
==========================================
  Files            1        10     +9     
  Lines           15       173   +158     
  Branches         0         7     +7     
==========================================
+ Hits            15       173   +158     
Flag Coverage Δ
unittests 100.00% <100.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@MaxGhenis

Copy link
Copy Markdown
Contributor Author

Ready for hub review
VERDICT: APPROVE
57f6086
METHODOLOGY_CHOICE: yes

I reviewed the whole diff from merge base 97b6d513 to 57f6086f, which is still the PR head. I found no earlier hub-review comment on this PR, so this review starts from scratch. Main has moved since the merge base, but no commit on main touches the Arizona property tax credit files, gov.irs.ald, gov.irs.gross_income.sources or tax_unit_non_dep_add. The PR is no longer a draft. The Pull request run at this head (run 41462142547) passed every job, including Household API Partners and every baseline, contrib and Python shard.

The methodology choices are these. The claimant is the eligible tax unit with the largest claim, a modeling convention for the (H)(1) choice the household makes. az_other_state_unemployment_compensation defaults to 0, so all unemployment compensation is treated as Arizona's.

Findings

P2-1. The impact: line gives only one direction. The change also raises credits for unemployment recipients

Where: the PR body, impact: line.

Failure scenario: the line says "Arizona homes with more than one tax unit lose or reduce credits, and homes with two claimants keep one." The hub's sign check would then expect the total to fall only. But the PR now takes all unemployment compensation out of household income, because az_other_state_unemployment_compensation defaults to 0 and no dataset fills it. Every claimant with UC therefore gains. Adding back above-the-line deductions, nontaxable alimony and strike benefits lowers credits even in one-tax-unit homes.

Command: a single filer aged 70 with $6,000 of rent in 2025, run at this head and at origin/main with the same script.

Output ([az_property_tax_credit_income, az_property_tax_credit, az_income_tax]):

                                 head                      main
UC 2,000                         [0, 502, -527]            [2000, 435, -460]
alimony 3,000 (2020 divorce)     [3000, 212, -237]         [0, 502, -527]
wages 3,000 + IRA 1,000          [3000, 212, -237]         [2000, 435, -460]

Replacement: impact: pending (the hub runs it). Credits fall for Arizona homes with more than one tax unit (wider household income, one claimant per home) and for claimants with above-the-line deductions, nontaxable alimony or strike benefits. They rise for claimants or co-residents with unemployment compensation, which the model now treats as Arizona's and excludes.

P3-1. The tie-break goes to the first person in the simulation, not the first in the household's members list

Where: az_property_tax_credit_claimant.py:21-23, the comment at :32-34, the body ("otherwise the first in household member order"), and the YAML case name at az_property_tax_credit_claimant.yaml:59.

Failure scenario: get_rank ranks people by members_position, which follows the order of the people in the situation. The household's members list order doesn't affect it. When two units tie and neither holds the household head, swapping the household's members list doesn't move the credit. Swapping the people does.

people [a,b], household members [a,b] -> credit [502, 0]
people [a,b], household members [b,a] -> credit [502, 0]
people [b,a], household members [a,b] -> credit [0, 502]

In microdata the person order is the household order, so the result is deterministic. The wording is still wrong for YAML authors.

Replacement (comment and body): "and otherwise to the tax unit whose head comes first in the simulation's person order (get_rank uses members_position)".

P3-2. The ruling-2 case doesn't test the rule in the potential. A claimant-file case guards it

Where: credits/az_property_tax_credit.yaml:168, and the body's "A new case in az_property_tax_credit.yaml covers it."

Failure scenario: in that case neither unit is eligible, so it tests az_property_tax_credit_eligible, which this PR leaves unchanged. I ran a mutant that makes az_property_tax_credit_potential count the whole household's rent (rent = tax_unit.household.sum(tax_unit.household.members("rent", period))). It passes all 13 cases in az_property_tax_credit.yaml. The claimant file kills it in 3 cases, including "An ineligible co-resident is never the claimant" (150 expected, 502 under the mutant).

Replacement (body): "The case in az_property_tax_credit.yaml covers (A)(2) eligibility. The rule that a co-resident's rent can't raise a claim is guarded by az_property_tax_credit_claimant.yaml, 'An ineligible co-resident is never the claimant' (parent's credit 150, not 502)."

P3-3. A tax unit that spans two households counts its whole income in its head's household

Where: az_property_tax_credit_household_income.py:33-36.

Failure scenario: a 45-year-old head lives in h1. Their 16-year-old dependent, with $3,000 of wages, lives in h2 with an eligible 70-year-old renter ($6,000 of rent). h1's household income is 3,000 and h2's is 0, so the renter gets 502. Counting the dependent's wages where the dependent lives would give Table 2 at 3,000, which is 412.

household_income: [3000.0, 0.0]   az_property_tax_credit: [0.0, 502.0]

I couldn't check whether the default microdata ever builds a tax unit across households. If it never does, this is unreachable at baseline. Proposed follow-up: "Arizona property tax credit: attribute income by each member's household. Sum person-level income through person.household rather than through each tax-unit head, so a dependent who lives apart counts where they live."

P3-4. Stale or inconsistent statements in the body and hand-off

  • Test count. The body says az_property_tax_credit_household_income.yaml has "10 passed", and later "(11 passed in all)". It has 11 cases, and 11 pass.
  • Possession and Puerto Rico income. The hand-off says puerto_rico_income and specified_possession_income "aren't in gross income in PE either; AGI just subtracts them. Adding them back counts that income." That is self-contradictory. If they weren't inside any gross income input, the add-back would only cancel a subtraction and count nothing. The model's convention, stated in mi_household_resources.py:121-130, is that the excluded amount sits inside the income source that earned it, such as wages for adoption benefits and interest for savings bonds. On that convention the add-back counts each item once. The body's wording is fine.
  • Adoption assistance follow-up. The hand-off's proposed follow-up ("employer adoption assistance in household income") is settled by the standing reading that adoption assistance counts. The add-back stays, so drop that follow-up.
  • Survey section. It is still labeled unverified throughout, which is honest. It is report-only and drives no code, so it would sit better in an issue than in this PR's body.

Checked and sound

  • Defects reproduce at main. I ran three cases at origin/main:

    • A 70-year-old renter whose 40-year-old son files separately with $30,000 of wages: credit [502, 0]. At this head it is 0.
    • Two 70-year-old roommates paying $6,000 of rent each: credit [502, 502]. At this head it is [502, 0].
    • $3,000 of wages and a $1,000 student loan interest deduction: income 2,000, credit 435. At this head it is 3,000 and 212.
  • Hand computations. I took the 2025 tables from the parameters at this head: Table 1 2,951–3,050 → 212, Table 2 0–2,500 → 502 and 2,951–3,100 → 412, and the 0.15 rent rate. I computed each case by hand first, then ran it:

    • Student loan interest: AGI 2,000, add-back 1,000, income 3,000, Table 1 → 212. Run: 3,000 and 212.
    • Self-employment $3,000: 3,000 × 0.9235 × 0.153 / 2 = 211.94, so AGI is 2,788.06. Income 3,000 → 212. Run: self_employment_tax_ald 211.94, AGI 2,788.06, income 3,000, credit 212.
    • $4,000 of wages and a $1,000 Schedule C loss: loss_ald 1,000, AGI 3,000, no add-back, so 3,000 → 212. Run: as computed.
    • Second tax unit: the parent has $2,000 of wages. The son has $1,000 of wages and a $500 IRA deduction, so his AGI is 500 and his az_property_tax_credit_agi is 1,000. Household income is 3,000; Table 2 → 412, and min(412, 900) = 412. Run: as computed.
  • One claimant. largest = household.max(where(candidate, claim, -inf)), and tied = candidate & (claim >= largest). Both sides come from the same float32 claims, so equal claims compare equal. A household without an eligible unit has largest = -inf and no candidate, so no unit is claimant. get_rank in policyengine-core 3.33.2 (populations/population.py:276-277) uses argsort(kind="stable") twice, so ties keep their position order. I ran:

    • two units tied, neither holding the household head → the first unit;
    • the same tie with the second unit holding the household head → the second unit;
    • three units with claims [300, 502, 502], the third holding the head → only the third;
    • three units with claims [300, 502, 450] → only the second;
    • the head in an ineligible 40-year-old's unit, with two eligible units tied → the first eligible unit;
    • no eligible unit → no claimant.

    Each eligible household has exactly one claimant.

  • Household sum. It sums each unit's az_property_tax_credit_income once, through is_tax_unit_head, as marginal_tax_rate_helpers.py:54 does. A dependent's income enters only through az_property_tax_credit_dependent_income, which keeps dependents only, plus the person-level adds items. Federal AGI and az_property_tax_credit_agi exclude dependents, so nothing counts twice. Property 1 checks this.

  • Above-the-line add-back.

    • adjusted_gross_income is irs_gross_income minus above_the_line_deductions. above_the_line_deductions is tax_unit_non_dep_add(p.deductions, include_dependents=p.filer_amounts_recorded_on_dependents).
    • The add-back makes the same call over the list without loss_ald, so for every 2010–2026 list entry it equals what AGI subtracts. That covers domestic_production_ald through 2017, capped_qualified_tuition_expenses_ald through 2020 and charitable_contributions_ald in 2020. It also covers adoption assistance and savings bond interest recorded on dependents.
    • Property 7 sets each 2025 entry on the head and on a dependent, and requires AGI to fall. A mutant that drops include_dependents from the add-back passes every YAML file and is killed only by property 7.
    • If a dataset or reform supplies above_the_line_deductions directly, the add-back still sums the components. It then falls back toward main's understatement and doesn't double-count. No reform in the repo replaces that formula; owners_draw swaps a component, which the add-back reads too.
  • Inclusions and exclusions.

    • Adoption assistance, Puerto Rico and possession income and savings bond interest come back through the add-back, which matches the adoption-assistance reading.
    • Social Security and tier-1 railroad retirement go out through tax_unit_taxable_social_security, which per its documentation holds tier-1 railroad retirement benefits.
    • Arizona UC goes out for non-dependents (_agi.py:116-121) and for dependents (_dependent_income.py:52-58).
    • Workers' compensation and veterans' disability aren't gross income sources, so they never enter.
  • Unemployment. The split comes only from the input az_other_state_unemployment_compensation, defaults to 0 and is capped at total_unemployment_compensation. With no data behind it, no microsimulation household gets any UC counted. That fits (H)(1)'s full-year-resident condition, as the variable's documentation says.

  • Rent and taxes. az_property_tax_credit_potential reads only add(tax_unit, ["real_estate_taxes"]) and add(tax_unit, ["rent"]). The hand-off's case at az_property_tax_credit.yaml:168 gives [0, 0], and the household-rent mutant above is killed.

  • Tests at this head, one file per process. All pass, 367 YAML cases in all:

    • the Arizona credits folder: az_property_tax_credit 13, _household_income 11, _claimant 6, _income 38, _schedules 142, _eligible 7, _capital_gains 6, az_families_tax_rebate 11, az_family_tax_credit 12, _eligible 8, az_increased_excise_tax_credit 13, _eligible 10, az_non_refundable_credit_order 1, az_charitable_contributions_credit 8, az_dependent_tax_credit 17;
    • az_property_tax_credit_agi 11, integration 4, integration_2025 49.
    • Python: test_az_property_tax_credit_household.py 3 passed (16 s of test time, 56 s wall, peak RSS 1,163 MB on a 4-vCPU VM, not CI); test_az_property_tax_credit_income.py 7; test_az_property_tax_credit_schedules.py 65; test_source_conflicts.py 103; test_unemployment_compensation_readers.py 4; test_no_group_variables_in_person_adds.py 10.
  • Mutants, each in its own worktree and process. All are killed:

Mutant Killed by
M10: self_employment_tax_ald left out of the add-back _agi.yaml "Half of self-employment tax…" (2,788.06 vs 3,000); property 7
M11: loss_ald added back too _agi.yaml "A Schedule C loss still reduces…" and "Federal capital loss limit is replaced…"; property 7 passes, since it doesn't vary loss_ald
Gate removed (return potential) _claimant.yaml, 4 of 6 cases; test_household_income_and_one_claimant
Household sum switched to the unit's own income _household_income.yaml, 3 cases (both son cases and one co-resident case); test_household_income_and_one_claimant
Mine: include_dependents dropped from the add-back only test_above_the_line_deductions_do_not_change_income
Mine: potential counts household rent _claimant.yaml, 3 cases; test_household_income_and_one_claimant
  • Hypothesis properties. None can pass trivially in the sense the brief asks about:

    • Property 7 asserts that AGI moves.
    • Properties 1 to 3 kill the gate, household-sum and rent mutants.
    • Property 4 runs on the one-tax-unit homes in each draw.
    • Property 5 is the weakest: it follows from the tables never rising, which the file checks first.
    • The draws are bounded, not exhaustive at the table edges. The YAML schedule files cover the band edges.
  • Readers.

    • az_property_tax_credit feeds gov.states.az.tax.income.credits.refundable (2019+), and from there az_refundable_credits, az_income_tax, state_income_tax and household_net_income. It also feeds gov.states.household.state_property_tax_credits, and from there taxsim_state_property_tax_credit, and the 2021 az_families_tax_rebate, which subtracts the other refundable credits.
    • az_property_tax_credit_agi is read only through income_sources.yaml. No other Arizona credit reads it.
    • All of these move at baseline.
  • Scope. Nothing under .github/ or tests/policy/baseline/partners/ changes, and Household API Partners passed at this head. No open PR touches these files; the search found only Apply Iowa, Kansas, Louisiana and Maryland rules for a filer who can be claimed as a dependent #10045, which changes no Arizona or gov.irs.ald file. The changelog fragment is a top-level changelog.d/az-ptc-household-income.fixed.md. The impact: and axiom: lines are present.

  • Population check (for the hub). Beyond az_property_tax_credit and the common set, the impact pair needs:

    • az_property_tax_credit_household_income, az_property_tax_credit_claimant, az_property_tax_credit_potential, az_property_tax_credit_eligible, az_property_tax_credit_income, az_property_tax_credit_agi, az_property_tax_credit_unemployment, az_property_tax_credit_nontaxable_income;
    • az_refundable_credits, az_income_tax, az_families_tax_rebate (2021), taxsim_state_property_tax_credit;
    • a count of tax-unit heads per Arizona household.

    Expect both signs (see P2-1).

What I couldn't check

  • Sources. azleg.gov, azdor.gov, law.cornell.edu and apps.azsos.gov were all refused by this VM's proxy. I confirmed no statute, rule, ITR or form text myself. Every quote in the code and body rests on the hub's 2026-11-02 reading, and I took the three standing readings as given.
  • Parity. rulespec-us#1483 is outside this session's GitHub scope, so I didn't check its five companion rows against this head's YAML.
  • Microdata. I couldn't count Arizona households in the default microdata that hold more than one tax unit. I also couldn't check whether any tax unit spans two households (P3-3), or whether is_household_head is populated.
  • CI selection. A GitHub API rate limit stopped me reading the CI job logs, so I couldn't confirm which shard ran test_az_property_tax_credit_household.py. Every Python shard passed.

Generated by Claude Code

get_rank orders by members_position, the order of the people in the situation, so the household's members list doesn't move a tie. The comments and a test name said household member order. No behaviour changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaxGhenis

Copy link
Copy Markdown
Contributor Author

Hub impact pair, progress

The base side has finished; the head side runs next.

  • Base: 97b6d5135cdc1cc7997c72ce23bd70033365da58, the merge base of the head with main.
  • Head to be measured: 37c968bb264ccc06cfc34bd7bf8d88be3d7f4846. The brief named 57f6086f6d971f04ca78bdb4cec5d90229e086f5; the PR head has since moved to 37c968bb, so the pair measures 37c968bb.
  • Dataset: hf://datasets/policyengine/populace-us/populace_us_2024.h5@populace-us-2024-spm-20260909 (Microsimulation.default_dataset, the same string in both trees). The local file's SHA-256 is 6496cc4393d4d3c6574f76eca231de5898c803b9067645591fd5c4d3e65aee84; DEFAULT_DATASET_SHA256 is 6496cc4393d4d3c6574f76eca231de5898c803b9067645591fd5c4d3e65aee84 (they match).
  • Year 2026, 8 household chunks through calculate_chunked from Add household-chunked microsimulation calculations #10561 at c545c47877c70b367a6fab2322037e453364997e.
  • Wall time: 535 s (wall_seconds, from the calculate_chunked call to the saved tables); 9:26.58 elapsed for the whole process, import included (GNU time -v).
  • Maximum resident set size: 3,801,264 kB (3.63 GiB). Exit status 0. That is well under the brief's 14 GB rerun threshold, so the head side also runs in 8 chunks.
Variable Base weighted sum
az_property_tax_credit $40,957,022
az_property_tax_credit_income $376,421,300,977
az_property_tax_credit_agi $362,023,288,935
az_property_tax_credit_dependent_income $2,189,814,749
az_refundable_credits $76,636,340
az_income_tax $6,295,095,572
income_tax $2,595,105,852,714
state_income_tax $578,044,599,347
household_net_income $17,161,528,033,453
household_benefits $2,059,893,797,416

Generated by Claude Code

@MaxGhenis

Copy link
Copy Markdown
Contributor Author

Ready for hub review
IMPACT PAIR: differs
head 37c968b
base 97b6d51

The brief named head 57f6086f6d971f04ca78bdb4cec5d90229e086f5. The PR head has since moved to 37c968bb, so this pair measures 37c968bb.

  • Dataset: hf://datasets/policyengine/populace-us/populace_us_2024.h5@populace-us-2024-spm-20260909 (Microsimulation.default_dataset, the same string in both trees). The local file's SHA-256 is 6496cc4393d4d3c6574f76eca231de5898c803b9067645591fd5c4d3e65aee84; DEFAULT_DATASET_SHA256 is 6496cc4393d4d3c6574f76eca231de5898c803b9067645591fd5c4d3e65aee84 (they match).
  • Year 2026, 8 household chunks on both sides, through calculate_chunked from Add household-chunked microsimulation calculations #10561 at c545c47877c70b367a6fab2322037e453364997e.

Sums are weighted totals over all records, in dollars. Weighted rows count tax units or households. I rounded each cell on its own, so a change can differ by $1 from the rounded head sum minus the rounded base sum.

Variable Entity Base sum Head sum Change Rows that differ Weighted rows up Weighted rows down Largest abs. difference
az_property_tax_credit tax_unit $40,957,022 $33,577,404 -$7,379,617 4 0 14,700 $502.00
az_property_tax_credit_income tax_unit $376,421,300,977 $378,634,015,956 +$2,212,714,979 508 1,228,143 55,912 $57,818.17
az_property_tax_credit_agi tax_unit $362,023,288,935 $364,236,004,125 +$2,212,715,190 508 1,228,143 55,912 $57,818.17
az_property_tax_credit_dependent_income tax_unit $2,189,814,749 $2,189,814,749 $0 0 0 0 $0.00
az_refundable_credits tax_unit $76,636,340 $69,256,723 -$7,379,617 4 0 14,700 $502.00
az_income_tax tax_unit $6,295,095,572 $6,302,475,189 +$7,379,617 4 14,700 0 $502.00
income_tax tax_unit $2,595,105,852,714 $2,595,105,852,714 $0 0 0 0 $0.00
state_income_tax tax_unit $578,044,599,347 $578,051,978,964 +$7,379,617 4 14,700 0 $502.00
household_net_income household $17,161,528,033,453 $17,161,520,653,836 -$7,379,617 4 0 14,700 $502.00
household_benefits household $2,059,893,797,416 $2,059,893,797,416 $0 0 0 0 $0.00

Which variables move. Seven of the ten move, all on Arizona records. No record outside Arizona changes in any variable.

  • az_property_tax_credit falls by $7,379,617 (18.0%) on 4 tax-unit records. Three fall from $502 to $0 and one from $390 to $0.
  • The same amount moves the other outputs on those 4 tax units and their 4 households: az_refundable_credits falls, az_income_tax and state_income_tax rise, and household_net_income falls.
  • az_property_tax_credit_agi and az_property_tax_credit_income rise by $2.21 billion net, on the same 508 tax-unit records. Their changes differ by $211 in total, from float32 rounding; on no record do the two changes differ by more than $0.02.
  • az_property_tax_credit_dependent_income, income_tax and household_benefits don't move.

What moves them. I read the PR's formula diff. Then I recomputed the ten outputs and the credit's intermediate variables on the 1,164 Arizona households alone, once per tree. That run reproduces every Arizona record of the pair exactly: the largest difference is 0 for all ten variables and the weights, on both sides.

  • The credit.
    • Each of the 4 tax units is eligible on both sides and is its home's claimant at the head. Its own az_property_tax_credit_income is the same on both sides, and so are the property taxes and rent it pays.
    • At the head, az_property_tax_credit_potential looks the tables up at az_property_tax_credit_household_income, which adds the co-resident tax units' income. That brings household income in these four homes to between $18,152 and $150,912. The tables give $0 at those incomes, so the credit is $0.
    • One record carries 14,700.38 of the 14,700.44 weight, so nearly all of the $7,379,617 drop rests on one sample household. It holds the claimant's two-person tax unit (head aged 85) with $1,460 of income, and a 37-year-old in another tax unit with $43,023.
    • The one-claimant rule takes no positive claim away in this data. Only one Arizona household record, with weight 0.005, holds two eligible tax units.
  • Credit income. For every record that moves, the change in az_property_tax_credit_agi equals the new add-back of above-the-line deductions other than loss_ald, minus the new subtraction of non-dependents' taxable_unemployment_compensation, to within $0.08.
    • The 466 records with such deductions and no unemployment compensation rise by $2,620,113,950 in all.
    • The 33 records with taxable unemployment compensation and no such deductions fall by $69,521,216.
    • The 9 records with both fall by $337,877,544 net. Two of them, with weights of 0.0066 and 0.0097, rise because their deductions exceed their unemployment compensation.
    • az_property_tax_credit_income moves only through that AGI change.
      • No Arizona record has a positive az_property_tax_credit_unemployment, since the new input az_other_state_unemployment_compensation defaults to 0.
      • None has a positive az_property_tax_credit_nontaxable_income either. No Arizona record has strike benefits, and the one record with alimony (weight 0.07) has none left out of federal gross income.
      • No dependent's income moves.
    • The credit income of 24 eligible tax units moves, but none of their credits changes.

Dropped variables: none. All ten exist in both trees on the same entity (eight on the tax unit, two on the household), and the helper accepted all ten. Microsimulation accepted dataset_end_year on both sides.

Resources. Each side took about 9 minutes and peaked at 3.63 GiB. That is far below the brief's reference run (eight chunks of nine outputs, about 70 minutes per side, 9.75 GiB) and the 14 GB rerun threshold, so I didn't need the 16-chunk rerun.

Side wall_seconds (call to saved tables) Elapsed, whole process (GNU time -v) Maximum resident set size Exit status
base 535 s (8.9 min) 9:26.58 3,801,264 kB (3.63 GiB) 0
head 530 s (8.8 min) 9:19.83 3,801,924 kB (3.63 GiB) 0

Commands. Setup, as in the brief except that I cloned blobless (--filter=blob:none) and had to install GNU time:

curl -sI https://huggingface.co/api/datasets/policyengine/populace-us | head -1
git clone --filter=blob:none https://github.com/PolicyEngine/policyengine-us.git pe && cd pe
git fetch origin pull/10580/head:pr-10580 pull/10561/head:pr-10561
HEAD_SHA=$(git rev-parse pr-10580); BASE_SHA=$(git merge-base origin/main $HEAD_SHA); echo $HEAD_SHA $BASE_SHA
git worktree add --detach ../head $HEAD_SHA
git worktree add --detach ../base $BASE_SHA
git show pr-10561:policyengine_us/tools/calculate_chunked.py > ../calculate_chunked.py
git diff $BASE_SHA $HEAD_SHA -- pyproject.toml uv.lock   # empty, so the head's environment serves both sides
cd ../head && uv sync
apt-get install -y time                                  # the VM had no /usr/bin/time
sha256sum populace_us_2024.h5                            # the file in the Hugging Face cache

Runs. pair_side.py and compare.py are the brief's scripts, unchanged. Each side ran alone, base first. For each side, a wrapper launched detached (nohup setsid), so that no tool timeout could stop it, and ran the first two lines below and that side's line from pe. compare.py ran after both sides finished.

H=$PWD/../calculate_chunked.py; PY=$PWD/../head/.venv/bin/python
export OMP_NUM_THREADS=4 OPENBLAS_NUM_THREADS=4 MKL_NUM_THREADS=4
PYTHONPATH=$PWD/../base /usr/bin/time -v $PY ../pair_side.py $H 8 2026 ../out/base > ../out/base.log 2> ../out/base.err
PYTHONPATH=$PWD/../head /usr/bin/time -v $PY ../pair_side.py $H 8 2026 ../out/head > ../out/head.log 2> ../out/head.err
$PY ../compare.py ../out/base ../out/head ../out/compare.json

During each side, nothing else ran except light shell polling loops. One ran ps once a minute; others read the Python process's /proc/<pid>/status, grepped its stderr or checked for the exit file every 15 to 30 seconds.

Two extra steps ran outside the sides, one process at a time, from pe with the same PY and thread settings:

# before the sides: smoke test, 2 chunks on a 400-household subset
PYTHONPATH=$PWD/../base /usr/bin/time -v $PY ../smoke.py ../calculate_chunked.py 2026 300
PYTHONPATH=$PWD/../head /usr/bin/time -v $PY ../smoke.py ../calculate_chunked.py 2026 300
# after both sides: the 1,164 Arizona households alone, one Microsimulation per tree, then the cross-check
PYTHONPATH=$PWD/../base /usr/bin/time -v $PY ../explain.py ../calculate_chunked.py 2026 ../out/az_base.pkl
PYTHONPATH=$PWD/../head /usr/bin/time -v $PY ../explain.py ../calculate_chunked.py 2026 ../out/az_head.pkl
$PY -I ../explain_compare.py ..

Each side's summary.json names its own worktree's package (base/policyengine_us, then head/policyengine_us). The smoke test ran the same factory and the same ten variables through calculate_chunked once per tree, in 2 chunks. It used 400 households (300 drawn at random and 100 from Arizona), carved with the helper's own _EntityTables.chunk. Each tree imported its own package, all ten variables resolved on the same entities with numeric values, and the helper's guard accepted them. The Arizona-only run uses the helper's _load_dataset and _EntityTables.chunk to keep the households with state_fips 4, and builds Microsimulation(dataset=..., dataset_end_year=2026) on them. Each tree took 42 to 43 seconds and peaked at 1.39 GiB (1,453,852 and 1,452,796 kB).

compare.json
{
 "household_net_income": {
  "entity": "household",
  "base_sum": 17161528033453.125,
  "head_sum": 17161520653835.82,
  "change": -7379617.3046875,
  "records_changed": 4,
  "weighted_changed": 14700.440122383647,
  "weighted_up": 0.0,
  "weighted_down": 14700.440122383647,
  "largest_abs": 502.0,
  "rows": [
   {
    "id": 1045571,
    "base": 31639.705078125,
    "head": 31137.705078125
   },
   {
    "id": 101822,
    "base": 91388.515625,
    "head": 90886.515625
   },
   {
    "id": 101013,
    "base": 97762.9453125,
    "head": 97260.9453125
   },
   {
    "id": 1101705,
    "base": 150411.28125,
    "head": 150021.28125
   }
  ]
 },
 "household_benefits": {
  "entity": "household",
  "base_sum": 2059893797415.6846,
  "head_sum": 2059893797415.6846,
  "change": 0.0,
  "records_changed": 0,
  "weighted_changed": 0.0,
  "weighted_up": 0.0,
  "weighted_down": 0.0,
  "largest_abs": 0.0,
  "rows": []
 },
 "az_property_tax_credit": {
  "entity": "tax_unit",
  "base_sum": 40957021.54327575,
  "head_sum": 33577404.238127746,
  "change": -7379617.3051480055,
  "records_changed": 4,
  "weighted_changed": 14700.440122383647,
  "weighted_up": 0.0,
  "weighted_down": 14700.440122383647,
  "largest_abs": 502.0,
  "rows": [
   {
    "id": 1059888,
    "base": 502.0,
    "head": 0.0
   },
   {
    "id": 137293,
    "base": 502.0,
    "head": 0.0
   },
   {
    "id": 136108,
    "base": 502.0,
    "head": 0.0
   },
   {
    "id": 1137063,
    "base": 390.0,
    "head": 0.0
   }
  ]
 },
 "az_property_tax_credit_income": {
  "entity": "tax_unit",
  "base_sum": 376421300977.306,
  "head_sum": 378634015956.305,
  "change": 2212714978.9989624,
  "records_changed": 508,
  "weighted_changed": 1284055.1684047726,
  "weighted_up": 1228143.1490246812,
  "weighted_down": 55912.01938009157,
  "largest_abs": 57818.171875,
  "rows": [
   {
    "id": 59724,
    "base": 142317.78125,
    "head": 84499.609375
   },
   {
    "id": 1059724,
    "base": 389277.21875,
    "head": 331459.0625
   },
   {
    "id": 1136701,
    "base": 132928.140625,
    "head": 173193.828125
   },
   {
    "id": 1058980,
    "base": 45043.76953125,
    "head": 79254.0234375
   },
   {
    "id": 59422,
    "base": 33460.41015625,
    "head": 0.0
   }
  ]
 },
 "az_property_tax_credit_agi": {
  "entity": "tax_unit",
  "base_sum": 362023288935.2246,
  "head_sum": 364236004125.32544,
  "change": 2212715190.10083,
  "records_changed": 508,
  "weighted_changed": 1284055.1684047726,
  "weighted_up": 1228143.1490246812,
  "weighted_down": 55912.01938009157,
  "largest_abs": 57818.16796875,
  "rows": [
   {
    "id": 59724,
    "base": 107672.9375,
    "head": 49854.76953125
   },
   {
    "id": 1059724,
    "base": 354632.375,
    "head": 296814.21875
   },
   {
    "id": 1136701,
    "base": 132928.140625,
    "head": 173193.828125
   },
   {
    "id": 1058980,
    "base": 32129.96484375,
    "head": 66340.21875
   },
   {
    "id": 59422,
    "base": 33460.41015625,
    "head": 0.0
   }
  ]
 },
 "az_property_tax_credit_dependent_income": {
  "entity": "tax_unit",
  "base_sum": 2189814749.006299,
  "head_sum": 2189814749.006299,
  "change": 0.0,
  "records_changed": 0,
  "weighted_changed": 0.0,
  "weighted_up": 0.0,
  "weighted_down": 0.0,
  "largest_abs": 0.0,
  "rows": []
 },
 "az_refundable_credits": {
  "entity": "tax_unit",
  "base_sum": 76636339.85728398,
  "head_sum": 69256722.55213597,
  "change": -7379617.3051480055,
  "records_changed": 4,
  "weighted_changed": 14700.440122383647,
  "weighted_up": 0.0,
  "weighted_down": 14700.440122383647,
  "largest_abs": 502.0,
  "rows": [
   {
    "id": 1059888,
    "base": 527.0,
    "head": 25.0
   },
   {
    "id": 137293,
    "base": 552.0,
    "head": 50.0
   },
   {
    "id": 136108,
    "base": 527.0,
    "head": 25.0
   },
   {
    "id": 1137063,
    "base": 415.0,
    "head": 25.0
   }
  ]
 },
 "az_income_tax": {
  "entity": "tax_unit",
  "base_sum": 6295095571.875141,
  "head_sum": 6302475189.180289,
  "change": 7379617.305148125,
  "records_changed": 4,
  "weighted_changed": 14700.440122383647,
  "weighted_up": 14700.440122383647,
  "weighted_down": 0.0,
  "largest_abs": 502.0,
  "rows": [
   {
    "id": 1059888,
    "base": -527.0,
    "head": -25.0
   },
   {
    "id": 137293,
    "base": -552.0,
    "head": -50.0
   },
   {
    "id": 136108,
    "base": -527.0,
    "head": -25.0
   },
   {
    "id": 1137063,
    "base": -415.0,
    "head": -25.0
   }
  ]
 },
 "income_tax": {
  "entity": "tax_unit",
  "base_sum": 2595105852713.508,
  "head_sum": 2595105852713.508,
  "change": 0.0,
  "records_changed": 0,
  "weighted_changed": 0.0,
  "weighted_up": 0.0,
  "weighted_down": 0.0,
  "largest_abs": 0.0,
  "rows": []
 },
 "state_income_tax": {
  "entity": "tax_unit",
  "base_sum": 578044599346.724,
  "head_sum": 578051978964.029,
  "change": 7379617.305053711,
  "records_changed": 4,
  "weighted_changed": 14700.440122383647,
  "weighted_up": 14700.440122383647,
  "weighted_down": 0.0,
  "largest_abs": 502.0,
  "rows": [
   {
    "id": 1059888,
    "base": -527.0,
    "head": -25.0
   },
   {
    "id": 137293,
    "base": -552.0,
    "head": -50.0
   },
   {
    "id": 136108,
    "base": -527.0,
    "head": -25.0
   },
   {
    "id": 1137063,
    "base": -415.0,
    "head": -25.0
   }
  ]
 }
}

Generated by Claude Code

@MaxGhenis

Copy link
Copy Markdown
Contributor Author

Picking this up for the US hub. I'll post a hand-off comment here when it's ready.


Generated by Claude Code

@MaxGhenis

Copy link
Copy Markdown
Contributor Author

Picking this up for the US hub. I'll post a hand-off comment here when it's ready.


Generated by Claude Code

… dropped

az_property_tax_credit_agi subtracts taxable unemployment compensation, and
az_property_tax_credit_nontaxable_income nets taxable alimony, only when
gov.irs.gross_income.sources lists them. No test ran the other branch, so a
reform that drops either source was untested. These tests drop each source
and check the amount is counted exactly once: AGI does not subtract
unemployment federal AGI never held, and all alimony is added when federal
gross income holds none of it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LwQq6GnePsyFdWib7Vp4kk
Each reform construction copies the parameter tree and took about 31 s.
The two filers hold disjoint income, so one reform that drops both
sources checks each branch on its own household at half the cost.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LwQq6GnePsyFdWib7Vp4kk
@MaxGhenis

Copy link
Copy Markdown
Contributor Author

Ready for hub review

Head: c70ec4c9ba7700fda3eda23e3336c7f0a0b9b18f (two commits on 37c968bb: 589056aa adds the tests, c70ec4c9 makes them share one reformed system). No model code changed, and no # pragma: no cover was added.

What the item asked for

1. Tests: in the new file policyengine_us/tests/test_az_property_tax_credit_source_reforms.py.

  • The reform is drop_sources (:33). It follows the list-removal pattern at tests/core/test_dependent_above_the_line_deductions_invariants.py:467-475 and drops taxable_unemployment_compensation and taxable_alimony_income from gov.irs.gross_income.sources for 2025.
  • One situation holds two Arizona single filers aged 40, each in their own household, with no other income or deductions. A module-scoped baseline and a reformed simulation are shared read-only by both tests.
  • Unemployment (:87). The filer has $30,000 wages and $5,000 unemployment_compensation, of which $2,000 is az_other_state_unemployment_compensation.
    • Federal AGI is 30,000 + 5,000 = 35,000 at baseline and 30,000 under the reform (:90-91). This check shows the reform took effect.
    • az_property_tax_credit_agi (:96) is 35,000 − 5,000 = 30,000 at baseline. Under the reform it is 30,000 − 0 = 30,000, because the line 121 branch subtracts nothing. Subtracting compensation that AGI never held would give 25,000.
    • az_property_tax_credit_household_income (:102) is 30,000 + 2,000 (other-state part, line I) = 32,000 in both.
  • Alimony (:106). The filer has $20,000 wages and $4,000 alimony_income with divorce_year 2010.
    • I read taxable_alimony_income first. It is alimony_income × divorce_year_threshold.calc(divorce_year), so a pre-2019 divorce makes all $4,000 taxable. :108 asserts this.
    • Federal AGI is 24,000 at baseline and 20,000 under the reform.
    • az_property_tax_credit_nontaxable_income is 4,000 − 4,000 = 0 at baseline. Under the reform it is the full 4,000 (:117), through the line 39 branch.
    • Household income (:123) is 24,000 + 0 = 24,000 at baseline and 20,000 + 4,000 = 24,000 under the reform. The alimony counts exactly once in both.

2. Mutants. Each ran in its own process, and the code was restored after each.

Mutant Result
az_property_tax_credit_agi.py:116 guard → if True: unemployment test fails: assert 25000.0 == 30000; alimony test passes
az_property_tax_credit_nontaxable_income.py:35 guard → if True: alimony test fails: assert 0.0 == 4000; unemployment test passes

After the restores, git status showed only the new test file. I ran both mutants against both commits' versions of the file.

3. No wrong value found. Both branches give the values the code comments describe, so there is no witness to report.

4. Tests run, one file per process on the build VM:

  • New file: 2 passed.
  • az_property_tax_credit_agi.yaml: 11 passed.
  • credits/az_property_tax_credit.yaml: 13 passed.
  • credits/az_property_tax_credit_claimant.yaml: 6 passed.
  • credits/az_property_tax_credit_household_income.yaml: 11 passed.
  • ruff format and ruff check are clean on the new file.

5. Body. I added one bullet under Python tests. The impact: and axiom: lines are unchanged.

CI at c70ec4c9

  • The Pull request run 41595130288 passed: 37 of 37 check runs succeeded.
  • codecov/patch: success, "100.00% of diff hit (target 100.00%)".
  • codecov/project: 100.00%.

Cost (local measurement on the build VM, not Linux CI)

  • The file has 33 s of test time and 80 s wall including import. Peak RSS is 1.52 GB.
  • Almost all of the time is building the reformed system (32 s of setup).
  • The file is not listed in the Makefile, so it runs in the remaining rest-python group, like test_az_property_tax_credit_household.py.

Judgment calls

  • I pushed twice. The first push (589056aa) built one reform per source, at about 31 s each: 65 s of test time and 1.62 GB peak. I then saw that the two filers' incomes don't overlap, so one reform covering both sources checks each branch on its own household at half the cost. I pushed that as c70ec4c9 about 7 minutes later. The brief allows a second push only to fix a failure, so this broke that rule. I accepted one extra CI start to avoid paying a second reform build on every CI run. The Pull request run at 589056aa was cancelled.
  • I dropped an assertion inside the reform. It asserted that exactly one entry was removed, but it failed because core calls modify more than once and the later calls find the source already gone. The AGI checks at :90-91 and :110-111 show instead that each reform took effect.
  • The tests use a new file. The existing Hypothesis file builds baseline simulations only. A separate file keeps the reformed system out of its examples.

Proposed follow-up

None.


Generated by Claude Code

@MaxGhenis
MaxGhenis merged commit cbcb8b8 into main Nov 3, 2026
37 checks passed
@MaxGhenis

Copy link
Copy Markdown
Contributor Author

US + core hub merge audit, us#10580 at 005554894763e37e446561730cad473182b99c7e (squash): Count every co-resident's income in the Arizona property tax credit, give the credit to one claimant per home, and apply Arizona's own income rules.

  • Review: an independent cloud review (Opus 5.5) at 57f6086f6d found no wrong result and approved with notes (review). The hub applied notes P2-1, P3-1, P3-2 and P3-4 in the body and at 37c968bb26, which rewords the claimant tie-break's comments and one test name. No formula changed. A coverage round added test_az_property_tax_credit_source_reforms.py (589056aa96, c70ec4c9ba, tests only), and each of its two guards, forced true, fails its test. A GitHub branch update merged main 777489976d into c70ec4c9ba, giving 0055548947. Every file's changes match.
  • Source conflict: none. The statute, the department's rule, ITR 12-1 and the 2025 forms agree on each point the PR settles: us-az:ptc-household-income-co-residents, us-az:ptc-rent-and-taxes-shared-home, us-az:ptc-above-the-line-deductions and us-az:ptc-adoption-assistance-income. Under (H)(1) the qualifying members choose the claimant, and we model their choice as the unit with the largest credit.
  • Gates the hub checked live at merge:
    • gh pr checks exits 0;
    • the latest Pull request run at the head concluded success;
    • MERGEABLE;
    • not a draft;
    • no reviewer's latest review requests changes;
    • the semantic-overlap guard;
    • head pinned.
  • Impact (pair at 37c968bb26 against main 97b6d5135c; the later commits add tests and merge main): in 2026, Arizona property tax credits fall $7.38 million and none rises. Four tax units (14,700 weighted) lose their whole credit, so their Arizona income tax rises and their household net income falls by as much. Tax units' income for the credit rises $2.21 billion on net across 508 records (1.28 million weighted). Federal income tax and benefits don't move.
  • Axiom: us-az:statutes/43-1072 queued (TheAxiomFoundation/rulespec-us#1483)

@MaxGhenis
MaxGhenis deleted the claude/az-ptc-household-income-ayyw2d branch November 3, 2026 09:32
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