Skip to content

Utah CTC contrib reform changes years in which its in_effect switch is off #9842

Open

Description

@MaxGhenis

Switching on gov.contrib.states.ut.ctc.in_effect from 2026 changes Utah income tax in 2024 and 2025, when the switch is still false.

Repro

Run on the head of #9628 (743b6dfd3d, which is main at ea79c39fb7 plus that PR), with policyengine-core 3.32.15:

from policyengine_us import Simulation

YEARS = (2024, 2025, 2026)
members = ["adult1", "adult2", "child1", "child2"]
situation = {
    "people": {
        "adult1": {
            "age": {y: 35 for y in YEARS},
            "employment_income": {y: 110_000 for y in YEARS},
        },
        "adult2": {"age": {y: 35 for y in YEARS}},
        "child1": {"age": {y: y - 2023 for y in YEARS}},
        "child2": {"age": {y: y - 2022 for y in YEARS}},
    },
    "tax_units": {"tu": {"members": members}},
    "marital_units": {"mu": {"members": ["adult1", "adult2"]}},
    "households": {
        "hh": {"members": members, "state_code": {y: "UT" for y in YEARS}}
    },
}
baseline = Simulation(situation=situation)
reformed = Simulation(
    situation=situation,
    reform={"gov.contrib.states.ut.ctc.in_effect": {"2026-01-01.2100-12-31": True}},
)
for y in YEARS:
    print(
        y,
        reformed.calculate("household_net_income", y)[0]
        - baseline.calculate("household_net_income", y)[0],
    )
Year in_effect Change in household_net_income Change in ut_income_tax
2024 false +$800 −$800
2025 false +$800 −$800
2026 true +$800 −$800

Cause

create_ut_ctc_reform (policyengine_us/reforms/states/ut/ctc/ut_ctc_reform.py) installs the reform for the whole simulation when in_effect is true in any of the five years from the simulation's start. The variables it installs (ut_ctc_eligible_children, ut_ctc_potential and ut_refundable_ctc) replace the baseline ones, and none of them reads in_effect, so they run in every year, including the years before the switch turns on.

Other contrib reforms that pair look-ahead detection with formulas that don't read the switch would behave the same way. I have only checked this one.

Found while reviewing #9628. On main, that PR's example (which also changes the reform amounts from 2026) shows a larger 2024–2025 change, because the changed amounts also leak back to 2015. #9628 fixes the leak but not this.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions