From 9d2bddeb6094736bfb80d911aa4eebe18ba5e9eb Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sun, 18 Oct 2026 17:58:23 -0400 Subject: [PATCH 1/3] Use the OBBBA federal credit for Kentucky's 2026 dependent care credit KRS 141.067 sets Kentucky's household and dependent care service credit at 20% of the federal credit allowed under IRC section 21, and KRS 141.010(21) fixes that Code at a reference date. 2026 Ky. Acts ch. 161, sec. 6 moved the date from December 31, 2024 to December 31, 2025 for tax years beginning on or after January 1, 2026, so Kentucky adopts the One Big Beautiful Bill Act's section 21 rate increase from 2026. The model still read the pre-OBBBA credit through a hard-coded 2026 year check. - Add gov.states.ky.tax.income.irc_conformity.obbba (false through 2025, true from 2026) and branch ky_cdcc_potential on it. - Make the pre_obbba_cdcc mirrors equal their live variables in years the Act does not change section 21 (including 2021's refundable credit), so a state can read them through a conformity parameter in any year without changing pre-2026 results or ignoring cdcc inputs. - YAML cases for 2025 and 2026 (the reviewer's household, the liability cap, both phase-downs) and a Hypothesis property test of the 20% match. Co-Authored-By: Claude Opus 5.5 --- .../fix-ky-irc-conformity-2026.fixed.md | 1 + .../ky/tax/income/irc_conformity/obbba.yaml | 25 ++ .../gov/irs/credits/cdcc/pre_obbba_cdcc.yaml | 43 ++- .../dependent_care_credit/ky_cdcc.yaml | 149 +++++++++- .../tax/income/test_ky_cdcc_federal_match.py | 281 ++++++++++++++++++ .../gov/irs/credits/cdcc/pre_obbba_cdcc.py | 34 ++- .../ky_cdcc_potential.py | 29 +- 7 files changed, 533 insertions(+), 29 deletions(-) create mode 100644 changelog.d/fix-ky-irc-conformity-2026.fixed.md create mode 100644 policyengine_us/parameters/gov/states/ky/tax/income/irc_conformity/obbba.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ky/tax/income/test_ky_cdcc_federal_match.py diff --git a/changelog.d/fix-ky-irc-conformity-2026.fixed.md b/changelog.d/fix-ky-irc-conformity-2026.fixed.md new file mode 100644 index 00000000000..032cd28d9dd --- /dev/null +++ b/changelog.d/fix-ky-irc-conformity-2026.fixed.md @@ -0,0 +1 @@ +Kentucky's household and dependent care service credit uses the federal credit as amended by the One Big Beautiful Bill Act from 2026, when 2026 Ky. Acts ch. 161 moved Kentucky's Internal Revenue Code reference date to December 31, 2025. A new parameter records Kentucky's conformity to the Act, and the pre-OBBBA federal credit variables now equal the live credit in years the Act does not change section 21. diff --git a/policyengine_us/parameters/gov/states/ky/tax/income/irc_conformity/obbba.yaml b/policyengine_us/parameters/gov/states/ky/tax/income/irc_conformity/obbba.yaml new file mode 100644 index 00000000000..427567df1e1 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ky/tax/income/irc_conformity/obbba.yaml @@ -0,0 +1,25 @@ +description: Kentucky adopts the One Big Beautiful Bill Act (Public Law 119-21) amendments to the Internal Revenue Code if this is true. +# KRS 141.010(21) defines Kentucky's "Internal Revenue Code" as the Code in +# effect on a fixed reference date. The Act was enacted on July 4, 2025. +# - Tax years 2018 to 2025: every reference date (December 31, 2017, 2018, +# 2021, 2022, 2023 and 2024) predates the Act. For 2025, 2025 Ky. Acts +# ch. 98, sec. 30 set the date at December 31, 2024. +# - Tax years 2026 on: 2026 Ky. Acts ch. 161, sec. 6 moved the date to +# December 31, 2025, which includes the Act. +# Kentucky decouples from specific provisions of the Act in KRS 141.019 and +# 141.0101 (for example sections 174A, 224 and 225); this parameter does not +# govern those. +values: + 2018-01-01: false + 2026-01-01: true +metadata: + unit: bool + period: year + label: Kentucky Internal Revenue Code conformity to the One Big Beautiful Bill Act + reference: + - title: KRS 141.010(21) + href: https://apps.legislature.ky.gov/law/statutes/statute.aspx?id=57913#page=3 + - title: 2026 Ky. Acts ch. 161 (HB 757), sec. 6 + href: https://apps.legislature.ky.gov/law/acts/26RS/documents/0161.pdf#page=9 + - title: 2025 Ky. Acts ch. 98, sec. 30 + href: https://apps.legislature.ky.gov/law/acts/25RS/documents/0098.pdf#page=56 diff --git a/policyengine_us/tests/policy/baseline/gov/irs/credits/cdcc/pre_obbba_cdcc.yaml b/policyengine_us/tests/policy/baseline/gov/irs/credits/cdcc/pre_obbba_cdcc.yaml index 1806d204ca7..77211cf205b 100644 --- a/policyengine_us/tests/policy/baseline/gov/irs/credits/cdcc/pre_obbba_cdcc.yaml +++ b/policyengine_us/tests/policy/baseline/gov/irs/credits/cdcc/pre_obbba_cdcc.yaml @@ -1,9 +1,10 @@ # The pre_obbba_cdcc family recomputes the federal section 21 credit on the # rate schedule as it stood before the One Big Beautiful Bill Act (OBBBA). For -# 2025 it must equal the live cdcc (identical schedule); for 2026 it must hold -# the pre-OBBBA rate (max 35%, min 20%, no amended second phase-out) while the -# live cdcc reflects the OBBBA increase (max 50%, min 35%). Read by states whose -# income tax statically conforms to a pre-2026 IRC (KY, ME, VT). +# every year the Act does not change section 21 it must equal the live cdcc, +# including 2021's refundable American Rescue Plan Act credit; for 2026 it must +# hold the pre-OBBBA rate (max 35%, min 20%, no amended second phase-out) while +# the live cdcc reflects the OBBBA increase (max 50%, min 35%). Read by states +# whose income tax statically conforms to a pre-OBBBA IRC. # Low-income joint family, two children, $6,000 childcare, AGI below the first # phase-out start so the applicable rate is at its maximum. @@ -65,3 +66,37 @@ pre_obbba_cdcc_potential: 1_200 pre_obbba_cdcc: 1_200 pre_obbba_capped_cdcc: 1_200 + +# 2021: the American Rescue Plan Act made the credit refundable with a 50% rate +# below $125,000 of AGI and $8,000 / $16,000 expense limits (IRC 21(g)). The Act +# did not change 2021, so the pre-OBBBA credit is the live refundable credit, +# not the 2025 rate on 2021 expense limits ($1,200 before this fix). +- name: 2021 pre-OBBBA CDCC equals the live refundable ARPA credit + period: 2021 + absolute_error_margin: 0.01 + input: + people: + head: + age: 35 + employment_income: 25_000 + spouse: + age: 35 + employment_income: 25_000 + child1: + age: 5 + child2: + age: 7 + tax_units: + tax_unit: + members: [head, spouse, child1, child2] + filing_status: JOINT + tax_unit_childcare_expenses: 6_000 + premium_tax_credit: 0 + output: + # 50% x $6,000 = $3,000, refundable, so not capped at liability. + cdcc_potential: 3_000 + cdcc: 3_000 + capped_cdcc: 3_000 + pre_obbba_cdcc_potential: 3_000 + pre_obbba_cdcc: 3_000 + pre_obbba_capped_cdcc: 3_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ky/tax/income/credits/dependent_care_credit/ky_cdcc.yaml b/policyengine_us/tests/policy/baseline/gov/states/ky/tax/income/credits/dependent_care_credit/ky_cdcc.yaml index e57c2abaa4b..6ebe8cb039a 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ky/tax/income/credits/dependent_care_credit/ky_cdcc.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ky/tax/income/credits/dependent_care_credit/ky_cdcc.yaml @@ -21,10 +21,78 @@ output: ky_cdcc: 0 -# KRS 141.010(21) freezes Kentucky's IRC at December 31, 2024, so from 2026 the -# credit uses the pre-OBBBA federal section 21 credit (20% of $1,200 = $240), -# not the OBBBA-inflated live credit (which would give 20% of $1,780 = $356). -- name: 2026 uses the pre-OBBBA federal credit under static conformity +# KRS 141.067 sets the credit at 20% of the federal credit allowed under IRC +# section 21, and KRS 141.010(21) fixes Kentucky's Code at a reference date. +# For 2025 that date is December 31, 2024, before the One Big Beautiful Bill +# Act; from 2026 it is December 31, 2025 (2026 Ky. Acts ch. 161, sec. 6), so +# Kentucky adopts the Act's section 21 rate schedule: 50% less one point per +# $2,000 of AGI over $15,000, floored at 35%, then one point per $2,000 ($4,000 +# joint) of AGI over $75,000 ($150,000 joint), floored at 20%. The pre-OBBBA +# schedule is 35% less one point per $2,000 over $15,000, floored at 20%. + +- name: 2025 single parent, $50,000 earnings, $1,000 care for a child of five + period: 2025 + absolute_error_margin: 0.01 + input: + people: + parent: + age: 30 + employment_income: 50_000 + child: + age: 5 + tax_units: + tax_unit: + members: [parent, child] + tax_unit_childcare_expenses: 1_000 + premium_tax_credit: 0 + households: + household: + members: [parent, child] + state_code: KY + output: + # 2025 is before the Act's section 21 change: 35% - 18 points = 17%, + # floored at 20%, so $200 federally, under the federal liability. + cdcc: 200 + pre_obbba_cdcc: 200 + ky_cdcc_potential: 40 + ky_cdcc: 40 + # ($50,000 - $3,270 standard deduction) x 4% = $1,869.20, less $40. + ky_income_tax: 1_829.2 + +- name: 2026 single parent, $50,000 earnings, $1,000 care for a child of five + period: 2026 + absolute_error_margin: 0.01 + input: + people: + parent: + age: 30 + employment_income: 50_000 + child: + age: 5 + tax_units: + tax_unit: + members: [parent, child] + tax_unit_childcare_expenses: 1_000 + premium_tax_credit: 0 + households: + household: + members: [parent, child] + state_code: KY + output: + # The Act's schedule: 50% - 18 points = 32%, floored at 35%; AGI is under + # the $75,000 second phase-down. 35% x $1,000 = $350, under the federal + # liability. The pre-OBBBA schedule would give 20%, or $200. + cdcc: 350 + pre_obbba_cdcc: 200 + # 20% of $350. + ky_cdcc_potential: 70 + ky_cdcc: 70 + # ($50,000 - $3,360 standard deduction) x 3.5% = $1,632.40, less $70. + ky_income_tax: 1_562.4 + +# The federal credit is capped at federal liability (IRC 26), and Kentucky +# matches the capped "credit allowed". +- name: 2026 joint filers with $50,000 earnings and $6,000 care get 20% of the capped federal credit period: 2026 absolute_error_margin: 0.01 input: @@ -54,5 +122,76 @@ members: [head, spouse, child1, child2] state_code: KY output: - # 20% of the pre-OBBBA $1,200 federal credit. + # 35% x $6,000 = $2,100, capped at the $1,780 federal liability. + cdcc_potential: 2_100 + cdcc: 1_780 + # 20% of $1,780. + ky_cdcc_potential: 356 + ky_cdcc: 356 + +- name: 2026 joint filers in the Act's second phase-down + period: 2026 + absolute_error_margin: 0.01 + input: + people: + head: + age: 40 + employment_income: 80_000 + spouse: + age: 40 + employment_income: 80_000 + child1: + age: 3 + child2: + age: 6 + tax_units: + tax_unit: + members: [head, spouse, child1, child2] + filing_status: JOINT + tax_unit_childcare_expenses: 6_000 + premium_tax_credit: 0 + households: + household: + members: [head, spouse, child1, child2] + state_code: KY + output: + # 35% less one point per $4,000 (or part) over $150,000: $10,000 is three + # increments, so 32%. 32% x $6,000 = $1,920. Pre-OBBBA: 20%, or $1,200. + cdcc: 1_920 + pre_obbba_cdcc: 1_200 + # 20% of $1,920. + ky_cdcc_potential: 384 + ky_cdcc: 384 + +- name: 2026 joint filers at the bottom of the Act's second phase-down + period: 2026 + absolute_error_margin: 0.01 + input: + people: + head: + age: 40 + employment_income: 110_000 + spouse: + age: 40 + employment_income: 110_000 + child1: + age: 3 + child2: + age: 6 + tax_units: + tax_unit: + members: [head, spouse, child1, child2] + filing_status: JOINT + tax_unit_childcare_expenses: 6_000 + premium_tax_credit: 0 + households: + household: + members: [head, spouse, child1, child2] + state_code: KY + output: + # $70,000 over $150,000 is 18 increments: 35% - 18 = 17%, floored at 20%, + # the same rate as the pre-OBBBA schedule. 20% x $6,000 = $1,200. + cdcc: 1_200 + pre_obbba_cdcc: 1_200 + ky_cdcc_potential: 240 ky_cdcc: 240 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ky/tax/income/test_ky_cdcc_federal_match.py b/policyengine_us/tests/policy/baseline/gov/states/ky/tax/income/test_ky_cdcc_federal_match.py new file mode 100644 index 00000000000..f018a949deb --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ky/tax/income/test_ky_cdcc_federal_match.py @@ -0,0 +1,281 @@ +"""Property tests: Kentucky's dependent care credit is 20% of the federal +section 21 credit under Kentucky's conformed Internal Revenue Code. + +KRS 141.067: "The credit shall be twenty percent (20%) of the federal credit +allowed under Section 21 of the Internal Revenue Code." KRS 141.010(21) fixes +that Code at a reference date: December 31, 2024 for 2025 (2025 Ky. Acts ch. +98, sec. 30) and December 31, 2025 from 2026 (2026 Ky. Acts ch. 161, sec. 6). +The One Big Beautiful Bill Act, enacted July 4, 2025, amended section 21 for +tax years beginning after 2025, so Kentucky adopts that change from 2026. + +For each Kentucky tax unit, with C the federal credit allowed (cdcc, after the +IRC 26 liability cap), P the same credit on the pre-OBBBA rate schedule +(pre_obbba_cdcc), K = ky_cdcc_potential and k = ky_cdcc: + +1. K = 0.2 * C in 2025, 2026 and 2027. Before 2026 Kentucky's Code predates + the Act, but the Act does not change section 21 for those years. +2. In years the Act does not change section 21 (2021 and 2025 here, including + the refundable 2021 credit), each pre-OBBBA mirror equals its live variable. +3. From 2026, C >= P: the Act's rate is at least the pre-OBBBA rate at every + AGI, so adopting it never lowers Kentucky's credit. +4. The federal potential credit equals a reference written from IRC 21(a)(2) + (and, from 2026, the Act's amended schedule) times the relevant expenses. +5. 0 <= k <= K. +6. Under a reform that turns Kentucky's OBBBA conformity off, K = 0.2 * P + from 2026, and K is unchanged in 2025 (checked on the grid only, since the + reformed system costs about 0.55 GiB and 7 seconds to build). +7. The OBBBA marker that the pre-OBBBA mirrors read switches on in exactly the + years the live rate schedule departs from the frozen pre-OBBBA one. + +Each Simulation holds every year at once, so a batch costs one Simulation. +The model computes in single precision, so comparisons allow one cent or eight +float32 spacings at the largest amount, whichever is larger. +""" + +from math import ceil + +import numpy as np +import pytest +from policyengine_core.reforms import Reform + +from policyengine_us import CountryTaxBenefitSystem, Simulation + +hypothesis = pytest.importorskip("hypothesis") +st = pytest.importorskip("hypothesis.strategies") + +MATCH = 0.2 +CONFORMITY = "gov.states.ky.tax.income.irc_conformity.obbba" +YEARS = [2021, 2025, 2026, 2027] +MATCH_YEARS = [2025, 2026, 2027] +NO_OBBBA_CHANGE_YEARS = [2021, 2025] +OBBBA_YEARS = [2026, 2027] +REFORM_YEARS = [2025, 2026, 2027] + +OUTPUTS = [ + "adjusted_gross_income", + "cdcc_filing_status_eligible", + "cdcc_relevant_expenses", + "cdcc_potential", + "cdcc", + "capped_cdcc", + "pre_obbba_cdcc_potential", + "pre_obbba_cdcc", + "pre_obbba_capped_cdcc", + "ky_cdcc_potential", + "ky_cdcc", +] +PAIRS = [ + ("pre_obbba_cdcc_potential", "cdcc_potential"), + ("pre_obbba_cdcc", "cdcc"), + ("pre_obbba_capped_cdcc", "capped_cdcc"), +] + + +@pytest.fixture(scope="module") +def decoupled_system(): + # Built once for the module and released at its end, so the reformed + # parameter tree does not stay resident for the rest of the test process. + reform = Reform.from_dict({CONFORMITY: {"2018-01-01.2100-12-31": False}}, "us") + yield CountryTaxBenefitSystem(reform=reform) + + +def tolerance(*amounts): + scale = np.float32(max(np.max(np.abs(a)) for a in amounts)) + return max(0.01, 8 * float(np.spacing(scale))) + + +def situation(units, years): + """One Kentucky tax unit per household: a head, a spouse if married, and + children of the given ages, with the same inputs in every year.""" + people, tax_units, households = {}, {}, {} + + def each_year(value): + return {year: value for year in years} + + for i, unit in enumerate(units): + head = f"head{i}" + members = [head] + people[head] = { + "age": each_year(35), + "employment_income": each_year(unit["wages"]), + } + if unit["married"]: + spouse = f"spouse{i}" + members.append(spouse) + people[spouse] = { + "age": each_year(35), + "employment_income": each_year(unit["spouse_wages"]), + } + for j, age in enumerate(unit["child_ages"]): + child = f"child{i}_{j}" + members.append(child) + people[child] = {"age": each_year(age)} + tax_units[f"t{i}"] = { + "members": members, + "tax_unit_childcare_expenses": each_year(unit["expenses"]), + "premium_tax_credit": each_year(0), + } + households[f"h{i}"] = {"members": members, "state_code": each_year("KY")} + return {"people": people, "tax_units": tax_units, "households": households} + + +def calculate(units, years, outputs, **system): + sim = Simulation(situation=situation(units, years), **system) + return { + year: {name: sim.calculate(name, year) for name in outputs} for year in years + } + + +def reference_rate(agi, joint, year): + """IRC 21(a)(2): 35% less one point per $2,000 (or part) of AGI over + $15,000, floored at 20%. From 2026 the Act raises that to 50% floored at + 35%, then subtracts one point per $2,000 ($4,000 joint) of AGI over + $75,000 ($150,000 joint), floored at 20%.""" + first = ceil(max(0, agi - 15_000) / 2_000) / 100 + if year < 2026: + return max(0.20, 0.35 - first) + start, step = (150_000, 4_000) if joint else (75_000, 2_000) + second = ceil(max(0, agi - start) / step) / 100 + return max(0.20, max(0.35, 0.50 - first) - second) + + +def check(units): + result = calculate(units, YEARS, OUTPUTS) + for year in YEARS: + r = result[year] + tol = tolerance(r["cdcc_potential"], r["pre_obbba_cdcc_potential"]) + k, big_k = r["ky_cdcc"], r["ky_cdcc_potential"] + c, p = r["cdcc"], r["pre_obbba_cdcc"] + # 1. Kentucky matches 20% of the live federal credit allowed. + if year in MATCH_YEARS: + np.testing.assert_allclose(big_k, MATCH * c, atol=tol) + # 2. The pre-OBBBA mirrors equal the live credits where the Act does + # not change section 21. + if year in NO_OBBBA_CHANGE_YEARS: + for mirror, live in PAIRS: + np.testing.assert_allclose(r[mirror], r[live], atol=tol) + # 3. The Act never lowers the federal credit, before or after the cap. + if year in OBBBA_YEARS: + assert (c >= p - tol).all() + assert (r["cdcc_potential"] >= r["pre_obbba_cdcc_potential"] - tol).all() + # 4. The potential credit follows the statute's rate schedule. 2021's + # American Rescue Plan Act schedule is outside this reference. + if year != 2021: + joint = np.array([u["married"] for u in units]) + rate = np.array( + [ + reference_rate(float(agi), married, year) + for agi, married in zip(r["adjusted_gross_income"], joint) + ] + ) + expected = ( + r["cdcc_filing_status_eligible"] * r["cdcc_relevant_expenses"] * rate + ) + np.testing.assert_allclose(r["cdcc_potential"], expected, atol=tol) + # 5. The liability-limited credit never exceeds its potential. + assert (k >= -tol).all() + assert (k <= big_k + tol).all() + return result + + +def check_decoupled(units, baseline, system): + # 6. With Kentucky's OBBBA conformity off, Kentucky reads the pre-OBBBA + # credit once the Act changes section 21, and nothing changes before. + decoupled = calculate( + units, REFORM_YEARS, ["ky_cdcc_potential"], tax_benefit_system=system + ) + for year in REFORM_YEARS: + r = baseline[year] + tol = tolerance(r["cdcc_potential"]) + big_k = decoupled[year]["ky_cdcc_potential"] + if year in OBBBA_YEARS: + np.testing.assert_allclose(big_k, MATCH * r["pre_obbba_cdcc"], atol=tol) + # Conforming never lowers Kentucky's credit. + assert (r["ky_cdcc_potential"] >= big_k - tol).all() + else: + np.testing.assert_allclose(big_k, r["ky_cdcc_potential"], atol=tol) + + +def unit(married, wages, spouse_wages, child_ages, expenses): + return { + "married": married, + "wages": wages, + "spouse_wages": spouse_wages, + "child_ages": child_ages, + "expenses": expenses, + } + + +# Boundaries of both phase-downs, either side of each, the cap on expenses, +# a non-qualifying 13-year-old, no expenses, and a unit whose federal credit +# is cut by liability. +GRID = [ + # Unmarried: first phase-down from $15,000, second from $75,000. + unit(False, 15_000, 0, [4], 3_000), + unit(False, 15_001, 0, [4], 3_000), + unit(False, 50_000, 0, [5], 1_000), + unit(False, 75_000, 0, [2, 9], 8_000), + unit(False, 75_001, 0, [2, 9], 8_000), + unit(False, 103_000, 0, [2, 9], 6_000), + unit(False, 103_001, 0, [2, 9], 6_000), + unit(False, 60_000, 0, [13], 4_000), + unit(False, 40_000, 0, [3], 0), + # Married filing jointly: second phase-down from $150,000 by $4,000. + unit(True, 25_000, 25_000, [5, 7], 6_000), + unit(True, 75_000, 75_000, [1, 4, 6], 9_000), + unit(True, 75_000, 75_001, [1, 4, 6], 9_000), + unit(True, 80_000, 80_000, [3, 6], 6_000), + unit(True, 105_000, 105_000, [3, 6], 6_000), + unit(True, 105_000, 105_001, [3, 6], 6_000), + # Lower earner's income limits the expenses (IRC 21(d)(1)). + unit(True, 90_000, 1_500, [3], 3_000), +] + + +def test_grid_matches_20_percent_of_federal_credit(decoupled_system): + result = check(GRID) + check_decoupled(GRID, result, decoupled_system) + # The grid has 2026 units where the Act raises the credit, units where + # both schedules give the same positive credit, and units whose federal + # credit the liability cap cuts. + r = result[2026] + differs = r["cdcc"] > r["pre_obbba_cdcc"] + 0.01 + same = np.isclose(r["cdcc"], r["pre_obbba_cdcc"]) + capped = r["cdcc"] < r["cdcc_potential"] - 0.01 + assert differs.any() and (same & (r["cdcc"] > 0)).any() and capped.any() + + +def test_obbba_marker_matches_rate_schedule(): + # 7. The mirrors read amended_structure.applies as the years the Act + # changes section 21. It must switch on with the Act's rate changes. + from policyengine_us.system import system + + parameters = system.parameters + frozen = parameters.gov.irs.credits.cdcc("2025-01-01").phase_out + for year in range(2022, 2036): + live = parameters.gov.irs.credits.cdcc(f"{year}-01-01").phase_out + departs = (live.max, live.min) != (frozen.max, frozen.min) + assert bool(live.amended_structure.applies) == departs, year + + +unit_strategy = st.builds( + unit, + st.booleans(), + st.one_of(st.just(0), st.integers(1, 260_000)), + st.one_of(st.just(0), st.integers(1, 160_000)), + st.lists(st.integers(0, 14), max_size=3), + st.one_of(st.just(0), st.integers(1, 12_000)), +) + + +@hypothesis.settings( + max_examples=10, + deadline=None, + suppress_health_check=[ + hypothesis.HealthCheck.too_slow, + hypothesis.HealthCheck.data_too_large, + ], +) +@hypothesis.given(st.lists(unit_strategy, min_size=1, max_size=20)) +def test_random_units_match_20_percent_of_federal_credit(units): + check(units) diff --git a/policyengine_us/variables/gov/irs/credits/cdcc/pre_obbba_cdcc.py b/policyengine_us/variables/gov/irs/credits/cdcc/pre_obbba_cdcc.py index 90d52da4f6a..d8b2d510d87 100644 --- a/policyengine_us/variables/gov/irs/credits/cdcc/pre_obbba_cdcc.py +++ b/policyengine_us/variables/gov/irs/credits/cdcc/pre_obbba_cdcc.py @@ -1,6 +1,16 @@ from policyengine_us.model_api import * +def obbba_amends_section_21(parameters, period): + # The Act's section 21 amendments (the higher maximum and minimum rates + # and the amended second phase-out) all take effect for tax years + # beginning after 2025-12-31. The amended phase-out structure flag is + # dated with them, so it marks the years the Act changes section 21. In + # other years the pre-OBBBA credit is the live credit, including the 2021 + # American Rescue Plan Act schedule. + return parameters(period).gov.irs.credits.cdcc.phase_out.amended_structure.applies + + class pre_obbba_cdcc_potential(Variable): value_type = float entity = TaxUnit @@ -9,16 +19,19 @@ class pre_obbba_cdcc_potential(Variable): "The federal child and dependent care credit before the section 26 " "liability cap, recomputed with the IRC section 21 rate schedule as it " "stood before the One Big Beautiful Bill Act (OBBBA). States whose " - "income tax statically conforms to a pre-2026 IRC read this instead of " - "the live federal credit so they do not silently adopt the OBBBA " + "income tax statically conforms to a pre-OBBBA IRC read this instead " + "of the live federal credit so they do not silently adopt the OBBBA " "section 21 rate increase, effective for tax years beginning after " - "2025-12-31." + "2025-12-31. In years the Act does not change section 21, this equals " + "the live cdcc_potential." ) unit = USD definition_period = YEAR reference = "https://www.law.cornell.edu/uscode/text/26/21#a_2" def formula(tax_unit, period, parameters): + if not obbba_amends_section_21(parameters, period): + return tax_unit("cdcc_potential", period) # Only the section 21(a)(2) rate schedule changed under OBBBA # (phase_out.max 0.35->0.50, phase_out.min 0.20->0.35, plus a new # amended second phase-out), all dated 2026-01-01. The section 21(b)-(e) @@ -48,16 +61,18 @@ class pre_obbba_cdcc(Variable): documentation = ( "Mirror of the live cdcc variable but built on the pre-OBBBA section 21 " "rate schedule, for states whose income tax statically conforms to a " - "pre-2026 IRC." + "pre-OBBBA IRC. In years the Act does not change section 21, this " + "equals the live cdcc." ) unit = USD definition_period = YEAR reference = "https://www.law.cornell.edu/uscode/text/26/21" def formula(tax_unit, period, parameters): - # cdcc has been non-refundable since 2022; every state that reads this - # computes post-2022, so apply the section 26 liability cap directly - # (the refundable-2021 branch of the live cdcc is not reachable here). + if not obbba_amends_section_21(parameters, period): + return tax_unit("cdcc", period) + # The Act leaves the credit non-refundable, so apply the section 26 + # liability cap as the live cdcc does in non-refundable years. potential = tax_unit("pre_obbba_cdcc_potential", period) credit_limit = tax_unit("cdcc_credit_limit", period) return min_(credit_limit, potential) @@ -70,13 +85,16 @@ class pre_obbba_capped_cdcc(Variable): documentation = ( "Mirror of the live capped_cdcc variable but built on the pre-OBBBA " "section 21 rate schedule, for states whose income tax statically " - "conforms to a pre-2026 IRC." + "conforms to a pre-OBBBA IRC. In years the Act does not change " + "section 21, this equals the live capped_cdcc." ) unit = USD definition_period = YEAR reference = "https://www.irs.gov/instructions/i2441" def formula(tax_unit, period, parameters): + if not obbba_amends_section_21(parameters, period): + return tax_unit("capped_cdcc", period) cdcc = tax_unit("pre_obbba_cdcc", period) # 2022 Form 2441 Credit Limit Worksheet: cap at tax before credits less # the foreign tax credit (the section 26 cap is unchanged by OBBBA). diff --git a/policyengine_us/variables/gov/states/ky/tax/income/credits/dependent_care_service/ky_cdcc_potential.py b/policyengine_us/variables/gov/states/ky/tax/income/credits/dependent_care_service/ky_cdcc_potential.py index 7a7ea11a9d9..73f62508423 100644 --- a/policyengine_us/variables/gov/states/ky/tax/income/credits/dependent_care_service/ky_cdcc_potential.py +++ b/policyengine_us/variables/gov/states/ky/tax/income/credits/dependent_care_service/ky_cdcc_potential.py @@ -7,21 +7,26 @@ class ky_cdcc_potential(Variable): label = "Kentucky household and dependent care service credit" unit = USD definition_period = YEAR - reference = "https://apps.legislature.ky.gov/law/statutes/statute.aspx?id=29058" + reference = ( + "https://apps.legislature.ky.gov/law/statutes/statute.aspx?id=29058", + "https://apps.legislature.ky.gov/law/statutes/statute.aspx?id=57913#page=3", + ) defined_for = StateCode.KY def formula(tax_unit, period, parameters): + p = parameters(period).gov.states.ky.tax.income # Kentucky matches the federal credit taken. KRS 141.067 sets the credit # at 20% of "the federal credit allowed under Section 21 of the Internal - # Revenue Code," and KRS 141.010(21) fixes Kentucky's IRC at the Code in - # effect on December 31, 2024. From 2026 that frozen Code excludes the - # OBBBA section 21 rate increase (effective for tax years beginning after - # 2025-12-31), so Kentucky uses the pre-OBBBA federal credit. - if period.start.year >= 2026: - dependent_care_credit = tax_unit("pre_obbba_cdcc", period) + # Revenue Code," and KRS 141.010(21) fixes that Code at a reference + # date. Where the reference date predates the One Big Beautiful Bill + # Act, Kentucky's section 21 excludes the Act's rate increase. From + # 2026 the reference date is December 31, 2025, which includes it. + # The 2019-2021 reference date (December 31, 2018) also excludes the + # American Rescue Plan Act's 2021 section 21 expansion (2021 Form + # 2441-K); the model does not apply that yet, so 2021 reads the live + # federal credit. + if p.irc_conformity.obbba: + federal_credit = tax_unit("cdcc", period) else: - dependent_care_credit = tax_unit("cdcc", period) - rate = parameters( - period - ).gov.states.ky.tax.income.credits.dependent_care_service.match - return dependent_care_credit * rate + federal_credit = tax_unit("pre_obbba_cdcc", period) + return federal_credit * p.credits.dependent_care_service.match From 338fd8db43ec7202f789e4ca9aebbecfb2f56f5c Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sun, 18 Oct 2026 18:31:10 -0400 Subject: [PATCH 2/3] Key pre-OBBBA mirrors on the Act's effective date; test the lever in YAML Review round 1 (GPT-6.1 Sol) on 9d2bddeb60: - The mirrors read gov.irs.credits.cdcc.phase_out.amended_structure.applies as the years the Act changes section 21, but that is a policy lever: a reform switching it off in 2026 kept the 50%/35% rates and made the mirrors live ($200 -> $350). Key them on P.L. 119-21 sec. 70405(b)'s effective date (taxable years beginning after December 31, 2025) instead, and add a YAML case for that reform. - YAML accepts parameter inputs, so test the Kentucky conformity lever there (2026 off -> $40; 2025 on -> unchanged) and drop the reformed system from the property test. Invariant 6 now checks the effective date against the baseline schedule. - Fix the stale comment in pre_obbba_cdcc.yaml ($50,000 is past the first phase-out start; the 2025 rate is the 20% floor). Co-Authored-By: Claude Opus 5.5 --- .../gov/irs/credits/cdcc/pre_obbba_cdcc.yaml | 36 ++++++++-- .../dependent_care_credit/ky_cdcc.yaml | 52 ++++++++++++++ .../tax/income/test_ky_cdcc_federal_match.py | 67 +++++++------------ .../gov/irs/credits/cdcc/pre_obbba_cdcc.py | 37 +++++----- 4 files changed, 128 insertions(+), 64 deletions(-) diff --git a/policyengine_us/tests/policy/baseline/gov/irs/credits/cdcc/pre_obbba_cdcc.yaml b/policyengine_us/tests/policy/baseline/gov/irs/credits/cdcc/pre_obbba_cdcc.yaml index 77211cf205b..9d65c0bcd30 100644 --- a/policyengine_us/tests/policy/baseline/gov/irs/credits/cdcc/pre_obbba_cdcc.yaml +++ b/policyengine_us/tests/policy/baseline/gov/irs/credits/cdcc/pre_obbba_cdcc.yaml @@ -1,13 +1,14 @@ # The pre_obbba_cdcc family recomputes the federal section 21 credit on the # rate schedule as it stood before the One Big Beautiful Bill Act (OBBBA). For -# every year the Act does not change section 21 it must equal the live cdcc, -# including 2021's refundable American Rescue Plan Act credit; for 2026 it must +# tax years before the Act's section 21 amendment applies (P.L. 119-21 sec. +# 70405(b): years beginning after December 31, 2025) it must equal the live +# cdcc, including 2021's refundable American Rescue Plan Act credit; for 2026 it must # hold the pre-OBBBA rate (max 35%, min 20%, no amended second phase-out) while # the live cdcc reflects the OBBBA increase (max 50%, min 35%). Read by states # whose income tax statically conforms to a pre-OBBBA IRC. -# Low-income joint family, two children, $6,000 childcare, AGI below the first -# phase-out start so the applicable rate is at its maximum. +# Joint family, two children, $6,000 childcare, $50,000 AGI: $35,000 over the +# $15,000 phase-out start is 18 increments, so the 2025 rate is the 20% floor. - name: 2025 pre-OBBBA CDCC equals the live CDCC (identical schedule) period: 2025 absolute_error_margin: 0.01 @@ -100,3 +101,30 @@ pre_obbba_cdcc_potential: 3_000 pre_obbba_cdcc: 3_000 pre_obbba_capped_cdcc: 3_000 + +# The mirrors key on the Act's effective date, not on a section 21 parameter. +# A reform that switches off the amended second phase-out in 2026 leaves the +# live 50% maximum and 35% floor in place, and must not move the mirrors. +- name: 2026 pre-OBBBA CDCC stays frozen when a reform switches off the amended phase-out + period: 2026 + absolute_error_margin: 0.01 + input: + gov.irs.credits.cdcc.phase_out.amended_structure.applies: false + people: + parent: + age: 30 + employment_income: 50_000 + child: + age: 5 + tax_units: + tax_unit: + members: [parent, child] + tax_unit_childcare_expenses: 1_000 + premium_tax_credit: 0 + output: + # Live: 50% less 18 points = 32%, floored at 35%; no second phase-down. + cdcc: 350 + # Pre-OBBBA: 35% less 18 points = 17%, floored at 20%. + pre_obbba_cdcc_potential: 200 + pre_obbba_cdcc: 200 + pre_obbba_capped_cdcc: 200 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ky/tax/income/credits/dependent_care_credit/ky_cdcc.yaml b/policyengine_us/tests/policy/baseline/gov/states/ky/tax/income/credits/dependent_care_credit/ky_cdcc.yaml index 6ebe8cb039a..0c2c44f6451 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ky/tax/income/credits/dependent_care_credit/ky_cdcc.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ky/tax/income/credits/dependent_care_credit/ky_cdcc.yaml @@ -195,3 +195,55 @@ pre_obbba_cdcc: 1_200 ky_cdcc_potential: 240 ky_cdcc: 240 + +# The conformity parameter is the lever: with it off, Kentucky reads the +# pre-OBBBA credit once the Act changes section 21. +- name: 2026 single parent under a reform that keeps Kentucky's Code before the Act + period: 2026 + absolute_error_margin: 0.01 + input: + gov.states.ky.tax.income.irc_conformity.obbba: false + people: + parent: + age: 30 + employment_income: 50_000 + child: + age: 5 + tax_units: + tax_unit: + members: [parent, child] + tax_unit_childcare_expenses: 1_000 + premium_tax_credit: 0 + households: + household: + members: [parent, child] + state_code: KY + output: + cdcc: 350 + # 20% of the $200 pre-OBBBA credit. + ky_cdcc_potential: 40 + +# Before 2026 the Act does not change section 21, so the lever has no effect. +- name: 2025 single parent under a reform that sets Kentucky's Code to include the Act + period: 2025 + absolute_error_margin: 0.01 + input: + gov.states.ky.tax.income.irc_conformity.obbba: true + people: + parent: + age: 30 + employment_income: 50_000 + child: + age: 5 + tax_units: + tax_unit: + members: [parent, child] + tax_unit_childcare_expenses: 1_000 + premium_tax_credit: 0 + households: + household: + members: [parent, child] + state_code: KY + output: + cdcc: 200 + ky_cdcc_potential: 40 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ky/tax/income/test_ky_cdcc_federal_match.py b/policyengine_us/tests/policy/baseline/gov/states/ky/tax/income/test_ky_cdcc_federal_match.py index f018a949deb..b7246e1a863 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ky/tax/income/test_ky_cdcc_federal_match.py +++ b/policyengine_us/tests/policy/baseline/gov/states/ky/tax/income/test_ky_cdcc_federal_match.py @@ -21,11 +21,13 @@ 4. The federal potential credit equals a reference written from IRC 21(a)(2) (and, from 2026, the Act's amended schedule) times the relevant expenses. 5. 0 <= k <= K. -6. Under a reform that turns Kentucky's OBBBA conformity off, K = 0.2 * P - from 2026, and K is unchanged in 2025 (checked on the grid only, since the - reformed system costs about 0.55 GiB and 7 seconds to build). -7. The OBBBA marker that the pre-OBBBA mirrors read switches on in exactly the - years the live rate schedule departs from the frozen pre-OBBBA one. +6. The Act's effective date that the pre-OBBBA mirrors key on (P.L. 119-21 + sec. 70405(b)) is the first year the baseline section 21 parameters depart + from the frozen pre-OBBBA schedule. + +The conformity parameter as a reform lever (Kentucky reads P when it is false +and the Act changes section 21) is covered in ky_cdcc.yaml, where a parameter +input needs no separately built system. Each Simulation holds every year at once, so a batch costs one Simulation. The model computes in single precision, so comparisons allow one cent or eight @@ -36,20 +38,21 @@ import numpy as np import pytest -from policyengine_core.reforms import Reform -from policyengine_us import CountryTaxBenefitSystem, Simulation +from policyengine_us import Simulation +from policyengine_us.variables.gov.irs.credits.cdcc.pre_obbba_cdcc import ( + OBBBA_SECTION_21_EFFECTIVE, + PRE_OBBBA_INSTANT, +) hypothesis = pytest.importorskip("hypothesis") st = pytest.importorskip("hypothesis.strategies") MATCH = 0.2 -CONFORMITY = "gov.states.ky.tax.income.irc_conformity.obbba" YEARS = [2021, 2025, 2026, 2027] MATCH_YEARS = [2025, 2026, 2027] NO_OBBBA_CHANGE_YEARS = [2021, 2025] OBBBA_YEARS = [2026, 2027] -REFORM_YEARS = [2025, 2026, 2027] OUTPUTS = [ "adjusted_gross_income", @@ -71,14 +74,6 @@ ] -@pytest.fixture(scope="module") -def decoupled_system(): - # Built once for the module and released at its end, so the reformed - # parameter tree does not stay resident for the rest of the test process. - reform = Reform.from_dict({CONFORMITY: {"2018-01-01.2100-12-31": False}}, "us") - yield CountryTaxBenefitSystem(reform=reform) - - def tolerance(*amounts): scale = np.float32(max(np.max(np.abs(a)) for a in amounts)) return max(0.01, 8 * float(np.spacing(scale))) @@ -119,8 +114,8 @@ def each_year(value): return {"people": people, "tax_units": tax_units, "households": households} -def calculate(units, years, outputs, **system): - sim = Simulation(situation=situation(units, years), **system) +def calculate(units, years, outputs): + sim = Simulation(situation=situation(units, years)) return { year: {name: sim.calculate(name, year) for name in outputs} for year in years } @@ -178,24 +173,6 @@ def check(units): return result -def check_decoupled(units, baseline, system): - # 6. With Kentucky's OBBBA conformity off, Kentucky reads the pre-OBBBA - # credit once the Act changes section 21, and nothing changes before. - decoupled = calculate( - units, REFORM_YEARS, ["ky_cdcc_potential"], tax_benefit_system=system - ) - for year in REFORM_YEARS: - r = baseline[year] - tol = tolerance(r["cdcc_potential"]) - big_k = decoupled[year]["ky_cdcc_potential"] - if year in OBBBA_YEARS: - np.testing.assert_allclose(big_k, MATCH * r["pre_obbba_cdcc"], atol=tol) - # Conforming never lowers Kentucky's credit. - assert (r["ky_cdcc_potential"] >= big_k - tol).all() - else: - np.testing.assert_allclose(big_k, r["ky_cdcc_potential"], atol=tol) - - def unit(married, wages, spouse_wages, child_ages, expenses): return { "married": married, @@ -232,9 +209,8 @@ def unit(married, wages, spouse_wages, child_ages, expenses): ] -def test_grid_matches_20_percent_of_federal_credit(decoupled_system): +def test_grid_matches_20_percent_of_federal_credit(): result = check(GRID) - check_decoupled(GRID, result, decoupled_system) # The grid has 2026 units where the Act raises the credit, units where # both schedules give the same positive credit, and units whose federal # credit the liability cap cuts. @@ -245,17 +221,20 @@ def test_grid_matches_20_percent_of_federal_credit(decoupled_system): assert differs.any() and (same & (r["cdcc"] > 0)).any() and capped.any() -def test_obbba_marker_matches_rate_schedule(): - # 7. The mirrors read amended_structure.applies as the years the Act - # changes section 21. It must switch on with the Act's rate changes. +def test_obbba_effective_date_matches_rate_schedule(): + # 6. From the Act's effective date on, and only then, the baseline section + # 21 schedule departs from the frozen one in both its rates and its amended + # second phase-out. from policyengine_us.system import system parameters = system.parameters - frozen = parameters.gov.irs.credits.cdcc("2025-01-01").phase_out + frozen = parameters.gov.irs.credits.cdcc(PRE_OBBBA_INSTANT).phase_out + effective = OBBBA_SECTION_21_EFFECTIVE.year for year in range(2022, 2036): live = parameters.gov.irs.credits.cdcc(f"{year}-01-01").phase_out departs = (live.max, live.min) != (frozen.max, frozen.min) - assert bool(live.amended_structure.applies) == departs, year + assert departs == (year >= effective), year + assert bool(live.amended_structure.applies) == (year >= effective), year unit_strategy = st.builds( diff --git a/policyengine_us/variables/gov/irs/credits/cdcc/pre_obbba_cdcc.py b/policyengine_us/variables/gov/irs/credits/cdcc/pre_obbba_cdcc.py index d8b2d510d87..c3c4d1d603d 100644 --- a/policyengine_us/variables/gov/irs/credits/cdcc/pre_obbba_cdcc.py +++ b/policyengine_us/variables/gov/irs/credits/cdcc/pre_obbba_cdcc.py @@ -1,14 +1,20 @@ +from policyengine_core.periods import instant + from policyengine_us.model_api import * +# P.L. 119-21 sec. 70405(b): the Act's amendment of section 21(a)(2) "shall +# apply to taxable years beginning after December 31, 2025." These mirrors model +# section 21 without that amendment, so they key on the statutory date rather +# than on a section 21 parameter that a reform could change. +OBBBA_SECTION_21_EFFECTIVE = instant("2026-01-01") +# Any 2023-2025 instant gives the pre-OBBBA rate schedule. +PRE_OBBBA_INSTANT = "2025-01-01" + -def obbba_amends_section_21(parameters, period): - # The Act's section 21 amendments (the higher maximum and minimum rates - # and the amended second phase-out) all take effect for tax years - # beginning after 2025-12-31. The amended phase-out structure flag is - # dated with them, so it marks the years the Act changes section 21. In - # other years the pre-OBBBA credit is the live credit, including the 2021 - # American Rescue Plan Act schedule. - return parameters(period).gov.irs.credits.cdcc.phase_out.amended_structure.applies +def obbba_amends_section_21(period): + # Before the effective date the pre-OBBBA credit is the live credit, + # including the 2021 American Rescue Plan Act schedule. + return period.start >= OBBBA_SECTION_21_EFFECTIVE class pre_obbba_cdcc_potential(Variable): @@ -30,17 +36,16 @@ class pre_obbba_cdcc_potential(Variable): reference = "https://www.law.cornell.edu/uscode/text/26/21#a_2" def formula(tax_unit, period, parameters): - if not obbba_amends_section_21(parameters, period): + if not obbba_amends_section_21(period): return tax_unit("cdcc_potential", period) # Only the section 21(a)(2) rate schedule changed under OBBBA # (phase_out.max 0.35->0.50, phase_out.min 0.20->0.35, plus a new # amended second phase-out), all dated 2026-01-01. The section 21(b)-(e) # expense base is unchanged, so freeze only the rate by reading the cdcc - # parameter subtree at a pre-OBBBA instant. Any 2023-2025 instant yields - # the same schedule; use 2025-01-01. The pre-OBBBA schedule has no - # second phase-out after 2021 (second_start is infinite from 2022), so - # the first phase-out is the whole rate computation. - frozen = parameters("2025-01-01").gov.irs.credits.cdcc + # parameter subtree at a pre-OBBBA instant. The pre-OBBBA schedule has + # no second phase-out after 2021 (second_start is infinite from 2022), + # so the first phase-out is the whole rate computation. + frozen = parameters(PRE_OBBBA_INSTANT).gov.irs.credits.cdcc agi = tax_unit("adjusted_gross_income", period) excess_agi = max_(0, agi - frozen.phase_out.start) increments = np.ceil(excess_agi / frozen.phase_out.increment) @@ -69,7 +74,7 @@ class pre_obbba_cdcc(Variable): reference = "https://www.law.cornell.edu/uscode/text/26/21" def formula(tax_unit, period, parameters): - if not obbba_amends_section_21(parameters, period): + if not obbba_amends_section_21(period): return tax_unit("cdcc", period) # The Act leaves the credit non-refundable, so apply the section 26 # liability cap as the live cdcc does in non-refundable years. @@ -93,7 +98,7 @@ class pre_obbba_capped_cdcc(Variable): reference = "https://www.irs.gov/instructions/i2441" def formula(tax_unit, period, parameters): - if not obbba_amends_section_21(parameters, period): + if not obbba_amends_section_21(period): return tax_unit("capped_cdcc", period) cdcc = tax_unit("pre_obbba_cdcc", period) # 2022 Form 2441 Credit Limit Worksheet: cap at tax before credits less From f78b6e0d971e5302516dd9e587a154489d710b34 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sun, 18 Oct 2026 18:47:19 -0400 Subject: [PATCH 3/3] State invariant 6's 2022-2035 scope in the property test docstring Review round 2 nit: 2021's American Rescue Plan Act rates also differ from the frozen snapshot, so "the first year the schedule departs" needs the range the assertions cover. Docstring only. Co-Authored-By: Claude Opus 5.5 --- .../gov/states/ky/tax/income/test_ky_cdcc_federal_match.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/policyengine_us/tests/policy/baseline/gov/states/ky/tax/income/test_ky_cdcc_federal_match.py b/policyengine_us/tests/policy/baseline/gov/states/ky/tax/income/test_ky_cdcc_federal_match.py index b7246e1a863..128bac253dd 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ky/tax/income/test_ky_cdcc_federal_match.py +++ b/policyengine_us/tests/policy/baseline/gov/states/ky/tax/income/test_ky_cdcc_federal_match.py @@ -21,9 +21,10 @@ 4. The federal potential credit equals a reference written from IRC 21(a)(2) (and, from 2026, the Act's amended schedule) times the relevant expenses. 5. 0 <= k <= K. -6. The Act's effective date that the pre-OBBBA mirrors key on (P.L. 119-21 - sec. 70405(b)) is the first year the baseline section 21 parameters depart - from the frozen pre-OBBBA schedule. +6. Over 2022 to 2035, the baseline section 21 parameters depart from the + frozen pre-OBBBA schedule in exactly the years from the Act's effective date + (P.L. 119-21 sec. 70405(b)) that the pre-OBBBA mirrors key on. 2021 is + excluded: its American Rescue Plan Act rates also differ from the snapshot. The conformity parameter as a reform lever (Kentucky reads P when it is false and the Act changes section 21) is covered in ky_cdcc.yaml, where a parameter