diff --git a/changelog.d/ct-liheap-wave2c.added.md b/changelog.d/ct-liheap-wave2c.added.md new file mode 100644 index 00000000000..978148d962a --- /dev/null +++ b/changelog.d/ct-liheap-wave2c.added.md @@ -0,0 +1 @@ +Add Connecticut Energy Assistance Program basic and rental heating assistance for fiscal years 2026 and 2027, including federal income protection, military pensions, Social Security net of Part B premiums and receipt-based benefits. diff --git a/policyengine_us/parameters/gov/states/ct/dss/ceap/eligibility/smi_rate.yaml b/policyengine_us/parameters/gov/states/ct/dss/ceap/eligibility/smi_rate.yaml new file mode 100644 index 00000000000..31a08a89f90 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ct/dss/ceap/eligibility/smi_rate.yaml @@ -0,0 +1,13 @@ +description: Connecticut limits household income to this share of state median income under the Connecticut Energy Assistance Program. +values: + 2025-10-01: 0.6 + +metadata: + unit: /1 + period: year + label: Connecticut CEAP state median income limit + reference: + - title: Connecticut FY2026 LIHEAP State Plan, Section 2.1 + href: https://liheapch.acf.gov/docs/2026/state-plans/CT_Plan_2026.pdf#page=9 + - title: Connecticut approved FY2027 LIHEAP Allocation Plan, Section IV.B + href: https://portal.ct.gov/dss/-/media/departments-and-agencies/dss/winter-heating-assistance/09012026/ffy-27-liheap-allocation-plan.pdf#page=7 diff --git a/policyengine_us/parameters/gov/states/ct/dss/ceap/income/earned_income_min_age.yaml b/policyengine_us/parameters/gov/states/ct/dss/ceap/income/earned_income_min_age.yaml new file mode 100644 index 00000000000..2013508846c --- /dev/null +++ b/policyengine_us/parameters/gov/states/ct/dss/ceap/income/earned_income_min_age.yaml @@ -0,0 +1,11 @@ +description: Connecticut counts earned income from household members this age or older under the Connecticut Energy Assistance Program. +values: + 2025-10-01: 18 + +metadata: + unit: year + period: year + label: Connecticut CEAP minimum age for earned income + reference: + - title: "Connecticut FY2026 LIHEAP State Plan, Section 1.8-1.9 #page 5-7" + href: https://liheapch.acf.gov/docs/2026/state-plans/CT_Plan_2026.pdf#page=5 diff --git a/policyengine_us/parameters/gov/states/ct/dss/ceap/income/sources/earned.yaml b/policyengine_us/parameters/gov/states/ct/dss/ceap/income/sources/earned.yaml new file mode 100644 index 00000000000..3017bd3887c --- /dev/null +++ b/policyengine_us/parameters/gov/states/ct/dss/ceap/income/sources/earned.yaml @@ -0,0 +1,20 @@ +description: Connecticut counts these earned income sources under the Connecticut Energy Assistance Program. +values: + 2025-10-01: + - employment_income + # Enter basic pay here or in employment_income, not both. + - military_basic_pay + - self_employment_income + - sstb_self_employment_income + - farm_operations_income + - partnership_s_corp_income + +metadata: + unit: list + period: year + label: Connecticut CEAP countable earned income sources + reference: + - title: "Connecticut FY2026 LIHEAP State Plan, Section 1.8-1.9 #page 5-7" + href: https://liheapch.acf.gov/docs/2026/state-plans/CT_Plan_2026.pdf#page=5 + - title: "Connecticut approved FY2027 LIHEAP Allocation Plan, Sections III-V #page 5-9" + href: https://portal.ct.gov/dss/-/media/departments-and-agencies/dss/winter-heating-assistance/09012026/ffy-27-liheap-allocation-plan.pdf#page=5 diff --git a/policyengine_us/parameters/gov/states/ct/dss/ceap/income/sources/unearned.yaml b/policyengine_us/parameters/gov/states/ct/dss/ceap/income/sources/unearned.yaml new file mode 100644 index 00000000000..7feb41aa506 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ct/dss/ceap/income/sources/unearned.yaml @@ -0,0 +1,39 @@ +description: Connecticut counts these unearned income sources under the Connecticut Energy Assistance Program. +values: + 2025-10-01: + # Social Security is counted separately after its Medicare deduction. + - total_unemployment_compensation + - strike_benefits + - pension_income + # Military retirement includes Survivor Benefit Plan annuities. + - military_retirement_income + - railroad_benefits + # Ongoing IRA/401k distributions are separate from pension_income. + # Include taxable and exempt account distributions once. + - retirement_distributions + - survivor_benefits + - workers_compensation + - disability_benefits + - rental_income + - farm_rent_income + - estate_income + - interest_income + - ordinary_dividend_income + - alimony_income + - child_support_received + - financial_assistance + - gambling_winnings + # The residual input for the plan's one-time lump sums, jury duty, legal + # settlements and insurance payments; it may hold other receipts. + - miscellaneous_income + - veterans_benefits + +metadata: + unit: list + period: year + label: Connecticut CEAP countable unearned income sources + reference: + - title: "Connecticut FY2026 LIHEAP State Plan, Section 1.8-1.9 #page 5-7" + href: https://liheapch.acf.gov/docs/2026/state-plans/CT_Plan_2026.pdf#page=5 + - title: "Connecticut approved FY2027 LIHEAP Allocation Plan, Sections III-V #page 5-9" + href: https://portal.ct.gov/dss/-/media/departments-and-agencies/dss/winter-heating-assistance/09012026/ffy-27-liheap-allocation-plan.pdf#page=5 diff --git a/policyengine_us/parameters/gov/states/ct/dss/ceap/payment/basic.yaml b/policyengine_us/parameters/gov/states/ct/dss/ceap/payment/basic.yaml new file mode 100644 index 00000000000..cac3356e5c0 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ct/dss/ceap/payment/basic.yaml @@ -0,0 +1,25 @@ +description: Connecticut provides this basic heating benefit by income level under the Connecticut Energy Assistance Program. +1: + 2025-10-01: 595 + 2026-10-01: 655 +2: + 2025-10-01: 445 + 2026-10-01: 505 +3: + 2025-10-01: 295 + 2026-10-01: 355 + +metadata: + unit: currency-USD + period: year + label: Connecticut CEAP basic heating benefit + propagate_metadata_to_children: true + breakdown: + - range(1, 4) + breakdown_labels: + - Benefit income level + reference: + - title: Connecticut FY2026 LIHEAP Benefit Matrix + href: https://liheapch.acf.gov/docs/2026/benefits-matricies/CT_BenefitMatrix_Heat-Crisis_2026.pdf + - title: "Connecticut approved FY2027 LIHEAP Allocation Plan, Sections VIII-IX #page 10-11" + href: https://portal.ct.gov/dss/-/media/departments-and-agencies/dss/winter-heating-assistance/09012026/ffy-27-liheap-allocation-plan.pdf#page=10 diff --git a/policyengine_us/parameters/gov/states/ct/dss/ceap/payment/fpg_year_lag.yaml b/policyengine_us/parameters/gov/states/ct/dss/ceap/payment/fpg_year_lag.yaml new file mode 100644 index 00000000000..393ae2f1120 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ct/dss/ceap/payment/fpg_year_lag.yaml @@ -0,0 +1,19 @@ +description: Connecticut uses federal poverty guidelines from this many years before the benefit fiscal year for payment bands and the federal income floor under the Connecticut Energy Assistance Program. +# The FY2026 matrix uses 2025 guidelines and FY2027 uses 2026 guidelines, +# matching HHS's mandatory fiscal-year timing for both bands and the floor. +values: + 2025-10-01: 1 + +metadata: + unit: year + period: year + label: Connecticut CEAP federal poverty guideline lag + reference: + - title: Connecticut FY2026 LIHEAP Benefit Matrix + href: https://liheapch.acf.gov/docs/2026/benefits-matricies/CT_BenefitMatrix_Heat-Crisis_2026.pdf + - title: "Connecticut approved FY2027 LIHEAP Allocation Plan, Sections VIII-IX #page 10-11" + href: https://portal.ct.gov/dss/-/media/departments-and-agencies/dss/winter-heating-assistance/09012026/ffy-27-liheap-allocation-plan.pdf#page=10 + - title: LIHEAP IM 2025-02, Attachment 2, poverty guidelines for mandatory use in FY26 + href: https://acf.gov/sites/default/files/documents/ocs/COMM_LIHEAP_IM2025-02_FPGSte-Table_Att2.pdf#page=1 + - title: LIHEAP IM 2026-01, poverty guidelines for optional use in FY26 and mandatory use in FY27 + href: https://acf.gov/ocs/policy-guidance/liheap-im2026-01-federal-poverty-guidelines-fpg-and-state-median-income-smi diff --git a/policyengine_us/parameters/gov/states/ct/dss/ceap/payment/income_level.yaml b/policyengine_us/parameters/gov/states/ct/dss/ceap/payment/income_level.yaml new file mode 100644 index 00000000000..de1c99f31e7 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ct/dss/ceap/payment/income_level.yaml @@ -0,0 +1,27 @@ +description: Connecticut assigns this benefit level by the ratio of countable income to federal poverty guidelines under the Connecticut Energy Assistance Program. +brackets: + - threshold: + 2025-10-01: -.inf + amount: + 2025-10-01: 1 + - threshold: + 2025-10-01: 1.25 + amount: + 2025-10-01: 2 + - threshold: + 2025-10-01: 2 + amount: + 2025-10-01: 3 + +metadata: + unit: /1 + period: year + label: Connecticut CEAP benefit income level + type: single_amount + threshold_unit: /1 + amount_unit: /1 + reference: + - title: Connecticut FY2026 LIHEAP Benefit Matrix + href: https://liheapch.acf.gov/docs/2026/benefits-matricies/CT_BenefitMatrix_Heat-Crisis_2026.pdf + - title: "Connecticut approved FY2027 LIHEAP Allocation Plan, Sections VIII-IX #page 10-11" + href: https://portal.ct.gov/dss/-/media/departments-and-agencies/dss/winter-heating-assistance/09012026/ffy-27-liheap-allocation-plan.pdf#page=10 diff --git a/policyengine_us/parameters/gov/states/ct/dss/ceap/payment/rental.yaml b/policyengine_us/parameters/gov/states/ct/dss/ceap/payment/rental.yaml new file mode 100644 index 00000000000..dc01df25d19 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ct/dss/ceap/payment/rental.yaml @@ -0,0 +1,25 @@ +description: Connecticut provides this rental heating benefit by income level under the Connecticut Energy Assistance Program. +1: + 2025-10-01: 125 + 2026-10-01: 140 +2: + 2025-10-01: 100 + 2026-10-01: 115 +3: + 2025-10-01: 75 + 2026-10-01: 90 + +metadata: + unit: currency-USD + period: year + label: Connecticut CEAP rental heating benefit + propagate_metadata_to_children: true + breakdown: + - range(1, 4) + breakdown_labels: + - Benefit income level + reference: + - title: Connecticut FY2026 LIHEAP Benefit Matrix + href: https://liheapch.acf.gov/docs/2026/benefits-matricies/CT_BenefitMatrix_Heat-Crisis_2026.pdf + - title: "Connecticut approved FY2027 LIHEAP Allocation Plan, Sections VIII-IX #page 10-11" + href: https://portal.ct.gov/dss/-/media/departments-and-agencies/dss/winter-heating-assistance/09012026/ffy-27-liheap-allocation-plan.pdf#page=10 diff --git a/policyengine_us/parameters/gov/states/ct/dss/ceap/payment/vulnerable/elderly_age.yaml b/policyengine_us/parameters/gov/states/ct/dss/ceap/payment/vulnerable/elderly_age.yaml new file mode 100644 index 00000000000..ebaa6a0df5e --- /dev/null +++ b/policyengine_us/parameters/gov/states/ct/dss/ceap/payment/vulnerable/elderly_age.yaml @@ -0,0 +1,13 @@ +description: Connecticut treats household members this age or older as vulnerable under the Connecticut Energy Assistance Program. +values: + 2025-10-01: 60 + +metadata: + unit: year + period: year + label: Connecticut CEAP elderly age threshold + reference: + - title: Connecticut FY2026 LIHEAP Benefit Matrix + href: https://liheapch.acf.gov/docs/2026/benefits-matricies/CT_BenefitMatrix_Heat-Crisis_2026.pdf + - title: "Connecticut approved FY2027 LIHEAP Allocation Plan, Sections VIII-IX #page 10-11" + href: https://portal.ct.gov/dss/-/media/departments-and-agencies/dss/winter-heating-assistance/09012026/ffy-27-liheap-allocation-plan.pdf#page=10 diff --git a/policyengine_us/parameters/gov/states/ct/dss/ceap/payment/vulnerable/supplement.yaml b/policyengine_us/parameters/gov/states/ct/dss/ceap/payment/vulnerable/supplement.yaml new file mode 100644 index 00000000000..24d1fb2e344 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ct/dss/ceap/payment/vulnerable/supplement.yaml @@ -0,0 +1,13 @@ +description: Connecticut adds this amount to basic heating assistance for households with a vulnerable member under the Connecticut Energy Assistance Program. +values: + 2025-10-01: 50 + +metadata: + unit: currency-USD + period: year + label: Connecticut CEAP vulnerable household supplement + reference: + - title: Connecticut FY2026 LIHEAP Benefit Matrix + href: https://liheapch.acf.gov/docs/2026/benefits-matricies/CT_BenefitMatrix_Heat-Crisis_2026.pdf + - title: "Connecticut approved FY2027 LIHEAP Allocation Plan, Sections VIII-IX #page 10-11" + href: https://portal.ct.gov/dss/-/media/departments-and-agencies/dss/winter-heating-assistance/09012026/ffy-27-liheap-allocation-plan.pdf#page=10 diff --git a/policyengine_us/parameters/gov/states/ct/dss/ceap/payment/vulnerable/young_child_age.yaml b/policyengine_us/parameters/gov/states/ct/dss/ceap/payment/vulnerable/young_child_age.yaml new file mode 100644 index 00000000000..49fc56177bd --- /dev/null +++ b/policyengine_us/parameters/gov/states/ct/dss/ceap/payment/vulnerable/young_child_age.yaml @@ -0,0 +1,13 @@ +description: Connecticut treats children below this age as vulnerable under the Connecticut Energy Assistance Program. +values: + 2025-10-01: 6 + +metadata: + unit: year + period: year + label: Connecticut CEAP young child age threshold + reference: + - title: Connecticut FY2026 LIHEAP Benefit Matrix + href: https://liheapch.acf.gov/docs/2026/benefits-matricies/CT_BenefitMatrix_Heat-Crisis_2026.pdf + - title: "Connecticut approved FY2027 LIHEAP Allocation Plan, Sections VIII-IX #page 10-11" + href: https://portal.ct.gov/dss/-/media/departments-and-agencies/dss/winter-heating-assistance/09012026/ffy-27-liheap-allocation-plan.pdf#page=10 diff --git a/policyengine_us/programs.yaml b/policyengine_us/programs.yaml index c181505c73b..362bdca4f4b 100644 --- a/policyengine_us/programs.yaml +++ b/policyengine_us/programs.yaml @@ -987,7 +987,7 @@ programs: category: Benefits agency: HHS status: partial - coverage: AK, AR, AL, AZ, CA, CO, DC, DE, GA, HI, Riverside County, MA, FL, IL, IA, IN, KS, KY, LA, MD, ME, MN, MO, MS, MT, NC, ND, NE, NH, NJ, NM, NV, NY, OH, OK, OR, PA, SC, SD, RI, TN, TX, UT, VA, VT, WA, WI, WY + coverage: AK, AR, AL, AZ, CA, CO, CT, DC, DE, GA, HI, Riverside County, MA, FL, IL, IA, IN, KS, KY, LA, MD, ME, MN, MO, MS, MT, NC, ND, NE, NH, NJ, NM, NV, NY, OH, OK, OR, PA, SC, SD, RI, TN, TX, UT, VA, VT, WA, WI, WY state_implementations: - state: AL status: partial @@ -1036,6 +1036,14 @@ programs: parameter_prefix: gov.states.co.cdhs.leap verified_years: "2026" notes: FY2026 regular heating assistance, including heat-in-rent costs, income contribution rates and the subsidized-housing deduction. Crisis, cooling, weatherization and equipment assistance are out of scope. + - state: CT + status: partial + name: Connecticut CEAP + full_name: Connecticut Energy Assistance Program + variable: ct_ceap + parameter_prefix: gov.states.ct.dss.ceap + verified_years: "2026-2027" + notes: FY2026-FY2027 basic and rental heating assistance. The SNAP nominal benefit, crisis, weatherization and equipment assistance are out of scope. - state: GA status: partial name: Georgia LIHEAP diff --git a/policyengine_us/tests/policy/baseline/gov/states/ct/dss/ceap/ct_ceap.yaml b/policyengine_us/tests/policy/baseline/gov/states/ct/dss/ceap/ct_ceap.yaml new file mode 100644 index 00000000000..eb13cb68b3b --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ct/dss/ceap/ct_ceap.yaml @@ -0,0 +1,2944 @@ +# Independent end-to-end source scenarios; no CEAP intermediates supplied as inputs. +# Sources: +# - https://liheapch.acf.gov/docs/2026/benefits-matricies/CT_BenefitMatrix_Heat-Crisis_2026.pdf +# PDF pages 5-7 +# - https://liheapch.acf.gov/docs/2026/state-plans/CT_Plan_2026.pdf#page=5 +# PDF pages 5-7,9-11,15 +# - https://portal.ct.gov/dss/-/media/departments-and-agencies/dss/winter-heating-assistance/09012026/ffy-27-liheap-allocation-plan.pdf#page=5 +# - https://www.law.cornell.edu/uscode/text/42/8624#b_2_B +# Published basic or rental amount; direct annual expense 1,000 exceeds schedule. +- name: Case 1, FY2026 level 1 direct heating grant. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + employment_income: 0 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap_countable_income: 0 + ct_ceap_household_size: 1 + ct_ceap_benefit_level: 1 + ct_ceap_eligible: true + ct_ceap: 595 + +# Published basic or rental amount; direct annual expense 1,000 exceeds schedule. +- name: Case 2, FY2026 level 1 rental grant. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + employment_income: 0 + spm_units: + spm_unit: + members: [person1] + heating_type: UNSPECIFIED + gas_expense: 0 + heat_expense_included_in_rent: true + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap_countable_income: 0 + ct_ceap_household_size: 1 + ct_ceap_benefit_level: 1 + ct_ceap_eligible: true + ct_ceap: 125 + +# Published basic or rental amount; direct annual expense 1,000 exceeds schedule. +- name: Case 3, FY2026 level 2 direct heating grant. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + employment_income: 20_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap_countable_income: 20_000 + ct_ceap_household_size: 1 + ct_ceap_benefit_level: 2 + ct_ceap_eligible: true + ct_ceap: 445 + +# Published basic or rental amount; direct annual expense 1,000 exceeds schedule. +- name: Case 4, FY2026 level 2 rental grant. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + employment_income: 20_000 + spm_units: + spm_unit: + members: [person1] + heating_type: UNSPECIFIED + gas_expense: 0 + heat_expense_included_in_rent: true + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap_countable_income: 20_000 + ct_ceap_household_size: 1 + ct_ceap_benefit_level: 2 + ct_ceap_eligible: true + ct_ceap: 100 + +# Published basic or rental amount; direct annual expense 1,000 exceeds schedule. +- name: Case 5, FY2026 level 3 direct heating grant. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + employment_income: 40_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap_countable_income: 40_000 + ct_ceap_household_size: 1 + ct_ceap_benefit_level: 3 + ct_ceap_eligible: true + ct_ceap: 295 + +# Published basic or rental amount; direct annual expense 1,000 exceeds schedule. +- name: Case 6, FY2026 level 3 rental grant. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + employment_income: 40_000 + spm_units: + spm_unit: + members: [person1] + heating_type: UNSPECIFIED + gas_expense: 0 + heat_expense_included_in_rent: true + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap_countable_income: 40_000 + ct_ceap_household_size: 1 + ct_ceap_benefit_level: 3 + ct_ceap_eligible: true + ct_ceap: 75 + +# Published basic or rental amount; direct annual expense 1,000 exceeds schedule. +- name: Case 7, FY2027 level 1 direct heating grant. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2027-01: false + ssi: + '2027': 0 + social_security: 0 + employment_income: 0 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2027': 0 + tanf: + '2027': 0 + ct_ssp: + '2027': 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap_countable_income: 0 + ct_ceap_household_size: 1 + ct_ceap_benefit_level: 1 + ct_ceap_eligible: true + ct_ceap: 655 + +# Published basic or rental amount; direct annual expense 1,000 exceeds schedule. +- name: Case 8, FY2027 level 1 rental grant. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2027-01: false + ssi: + '2027': 0 + social_security: 0 + employment_income: 0 + spm_units: + spm_unit: + members: [person1] + heating_type: UNSPECIFIED + gas_expense: 0 + heat_expense_included_in_rent: true + snap: + '2027': 0 + tanf: + '2027': 0 + ct_ssp: + '2027': 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap_countable_income: 0 + ct_ceap_household_size: 1 + ct_ceap_benefit_level: 1 + ct_ceap_eligible: true + ct_ceap: 140 + +# Published basic or rental amount; direct annual expense 1,000 exceeds schedule. +- name: Case 9, FY2027 level 2 direct heating grant. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2027-01: false + ssi: + '2027': 0 + social_security: 0 + employment_income: 20_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2027': 0 + tanf: + '2027': 0 + ct_ssp: + '2027': 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap_countable_income: 20_000 + ct_ceap_household_size: 1 + ct_ceap_benefit_level: 2 + ct_ceap_eligible: true + ct_ceap: 505 + +# Published basic or rental amount; direct annual expense 1,000 exceeds schedule. +- name: Case 10, FY2027 level 2 rental grant. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2027-01: false + ssi: + '2027': 0 + social_security: 0 + employment_income: 20_000 + spm_units: + spm_unit: + members: [person1] + heating_type: UNSPECIFIED + gas_expense: 0 + heat_expense_included_in_rent: true + snap: + '2027': 0 + tanf: + '2027': 0 + ct_ssp: + '2027': 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap_countable_income: 20_000 + ct_ceap_household_size: 1 + ct_ceap_benefit_level: 2 + ct_ceap_eligible: true + ct_ceap: 115 + +# Published basic or rental amount; direct annual expense 1,000 exceeds schedule. +- name: Case 11, FY2027 level 3 direct heating grant. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2027-01: false + ssi: + '2027': 0 + social_security: 0 + employment_income: 40_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2027': 0 + tanf: + '2027': 0 + ct_ssp: + '2027': 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap_countable_income: 40_000 + ct_ceap_household_size: 1 + ct_ceap_benefit_level: 3 + ct_ceap_eligible: true + ct_ceap: 355 + +# Published basic or rental amount; direct annual expense 1,000 exceeds schedule. +- name: Case 12, FY2027 level 3 rental grant. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2027-01: false + ssi: + '2027': 0 + social_security: 0 + employment_income: 40_000 + spm_units: + spm_unit: + members: [person1] + heating_type: UNSPECIFIED + gas_expense: 0 + heat_expense_included_in_rent: true + snap: + '2027': 0 + tanf: + '2027': 0 + ct_ssp: + '2027': 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap_countable_income: 40_000 + ct_ceap_household_size: 1 + ct_ceap_benefit_level: 3 + ct_ceap_eligible: true + ct_ceap: 90 + +# Age 60 meets elderly boundary; Level 1 basic plus 50. +- name: Case 13, FY2026 elderly member receives fifty dollar supplement. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 60 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap: 645 + +# Age 60 meets elderly boundary; Level 1 basic plus 50. +- name: Case 14, FY2027 elderly member receives fifty dollar supplement. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 60 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2027-01: false + ssi: + '2027': 0 + social_security: 0 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2027': 0 + tanf: + '2027': 0 + ct_ssp: + '2027': 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap: 705 + +# Vulnerability is a household condition, with one 50 dollar add-on. +- name: Case 15, age just below sixty is not elderly. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 59.99 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap: 595 + +# Vulnerability is a household condition, with one 50 dollar add-on. +- name: Case 16, disabled adult receives vulnerability supplement. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: true + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap: 645 + +# Vulnerability is a household condition, with one 50 dollar add-on. +- name: Case 17, child just below six receives vulnerability supplement. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + person2: + age: 5.99 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + spm_units: + spm_unit: + members: [person1, person2] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1, person2] + state_code: CT + output: + ct_ceap: 645 + +# Vulnerability is a household condition, with one 50 dollar add-on. +- name: Case 18, child at six no longer supplies young child supplement. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + person2: + age: 6 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + spm_units: + spm_unit: + members: [person1, person2] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1, person2] + state_code: CT + output: + ct_ceap: 595 + +# Vulnerability is a household condition, with one 50 dollar add-on. +- name: Case 19, multiple vulnerable members receive one supplement. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 65 + immigration_status: CITIZEN + is_disabled: true + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + person2: + age: 5 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + spm_units: + spm_unit: + members: [person1, person2] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1, person2] + state_code: CT + output: + ct_ceap: 645 + +# Rental Level 1 is 125, no 50 dollar supplement and no exclusion based only on housing assistance. +- name: Case 20, vulnerable subsidized rental household receives rental amount only. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 65 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + spm_units: + spm_unit: + members: [person1] + heating_type: UNSPECIFIED + gas_expense: 0 + heat_expense_included_in_rent: true + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + receives_housing_assistance: true + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap: 125 + +# Retained direct award = smaller of regular schedule and nonnegative primary-fuel cost. +- name: Case 21, gas bill below schedule caps retained grant. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 100 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap: 100 + +# Retained direct award = smaller of regular schedule and nonnegative primary-fuel cost. +- name: Case 22, gas bill exactly at schedule pays full amount. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 595 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap: 595 + +# Retained direct award = smaller of regular schedule and nonnegative primary-fuel cost. +- name: Case 23, gas bill above schedule does not increase grant. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 596 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap: 595 + +# Retained direct award = smaller of regular schedule and nonnegative primary-fuel cost. +- name: Case 24, fuel oil selects oil expense not larger gas bill. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + spm_units: + spm_unit: + members: [person1] + heating_type: FUEL_OIL + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + fuel_oil_expense: 100 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap: 100 + +# Retained direct award = smaller of regular schedule and nonnegative primary-fuel cost. +- name: Case 25, electric heating uses pre subsidy electricity expense. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + spm_units: + spm_unit: + members: [person1] + heating_type: ELECTRICITY + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + pre_subsidy_electricity_expense: 200 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap: 200 + +# Retained direct award = smaller of regular schedule and nonnegative primary-fuel cost. +- name: Case 26, wood heating uses wood expense. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + spm_units: + spm_unit: + members: [person1] + heating_type: WOOD + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + wood_expense: 300 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap: 300 + +# Retained direct award = smaller of regular schedule and nonnegative primary-fuel cost. +- name: Case 27, no direct heating expense yields no benefit. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 0 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap: 0 + +# Positive receipt represents application receipt; above-limit income still sets Level 3, with vulnerability where applicable. +- name: Case 28, snap receipt bypasses income ceiling but retains level three. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + employment_income: 100_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2026': 120 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap_countable_income: 100_000 + ct_ceap_categorically_eligible: true + ct_ceap_benefit_level: 3 + ct_ceap: 295 + +# Rental aid keeps the 60% SMI ceiling; separate 20.01 SNAP nominal payment is outside scope. +- name: Case 29, snap does not bypass rental income ceiling. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + employment_income: 100_000 + spm_units: + spm_unit: + members: [person1] + heating_type: UNSPECIFIED + gas_expense: 0 + heat_expense_included_in_rent: true + snap: + '2026': 120 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap_categorically_eligible: false + ct_ceap_eligible: false + ct_ceap: 0 + +# Positive receipt represents application receipt; above-limit income still sets Level 3, with vulnerability where applicable. +- name: Case 30, TFA receipt bypasses income ceiling but retains level three. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + employment_income: 100_000 + person2: + age: 10 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + spm_units: + spm_unit: + members: [person1, person2] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 120 + ct_ssp: + '2026': 0 + households: + household: + members: [person1, person2] + state_code: CT + output: + ct_ceap_countable_income: 100_000 + ct_ceap_categorically_eligible: true + ct_ceap_benefit_level: 3 + ct_ceap: 295 + +# Rental aid keeps the 60% SMI ceiling; separate 20.01 SNAP nominal payment is outside scope. +- name: Case 31, TFA does not bypass rental income ceiling. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + employment_income: 100_000 + person2: + age: 10 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + spm_units: + spm_unit: + members: [person1, person2] + heating_type: UNSPECIFIED + gas_expense: 0 + heat_expense_included_in_rent: true + snap: + '2026': 0 + tanf: + '2026': 120 + ct_ssp: + '2026': 0 + households: + household: + members: [person1, person2] + state_code: CT + output: + ct_ceap_categorically_eligible: false + ct_ceap_eligible: false + ct_ceap: 0 + +# Positive receipt represents application receipt; above-limit income still sets Level 3, with vulnerability where applicable. +- name: Case 32, ssi receipt bypasses income ceiling but retains level three. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: true + is_in_foster_care: + 2026-01: false + ssi: + '2026': 120 + social_security: 0 + employment_income: 100_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap_countable_income: 100_000 + ct_ceap_categorically_eligible: true + ct_ceap_benefit_level: 3 + ct_ceap: 345 + +# Rental aid keeps the 60% SMI ceiling; separate 20.01 SNAP nominal payment is outside scope. +- name: Case 33, ssi does not bypass rental income ceiling. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: true + is_in_foster_care: + 2026-01: false + ssi: + '2026': 120 + social_security: 0 + employment_income: 100_000 + spm_units: + spm_unit: + members: [person1] + heating_type: UNSPECIFIED + gas_expense: 0 + heat_expense_included_in_rent: true + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap_categorically_eligible: false + ct_ceap_eligible: false + ct_ceap: 0 + +# Positive receipt represents application receipt; above-limit income still sets Level 3, with vulnerability where applicable. +- name: Case 34, ct_ssp receipt bypasses income ceiling but retains level three. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 65 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + employment_income: 100_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 120 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap_countable_income: 100_000 + ct_ceap_categorically_eligible: true + ct_ceap_benefit_level: 3 + ct_ceap: 345 + +# Rental aid keeps the 60% SMI ceiling; separate 20.01 SNAP nominal payment is outside scope. +- name: Case 35, ct_ssp does not bypass rental income ceiling. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 65 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + employment_income: 100_000 + spm_units: + spm_unit: + members: [person1] + heating_type: UNSPECIFIED + gas_expense: 0 + heat_expense_included_in_rent: true + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 120 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap_categorically_eligible: false + ct_ceap_eligible: false + ct_ceap: 0 + +# Size 1, income 20,000 gives Level 2; qualified young child adds 50 to 445. +- name: Case 36, citizen child with nonqualified parent uses child size and all income. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: UNDOCUMENTED + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + employment_income: 20_000 + person2: + age: 5 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + spm_units: + spm_unit: + members: [person1, person2] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1, person2] + state_code: CT + output: + ct_ceap_countable_income: 20_000 + ct_ceap_household_size: 1 + ct_ceap_income_limit: 47_764 + ct_ceap_benefit_level: 2 + ct_ceap: 495 + +# Excluded elder is not a member for vulnerability. +- name: Case 37, nonqualified elder does not establish vulnerability. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + person2: + age: 65 + immigration_status: UNDOCUMENTED + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + spm_units: + spm_unit: + members: [person1, person2] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1, person2] + state_code: CT + output: + ct_ceap_household_size: 1 + ct_ceap: 595 + +# Removing foster child excludes 30,000 unearned income and young-child supplement; remaining adult gets Level 2 basic 445. +- name: Case 38, represented foster child excluded from income size and vulnerability. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + employment_income: 20_000 + person2: + age: 5 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: true + ssi: + '2026': 0 + social_security: 30_000 + spm_units: + spm_unit: + members: [person1, person2] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1, person2] + state_code: CT + output: + ct_ceap_countable_income: 20_000 + ct_ceap_household_size: 1 + ct_ceap_benefit_level: 2 + ct_ceap: 445 + +# Each SPM unit belongs to its own state household; all CT variables are state-guarded. +- name: Case 39, mixed state batch isolates Connecticut calculation. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + person2: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + person3: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + spm_units: + spm_unit1: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + spm_unit2: + members: [person2] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + spm_unit3: + members: [person3] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household1: + members: [person1] + state_code: CT + household2: + members: [person2] + state_code: MA + household3: + members: [person3] + state_code: NY + output: + ct_ceap_countable_income: [0, 0, 0] + ct_ceap_household_size: [1, 0, 0] + ct_ceap_income_limit: [47_764, 0, 0] + ct_ceap_categorically_eligible: [false, false, false] + ct_ceap_eligible: [true, false, false] + ct_ceap_benefit_level: [1, 0, 0] + ct_ceap: [595, 0, 0] + +# Represented foster members are outside the energy household. +# The adult has 100,000 countable income and no qualifying receipt of their own. +- name: Case 40, represented foster SSI does not establish categorical receipt. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + employment_income: 100_000 + social_security: 0 + ssi: + '2026': 0 + is_in_foster_care: + 2026-01: false + person2: + age: 5 + immigration_status: CITIZEN + is_disabled: true + social_security: 0 + ssi: + '2026': 120 + is_in_foster_care: + 2026-01: true + spm_units: + spm_unit: + members: [person1, person2] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1, person2] + state_code: CT + output: + ct_ceap_countable_income: 100_000 + ct_ceap_household_size: 1 + ct_ceap_categorically_eligible: false + ct_ceap_eligible: false + ct_ceap: 0 + +# Independent review C1/C3 examples: FY2026 matrix categorical footnote and +# allocation plan household exclusion, physical pages 5-7. All receipts computed. +# PDF pages 5-7 +# - https://www.cga.ct.gov/app/related/20250616_2025%20Block%20Grants%20and%20Waiver%20Applications/FFY%202026%20LIHEAP%20Allocation%20Plan.pdf#page=5 +# C1: 10 * 13,600 = 136,000 > floor(91,854 * 1.47) = 135,025; +# categorical level 3 basic 295 + vulnerable 50 = 345 (not FPG level 2). +# C3: foster SSI/SSP excluded; remaining member income 100,000 > 47,764. +- name: Case 41, above-SMI categorical large household receives level 3. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: + '2026': 40 + immigration_status: + '2026': CITIZEN + employment_income: + '2026': 13600 + social_security: + '2026': 0 + is_disabled: + '2026': false + meets_ssi_disability_criteria: + '2026': false + is_in_foster_care: + 2026-01: false + 2026-02: false + 2026-03: false + 2026-04: false + 2026-05: false + 2026-06: false + 2026-07: false + 2026-08: false + 2026-09: false + 2026-10: false + 2026-11: false + 2026-12: false + person2: + age: + '2026': 40 + immigration_status: + '2026': CITIZEN + employment_income: + '2026': 13600 + social_security: + '2026': 0 + is_disabled: + '2026': false + meets_ssi_disability_criteria: + '2026': false + is_in_foster_care: + 2026-01: false + 2026-02: false + 2026-03: false + 2026-04: false + 2026-05: false + 2026-06: false + 2026-07: false + 2026-08: false + 2026-09: false + 2026-10: false + 2026-11: false + 2026-12: false + person3: + age: + '2026': 40 + immigration_status: + '2026': CITIZEN + employment_income: + '2026': 13600 + social_security: + '2026': 0 + is_disabled: + '2026': false + meets_ssi_disability_criteria: + '2026': false + is_in_foster_care: + 2026-01: false + 2026-02: false + 2026-03: false + 2026-04: false + 2026-05: false + 2026-06: false + 2026-07: false + 2026-08: false + 2026-09: false + 2026-10: false + 2026-11: false + 2026-12: false + person4: + age: + '2026': 40 + immigration_status: + '2026': CITIZEN + employment_income: + '2026': 13600 + social_security: + '2026': 0 + is_disabled: + '2026': false + meets_ssi_disability_criteria: + '2026': false + is_in_foster_care: + 2026-01: false + 2026-02: false + 2026-03: false + 2026-04: false + 2026-05: false + 2026-06: false + 2026-07: false + 2026-08: false + 2026-09: false + 2026-10: false + 2026-11: false + 2026-12: false + person5: + age: + '2026': 40 + immigration_status: + '2026': CITIZEN + employment_income: + '2026': 13600 + social_security: + '2026': 0 + is_disabled: + '2026': false + meets_ssi_disability_criteria: + '2026': false + is_in_foster_care: + 2026-01: false + 2026-02: false + 2026-03: false + 2026-04: false + 2026-05: false + 2026-06: false + 2026-07: false + 2026-08: false + 2026-09: false + 2026-10: false + 2026-11: false + 2026-12: false + person6: + age: + '2026': 40 + immigration_status: + '2026': CITIZEN + employment_income: + '2026': 13600 + social_security: + '2026': 0 + is_disabled: + '2026': false + meets_ssi_disability_criteria: + '2026': false + is_in_foster_care: + 2026-01: false + 2026-02: false + 2026-03: false + 2026-04: false + 2026-05: false + 2026-06: false + 2026-07: false + 2026-08: false + 2026-09: false + 2026-10: false + 2026-11: false + 2026-12: false + person7: + age: + '2026': 40 + immigration_status: + '2026': CITIZEN + employment_income: + '2026': 13600 + social_security: + '2026': 0 + is_disabled: + '2026': false + meets_ssi_disability_criteria: + '2026': false + is_in_foster_care: + 2026-01: false + 2026-02: false + 2026-03: false + 2026-04: false + 2026-05: false + 2026-06: false + 2026-07: false + 2026-08: false + 2026-09: false + 2026-10: false + 2026-11: false + 2026-12: false + person8: + age: + '2026': 40 + immigration_status: + '2026': CITIZEN + employment_income: + '2026': 13600 + social_security: + '2026': 0 + is_disabled: + '2026': false + meets_ssi_disability_criteria: + '2026': false + is_in_foster_care: + 2026-01: false + 2026-02: false + 2026-03: false + 2026-04: false + 2026-05: false + 2026-06: false + 2026-07: false + 2026-08: false + 2026-09: false + 2026-10: false + 2026-11: false + 2026-12: false + person9: + age: + '2026': 40 + immigration_status: + '2026': CITIZEN + employment_income: + '2026': 13600 + social_security: + '2026': 0 + is_disabled: + '2026': false + meets_ssi_disability_criteria: + '2026': false + is_in_foster_care: + 2026-01: false + 2026-02: false + 2026-03: false + 2026-04: false + 2026-05: false + 2026-06: false + 2026-07: false + 2026-08: false + 2026-09: false + 2026-10: false + 2026-11: false + 2026-12: false + person10: + age: + '2026': 40 + immigration_status: + '2026': CITIZEN + employment_income: + '2026': 13600 + social_security: + '2026': 0 + is_disabled: + '2026': false + meets_ssi_disability_criteria: + '2026': false + is_in_foster_care: + 2026-01: false + 2026-02: false + 2026-03: false + 2026-04: false + 2026-05: false + 2026-06: false + 2026-07: false + 2026-08: false + 2026-09: false + 2026-10: false + 2026-11: false + 2026-12: false + person11: + age: + '2026': 40 + immigration_status: + '2026': CITIZEN + employment_income: + '2026': 0 + social_security: + '2026': 0 + is_disabled: + '2026': true + meets_ssi_disability_criteria: + '2026': true + is_in_foster_care: + 2026-01: false + 2026-02: false + 2026-03: false + 2026-04: false + 2026-05: false + 2026-06: false + 2026-07: false + 2026-08: false + 2026-09: false + 2026-10: false + 2026-11: false + 2026-12: false + spm_units: + unit: + members: + - person1 + - person2 + - person3 + - person4 + - person5 + - person6 + - person7 + - person8 + - person9 + - person10 + - person11 + heating_type: + '2026': NATURAL_GAS + gas_expense: + '2026': 1000 + heat_expense_included_in_rent: + '2026': false + households: + household: + members: + - person1 + - person2 + - person3 + - person4 + - person5 + - person6 + - person7 + - person8 + - person9 + - person10 + - person11 + state_code: + '2026': CT + tax_units: + person1: + members: + - person1 + person2: + members: + - person2 + person3: + members: + - person3 + person4: + members: + - person4 + person5: + members: + - person5 + person6: + members: + - person6 + person7: + members: + - person7 + person8: + members: + - person8 + person9: + members: + - person9 + person10: + members: + - person10 + person11: + members: + - person11 + marital_units: + person1: + members: + - person1 + person2: + members: + - person2 + person3: + members: + - person3 + person4: + members: + - person4 + person5: + members: + - person5 + person6: + members: + - person6 + person7: + members: + - person7 + person8: + members: + - person8 + person9: + members: + - person9 + person10: + members: + - person10 + person11: + members: + - person11 + families: + person1: + members: + - person1 + person2: + members: + - person2 + person3: + members: + - person3 + person4: + members: + - person4 + person5: + members: + - person5 + person6: + members: + - person6 + person7: + members: + - person7 + person8: + members: + - person8 + person9: + members: + - person9 + person10: + members: + - person10 + person11: + members: + - person11 + output: + ct_ceap_household_size: 11 + ct_ceap_countable_income: 136000 + ct_ceap_income_limit: 135025 + ct_ceap_categorically_eligible: true + ct_ceap_benefit_level: 3 + ct_ceap: 345 + +- name: Case 42, excluded foster adult SSP cannot establish categorical eligibility. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: + '2026': 40 + immigration_status: + '2026': CITIZEN + employment_income: + '2026': 100000 + social_security: + '2026': 0 + is_disabled: + '2026': false + is_blind: + '2026': false + is_in_foster_care: + 2026-01: false + 2026-02: false + 2026-03: false + 2026-04: false + 2026-05: false + 2026-06: false + 2026-07: false + 2026-08: false + 2026-09: false + 2026-10: false + 2026-11: false + 2026-12: false + takes_up_ssi_if_eligible: + '2026': false + person2: + age: + '2026': 40 + immigration_status: + '2026': CITIZEN + employment_income: + '2026': 0 + social_security: + '2026': 0 + is_disabled: + '2026': true + meets_ssi_disability_criteria: + '2026': true + is_in_foster_care: + 2026-01: true + 2026-02: true + 2026-03: true + 2026-04: true + 2026-05: true + 2026-06: true + 2026-07: true + 2026-08: true + 2026-09: true + 2026-10: true + 2026-11: true + 2026-12: true + takes_up_ssi_if_eligible: + '2026': true + pre_subsidy_rent: + '2026': 4800 + ct_ssp_lives_with_others: + 2026-01: true + 2026-02: true + 2026-03: true + 2026-04: true + 2026-05: true + 2026-06: true + 2026-07: true + 2026-08: true + 2026-09: true + 2026-10: true + 2026-11: true + 2026-12: true + spm_units: + unit: + members: + - person1 + - person2 + heating_type: + '2026': NATURAL_GAS + gas_expense: + '2026': 1000 + heat_expense_included_in_rent: + '2026': false + households: + household: + members: + - person1 + - person2 + state_code: + '2026': CT + tax_units: + tax1: + members: + - person1 + tax2: + members: + - person2 + marital_units: + marital1: + members: + - person1 + marital2: + members: + - person2 + families: + family1: + members: + - person1 + family2: + members: + - person2 + output: + ct_ceap_household_size: 1 + ct_ceap_countable_income: 100000 + ct_ceap_categorically_eligible: false + ct_ceap_eligible: false + ct_ceap: 0 + +# Recurring IRA receipts exceed the published one-person income ceiling. +- name: Case 43, recurring IRA income above the limit prevents regular heating assistance. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + immigration_status: CITIZEN + taxable_ira_distributions: 100_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap: 0 + +- name: Case 44, actual large households retain the ordinary tier through the strict federal floor. + period: 2026 + absolute_error_margin: 0.01 + # Threshold edges: 2025 FPG for 30 = 15_650 + 29 x 5_500 = 175_150; + # 110% rounded = 192_665. Shared SMI = floor(floor(153_091 x 0.6) + # x (1.32 + 24 x 0.03)) = floor(91_854 x 2.04) = 187_382. + # All four exceed SMI. The first two pass only through the floor and stay + # Level 1: income <= 125% FPG = 218_937.50. No member is vulnerable. + # Pay min(595, 1_000) = 595; at and above 192_665, pay zero. + # Household size, income, eligibility and payment are all calculated. + input: + people: + person1: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0, employment_income: 190_000} + person2: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person3: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person4: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person5: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person6: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person7: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person8: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person9: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person10: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person11: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person12: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person13: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person14: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person15: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person16: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person17: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person18: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person19: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person20: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person21: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person22: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person23: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person24: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person25: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person26: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person27: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person28: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person29: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person30: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person31: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0, employment_income: 192_664.99} + person32: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person33: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person34: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person35: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person36: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person37: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person38: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person39: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person40: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person41: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person42: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person43: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person44: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person45: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person46: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person47: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person48: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person49: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person50: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person51: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person52: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person53: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person54: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person55: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person56: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person57: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person58: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person59: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person60: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person61: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0, employment_income: 192_665} + person62: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person63: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person64: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person65: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person66: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person67: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person68: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person69: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person70: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person71: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person72: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person73: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person74: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person75: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person76: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person77: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person78: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person79: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person80: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person81: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person82: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person83: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person84: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person85: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person86: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person87: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person88: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person89: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person90: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person91: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0, employment_income: 192_665.01} + person92: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person93: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person94: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person95: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person96: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person97: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person98: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person99: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person100: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person101: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person102: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person103: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person104: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person105: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person106: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person107: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person108: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person109: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person110: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person111: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person112: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person113: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person114: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person115: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person116: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person117: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person118: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person119: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person120: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + spm_units: + spm_unit1: + members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10, person11, person12, person13, person14, person15, person16, person17, person18, person19, person20, person21, person22, person23, person24, person25, person26, person27, person28, person29, person30] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: 0 + tanf: 0 + ct_ssp: 0 + spm_unit2: + members: [person31, person32, person33, person34, person35, person36, person37, person38, person39, person40, person41, person42, person43, person44, person45, person46, person47, person48, person49, person50, person51, person52, person53, person54, person55, person56, person57, person58, person59, person60] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: 0 + tanf: 0 + ct_ssp: 0 + spm_unit3: + members: [person61, person62, person63, person64, person65, person66, person67, person68, person69, person70, person71, person72, person73, person74, person75, person76, person77, person78, person79, person80, person81, person82, person83, person84, person85, person86, person87, person88, person89, person90] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: 0 + tanf: 0 + ct_ssp: 0 + spm_unit4: + members: [person91, person92, person93, person94, person95, person96, person97, person98, person99, person100, person101, person102, person103, person104, person105, person106, person107, person108, person109, person110, person111, person112, person113, person114, person115, person116, person117, person118, person119, person120] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: 0 + tanf: 0 + ct_ssp: 0 + households: + household1: + members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10, person11, person12, person13, person14, person15, person16, person17, person18, person19, person20, person21, person22, person23, person24, person25, person26, person27, person28, person29, person30] + state_code: CT + household2: + members: [person31, person32, person33, person34, person35, person36, person37, person38, person39, person40, person41, person42, person43, person44, person45, person46, person47, person48, person49, person50, person51, person52, person53, person54, person55, person56, person57, person58, person59, person60] + state_code: CT + household3: + members: [person61, person62, person63, person64, person65, person66, person67, person68, person69, person70, person71, person72, person73, person74, person75, person76, person77, person78, person79, person80, person81, person82, person83, person84, person85, person86, person87, person88, person89, person90] + state_code: CT + household4: + members: [person91, person92, person93, person94, person95, person96, person97, person98, person99, person100, person101, person102, person103, person104, person105, person106, person107, person108, person109, person110, person111, person112, person113, person114, person115, person116, person117, person118, person119, person120] + state_code: CT + output: + ct_ceap_household_size: [30, 30, 30, 30] + ct_ceap_countable_income: [190_000, 192_664.99, 192_665, 192_665.01] + ct_ceap_income_limit: [187_382, 187_382, 187_382, 187_382] + ct_ceap_categorically_eligible: [false, false, false, false] + ct_ceap_benefit_level: [1, 1, 1, 1] + ct_ceap_eligible: [true, true, false, false] + ct_ceap: [595, 595, 0, 0] + +- name: Case 45, military retirement pay counts outside ordinary pension income. + period: 2026 + absolute_error_margin: 0.01 + # Pensions are counted by the FY2026 plan and FY2027 income definition. + # 60_000 military pay, or 30_000 pension + 30_000 military, both count as + # 60_000, above the one-person 47_764 limit. Neither receives a grant. + input: + people: + person1: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0, military_retirement_pay: 60_000} + person2: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0, pension_income: 30_000, military_retirement_pay: 30_000} + spm_units: + spm_unit1: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: 0 + tanf: 0 + ct_ssp: 0 + spm_unit2: + members: [person2] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: 0 + tanf: 0 + ct_ssp: 0 + households: + household1: + members: [person1] + state_code: CT + household2: + members: [person2] + state_code: CT + output: + ct_ceap_countable_income: [60_000, 60_000] + ct_ceap_eligible: [false, false] + ct_ceap: [0, 0] + +- name: Case 46, each Social Security receipt is net of its paid Part B premium and floored. + period: 2026 + absolute_error_margin: 0.01 + # FY2026 plan page 6 selects SSA excluding Medicare deductions. + # 49_000 gross SSA - 2_400 explicitly supplied paid Part B = 46_600, + # below 47_764 and above 200% FPG (31_300): Level 3 plus age-68 + # supplement gives min(295 + 50, 1_000) = 345. + # Second member: max(1_000 SSA - 2_400 Part B, 0) + 5_000 pension + # = 5_000, Level 1, min(595 + 50, 1_000) = 645. Excess premiums + # cannot deduct a different income source. + input: + people: + person1: {age: 68, immigration_status: CITIZEN, is_disabled: false, ssi: 0, social_security_retirement: 49_000, medicare_enrolled: true, medicare_part_b_premium: 2_400} + person2: {age: 68, immigration_status: CITIZEN, is_disabled: false, ssi: 0, social_security_retirement: 1_000, pension_income: 5_000, medicare_enrolled: true, medicare_part_b_premium: 2_400} + spm_units: + spm_unit1: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: 0 + tanf: 0 + ct_ssp: 0 + spm_unit2: + members: [person2] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: 0 + tanf: 0 + ct_ssp: 0 + households: + household1: + members: [person1] + state_code: CT + household2: + members: [person2] + state_code: CT + output: + ct_ceap_countable_income: [46_600, 5_000] + ct_ceap_benefit_level: [3, 1] + ct_ceap_eligible: [true, true] + ct_ceap: [345, 645] + +- name: Case 47, rental losses cannot cancel pension receipts within or across members. + period: 2026 + absolute_error_margin: 0.01 + # The source counts gross rental receipts. Existing rental inputs stand + # in for nonnegative gross receipts, so a negative input contributes zero. + # Each household counts 49_000 pension, above its qualified-size-one + # 47_764 ceiling. The second rental owner is excluded from size, while + # their countable receipts would remain included. Both grants are zero. + input: + people: + person1: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0, pension_income: 49_000, rental_income: -10_000} + person2: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0, pension_income: 49_000} + person3: {age: 40, immigration_status: UNDOCUMENTED, is_disabled: false, ssi: 0, rental_income: -10_000} + spm_units: + spm_unit1: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: 0 + tanf: 0 + ct_ssp: 0 + spm_unit2: + members: [person2, person3] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: 0 + tanf: 0 + ct_ssp: 0 + households: + household1: + members: [person1] + state_code: CT + household2: + members: [person2, person3] + state_code: CT + output: + ct_ceap_household_size: [1, 1] + ct_ceap_countable_income: [49_000, 49_000] + ct_ceap_eligible: [false, false] + ct_ceap: [0, 0] + +- name: Case 48, a supplied TFA entitlement requires actual take-up for categorical receipt. + period: 2026 + absolute_error_margin: 0.01 + # The supplied 6_000 TFA entitlement isolates take-up, rather than testing + # TFA entitlement rules. Nonparticipation makes tanf zero and gives no + # categorical bypass. A participant receives 6_000 and is categorical. + # TFA remains excluded from CEAP income: both count 100_000 wages. + # The participant above SMI keeps the sourced Level 3 award of 295. + input: + people: + person1: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0, employment_income: 100_000} + person2: {age: 10, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person3: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0, employment_income: 100_000} + person4: {age: 10, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + spm_units: + spm_unit1: + members: [person1, person2] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: 0 + ct_ssp: 0 + ct_tfa: 6_000 + takes_up_tanf_if_eligible: false + spm_unit2: + members: [person3, person4] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: 0 + ct_ssp: 0 + ct_tfa: 6_000 + takes_up_tanf_if_eligible: true + households: + household1: + members: [person1, person2] + state_code: CT + household2: + members: [person3, person4] + state_code: CT + output: + tanf: [0, 6_000] + ct_ceap_countable_income: [100_000, 100_000] + ct_ceap_categorically_eligible: [false, true] + ct_ceap_benefit_level: [3, 3] + ct_ceap_eligible: [false, true] + ct_ceap: [0, 295] + +- name: Case 49, unemployment fallback and reported override reach the final heating grant. + period: 2026 + absolute_error_margin: 0.01 + # The existing modeled-UI input isolates the shared fallback contract. + # 45_000 wages + 6_000 modeled UI (reported zero) = 51_000, above + # 47_764. Reported 1_200 overrides modeled 6_000, giving 46_200: + # Level 3, nonvulnerable, min(295, 1_000) = 295. + input: + people: + person1: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0, employment_income: 45_000, unemployment_compensation: 0, modeled_state_unemployment_compensation: 6_000} + person2: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0, employment_income: 45_000, unemployment_compensation: 1_200, modeled_state_unemployment_compensation: 6_000} + spm_units: + spm_unit1: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: 0 + tanf: 0 + ct_ssp: 0 + spm_unit2: + members: [person2] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: 0 + tanf: 0 + ct_ssp: 0 + households: + household1: + members: [person1] + state_code: CT + household2: + members: [person2] + state_code: CT + output: + total_unemployment_compensation: [6_000, 1_200] + ct_ceap_countable_income: [51_000, 46_200] + ct_ceap_eligible: [false, true] + ct_ceap: [0, 295] + +- name: Case 50, FY2027 federal floor uses the lagged guideline and adopted heating schedule. + period: 2027 + absolute_error_margin: 0.01 + # Threshold edges: 2026 FPG for 30 = 15_960 + 29 x 5_680 = 180_680; + # 110% = 198_748. The shared SMI limit is floor(93_681 x 2.04) = + # 191_109. Below the floor, income is below 125% FPG (225_850), so + # the adopted FY2027 Level 1 amount pays min(655, 1_000) = 655. + # Income exactly at the federal floor is not protected. + input: + people: + person1: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0, employment_income: 198_747.99} + person2: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person3: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person4: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person5: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person6: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person7: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person8: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person9: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person10: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person11: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person12: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person13: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person14: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person15: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person16: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person17: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person18: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person19: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person20: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person21: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person22: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person23: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person24: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person25: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person26: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person27: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person28: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person29: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person30: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person31: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0, employment_income: 198_748} + person32: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person33: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person34: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person35: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person36: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person37: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person38: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person39: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person40: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person41: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person42: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person43: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person44: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person45: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person46: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person47: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person48: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person49: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person50: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person51: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person52: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person53: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person54: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person55: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person56: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person57: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person58: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person59: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person60: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + spm_units: + spm_unit1: + members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10, person11, person12, person13, person14, person15, person16, person17, person18, person19, person20, person21, person22, person23, person24, person25, person26, person27, person28, person29, person30] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: 0 + tanf: 0 + ct_ssp: 0 + spm_unit2: + members: [person31, person32, person33, person34, person35, person36, person37, person38, person39, person40, person41, person42, person43, person44, person45, person46, person47, person48, person49, person50, person51, person52, person53, person54, person55, person56, person57, person58, person59, person60] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: 0 + tanf: 0 + ct_ssp: 0 + households: + household1: + members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10, person11, person12, person13, person14, person15, person16, person17, person18, person19, person20, person21, person22, person23, person24, person25, person26, person27, person28, person29, person30] + state_code: CT + household2: + members: [person31, person32, person33, person34, person35, person36, person37, person38, person39, person40, person41, person42, person43, person44, person45, person46, person47, person48, person49, person50, person51, person52, person53, person54, person55, person56, person57, person58, person59, person60] + state_code: CT + output: + ct_ceap_household_size: [30, 30] + ct_ceap_countable_income: [198_747.99, 198_748] + ct_ceap_income_limit: [191_109, 191_109] + ct_ceap_benefit_level: [1, 1] + ct_ceap_eligible: [true, false] + ct_ceap: [655, 0] + +# Allocation plans: rental benefits apply when heat is in rent and carry no bill +# cap, so a $50 gas bill does not limit the Level 1 FY2026 amount of $125. +- name: Case 51, a rental benefit is not capped by a reported bill. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + social_security: 0 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 50 + heat_expense_included_in_rent: true + snap: 0 + tanf: 0 + ct_ssp: 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap_benefit_level: 1 + ct_ceap: 125 + +# 2025 guideline for 11 members: 15,650 + 10 x 5,500 = 70,650. Income of exactly +# floor(91,854 x 1.47) = 135,025 is not above the limit, so the ratio sets the +# level: 135,025 / 70,650 = 1.91, Level 2, $445. Case 41 is above the limit. +- name: Case 52, a categorical household exactly at the limit keeps its poverty level. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: {age: 40, immigration_status: CITIZEN, ssi: 0, social_security: 0, employment_income: 135_025} + person2: {age: 40, immigration_status: CITIZEN, ssi: 0, social_security: 0} + person3: {age: 40, immigration_status: CITIZEN, ssi: 0, social_security: 0} + person4: {age: 40, immigration_status: CITIZEN, ssi: 0, social_security: 0} + person5: {age: 40, immigration_status: CITIZEN, ssi: 0, social_security: 0} + person6: {age: 40, immigration_status: CITIZEN, ssi: 0, social_security: 0} + person7: {age: 40, immigration_status: CITIZEN, ssi: 0, social_security: 0} + person8: {age: 40, immigration_status: CITIZEN, ssi: 0, social_security: 0} + person9: {age: 40, immigration_status: CITIZEN, ssi: 0, social_security: 0} + person10: {age: 40, immigration_status: CITIZEN, ssi: 0, social_security: 0} + person11: {age: 40, immigration_status: CITIZEN, ssi: 0, social_security: 0} + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10, person11] + heating_type: NATURAL_GAS + gas_expense: 1_000 + snap: 1_200 + tanf: 0 + ct_ssp: 0 + households: + household: + members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10, person11] + state_code: CT + output: + ct_ceap_income_limit: 135_025 + ct_ceap_categorically_eligible: true + ct_ceap_benefit_level: 2 + ct_ceap: 445 + +# Allocation plans p. 5: households do not include incarcerated individuals. +# First unit: size 1, 55,000 is above the 47,764 limit and the 17,215 floor, and +# the incarcerated member's SSI establishes no categorical receipt: $0. Second +# unit: 25,000 / 15,650 = 1.60, Level 2, $445; the incarcerated member's wages +# and age 65 count for neither income nor vulnerability. +- name: Case 53, incarcerated members are outside size income vulnerability and categorical receipt. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + social_security: 0 + employment_income: 55_000 + person2: + age: 40 + immigration_status: CITIZEN + is_incarcerated: + 2026-01: true + ssi: 1_200 + social_security: 0 + person3: + age: 40 + immigration_status: CITIZEN + ssi: 0 + social_security: 0 + employment_income: 25_000 + person4: + age: 65 + immigration_status: CITIZEN + is_incarcerated: + 2026-01: true + ssi: 0 + social_security: 0 + employment_income: 10_000 + spm_units: + spm_unit1: + members: [person1, person2] + heating_type: NATURAL_GAS + gas_expense: 1_000 + snap: 0 + tanf: 0 + ct_ssp: 0 + spm_unit2: + members: [person3, person4] + heating_type: NATURAL_GAS + gas_expense: 1_000 + snap: 0 + tanf: 0 + ct_ssp: 0 + households: + household1: + members: [person1, person2] + state_code: CT + household2: + members: [person3, person4] + state_code: CT + output: + ct_ceap_household_size: [1, 1] + ct_ceap_countable_income: [55_000, 25_000] + ct_ceap_categorically_eligible: [false, false] + ct_ceap: [0, 445] + +- name: Case 54, a categorical household the federal floor admits keeps its FY2026 income level. + period: 2026 + absolute_error_margin: 0.01 + # 2025 FPG for 30 = 175_150; 110% = 192_665; SMI limit = 187_382 (Case 44). + # The floor admits 190_000 without SNAP, so 42 U.S.C. 8624(b)(5) bars paying + # less because of SNAP: 190_000 / 175_150 = 1.08, Level 1, min(595, 1_000) = 595. + input: + people: + person1: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0, employment_income: 190_000} + person2: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person3: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person4: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person5: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person6: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person7: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person8: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person9: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person10: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person11: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person12: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person13: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person14: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person15: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person16: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person17: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person18: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person19: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person20: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person21: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person22: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person23: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person24: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person25: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person26: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person27: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person28: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person29: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person30: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10, person11, person12, person13, person14, person15, person16, person17, person18, person19, person20, person21, person22, person23, person24, person25, person26, person27, person28, person29, person30] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: 1_200 + tanf: 0 + ct_ssp: 0 + households: + household: + members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10, person11, person12, person13, person14, person15, person16, person17, person18, person19, person20, person21, person22, person23, person24, person25, person26, person27, person28, person29, person30] + state_code: CT + output: + ct_ceap_household_size: 30 + ct_ceap_categorically_eligible: true + ct_ceap_income_eligible: true + ct_ceap_benefit_level: 1 + ct_ceap: 595 + +- name: Case 55, a categorical household the federal floor admits keeps its FY2027 income level. + period: 2027 + absolute_error_margin: 0.01 + # 2026 FPG for 28 = 15_960 + 27 x 5_680 = 169_320; 110% = 186_252; SMI limit = + # floor(93_681 x 1.98) = 185_488. 186_000 / 169_320 = 1.10, Level 1, + # min(655, 1_000) = 655. + input: + people: + person1: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0, employment_income: 186_000} + person2: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person3: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person4: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person5: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person6: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person7: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person8: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person9: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person10: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person11: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person12: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person13: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person14: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person15: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person16: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person17: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person18: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person19: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person20: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person21: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person22: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person23: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person24: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person25: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person26: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person27: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + person28: {age: 40, immigration_status: CITIZEN, is_disabled: false, ssi: 0} + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10, person11, person12, person13, person14, person15, person16, person17, person18, person19, person20, person21, person22, person23, person24, person25, person26, person27, person28] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: 1_200 + tanf: 0 + ct_ssp: 0 + households: + household: + members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10, person11, person12, person13, person14, person15, person16, person17, person18, person19, person20, person21, person22, person23, person24, person25, person26, person27, person28] + state_code: CT + output: + ct_ceap_household_size: 28 + ct_ceap_categorically_eligible: true + ct_ceap_income_eligible: true + ct_ceap_benefit_level: 1 + ct_ceap: 655 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ct/dss/ceap/eligibility/ct_ceap_categorically_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ct/dss/ceap/eligibility/ct_ceap_categorically_eligible.yaml new file mode 100644 index 00000000000..0960c55841b --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ct/dss/ceap/eligibility/ct_ceap_categorically_eligible.yaml @@ -0,0 +1,388 @@ +# FY2026 plan page 5; FY2026 and FY2027 allocation plans, sections IV and IX; direct-vendor exception. +# Sources: +# PDF pages 5-7 +# - https://liheapch.acf.gov/docs/2026/state-plans/CT_Plan_2026.pdf#page=5 +# PDF pages 5-7,9-11,15 +# - https://portal.ct.gov/dss/-/media/departments-and-agencies/dss/winter-heating-assistance/09012026/ffy-27-liheap-allocation-plan.pdf#page=5 +# Direct-vendor receipt bypasses the income ceiling; rental assistance keeps its income test. +- name: Case 1, snap receipt with direct heating. + period: 2026 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2026': 120 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap_categorically_eligible: true + +# Direct-vendor receipt bypasses the income ceiling; rental assistance keeps its income test. +- name: Case 2, snap receipt with heat included in rent. + period: 2026 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: true + snap: + '2026': 120 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap_categorically_eligible: false + +# Direct-vendor receipt bypasses the income ceiling; rental assistance keeps its income test. +- name: Case 3, TFA receipt with direct heating. + period: 2026 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + person2: + age: 10 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + spm_units: + spm_unit: + members: [person1, person2] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 120 + ct_ssp: + '2026': 0 + households: + household: + members: [person1, person2] + state_code: CT + output: + ct_ceap_categorically_eligible: true + +# Direct-vendor receipt bypasses the income ceiling; rental assistance keeps its income test. +- name: Case 4, TFA receipt with heat included in rent. + period: 2026 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + person2: + age: 10 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + spm_units: + spm_unit: + members: [person1, person2] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: true + snap: + '2026': 0 + tanf: + '2026': 120 + ct_ssp: + '2026': 0 + households: + household: + members: [person1, person2] + state_code: CT + output: + ct_ceap_categorically_eligible: false + +# Direct-vendor receipt bypasses the income ceiling; rental assistance keeps its income test. +- name: Case 5, ssi receipt with direct heating. + period: 2026 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: true + is_in_foster_care: + 2026-01: false + ssi: + '2026': 120 + social_security: 0 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap_categorically_eligible: true + +# Direct-vendor receipt bypasses the income ceiling; rental assistance keeps its income test. +- name: Case 6, ssi receipt with heat included in rent. + period: 2026 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: true + is_in_foster_care: + 2026-01: false + ssi: + '2026': 120 + social_security: 0 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: true + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap_categorically_eligible: false + +# Direct-vendor receipt bypasses the income ceiling; rental assistance keeps its income test. +- name: Case 7, ct_ssp receipt with direct heating. + period: 2026 + input: + people: + person1: + age: 65 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 120 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap_categorically_eligible: true + +# Direct-vendor receipt bypasses the income ceiling; rental assistance keeps its income test. +- name: Case 8, ct_ssp receipt with heat included in rent. + period: 2026 + input: + people: + person1: + age: 65 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: true + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 120 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap_categorically_eligible: false + +- name: Case 9, no qualifying receipt has no categorical exception. + period: 2026 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap_categorically_eligible: false + +# Generic VA does not identify the required means-tested program. +- name: Case 10, generic veterans benefits do not establish categorical receipt. + period: 2026 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + veterans_benefits: 20_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap_categorically_eligible: false + +# Reported SSI receipt establishes categorical receipt when the +# modeled SSI amount is zero. +- name: Case 11, reported SSI receipt with direct heating. + period: 2026 + input: + people: + person1: + age: 70 + immigration_status: CITIZEN + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + receives_ssi: + 2026-01: true + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap_categorically_eligible: true + diff --git a/policyengine_us/tests/policy/baseline/gov/states/ct/dss/ceap/eligibility/ct_ceap_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ct/dss/ceap/eligibility/ct_ceap_eligible.yaml new file mode 100644 index 00000000000..4adfef6a5b0 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ct/dss/ceap/eligibility/ct_ceap_eligible.yaml @@ -0,0 +1,436 @@ +# State, membership, income and heating responsibility. +# Sources: +# - https://liheapch.acf.gov/docs/2026/benefits-matricies/CT_BenefitMatrix_Heat-Crisis_2026.pdf +# PDF pages 5-7,9-11,15 +# - https://portal.ct.gov/dss/-/media/departments-and-agencies/dss/winter-heating-assistance/09012026/ffy-27-liheap-allocation-plan.pdf#page=5 +# Published one-person SMI ceiling is inclusive. +- name: Case 1, FY2026 income at ceiling eligible. + period: 2026 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + employment_income: 47_764 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap_eligible: true + +# Published one-person SMI ceiling is inclusive. +- name: Case 2, FY2026 income one cent over ceiling ineligible. + period: 2026 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + employment_income: 47_764.01 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap_eligible: false + +# Published one-person SMI ceiling is inclusive. +- name: Case 3, FY2027 income at ceiling eligible. + period: 2027 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2027-01: false + ssi: + '2027': 0 + social_security: 0 + employment_income: 48_714 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2027': 0 + tanf: + '2027': 0 + ct_ssp: + '2027': 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap_eligible: true + +# Published one-person SMI ceiling is inclusive. +- name: Case 4, FY2027 income one cent over ceiling ineligible. + period: 2027 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2027-01: false + ssi: + '2027': 0 + social_security: 0 + employment_income: 48_714.01 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2027': 0 + tanf: + '2027': 0 + ct_ssp: + '2027': 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap_eligible: false + +# Heating responsibility gate, with heat-in-rent exception to direct expense evidence. +- name: Case 5, known direct fuel with positive matching cost. + period: 2026 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap_eligible: true + +# Heating responsibility gate, with heat-in-rent exception to direct expense evidence. +- name: Case 6, direct fuel with zero matching cost. + period: 2026 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 0 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap_eligible: false + +# Heating responsibility gate, with heat-in-rent exception to direct expense evidence. +- name: Case 7, direct fuel with negative matching cost. + period: 2026 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: -100 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap_eligible: false + +# Heating responsibility gate, with heat-in-rent exception to direct expense evidence. +- name: Case 8, affirmative no heating despite reported bills. + period: 2026 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + spm_units: + spm_unit: + members: [person1] + heating_type: NONE + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap_eligible: false + +# Heating responsibility gate, with heat-in-rent exception to direct expense evidence. +- name: Case 9, unknown direct fuel does not establish a heating bill. + period: 2026 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + spm_units: + spm_unit: + members: [person1] + heating_type: UNSPECIFIED + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap_eligible: false + +# Heating responsibility gate, with heat-in-rent exception to direct expense evidence. +- name: Case 10, rental with unknown fuel and no separate cost. + period: 2026 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + spm_units: + spm_unit: + members: [person1] + heating_type: UNSPECIFIED + gas_expense: 0 + heat_expense_included_in_rent: true + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap_eligible: true + +# Heating responsibility gate, with heat-in-rent exception to direct expense evidence. +- name: Case 11, rental with affirmative no heat. + period: 2026 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + spm_units: + spm_unit: + members: [person1] + heating_type: NONE + gas_expense: 0 + heat_expense_included_in_rent: true + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap_eligible: false + +# Categorical receipt does not waive qualified membership. +- name: Case 12, no qualified members ineligible despite SNAP receipt. + period: 2026 + input: + people: + person1: + age: 40 + immigration_status: UNDOCUMENTED + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2026': 120 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap_eligible: false + +- name: Case 13, categorical receipt does not waive heating responsibility. + period: 2026 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 0 + heat_expense_included_in_rent: false + snap: + '2026': 120 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/ct/dss/ceap/eligibility/ct_ceap_household_member.yaml b/policyengine_us/tests/policy/baseline/gov/states/ct/dss/ceap/eligibility/ct_ceap_household_member.yaml new file mode 100644 index 00000000000..c9586bbf631 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ct/dss/ceap/eligibility/ct_ceap_household_member.yaml @@ -0,0 +1,28 @@ +# PDF page 5 +# - https://portal.ct.gov/dss/-/media/departments-and-agencies/dss/winter-heating-assistance/09012026/ffy-27-liheap-allocation-plan.pdf#page=5 + +- name: Case 1, foster and incarcerated people are outside the household. + period: 2026 + input: + people: + person1: + age: 40 + person2: + age: 10 + is_in_foster_care: + 2026-01: true + person3: + age: 40 + is_incarcerated: + 2026-01: true + spm_units: + spm_unit: + members: [person1, person2, person3] + heating_type: NATURAL_GAS + gas_expense: 1_000 + households: + household: + members: [person1, person2, person3] + state_code: CT + output: + ct_ceap_household_member: [true, false, false] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ct/dss/ceap/eligibility/ct_ceap_household_size.yaml b/policyengine_us/tests/policy/baseline/gov/states/ct/dss/ceap/eligibility/ct_ceap_household_size.yaml new file mode 100644 index 00000000000..19f6232ca94 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ct/dss/ceap/eligibility/ct_ceap_household_size.yaml @@ -0,0 +1,278 @@ +# FY2026 and FY2027 allocation plans, sections III and V.J-K; qualified membership and represented foster exclusion. +# Sources: +# PDF pages 5,9 +# - https://www.cga.ct.gov/app/related/20250616_2025%20Block%20Grants%20and%20Waiver%20Applications/FFY%202026%20LIHEAP%20Allocation%20Plan.pdf#page=5 +# PDF pages 5-7,9-11,15 +# - https://portal.ct.gov/dss/-/media/departments-and-agencies/dss/winter-heating-assistance/09012026/ffy-27-liheap-allocation-plan.pdf#page=5 +# Count qualified members, excluding represented foster members. +- name: Case 1, citizen and qualified noncitizens count. + period: 2026 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + person2: + age: 38 + immigration_status: LEGAL_PERMANENT_RESIDENT + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + person3: + age: 17 + immigration_status: REFUGEE + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + spm_units: + spm_unit: + members: [person1, person2, person3] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1, person2, person3] + state_code: CT + output: + ct_ceap_household_size: 3 + +# Count qualified members, excluding represented foster members. +- name: Case 2, undocumented parent does not count but citizen child does. + period: 2026 + input: + people: + person1: + age: 40 + immigration_status: UNDOCUMENTED + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + person2: + age: 38 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + spm_units: + spm_unit: + members: [person1, person2] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1, person2] + state_code: CT + output: + ct_ceap_household_size: 1 + +# Count qualified members, excluding represented foster members. +- name: Case 3, all nonqualified members yield zero size. + period: 2026 + input: + people: + person1: + age: 40 + immigration_status: UNDOCUMENTED + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + person2: + age: 38 + immigration_status: DACA + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + spm_units: + spm_unit: + members: [person1, person2] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1, person2] + state_code: CT + output: + ct_ceap_household_size: 0 + +# Count qualified members, excluding represented foster members. +- name: Case 4, represented foster child is excluded. + period: 2026 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + person2: + age: 10 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: true + ssi: + '2026': 0 + social_security: 0 + spm_units: + spm_unit: + members: [person1, person2] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1, person2] + state_code: CT + output: + ct_ceap_household_size: 1 + +# Count qualified members, excluding represented foster members. +- name: Case 5, eight qualified household members count. + period: 2026 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + person2: + age: 38 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + person3: + age: 17 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + person4: + age: 15 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + person5: + age: 12 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + person6: + age: 10 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + person7: + age: 8 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + person8: + age: 6 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5, person6, person7, person8] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1, person2, person3, person4, person5, person6, person7, person8] + state_code: CT + output: + ct_ceap_household_size: 8 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ct/dss/ceap/eligibility/ct_ceap_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ct/dss/ceap/eligibility/ct_ceap_income_eligible.yaml new file mode 100644 index 00000000000..38ccf38cdb3 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ct/dss/ceap/eligibility/ct_ceap_income_eligible.yaml @@ -0,0 +1,16 @@ +# Income test before categorical receipt. +# Sources: +# - https://portal.ct.gov/dss/-/media/departments-and-agencies/dss/winter-heating-assistance/09012026/ffy-27-liheap-allocation-plan.pdf#page=7 +# - https://www.law.cornell.edu/uscode/text/42/8624#b_2_B +# The one-person limit is inclusive at 47,764. For 30 people the limit is 187,382 +# and the floor is 1.1 x 175,150 = 192,665, with a strict "below". +- name: Case 1, the limit is inclusive and the federal floor is strict. + period: 2026 + input: + state_code: [CT, CT, CT, CT, CT] + heating_type: [NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, NATURAL_GAS] + gas_expense: [1_000, 1_000, 1_000, 1_000, 1_000] + ct_ceap_household_size: [1, 1, 30, 30, 30] + ct_ceap_countable_income: [47_764, 47_764.01, 187_382.01, 192_664.99, 192_665] + output: + ct_ceap_income_eligible: [true, false, true, true, false] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ct/dss/ceap/eligibility/ct_ceap_income_limit.yaml b/policyengine_us/tests/policy/baseline/gov/states/ct/dss/ceap/eligibility/ct_ceap_income_limit.yaml new file mode 100644 index 00000000000..3e721064bd5 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ct/dss/ceap/eligibility/ct_ceap_income_limit.yaml @@ -0,0 +1,42 @@ +# FY2026 benefit matrix and FY2027 allocation plan page 7; published annual income ceilings. +# Sources: +# - https://liheapch.acf.gov/docs/2026/benefits-matricies/CT_BenefitMatrix_Heat-Crisis_2026.pdf +# PDF pages 5-7,9-11,15 +# - https://portal.ct.gov/dss/-/media/departments-and-agencies/dss/winter-heating-assistance/09012026/ffy-27-liheap-allocation-plan.pdf#page=5 +# Source table amounts, not values evaluated from the model formula. +- name: Case 1, all eight published FY2026 household income limits. + period: 2026 + absolute_error_margin: 0.01 + input: + state_code: [CT, CT, CT, CT, CT, CT, CT, CT] + heating_type: [NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, + NATURAL_GAS] + gas_expense: [1_000, 1_000, 1_000, 1_000, 1_000, 1_000, 1_000, 1_000] + ct_ceap_household_size: [1, 2, 3, 4, 5, 6, 7, 8] + output: + ct_ceap_income_limit: [47_764, 62_460, 77_157, 91_854, 106_550, 121_247, 124_002, 126_758] + +# Source table amounts, not values evaluated from the model formula. +- name: Case 2, all eight published FY2027 household income limits. + period: 2027 + absolute_error_margin: 0.01 + input: + state_code: [CT, CT, CT, CT, CT, CT, CT, CT] + heating_type: [NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, + NATURAL_GAS] + gas_expense: [1_000, 1_000, 1_000, 1_000, 1_000, 1_000, 1_000, 1_000] + ct_ceap_household_size: [1, 2, 3, 4, 5, 6, 7, 8] + output: + ct_ceap_income_limit: [48_714, 63_703, 78_692, 93_681, 108_669, 123_658, 126_469, 129_279] + +# Eligibility requires a positive qualified household size. +- name: Case 3, no qualified members have no income allowance. + period: 2026 + absolute_error_margin: 0.01 + input: + state_code: CT + heating_type: NATURAL_GAS + gas_expense: 1_000 + ct_ceap_household_size: 0 + output: + ct_ceap_income_limit: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ct/dss/ceap/income/ct_ceap_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ct/dss/ceap/income/ct_ceap_countable_income.yaml new file mode 100644 index 00000000000..e844872a70e --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ct/dss/ceap/income/ct_ceap_countable_income.yaml @@ -0,0 +1,467 @@ +# FY2026 plan pages 6-7 check-box source list; FY2026 and FY2027 allocation plans, section III. +# Sources: +# PDF pages 5-7 +# - https://liheapch.acf.gov/docs/2026/state-plans/CT_Plan_2026.pdf#page=5 +# PDF pages 5,9 +# - https://www.cga.ct.gov/app/related/20250616_2025%20Block%20Grants%20and%20Waiver%20Applications/FFY%202026%20LIHEAP%20Allocation%20Plan.pdf#page=5 +# PDF pages 5-7,9-11,15 +# - https://portal.ct.gov/dss/-/media/departments-and-agencies/dss/winter-heating-assistance/09012026/ffy-27-liheap-allocation-plan.pdf#page=5 +# 1,000 + 6,000 + 2,000 + 3,000 + 4,000 + 5,000 = 21,000. +- name: Case 1, adult earned sources all count. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + employment_income: 1_000 + military_basic_pay: 6_000 + self_employment_income: 2_000 + sstb_self_employment_income: 3_000 + farm_operations_income: 4_000 + partnership_s_corp_income: 5_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap_countable_income: 21_000 + +# 100 + 200 + ... + 1,700 = 15,300. Generic VA is countable under the documented input limitation. +- name: Case 2, supported disjoint unearned sources count once. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 100 + unemployment_compensation: 200 + strike_benefits: 300 + pension_income: 400 + survivor_benefits: 500 + workers_compensation: 600 + disability_benefits: 700 + rental_income: 800 + farm_rent_income: 900 + estate_income: 1_000 + interest_income: 1_100 + ordinary_dividend_income: 1_200 + alimony_income: 1_300 + child_support_received: 1_400 + financial_assistance: 1_500 + gambling_winnings: 1_600 + veterans_benefits: 1_700 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap_countable_income: 15_300 + +# 1,200 taxable + 300 exempt pension = 1,500, without counting the aggregate twice. +- name: Case 3, pension components aggregate once. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + taxable_pension_income: 1_200 + tax_exempt_pension_income: 300 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap_countable_income: 1_500 + +# 10,000 adult wages + 1,000 child Social Security + 2,000 child support = 13,000. +- name: Case 4, child earned income excluded but unearned retained. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + employment_income: 10_000 + person2: + age: 17.99 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 1_000 + employment_income: 20_000 + self_employment_income: 1_000 + child_support_received: 2_000 + spm_units: + spm_unit: + members: [person1, person2] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1, person2] + state_code: CT + output: + ct_ceap_countable_income: 13_000 + +# 20,000 + 1,000 earned and 3,000 unearned = 24,000 at age 18. +- name: Case 5, earned income counts at age eighteen. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 18 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 1_000 + employment_income: 20_000 + self_employment_income: 1_000 + child_support_received: 2_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap_countable_income: 24_000 + +# 10,000 wages + 2,000 SSTB + 1,000 partnership = 13,000; losses contribute zero. +- name: Case 6, business losses do not offset other earnings. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + employment_income: 10_000 + self_employment_income: -5_000 + sstb_self_employment_income: 2_000 + farm_operations_income: -3_000 + partnership_s_corp_income: 1_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap_countable_income: 13_000 + +# The FY2026 plan's countable-income checklist leaves SSI, TANF and general assistance unchecked. +- name: Case 7, SSI TFA and general assistance excluded. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: true + is_in_foster_care: + 2026-01: false + ssi: + '2026': 12_000 + social_security: 0 + employment_income: 1_000 + general_assistance: 2_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 6_000 + ct_ssp: + '2026': 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap_countable_income: 1_000 + +# All 20,000 of excluded-from-size parent wages plus 1,000 child support counts. +- name: Case 8, nonqualified members income fully counts. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: UNDOCUMENTED + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + employment_income: 20_000 + person2: + age: 5 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + child_support_received: 1_000 + spm_units: + spm_unit: + members: [person1, person2] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1, person2] + state_code: CT + output: + ct_ceap_countable_income: 21_000 + +# Foster member is outside the energy household, including the members 8,000 unearned income. +- name: Case 9, represented foster income excluded. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: false + ssi: + '2026': 0 + social_security: 0 + employment_income: 10_000 + person2: + age: 17 + immigration_status: CITIZEN + is_disabled: false + is_in_foster_care: + 2026-01: true + ssi: + '2026': 0 + social_security: 6_000 + child_support_received: 2_000 + spm_units: + spm_unit: + members: [person1, person2] + heating_type: NATURAL_GAS + gas_expense: 1_000 + heat_expense_included_in_rent: false + snap: + '2026': 0 + tanf: + '2026': 0 + ct_ssp: + '2026': 0 + households: + household: + members: [person1, person2] + state_code: CT + output: + ct_ceap_countable_income: 10_000 + +# Ongoing retirement receipts: pension 1,000 + taxable IRA 12,000 + exempt IRA 3,000. +# Count the two aggregates once; one-time lump sums are not represented here. +- name: Case 10, recurring taxable and exempt retirement distributions count beside pensions. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + immigration_status: CITIZEN + ssi: 0 + pension_income: 1_000 + taxable_ira_distributions: 12_000 + tax_exempt_ira_distributions: 3_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + snap: 0 + tanf: 0 + ct_ssp: 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap_countable_income: 16_000 + +# Plan item 1.9 counts retirement and pension benefits: railroad retirement 6,000. +- name: Case 11, railroad retirement counts as a retirement benefit. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 60 + immigration_status: CITIZEN + ssi: 0 + railroad_benefits: 6_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + snap: 0 + tanf: 0 + ct_ssp: 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap_countable_income: 6_000 + +# Plan 1.9 (p. 6) checks one-time lump sums, jury duty, legal settlements and +# insurance payments, which miscellaneous_income carries: 30,000 + 20,000 = +# 50,000, above the 47,764 one-person limit and the 17,215 floor. +- name: Case 12, miscellaneous income counts toward the income limit. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + employment_income: 30_000 + miscellaneous_income: 20_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_000 + snap: 0 + tanf: 0 + ct_ssp: 0 + households: + household: + members: [person1] + state_code: CT + output: + ct_ceap_countable_income: 50_000 + ct_ceap: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ct/dss/ceap/payment/ct_ceap_benefit_level.yaml b/policyengine_us/tests/policy/baseline/gov/states/ct/dss/ceap/payment/ct_ceap_benefit_level.yaml new file mode 100644 index 00000000000..979f3eba992 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ct/dss/ceap/payment/ct_ceap_benefit_level.yaml @@ -0,0 +1,42 @@ +# FY2026 benefit matrix and FY2027 allocation plan pages 7,10-11; prior-year FPG thresholds. +# Sources: +# - https://liheapch.acf.gov/docs/2026/benefits-matricies/CT_BenefitMatrix_Heat-Crisis_2026.pdf +# PDF pages 5-7,9-11,15 +# - https://portal.ct.gov/dss/-/media/departments-and-agencies/dss/winter-heating-assistance/09012026/ffy-27-liheap-allocation-plan.pdf#page=5 +# Prior-year FPG; 125% boundary 19,562.50, 200% boundary 31,300.00. +- name: Case 1, FY2026 inclusive poverty boundaries and no gaps. + period: 2026 + input: + state_code: [CT, CT, CT, CT, CT, CT, CT, CT] + heating_type: [NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, + NATURAL_GAS] + gas_expense: [1_000, 1_000, 1_000, 1_000, 1_000, 1_000, 1_000, 1_000] + ct_ceap_household_size: [1, 1, 1, 1, 1, 1, 1, 1] + ct_ceap_countable_income: [0, 19562.49, 19562.5, 19562.51, 31299.99, 31_300, 31300.01, 100_000] + output: + ct_ceap_benefit_level: [1, 1, 1, 2, 2, 2, 3, 3] + +# Prior-year FPG; 125% boundary 19,950.00, 200% boundary 31,920.00. +- name: Case 2, FY2027 inclusive poverty boundaries and no gaps. + period: 2027 + input: + state_code: [CT, CT, CT, CT, CT, CT, CT, CT] + heating_type: [NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, + NATURAL_GAS] + gas_expense: [1_000, 1_000, 1_000, 1_000, 1_000, 1_000, 1_000, 1_000] + ct_ceap_household_size: [1, 1, 1, 1, 1, 1, 1, 1] + ct_ceap_countable_income: [0, 19949.99, 19_950, 19950.01, 31919.99, 31_920, 31920.01, 100_000] + output: + ct_ceap_benefit_level: [1, 1, 1, 2, 2, 2, 3, 3] + +# 2025 two-person FPG is 15,650 + 5,500 = 21,150; multiply by 1.25 and 2. +- name: Case 3, two person family uses additional person FPG. + period: 2026 + input: + state_code: [CT, CT, CT, CT] + heating_type: [NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, NATURAL_GAS] + gas_expense: [1_000, 1_000, 1_000, 1_000] + ct_ceap_household_size: [2, 2, 2, 2] + ct_ceap_countable_income: [26437.5, 26437.51, 42_300, 42300.01] + output: + ct_ceap_benefit_level: [1, 2, 2, 3] diff --git a/policyengine_us/variables/gov/states/ct/dss/ceap/ct_ceap.py b/policyengine_us/variables/gov/states/ct/dss/ceap/ct_ceap.py new file mode 100644 index 00000000000..59728e202fc --- /dev/null +++ b/policyengine_us/variables/gov/states/ct/dss/ceap/ct_ceap.py @@ -0,0 +1,40 @@ +from policyengine_us.model_api import * + + +class ct_ceap(Variable): + value_type = float + entity = SPMUnit + label = "Connecticut Energy Assistance Program regular heating benefit" + unit = USD + definition_period = YEAR + defined_for = "ct_ceap_eligible" + # PDF pages 6,10-11,15 + reference = "https://portal.ct.gov/dss/-/media/departments-and-agencies/dss/winter-heating-assistance/09012026/ffy-27-liheap-allocation-plan.pdf#page=6" + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ct.dss.ceap.payment + # State-scoped helpers return zero on other-state rows in a mixed + # simulation. Keep all vectorized lookups valid before eligibility masks. + level = max_(spm_unit("ct_ceap_benefit_level", period), 1) + person = spm_unit.members + age = person("age", period) + qualified = person("is_citizen_or_legal_immigrant", period) & person( + "ct_ceap_household_member", period + ) + vulnerable = spm_unit.any( + qualified + & ( + (age >= p.vulnerable.elderly_age) + | (age < p.vulnerable.young_child_age) + | person("is_disabled", period) + ) + ) + basic = p.basic[level] + vulnerable * p.vulnerable.supplement + # Utility credits exceeding covered-season charges must be returned; + # delivered-fuel payments cover actual deliveries. Annual primary-fuel + # expense approximates covered-season cost and oil vendor pricing. + direct_payment = min_(basic, spm_unit("heating_expense", period)) + heat_in_rent = spm_unit("heat_expense_included_in_rent", period) + # Rental cash grants have no bill cap. Prior awards/moves, the separate + # SNAP nominal payment, crisis, weatherization and equipment are excluded. + return where(heat_in_rent, p.rental[level], direct_payment) diff --git a/policyengine_us/variables/gov/states/ct/dss/ceap/eligibility/ct_ceap_categorically_eligible.py b/policyengine_us/variables/gov/states/ct/dss/ceap/eligibility/ct_ceap_categorically_eligible.py new file mode 100644 index 00000000000..8672b1e54b0 --- /dev/null +++ b/policyengine_us/variables/gov/states/ct/dss/ceap/eligibility/ct_ceap_categorically_eligible.py @@ -0,0 +1,35 @@ +from policyengine_us.model_api import * + + +class ct_ceap_categorically_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Categorically eligible for Connecticut CEAP" + definition_period = YEAR + defined_for = StateCode.CT + # PDF pages 6-7,11 + reference = "https://portal.ct.gov/dss/-/media/departments-and-agencies/dss/winter-heating-assistance/09012026/ffy-27-liheap-allocation-plan.pdf#page=6" + + def formula(spm_unit, period, parameters): + # Positive annual receipt approximates receipt at application. + # Refugee Cash Assistance and means-tested VA receipt are unavailable; + # generic veterans_benefits does not establish VA eligibility. + person = spm_unit.members + member = person("ct_ceap_household_member", period) + ssi = spm_unit.sum(member * person("ssi", period, options=[ADD])) + # Remove SSP attributable to members outside the household from the + # household receipt, preserving a supplied household SSP total. The + # floor stops a supplied total below the excluded members' SSP from + # cancelling other receipt. + excluded_ssp = spm_unit.sum( + ~member * person("ct_ssp_person", period, options=[ADD]) + ) + ssp = max_(spm_unit("ct_ssp", period, options=[ADD]) - excluded_ssp, 0) + reported_ssi = spm_unit.any( + member & (add(person, period, ["receives_ssi"]) > 0) + ) + receipt = (add(spm_unit, period, ["snap", "tanf"]) + ssi + ssp > 0) | ( + reported_ssi + ) + heat_in_rent = spm_unit("heat_expense_included_in_rent", period) + return receipt & ~heat_in_rent diff --git a/policyengine_us/variables/gov/states/ct/dss/ceap/eligibility/ct_ceap_eligible.py b/policyengine_us/variables/gov/states/ct/dss/ceap/eligibility/ct_ceap_eligible.py new file mode 100644 index 00000000000..4587e68b5cb --- /dev/null +++ b/policyengine_us/variables/gov/states/ct/dss/ceap/eligibility/ct_ceap_eligible.py @@ -0,0 +1,27 @@ +from policyengine_us.model_api import * + + +class ct_ceap_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Eligible for Connecticut CEAP basic or rental heating assistance" + definition_period = YEAR + defined_for = StateCode.CT + reference = ( + # PDF pages 7,9,11,15 + "https://portal.ct.gov/dss/-/media/departments-and-agencies/dss/winter-heating-assistance/09012026/ffy-27-liheap-allocation-plan.pdf#page=7", + "https://www.law.cornell.edu/uscode/text/42/8624#b_2_B", + ) + + def formula(spm_unit, period, parameters): + size = spm_unit("ct_ceap_household_size", period) + income_eligible = spm_unit("ct_ceap_income_eligible", period) | spm_unit( + "ct_ceap_categorically_eligible", period + ) + heat_in_rent = spm_unit("heat_expense_included_in_rent", period) + expense = spm_unit("heating_expense", period) + heating_type = spm_unit("heating_type", period) + has_heat = heating_type != heating_type.possible_values.NONE + # Subsidized renters are not independently excluded. Heat-in-rent covers + # verified rental heating costs; landlord/account verification is assumed. + return (size > 0) & income_eligible & (heat_in_rent | (expense > 0)) & has_heat diff --git a/policyengine_us/variables/gov/states/ct/dss/ceap/eligibility/ct_ceap_household_member.py b/policyengine_us/variables/gov/states/ct/dss/ceap/eligibility/ct_ceap_household_member.py new file mode 100644 index 00000000000..4a17fb1f944 --- /dev/null +++ b/policyengine_us/variables/gov/states/ct/dss/ceap/eligibility/ct_ceap_household_member.py @@ -0,0 +1,17 @@ +from policyengine_us.model_api import * + + +class ct_ceap_household_member(Variable): + value_type = bool + entity = Person + label = "Connecticut CEAP household member" + definition_period = YEAR + defined_for = StateCode.CT + reference = "https://portal.ct.gov/dss/-/media/departments-and-agencies/dss/winter-heating-assistance/09012026/ffy-27-liheap-allocation-plan.pdf#page=5" + + def formula(person, period, parameters): + # Households exclude incarcerated people and foster children or adults. + # January status stands in for status at application. Boarders and + # residents of institutions of higher learning have no input. + month = period.first_month + return ~person("is_in_foster_care", month) & ~person("is_incarcerated", month) diff --git a/policyengine_us/variables/gov/states/ct/dss/ceap/eligibility/ct_ceap_household_size.py b/policyengine_us/variables/gov/states/ct/dss/ceap/eligibility/ct_ceap_household_size.py new file mode 100644 index 00000000000..ead6ca9ba51 --- /dev/null +++ b/policyengine_us/variables/gov/states/ct/dss/ceap/eligibility/ct_ceap_household_size.py @@ -0,0 +1,18 @@ +from policyengine_us.model_api import * + + +class ct_ceap_household_size(Variable): + value_type = int + entity = SPMUnit + label = "Connecticut CEAP household size" + definition_period = YEAR + defined_for = StateCode.CT + # PDF pages 5,9 + reference = "https://portal.ct.gov/dss/-/media/departments-and-agencies/dss/winter-heating-assistance/09012026/ffy-27-liheap-allocation-plan.pdf#page=5" + # The SPM unit approximates the common energy household. + + def formula(spm_unit, period, parameters): + person = spm_unit.members + qualified = person("is_citizen_or_legal_immigrant", period) + member = person("ct_ceap_household_member", period) + return spm_unit.sum(qualified & member) diff --git a/policyengine_us/variables/gov/states/ct/dss/ceap/eligibility/ct_ceap_income_eligible.py b/policyengine_us/variables/gov/states/ct/dss/ceap/eligibility/ct_ceap_income_eligible.py new file mode 100644 index 00000000000..5ffbc2331b6 --- /dev/null +++ b/policyengine_us/variables/gov/states/ct/dss/ceap/eligibility/ct_ceap_income_eligible.py @@ -0,0 +1,27 @@ +from policyengine_us.model_api import * +from policyengine_us.variables.gov.hhs.tax_unit_fpg import fpg + + +class ct_ceap_income_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Connecticut CEAP income eligible without categorical receipt" + definition_period = YEAR + defined_for = StateCode.CT + reference = ( + "https://portal.ct.gov/dss/-/media/departments-and-agencies/dss/winter-heating-assistance/09012026/ffy-27-liheap-allocation-plan.pdf#page=7", + "https://www.law.cornell.edu/uscode/text/42/8624#b_2_B", + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ct.dss.ceap.payment + p_hhs = parameters(period).gov.hhs.liheap + size = spm_unit("ct_ceap_household_size", period) + state_group = spm_unit.household("state_group_str", period) + guideline = fpg(size, state_group, period, parameters, year_lag=p.fpg_year_lag) + # Preserve the published ceiling and the strict federal protection + # where the SMI limit is lower for large households. + floor = np.round(guideline * p_hhs.fpg_floor, 2) + income = spm_unit("ct_ceap_countable_income", period) + limit = spm_unit("ct_ceap_income_limit", period) + return (income <= limit) | (income < floor) diff --git a/policyengine_us/variables/gov/states/ct/dss/ceap/eligibility/ct_ceap_income_limit.py b/policyengine_us/variables/gov/states/ct/dss/ceap/eligibility/ct_ceap_income_limit.py new file mode 100644 index 00000000000..2c8ae32aca1 --- /dev/null +++ b/policyengine_us/variables/gov/states/ct/dss/ceap/eligibility/ct_ceap_income_limit.py @@ -0,0 +1,30 @@ +from policyengine_us.model_api import * +from policyengine_us.variables.gov.hhs.hhs_smi import liheap_smi_limit + + +class ct_ceap_income_limit(Variable): + value_type = float + entity = SPMUnit + label = "Connecticut CEAP income limit" + unit = USD + definition_period = YEAR + defined_for = StateCode.CT + reference = ( + "https://liheapch.acf.gov/docs/2026/benefits-matricies/CT_BenefitMatrix_Heat-Crisis_2026.pdf", + "https://portal.ct.gov/dss/-/media/departments-and-agencies/dss/winter-heating-assistance/09012026/ffy-27-liheap-allocation-plan.pdf#page=7", + ) + + def formula(spm_unit, period, parameters): + size = spm_unit("ct_ceap_household_size", period) + state = spm_unit.household("state_code_str", period) + p = parameters(period) + # This order reproduces every published FY2026/FY2027 size 1-8 limit; + # the source prints the amounts but does not specify the rounding order. + amount = liheap_smi_limit( + size, + state, + p.gov.states.ct.dss.ceap.eligibility.smi_rate, + period, + parameters, + ) + return where(size > 0, amount, 0) diff --git a/policyengine_us/variables/gov/states/ct/dss/ceap/income/ct_ceap_countable_income.py b/policyengine_us/variables/gov/states/ct/dss/ceap/income/ct_ceap_countable_income.py new file mode 100644 index 00000000000..58834cf3e25 --- /dev/null +++ b/policyengine_us/variables/gov/states/ct/dss/ceap/income/ct_ceap_countable_income.py @@ -0,0 +1,43 @@ +from policyengine_us.model_api import * + + +class ct_ceap_countable_income(Variable): + value_type = float + entity = SPMUnit + label = "Connecticut CEAP countable income" + unit = USD + definition_period = YEAR + defined_for = StateCode.CT + reference = ( + # PDF pages 6-7 + "https://liheapch.acf.gov/docs/2026/state-plans/CT_Plan_2026.pdf#page=6", + # PDF pages 5,8-9 + "https://portal.ct.gov/dss/-/media/departments-and-agencies/dss/winter-heating-assistance/09012026/ffy-27-liheap-allocation-plan.pdf#page=5", + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ct.dss.ceap.income + person = spm_unit.members + # Annual inputs approximate the permitted 52-week assessment. Existing + # net business inputs are used without further business-cost deductions. + earned = 0 + for source in p.sources.earned: + earned = earned + max_(person(source, period), 0) + adult = person("age", period) >= p.earned_income_min_age + member = person("ct_ceap_household_member", period) + unearned = 0 + for source in p.sources.unearned: + unearned = unearned + max_(person(source, period), 0) + social_security = max_( + person("social_security", period) + - person("medicare_part_b_premium", period), + 0, + ) + # Nonqualified members' income counts in full. SSI, TFA and general + # assistance are excluded by the model plan's income checklist. + # Rental inputs stand in for nonnegative gross receipts. Excluded VA + # pension subtypes, in-kind support and AmeriCorps payments cannot be + # resolved by these existing income inputs. + return spm_unit.sum( + member * (where(adult, earned, 0) + unearned + social_security) + ) diff --git a/policyengine_us/variables/gov/states/ct/dss/ceap/payment/ct_ceap_benefit_level.py b/policyengine_us/variables/gov/states/ct/dss/ceap/payment/ct_ceap_benefit_level.py new file mode 100644 index 00000000000..fa25cbda36e --- /dev/null +++ b/policyengine_us/variables/gov/states/ct/dss/ceap/payment/ct_ceap_benefit_level.py @@ -0,0 +1,32 @@ +from policyengine_us.model_api import * +from policyengine_us.variables.gov.hhs.tax_unit_fpg import fpg + + +class ct_ceap_benefit_level(Variable): + value_type = int + entity = SPMUnit + label = "Connecticut CEAP benefit level" + definition_period = YEAR + defined_for = StateCode.CT + reference = ( + # PDF pages 7,10-11 + "https://portal.ct.gov/dss/-/media/departments-and-agencies/dss/winter-heating-assistance/09012026/ffy-27-liheap-allocation-plan.pdf#page=7", + "https://www.law.cornell.edu/uscode/text/42/8624#b_5", + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ct.dss.ceap.payment + size = spm_unit("ct_ceap_household_size", period) + group = spm_unit.household("state_group_str", period) + guideline = fpg(size, group, period, parameters, year_lag=p.fpg_year_lag) + income = spm_unit("ct_ceap_countable_income", period) + level = p.income_level.calc(income / guideline, right=True) + # Categorical households that fail the income test receive the last + # level (201% FPG to 60% SMI) even when large-family FPG thresholds + # would put them in a higher tier. Households the income test admits, + # including through the federal floor, keep their level whether or not + # they are categorical: 42 U.S.C. 8624(b)(5) bars differentiating them. + lowest_level = p.income_level.amounts[-1] + categorical = spm_unit("ct_ceap_categorically_eligible", period) + income_eligible = spm_unit("ct_ceap_income_eligible", period) + return where(categorical & ~income_eligible, lowest_level, level) diff --git a/source_conflicts/candidates.yaml b/source_conflicts/candidates.yaml index 7504c9712a5..10770cf9257 100644 --- a/source_conflicts/candidates.yaml +++ b/source_conflicts/candidates.yaml @@ -1965,6 +1965,103 @@ candidates: state: ruled note: 'Ruled in October 2026 to follow the statute; verify the applicable regulation version. Code not yet on main: co premium assistance formula, aca_ptc_slcsp.' +- id: us-ct:liheap-income-floor-vs-smi-limit + program: liheap + years: + from: 2026 + to: 2027 + type: federal-fiscal + question: Can Connecticut's 60% SMI CEAP limit exclude a very large household whose income is below the federal 110% + poverty-guideline floor? + sources: + - kind: statute + citation: 42 U.S.C. 8624(b)(2)(B) + url: https://www.law.cornell.edu/uscode/text/42/8624#b_2_B + - kind: plan + citation: Connecticut approved FFY2027 LIHEAP Allocation Plan, section IV.B, p.7 + url: https://portal.ct.gov/dss/-/media/departments-and-agencies/dss/winter-heating-assistance/09012026/ffy-27-liheap-allocation-plan.pdf#page=7 + readings: + statute: Income below 110% of the poverty guideline cannot by itself exclude the household. + other: The 60% SMI limit falls below that floor from 29 members in FY2026 and 28 in FY2027. + example: Thirty people with $190,000 exceed the $187,382 FY2026 limit but are below the $192,665 floor (2025 + guideline, one-year lag), so they keep the Level 1 basic benefit of $595. + pe_us: + follows: statute + code: + - policyengine_us/variables/gov/states/ct/dss/ceap/eligibility/ct_ceap_income_eligible.py + - policyengine_us/variables/gov/states/ct/dss/ceap/payment/ct_ceap_benefit_level.py + - policyengine_us/parameters/gov/hhs/liheap/fpg_floor.yaml + - policyengine_us/parameters/gov/states/ct/dss/ceap/payment/fpg_year_lag.yaml + prs: + - https://github.com/PolicyEngine/policyengine-us/pull/10611 + state: unreviewed + note: PE-US applies the floor, rounded to cents with the statute's strict "less than" (ct_ceap_income_eligible.py). The + benefit matrix note's Level 3 reaches only categorical households the income test would deny. A categorical + household the floor admits keeps its income level, because 42 U.S.C. 8624(b)(5) bars differentiating between + (b)(2)(A) and (b)(2)(B) households, so those thirty people get $595 with or without SNAP. +- id: us-ct:liheap-plan-income-checklist + program: liheap + years: + from: 2026 + to: 2027 + type: federal-fiscal + question: Do SSI, TFA, general assistance and a minor's earnings count for CEAP, as the allocation plans' income + definition can be read, or stay out, as the FY2026 plan's section 1.9 check boxes leave them? + sources: + - kind: plan + citation: Connecticut FY2026 LIHEAP State Plan, section 1.9, pp.6-7 + url: https://liheapch.acf.gov/docs/2026/state-plans/CT_Plan_2026.pdf#page=6 + - kind: plan + citation: Connecticut approved FFY2027 LIHEAP Allocation Plan, section III, p.5 + url: https://portal.ct.gov/dss/-/media/departments-and-agencies/dss/winter-heating-assistance/09012026/ffy-27-liheap-allocation-plan.pdf#page=5 + readings: + plan: Plan 1.9 leaves SSI, General Assistance, TANF, "Other" and "Earned income of a child under the age of 18" + unchecked. + other: Section III of both allocation plans counts "Gross salaries/wages" with no age exception and "governmental + assistance not otherwise excluded as income". + example: A parent aged 40 with wages of $20,000 and a child aged 17 with wages of $8,000 is at 95% of the 2025 + guideline for two, Level 1 and $595, under plan 1.9, and at 132%, Level 2 and $445, if the child's wages count. + pe_us: + follows: gap-fill + code: + - policyengine_us/parameters/gov/states/ct/dss/ceap/income/sources/earned.yaml + - policyengine_us/parameters/gov/states/ct/dss/ceap/income/sources/unearned.yaml + - policyengine_us/variables/gov/states/ct/dss/ceap/income/ct_ceap_countable_income.py + prs: + - https://github.com/PolicyEngine/policyengine-us/pull/10611 + state: unreviewed + note: PE-US follows plan 1.9, the specific list, and carries it into FY2027, which has no model plan. +- id: us-ct:liheap-state-supplement-income + program: liheap + years: + from: 2026 + to: 2027 + type: federal-fiscal + question: Does the Connecticut State Supplement count as CEAP income under the allocation plans' governmental-assistance + clause, or stay out, with the FY2026 plan's section 1.9 "Other" box unchecked? + sources: + - kind: plan + citation: Connecticut FY2026 LIHEAP State Plan, section 1.9, pp.6-7 + url: https://liheapch.acf.gov/docs/2026/state-plans/CT_Plan_2026.pdf#page=6 + - kind: plan + citation: Connecticut approved FFY2027 LIHEAP Allocation Plan, section III, p.5 + url: https://portal.ct.gov/dss/-/media/departments-and-agencies/dss/winter-heating-assistance/09012026/ffy-27-liheap-allocation-plan.pdf#page=5 + readings: + plan: Plan 1.9 leaves General Assistance, SSI, TANF and "Other" unchecked and does not name the State Supplement. + other: Section III of both allocation plans counts "governmental assistance not otherwise excluded as income" and + does not name the State Supplement either. + example: A disabled person aged 50 with a pension of $18,000, a $2,400 State Supplement and a $1,000 gas bill is at 115% + of the 2025 guideline, Level 1 and $645, with the supplement out, and at 130%, Level 2 and $495, with it counted. + pe_us: + follows: gap-fill + code: + - policyengine_us/parameters/gov/states/ct/dss/ceap/income/sources/unearned.yaml + - policyengine_us/variables/gov/states/ct/dss/ceap/income/ct_ceap_countable_income.py + prs: + - https://github.com/PolicyEngine/policyengine-us/pull/10611 + state: ruled + note: 'Ruled 2026-11-02 by the PR author in the pre-filing review of this PR, item CT-S3: keep the State Supplement out + of countable income. Neither document names it, and plan 1.9 is the specific list.' - id: us-dc:eitc-no-tin-child-schedule-before-2023 program: income-tax years: