From 80c583a89a15fc8d41ad9e324f97a73143cf9bfa Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 2 Nov 2026 23:52:20 +0000 Subject: [PATCH 1/5] Stop Colorado CCAP reading parameters before 2015 CCAP reads its parameters at the October 1 before each month, so January to September 2015 read them at 2014-10-01. Parameters are backdated only to 2015-01-01, so the CCAP parameters had no value there and a 2015 Colorado household raised ParameterNotFoundError whenever itemization branching reached the CDCC and child care subsidies. A shared helper now reads those months at the backdating floor instead, adding no earlier parameter value. The regression case sets the branching flag itself, so it fails without the fix even though CI's update_itemization.sh turns branching off. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01LwQq6FjgHJQCKydAZomnYR --- changelog.d/co-early-year-guards.fixed.md | 1 + .../co/ccap/co_ccap_child_eligible.yaml | 11 ++++++++++ .../gov/states/co/ccap/co_ccap_smi.yaml | 14 +++++++++++++ .../co/ccap/entry/co_ccap_fpg_eligible.yaml | 13 ++++++++++++ ...ome_tax_before_non_refundable_credits.yaml | 16 +++++++++++++++ .../co/ccap/co_ccap_add_on_parent_fee.py | 9 ++++----- .../states/co/ccap/co_ccap_base_parent_fee.py | 9 ++++----- .../states/co/ccap/co_ccap_child_eligible.py | 9 ++++----- .../co/ccap/co_ccap_parameter_instant.py | 20 +++++++++++++++++++ .../gov/states/co/ccap/co_ccap_parent_fee.py | 9 ++++----- .../gov/states/co/ccap/co_ccap_smi.py | 10 ++++------ .../co/ccap/entry/co_ccap_fpg_eligible.py | 9 ++++----- .../co/ccap/entry/co_ccap_smi_eligible.py | 9 ++++----- ...o_ccap_re_determination_income_eligible.py | 9 ++++----- 14 files changed, 107 insertions(+), 41 deletions(-) create mode 100644 changelog.d/co-early-year-guards.fixed.md create mode 100644 policyengine_us/variables/gov/states/co/ccap/co_ccap_parameter_instant.py diff --git a/changelog.d/co-early-year-guards.fixed.md b/changelog.d/co-early-year-guards.fixed.md new file mode 100644 index 00000000000..3da6a96f983 --- /dev/null +++ b/changelog.d/co-early-year-guards.fixed.md @@ -0,0 +1 @@ +Stop Colorado CCAP from reading parameters before 2015, which raised ParameterNotFoundError for January to September 2015 under itemization branching. diff --git a/policyengine_us/tests/policy/baseline/gov/states/co/ccap/co_ccap_child_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/co/ccap/co_ccap_child_eligible.yaml index f3a235d6053..28007833960 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/co/ccap/co_ccap_child_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/co/ccap/co_ccap_child_eligible.yaml @@ -41,3 +41,14 @@ output: co_ccap_child_eligible: 2022-12: false + +- name: Child eligibility in January 2015, before the first October read. + period: 2015 + input: + is_disabled: false + is_tax_unit_dependent: true + age: 12 + state_code: CO + output: + co_ccap_child_eligible: + 2015-01: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/co/ccap/co_ccap_smi.yaml b/policyengine_us/tests/policy/baseline/gov/states/co/ccap/co_ccap_smi.yaml index 6e858218787..0841f38395f 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/co/ccap/co_ccap_smi.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/co/ccap/co_ccap_smi.yaml @@ -69,3 +69,17 @@ output: co_ccap_smi: 2022-01: 1.35 * 106_120 / 12 + +# Before October 2015, the October before each month falls before the date +# parameters are backdated to, so the parameters are read at 2015-01-01. +# HHS's FY 2015 SMI for Colorado, effective 2014-10-01, still applies there. +- name: Household size 4, State CO, January and October 2015 + period: 2015 + input: + spm_unit_size: 4 + state_code_str: CO + output: + co_ccap_smi: + 2015-01: 85_182 / 12 + 2015-09: 85_182 / 12 + 2015-10: 85_915 / 12 diff --git a/policyengine_us/tests/policy/baseline/gov/states/co/ccap/entry/co_ccap_fpg_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/co/ccap/entry/co_ccap_fpg_eligible.yaml index eab6ece1bb6..4db517693fa 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/co/ccap/entry/co_ccap_fpg_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/co/ccap/entry/co_ccap_fpg_eligible.yaml @@ -37,3 +37,16 @@ spm_unit_fpg: [12, 12] output: co_ccap_fpg_eligible: [false, true] + +# Before October 2015, the parameters are read at 2015-01-01, the date they +# are backdated to, rather than the October before, where none exist. +- name: In January 2015, Adams County limit is 235% of FPL. + period: 2015-01 + input: + state_code_str: [CO, CO] + co_ccap_countable_income: [28.1, 28.3] + county_str: [ADAMS_COUNTY_CO, ADAMS_COUNTY_CO] + spm_unit_fpg: [144, 144] + output: + # 144 / 12 x 2.35 = 28.20. + co_ccap_fpg_eligible: [true, false] diff --git a/policyengine_us/tests/policy/baseline/gov/states/co/tax/income/co_income_tax_before_non_refundable_credits.yaml b/policyengine_us/tests/policy/baseline/gov/states/co/tax/income/co_income_tax_before_non_refundable_credits.yaml index c011646e435..5936f303f94 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/co/tax/income/co_income_tax_before_non_refundable_credits.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/co/tax/income/co_income_tax_before_non_refundable_credits.yaml @@ -55,3 +55,19 @@ co_taxable_income: 0 output: co_income_tax_before_non_refundable_credits: 0 + +# Under itemization branching, the federal tax computed for itemizing reaches +# the child and dependent care credit, child care expenses and Colorado CCAP. +# For January to September 2015, CCAP once read its parameters at +# 2014-10-01, before the date parameters are backdated to, and raised +# ParameterNotFoundError. The flag is set here so the case doesn't depend on +# the package default. +- name: 2015 single filer with no income, under itemization branching + period: 2015 + absolute_error_margin: 0 + input: + gov.simulation.branch_to_determine_itemization: true + state_code: CO + filing_status: SINGLE + output: + co_income_tax_before_non_refundable_credits: 0 diff --git a/policyengine_us/variables/gov/states/co/ccap/co_ccap_add_on_parent_fee.py b/policyengine_us/variables/gov/states/co/ccap/co_ccap_add_on_parent_fee.py index 61bd44815bc..e6382e0de6e 100644 --- a/policyengine_us/variables/gov/states/co/ccap/co_ccap_add_on_parent_fee.py +++ b/policyengine_us/variables/gov/states/co/ccap/co_ccap_add_on_parent_fee.py @@ -1,4 +1,7 @@ from policyengine_us.model_api import * +from policyengine_us.variables.gov.states.co.ccap.co_ccap_parameter_instant import ( + co_ccap_parameter_instant, +) class co_ccap_add_on_parent_fee(Variable): @@ -13,11 +16,7 @@ class co_ccap_add_on_parent_fee(Variable): definition_period = MONTH def formula(spm_unit, period, parameters): - year = period.start.year - if period.start.month >= 10: - instant_str = f"{year}-10-01" - else: - instant_str = f"{year - 1}-10-01" + instant_str = co_ccap_parameter_instant(period) p = parameters(instant_str).gov.states.co.ccap # Calculate base parent fee and add on parent fee. gross_income = spm_unit("co_ccap_countable_income", period) diff --git a/policyengine_us/variables/gov/states/co/ccap/co_ccap_base_parent_fee.py b/policyengine_us/variables/gov/states/co/ccap/co_ccap_base_parent_fee.py index 9393506cf4a..a8e2a3163c5 100644 --- a/policyengine_us/variables/gov/states/co/ccap/co_ccap_base_parent_fee.py +++ b/policyengine_us/variables/gov/states/co/ccap/co_ccap_base_parent_fee.py @@ -1,4 +1,7 @@ from policyengine_us.model_api import * +from policyengine_us.variables.gov.states.co.ccap.co_ccap_parameter_instant import ( + co_ccap_parameter_instant, +) class co_ccap_base_parent_fee(Variable): @@ -13,11 +16,7 @@ class co_ccap_base_parent_fee(Variable): definition_period = MONTH def formula(spm_unit, period, parameters): - year = period.start.year - if period.start.month >= 10: - instant_str = f"{year}-10-01" - else: - instant_str = f"{year - 1}-10-01" + instant_str = co_ccap_parameter_instant(period) p = parameters(instant_str).gov.states.co.ccap # Calculate base parent fee and add on parent fee. gross_income = spm_unit("co_ccap_countable_income", period) diff --git a/policyengine_us/variables/gov/states/co/ccap/co_ccap_child_eligible.py b/policyengine_us/variables/gov/states/co/ccap/co_ccap_child_eligible.py index 298f7fcfb4b..32b1810ad0c 100644 --- a/policyengine_us/variables/gov/states/co/ccap/co_ccap_child_eligible.py +++ b/policyengine_us/variables/gov/states/co/ccap/co_ccap_child_eligible.py @@ -1,4 +1,7 @@ from policyengine_us.model_api import * +from policyengine_us.variables.gov.states.co.ccap.co_ccap_parameter_instant import ( + co_ccap_parameter_instant, +) class co_ccap_child_eligible(Variable): @@ -14,11 +17,7 @@ class co_ccap_child_eligible(Variable): defined_for = StateCode.CO def formula(person, period, parameters): - year = period.start.year - if period.start.month >= 10: - instant_str = f"{year}-10-01" - else: - instant_str = f"{year - 1}-10-01" + instant_str = co_ccap_parameter_instant(period) p = parameters(instant_str).gov.states.co.ccap # Section 3.105.1(F) (now 3.111(F)) extends the under-19 limit to # children under court supervision; the required documentation of care diff --git a/policyengine_us/variables/gov/states/co/ccap/co_ccap_parameter_instant.py b/policyengine_us/variables/gov/states/co/ccap/co_ccap_parameter_instant.py new file mode 100644 index 00000000000..4c93362f8fa --- /dev/null +++ b/policyengine_us/variables/gov/states/co/ccap/co_ccap_parameter_instant.py @@ -0,0 +1,20 @@ +from policyengine_us.tools.parameters import FIRST_MODELED_YEAR + + +def co_ccap_parameter_instant(period) -> str: + """The instant at which Colorado CCAP reads its parameters for a month. + + CCAP sets its limits each October, so a month from January to September + uses the limits that took effect the previous October 1. Before October + of the first modeled year, that October falls before the date to which + CountryTaxBenefitSystem backdates parameters, where the CCAP parameters + have no value. Those months read the parameters at the start of the + first modeled year instead: the same backdated values the model applies + from that October, with no value added before it. + """ + year = period.start.year + if period.start.month >= 10: + return f"{year}-10-01" + if year - 1 < FIRST_MODELED_YEAR: + return f"{FIRST_MODELED_YEAR}-01-01" + return f"{year - 1}-10-01" diff --git a/policyengine_us/variables/gov/states/co/ccap/co_ccap_parent_fee.py b/policyengine_us/variables/gov/states/co/ccap/co_ccap_parent_fee.py index 8983609a245..1aea57f8d1e 100644 --- a/policyengine_us/variables/gov/states/co/ccap/co_ccap_parent_fee.py +++ b/policyengine_us/variables/gov/states/co/ccap/co_ccap_parent_fee.py @@ -1,4 +1,7 @@ from policyengine_us.model_api import * +from policyengine_us.variables.gov.states.co.ccap.co_ccap_parameter_instant import ( + co_ccap_parameter_instant, +) class co_ccap_parent_fee(Variable): @@ -13,11 +16,7 @@ class co_ccap_parent_fee(Variable): definition_period = MONTH def formula(spm_unit, period, parameters): - year = period.start.year - if period.start.month >= 10: - instant_str = f"{year}-10-01" - else: - instant_str = f"{year - 1}-10-01" + instant_str = co_ccap_parameter_instant(period) p = parameters(instant_str).gov.states.co.ccap eligible_children = spm_unit("co_ccap_eligible_children", period) base_parent_fee = spm_unit("co_ccap_base_parent_fee", period) diff --git a/policyengine_us/variables/gov/states/co/ccap/co_ccap_smi.py b/policyengine_us/variables/gov/states/co/ccap/co_ccap_smi.py index 7f919461bd6..201151bc735 100644 --- a/policyengine_us/variables/gov/states/co/ccap/co_ccap_smi.py +++ b/policyengine_us/variables/gov/states/co/ccap/co_ccap_smi.py @@ -1,4 +1,7 @@ from policyengine_us.model_api import * +from policyengine_us.variables.gov.states.co.ccap.co_ccap_parameter_instant import ( + co_ccap_parameter_instant, +) from policyengine_us.variables.gov.hhs.hhs_smi import smi @@ -13,10 +16,5 @@ class co_ccap_smi(Variable): def formula(spm_unit, period, parameters): size = spm_unit("spm_unit_size", period.this_year) state_code = spm_unit.household("state_code_str", period.this_year) - year = period.start.year - month = period.start.month - if month >= 10: - instant_str = f"{year}-10-01" - else: - instant_str = f"{year - 1}-10-01" + instant_str = co_ccap_parameter_instant(period) return smi(size, state_code, instant_str, parameters) / MONTHS_IN_YEAR diff --git a/policyengine_us/variables/gov/states/co/ccap/entry/co_ccap_fpg_eligible.py b/policyengine_us/variables/gov/states/co/ccap/entry/co_ccap_fpg_eligible.py index f75c0ea4b1d..7aca7415357 100644 --- a/policyengine_us/variables/gov/states/co/ccap/entry/co_ccap_fpg_eligible.py +++ b/policyengine_us/variables/gov/states/co/ccap/entry/co_ccap_fpg_eligible.py @@ -1,4 +1,7 @@ from policyengine_us.model_api import * +from policyengine_us.variables.gov.states.co.ccap.co_ccap_parameter_instant import ( + co_ccap_parameter_instant, +) class co_ccap_fpg_eligible(Variable): @@ -16,11 +19,7 @@ def formula(spm_unit, period, parameters): spm_unit("co_ccap_countable_income", period), 2, ) - year = period.start.year - if period.start.month >= 10: - instant_str = f"{year}-10-01" - else: - instant_str = f"{year - 1}-10-01" + instant_str = co_ccap_parameter_instant(period) p = parameters(instant_str).gov.states.co.ccap # Calculate monthly fpg limit, only for counties in Colorado. county = household("county_str", period.this_year) diff --git a/policyengine_us/variables/gov/states/co/ccap/entry/co_ccap_smi_eligible.py b/policyengine_us/variables/gov/states/co/ccap/entry/co_ccap_smi_eligible.py index ceb92ea8656..6c3cbea2d7e 100644 --- a/policyengine_us/variables/gov/states/co/ccap/entry/co_ccap_smi_eligible.py +++ b/policyengine_us/variables/gov/states/co/ccap/entry/co_ccap_smi_eligible.py @@ -1,4 +1,7 @@ from policyengine_us.model_api import * +from policyengine_us.variables.gov.states.co.ccap.co_ccap_parameter_instant import ( + co_ccap_parameter_instant, +) class co_ccap_smi_eligible(Variable): @@ -14,11 +17,7 @@ def formula(spm_unit, period, parameters): spm_unit("co_ccap_countable_income", period), 2, ) - year = period.start.year - if period.start.month >= 10: - instant_str = f"{year}-10-01" - else: - instant_str = f"{year - 1}-10-01" + instant_str = co_ccap_parameter_instant(period) p = parameters(instant_str).gov.states.co.ccap # Calculate monthly smi limit smi = spm_unit("co_ccap_smi", period) diff --git a/policyengine_us/variables/gov/states/co/ccap/re_determination/co_ccap_re_determination_income_eligible.py b/policyengine_us/variables/gov/states/co/ccap/re_determination/co_ccap_re_determination_income_eligible.py index c2260252a1e..5af7a245b96 100644 --- a/policyengine_us/variables/gov/states/co/ccap/re_determination/co_ccap_re_determination_income_eligible.py +++ b/policyengine_us/variables/gov/states/co/ccap/re_determination/co_ccap_re_determination_income_eligible.py @@ -1,4 +1,7 @@ from policyengine_us.model_api import * +from policyengine_us.variables.gov.states.co.ccap.co_ccap_parameter_instant import ( + co_ccap_parameter_instant, +) class co_ccap_re_determination_income_eligible(Variable): @@ -14,11 +17,7 @@ def formula(spm_unit, period, parameters): spm_unit("co_ccap_countable_income", period), 2, ) - year = period.start.year - if period.start.month >= 10: - instant_str = f"{year}-10-01" - else: - instant_str = f"{year - 1}-10-01" + instant_str = co_ccap_parameter_instant(period) p = parameters(instant_str).gov.states.co.ccap # Calculate monthly smi limit smi = spm_unit("co_ccap_smi", period) From 113ba72d3baeb46a19fbaa64cbda88bd6ac3c70d Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Mon, 2 Nov 2026 19:37:45 -0500 Subject: [PATCH 2/5] Measure the Colorado refund's age at the end of the prior year C.R.S. 39-22-2003(1)(a)(II) requires age 18 "as of December 31 of the taxable year preceding such taxable year", and the 2015 Form 104 says "born before 1997". The formula compared the year's age with 18, so a filer who turned 18 during the year qualified. The eligibility test now reads birth_year, and the case at age 18 now expects false. Co-Authored-By: Claude Opus 5.5 --- changelog.d/co-early-year-guards.fixed.md | 2 +- .../co_sales_tax_refund_person_eligible.yaml | 66 ++++++++++++++++++- .../co_sales_tax_refund_person_eligible.py | 14 ++-- 3 files changed, 74 insertions(+), 8 deletions(-) diff --git a/changelog.d/co-early-year-guards.fixed.md b/changelog.d/co-early-year-guards.fixed.md index 3da6a96f983..2e19b26c90f 100644 --- a/changelog.d/co-early-year-guards.fixed.md +++ b/changelog.d/co-early-year-guards.fixed.md @@ -1 +1 @@ -Stop Colorado CCAP from reading parameters before 2015, which raised ParameterNotFoundError for January to September 2015 under itemization branching. +Stop Colorado CCAP from reading parameters before 2015, which raised ParameterNotFoundError for January to September 2015 under itemization branching. Measure the Colorado sales tax refund's age test as of December 31 of the preceding year, as C.R.S. 39-22-2003(1)(a)(II) says. diff --git a/policyengine_us/tests/policy/baseline/gov/states/co/tax/income/credits/sales_tax_refund/co_sales_tax_refund_person_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/co/tax/income/credits/sales_tax_refund/co_sales_tax_refund_person_eligible.yaml index 5d2324ed768..ce0049fb4f6 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/co/tax/income/credits/sales_tax_refund/co_sales_tax_refund_person_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/co/tax/income/credits/sales_tax_refund/co_sales_tax_refund_person_eligible.yaml @@ -128,9 +128,10 @@ output: co_sales_tax_refund_person_eligible: [true, true] -# Age boundary: a filer exactly at the age threshold (18) qualifies via -# C.R.S. 39-22-2003(1)(a)(II). -- name: Head exactly age 18 -> eligible +# Age boundary: C.R.S. 39-22-2003(1)(a)(II) requires age 18 as of December 31 +# of the preceding taxable year. Born in 2004, this filer reaches 18 in 2022, the +# taxable year, and was 17 on December 31, 2021. +- name: Head turning 18 during the year -> ineligible period: 2022 input: people: @@ -146,6 +147,65 @@ household: members: [head] state_code: CO + output: + co_sales_tax_refund_person_eligible: false + +# Born in 2003, this filer was 18 on December 31, 2021. +- name: Head 18 at the end of the preceding year -> eligible + period: 2022 + input: + people: + head: + age: 19 + is_tax_unit_head: true + irs_employment_income: 0 + tax_units: + tax_unit: + members: [head] + co_income_tax_before_non_refundable_credits: 0 + households: + household: + members: [head] + state_code: CO + output: + co_sales_tax_refund_person_eligible: true + +# The 2015 Form 104 line 46 test: "born before 1997". +- name: 2015 head born in 1997 -> ineligible + period: 2015 + input: + people: + head: + age: 18 + is_tax_unit_head: true + irs_employment_income: 0 + tax_units: + tax_unit: + members: [head] + co_income_tax_before_non_refundable_credits: 0 + households: + household: + members: [head] + state_code: CO + output: + co_sales_tax_refund_person_eligible: false + +- name: 2015 head born in 1996 -> eligible + period: 2015 + input: + people: + head: + age: 19 + is_tax_unit_head: true + irs_employment_income: 0 + tax_units: + tax_unit: + members: [head] + co_income_tax_before_non_refundable_credits: 0 + households: + household: + members: [head] + state_code: CO output: co_sales_tax_refund_person_eligible: true diff --git a/policyengine_us/variables/gov/states/co/tax/income/credits/sales_tax_refund/co_sales_tax_refund_person_eligible.py b/policyengine_us/variables/gov/states/co/tax/income/credits/sales_tax_refund/co_sales_tax_refund_person_eligible.py index c61bd70056f..51e154ac63a 100644 --- a/policyengine_us/variables/gov/states/co/tax/income/credits/sales_tax_refund/co_sales_tax_refund_person_eligible.py +++ b/policyengine_us/variables/gov/states/co/tax/income/credits/sales_tax_refund/co_sales_tax_refund_person_eligible.py @@ -9,8 +9,10 @@ class co_sales_tax_refund_person_eligible(Variable): reference = ( # C.R.S. 39-22-2003(1)(a) defines a "qualified individual" via a # disjunctive test: (I) has CO income tax liability or files to claim a - # refund of withheld wages, OR (II) is at least 18 years of age. + # refund of withheld wages, OR (II) is at least 18 years of age as of + # December 31 of the preceding taxable year. "https://leg.colorado.gov/sites/default/files/images/olls/crs2023-title-39.pdf", + "https://colorado.public.law/statutes/crs_39-22-2003", "https://tax.colorado.gov/sites/tax/files/documents/DR_104_Book_2022.pdf#page=23", ) defined_for = StateCode.CO @@ -21,9 +23,13 @@ def formula(person, period, parameters): is_filer = person("is_tax_unit_head", period) | person( "is_tax_unit_spouse", period ) - # The statute measures age as of December 31 of the year preceding the - # taxable year; the model approximates this with current-year age. - age_eligible = person("age", period) >= p.age_threshold + # C.R.S. 39-22-2003(1)(a)(II) measures age "as of December 31 of the + # taxable year preceding such taxable year", so a filer who turns 18 + # during the year doesn't qualify on age. The 2015 Form 104 states the + # same test as "born before 1997". + age_eligible = ( + person("birth_year", period) < period.start.year - p.age_threshold + ) # Filers that had Colorado tax withheld are also eligible; use employment # income as a proxy. employment_income_eligible = person("irs_employment_income", period) > 0 From 17179a9aeb6f50aa52d54c108ba70c0a1f13228d Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Mon, 2 Nov 2026 19:38:28 -0500 Subject: [PATCH 3/5] Move the tax-unit refund cases to the prior-year age test Age 19 now holds the boundary these cases meant to test, and a new case pins a filer who turns 18 during the year. Co-Authored-By: Claude Opus 5.5 --- .../co_sales_tax_refund_eligible.yaml | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/policyengine_us/tests/policy/baseline/gov/states/co/tax/income/credits/sales_tax_refund/co_sales_tax_refund_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/co/tax/income/credits/sales_tax_refund/co_sales_tax_refund_eligible.yaml index 86aaad16059..928d4d7cfad 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/co/tax/income/credits/sales_tax_refund/co_sales_tax_refund_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/co/tax/income/credits/sales_tax_refund/co_sales_tax_refund_eligible.yaml @@ -18,7 +18,7 @@ output: co_sales_tax_refund_eligible: false -- name: Age eligible +- name: Turns 18 during the year, not age eligible period: 2022 input: people: @@ -35,6 +35,26 @@ household: members: [head] state_code: CO + output: + co_sales_tax_refund_eligible: false + +- name: Age eligible + period: 2022 + input: + people: + head: + age: 19 + is_tax_unit_head: true + irs_employment_income: 0 + tax_units: + tax_unit: + members: [head] + co_income_tax_before_non_refundable_credits: 0 + filing_status: SINGLE + households: + household: + members: [head] + state_code: CO output: co_sales_tax_refund_eligible: true @@ -87,11 +107,11 @@ input: people: head: - age: 18 + age: 19 is_tax_unit_head: true irs_employment_income: 0 spouse: - age: 18 + age: 19 is_tax_unit_spouse: true irs_employment_income: 0 tax_units: From 5f8b04879ed30c11d0598ee755d7855f17022813 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Mon, 2 Nov 2026 23:16:36 -0500 Subject: [PATCH 4/5] Test the 2015 Colorado CDCC path without itemization branching Main raised ParameterNotFoundError for 2015 Colorado income tax with branching off too, through co_cdcc, cdcc and child care expenses. Add the review's flag-off case, and correct the changelog, the test comment and the helper's docstring (SMI holds FY 2015 values in January to September 2015). Co-Authored-By: Claude Opus 5.5 --- changelog.d/co-early-year-guards.fixed.md | 2 +- ...co_income_tax_before_non_refundable_credits.yaml | 7 ++++--- .../states/co/tax/income/credits/cdcc/co_cdcc.yaml | 13 +++++++++++++ .../gov/states/co/ccap/co_ccap_parameter_instant.py | 6 ++++-- 4 files changed, 22 insertions(+), 6 deletions(-) diff --git a/changelog.d/co-early-year-guards.fixed.md b/changelog.d/co-early-year-guards.fixed.md index 2e19b26c90f..e26645c7c00 100644 --- a/changelog.d/co-early-year-guards.fixed.md +++ b/changelog.d/co-early-year-guards.fixed.md @@ -1 +1 @@ -Stop Colorado CCAP from reading parameters before 2015, which raised ParameterNotFoundError for January to September 2015 under itemization branching. Measure the Colorado sales tax refund's age test as of December 31 of the preceding year, as C.R.S. 39-22-2003(1)(a)(II) says. +Stop Colorado CCAP from reading parameters before 2015, which made every 2015 Colorado income tax calculation raise ParameterNotFoundError. Measure the Colorado sales tax refund's age test as of December 31 of the preceding year, per C.R.S. 39-22-2003(1)(a)(II). diff --git a/policyengine_us/tests/policy/baseline/gov/states/co/tax/income/co_income_tax_before_non_refundable_credits.yaml b/policyengine_us/tests/policy/baseline/gov/states/co/tax/income/co_income_tax_before_non_refundable_credits.yaml index 5936f303f94..e984ededfe1 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/co/tax/income/co_income_tax_before_non_refundable_credits.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/co/tax/income/co_income_tax_before_non_refundable_credits.yaml @@ -59,9 +59,10 @@ # Under itemization branching, the federal tax computed for itemizing reaches # the child and dependent care credit, child care expenses and Colorado CCAP. # For January to September 2015, CCAP once read its parameters at -# 2014-10-01, before the date parameters are backdated to, and raised -# ParameterNotFoundError. The flag is set here so the case doesn't depend on -# the package default. +# 2014-10-01, before the date to which the model backdates parameters, and +# raised ParameterNotFoundError. This case covers that itemization path and +# sets the flag so it doesn't depend on the package default. The Colorado +# CDCC reaches CCAP without branching too; co_cdcc.yaml covers that path. - name: 2015 single filer with no income, under itemization branching period: 2015 absolute_error_margin: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/co/tax/income/credits/cdcc/co_cdcc.yaml b/policyengine_us/tests/policy/baseline/gov/states/co/tax/income/credits/cdcc/co_cdcc.yaml index be550a08624..4c9eea9f8b7 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/co/tax/income/credits/cdcc/co_cdcc.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/co/tax/income/credits/cdcc/co_cdcc.yaml @@ -173,3 +173,16 @@ state_code: CO output: co_cdcc: 0 + +# Without itemization branching, co_cdcc reaches CCAP through the federal CDCC +# and child care expenses. For January to September 2015, CCAP once read its +# parameters at 2014-10-01 and raised ParameterNotFoundError. +- name: 2015 single filer with no income, without itemization branching + period: 2015 + absolute_error_margin: 0 + input: + gov.simulation.branch_to_determine_itemization: false + state_code: CO + filing_status: SINGLE + output: + co_cdcc: 0 diff --git a/policyengine_us/variables/gov/states/co/ccap/co_ccap_parameter_instant.py b/policyengine_us/variables/gov/states/co/ccap/co_ccap_parameter_instant.py index 4c93362f8fa..42c2f3cc959 100644 --- a/policyengine_us/variables/gov/states/co/ccap/co_ccap_parameter_instant.py +++ b/policyengine_us/variables/gov/states/co/ccap/co_ccap_parameter_instant.py @@ -9,8 +9,10 @@ def co_ccap_parameter_instant(period) -> str: of the first modeled year, that October falls before the date to which CountryTaxBenefitSystem backdates parameters, where the CCAP parameters have no value. Those months read the parameters at the start of the - first modeled year instead: the same backdated values the model applies - from that October, with no value added before it. + first modeled year instead. There the CCAP parameters hold their + backdated values, and `gov.hhs.smi` still holds HHS's values for the + fiscal year that began the previous October. The helper backdates + nothing further. """ year = period.start.year if period.start.month >= 10: From 4594c7b5cd3491735e756dde1d6f7d46aa1bb062 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Tue, 3 Nov 2026 01:09:02 -0500 Subject: [PATCH 5/5] Say when Colorado measures the refund's age The refund formula tests whether a filer was 18 by December 31 of the year before the tax year (C.R.S. 39-22-2003(1)(a)(II)), so we added that date to the threshold's description. The rest of the description comes from #10309, which landed first. Co-Authored-By: Claude Opus 5.5 --- .../co/tax/income/credits/sales_tax_refund/age_threshold.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/policyengine_us/parameters/gov/states/co/tax/income/credits/sales_tax_refund/age_threshold.yaml b/policyengine_us/parameters/gov/states/co/tax/income/credits/sales_tax_refund/age_threshold.yaml index de5407b2f2a..2cc7cb915c3 100644 --- a/policyengine_us/parameters/gov/states/co/tax/income/credits/sales_tax_refund/age_threshold.yaml +++ b/policyengine_us/parameters/gov/states/co/tax/income/credits/sales_tax_refund/age_threshold.yaml @@ -1,5 +1,6 @@ description: >- - Colorado limits its sales tax refund to filers this age or older. The refund is + Colorado limits its sales tax refund to filers this age or older as of December 31 of + the year before the tax year. The refund is attributed to the modeled eligibility tax year, even when the return and payment occur later. This is the residual sales tax refund mechanism, separate from Colorado Cash Back; in_effect controls whether the refund is available.