diff --git a/changelog.d/head-start-net-income-gate.added.md b/changelog.d/head-start-net-income-gate.added.md new file mode 100644 index 00000000000..a63e5498d34 --- /dev/null +++ b/changelog.d/head-start-net-income-gate.added.md @@ -0,0 +1 @@ +Gate Head Start and Early Head Start behind gov.simulation.include_head_start_benefits_in_net_income (default false), so per-enrollee program values no longer enter household net income by default, mirroring the health benefits inclusion switch. diff --git a/policyengine_us/parameters/gov/household/household_benefits.yaml b/policyengine_us/parameters/gov/household/household_benefits.yaml index ab3e4f76b71..593be7c3310 100644 --- a/policyengine_us/parameters/gov/household/household_benefits.yaml +++ b/policyengine_us/parameters/gov/household/household_benefits.yaml @@ -19,8 +19,7 @@ values: - educational_assistance - financial_assistance - survivor_benefits - - head_start - - early_head_start + - household_head_start_benefits # One-time energy relief payments. # Paid at the same time as the Alaska Permanent Fund Dividend, # which is part of IRS gross income. @@ -49,8 +48,7 @@ values: - educational_assistance - financial_assistance - survivor_benefits - - head_start - - early_head_start + - household_head_start_benefits # Contributed. - basic_income - spm_unit_capped_housing_subsidy diff --git a/policyengine_us/parameters/gov/household/household_head_start_benefits.yaml b/policyengine_us/parameters/gov/household/household_head_start_benefits.yaml new file mode 100644 index 00000000000..18ea4cb0c83 --- /dev/null +++ b/policyengine_us/parameters/gov/household/household_head_start_benefits.yaml @@ -0,0 +1,10 @@ +description: The government counts these Head Start program sources as household benefits. +values: + 2022-01-01: + - head_start + - early_head_start + +metadata: + unit: list + period: year + label: Household Head Start benefits diff --git a/policyengine_us/parameters/gov/simulation/include_head_start_benefits_in_net_income.yaml b/policyengine_us/parameters/gov/simulation/include_head_start_benefits_in_net_income.yaml new file mode 100644 index 00000000000..0a0b56241e9 --- /dev/null +++ b/policyengine_us/parameters/gov/simulation/include_head_start_benefits_in_net_income.yaml @@ -0,0 +1,6 @@ +description: Whether to include Head Start benefits in net income. +values: + 0000-01-01: false +metadata: + unit: bool + label: Include Head Start benefits in net income diff --git a/policyengine_us/reforms/congress/tlaib/boost/boost_middle_class_tax_credit.py b/policyengine_us/reforms/congress/tlaib/boost/boost_middle_class_tax_credit.py index 62dc8fa45ee..f56b87f3bc9 100644 --- a/policyengine_us/reforms/congress/tlaib/boost/boost_middle_class_tax_credit.py +++ b/policyengine_us/reforms/congress/tlaib/boost/boost_middle_class_tax_credit.py @@ -74,6 +74,7 @@ def formula(household, period, parameters): "basic_income", "spm_unit_capped_housing_subsidy", "household_state_benefits", + "household_head_start_benefits", ] if parameters(period).gov.hud.abolition: BENEFITS = [ diff --git a/policyengine_us/reforms/congress/tlaib/end_child_poverty_act.py b/policyengine_us/reforms/congress/tlaib/end_child_poverty_act.py index f451389f505..f24d8e49ffc 100644 --- a/policyengine_us/reforms/congress/tlaib/end_child_poverty_act.py +++ b/policyengine_us/reforms/congress/tlaib/end_child_poverty_act.py @@ -110,6 +110,7 @@ def formula(household, period, parameters): "basic_income", "spm_unit_capped_housing_subsidy", "household_state_benefits", + "household_head_start_benefits", "ecpa_child_benefit", ] if parameters(period).gov.hud.abolition: diff --git a/policyengine_us/tests/policy/baseline/household/income/household/household_benefits.yaml b/policyengine_us/tests/policy/baseline/household/income/household/household_benefits.yaml index 8b97c7d2f53..545b50217f6 100644 --- a/policyengine_us/tests/policy/baseline/household/income/household/household_benefits.yaml +++ b/policyengine_us/tests/policy/baseline/household/income/household/household_benefits.yaml @@ -57,3 +57,33 @@ household_health_benefits: 0 output: household_benefits: 0 + +- name: Head Start values are excluded from household benefits by default. + period: 2024 + input: + age: 30 + head_start: 8_000 + early_head_start: 21_000 + child_support_received: 0 + workers_compensation: 0 + educational_assistance: 0 + financial_assistance: 0 + survivor_benefits: 0 + social_security: 0 + ssi: 0 + tanf: 0 + unemployment_compensation: 0 + snap: 0 + wic: 0 + free_school_meals: 0 + reduced_price_school_meals: 0 + acp: 0 + ebb: 0 + basic_income: 0 + spm_unit_capped_housing_subsidy: 0 + household_state_benefits: 0 + commodity_supplemental_food_program: 0 + household_health_benefits: 0 + output: + household_head_start_benefits: 0 + household_benefits: 0 diff --git a/policyengine_us/tests/policy/baseline/household/income/household/household_head_start_benefits.yaml b/policyengine_us/tests/policy/baseline/household/income/household/household_head_start_benefits.yaml new file mode 100644 index 00000000000..5360f356863 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/household/income/household/household_head_start_benefits.yaml @@ -0,0 +1,85 @@ +- name: Case 1, flag off excludes Head Start values from household benefits. + period: 2026 + absolute_error_margin: 0.01 + input: + gov.simulation.include_head_start_benefits_in_net_income: false + head_start: 8_000 + early_head_start: 21_000 + snap: 0 + output: + household_head_start_benefits: 0 + household_benefits: 0 + +- name: Case 2, flag on includes Head Start and Early Head Start values. + period: 2026 + absolute_error_margin: 0.01 + input: + gov.simulation.include_head_start_benefits_in_net_income: true + head_start: 8_000 + early_head_start: 21_000 + snap: 0 + output: + household_head_start_benefits: 29_000 + household_benefits: 29_000 + +- name: Case 3, flag on composes through the pre-2024 household_benefits bracket. + period: 2023 + absolute_error_margin: 0.01 + input: + gov.simulation.include_head_start_benefits_in_net_income: true + head_start: 8_000 + early_head_start: 21_000 + snap: 0 + acp: 0 + ebb: 0 + output: + household_head_start_benefits: 29_000 + household_benefits: 29_000 + +- name: Case 4, the Head Start flag does not activate health benefits. + period: 2026 + absolute_error_margin: 0.01 + input: + gov.simulation.include_head_start_benefits_in_net_income: true + head_start: 8_000 + medicaid_cost: 500 + chip: 300 + snap: 0 + output: + household_head_start_benefits: 8_000 + household_health_benefits: 0 + household_benefits: 8_000 + +- name: Case 5, the health flag does not activate Head Start benefits. + period: 2026 + absolute_error_margin: 0.01 + input: + gov.simulation.include_health_benefits_in_net_income: true + head_start: 8_000 + early_head_start: 21_000 + medicaid_cost: 500 + snap: 0 + output: + household_health_benefits: 500 + household_head_start_benefits: 0 + household_benefits: 500 + +- name: Case 6, per-person values aggregate to the household level. + period: 2026 + absolute_error_margin: 0.01 + input: + gov.simulation.include_head_start_benefits_in_net_income: true + people: + parent: + age: 30 + child1: + age: 4 + head_start: 8_000 + child2: + age: 1 + early_head_start: 21_000 + households: + household: + members: [parent, child1, child2] + output: + household_head_start_benefits: 29_000 diff --git a/policyengine_us/tests/policy/baseline/household/income/household/household_net_income.yaml b/policyengine_us/tests/policy/baseline/household/income/household/household_net_income.yaml index b6aea7ef3cf..bad1d7579a7 100644 --- a/policyengine_us/tests/policy/baseline/household/income/household/household_net_income.yaml +++ b/policyengine_us/tests/policy/baseline/household/income/household/household_net_income.yaml @@ -64,3 +64,70 @@ household_health_costs: 0 output: household_net_income: 0 + +- name: Head Start values are excluded from household net income by default. + period: 2024 + input: + age: 30 + head_start: 8_000 + early_head_start: 21_000 + household_market_income: 0 + child_support_received: 0 + workers_compensation: 0 + educational_assistance: 0 + financial_assistance: 0 + survivor_benefits: 0 + social_security: 0 + ssi: 0 + tanf: 0 + unemployment_compensation: 0 + snap: 0 + wic: 0 + free_school_meals: 0 + reduced_price_school_meals: 0 + acp: 0 + ebb: 0 + basic_income: 0 + spm_unit_capped_housing_subsidy: 0 + household_state_benefits: 0 + commodity_supplemental_food_program: 0 + household_health_benefits: 0 + household_refundable_tax_credits: 0 + household_tax_before_refundable_credits: 0 + household_health_costs: 0 + output: + household_net_income: 0 + +- name: Head Start values are included in household net income when the switch is on. + period: 2024 + input: + gov.simulation.include_head_start_benefits_in_net_income: true + age: 30 + head_start: 8_000 + early_head_start: 21_000 + household_market_income: 0 + child_support_received: 0 + workers_compensation: 0 + educational_assistance: 0 + financial_assistance: 0 + survivor_benefits: 0 + social_security: 0 + ssi: 0 + tanf: 0 + unemployment_compensation: 0 + snap: 0 + wic: 0 + free_school_meals: 0 + reduced_price_school_meals: 0 + acp: 0 + ebb: 0 + basic_income: 0 + spm_unit_capped_housing_subsidy: 0 + household_state_benefits: 0 + commodity_supplemental_food_program: 0 + household_health_benefits: 0 + household_refundable_tax_credits: 0 + household_tax_before_refundable_credits: 0 + household_health_costs: 0 + output: + household_net_income: 29_000 diff --git a/policyengine_us/tests/policy/reform/ecpa_head_start_benefits_composition.yaml b/policyengine_us/tests/policy/reform/ecpa_head_start_benefits_composition.yaml new file mode 100644 index 00000000000..797d3424607 --- /dev/null +++ b/policyengine_us/tests/policy/reform/ecpa_head_start_benefits_composition.yaml @@ -0,0 +1,41 @@ +# Head Start values compose into ECPA's static household_benefits list when +# gov.simulation.include_head_start_benefits_in_net_income is on. +# +# NOTE: This lives under tests/policy/reform (one subprocess per file) rather +# than contrib/congress/tlaib because the congress structural batch runs each +# proposal directory in a single process at its memory ceiling; the extra +# reformed-system variant this case requires pushed the tlaib batch past the +# CI runner's RAM and stalled the job. + +- name: Head Start values compose into ECPA household benefits when the inclusion switch is on. + period: 2023 + reforms: policyengine_us.reforms.congress.tlaib.end_child_poverty_act.end_child_poverty_act + input: + gov.contrib.congress.tlaib.end_child_poverty_act.in_effect: true + gov.simulation.include_head_start_benefits_in_net_income: true + age: 30 + head_start: 8_000 + early_head_start: 21_000 + social_security: 0 + ssi: 0 + snap: 0 + wic: 0 + free_school_meals: 0 + reduced_price_school_meals: 0 + child_support_received: 0 + workers_compensation: 0 + educational_assistance: 0 + financial_assistance: 0 + survivor_benefits: 0 + acp: 0 + ebb: 0 + tanf: 0 + high_efficiency_electric_home_rebate: 0 + residential_efficiency_electrification_rebate: 0 + unemployment_compensation: 0 + basic_income: 0 + spm_unit_capped_housing_subsidy: 0 + household_state_benefits: 0 + output: + household_head_start_benefits: 29_000 + household_benefits: 29_000 diff --git a/policyengine_us/variables/household/income/household/household_head_start_benefits.py b/policyengine_us/variables/household/income/household/household_head_start_benefits.py new file mode 100644 index 00000000000..1e7a74016d1 --- /dev/null +++ b/policyengine_us/variables/household/income/household/household_head_start_benefits.py @@ -0,0 +1,24 @@ +from policyengine_us.model_api import * + + +class household_head_start_benefits(Variable): + value_type = float + entity = Household + label = "Household Head Start benefits" + unit = USD + definition_period = YEAR + documentation = ( + "Annual Head Start and Early Head Start value included in " + "household_benefits only when " + "gov.simulation.include_head_start_benefits_in_net_income is " + "enabled. The programs are valued at per-enrollee cost and their " + "take-up flags default to true, so datasets without seeded " + "enrollment flags value every eligible person at full cost." + ) + + def formula(household, period, parameters): + p = parameters(period) + if p.gov.simulation.include_head_start_benefits_in_net_income: + return add(household, period, p.gov.household.household_head_start_benefits) + else: + return 0