diff --git a/obbba_district_impacts/Congressional-Hackathon-2025 b/obbba_district_impacts/Congressional-Hackathon-2025
new file mode 160000
index 0000000..3f6d05e
--- /dev/null
+++ b/obbba_district_impacts/Congressional-Hackathon-2025
@@ -0,0 +1 @@
+Subproject commit 3f6d05e76400c6e396a3a4eddd34a7b3f6919fc3
diff --git a/us/debug_income_security_reforms.ipynb b/us/debug_income_security_reforms.ipynb
new file mode 100644
index 0000000..00d9386
--- /dev/null
+++ b/us/debug_income_security_reforms.ipynb
@@ -0,0 +1,1147 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Debug Tlaib Income Security Package Reforms\n",
+ "\n",
+ "Testing specific household scenarios to identify issues with reform impacts."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "c:\\Users\\dtsax\\envs\\pe\\Lib\\site-packages\\tqdm\\auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n",
+ " from .autonotebook import tqdm as notebook_tqdm\n"
+ ]
+ }
+ ],
+ "source": [
+ "import pandas as pd\n",
+ "from policyengine_us import Simulation\n",
+ "\n",
+ "pd.set_option('display.float_format', '{:.2f}'.format)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Helper Functions"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def create_situation_baby_bonus():\n",
+ " \"\"\"Single parent with newborn (under 1), $50,000 income\"\"\"\n",
+ " return {\n",
+ " \"people\": {\n",
+ " \"parent\": {\n",
+ " \"age\": {\"2026\": 30},\n",
+ " \"employment_income\": {\"2026\": 50_000},\n",
+ " },\n",
+ " \"baby\": {\n",
+ " \"age\": {\"2026\": 0},\n",
+ " },\n",
+ " },\n",
+ " \"families\": {\"family\": {\"members\": [\"parent\", \"baby\"]}},\n",
+ " \"marital_units\": {\"marital_unit\": {\"members\": [\"parent\"]}},\n",
+ " \"tax_units\": {\"tax_unit\": {\"members\": [\"parent\", \"baby\"]}},\n",
+ " \"spm_units\": {\"spm_unit\": {\"members\": [\"parent\", \"baby\"]}},\n",
+ " \"households\": {\"household\": {\"members\": [\"parent\", \"baby\"]}},\n",
+ " }\n",
+ "\n",
+ "def create_situation_ecpa():\n",
+ " \"\"\"Married, three kids (6, 18, 19), $50,000 income\"\"\"\n",
+ " return {\n",
+ " \"people\": {\n",
+ " \"adult1\": {\n",
+ " \"age\": {\"2026\": 40},\n",
+ " \"employment_income\": {\"2026\": 50_000},\n",
+ " },\n",
+ " \"adult2\": {\n",
+ " \"age\": {\"2026\": 38},\n",
+ " },\n",
+ " \"child1\": {\n",
+ " \"age\": {\"2026\": 6},\n",
+ " },\n",
+ " \"child2\": {\n",
+ " \"age\": {\"2026\": 18},\n",
+ " },\n",
+ " \"child3\": {\n",
+ " \"age\": {\"2026\": 19},\n",
+ " },\n",
+ " },\n",
+ " \"families\": {\"family\": {\"members\": [\"adult1\", \"adult2\", \"child1\", \"child2\", \"child3\"]}},\n",
+ " \"marital_units\": {\"marital_unit\": {\"members\": [\"adult1\", \"adult2\"]}},\n",
+ " \"tax_units\": {\"tax_unit\": {\"members\": [\"adult1\", \"adult2\", \"child1\", \"child2\", \"child3\"]}},\n",
+ " \"spm_units\": {\"spm_unit\": {\"members\": [\"adult1\", \"adult2\", \"child1\", \"child2\", \"child3\"]}},\n",
+ " \"households\": {\"household\": {\"members\": [\"adult1\", \"adult2\", \"child1\", \"child2\", \"child3\"]}},\n",
+ " }\n",
+ "\n",
+ "def create_situation_boost():\n",
+ " \"\"\"Single person, $100,000 income\"\"\"\n",
+ " return {\n",
+ " \"people\": {\n",
+ " \"adult\": {\n",
+ " \"age\": {\"2026\": 35},\n",
+ " \"employment_income\": {\"2026\": 100_000},\n",
+ " },\n",
+ " },\n",
+ " \"families\": {\"family\": {\"members\": [\"adult\"]}},\n",
+ " \"marital_units\": {\"marital_unit\": {\"members\": [\"adult\"]}},\n",
+ " \"tax_units\": {\"tax_unit\": {\"members\": [\"adult\"]}},\n",
+ " \"spm_units\": {\"spm_unit\": {\"members\": [\"adult\"]}},\n",
+ " \"households\": {\"household\": {\"members\": [\"adult\"]}},\n",
+ " }\n",
+ "\n",
+ "def create_situation_combined():\n",
+ " \"\"\"Married, three kids (newborn, 18, 19), $100,000 income\"\"\"\n",
+ " return {\n",
+ " \"people\": {\n",
+ " \"adult1\": {\n",
+ " \"age\": {\"2026\": 40},\n",
+ " \"employment_income\": {\"2026\": 100_000},\n",
+ " },\n",
+ " \"adult2\": {\n",
+ " \"age\": {\"2026\": 38},\n",
+ " },\n",
+ " \"baby\": {\n",
+ " \"age\": {\"2026\": 0},\n",
+ " },\n",
+ " \"child2\": {\n",
+ " \"age\": {\"2026\": 18},\n",
+ " },\n",
+ " \"child3\": {\n",
+ " \"age\": {\"2026\": 19},\n",
+ " },\n",
+ " },\n",
+ " \"families\": {\"family\": {\"members\": [\"adult1\", \"adult2\", \"baby\", \"child2\", \"child3\"]}},\n",
+ " \"marital_units\": {\"marital_unit\": {\"members\": [\"adult1\", \"adult2\"]}},\n",
+ " \"tax_units\": {\"tax_unit\": {\"members\": [\"adult1\", \"adult2\", \"baby\", \"child2\", \"child3\"]}},\n",
+ " \"spm_units\": {\"spm_unit\": {\"members\": [\"adult1\", \"adult2\", \"baby\", \"child2\", \"child3\"]}},\n",
+ " \"households\": {\"household\": {\"members\": [\"adult1\", \"adult2\", \"baby\", \"child2\", \"child3\"]}},\n",
+ " }\n",
+ "\n",
+ "def test_scenario(situation, name, reform_params=None):\n",
+ " \"\"\"Test a scenario with baseline and reform\"\"\"\n",
+ " print(f\"\\n{'='*60}\")\n",
+ " print(f\"Testing: {name}\")\n",
+ " print(f\"{'='*60}\")\n",
+ " \n",
+ " # Baseline\n",
+ " baseline = Simulation(situation=situation)\n",
+ " \n",
+ " # Reform\n",
+ " if reform_params is None:\n",
+ " reform_params = {}\n",
+ " \n",
+ " reformed = Simulation(\n",
+ " situation=situation,\n",
+ " reform=reform_params\n",
+ " )\n",
+ " \n",
+ " # Standard variables that exist in both baseline and reform\n",
+ " standard_variables = [\n",
+ " # Income components\n",
+ " \"employment_income\",\n",
+ " \"adjusted_gross_income\",\n",
+ " \n",
+ " # Standard tax credits (check if affected)\n",
+ " \"income_tax_before_refundable_credits\",\n",
+ " \"income_tax_non_refundable_credits\",\n",
+ " \"non_refundable_ctc\",\n",
+ " \"income_tax_refundable_credits\",\n",
+ " \"refundable_ctc\",\n",
+ " \"eitc\",\n",
+ " \"cdcc\",\n",
+ " \"income_tax\",\n",
+ " \n",
+ " # Other benefit programs (check for unintended changes)\n",
+ " \"snap\",\n",
+ " \"wic\",\n",
+ " \"tanf\",\n",
+ " \"social_security\",\n",
+ " \"ssi\",\n",
+ " \"unemployment_compensation\",\n",
+ " \"free_school_meals\",\n",
+ " \"reduced_price_school_meals\",\n",
+ " \n",
+ " # Aggregated outcomes\n",
+ " \"household_benefits\",\n",
+ " \"household_tax_before_refundable_credits\",\n",
+ " \"household_refundable_tax_credits\",\n",
+ " \"household_net_income\",\n",
+ " ]\n",
+ " \n",
+ " # Reform-specific variables (only exist in reform)\n",
+ " reform_variables = [\n",
+ " \"baby_bonus_act_payment\",\n",
+ " \"boost_act_payment\",\n",
+ " \"boost_act_tax\",\n",
+ " \"ecpa_child_benefit\",\n",
+ " \"ecpa_adult_dependent_credit\",\n",
+ " \"ecpa_filer_credit\",\n",
+ " ]\n",
+ " \n",
+ " results = []\n",
+ " \n",
+ " # Calculate standard variables\n",
+ " for var in standard_variables:\n",
+ " try:\n",
+ " base_val = baseline.calculate(var, \"2026\")[0]\n",
+ " reform_val = reformed.calculate(var, \"2026\")[0]\n",
+ " diff = reform_val - base_val\n",
+ " \n",
+ " results.append({\n",
+ " \"Variable\": var,\n",
+ " \"Baseline\": base_val,\n",
+ " \"Reform\": reform_val,\n",
+ " \"Change\": diff\n",
+ " })\n",
+ " except Exception as e:\n",
+ " results.append({\n",
+ " \"Variable\": var,\n",
+ " \"Baseline\": \"ERROR\",\n",
+ " \"Reform\": \"ERROR\",\n",
+ " \"Change\": str(e)[:50]\n",
+ " })\n",
+ " \n",
+ " # Calculate reform-specific variables (baseline = 0)\n",
+ " for var in reform_variables:\n",
+ " try:\n",
+ " reform_val = reformed.calculate(var, \"2026\")[0]\n",
+ " results.append({\n",
+ " \"Variable\": var,\n",
+ " \"Baseline\": 0,\n",
+ " \"Reform\": reform_val,\n",
+ " \"Change\": reform_val\n",
+ " })\n",
+ " except Exception as e:\n",
+ " # Variable doesn't exist in this reform configuration\n",
+ " pass\n",
+ " \n",
+ " df = pd.DataFrame(results)\n",
+ " \n",
+ " # Only show rows with non-zero baseline or reform values\n",
+ " df_nonzero = df[\n",
+ " ((df[\"Baseline\"] != 0) & (df[\"Baseline\"] != \"ERROR\")) | \n",
+ " ((df[\"Reform\"] != 0) & (df[\"Reform\"] != \"ERROR\"))\n",
+ " ]\n",
+ " \n",
+ " print(\"\\n=== NON-ZERO VALUES ===\")\n",
+ " print(df_nonzero.to_string(index=False))\n",
+ " \n",
+ " # Show rows with changes\n",
+ " df_changes = df[\n",
+ " (df[\"Change\"] != 0) & (df[\"Change\"] != \"ERROR\")\n",
+ " ]\n",
+ " print(\"\\n=== VALUES THAT CHANGED ===\")\n",
+ " print(df_changes.to_string(index=False))\n",
+ " \n",
+ " return df"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Test 1: Baby Bonus (Single Parent with Newborn, $50k)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n",
+ "============================================================\n",
+ "Testing: Baby Bonus: Single parent with newborn, $50k\n",
+ "============================================================\n",
+ "\n",
+ "=== NON-ZERO VALUES ===\n",
+ " Variable Baseline Reform Change\n",
+ " employment_income 50000.00 50000.00 0.00\n",
+ " adjusted_gross_income 50000.00 50000.00 0.00\n",
+ " income_tax_before_refundable_credits 548.00 548.00 0.00\n",
+ " income_tax_non_refundable_credits 2200.00 2200.00 0.00\n",
+ " non_refundable_ctc 2200.00 2200.00 0.00\n",
+ " income_tax_refundable_credits 246.63 246.63 0.00\n",
+ " eitc 246.63 246.63 0.00\n",
+ " income_tax 301.37 301.37 0.00\n",
+ " household_benefits 2186.02 4186.02 2000.00\n",
+ "household_tax_before_refundable_credits 4373.00 4373.00 0.00\n",
+ " household_refundable_tax_credits 246.63 246.63 0.00\n",
+ " household_net_income 48059.65 50059.65 2000.00\n",
+ "\n",
+ "=== VALUES THAT CHANGED ===\n",
+ " Variable Baseline Reform Change\n",
+ " household_benefits 2186.02 4186.02 2000.00\n",
+ "household_net_income 48059.65 50059.65 2000.00\n"
+ ]
+ }
+ ],
+ "source": [
+ "baby_bonus_reform = {\n",
+ " \"gov.contrib.congress.tlaib.income_security_package.baby_bonus_act.in_effect\": {\n",
+ " \"2026-01-01.2100-12-31\": True\n",
+ " }\n",
+ "}\n",
+ "\n",
+ "df_baby = test_scenario(\n",
+ " create_situation_baby_bonus(),\n",
+ " \"Baby Bonus: Single parent with newborn, $50k\",\n",
+ " baby_bonus_reform\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Test 2: ECPA (Married, 3 Kids Ages 6, 18, 19, $50k)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n",
+ "============================================================\n",
+ "Testing: ECPA: Married, 3 kids (6, 18, 19), $50k\n",
+ "============================================================\n",
+ "\n",
+ "=== NON-ZERO VALUES ===\n",
+ " Variable Baseline Reform Change\n",
+ " employment_income 50000.00 50000.00 0.00\n",
+ " adjusted_gross_income 50000.00 50000.00 0.00\n",
+ " income_tax_before_refundable_credits 0.00 1780.00 1780.00\n",
+ " income_tax_non_refundable_credits 1780.00 0.00 -1780.00\n",
+ " non_refundable_ctc 1780.00 1780.00 0.00\n",
+ " income_tax_refundable_credits 4755.66 1600.00 -3155.66\n",
+ " refundable_ctc 1420.00 1420.00 0.00\n",
+ " eitc 3335.66 3335.66 0.00\n",
+ " income_tax -4755.66 180.00 4935.66\n",
+ " snap 3221.75 3221.75 0.00\n",
+ " free_school_meals 1130.96 1130.96 0.00\n",
+ " household_benefits 4352.72 15612.72 11260.00\n",
+ "household_tax_before_refundable_credits 3825.00 5605.00 1780.00\n",
+ " household_refundable_tax_credits 4755.66 1600.00 -3155.66\n",
+ " household_net_income 55283.38 61607.72 6324.34\n",
+ " ecpa_filer_credit 0.00 900.00 900.00\n",
+ "\n",
+ "=== VALUES THAT CHANGED ===\n",
+ " Variable Baseline Reform Change\n",
+ " income_tax_before_refundable_credits 0.00 1780.00 1780.00\n",
+ " income_tax_non_refundable_credits 1780.00 0.00 -1780.00\n",
+ " income_tax_refundable_credits 4755.66 1600.00 -3155.66\n",
+ " income_tax -4755.66 180.00 4935.66\n",
+ " household_benefits 4352.72 15612.72 11260.00\n",
+ "household_tax_before_refundable_credits 3825.00 5605.00 1780.00\n",
+ " household_refundable_tax_credits 4755.66 1600.00 -3155.66\n",
+ " household_net_income 55283.38 61607.72 6324.34\n",
+ " ecpa_filer_credit 0.00 900.00 900.00\n"
+ ]
+ }
+ ],
+ "source": [
+ "ecpa_reform = {\n",
+ " \"gov.contrib.congress.tlaib.income_security_package.end_child_poverty_act.in_effect\": {\n",
+ " \"2026-01-01.2100-12-31\": True\n",
+ " }\n",
+ "}\n",
+ "\n",
+ "df_ecpa = test_scenario(\n",
+ " create_situation_ecpa(),\n",
+ " \"ECPA: Married, 3 kids (6, 18, 19), $50k\",\n",
+ " ecpa_reform\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Test 3: BOOST (Single Person, $100k)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n",
+ "============================================================\n",
+ "Testing: BOOST: Single person, $100k\n",
+ "============================================================\n",
+ "\n",
+ "=== NON-ZERO VALUES ===\n",
+ " Variable Baseline Reform Change\n",
+ " employment_income 100000.00 100000.00 0.00\n",
+ " adjusted_gross_income 100000.00 100000.00 0.00\n",
+ " income_tax_before_refundable_credits 13170.00 13170.00 0.00\n",
+ " income_tax 13170.00 14920.00 1750.00\n",
+ " household_benefits 0.00 3000.00 3000.00\n",
+ "household_tax_before_refundable_credits 25810.07 27560.07 1750.00\n",
+ " household_net_income 74189.94 75439.94 1250.00\n",
+ " boost_act_payment 0.00 3000.00 3000.00\n",
+ " boost_act_tax 0.00 1750.00 1750.00\n",
+ "\n",
+ "=== VALUES THAT CHANGED ===\n",
+ " Variable Baseline Reform Change\n",
+ " income_tax 13170.00 14920.00 1750.00\n",
+ " household_benefits 0.00 3000.00 3000.00\n",
+ "household_tax_before_refundable_credits 25810.07 27560.07 1750.00\n",
+ " household_net_income 74189.94 75439.94 1250.00\n",
+ " boost_act_payment 0.00 3000.00 3000.00\n",
+ " boost_act_tax 0.00 1750.00 1750.00\n"
+ ]
+ }
+ ],
+ "source": [
+ "boost_reform = {\n",
+ " \"gov.contrib.congress.tlaib.income_security_package.boost_act.in_effect\": {\n",
+ " \"2026-01-01.2100-12-31\": True\n",
+ " }\n",
+ "}\n",
+ "\n",
+ "df_boost = test_scenario(\n",
+ " create_situation_boost(),\n",
+ " \"BOOST: Single person, $100k\",\n",
+ " boost_reform\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Test 4: Combined (Married, 3 Kids including Newborn, $100k)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n",
+ "============================================================\n",
+ "Testing: Combined: Married, 3 kids (newborn, 18, 19), $100k\n",
+ "============================================================\n",
+ "\n",
+ "=== NON-ZERO VALUES ===\n",
+ " Variable Baseline Reform Change\n",
+ " employment_income 100000.00 100000.00 0.00\n",
+ " adjusted_gross_income 100000.00 100000.00 0.00\n",
+ " income_tax_before_refundable_credits 4440.00 7640.00 3200.00\n",
+ " income_tax_non_refundable_credits 3200.00 0.00 -3200.00\n",
+ " non_refundable_ctc 3200.00 3200.00 0.00\n",
+ " income_tax_refundable_credits 0.00 700.00 700.00\n",
+ " income_tax 4440.00 7940.00 3500.00\n",
+ " household_benefits 2186.02 24446.02 22260.00\n",
+ "household_tax_before_refundable_credits 12663.31 16863.31 4200.00\n",
+ " household_refundable_tax_credits 0.00 700.00 700.00\n",
+ " household_net_income 89522.70 108282.70 18760.00\n",
+ " boost_act_payment 0.00 3000.00 3000.00\n",
+ " boost_act_tax 0.00 1000.00 1000.00\n",
+ "\n",
+ "=== VALUES THAT CHANGED ===\n",
+ " Variable Baseline Reform Change\n",
+ " income_tax_before_refundable_credits 4440.00 7640.00 3200.00\n",
+ " income_tax_non_refundable_credits 3200.00 0.00 -3200.00\n",
+ " income_tax_refundable_credits 0.00 700.00 700.00\n",
+ " income_tax 4440.00 7940.00 3500.00\n",
+ " household_benefits 2186.02 24446.02 22260.00\n",
+ "household_tax_before_refundable_credits 12663.31 16863.31 4200.00\n",
+ " household_refundable_tax_credits 0.00 700.00 700.00\n",
+ " household_net_income 89522.70 108282.70 18760.00\n",
+ " boost_act_payment 0.00 3000.00 3000.00\n",
+ " boost_act_tax 0.00 1000.00 1000.00\n"
+ ]
+ }
+ ],
+ "source": [
+ "combined_reform = {\n",
+ " \"gov.contrib.congress.tlaib.income_security_package.baby_bonus_act.in_effect\": {\n",
+ " \"2026-01-01.2100-12-31\": True\n",
+ " },\n",
+ " \"gov.contrib.congress.tlaib.income_security_package.boost_act.in_effect\": {\n",
+ " \"2026-01-01.2100-12-31\": True\n",
+ " },\n",
+ " \"gov.contrib.congress.tlaib.income_security_package.end_child_poverty_act.in_effect\": {\n",
+ " \"2026-01-01.2100-12-31\": True\n",
+ " }\n",
+ "}\n",
+ "\n",
+ "df_combined = test_scenario(\n",
+ " create_situation_combined(),\n",
+ " \"Combined: Married, 3 kids (newborn, 18, 19), $100k\",\n",
+ " combined_reform\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Detailed Person-Level Analysis\n",
+ "\n",
+ "Let's check person-level values to see if payments are being assigned correctly:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def analyze_person_level(situation, name, reform_params):\n",
+ " print(f\"\\n{'='*60}\")\n",
+ " print(f\"Person-level analysis: {name}\")\n",
+ " print(f\"{'='*60}\")\n",
+ " \n",
+ " sim = Simulation(situation=situation, reform=reform_params)\n",
+ " \n",
+ " # Get all person IDs\n",
+ " people = list(situation[\"people\"].keys())\n",
+ " \n",
+ " # Standard variables\n",
+ " standard_vars = [\n",
+ " \"age\",\n",
+ " \"employment_income\",\n",
+ " \"is_tax_unit_dependent\",\n",
+ " ]\n",
+ " \n",
+ " # Reform-specific variables\n",
+ " reform_vars = [\n",
+ " \"baby_bonus_act_payment\",\n",
+ " \"boost_act_payment\",\n",
+ " \"ecpa_child_benefit\",\n",
+ " \"ecpa_adult_dependent_credit\",\n",
+ " ]\n",
+ " \n",
+ " results = []\n",
+ " for person_idx, person in enumerate(people):\n",
+ " row = {\"Person\": person}\n",
+ " \n",
+ " # Calculate standard variables\n",
+ " for var in standard_vars:\n",
+ " try:\n",
+ " vals = sim.calculate(var, \"2026\")\n",
+ " row[var] = vals[person_idx]\n",
+ " except Exception as e:\n",
+ " row[var] = f\"ERROR: {str(e)[:30]}\"\n",
+ " \n",
+ " # Calculate reform-specific variables\n",
+ " for var in reform_vars:\n",
+ " try:\n",
+ " vals = sim.calculate(var, \"2026\")\n",
+ " row[var] = vals[person_idx]\n",
+ " except Exception as e:\n",
+ " # Variable doesn't exist in this reform\n",
+ " row[var] = 0\n",
+ " \n",
+ " results.append(row)\n",
+ " \n",
+ " df = pd.DataFrame(results)\n",
+ " print(df.to_string(index=False))\n",
+ " return df"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n",
+ "============================================================\n",
+ "Person-level analysis: Baby Bonus\n",
+ "============================================================\n",
+ "Person age employment_income is_tax_unit_dependent baby_bonus_act_payment boost_act_payment ecpa_child_benefit ecpa_adult_dependent_credit\n",
+ "parent 30.00 50000.00 False 0.00 0.00 0.00 0.00\n",
+ " baby 0.00 0.00 True 2000.00 0.00 0.00 0.00\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "
\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " Person | \n",
+ " age | \n",
+ " employment_income | \n",
+ " is_tax_unit_dependent | \n",
+ " baby_bonus_act_payment | \n",
+ " boost_act_payment | \n",
+ " ecpa_child_benefit | \n",
+ " ecpa_adult_dependent_credit | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 0 | \n",
+ " parent | \n",
+ " 30.00 | \n",
+ " 50000.00 | \n",
+ " False | \n",
+ " 0.00 | \n",
+ " 0.00 | \n",
+ " 0.00 | \n",
+ " 0.00 | \n",
+ "
\n",
+ " \n",
+ " | 1 | \n",
+ " baby | \n",
+ " 0.00 | \n",
+ " 0.00 | \n",
+ " True | \n",
+ " 2000.00 | \n",
+ " 0.00 | \n",
+ " 0.00 | \n",
+ " 0.00 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " Person age employment_income is_tax_unit_dependent \\\n",
+ "0 parent 30.00 50000.00 False \n",
+ "1 baby 0.00 0.00 True \n",
+ "\n",
+ " baby_bonus_act_payment boost_act_payment ecpa_child_benefit \\\n",
+ "0 0.00 0.00 0.00 \n",
+ "1 2000.00 0.00 0.00 \n",
+ "\n",
+ " ecpa_adult_dependent_credit \n",
+ "0 0.00 \n",
+ "1 0.00 "
+ ]
+ },
+ "execution_count": 8,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# Baby Bonus person-level\n",
+ "analyze_person_level(\n",
+ " create_situation_baby_bonus(),\n",
+ " \"Baby Bonus\",\n",
+ " baby_bonus_reform\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n",
+ "============================================================\n",
+ "Person-level analysis: ECPA\n",
+ "============================================================\n",
+ "Person age employment_income is_tax_unit_dependent baby_bonus_act_payment boost_act_payment ecpa_child_benefit ecpa_adult_dependent_credit\n",
+ "adult1 40.00 50000.00 False 0.00 0.00 0.00 0.00\n",
+ "adult2 38.00 0.00 False 0.00 0.00 0.00 0.00\n",
+ "child1 6.00 0.00 True 0.00 0.00 5630.00 0.00\n",
+ "child2 18.00 0.00 True 0.00 0.00 5630.00 0.00\n",
+ "child3 19.00 0.00 True 0.00 0.00 0.00 700.00\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " Person | \n",
+ " age | \n",
+ " employment_income | \n",
+ " is_tax_unit_dependent | \n",
+ " baby_bonus_act_payment | \n",
+ " boost_act_payment | \n",
+ " ecpa_child_benefit | \n",
+ " ecpa_adult_dependent_credit | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 0 | \n",
+ " adult1 | \n",
+ " 40.00 | \n",
+ " 50000.00 | \n",
+ " False | \n",
+ " 0.00 | \n",
+ " 0.00 | \n",
+ " 0.00 | \n",
+ " 0.00 | \n",
+ "
\n",
+ " \n",
+ " | 1 | \n",
+ " adult2 | \n",
+ " 38.00 | \n",
+ " 0.00 | \n",
+ " False | \n",
+ " 0.00 | \n",
+ " 0.00 | \n",
+ " 0.00 | \n",
+ " 0.00 | \n",
+ "
\n",
+ " \n",
+ " | 2 | \n",
+ " child1 | \n",
+ " 6.00 | \n",
+ " 0.00 | \n",
+ " True | \n",
+ " 0.00 | \n",
+ " 0.00 | \n",
+ " 5630.00 | \n",
+ " 0.00 | \n",
+ "
\n",
+ " \n",
+ " | 3 | \n",
+ " child2 | \n",
+ " 18.00 | \n",
+ " 0.00 | \n",
+ " True | \n",
+ " 0.00 | \n",
+ " 0.00 | \n",
+ " 5630.00 | \n",
+ " 0.00 | \n",
+ "
\n",
+ " \n",
+ " | 4 | \n",
+ " child3 | \n",
+ " 19.00 | \n",
+ " 0.00 | \n",
+ " True | \n",
+ " 0.00 | \n",
+ " 0.00 | \n",
+ " 0.00 | \n",
+ " 700.00 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " Person age employment_income is_tax_unit_dependent \\\n",
+ "0 adult1 40.00 50000.00 False \n",
+ "1 adult2 38.00 0.00 False \n",
+ "2 child1 6.00 0.00 True \n",
+ "3 child2 18.00 0.00 True \n",
+ "4 child3 19.00 0.00 True \n",
+ "\n",
+ " baby_bonus_act_payment boost_act_payment ecpa_child_benefit \\\n",
+ "0 0.00 0.00 0.00 \n",
+ "1 0.00 0.00 0.00 \n",
+ "2 0.00 0.00 5630.00 \n",
+ "3 0.00 0.00 5630.00 \n",
+ "4 0.00 0.00 0.00 \n",
+ "\n",
+ " ecpa_adult_dependent_credit \n",
+ "0 0.00 \n",
+ "1 0.00 \n",
+ "2 0.00 \n",
+ "3 0.00 \n",
+ "4 700.00 "
+ ]
+ },
+ "execution_count": 9,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# ECPA person-level\n",
+ "analyze_person_level(\n",
+ " create_situation_ecpa(),\n",
+ " \"ECPA\",\n",
+ " ecpa_reform\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n",
+ "============================================================\n",
+ "Person-level analysis: BOOST\n",
+ "============================================================\n",
+ "Person age employment_income is_tax_unit_dependent baby_bonus_act_payment boost_act_payment ecpa_child_benefit ecpa_adult_dependent_credit\n",
+ " adult 35.00 100000.00 False 0.00 3000.00 0.00 0.00\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " Person | \n",
+ " age | \n",
+ " employment_income | \n",
+ " is_tax_unit_dependent | \n",
+ " baby_bonus_act_payment | \n",
+ " boost_act_payment | \n",
+ " ecpa_child_benefit | \n",
+ " ecpa_adult_dependent_credit | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 0 | \n",
+ " adult | \n",
+ " 35.00 | \n",
+ " 100000.00 | \n",
+ " False | \n",
+ " 0.00 | \n",
+ " 3000.00 | \n",
+ " 0.00 | \n",
+ " 0.00 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " Person age employment_income is_tax_unit_dependent \\\n",
+ "0 adult 35.00 100000.00 False \n",
+ "\n",
+ " baby_bonus_act_payment boost_act_payment ecpa_child_benefit \\\n",
+ "0 0.00 3000.00 0.00 \n",
+ "\n",
+ " ecpa_adult_dependent_credit \n",
+ "0 0.00 "
+ ]
+ },
+ "execution_count": 10,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# BOOST person-level\n",
+ "analyze_person_level(\n",
+ " create_situation_boost(),\n",
+ " \"BOOST\",\n",
+ " boost_reform\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n",
+ "============================================================\n",
+ "Person-level analysis: Combined\n",
+ "============================================================\n",
+ "Person age employment_income is_tax_unit_dependent baby_bonus_act_payment boost_act_payment ecpa_child_benefit ecpa_adult_dependent_credit\n",
+ "adult1 40.00 100000.00 False 0.00 3000.00 0.00 0.00\n",
+ "adult2 38.00 0.00 False 0.00 3000.00 0.00 0.00\n",
+ " baby 0.00 0.00 True 2000.00 0.00 5630.00 0.00\n",
+ "child2 18.00 0.00 True 0.00 0.00 5630.00 0.00\n",
+ "child3 19.00 0.00 True 0.00 3000.00 0.00 700.00\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " Person | \n",
+ " age | \n",
+ " employment_income | \n",
+ " is_tax_unit_dependent | \n",
+ " baby_bonus_act_payment | \n",
+ " boost_act_payment | \n",
+ " ecpa_child_benefit | \n",
+ " ecpa_adult_dependent_credit | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 0 | \n",
+ " adult1 | \n",
+ " 40.00 | \n",
+ " 100000.00 | \n",
+ " False | \n",
+ " 0.00 | \n",
+ " 3000.00 | \n",
+ " 0.00 | \n",
+ " 0.00 | \n",
+ "
\n",
+ " \n",
+ " | 1 | \n",
+ " adult2 | \n",
+ " 38.00 | \n",
+ " 0.00 | \n",
+ " False | \n",
+ " 0.00 | \n",
+ " 3000.00 | \n",
+ " 0.00 | \n",
+ " 0.00 | \n",
+ "
\n",
+ " \n",
+ " | 2 | \n",
+ " baby | \n",
+ " 0.00 | \n",
+ " 0.00 | \n",
+ " True | \n",
+ " 2000.00 | \n",
+ " 0.00 | \n",
+ " 5630.00 | \n",
+ " 0.00 | \n",
+ "
\n",
+ " \n",
+ " | 3 | \n",
+ " child2 | \n",
+ " 18.00 | \n",
+ " 0.00 | \n",
+ " True | \n",
+ " 0.00 | \n",
+ " 0.00 | \n",
+ " 5630.00 | \n",
+ " 0.00 | \n",
+ "
\n",
+ " \n",
+ " | 4 | \n",
+ " child3 | \n",
+ " 19.00 | \n",
+ " 0.00 | \n",
+ " True | \n",
+ " 0.00 | \n",
+ " 3000.00 | \n",
+ " 0.00 | \n",
+ " 700.00 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " Person age employment_income is_tax_unit_dependent \\\n",
+ "0 adult1 40.00 100000.00 False \n",
+ "1 adult2 38.00 0.00 False \n",
+ "2 baby 0.00 0.00 True \n",
+ "3 child2 18.00 0.00 True \n",
+ "4 child3 19.00 0.00 True \n",
+ "\n",
+ " baby_bonus_act_payment boost_act_payment ecpa_child_benefit \\\n",
+ "0 0.00 3000.00 0.00 \n",
+ "1 0.00 3000.00 0.00 \n",
+ "2 2000.00 0.00 5630.00 \n",
+ "3 0.00 0.00 5630.00 \n",
+ "4 0.00 3000.00 0.00 \n",
+ "\n",
+ " ecpa_adult_dependent_credit \n",
+ "0 0.00 \n",
+ "1 0.00 \n",
+ "2 0.00 \n",
+ "3 0.00 \n",
+ "4 700.00 "
+ ]
+ },
+ "execution_count": 11,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# Combined person-level\n",
+ "analyze_person_level(\n",
+ " create_situation_combined(),\n",
+ " \"Combined\",\n",
+ " combined_reform\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Summary Comparison\n",
+ "\n",
+ "Net income impact for each scenario:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n",
+ "============================================================\n",
+ "SUMMARY: Net Income Impact\n",
+ "============================================================\n",
+ " Scenario Baseline Net Income Reform Net Income Change\n",
+ "Baby Bonus 48059.65 50059.65 2000.00\n",
+ " ECPA 55283.38 61607.72 6324.34\n",
+ " BOOST 74189.94 75439.94 1250.00\n",
+ " Combined 89522.70 108282.70 18760.00\n"
+ ]
+ }
+ ],
+ "source": [
+ "summary_data = []\n",
+ "\n",
+ "for df, name in [\n",
+ " (df_baby, \"Baby Bonus\"),\n",
+ " (df_ecpa, \"ECPA\"),\n",
+ " (df_boost, \"BOOST\"),\n",
+ " (df_combined, \"Combined\")\n",
+ "]:\n",
+ " net_income_row = df[df[\"Variable\"] == \"household_net_income\"]\n",
+ " if not net_income_row.empty:\n",
+ " summary_data.append({\n",
+ " \"Scenario\": name,\n",
+ " \"Baseline Net Income\": net_income_row[\"Baseline\"].values[0],\n",
+ " \"Reform Net Income\": net_income_row[\"Reform\"].values[0],\n",
+ " \"Change\": net_income_row[\"Change\"].values[0]\n",
+ " })\n",
+ "\n",
+ "summary_df = pd.DataFrame(summary_data)\n",
+ "print(\"\\n\" + \"=\"*60)\n",
+ "print(\"SUMMARY: Net Income Impact\")\n",
+ "print(\"=\"*60)\n",
+ "print(summary_df.to_string(index=False))"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "pe",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.12.10"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/us/test_ctc_adult_dependent_removal.ipynb b/us/test_ctc_adult_dependent_removal.ipynb
new file mode 100644
index 0000000..6052445
--- /dev/null
+++ b/us/test_ctc_adult_dependent_removal.ipynb
@@ -0,0 +1,376 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Test: CTC Adult Dependent Credit Removal\n",
+ "\n",
+ "This notebook verifies that the current CTC adult dependent credit is properly removed when ECPA is active."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "c:\\Users\\dtsax\\envs\\pe\\Lib\\site-packages\\tqdm\\auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n",
+ " from .autonotebook import tqdm as notebook_tqdm\n"
+ ]
+ }
+ ],
+ "source": [
+ "import pandas as pd\n",
+ "from policyengine_us import Simulation\n",
+ "\n",
+ "pd.set_option('display.float_format', '{:.2f}'.format)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Test Scenario: Household with Adult Dependent\n",
+ "\n",
+ "Single filer, 1 adult dependent (age 21), $150,000 income\n",
+ "\n",
+ "Under current law, should get CTC adult dependent credit ($500 in 2026)."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "situation = {\n",
+ " \"people\": {\n",
+ " \"adult1\": {\n",
+ " \"age\": {\"2026\": 45},\n",
+ " \"employment_income\": {\"2026\": 150_000},\n",
+ " },\n",
+ " \"adult_dependent\": {\n",
+ " \"age\": {\"2026\": 21},\n",
+ " \"is_tax_unit_dependent\": {\"2026\": True},\n",
+ " },\n",
+ " },\n",
+ " \"families\": {\"family\": {\"members\": [\"adult1\", \"adult_dependent\"]}},\n",
+ " \"marital_units\": {\"marital_unit\": {\"members\": [\"adult1\"]}},\n",
+ " \"tax_units\": {\"tax_unit\": {\"members\": [\"adult1\", \"adult_dependent\"]}},\n",
+ " \"spm_units\": {\"spm_unit\": {\"members\": [\"adult1\", \"adult_dependent\"]}},\n",
+ " \"households\": {\"household\": {\"members\": [\"adult1\", \"adult_dependent\"]}},\n",
+ "}"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Debug: Check Dependency Status\n",
+ "\n",
+ "Let's verify the dependency relationship is being calculated correctly:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "============================================================\n",
+ "PERSON-LEVEL DEPENDENCY DEBUG\n",
+ "============================================================\n",
+ "\n",
+ "adult1:\n",
+ " age : 45.0\n",
+ " is_child : False\n",
+ " is_tax_unit_head : True\n",
+ " is_tax_unit_spouse : False\n",
+ " is_tax_unit_dependent : False\n",
+ " ctc_child_individual_maximum : 0.0\n",
+ " ctc_adult_individual_maximum : 0.0\n",
+ "\n",
+ "adult_dependent:\n",
+ " age : 21.0\n",
+ " is_child : False\n",
+ " is_tax_unit_head : False\n",
+ " is_tax_unit_spouse : True\n",
+ " is_tax_unit_dependent : True\n",
+ " ctc_child_individual_maximum : 0.0\n",
+ " ctc_adult_individual_maximum : 500.0\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Create simulation for debugging\n",
+ "debug_sim = Simulation(situation=situation)\n",
+ "\n",
+ "# Check dependency variables for each person\n",
+ "people = [\"adult1\", \"adult_dependent\"]\n",
+ "debug_vars = [\n",
+ " \"age\",\n",
+ " \"is_child\",\n",
+ " \"is_tax_unit_head\",\n",
+ " \"is_tax_unit_spouse\",\n",
+ " \"is_tax_unit_dependent\",\n",
+ " \"ctc_child_individual_maximum\",\n",
+ " \"ctc_adult_individual_maximum\",\n",
+ "]\n",
+ "\n",
+ "print(\"=\" * 60)\n",
+ "print(\"PERSON-LEVEL DEPENDENCY DEBUG\")\n",
+ "print(\"=\" * 60)\n",
+ "\n",
+ "for person_idx, person in enumerate(people):\n",
+ " print(f\"\\n{person}:\")\n",
+ " for var in debug_vars:\n",
+ " try:\n",
+ " vals = debug_sim.calculate(var, \"2026\")\n",
+ " val = vals[person_idx]\n",
+ " print(f\" {var:35s}: {val}\")\n",
+ " except Exception as e:\n",
+ " print(f\" {var:35s}: ERROR - {str(e)[:40]}\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Baseline: No ECPA (Current Law)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "============================================================\n",
+ "BASELINE (Current Law)\n",
+ "============================================================\n",
+ "ctc_adult_individual_maximum : $0.00\n",
+ "ctc_child_individual_maximum : $0.00\n",
+ "ctc : $500.00\n",
+ "non_refundable_ctc : $500.00\n",
+ "refundable_ctc : $0.00\n",
+ "income_tax_non_refundable_credits : $500.00\n",
+ "income_tax_refundable_credits : $0.00\n",
+ "income_tax : $14,840.00\n"
+ ]
+ }
+ ],
+ "source": [
+ "baseline = Simulation(situation=situation)\n",
+ "\n",
+ "print(\"=\" * 60)\n",
+ "print(\"BASELINE (Current Law)\")\n",
+ "print(\"=\" * 60)\n",
+ "\n",
+ "variables = [\n",
+ " \"ctc_adult_individual_maximum\",\n",
+ " \"ctc_child_individual_maximum\",\n",
+ " \"ctc\",\n",
+ " \"non_refundable_ctc\",\n",
+ " \"refundable_ctc\",\n",
+ " \"income_tax_non_refundable_credits\",\n",
+ " \"income_tax_refundable_credits\",\n",
+ " \"income_tax\",\n",
+ "]\n",
+ "\n",
+ "for var in variables:\n",
+ " try:\n",
+ " val = baseline.calculate(var, \"2026\")[0]\n",
+ " print(f\"{var:40s}: ${val:,.2f}\")\n",
+ " except Exception as e:\n",
+ " print(f\"{var:40s}: ERROR - {e}\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## With ECPA Active"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n",
+ "============================================================\n",
+ "WITH ECPA ACTIVE\n",
+ "============================================================\n",
+ "ctc_adult_individual_maximum : $0.00\n",
+ "ctc_child_individual_maximum : $0.00\n",
+ "ctc : $500.00\n",
+ "non_refundable_ctc : $500.00\n",
+ "refundable_ctc : $0.00\n",
+ "income_tax_non_refundable_credits : $0.00\n",
+ "income_tax_refundable_credits : $700.00\n",
+ "income_tax : $14,640.00\n"
+ ]
+ }
+ ],
+ "source": [
+ "ecpa_reform = {\n",
+ " \"gov.contrib.congress.tlaib.income_security_package.end_child_poverty_act.in_effect\": {\n",
+ " \"2026-01-01.2100-12-31\": True\n",
+ " }\n",
+ "}\n",
+ "\n",
+ "reformed = Simulation(situation=situation, reform=ecpa_reform)\n",
+ "\n",
+ "print(\"\\n\" + \"=\" * 60)\n",
+ "print(\"WITH ECPA ACTIVE\")\n",
+ "print(\"=\" * 60)\n",
+ "\n",
+ "for var in variables:\n",
+ " try:\n",
+ " val = reformed.calculate(var, \"2026\")[0]\n",
+ " print(f\"{var:40s}: ${val:,.2f}\")\n",
+ " except Exception as e:\n",
+ " print(f\"{var:40s}: ERROR - {e}\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Comparison"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n",
+ "============================================================\n",
+ "COMPARISON\n",
+ "============================================================\n",
+ " Variable Baseline ECPA Change\n",
+ " ctc_adult_individual_maximum 0.00 0.00 0.00\n",
+ " ctc_child_individual_maximum 0.00 0.00 0.00\n",
+ " ctc 500.00 500.00 0.00\n",
+ " non_refundable_ctc 500.00 500.00 0.00\n",
+ " refundable_ctc 0.00 0.00 0.00\n",
+ "income_tax_non_refundable_credits 500.00 0.00 -500.00\n",
+ " income_tax_refundable_credits 0.00 700.00 700.00\n",
+ " income_tax 14840.00 14640.00 -200.00\n",
+ "\n",
+ "============================================================\n",
+ "KEY FINDINGS\n",
+ "============================================================\n",
+ "\n",
+ "Baseline CTC Adult Dependent Credit: $0.00\n",
+ "ECPA CTC Adult Dependent Credit: $0.00\n",
+ "\n",
+ "⚠ WARNING: No adult dependent in baseline (check test setup)\n",
+ "\n",
+ "ECPA Adult Dependent Credit: $0.00\n",
+ "⚠ ECPA adult dependent credit is $0 (check age boundaries)\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(\"\\n\" + \"=\" * 60)\n",
+ "print(\"COMPARISON\")\n",
+ "print(\"=\" * 60)\n",
+ "\n",
+ "results = []\n",
+ "for var in variables:\n",
+ " try:\n",
+ " base_val = baseline.calculate(var, \"2026\")[0]\n",
+ " reform_val = reformed.calculate(var, \"2026\")[0]\n",
+ " diff = reform_val - base_val\n",
+ " \n",
+ " results.append({\n",
+ " \"Variable\": var,\n",
+ " \"Baseline\": base_val,\n",
+ " \"ECPA\": reform_val,\n",
+ " \"Change\": diff\n",
+ " })\n",
+ " except Exception as e:\n",
+ " results.append({\n",
+ " \"Variable\": var,\n",
+ " \"Baseline\": \"ERROR\",\n",
+ " \"ECPA\": \"ERROR\",\n",
+ " \"Change\": str(e)[:40]\n",
+ " })\n",
+ "\n",
+ "df = pd.DataFrame(results)\n",
+ "print(df.to_string(index=False))\n",
+ "\n",
+ "print(\"\\n\" + \"=\" * 60)\n",
+ "print(\"KEY FINDINGS\")\n",
+ "print(\"=\" * 60)\n",
+ "\n",
+ "# Check if adult dependent credit is removed\n",
+ "base_adult_ctc = baseline.calculate(\"ctc_adult_individual_maximum\", \"2026\")[0]\n",
+ "reform_adult_ctc = reformed.calculate(\"ctc_adult_individual_maximum\", \"2026\")[0]\n",
+ "\n",
+ "print(f\"\\nBaseline CTC Adult Dependent Credit: ${base_adult_ctc:,.2f}\")\n",
+ "print(f\"ECPA CTC Adult Dependent Credit: ${reform_adult_ctc:,.2f}\")\n",
+ "\n",
+ "if base_adult_ctc > 0 and reform_adult_ctc == 0:\n",
+ " print(\"\\n✓ SUCCESS: CTC adult dependent credit properly removed under ECPA\")\n",
+ "elif base_adult_ctc > 0 and reform_adult_ctc > 0:\n",
+ " print(\"\\n✗ FAILURE: CTC adult dependent credit still present under ECPA\")\n",
+ " print(\" This means the old $500 credit is being added on top of new ECPA credits!\")\n",
+ "elif base_adult_ctc == 0:\n",
+ " print(\"\\n⚠ WARNING: No adult dependent in baseline (check test setup)\")\n",
+ "\n",
+ "# Check if ECPA adult dependent credit is present\n",
+ "try:\n",
+ " ecpa_adult_dep = reformed.calculate(\"ecpa_adult_dependent_credit\", \"2026\")[0]\n",
+ " print(f\"\\nECPA Adult Dependent Credit: ${ecpa_adult_dep:,.2f}\")\n",
+ " if ecpa_adult_dep == 700:\n",
+ " print(\"✓ ECPA adult dependent credit correctly calculated ($700)\")\n",
+ " elif ecpa_adult_dep == 0:\n",
+ " print(\"⚠ ECPA adult dependent credit is $0 (check age boundaries)\")\n",
+ "except Exception as e:\n",
+ " print(f\"\\n✗ ERROR: Could not calculate ecpa_adult_dependent_credit: {e}\")"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "pe",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.12.10"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}