From 9d684112b9de150c522f47da33b3fb968434e1ec Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Tue, 20 Oct 2026 16:57:42 -0400 Subject: [PATCH] Decide Colorado Premium Assistance's ceiling on the exact FPL ratio Amended Regulation 4-2-78 Section 4.C defines an eligible enrollee by household income "no greater than 400% of the Federal Poverty Level". The gate compared the truncated aca_magi_fraction with 4.0, so every income from 400.00% to 400.99% passed. The federal PTC gate ends at 400% under current law, so the error showed only when a reform extends the federal credit; test the exact ratio of nonnegative ACA MAGI to the prior-year guideline anyway, so the state ceiling holds on its own. Tests that supplied aca_magi_fraction now supply aca_magi against a prior-year guideline of $10,000; new cases use the real 2025 guideline at the edge and a reform that extends the federal credit. Co-Authored-By: Claude Opus 5.5 --- ...remium-assistance-exact-fpl-ratio.fixed.md | 1 + .../co_premium_assistance.yaml | 101 +++++++--- .../co_premium_assistance_eligible.yaml | 172 ++++++++++++++++-- .../doi/premium_assistance/integration.yaml | 45 +++-- .../co_premium_assistance_eligible.py | 17 +- 5 files changed, 273 insertions(+), 63 deletions(-) create mode 100644 changelog.d/co-premium-assistance-exact-fpl-ratio.fixed.md diff --git a/changelog.d/co-premium-assistance-exact-fpl-ratio.fixed.md b/changelog.d/co-premium-assistance-exact-fpl-ratio.fixed.md new file mode 100644 index 00000000000..159dc1bc6d3 --- /dev/null +++ b/changelog.d/co-premium-assistance-exact-fpl-ratio.fixed.md @@ -0,0 +1 @@ +Decide Colorado Premium Assistance's 400% income ceiling on the exact ratio of ACA MAGI to the prior-year poverty guideline instead of the truncated `aca_magi_fraction` (Amended Regulation 4-2-78, 3 CCR 702-4, Section 4.C: household income "no greater than 400% of the Federal Poverty Level"). Under current law the federal premium tax credit gate already ends at 400%, so this changes results only when a reform extends the federal credit above 400%, where incomes from 400.003% to 400.994% were eligible. diff --git a/policyengine_us/tests/policy/baseline/gov/states/co/doi/premium_assistance/co_premium_assistance.yaml b/policyengine_us/tests/policy/baseline/gov/states/co/doi/premium_assistance/co_premium_assistance.yaml index ec7b5568aeb..48768abbbd0 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/co/doi/premium_assistance/co_premium_assistance.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/co/doi/premium_assistance/co_premium_assistance.yaml @@ -1,8 +1,9 @@ # Unit tests for the Colorado Premium Assistance amount. # -# All inputs (is_aca_ptc_eligible per person, aca_magi_fraction, slcsp as an -# annual value, aca_ptc) are supplied directly so every expected value is -# exactly hand-verifiable and independent of the rating-area premium lookup. +# All inputs (is_aca_ptc_eligible per person, aca_magi against a prior-year +# tax_unit_fpg pinned to $10,000, slcsp as an annual value, aca_ptc) are supplied +# directly so every expected value is exactly hand-verifiable and independent of +# the rating-area premium lookup. # slcsp is a MONTH-period variable; the amount formula annualizes it via # add(tax_unit, period, ["slcsp"]). Providing slcsp at the YEAR period sets the # annual total, so the values below are annual SLCSP. @@ -30,7 +31,9 @@ tax_units: tax_unit: members: [person1] - aca_magi_fraction: 2.50 + aca_magi: 25_000 + tax_unit_fpg: + 2025: 10_000 slcsp: 10_000 aca_ptc: 2_000 households: @@ -57,7 +60,9 @@ tax_units: tax_unit: members: [person1, person2] - aca_magi_fraction: 3.00 + aca_magi: 30_000 + tax_unit_fpg: + 2025: 10_000 slcsp: 12_000 aca_ptc: 2_000 households: @@ -94,7 +99,9 @@ tax_units: tax_unit: members: [person1, person2, person3, person4, person5] - aca_magi_fraction: 3.00 + aca_magi: 30_000 + tax_unit_fpg: + 2025: 10_000 slcsp: 20_000 aca_ptc: 3_000 households: @@ -140,7 +147,9 @@ tax_units: tax_unit: members: [person1, person2, person3, person4, person5, person6, person7] - aca_magi_fraction: 3.00 + aca_magi: 30_000 + tax_unit_fpg: + 2025: 10_000 slcsp: 25_000 aca_ptc: 4_000 households: @@ -164,7 +173,9 @@ tax_units: tax_unit: members: [person1] - aca_magi_fraction: 2.50 + aca_magi: 25_000 + tax_unit_fpg: + 2025: 10_000 slcsp: 10_000 aca_ptc: 9_500 households: @@ -188,7 +199,9 @@ tax_units: tax_unit: members: [person1] - aca_magi_fraction: 2.50 + aca_magi: 25_000 + tax_unit_fpg: + 2025: 10_000 slcsp: 8_000 aca_ptc: 8_000 households: @@ -200,7 +213,7 @@ co_premium_assistance: 0 - name: Case 7, ineligible unit (above 400% FPL) -> amount 0. - # aca_magi_fraction 4.50 > 4.0 -> co_premium_assistance_eligible false -> + # 45_000 / 10_000 = 4.50 > 4.0 -> co_premium_assistance_eligible false -> # where(eligible, annual, 0) returns 0. period: 2026 absolute_error_margin: 0.01 @@ -212,7 +225,9 @@ tax_units: tax_unit: members: [person1] - aca_magi_fraction: 4.50 + aca_magi: 45_000 + tax_unit_fpg: + 2025: 10_000 slcsp: 10_000 aca_ptc: 2_000 households: @@ -234,7 +249,9 @@ tax_units: tax_unit: members: [person1] - aca_magi_fraction: 2.50 + aca_magi: 25_000 + tax_unit_fpg: + 2025: 10_000 slcsp: 10_000 aca_ptc: 2_000 households: @@ -256,7 +273,9 @@ tax_units: tax_unit: members: [person1] - aca_magi_fraction: 2.50 + aca_magi: 25_000 + tax_unit_fpg: + 2024: 10_000 slcsp: 10_000 aca_ptc: 2_000 households: @@ -281,7 +300,9 @@ tax_units: tax_unit: members: [person1] - aca_magi_fraction: 2.50 + aca_magi: 25_000 + tax_unit_fpg: + 2025: 10_000 slcsp: 0 aca_ptc: 0 households: @@ -305,7 +326,9 @@ tax_units: tax_unit: members: [person1] - aca_magi_fraction: 2.50 + aca_magi: 25_000 + tax_unit_fpg: + 2025: 10_000 slcsp: 8_000 aca_ptc: 7_040 households: @@ -346,7 +369,9 @@ tax_units: tax_unit: members: [person1, person2, person3, person4, person5, person6] - aca_magi_fraction: 3.00 + aca_magi: 30_000 + tax_unit_fpg: + 2025: 10_000 slcsp: 25_000 aca_ptc: 4_000 households: @@ -371,7 +396,9 @@ tax_units: tax_unit: members: [person1] - aca_magi_fraction: 1.01 + aca_magi: 10_100 + tax_unit_fpg: + 2025: 10_000 slcsp: 10_000 aca_ptc: 2_000 households: @@ -407,7 +434,9 @@ tax_units: tax_unit: members: [person1, person2, person3] - aca_magi_fraction: 3.00 + aca_magi: 30_000 + tax_unit_fpg: + 2025: 10_000 slcsp: 14_000 aca_ptc: 3_000 households: @@ -439,7 +468,9 @@ tax_units: tax_unit: members: [person1, person2] - aca_magi_fraction: 3.00 + aca_magi: 30_000 + tax_unit_fpg: + 2026: 10_000 slcsp: 14_000 aca_ptc: 3_000 households: @@ -477,7 +508,9 @@ tax_units: tax_unit: members: [person1, person2, person3, person4, person5] - aca_magi_fraction: 3.00 + aca_magi: 30_000 + tax_unit_fpg: + 2026: 10_000 slcsp: 22_000 aca_ptc: 4_000 households: @@ -504,7 +537,9 @@ tax_units: tax_unit: members: [person1] - aca_magi_fraction: 2.50 + aca_magi: 25_000 + tax_unit_fpg: + 2025: 10_000 slcsp: 8_000 aca_ptc: 9_000 households: @@ -531,7 +566,9 @@ tax_units: tax_unit: members: [person1] - aca_magi_fraction: 0.99 + aca_magi: 9_900 + tax_unit_fpg: + 2025: 10_000 slcsp: 10_000 aca_ptc: 2_000 households: @@ -558,7 +595,9 @@ tax_units: tax_unit: members: [person1] - aca_magi_fraction: 0.99 + aca_magi: 9_900 + tax_unit_fpg: + 2025: 10_000 slcsp: 10_000 aca_ptc: 0 households: @@ -592,7 +631,9 @@ tax_units: tax_unit: members: [person1, person2, person3, person4] - aca_magi_fraction: 3.00 + aca_magi: 30_000 + tax_unit_fpg: + 2025: 10_000 slcsp: 18_000 aca_ptc: 3_000 households: @@ -617,7 +658,9 @@ tax_units: tax_unit: members: [person1] - aca_magi_fraction: 2.50 + aca_magi: 25_000 + tax_unit_fpg: + 2025: 10_000 slcsp: 10_000 aca_ptc: 0 households: @@ -642,7 +685,9 @@ tax_units: tax_unit: members: [person1] - aca_magi_fraction: 2.50 + aca_magi: 25_000 + tax_unit_fpg: + 2027: 10_000 slcsp: 10_000 aca_ptc: 2_000 households: @@ -669,7 +714,9 @@ tax_units: tax_unit: members: [person1] - aca_magi_fraction: 2.50 + aca_magi: 25_000 + tax_unit_fpg: + 2025: 10_000 slcsp: 10_000 aca_ptc: 2_000 takes_up_co_premium_assistance_if_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/co/doi/premium_assistance/co_premium_assistance_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/co/doi/premium_assistance/co_premium_assistance_eligible.yaml index d1d77641c84..2315db3deb6 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/co/doi/premium_assistance/co_premium_assistance_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/co/doi/premium_assistance/co_premium_assistance_eligible.yaml @@ -3,10 +3,14 @@ # SB26-178), the household is in Colorado, at least one member is eligible for # the federal ACA premium tax credit, and household ACA MAGI is at or below the # 400% FPL ceiling (upper = 4.0 as an FPL fraction). Regulation 4-2-78 Section -# 4.C sets a 400%-inclusive ceiling with NO lower bound, so there is no 100% FPL -# floor: a sub-100%-FPL unit with an is_aca_ptc_eligible member is eligible. -# is_aca_ptc_eligible and aca_magi_fraction are supplied directly so the gate -# logic is tested in isolation from the premium-data / FPL lookups. +# 4.C ("no greater than 400% of the Federal Poverty Level") sets a 400%-inclusive +# ceiling with NO lower bound, so there is no 100% FPL floor: a sub-100%-FPL unit +# with an is_aca_ptc_eligible member is eligible. The ceiling applies to the +# exact ratio of ACA MAGI to the prior-year guideline, not the truncated +# aca_magi_fraction. is_aca_ptc_eligible is supplied directly; supplied-income +# cases pin the prior-year guideline to $10,000 and set aca_magi to the target +# ratio, so the gate logic is tested in isolation from the premium-data / FPL +# lookups. Income-derived cases use the actual 2025 one-person guideline, $15,650. - name: Case 1, CO APTC-eligible unit at 250% FPL in 2026 is eligible. # in_effect true, one is_aca_ptc_eligible member, 1.0 <= 2.50 <= 4.0. @@ -19,7 +23,9 @@ tax_units: tax_unit: members: [person1] - aca_magi_fraction: 2.50 + aca_magi: 25_000 + tax_unit_fpg: + 2025: 10_000 households: household: members: [person1] @@ -42,7 +48,9 @@ tax_units: tax_unit: members: [person1] - aca_magi_fraction: 0.99 + aca_magi: 9_900 + tax_unit_fpg: + 2025: 10_000 households: household: members: [person1] @@ -62,7 +70,9 @@ tax_units: tax_unit: members: [person1] - aca_magi_fraction: 1.00 + aca_magi: 10_000 + tax_unit_fpg: + 2025: 10_000 households: household: members: [person1] @@ -80,7 +90,9 @@ tax_units: tax_unit: members: [person1] - aca_magi_fraction: 4.00 + aca_magi: 40_000 + tax_unit_fpg: + 2025: 10_000 households: household: members: [person1] @@ -99,7 +111,9 @@ tax_units: tax_unit: members: [person1] - aca_magi_fraction: 4.01 + aca_magi: 40_100 + tax_unit_fpg: + 2025: 10_000 households: household: members: [person1] @@ -118,7 +132,9 @@ tax_units: tax_unit: members: [person1] - aca_magi_fraction: 2.50 + aca_magi: 25_000 + tax_unit_fpg: + 2025: 10_000 households: household: members: [person1] @@ -140,7 +156,9 @@ tax_units: tax_unit: members: [person1, person2] - aca_magi_fraction: 3.00 + aca_magi: 30_000 + tax_unit_fpg: + 2025: 10_000 households: household: members: [person1, person2] @@ -158,7 +176,9 @@ tax_units: tax_unit: members: [person1] - aca_magi_fraction: 2.50 + aca_magi: 25_000 + tax_unit_fpg: + 2025: 10_000 households: household: members: [person1] @@ -177,7 +197,9 @@ tax_units: tax_unit: members: [person1] - aca_magi_fraction: 2.50 + aca_magi: 25_000 + tax_unit_fpg: + 2024: 10_000 households: household: members: [person1] @@ -196,7 +218,9 @@ tax_units: tax_unit: members: [person1] - aca_magi_fraction: 2.50 + aca_magi: 25_000 + tax_unit_fpg: + 2027: 10_000 households: household: members: [person1] @@ -215,7 +239,9 @@ tax_units: tax_unit: members: [person1] - aca_magi_fraction: 2.50 + aca_magi: 25_000 + tax_unit_fpg: + 2026: 10_000 households: household: members: [person1] @@ -236,7 +262,9 @@ tax_units: tax_unit: members: [person1] - aca_magi_fraction: 1.01 + aca_magi: 10_100 + tax_unit_fpg: + 2025: 10_000 households: household: members: [person1] @@ -257,7 +285,9 @@ tax_units: tax_unit: members: [person1] - aca_magi_fraction: 3.99 + aca_magi: 39_900 + tax_unit_fpg: + 2025: 10_000 households: household: members: [person1] @@ -280,10 +310,116 @@ tax_units: tax_unit: members: [person1] - aca_magi_fraction: 0.50 + aca_magi: 5_000 + tax_unit_fpg: + 2025: 10_000 households: household: members: [person1] state_code: CO output: co_premium_assistance_eligible: false + +- name: Case 13, $62,599 (399.994% of the 2025 guideline) is eligible. + period: 2026 + input: + people: + person1: + age: 40 + is_aca_ptc_eligible: true + tax_units: + tax_unit: + members: [person1] + aca_magi: 62_599 + households: + household: + members: [person1] + state_code: CO + output: + aca_magi_fraction: 3.99 + co_premium_assistance_eligible: true + +- name: Case 14, $62,600 (exactly 400%) is eligible. + period: 2026 + input: + people: + person1: + age: 40 + is_aca_ptc_eligible: true + tax_units: + tax_unit: + members: [person1] + aca_magi: 62_600 + households: + household: + members: [person1] + state_code: CO + output: + aca_magi_fraction: 4.00 + co_premium_assistance_eligible: true + +- name: Case 15, $62,600.47 (400.003%) is ineligible though truncated to 4.00. + period: 2026 + input: + people: + person1: + age: 40 + is_aca_ptc_eligible: true + tax_units: + tax_unit: + members: [person1] + aca_magi: 62_600.47 + households: + household: + members: [person1] + state_code: CO + output: + aca_magi_fraction: 4.00 + co_premium_assistance_eligible: false + +- name: Case 16, $62,755.56 (400.994%) is ineligible though truncated to 4.00. + period: 2026 + input: + people: + person1: + age: 40 + is_aca_ptc_eligible: true + tax_units: + tax_unit: + members: [person1] + aca_magi: 62_755.56 + households: + household: + members: [person1] + state_code: CO + output: + aca_magi_fraction: 4.00 + co_premium_assistance_eligible: false + +- name: Case 17, with the federal credit extended above 400%, 400.003% is still ineligible. + # A reform that keeps the premium tax credit above 400% FPL (the enhanced-credit + # extension) makes is_aca_ptc_eligible true at $62,600.47, so the Colorado + # ceiling alone decides. 400.003% is above "no greater than 400%". + period: 2026 + input: + gov.aca.ptc_income_eligibility[2].amount: true + people: + person1: + age: 40 + is_medicaid_eligible: false + is_chip_eligible: false + is_basic_health_program_eligible: false + is_aca_eshi_eligible: false + is_medicare_eligible: false + tax_units: + tax_unit: + members: [person1] + aca_magi: 62_600.47 + filing_status: SINGLE + households: + household: + members: [person1] + state_code: CO + output: + is_aca_ptc_eligible: [true] + co_premium_assistance_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/co/doi/premium_assistance/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/co/doi/premium_assistance/integration.yaml index 84e73a3ad56..800facce6cc 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/co/doi/premium_assistance/integration.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/co/doi/premium_assistance/integration.yaml @@ -7,8 +7,9 @@ # verified by SB26-178), unfunded thereafter. # # To keep expected values exactly hand-verifiable and independent of the -# rating-area premium lookup, is_aca_ptc_eligible (per person), aca_magi_fraction, -# slcsp (annual) and aca_ptc are supplied directly, and each scenario asserts the +# rating-area premium lookup, is_aca_ptc_eligible (per person), aca_magi against +# a prior-year tax_unit_fpg pinned to $10,000, slcsp (annual) and aca_ptc are +# supplied directly, and each scenario asserts the # intermediate eligibility flag so a reviewer can follow the arithmetic: # n = count of is_aca_ptc_eligible members # flat_monthly = (80 + 29*(n-1)) if n >= 1 else 0 @@ -29,7 +30,9 @@ tax_units: tax_unit: members: [person1] - aca_magi_fraction: 1.50 + aca_magi: 15_000 + tax_unit_fpg: + 2025: 10_000 slcsp: 9_000 aca_ptc: 2_400 households: @@ -60,7 +63,9 @@ tax_units: tax_unit: members: [person1, person2, person3] - aca_magi_fraction: 3.00 + aca_magi: 30_000 + tax_unit_fpg: + 2025: 10_000 slcsp: 14_000 aca_ptc: 4_000 households: @@ -103,7 +108,9 @@ tax_units: tax_unit: members: [person1, person2, person3, person4, person5, person6] - aca_magi_fraction: 4.00 + aca_magi: 40_000 + tax_unit_fpg: + 2025: 10_000 slcsp: 22_000 aca_ptc: 5_000 households: @@ -130,7 +137,9 @@ tax_units: tax_unit: members: [person1, person2] - aca_magi_fraction: 2.00 + aca_magi: 20_000 + tax_unit_fpg: + 2025: 10_000 slcsp: 11_000 aca_ptc: 10_200 households: @@ -154,7 +163,9 @@ tax_units: tax_unit: members: [person1] - aca_magi_fraction: 2.50 + aca_magi: 25_000 + tax_unit_fpg: + 2025: 10_000 slcsp: 7_500 aca_ptc: 7_500 households: @@ -179,7 +190,9 @@ tax_units: tax_unit: members: [person1] - aca_magi_fraction: 2.50 + aca_magi: 25_000 + tax_unit_fpg: + 2026: 10_000 slcsp: 9_000 aca_ptc: 2_000 households: @@ -203,7 +216,9 @@ tax_units: tax_unit: members: [person1] - aca_magi_fraction: 2.50 + aca_magi: 25_000 + tax_unit_fpg: + 2024: 10_000 slcsp: 9_000 aca_ptc: 2_000 households: @@ -291,7 +306,9 @@ tax_units: tax_unit: members: [person1, person2, person3, person4] - aca_magi_fraction: 2.00 + aca_magi: 20_000 + tax_unit_fpg: + 2025: 10_000 slcsp: 16_000 aca_ptc: 3_000 households: @@ -324,7 +341,9 @@ tax_units: tax_unit: members: [person1] - aca_magi_fraction: 2.50 + aca_magi: 25_000 + tax_unit_fpg: + 2025: 10_000 slcsp: 10_000 aca_ptc: 2_000 assigned_aca_ptc: 0 @@ -365,7 +384,9 @@ tax_units: tax_unit: members: [person1] - aca_magi_fraction: 2.50 + aca_magi: 25_000 + tax_unit_fpg: + 2025: 10_000 slcsp: 10_000 aca_ptc: 2_000 takes_up_co_premium_assistance_if_eligible: false diff --git a/policyengine_us/variables/gov/states/co/doi/premium_assistance/co_premium_assistance_eligible.py b/policyengine_us/variables/gov/states/co/doi/premium_assistance/co_premium_assistance_eligible.py index e3f7d852c39..7761733affa 100644 --- a/policyengine_us/variables/gov/states/co/doi/premium_assistance/co_premium_assistance_eligible.py +++ b/policyengine_us/variables/gov/states/co/doi/premium_assistance/co_premium_assistance_eligible.py @@ -11,8 +11,9 @@ class co_premium_assistance_eligible(Variable): # in effect, at least one member is eligible for the federal ACA premium tax # credit (which embeds on-Marketplace enrollment and the required- # contribution income test), and household income is at or below the 400% - # federal poverty line ceiling. Regulation 4-2-78 Section 4.C sets a 400%- - # inclusive ceiling with no explicit lower bound. + # federal poverty line ceiling, on the exact ratio of ACA MAGI to the + # prior-year guideline. Regulation 4-2-78 Section 4.C sets a 400%-inclusive + # ceiling with no explicit lower bound. reference = ( # Amended Regulation 4-2-78 (3 CCR 702-4), Section 5.B and the 400%- # inclusive income ceiling in Section 4.C. Adopted via the DOI notice @@ -34,8 +35,12 @@ def formula(tax_unit, period, parameters): # exclusion, immigration/TIN status, and the required-contribution # income test. aptc_eligible = tax_unit.any(tax_unit.members("is_aca_ptc_eligible", period)) - # Regulation 4-2-78 Section 4.C caps eligibility at 400% FPL inclusive - # and states no lower bound. - magi_frac = tax_unit("aca_magi_fraction", period) - income_eligible = magi_frac <= p.fpl_limit.upper + # Regulation 4-2-78 Section 4.C defines an eligible enrollee by + # household income "no greater than 400% of the Federal Poverty Level" + # and states no lower bound. Test the exact ratio, not the truncated + # aca_magi_fraction: truncation maps 400.00%-400.99% to 4.00, which + # would admit incomes above 400%. + magi = max_(tax_unit("aca_magi", period), 0) + exact_magi_frac = magi / tax_unit("tax_unit_fpg", period.last_year) + income_eligible = exact_magi_frac <= p.fpl_limit.upper return aptc_eligible & income_eligible