From 8771422f66fdab39c9e7b87358188aa34bd1b263 Mon Sep 17 00:00:00 2001 From: Ziming Date: Wed, 8 Apr 2026 23:36:47 -0400 Subject: [PATCH 01/11] Initial commit for Georgia CCAP (CAPS) implementation Closes #7957 Co-Authored-By: Claude Opus 4.6 (1M context) From c0fac2c8fa192d060fc18c22ee2f6d944f5f7687 Mon Sep 17 00:00:00 2001 From: Ziming Date: Wed, 8 Apr 2026 23:37:17 -0400 Subject: [PATCH 02/11] Add changelog fragment for Georgia CCAP implementation Co-Authored-By: Claude Opus 4.6 (1M context) --- changelog.d/ga-ccap.added.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/ga-ccap.added.md diff --git a/changelog.d/ga-ccap.added.md b/changelog.d/ga-ccap.added.md new file mode 100644 index 00000000000..f4a1f3c8f69 --- /dev/null +++ b/changelog.d/ga-ccap.added.md @@ -0,0 +1 @@ +Implement Georgia CCAP (Childcare and Parent Services - CAPS). Closes #7957. From 0c78b14527910b8ef0e99eaa4bec64881206dfad Mon Sep 17 00:00:00 2001 From: Ziming Date: Thu, 9 Apr 2026 00:42:47 -0400 Subject: [PATCH 03/11] Implement Georgia CAPS (Childcare and Parent Services) (ref #7957) Co-Authored-By: Claude Opus 4.6 (1M context) --- .../hhs/ccdf/child_care_subsidy_programs.yaml | 1 + .../household/household_state_benefits.yaml | 2 + .../activity_requirements/weekly_hours.yaml | 13 + .../decal/caps/age_group/preschool_min.yaml | 11 + .../decal/caps/age_group/school_age_min.yaml | 11 + .../ga/decal/caps/age_group/toddler_min.yaml | 11 + .../ga/decal/caps/age_threshold/child.yaml | 13 + .../caps/age_threshold/disabled_child.yaml | 13 + .../caps/family_fee/minor_parent_age.yaml | 13 + .../states/ga/decal/caps/family_fee/rate.yaml | 30 ++ .../caps/income/countable_income/sources.yaml | 28 + .../income/smi_rate/initial_eligibility.yaml | 13 + .../income/smi_rate/ongoing_eligibility.yaml | 13 + .../decal/caps/quality_rated/bonus_rate.yaml | 24 + .../states/ga/decal/caps/rates/center.yaml | 102 ++++ .../states/ga/decal/caps/rates/family.yaml | 102 ++++ .../states/ga/decal/caps/rates/informal.yaml | 102 ++++ .../states/ga/decal/caps/zone_1_counties.yaml | 25 + .../states/ga/decal/caps/zone_2_counties.yaml | 57 +++ .../decal/caps/copay/ga_caps_family_fee.yaml | 180 +++++++ .../caps/copay/ga_caps_family_fee_edge.yaml | 215 ++++++++ .../ga_caps_activity_eligible.yaml | 139 +++++ .../ga_caps_activity_eligible_edge.yaml | 146 ++++++ .../caps/eligibility/ga_caps_eligible.yaml | 158 ++++++ .../eligibility/ga_caps_eligible_child.yaml | 216 ++++++++ .../ga_caps_eligible_child_edge.yaml | 202 ++++++++ .../eligibility/ga_caps_income_eligible.yaml | 129 +++++ .../ga_caps_income_eligible_edge.yaml | 215 ++++++++ .../states/ga/decal/caps/ga_caps_edge.yaml | 482 ++++++++++++++++++ .../gov/states/ga/decal/caps/integration.yaml | 383 ++++++++++++++ .../ga/decal/caps/integration_edge.yaml | 367 +++++++++++++ .../decal/caps/payment/ga_caps_age_group.yaml | 168 ++++++ .../ga_caps_maximum_weekly_benefit.yaml | 327 ++++++++++++ .../ga_caps_maximum_weekly_benefit_edge.yaml | 172 +++++++ .../ga/decal/caps/payment/ga_caps_zone.yaml | 103 ++++ .../ga/decal/caps/copay/ga_caps_family_fee.py | 38 ++ .../eligibility/ga_caps_activity_eligible.py | 20 + .../caps/eligibility/ga_caps_eligible.py | 17 + .../eligibility/ga_caps_eligible_child.py | 24 + .../eligibility/ga_caps_income_eligible.py | 23 + .../gov/states/ga/decal/caps/ga_caps.py | 51 ++ .../states/ga/decal/caps/ga_caps_enrolled.py | 9 + .../ga/decal/caps/ga_child_care_subsidies.py | 11 + .../caps/income/ga_caps_countable_income.py | 13 + .../decal/caps/payment/ga_caps_age_group.py | 36 ++ .../decal/caps/payment/ga_caps_care_type.py | 18 + .../payment/ga_caps_maximum_weekly_benefit.py | 40 ++ .../caps/payment/ga_caps_provider_type.py | 18 + .../caps/payment/ga_caps_quality_rating.py | 19 + .../ga/decal/caps/payment/ga_caps_zone.py | 29 ++ sources/working_references.md | 453 ++++++++-------- 51 files changed, 4782 insertions(+), 223 deletions(-) create mode 100644 policyengine_us/parameters/gov/states/ga/decal/caps/activity_requirements/weekly_hours.yaml create mode 100644 policyengine_us/parameters/gov/states/ga/decal/caps/age_group/preschool_min.yaml create mode 100644 policyengine_us/parameters/gov/states/ga/decal/caps/age_group/school_age_min.yaml create mode 100644 policyengine_us/parameters/gov/states/ga/decal/caps/age_group/toddler_min.yaml create mode 100644 policyengine_us/parameters/gov/states/ga/decal/caps/age_threshold/child.yaml create mode 100644 policyengine_us/parameters/gov/states/ga/decal/caps/age_threshold/disabled_child.yaml create mode 100644 policyengine_us/parameters/gov/states/ga/decal/caps/family_fee/minor_parent_age.yaml create mode 100644 policyengine_us/parameters/gov/states/ga/decal/caps/family_fee/rate.yaml create mode 100644 policyengine_us/parameters/gov/states/ga/decal/caps/income/countable_income/sources.yaml create mode 100644 policyengine_us/parameters/gov/states/ga/decal/caps/income/smi_rate/initial_eligibility.yaml create mode 100644 policyengine_us/parameters/gov/states/ga/decal/caps/income/smi_rate/ongoing_eligibility.yaml create mode 100644 policyengine_us/parameters/gov/states/ga/decal/caps/quality_rated/bonus_rate.yaml create mode 100644 policyengine_us/parameters/gov/states/ga/decal/caps/rates/center.yaml create mode 100644 policyengine_us/parameters/gov/states/ga/decal/caps/rates/family.yaml create mode 100644 policyengine_us/parameters/gov/states/ga/decal/caps/rates/informal.yaml create mode 100644 policyengine_us/parameters/gov/states/ga/decal/caps/zone_1_counties.yaml create mode 100644 policyengine_us/parameters/gov/states/ga/decal/caps/zone_2_counties.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/copay/ga_caps_family_fee.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/copay/ga_caps_family_fee_edge.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_activity_eligible.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_activity_eligible_edge.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_eligible.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_eligible_child.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_eligible_child_edge.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_income_eligible.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_income_eligible_edge.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/ga_caps_edge.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/integration.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/integration_edge.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/payment/ga_caps_age_group.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/payment/ga_caps_maximum_weekly_benefit.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/payment/ga_caps_maximum_weekly_benefit_edge.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/payment/ga_caps_zone.yaml create mode 100644 policyengine_us/variables/gov/states/ga/decal/caps/copay/ga_caps_family_fee.py create mode 100644 policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_activity_eligible.py create mode 100644 policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_eligible.py create mode 100644 policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_eligible_child.py create mode 100644 policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_income_eligible.py create mode 100644 policyengine_us/variables/gov/states/ga/decal/caps/ga_caps.py create mode 100644 policyengine_us/variables/gov/states/ga/decal/caps/ga_caps_enrolled.py create mode 100644 policyengine_us/variables/gov/states/ga/decal/caps/ga_child_care_subsidies.py create mode 100644 policyengine_us/variables/gov/states/ga/decal/caps/income/ga_caps_countable_income.py create mode 100644 policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_age_group.py create mode 100644 policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_care_type.py create mode 100644 policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_maximum_weekly_benefit.py create mode 100644 policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_provider_type.py create mode 100644 policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_quality_rating.py create mode 100644 policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_zone.py diff --git a/policyengine_us/parameters/gov/hhs/ccdf/child_care_subsidy_programs.yaml b/policyengine_us/parameters/gov/hhs/ccdf/child_care_subsidy_programs.yaml index 4050e47c83e..23966ac2cec 100644 --- a/policyengine_us/parameters/gov/hhs/ccdf/child_care_subsidy_programs.yaml +++ b/policyengine_us/parameters/gov/hhs/ccdf/child_care_subsidy_programs.yaml @@ -4,6 +4,7 @@ values: - ca_child_care_subsidies # California Child Care - co_child_care_subsidies # Colorado Child Care Assistance Program - de_child_care_subsidies # Delaware Purchase of Care + - ga_child_care_subsidies # Georgia Childcare and Parent Services - ma_child_care_subsidies # Massachusetts Child Care Financial Assistance - me_child_care_subsidies # Maine Child Care Affordability Program - ne_child_care_subsidies # Nebraska Child Care Subsidy diff --git a/policyengine_us/parameters/gov/household/household_state_benefits.yaml b/policyengine_us/parameters/gov/household/household_state_benefits.yaml index eb8c9cd5676..54c99404063 100644 --- a/policyengine_us/parameters/gov/household/household_state_benefits.yaml +++ b/policyengine_us/parameters/gov/household/household_state_benefits.yaml @@ -53,6 +53,8 @@ values: - al_ssp # Alaska benefits - ak_ssp + # Georgia benefits + - ga_child_care_subsidies # Nebraska benefits - ne_child_care_subsidies # North Carolina benefits diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/activity_requirements/weekly_hours.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/activity_requirements/weekly_hours.yaml new file mode 100644 index 00000000000..959f78d501d --- /dev/null +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/activity_requirements/weekly_hours.yaml @@ -0,0 +1,13 @@ +description: Georgia sets this amount as the minimum weekly hours of approved activity under the Childcare and Parent Services program. +values: + 2026-03-02: 24 + +metadata: + unit: hour + period: year + label: Georgia CAPS minimum weekly activity hours + reference: + - title: Georgia CAPS Policy Manual, Chapter 6 (Eligibility Requirements) + href: https://caps.decal.ga.gov/assets/downloads/CAPS/02-CAPS_Policy-Chapter_6.pdf#page=4 + - title: Georgia CCDF Plan FFY 2025-2027, Section 3.2.2 + href: https://www.acf.hhs.gov/sites/default/files/documents/occ/georgia_2025_2027_ccdf_state_plan.pdf#page=56 diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/age_group/preschool_min.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/age_group/preschool_min.yaml new file mode 100644 index 00000000000..230804f58a1 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/age_group/preschool_min.yaml @@ -0,0 +1,11 @@ +description: Georgia sets this age as the minimum for the preschool age group under the Childcare and Parent Services program. +values: + 2026-03-02: 3 + +metadata: + unit: year + period: year + label: Georgia CAPS preschool minimum age + reference: + - title: Georgia CAPS Appendix C - Reimbursement Rates (effective March 2, 2026) + href: https://caps.decal.ga.gov/assets/downloads/CAPS/Appendix_C-CAPS_Reimbursement_Rates.pdf#page=2 diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/age_group/school_age_min.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/age_group/school_age_min.yaml new file mode 100644 index 00000000000..ad3372601f5 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/age_group/school_age_min.yaml @@ -0,0 +1,11 @@ +description: Georgia sets this age as the minimum for the school age group under the Childcare and Parent Services program. +values: + 2026-03-02: 6 + +metadata: + unit: year + period: year + label: Georgia CAPS school age minimum age + reference: + - title: Georgia CAPS Appendix C - Reimbursement Rates (effective March 2, 2026) + href: https://caps.decal.ga.gov/assets/downloads/CAPS/Appendix_C-CAPS_Reimbursement_Rates.pdf#page=2 diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/age_group/toddler_min.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/age_group/toddler_min.yaml new file mode 100644 index 00000000000..6df555fce0a --- /dev/null +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/age_group/toddler_min.yaml @@ -0,0 +1,11 @@ +description: Georgia sets this age as the minimum for the toddler age group under the Childcare and Parent Services program. +values: + 2026-03-02: 1 + +metadata: + unit: year + period: year + label: Georgia CAPS toddler minimum age + reference: + - title: Georgia CAPS Appendix C - Reimbursement Rates (effective March 2, 2026) + href: https://caps.decal.ga.gov/assets/downloads/CAPS/Appendix_C-CAPS_Reimbursement_Rates.pdf#page=2 diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/age_threshold/child.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/age_threshold/child.yaml new file mode 100644 index 00000000000..82cf42f1cbf --- /dev/null +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/age_threshold/child.yaml @@ -0,0 +1,13 @@ +description: Georgia limits the Childcare and Parent Services program to children younger than this age. +values: + 2026-03-02: 13 + +metadata: + unit: year + period: year + label: Georgia CAPS child age threshold + reference: + - title: Georgia CAPS Policy Manual, Chapter 6 (Eligibility Requirements) + href: https://caps.decal.ga.gov/assets/downloads/CAPS/02-CAPS_Policy-Chapter_6.pdf#page=3 + - title: Georgia CCDF Plan FFY 2025-2027, Section 3.1.1 + href: https://www.acf.hhs.gov/sites/default/files/documents/occ/georgia_2025_2027_ccdf_state_plan.pdf#page=49 diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/age_threshold/disabled_child.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/age_threshold/disabled_child.yaml new file mode 100644 index 00000000000..999e0ec310b --- /dev/null +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/age_threshold/disabled_child.yaml @@ -0,0 +1,13 @@ +description: Georgia limits the Childcare and Parent Services program to disabled children up through this age. +values: + 2026-03-02: 17 + +metadata: + unit: year + period: year + label: Georgia CAPS disabled child age threshold + reference: + - title: Georgia CAPS Policy Manual, Chapter 6 (Eligibility Requirements) + href: https://caps.decal.ga.gov/assets/downloads/CAPS/02-CAPS_Policy-Chapter_6.pdf#page=3 + - title: Georgia CCDF Plan FFY 2025-2027, Section 3.1.1 + href: https://www.acf.hhs.gov/sites/default/files/documents/occ/georgia_2025_2027_ccdf_state_plan.pdf#page=49 diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/family_fee/minor_parent_age.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/family_fee/minor_parent_age.yaml new file mode 100644 index 00000000000..8f5d08014a4 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/family_fee/minor_parent_age.yaml @@ -0,0 +1,13 @@ +description: Georgia waives the family fee for parents at or below this age under the Childcare and Parent Services program. +values: + 2026-03-02: 17 + +metadata: + unit: year + period: year + label: Georgia CAPS minor parent age threshold for fee waiver + reference: + - title: Georgia CAPS Policy Manual, Chapter 6 (Eligibility Requirements) + href: https://caps.decal.ga.gov/assets/downloads/CAPS/02-CAPS_Policy-Chapter_6.pdf#page=5 + - title: Georgia CCDF Plan FFY 2025-2027, Section 4.3.2 + href: https://www.acf.hhs.gov/sites/default/files/documents/occ/georgia_2025_2027_ccdf_state_plan.pdf#page=117 diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/family_fee/rate.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/family_fee/rate.yaml new file mode 100644 index 00000000000..b2391beaaff --- /dev/null +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/family_fee/rate.yaml @@ -0,0 +1,30 @@ +description: Georgia sets this co-payment percentage under the Childcare and Parent Services program. +metadata: + type: single_amount + threshold_unit: /1 + amount_unit: /1 + period: year + label: Georgia CAPS family fee rate by FPL ratio + reference: + - title: Georgia CAPS Appendix D - Family Fee Schedule (effective March 2, 2026) + href: https://caps.decal.ga.gov/assets/downloads/CAPS/Appendix_D-CAPS_Family_Fee_702.pdf#page=2 + - title: Georgia CCDF Plan FFY 2025-2027, Section 4.3.2 + href: https://www.acf.hhs.gov/sites/default/files/documents/occ/georgia_2025_2027_ccdf_state_plan.pdf#page=117 + +brackets: + - threshold: + 2026-03-02: 0 + amount: + 2026-03-02: 0 + - threshold: + 2026-03-02: 0.1001 + amount: + 2026-03-02: 0.03 + - threshold: + 2026-03-02: 0.5001 + amount: + 2026-03-02: 0.05 + - threshold: + 2026-03-02: 1.0001 + amount: + 2026-03-02: 0.07 diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/income/countable_income/sources.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/income/countable_income/sources.yaml new file mode 100644 index 00000000000..cc438c7c072 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/income/countable_income/sources.yaml @@ -0,0 +1,28 @@ +description: Georgia counts these income sources under the Childcare and Parent Services program. +values: + 2026-03-02: + - employment_income + - self_employment_income + - unemployment_compensation + - workers_compensation + - alimony_income + - child_support_received + - veterans_benefits + - capital_gains + - rental_income + - dividend_income + - pension_income + - military_retirement_pay + # The following are counted per CAPS Policy Manual Ch.8 but have + # no matching variables: + # - lottery_payments + # - commissions (included in employment_income) + # - cash_bonuses (included in employment_income) + +metadata: + unit: list + period: year + label: Georgia CAPS countable income sources + reference: + - title: Georgia CAPS Policy Manual, Chapter 8 (Income) + href: https://caps.decal.ga.gov/assets/downloads/CAPS/04-CAPS_Policy-Chapter_8.pdf#page=3 diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/income/smi_rate/initial_eligibility.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/income/smi_rate/initial_eligibility.yaml new file mode 100644 index 00000000000..0ef8f887bb0 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/income/smi_rate/initial_eligibility.yaml @@ -0,0 +1,13 @@ +description: Georgia limits the Childcare and Parent Services program to new applicants with income at or below this share of state median income. +values: + 2026-03-02: 0.5 + +metadata: + unit: /1 + period: year + label: Georgia CAPS initial eligibility SMI rate + reference: + - title: Georgia CAPS Policy Manual, Chapter 8 (Income) + href: https://caps.decal.ga.gov/assets/downloads/CAPS/04-CAPS_Policy-Chapter_8.pdf#page=2 + - title: Georgia CAPS Appendix A - Income Limits (effective March 2, 2026) + href: https://caps.decal.ga.gov/assets/downloads/CAPS/Appendix_A-CAPS_702_Income_Limits.pdf#page=2 diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/income/smi_rate/ongoing_eligibility.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/income/smi_rate/ongoing_eligibility.yaml new file mode 100644 index 00000000000..84a2814468d --- /dev/null +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/income/smi_rate/ongoing_eligibility.yaml @@ -0,0 +1,13 @@ +description: Georgia limits the Childcare and Parent Services program to enrolled families with income at or below this share of state median income. +values: + 2026-03-02: 0.85 + +metadata: + unit: /1 + period: year + label: Georgia CAPS ongoing eligibility SMI rate + reference: + - title: Georgia CAPS Policy Manual, Chapter 8 (Income) + href: https://caps.decal.ga.gov/assets/downloads/CAPS/04-CAPS_Policy-Chapter_8.pdf#page=2 + - title: Georgia CAPS Appendix A - Income Limits (effective March 2, 2026) + href: https://caps.decal.ga.gov/assets/downloads/CAPS/Appendix_A-CAPS_702_Income_Limits.pdf#page=2 diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/quality_rated/bonus_rate.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/quality_rated/bonus_rate.yaml new file mode 100644 index 00000000000..c741a7da071 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/quality_rated/bonus_rate.yaml @@ -0,0 +1,24 @@ +description: Georgia provides this quality bonus rate under the Childcare and Parent Services program. +metadata: + type: single_amount + threshold_unit: /1 + amount_unit: /1 + period: year + label: Georgia CAPS Quality Rated bonus rate + reference: + - title: Georgia CCDF Plan FFY 2025-2027, Section 4.2.4 (Quality Rated Differential) + href: https://www.acf.hhs.gov/sites/default/files/documents/occ/georgia_2025_2027_ccdf_state_plan.pdf#page=110 + +brackets: + - threshold: + 2026-03-02: 0 + amount: + 2026-03-02: 0 + - threshold: + 2026-03-02: 2 + amount: + 2026-03-02: 0.05 + - threshold: + 2026-03-02: 3 + amount: + 2026-03-02: 0.10 diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/rates/center.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/rates/center.yaml new file mode 100644 index 00000000000..42f557f11bd --- /dev/null +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/rates/center.yaml @@ -0,0 +1,102 @@ +description: Georgia provides these reimbursement rates for child care centers under the Childcare and Parent Services program. +metadata: + unit: currency-USD + period: week + label: Georgia CAPS center reimbursement rates + breakdown: + - ga_caps_zone + - ga_caps_age_group + - ga_caps_care_type + reference: + - title: Georgia CAPS Appendix C - Reimbursement Rates (effective March 2, 2026) + href: https://caps.decal.ga.gov/assets/downloads/CAPS/Appendix_C-CAPS_Reimbursement_Rates.pdf#page=2 + +ZONE_1: + INFANT: + FULL_TIME: + 2026-03-02: 260 + PART_TIME: + 2026-03-02: 65 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 84 + TODDLER: + FULL_TIME: + 2026-03-02: 248 + PART_TIME: + 2026-03-02: 65 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 84 + PRESCHOOL: + FULL_TIME: + 2026-03-02: 221 + PART_TIME: + 2026-03-02: 65 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 84 + SCHOOL_AGE: + FULL_TIME: + 2026-03-02: 185 + PART_TIME: + 2026-03-02: 65 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 84 + +ZONE_2: + INFANT: + FULL_TIME: + 2026-03-02: 165 + PART_TIME: + 2026-03-02: 45 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 68 + TODDLER: + FULL_TIME: + 2026-03-02: 160 + PART_TIME: + 2026-03-02: 45 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 68 + PRESCHOOL: + FULL_TIME: + 2026-03-02: 150 + PART_TIME: + 2026-03-02: 45 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 68 + SCHOOL_AGE: + FULL_TIME: + 2026-03-02: 140 + PART_TIME: + 2026-03-02: 45 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 68 + +ZONE_3: + INFANT: + FULL_TIME: + 2026-03-02: 130 + PART_TIME: + 2026-03-02: 38 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 53 + TODDLER: + FULL_TIME: + 2026-03-02: 125 + PART_TIME: + 2026-03-02: 38 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 53 + PRESCHOOL: + FULL_TIME: + 2026-03-02: 120 + PART_TIME: + 2026-03-02: 38 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 53 + SCHOOL_AGE: + FULL_TIME: + 2026-03-02: 115 + PART_TIME: + 2026-03-02: 38 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 53 diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/rates/family.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/rates/family.yaml new file mode 100644 index 00000000000..d94158d1268 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/rates/family.yaml @@ -0,0 +1,102 @@ +description: Georgia provides these reimbursement rates for family child care homes under the Childcare and Parent Services program. +metadata: + unit: currency-USD + period: week + label: Georgia CAPS family child care home reimbursement rates + breakdown: + - ga_caps_zone + - ga_caps_age_group + - ga_caps_care_type + reference: + - title: Georgia CAPS Appendix C - Reimbursement Rates (effective March 2, 2026) + href: https://caps.decal.ga.gov/assets/downloads/CAPS/Appendix_C-CAPS_Reimbursement_Rates.pdf#page=2 + +ZONE_1: + INFANT: + FULL_TIME: + 2026-03-02: 199 + PART_TIME: + 2026-03-02: 53 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 68 + TODDLER: + FULL_TIME: + 2026-03-02: 188 + PART_TIME: + 2026-03-02: 53 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 68 + PRESCHOOL: + FULL_TIME: + 2026-03-02: 180 + PART_TIME: + 2026-03-02: 53 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 68 + SCHOOL_AGE: + FULL_TIME: + 2026-03-02: 156 + PART_TIME: + 2026-03-02: 53 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 68 + +ZONE_2: + INFANT: + FULL_TIME: + 2026-03-02: 145 + PART_TIME: + 2026-03-02: 40 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 58 + TODDLER: + FULL_TIME: + 2026-03-02: 140 + PART_TIME: + 2026-03-02: 40 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 58 + PRESCHOOL: + FULL_TIME: + 2026-03-02: 135 + PART_TIME: + 2026-03-02: 40 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 58 + SCHOOL_AGE: + FULL_TIME: + 2026-03-02: 135 + PART_TIME: + 2026-03-02: 40 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 58 + +ZONE_3: + INFANT: + FULL_TIME: + 2026-03-02: 120 + PART_TIME: + 2026-03-02: 35 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 47 + TODDLER: + FULL_TIME: + 2026-03-02: 110 + PART_TIME: + 2026-03-02: 35 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 47 + PRESCHOOL: + FULL_TIME: + 2026-03-02: 105 + PART_TIME: + 2026-03-02: 35 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 47 + SCHOOL_AGE: + FULL_TIME: + 2026-03-02: 94 + PART_TIME: + 2026-03-02: 35 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 47 diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/rates/informal.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/rates/informal.yaml new file mode 100644 index 00000000000..c25c57042db --- /dev/null +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/rates/informal.yaml @@ -0,0 +1,102 @@ +description: Georgia provides these reimbursement rates for informal child care providers under the Childcare and Parent Services program. +metadata: + unit: currency-USD + period: week + label: Georgia CAPS informal child care reimbursement rates + breakdown: + - ga_caps_zone + - ga_caps_age_group + - ga_caps_care_type + reference: + - title: Georgia CAPS Appendix C - Reimbursement Rates (effective March 2, 2026) + href: https://caps.decal.ga.gov/assets/downloads/CAPS/Appendix_C-CAPS_Reimbursement_Rates.pdf#page=2 + +ZONE_1: + INFANT: + FULL_TIME: + 2026-03-02: 199 + PART_TIME: + 2026-03-02: 53 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 68 + TODDLER: + FULL_TIME: + 2026-03-02: 188 + PART_TIME: + 2026-03-02: 53 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 68 + PRESCHOOL: + FULL_TIME: + 2026-03-02: 180 + PART_TIME: + 2026-03-02: 53 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 68 + SCHOOL_AGE: + FULL_TIME: + 2026-03-02: 156 + PART_TIME: + 2026-03-02: 53 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 68 + +ZONE_2: + INFANT: + FULL_TIME: + 2026-03-02: 145 + PART_TIME: + 2026-03-02: 40 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 58 + TODDLER: + FULL_TIME: + 2026-03-02: 140 + PART_TIME: + 2026-03-02: 40 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 58 + PRESCHOOL: + FULL_TIME: + 2026-03-02: 135 + PART_TIME: + 2026-03-02: 40 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 58 + SCHOOL_AGE: + FULL_TIME: + 2026-03-02: 135 + PART_TIME: + 2026-03-02: 40 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 58 + +ZONE_3: + INFANT: + FULL_TIME: + 2026-03-02: 120 + PART_TIME: + 2026-03-02: 35 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 47 + TODDLER: + FULL_TIME: + 2026-03-02: 110 + PART_TIME: + 2026-03-02: 35 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 47 + PRESCHOOL: + FULL_TIME: + 2026-03-02: 105 + PART_TIME: + 2026-03-02: 35 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 47 + SCHOOL_AGE: + FULL_TIME: + 2026-03-02: 94 + PART_TIME: + 2026-03-02: 35 + BEFORE_AFTER_SCHOOL: + 2026-03-02: 47 diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/zone_1_counties.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/zone_1_counties.yaml new file mode 100644 index 00000000000..e930a4c8a05 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/zone_1_counties.yaml @@ -0,0 +1,25 @@ +description: Georgia sets these counties as Zone 1 for reimbursement rate purposes under the Childcare and Parent Services program. +values: + 2026-03-02: + - CAMDEN_COUNTY_GA + - CHEROKEE_COUNTY_GA + - CLAYTON_COUNTY_GA + - COBB_COUNTY_GA + - DEKALB_COUNTY_GA + - DOUGLAS_COUNTY_GA + - FAYETTE_COUNTY_GA + - FORSYTH_COUNTY_GA + - FULTON_COUNTY_GA + - GWINNETT_COUNTY_GA + - HALL_COUNTY_GA + - HENRY_COUNTY_GA + - PAULDING_COUNTY_GA + - ROCKDALE_COUNTY_GA + +metadata: + unit: list + period: year + label: Georgia CAPS Zone 1 counties + reference: + - title: Georgia CAPS Appendix C - Reimbursement Rates (effective March 2, 2026) + href: https://caps.decal.ga.gov/assets/downloads/CAPS/Appendix_C-CAPS_Reimbursement_Rates.pdf#page=2 diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/zone_2_counties.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/zone_2_counties.yaml new file mode 100644 index 00000000000..6ab70c09c79 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/zone_2_counties.yaml @@ -0,0 +1,57 @@ +description: Georgia sets these counties as Zone 2 for reimbursement rate purposes under the Childcare and Parent Services program. +values: + 2026-03-02: + - BALDWIN_COUNTY_GA + - BARROW_COUNTY_GA + - BARTOW_COUNTY_GA + - BIBB_COUNTY_GA + - BRYAN_COUNTY_GA + - BULLOCH_COUNTY_GA + - BUTTS_COUNTY_GA + - CATOOSA_COUNTY_GA + - CHATHAM_COUNTY_GA + - CLARKE_COUNTY_GA + - COLUMBIA_COUNTY_GA + - COWETA_COUNTY_GA + - DAWSON_COUNTY_GA + - DOUGHERTY_COUNTY_GA + - EFFINGHAM_COUNTY_GA + - FLOYD_COUNTY_GA + - GLYNN_COUNTY_GA + - GORDON_COUNTY_GA + - HARRIS_COUNTY_GA + - HART_COUNTY_GA + - HOUSTON_COUNTY_GA + - JACKSON_COUNTY_GA + - JONES_COUNTY_GA + - LAMAR_COUNTY_GA + - LEE_COUNTY_GA + - LIBERTY_COUNTY_GA + - LOWNDES_COUNTY_GA + - LUMPKIN_COUNTY_GA + - MADISON_COUNTY_GA + - MCDUFFIE_COUNTY_GA + - MERIWETHER_COUNTY_GA + - MORGAN_COUNTY_GA + - MURRAY_COUNTY_GA + - MUSCOGEE_COUNTY_GA + - NEWTON_COUNTY_GA + - OCONEE_COUNTY_GA + - PEACH_COUNTY_GA + - PIKE_COUNTY_GA + - PULASKI_COUNTY_GA + - PUTNAM_COUNTY_GA + - RICHMOND_COUNTY_GA + - SPALDING_COUNTY_GA + - TIFT_COUNTY_GA + - TROUP_COUNTY_GA + - WALTON_COUNTY_GA + - WHITFIELD_COUNTY_GA + +metadata: + unit: list + period: year + label: Georgia CAPS Zone 2 counties + reference: + - title: Georgia CAPS Appendix C - Reimbursement Rates (effective March 2, 2026) + href: https://caps.decal.ga.gov/assets/downloads/CAPS/Appendix_C-CAPS_Reimbursement_Rates.pdf#page=2 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/copay/ga_caps_family_fee.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/copay/ga_caps_family_fee.yaml new file mode 100644 index 00000000000..c6fa27ae095 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/copay/ga_caps_family_fee.yaml @@ -0,0 +1,180 @@ +# GA CAPS family fee (co-payment) +# Tiers by FPL ratio: +# <= 10% FPL: 0% (no fee) +# > 10% to 50% FPL: 3% of income +# > 50% to 100% FPL: 5% of income +# > 100% FPL: 7% of income +# Weekly fee = floor(annual_income * rate / 52) +# Monthly fee = weekly_fee * 52 / 12 +# Fee waived for minor parents (age <= 17) +# +# 2026 FPG family of 3: 15,960 + 5,680 * 2 = $27,320 +# 2026 FPG family of 2: 15,960 + 5,680 = $21,640 + +- name: Case 1, income over 100 percent FPL pays 7 percent. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 30_000 + person2: + age: 5 + person3: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: GA + output: + # FPL ratio = 30,000 / 27,320 = 1.098 -> 7% rate + # weekly fee = floor(30,000 * 0.07 / 52) = floor(40.38) = $40 + # monthly fee = 40 * 52 / 12 = $173.33 + ga_caps_family_fee: 173.33 + +- name: Case 2, income at or below 10 percent FPL pays zero. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 2_000 + person2: + age: 5 + person3: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: GA + output: + # FPL ratio = 2,000 / 27,320 = 0.0732 -> 0% rate + # fee = 0 + ga_caps_family_fee: 0 + +- name: Case 3, income in 3 percent tier. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 10_000 + person2: + age: 5 + person3: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: GA + output: + # FPL ratio = 10,000 / 27,320 = 0.3660 -> 3% rate + # weekly fee = floor(10,000 * 0.03 / 52) = floor(5.77) = $5 + # monthly fee = 5 * 52 / 12 = $21.67 + ga_caps_family_fee: 21.67 + +- name: Case 4, income in 5 percent tier. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 20_000 + person2: + age: 5 + person3: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: GA + output: + # FPL ratio = 20,000 / 27,320 = 0.7320 -> 5% rate + # weekly fee = floor(20,000 * 0.05 / 52) = floor(19.23) = $19 + # monthly fee = 19 * 52 / 12 = $82.33 + ga_caps_family_fee: 82.33 + +- name: Case 5, zero income family has zero fee. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # $0 income -> FPL ratio = 0 -> 0% rate -> $0 fee + ga_caps_family_fee: 0 + +- name: Case 6, minor parent fee waiver. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 17 + employment_income: 30_000 + is_tax_unit_head: true + person2: + age: 1 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # Parent age 17 <= 17 -> minor parent fee waiver -> $0 + ga_caps_family_fee: 0 + +- name: Case 7, income exactly at 10 percent FPL boundary. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 2_732 + person2: + age: 5 + person3: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: GA + output: + # FPL ratio = 2,732 / 27,320 = 0.10 -> 0% rate (at or below 10%) + # fee = 0 + ga_caps_family_fee: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/copay/ga_caps_family_fee_edge.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/copay/ga_caps_family_fee_edge.yaml new file mode 100644 index 00000000000..f68052a449f --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/copay/ga_caps_family_fee_edge.yaml @@ -0,0 +1,215 @@ +# GA CAPS family fee - edge cases +# Tiers by FPL ratio: +# <= 10% FPL: 0% (no fee) +# > 10% to 50% FPL: 3% of income +# > 50% to 100% FPL: 5% of income +# > 100% FPL: 7% of income +# Weekly fee = floor(annual_income * rate / 52) +# Monthly fee = weekly_fee * 52 / 12 +# Fee waived for minor parents (age <= 17) +# +# 2026 FPG family of 2: $21,640 +# 2026 FPG family of 3: $27,320 + +- name: Case 1, FPL ratio just above 10 percent boundary. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + # 10% of FPG for family of 2 = 21,640 * 0.10 = $2,164 + # Just above: $2,165 + employment_income: 2_165 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # FPL ratio = 2,165 / 21,640 = 0.10005 -> > 0.1001? No, 0.10005 < 0.1001 + # Still in 0% tier + ga_caps_family_fee: 0 + +- name: Case 2, FPL ratio just crossing into 3 percent tier. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + # Threshold is 0.1001 of FPG + # 0.1001 * 21,640 = $2,166.16. So income $2,167 crosses. + employment_income: 2_167 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # FPL ratio = 2,167 / 21,640 = 0.10014 -> >= 0.1001 -> 3% rate + # weekly fee = floor(2,167 * 0.03 / 52) = floor(1.25) = $1 + # monthly fee = 1 * 52 / 12 = $4.33 + ga_caps_family_fee: 4.33 + +- name: Case 3, FPL ratio exactly at 50 percent boundary. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + # 50% of FPG for family of 2 = 21,640 * 0.50 = $10,820 + employment_income: 10_820 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # FPL ratio = 10,820 / 21,640 = 0.5000 -> < 0.5001 -> 3% rate + # weekly fee = floor(10,820 * 0.03 / 52) = floor(6.24) = $6 + # monthly fee = 6 * 52 / 12 = $26.00 + ga_caps_family_fee: 26.00 + +- name: Case 4, FPL ratio just crossing into 5 percent tier. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + # 0.5001 * 21,640 = $10,822.16. So income $10,823 crosses. + employment_income: 10_823 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # FPL ratio = 10,823 / 21,640 = 0.50014 -> >= 0.5001 -> 5% rate + # weekly fee = floor(10,823 * 0.05 / 52) = floor(10.41) = $10 + # monthly fee = 10 * 52 / 12 = $43.33 + ga_caps_family_fee: 43.33 + +- name: Case 5, FPL ratio exactly at 100 percent boundary. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + # 100% of FPG for family of 2 = $21,640 + employment_income: 21_640 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # FPL ratio = 21,640 / 21,640 = 1.0000 -> < 1.0001 -> 5% rate + # weekly fee = floor(21,640 * 0.05 / 52) = floor(20.81) = $20 + # monthly fee = 20 * 52 / 12 = $86.67 + ga_caps_family_fee: 86.67 + +- name: Case 6, FPL ratio just crossing into 7 percent tier. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + # 1.0001 * 21,640 = $21,642.16. So income $21,643 crosses. + employment_income: 21_643 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # FPL ratio = 21,643 / 21,640 = 1.00014 -> >= 1.0001 -> 7% rate + # weekly fee = floor(21,643 * 0.07 / 52) = floor(29.12) = $29 + # monthly fee = 29 * 52 / 12 = $125.67 + ga_caps_family_fee: 125.67 + +- name: Case 7, minor parent age 18 does not get fee waiver. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 18 + employment_income: 30_000 + person2: + age: 1 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # Parent age 18 > 17 -> no fee waiver + # FPG family of 2: $21,640 + # FPL ratio = 30,000 / 21,640 = 1.387 -> 7% rate + # weekly fee = floor(30,000 * 0.07 / 52) = floor(40.38) = $40 + # monthly fee = 40 * 52 / 12 = $173.33 + ga_caps_family_fee: 173.33 + +- name: Case 8, larger family of 5 with lower FPG threshold. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + employment_income: 20_000 + person2: + age: 30 + person3: + age: 10 + person4: + age: 7 + person5: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5] + households: + household: + members: [person1, person2, person3, person4, person5] + state_code: GA + output: + # FPG family of 5: 15,960 + 5,680 * 4 = $38,680 + # FPL ratio = 20,000 / 38,680 = 0.5171 -> >= 0.5001 -> 5% rate + # weekly fee = floor(20,000 * 0.05 / 52) = floor(19.23) = $19 + # monthly fee = 19 * 52 / 12 = $82.33 + ga_caps_family_fee: 82.33 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_activity_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_activity_eligible.yaml new file mode 100644 index 00000000000..3b9a6c59de6 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_activity_eligible.yaml @@ -0,0 +1,139 @@ +# GA CAPS activity eligibility +# Parent must average 24 hours/week in approved activities +# (employment or full-time student) + +- name: Case 1, single parent working 24 hours meets requirement. + period: 2026-01 + input: + people: + person1: + age: 30 + weekly_hours_worked: 24 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + ga_caps_activity_eligible: true + +- name: Case 2, single parent working 23 hours does not meet requirement. + period: 2026-01 + input: + people: + person1: + age: 30 + weekly_hours_worked: 23 + is_full_time_student: false + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + ga_caps_activity_eligible: false + +- name: Case 3, full time student parent qualifies. + period: 2026-01 + input: + people: + person1: + age: 25 + weekly_hours_worked: 0 + is_full_time_student: true + person2: + age: 3 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + ga_caps_activity_eligible: true + +- name: Case 4, two parents both working 24 plus hours. + period: 2026-01 + input: + people: + person1: + age: 30 + weekly_hours_worked: 30 + person2: + age: 28 + weekly_hours_worked: 24 + person3: + age: 5 + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: GA + output: + ga_caps_activity_eligible: true + +- name: Case 5, two parents one below 24 hours. + period: 2026-01 + input: + people: + person1: + age: 30 + weekly_hours_worked: 30 + person2: + age: 28 + weekly_hours_worked: 20 + is_full_time_student: false + person3: + age: 5 + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: GA + output: + ga_caps_activity_eligible: false + +- name: Case 6, one parent works and one is a full time student. + period: 2026-01 + input: + people: + person1: + age: 30 + weekly_hours_worked: 24 + person2: + age: 25 + weekly_hours_worked: 0 + is_full_time_student: true + person3: + age: 4 + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: GA + output: + ga_caps_activity_eligible: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_activity_eligible_edge.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_activity_eligible_edge.yaml new file mode 100644 index 00000000000..eb6dd547951 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_activity_eligible_edge.yaml @@ -0,0 +1,146 @@ +# GA CAPS activity eligibility - edge cases +# Parent must average 24 hours/week in approved activities +# (employment or full-time student) +# Existing tests cover: 24, 23, student, two-parent both pass/one fail + +- name: Case 1, single parent working exactly 25 hours just above threshold. + period: 2026-01 + input: + people: + person1: + age: 30 + weekly_hours_worked: 25 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # 25 >= 24 -> eligible + ga_caps_activity_eligible: true + +- name: Case 2, single parent working zero hours and not a student. + period: 2026-01 + input: + people: + person1: + age: 30 + weekly_hours_worked: 0 + is_full_time_student: false + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # 0 < 24 and not a student -> ineligible + ga_caps_activity_eligible: false + +- name: Case 3, two parents both full-time students. + period: 2026-01 + input: + people: + person1: + age: 22 + weekly_hours_worked: 0 + is_full_time_student: true + person2: + age: 21 + weekly_hours_worked: 0 + is_full_time_student: true + person3: + age: 2 + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: GA + output: + # Both are students -> both individually eligible + ga_caps_activity_eligible: true + +- name: Case 4, two parents both below 24 hours and not students. + period: 2026-01 + input: + people: + person1: + age: 30 + weekly_hours_worked: 20 + is_full_time_student: false + person2: + age: 28 + weekly_hours_worked: 15 + is_full_time_student: false + person3: + age: 4 + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: GA + output: + # Both below 24 hrs and not students -> ineligible + ga_caps_activity_eligible: false + +- name: Case 5, single parent working 40 hours per week. + period: 2026-01 + input: + people: + person1: + age: 30 + weekly_hours_worked: 40 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # 40 >= 24 -> eligible + ga_caps_activity_eligible: true + +- name: Case 6, child hours do not matter for activity requirement. + period: 2026-01 + input: + people: + person1: + age: 30 + weekly_hours_worked: 24 + person2: + age: 10 + weekly_hours_worked: 0 + is_full_time_student: false + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # Only heads/spouses checked; child's hours irrelevant + ga_caps_activity_eligible: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_eligible.yaml new file mode 100644 index 00000000000..ef2641a5b9e --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_eligible.yaml @@ -0,0 +1,158 @@ +# GA CAPS family eligibility +# Requires: eligible child, income eligible, activity eligible, asset eligible +# +# GA SMI for 4-person household at 2026-01: $116,773.19 (uprated) +# Family of 2: 116,773.19 * 0.68 = $79,405.77 +# 50% SMI = $39,702.88 + +- name: Case 1, eligible family with child under 13 and low income. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 30_000 + immigration_status: CITIZEN + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + ga_caps_eligible: true + +- name: Case 2, ineligible due to income above 50 percent SMI. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 40_000 + immigration_status: CITIZEN + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # income 40,000 > 39,702.88 (50% SMI for family of 2) -> ineligible + ga_caps_eligible: false + +- name: Case 3, ineligible with no eligible child. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 20_000 + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: GA + output: + # no child in unit -> ineligible + ga_caps_eligible: false + +- name: Case 4, ineligible due to assets above limit. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 20_000 + immigration_status: CITIZEN + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 1_500_000 + households: + household: + members: [person1, person2] + state_code: GA + output: + ga_caps_eligible: false + +- name: Case 5, ineligible when child is undocumented. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 20_000 + immigration_status: CITIZEN + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: UNDOCUMENTED + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + ga_caps_eligible: false + +- name: Case 6, ineligible due to insufficient activity hours. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 20_000 + immigration_status: CITIZEN + weekly_hours_worked: 20 + is_full_time_student: false + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # 20 hrs/wk < 24 required -> activity ineligible -> ineligible + ga_caps_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_eligible_child.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_eligible_child.yaml new file mode 100644 index 00000000000..275fdc276e4 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_eligible_child.yaml @@ -0,0 +1,216 @@ +# GA CAPS child eligibility +# Standard: age < 13 (12 or younger) +# Disabled: age <= 17 +# Must be tax unit dependent and immigration eligible + +- name: Case 1, child under 13 who is a citizen and dependent. + period: 2026-01 + input: + people: + person1: + age: 30 + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + ga_caps_eligible_child: [false, true] + +- name: Case 2, child age 12 is eligible. + period: 2026-01 + input: + people: + person1: + age: 35 + person2: + age: 12 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # age 12 < 13 -> eligible + ga_caps_eligible_child: [false, true] + +- name: Case 3, child age 13 ineligible without disability. + period: 2026-01 + input: + people: + person1: + age: 35 + person2: + age: 13 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # age 13 not < 13 -> ineligible + ga_caps_eligible_child: [false, false] + +- name: Case 4, disabled child age 15 eligible. + period: 2026-01 + input: + people: + person1: + age: 40 + person2: + age: 15 + is_tax_unit_dependent: true + is_disabled: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # disabled, age 15 <= 17 -> eligible + ga_caps_eligible_child: [false, true] + +- name: Case 5, disabled child age 17 eligible. + period: 2026-01 + input: + people: + person1: + age: 45 + person2: + age: 17 + is_tax_unit_dependent: true + is_disabled: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # disabled, age 17 <= 17 -> eligible + ga_caps_eligible_child: [false, true] + +- name: Case 6, disabled child age 18 ineligible. + period: 2026-01 + input: + people: + person1: + age: 45 + person2: + age: 18 + is_tax_unit_dependent: true + is_disabled: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # disabled, age 18 > 17 -> ineligible + ga_caps_eligible_child: [false, false] + +- name: Case 7, child who is not a dependent is ineligible. + period: 2026-01 + input: + people: + person1: + age: 30 + person2: + age: 8 + is_tax_unit_dependent: false + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + ga_caps_eligible_child: [false, false] + +- name: Case 8, undocumented child ineligible. + period: 2026-01 + input: + people: + person1: + age: 30 + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: UNDOCUMENTED + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + ga_caps_eligible_child: [false, false] + +- name: Case 9, adult is never an eligible child. + period: 2026-01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: GA + output: + ga_caps_eligible_child: [false] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_eligible_child_edge.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_eligible_child_edge.yaml new file mode 100644 index 00000000000..347a59e7032 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_eligible_child_edge.yaml @@ -0,0 +1,202 @@ +# GA CAPS eligible child - edge cases +# Standard: age < 13 (12 or younger) +# Disabled: age <= 17 +# Tests focus on age boundaries not already covered in ga_caps_eligible_child.yaml + +- name: Case 1, infant age 0 is eligible. + period: 2026-01 + input: + people: + person1: + age: 25 + person2: + age: 0 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # age 0 < 13 -> eligible + ga_caps_eligible_child: [false, true] + +- name: Case 2, toddler age 1 is eligible. + period: 2026-01 + input: + people: + person1: + age: 25 + person2: + age: 1 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # age 1 < 13 -> eligible + ga_caps_eligible_child: [false, true] + +- name: Case 3, preschool age 3 at boundary. + period: 2026-01 + input: + people: + person1: + age: 30 + person2: + age: 3 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # age 3 < 13 -> eligible + ga_caps_eligible_child: [false, true] + +- name: Case 4, school-age 6 at boundary. + period: 2026-01 + input: + people: + person1: + age: 35 + person2: + age: 6 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # age 6 < 13 -> eligible + ga_caps_eligible_child: [false, true] + +- name: Case 5, disabled child age 13 eligible with disability. + period: 2026-01 + input: + people: + person1: + age: 40 + person2: + age: 13 + is_tax_unit_dependent: true + is_disabled: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # disabled, age 13 <= 17 -> eligible + ga_caps_eligible_child: [false, true] + +- name: Case 6, non-disabled child age 13 ineligible contrasted with disabled. + period: 2026-01 + input: + people: + person1: + age: 40 + person2: + age: 13 + is_tax_unit_dependent: true + is_disabled: false + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # not disabled, age 13 >= 13 -> ineligible + ga_caps_eligible_child: [false, false] + +- name: Case 7, two children one eligible and one over age limit. + period: 2026-01 + input: + people: + person1: + age: 40 + person2: + age: 10 + is_tax_unit_dependent: true + immigration_status: CITIZEN + person3: + age: 14 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: GA + output: + # person2: age 10 < 13 -> eligible + # person3: age 14 >= 13, not disabled -> ineligible + ga_caps_eligible_child: [false, true, false] + +- name: Case 8, legal permanent resident child is eligible. + period: 2026-01 + input: + people: + person1: + age: 30 + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: LEGAL_PERMANENT_RESIDENT + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + ga_caps_eligible_child: [false, true] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_income_eligible.yaml new file mode 100644 index 00000000000..1811883eb8b --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_income_eligible.yaml @@ -0,0 +1,129 @@ +# GA CAPS income eligibility +# Initial (not enrolled): income <= 50% SMI +# Ongoing (enrolled): income <= 85% SMI +# +# GA SMI for 4-person household at 2026-01: $116,773.19 (uprated) +# Family of 2: 116,773.19 * 0.68 = $79,405.77 +# 50% SMI = $39,702.88 +# 85% SMI = $67,494.90 + +- name: Case 1, new applicant income below 50 percent SMI. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 30_000 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # income 30,000 <= 39,702.88 (50% SMI for family of 2) -> eligible + ga_caps_income_eligible: true + +- name: Case 2, new applicant income above 50 percent SMI. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 40_000 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # income 40,000 > 39,702.88 (50% SMI for family of 2) -> ineligible + ga_caps_income_eligible: false + +- name: Case 3, enrolled family income between 50 and 85 percent SMI. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 50_000 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + ga_caps_enrolled: true + households: + household: + members: [person1, person2] + state_code: GA + output: + # enrolled: income 50,000 <= 67,494.90 (85% SMI) -> eligible + ga_caps_income_eligible: true + +- name: Case 4, enrolled family income above 85 percent SMI. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 68_000 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + ga_caps_enrolled: true + households: + household: + members: [person1, person2] + state_code: GA + output: + # enrolled: income 68,000 > 67,494.90 (85% SMI) -> ineligible + ga_caps_income_eligible: false + +- name: Case 5, non-enrolled family between 50 and 85 percent SMI. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 50_000 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + ga_caps_enrolled: false + households: + household: + members: [person1, person2] + state_code: GA + output: + # not enrolled: income 50,000 > 39,702.88 (50% SMI) -> ineligible + ga_caps_income_eligible: false + +- name: Case 6, zero income family is eligible. + period: 2026-01 + input: + people: + person1: + age: 30 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + ga_caps_income_eligible: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_income_eligible_edge.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_income_eligible_edge.yaml new file mode 100644 index 00000000000..c1735399e50 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_income_eligible_edge.yaml @@ -0,0 +1,215 @@ +# GA CAPS income eligibility - edge cases +# Initial (not enrolled): income <= 50% SMI +# Ongoing (enrolled): income <= 85% SMI +# +# GA SMI for 4-person household at 2026-01: $116,773.19 (uprated) +# Family of 2: 116,773.19 * 0.68 = $79,405.77 +# 50% SMI = $39,702.88 +# 85% SMI = $67,494.90 +# Family of 3: 116,773.19 * 0.84 = $98,089.48 +# 50% SMI = $49,044.74 +# 85% SMI = $83,376.06 +# Family of 5: 116,773.19 * 1.16 = $135,456.90 +# 50% SMI = $67,728.45 +# 85% SMI = $115,138.36 + +- name: Case 1, income exactly at 50 percent SMI threshold for family of 2. + period: 2026-01 + input: + people: + person1: + age: 30 + # 50% SMI for family of 2 is $39,702.88/yr + employment_income: 39_702 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # income 39,702 <= 39,702.88 -> eligible (just at threshold) + ga_caps_income_eligible: true + +- name: Case 2, income one dollar above 50 percent SMI threshold. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 39_703 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # income 39,703 > 39,702.88 -> ineligible + ga_caps_income_eligible: false + +- name: Case 3, enrolled income exactly at 85 percent SMI threshold. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 67_494 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + ga_caps_enrolled: true + households: + household: + members: [person1, person2] + state_code: GA + output: + # enrolled: income 67,494 <= 67,494.90 -> eligible + ga_caps_income_eligible: true + +- name: Case 4, enrolled income one dollar above 85 percent SMI. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 67_495 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + ga_caps_enrolled: true + households: + household: + members: [person1, person2] + state_code: GA + output: + # enrolled: income 67,495 > 67,494.90 -> ineligible + ga_caps_income_eligible: false + +- name: Case 5, very high income family ineligible. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 200_000 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + ga_caps_income_eligible: false + +- name: Case 6, larger family of 5 at 50 percent SMI threshold. + period: 2026-01 + input: + people: + person1: + age: 35 + employment_income: 67_728 + person2: + age: 30 + person3: + age: 10 + person4: + age: 7 + person5: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5] + households: + household: + members: [person1, person2, person3, person4, person5] + state_code: GA + output: + # 50% SMI family of 5 = $67,728.45 + # income 67,728 <= 67,728.45 -> eligible + ga_caps_income_eligible: true + +- name: Case 7, larger family of 5 one dollar over threshold. + period: 2026-01 + input: + people: + person1: + age: 35 + employment_income: 67_729 + person2: + age: 30 + person3: + age: 10 + person4: + age: 7 + person5: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5] + households: + household: + members: [person1, person2, person3, person4, person5] + state_code: GA + output: + # 50% SMI family of 5 = $67,728.45 + # income 67,729 > 67,728.45 -> ineligible + ga_caps_income_eligible: false + +- name: Case 8, enrolled family of 3 at ongoing threshold. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 83_376 + person2: + age: 28 + person3: + age: 5 + spm_units: + spm_unit: + members: [person1, person2, person3] + ga_caps_enrolled: true + households: + household: + members: [person1, person2, person3] + state_code: GA + output: + # 85% SMI family of 3 = $83,376.06 + # enrolled: income 83,376 <= 83,376.06 -> eligible + ga_caps_income_eligible: true + +- name: Case 9, multiple income sources combined. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 25_000 + self_employment_income: 10_000 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # total income = 25,000 + 10,000 = 35,000 <= 39,702.88 -> eligible + ga_caps_income_eligible: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/ga_caps_edge.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/ga_caps_edge.yaml new file mode 100644 index 00000000000..4aa83ea4656 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/ga_caps_edge.yaml @@ -0,0 +1,482 @@ +# GA CAPS benefit - edge cases +# Subsidy = min(expenses - fee, base_max) floored at 0 +# Quality bonus applied to net base payment when base_subsidy > 0 +# +# 2026 FPG (Contiguous US): +# first_person = 15,960, additional = 5,680 +# Family of 2: 21,640 +# Family of 3: 27,320 +# +# GA SMI 4-person at 2026-01: $116,773.19 (uprated) +# Family of 2: 116,773.19 * 0.68 = $79,405.77 -> 50% = $39,702.88 + +- name: Case 1, subsidy zero when fee exceeds expenses. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 35_000 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: NONE + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 2_000 + households: + household: + members: [person1, person2] + state_code: GA + county_str: FULTON_COUNTY_GA + output: + ga_caps_eligible: true + # FPG family of 2: $21,640 + # FPL ratio = 35,000 / 21,640 = 1.617 -> 7% rate + # weekly fee = floor(35,000 * 0.07 / 52) = floor(47.12) = $47 + # monthly fee = 47 * 52 / 12 = $203.67 + ga_caps_family_fee: 203.67 + # max annual = 221 * 52 = $11,492 + # annual fee = 47 * 52 = $2,444 + # uncapped = max(2,000 - 2,444, 0) = $0 (fee > expenses) + # base_subsidy = min(0, 11,492) = 0 + # quality bonus = 0 (base_subsidy is 0) + ga_caps: 0 + +- name: Case 2, quality bonus 1-star gives zero bonus. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 20_000 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: ONE_STAR + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 10_000 + households: + household: + members: [person1, person2] + state_code: GA + county_str: FULTON_COUNTY_GA + output: + ga_caps_eligible: true + # FPG family of 2: $21,640 + # FPL ratio = 20,000 / 21,640 = 0.9242 -> 5% rate + # weekly fee = floor(20,000 * 0.05 / 52) = floor(19.23) = $19 + # monthly fee = 19 * 52 / 12 = $82.33 + ga_caps_family_fee: 82.33 + # max annual = 221 * 52 = $11,492 + # annual fee = 19 * 52 = $988 + # uncapped = max(10,000 - 988, 0) = $9,012 + # base_subsidy = min(9,012, 11,492) = $9,012 + # 1-star bonus rate = 0% (threshold = 2 for 5%, 3 for 10%) + # quality_enhanced = 221 * (1 + 0) = 221/wk + # quality_max_monthly = 221 * 52 / 12 = $957.67 + # quality_bonus = 957.67 - 957.67 = 0 + # total = 9,012 / 12 + 0 = $751.00 + ga_caps: 751.00 + +- name: Case 3, quality bonus 2-star gives 5 percent. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 20_000 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: TWO_STAR + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 10_000 + households: + household: + members: [person1, person2] + state_code: GA + county_str: FULTON_COUNTY_GA + output: + ga_caps_eligible: true + # Same income/fee as Case 2 + ga_caps_family_fee: 82.33 + # base_max_monthly = 221 * 52 / 12 = $957.67 + # base_subsidy = min(max(10,000 - 988, 0), 957.67 * 12) / 12 + # = min(9,012, 11,492) / 12 = $751.00 + # quality_enhanced_weekly = 221 * 1.05 = $232.05 + # quality_max_monthly = 232.05 * 52 / 12 = $1,005.55 + # quality_bonus = 1,005.55 - 957.67 = $47.88 + # total = 751.00 + 47.88 = $798.88 + ga_caps: 798.88 + +- name: Case 4, quality bonus 3-star gives 10 percent. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 20_000 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: THREE_STAR + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 10_000 + households: + household: + members: [person1, person2] + state_code: GA + county_str: FULTON_COUNTY_GA + output: + ga_caps_eligible: true + ga_caps_family_fee: 82.33 + # base_subsidy = $751.00 (same as Cases 2-3) + # quality_enhanced_weekly = 221 * 1.10 = $243.10 + # quality_max_monthly = 243.10 * 52 / 12 = $1,053.43 + # quality_bonus = 1,053.43 - 957.67 = $95.77 + # total = 751.00 + 95.77 = $846.77 + ga_caps: 846.77 + +- name: Case 5, expenses capped at max rate. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 5_000 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: NONE + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + # Very high expenses, well above max rate + spm_unit_pre_subsidy_childcare_expenses: 25_000 + households: + household: + members: [person1, person2] + state_code: GA + county_str: FULTON_COUNTY_GA + output: + ga_caps_eligible: true + # FPL ratio = 5,000 / 21,640 = 0.231 -> 3% rate + # weekly fee = floor(5,000 * 0.03 / 52) = floor(2.88) = $2 + # monthly fee = 2 * 52 / 12 = $8.67 + ga_caps_family_fee: 8.67 + # base_max annual = 221 * 52 = $11,492 + # annual fee = 2 * 52 = $104 + # uncapped = max(25,000 - 104, 0) = $24,896 + # base_subsidy = min(24,896, 11,492) = $11,492 (capped at max) + # monthly = 11,492 / 12 = $957.67 + ga_caps: 957.67 + +- name: Case 6, minor parent with zero fee and quality bonus. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 17 + employment_income: 15_000 + immigration_status: CITIZEN + is_tax_unit_head: true + person2: + age: 0 + is_tax_unit_dependent: true + immigration_status: CITIZEN + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: THREE_STAR + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 10_000 + households: + household: + members: [person1, person2] + state_code: GA + county_str: FULTON_COUNTY_GA + output: + ga_caps_eligible: true + # Minor parent -> $0 fee + ga_caps_family_fee: 0 + # Zone 1, Center, Infant, FT = $260/week + # base_max annual = 260 * 52 = $13,520 + # uncapped = max(10,000 - 0, 0) = $10,000 + # base_subsidy = min(10,000, 13,520) = $10,000 + # base_max_monthly = 260 * 52 / 12 = $1,126.67 + # quality_enhanced_weekly = 260 * 1.10 = $286 + # quality_max_monthly = 286 * 52 / 12 = $1,239.33 + # quality_bonus = 1,239.33 - 1,126.67 = $112.67 + # monthly = 10,000/12 + 112.67 = $833.33 + $112.67 = $946.00 + ga_caps: 946.00 + +- name: Case 7, two children different age groups and care types. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 15_000 + immigration_status: CITIZEN + person2: + age: 0 + is_tax_unit_dependent: true + immigration_status: CITIZEN + ga_caps_provider_type: FAMILY + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: NONE + person3: + age: 7 + is_tax_unit_dependent: true + immigration_status: CITIZEN + ga_caps_provider_type: CENTER + ga_caps_care_type: BEFORE_AFTER_SCHOOL + ga_caps_quality_rating: NONE + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + spm_unit_pre_subsidy_childcare_expenses: 12_000 + households: + household: + members: [person1, person2, person3] + state_code: GA + county_str: CHATHAM_COUNTY_GA + output: + ga_caps_eligible_child: [false, true, true] + ga_caps_eligible: true + # Zone 2 (Chatham County) + # Child1 (age 0, Infant): Zone 2, Family, FT = $145/week + # Child2 (age 7, School Age): Zone 2, Center, B/A School = $68/week + ga_caps_maximum_weekly_benefit: [0, 145, 68] + # FPG family of 3 = $27,320 + # FPL ratio = 15,000 / 27,320 = 0.549 -> >= 0.5001 -> 5% rate + # weekly fee = floor(15,000 * 0.05 / 52) = floor(14.42) = $14 + # monthly fee = 14 * 52 / 12 = $60.67 + ga_caps_family_fee: 60.67 + # base_max annual = (145 + 68) * 52 = 213 * 52 = $11,076 + # annual fee = 14 * 52 = $728 + # uncapped = max(12,000 - 728, 0) = $11,272 + # base_subsidy = min(11,272, 11,076) = $11,076 + # quality bonus = 0 (NONE rating) + # monthly = 11,076 / 12 = $923.00 + ga_caps: 923.00 + +- name: Case 8, zero income family gets maximum subsidy up to expenses. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 0 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: NONE + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 8_000 + households: + household: + members: [person1, person2] + state_code: GA + county_str: FULTON_COUNTY_GA + output: + ga_caps_eligible: true + # $0 income -> 0% rate -> $0 fee + ga_caps_family_fee: 0 + # Zone 1, Center, Preschool, FT = $221/week + # base_max annual = 221 * 52 = $11,492 + # uncapped = max(8,000 - 0, 0) = $8,000 + # base_subsidy = min(8,000, 11,492) = $8,000 + # monthly = 8,000 / 12 = $666.67 + ga_caps: 666.67 + +- name: Case 9, subsidy with Zone 3 informal lowest rates. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 10_000 + immigration_status: CITIZEN + person2: + age: 8 + is_tax_unit_dependent: true + immigration_status: CITIZEN + ga_caps_provider_type: INFORMAL + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: NONE + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 6_000 + households: + household: + members: [person1, person2] + state_code: GA + county_str: APPLING_COUNTY_GA + output: + ga_caps_eligible: true + # FPG family of 2: $21,640 + # FPL ratio = 10,000 / 21,640 = 0.462 -> 3% rate + # weekly fee = floor(10,000 * 0.03 / 52) = floor(5.77) = $5 + # monthly fee = 5 * 52 / 12 = $21.67 + ga_caps_family_fee: 21.67 + # Zone 3, Informal, School Age, FT = $94/week + # base_max annual = 94 * 52 = $4,888 + # annual fee = 5 * 52 = $260 + # uncapped = max(6,000 - 260, 0) = $5,740 + # base_subsidy = min(5,740, 4,888) = $4,888 (capped at max rate) + # monthly = 4,888 / 12 = $407.33 + ga_caps: 407.33 + +- name: Case 10, zero childcare expenses means zero benefit. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 20_000 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: THREE_STAR + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 0 + households: + household: + members: [person1, person2] + state_code: GA + county_str: FULTON_COUNTY_GA + output: + ga_caps_eligible: true + # uncapped = max(0 - fee, 0) = 0 + # base_subsidy = 0 + # quality bonus = 0 (base_subsidy is 0, so no bonus applied) + ga_caps: 0 + +- name: Case 11, part-time care with daily rate conversion. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 10_000 + immigration_status: CITIZEN + person2: + age: 2 + is_tax_unit_dependent: true + immigration_status: CITIZEN + ga_caps_provider_type: CENTER + ga_caps_care_type: PART_TIME + ga_caps_quality_rating: NONE + childcare_days_per_week: 3 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 8_000 + households: + household: + members: [person1, person2] + state_code: GA + county_str: FULTON_COUNTY_GA + output: + ga_caps_eligible: true + # Zone 1, Center, Toddler, Part-time = $65/day + # Weekly = 65 * 3 = $195/week + ga_caps_maximum_weekly_benefit: [0, 195] + # FPG family of 2: $21,640 + # FPL ratio = 10,000 / 21,640 = 0.462 -> 3% rate + # weekly fee = floor(10,000 * 0.03 / 52) = floor(5.77) = $5 + # monthly fee = 5 * 52 / 12 = $21.67 + ga_caps_family_fee: 21.67 + # base_max annual = 195 * 52 = $10,140 + # annual fee = 5 * 52 = $260 + # uncapped = max(8,000 - 260, 0) = $7,740 + # base_subsidy = min(7,740, 10,140) = $7,740 + # monthly = 7,740 / 12 = $645.00 + ga_caps: 645.00 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/integration.yaml new file mode 100644 index 00000000000..f7ca781158b --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/integration.yaml @@ -0,0 +1,383 @@ +# GA CAPS Integration Tests +# +# 2026 FPG (Contiguous US): +# first_person = 15,960, additional = 5,680 +# Family of 2: 21,640 +# Family of 3: 27,320 +# Family of 4: 33,000 +# +# GA SMI 4-person at 2026-01: $116,773.19 (uprated) +# Family of 2: 116,773.19 * 0.68 = $79,405.77 -> 50% = $39,702.88 +# Family of 3: 116,773.19 * 0.84 = $98,089.48 -> 50% = $49,044.74 +# Family of 4: 116,773.19 * 1.00 = $116,773.19 -> 50% = $58,386.59 + +- name: Case 1, basic eligible family with Zone 1 center care. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + employment_income: 30_000 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: NONE + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 11_000 + households: + household: + members: [person1, person2] + state_code: GA + county_str: FULTON_COUNTY_GA + output: + # === Eligibility === + # Child age 4 < 13 -> age eligible + # Citizen -> immigration eligible + # Dependent -> eligible child + ga_caps_eligible_child: [false, true] + + # income 30,000 <= 39,702.88 (50% SMI for family of 2) -> income eligible + ga_caps_income_eligible: true + is_ccdf_asset_eligible: true + ga_caps_eligible: true + + # === Zone and rate === + # Fulton County -> Zone 1 + ga_caps_zone: ZONE_1 + # Age 4 -> PRESCHOOL + ga_caps_age_group: [PRESCHOOL, PRESCHOOL] + # Zone 1, Center, Preschool, Full-time = $221/week + ga_caps_maximum_weekly_benefit: [0, 221] + + # === Family fee === + # FPG family of 2: $21,640 + # FPL ratio = 30,000 / 21,640 = 1.386 -> 7% rate + # weekly fee = floor(30,000 * 0.07 / 52) = floor(40.38) = $40 + # monthly fee = 40 * 52 / 12 = $173.33 + ga_caps_family_fee: 173.33 + + # === Benefit === + # max annual = 221 * 52 = $11,492 + # annual fee = 40 * 52 = $2,080 + # uncapped = max(11,000 - 2,080, 0) = $8,920 + # annual benefit = min(8,920, 11,492) = $8,920 + # quality bonus = 0 (NONE rating) + # monthly = 8,920 / 12 = $743.33 + ga_caps: 743.33 + +- name: Case 2, low income family with zero fee. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 28 + employment_income: 2_000 + immigration_status: CITIZEN + person2: + age: 0 + is_tax_unit_dependent: true + immigration_status: CITIZEN + ga_caps_provider_type: FAMILY + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: NONE + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 8_000 + households: + household: + members: [person1, person2] + state_code: GA + county_str: FULTON_COUNTY_GA + output: + # === Eligibility === + ga_caps_eligible_child: [false, true] + ga_caps_income_eligible: true + ga_caps_eligible: true + + # === Zone and rate === + # Zone 1, Family, Infant, Full-time = $199/week + ga_caps_zone: ZONE_1 + ga_caps_age_group: [PRESCHOOL, INFANT] + ga_caps_maximum_weekly_benefit: [0, 199] + + # === Family fee === + # FPL ratio = 2,000 / 21,640 = 0.0924 -> 0% rate (<=10% FPL) + ga_caps_family_fee: 0 + + # === Benefit === + # max annual = 199 * 52 = $10,348 + # annual fee = $0 + # uncapped = max(8,000 - 0, 0) = $8,000 + # annual benefit = min(8,000, 10,348) = $8,000 + # monthly = 8,000 / 12 = $666.67 + ga_caps: 666.67 + +- name: Case 3, enrolled family at ongoing threshold with quality bonus. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 32 + employment_income: 60_000 + immigration_status: CITIZEN + person2: + age: 2 + is_tax_unit_dependent: true + immigration_status: CITIZEN + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: THREE_STAR + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + ga_caps_enrolled: true + spm_unit_pre_subsidy_childcare_expenses: 12_000 + households: + household: + members: [person1, person2] + state_code: GA + county_str: CHATHAM_COUNTY_GA + output: + # === Eligibility === + ga_caps_eligible_child: [false, true] + + # enrolled: 60,000 <= 67,494.90 (85% SMI for family of 2) -> eligible + ga_caps_income_eligible: true + ga_caps_eligible: true + + # === Zone and rate === + # Chatham County -> Zone 2 + ga_caps_zone: ZONE_2 + # Age 2 -> TODDLER + ga_caps_age_group: [PRESCHOOL, TODDLER] + # Zone 2, Center, Toddler, Full-time = $160/week + ga_caps_maximum_weekly_benefit: [0, 160] + + # === Family fee === + # FPG family of 2: $21,640 + # FPL ratio = 60,000 / 21,640 = 2.773 -> 7% rate + # weekly fee = floor(60,000 * 0.07 / 52) = floor(80.77) = $80 + # monthly fee = 80 * 52 / 12 = $346.67 + ga_caps_family_fee: 346.67 + + # === Benefit === + # Monthly expenses = 12,000 / 12 = $1,000 + # Monthly fee = $346.67 + # base_max_monthly = 160 * 52 / 12 = $693.33 + # base_subsidy = min(1,000 - 346.67, 693.33) = $653.33 + # quality_enhanced_weekly = 160 * 1.10 = $176 + # quality_max_monthly = 176 * 52 / 12 = $762.67 + # quality_bonus = 762.67 - 693.33 = $69.33 + # total = 653.33 + 69.33 = $722.67 + ga_caps: 722.67 + +- name: Case 4, ineligible family gets zero benefit. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + employment_income: 40_000 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: NONE + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 12_000 + households: + household: + members: [person1, person2] + state_code: GA + county_str: FULTON_COUNTY_GA + output: + # income 40,000 > 39,702.88 (50% SMI for family of 2) -> ineligible + ga_caps_income_eligible: false + ga_caps_eligible: false + ga_caps: 0 + +- name: Case 5, two children with different ages in Zone 3. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 20_000 + immigration_status: CITIZEN + person2: + age: 0 + is_tax_unit_dependent: true + immigration_status: CITIZEN + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: TWO_STAR + person3: + age: 8 + is_tax_unit_dependent: true + immigration_status: CITIZEN + ga_caps_provider_type: CENTER + ga_caps_care_type: BEFORE_AFTER_SCHOOL + ga_caps_quality_rating: TWO_STAR + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + spm_unit_pre_subsidy_childcare_expenses: 10_000 + households: + household: + members: [person1, person2, person3] + state_code: GA + county_str: APPLING_COUNTY_GA + output: + # === Eligibility === + ga_caps_eligible_child: [false, true, true] + + # FPG family of 3: $27,320 + # 50% SMI family of 3 = $49,044.74 + # income 20,000 <= 49,044.74 -> eligible + ga_caps_income_eligible: true + ga_caps_eligible: true + + # === Zone and rate === + # Appling County -> Zone 3 + ga_caps_zone: ZONE_3 + # child1: age 0 -> INFANT, Zone 3 Center FT = $130/week + # child2: age 8 -> SCHOOL_AGE, Zone 3 Center B/A School = $53/week + ga_caps_age_group: [PRESCHOOL, INFANT, SCHOOL_AGE] + ga_caps_maximum_weekly_benefit: [0, 130, 53] + + # === Family fee === + # FPL ratio = 20,000 / 27,320 = 0.732 -> 5% rate + # weekly fee = floor(20,000 * 0.05 / 52) = floor(19.23) = $19 + # monthly fee = 19 * 52 / 12 = $82.33 + ga_caps_family_fee: 82.33 + + # === Benefit === + # Monthly expenses = 10,000 / 12 = $833.33 + # Monthly fee = $82.33 + # base_max_monthly = 183 * 52 / 12 = $793.00 + # base_subsidy = min(833.33 - 82.33, 793.00) = $751.00 + # quality_enhanced: 130*1.05 + 53*1.05 = 192.15 + # quality_max_monthly = 192.15 * 52 / 12 = $832.65 + # quality_bonus = 832.65 - 793.00 = $39.65 + # total = 751.00 + 39.65 = $790.65 + ga_caps: 790.65 + +- name: Case 6, disabled teenager with family care in Zone 2. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 45 + employment_income: 35_000 + immigration_status: CITIZEN + person2: + age: 15 + is_tax_unit_dependent: true + is_disabled: true + immigration_status: CITIZEN + ga_caps_provider_type: FAMILY + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: NONE + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 7_000 + households: + household: + members: [person1, person2] + state_code: GA + county_str: BIBB_COUNTY_GA + output: + # === Eligibility === + # disabled, age 15 <= 17 -> eligible child + ga_caps_eligible_child: [false, true] + + # income 35,000 <= 39,702.88 (50% SMI for family of 2) -> eligible + ga_caps_income_eligible: true + ga_caps_eligible: true + + # === Zone and rate === + # Bibb County -> Zone 2 + ga_caps_zone: ZONE_2 + # Age 15 -> SCHOOL_AGE + ga_caps_age_group: [PRESCHOOL, SCHOOL_AGE] + # Zone 2, Family, School Age, Full-time = $135/week + ga_caps_maximum_weekly_benefit: [0, 135] + + # === Family fee === + # FPG family of 2: $21,640 + # FPL ratio = 35,000 / 21,640 = 1.618 -> 7% rate + # weekly fee = floor(35,000 * 0.07 / 52) = floor(47.12) = $47 + # monthly fee = 47 * 52 / 12 = $203.67 + ga_caps_family_fee: 203.67 + + # === Benefit === + # max annual = 135 * 52 = $7,020 + # annual fee = 47 * 52 = $2,444 + # uncapped = max(7,000 - 2,444, 0) = $4,556 + # annual benefit = min(4,556, 7,020) = $4,556 + # monthly = 4,556 / 12 = $379.67 + ga_caps: 379.67 + +- name: Case 7, non-Georgia family gets zero benefit. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + employment_income: 20_000 + person2: + age: 4 + is_tax_unit_dependent: true + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 10_000 + households: + household: + members: [person1, person2] + state_code: FL + output: + ga_caps: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/integration_edge.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/integration_edge.yaml new file mode 100644 index 00000000000..495bf4aad06 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/integration_edge.yaml @@ -0,0 +1,367 @@ +# GA CAPS Integration Edge Cases +# +# 2026 FPG (Contiguous US): +# first_person = 15,960, additional = 5,680 +# Family of 2: 21,640 +# Family of 3: 27,320 +# Family of 4: 33,000 +# Family of 5: 38,680 +# Family of 6: 44,360 +# +# GA SMI 4-person at 2026-01: $116,773.19 (uprated) +# Family of 2: 116,773.19 * 0.68 = $79,405.77 -> 50% = $39,702.88 +# Family of 3: 116,773.19 * 0.84 = $98,089.48 -> 50% = $49,044.74 +# Family of 5: 116,773.19 * 1.16 = $135,456.90 -> 50% = $67,728.45 +# Family of 6: 116,773.19 * 1.32 = $154,140.61 -> 50% = $77,070.30 + +- name: Case 1, large family of 6 at income threshold boundary. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 73_085 + immigration_status: CITIZEN + person2: + age: 38 + immigration_status: CITIZEN + person3: + age: 10 + is_tax_unit_dependent: true + immigration_status: CITIZEN + ga_caps_provider_type: CENTER + ga_caps_care_type: BEFORE_AFTER_SCHOOL + ga_caps_quality_rating: NONE + person4: + age: 3 + is_tax_unit_dependent: true + immigration_status: CITIZEN + ga_caps_provider_type: FAMILY + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: TWO_STAR + person5: + age: 0 + is_tax_unit_dependent: true + immigration_status: CITIZEN + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: TWO_STAR + person6: + age: 14 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2, person3, person4, person5, person6] + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5, person6] + spm_unit_pre_subsidy_childcare_expenses: 20_000 + households: + household: + members: [person1, person2, person3, person4, person5, person6] + state_code: GA + county_str: COBB_COUNTY_GA + output: + # === Eligibility === + # person3 (10): age < 13 -> eligible + # person4 (3): age < 13 -> eligible + # person5 (0): age < 13 -> eligible + # person6 (14): age >= 13, not disabled -> ineligible + ga_caps_eligible_child: [false, false, true, true, true, false] + + # 50% SMI family of 6 = $77,070.30 + # income 73,085 <= 77,070.30 -> eligible + ga_caps_income_eligible: true + ga_caps_eligible: true + + # === Zone and rates === + # Cobb County -> Zone 1 + ga_caps_zone: ZONE_1 + # person3 (10): SCHOOL_AGE, Zone 1 Center B/A School = $84/week + # person4 (3): PRESCHOOL, Zone 1 Family FT = $180/week + # person5 (0): INFANT, Zone 1 Center FT = $260/week + ga_caps_age_group: [PRESCHOOL, PRESCHOOL, SCHOOL_AGE, PRESCHOOL, INFANT, PRESCHOOL] + ga_caps_maximum_weekly_benefit: [0, 0, 84, 180, 260, 0] + + # === Family fee === + # FPG family of 6: $44,360 + # FPL ratio = 73,085 / 44,360 = 1.648 -> 7% rate + # weekly fee = floor(73,085 * 0.07 / 52) = floor(98.38) = $98 + # monthly fee = 98 * 52 / 12 = $424.67 + ga_caps_family_fee: 424.67 + + # === Benefit === + # base_max weekly = 84 + 180 + 260 = $524 + # base_max annual = 524 * 52 = $27,248 + # annual fee = 98 * 52 = $5,096 + # uncapped = max(20,000 - 5,096, 0) = $14,904 + # base_subsidy = min(14,904, 27,248) = $14,904 + # base_max_monthly = 524 * 52 / 12 = $2,270.67 + # + # quality: person3 NONE (0%), person4 TWO_STAR (5%), person5 TWO_STAR (5%) + # quality_enhanced: 84*1.00 + 180*1.05 + 260*1.05 = 84 + 189 + 273 = 546 + # quality_max_monthly = 546 * 52 / 12 = $2,366.00 + # quality_bonus = 2,366.00 - 2,270.67 = $95.33 + # monthly = 14,904/12 + 95.33 = $1,242.00 + $95.33 = $1,337.33 + ga_caps: 1_337.33 + +- name: Case 2, enrolled family between 50 and 85 percent SMI. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + employment_income: 50_000 + immigration_status: CITIZEN + person2: + age: 1 + is_tax_unit_dependent: true + immigration_status: CITIZEN + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: THREE_STAR + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + ga_caps_enrolled: true + spm_unit_pre_subsidy_childcare_expenses: 15_000 + households: + household: + members: [person1, person2] + state_code: GA + county_str: DEKALB_COUNTY_GA + output: + # === Eligibility === + ga_caps_eligible_child: [false, true] + # enrolled: 50,000 <= 67,494.90 (85% SMI) -> eligible + # NOT eligible as new applicant: 50,000 > 39,702.88 (50% SMI) + ga_caps_income_eligible: true + ga_caps_eligible: true + + # === Zone and rates === + # DeKalb County -> Zone 1 + ga_caps_zone: ZONE_1 + # Age 1 -> TODDLER, Zone 1 Center FT = $248/week + ga_caps_age_group: [PRESCHOOL, TODDLER] + ga_caps_maximum_weekly_benefit: [0, 248] + + # === Family fee === + # FPG family of 2: $21,640 + # FPL ratio = 50,000 / 21,640 = 2.311 -> 7% rate + # weekly fee = floor(50,000 * 0.07 / 52) = floor(67.31) = $67 + # monthly fee = 67 * 52 / 12 = $290.33 + ga_caps_family_fee: 290.33 + + # === Benefit === + # base_max annual = 248 * 52 = $12,896 + # annual fee = 67 * 52 = $3,484 + # uncapped = max(15,000 - 3,484, 0) = $11,516 + # base_subsidy = min(11,516, 12,896) = $11,516 + # base_max_monthly = 248 * 52 / 12 = $1,074.67 + # quality_enhanced_weekly = 248 * 1.10 = $272.80 + # quality_max_monthly = 272.80 * 52 / 12 = $1,182.13 + # quality_bonus = 1,182.13 - 1,074.67 = $107.47 + # monthly = 11,516/12 + 107.47 = $959.67 + $107.47 = $1,067.13 + ga_caps: 1_067.13 + +- name: Case 3, non-enrolled family at 50 percent SMI plus 1 dollar is ineligible. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + employment_income: 39_703 + immigration_status: CITIZEN + person2: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: THREE_STAR + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 12_000 + households: + household: + members: [person1, person2] + state_code: GA + county_str: FULTON_COUNTY_GA + output: + ga_caps_eligible_child: [false, true] + # 39,703 > 39,702.88 (50% SMI for family of 2) -> ineligible + ga_caps_income_eligible: false + ga_caps_eligible: false + ga_caps: 0 + +- name: Case 4, mixed eligible and ineligible children in family. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 45 + employment_income: 30_000 + immigration_status: CITIZEN + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: NONE + person3: + age: 14 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + spm_unit_pre_subsidy_childcare_expenses: 10_000 + households: + household: + members: [person1, person2, person3] + state_code: GA + county_str: BIBB_COUNTY_GA + output: + # person2 (5): eligible, person3 (14): ineligible (not disabled) + ga_caps_eligible_child: [false, true, false] + # Family has at least one eligible child -> eligible + ga_caps_eligible: true + # Bibb -> Zone 2 + ga_caps_zone: ZONE_2 + # Only person2 gets a rate: Zone 2 Center Preschool FT = $150/week + # person3 is not an eligible child -> 0 rate + ga_caps_maximum_weekly_benefit: [0, 150, 0] + # FPG family of 3 = $27,320 + # FPL ratio = 30,000 / 27,320 = 1.098 -> 7% rate + # weekly fee = floor(30,000 * 0.07 / 52) = floor(40.38) = $40 + # monthly fee = 40 * 52 / 12 = $173.33 + ga_caps_family_fee: 173.33 + # base_max annual = 150 * 52 = $7,800 + # annual fee = 40 * 52 = $2,080 + # uncapped = max(10,000 - 2,080, 0) = $7,920 + # base_subsidy = min(7,920, 7,800) = $7,800 + # monthly = 7,800 / 12 = $650.00 + ga_caps: 650.00 + +- name: Case 5, disabled child age 16 with family provider in Zone 3. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 50 + employment_income: 20_000 + immigration_status: CITIZEN + person2: + age: 16 + is_tax_unit_dependent: true + is_disabled: true + immigration_status: CITIZEN + ga_caps_provider_type: FAMILY + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: TWO_STAR + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 5_000 + households: + household: + members: [person1, person2] + state_code: GA + county_str: APPLING_COUNTY_GA + output: + # disabled child age 16 <= 17 -> eligible + ga_caps_eligible_child: [false, true] + ga_caps_eligible: true + # Appling -> Zone 3 + ga_caps_zone: ZONE_3 + # Age 16 -> SCHOOL_AGE, Zone 3 Family FT = $94/week + ga_caps_maximum_weekly_benefit: [0, 94] + # FPG family of 2 = $21,640 + # FPL ratio = 20,000 / 21,640 = 0.924 -> 5% rate + # weekly fee = floor(20,000 * 0.05 / 52) = floor(19.23) = $19 + # monthly fee = 19 * 52 / 12 = $82.33 + ga_caps_family_fee: 82.33 + # base_max annual = 94 * 52 = $4,888 + # annual fee = 19 * 52 = $988 + # uncapped = max(5,000 - 988, 0) = $4,012 + # base_subsidy = min(4,012, 4,888) = $4,012 + # base_max_monthly = 94 * 52 / 12 = $407.33 + # quality_enhanced = 94 * 1.05 = $98.70 + # quality_max_monthly = 98.70 * 52 / 12 = $427.70 + # quality_bonus = 427.70 - 407.33 = $20.37 + # monthly = 4,012/12 + 20.37 = $334.33 + $20.37 = $354.70 + ga_caps: 354.70 + +- name: Case 6, two-parent family where one is a student. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 20_000 + immigration_status: CITIZEN + weekly_hours_worked: 24 + person2: + age: 28 + immigration_status: CITIZEN + weekly_hours_worked: 0 + is_full_time_student: true + person3: + age: 4 + is_tax_unit_dependent: true + immigration_status: CITIZEN + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: NONE + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + spm_unit_pre_subsidy_childcare_expenses: 10_000 + households: + household: + members: [person1, person2, person3] + state_code: GA + county_str: FULTON_COUNTY_GA + output: + ga_caps_eligible_child: [false, false, true] + # parent1: 24 hrs >= 24 -> ok + # parent2: student -> ok + ga_caps_activity_eligible: true + ga_caps_eligible: true + # Zone 1, Center, Preschool, FT = $221/week + ga_caps_maximum_weekly_benefit: [0, 0, 221] + # FPG family of 3 = $27,320 + # FPL ratio = 20,000 / 27,320 = 0.732 -> 5% rate + # weekly fee = floor(20,000 * 0.05 / 52) = floor(19.23) = $19 + # monthly fee = 19 * 52 / 12 = $82.33 + ga_caps_family_fee: 82.33 + # base_max annual = 221 * 52 = $11,492 + # annual fee = 19 * 52 = $988 + # uncapped = max(10,000 - 988, 0) = $9,012 + # base_subsidy = min(9,012, 11,492) = $9,012 + # monthly = 9,012 / 12 = $751.00 + ga_caps: 751.00 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/payment/ga_caps_age_group.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/payment/ga_caps_age_group.yaml new file mode 100644 index 00000000000..e0be26ab74b --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/payment/ga_caps_age_group.yaml @@ -0,0 +1,168 @@ +# GA CAPS age groups: +# INFANT: age < 1 +# TODDLER: 1 <= age < 3 +# PRESCHOOL: 3 <= age < 6 +# SCHOOL_AGE: age >= 6 +# Age group only computed for eligible children (defined_for = ga_caps_eligible_child). +# Non-eligible persons get default PRESCHOOL. + +- name: Case 1, infant age 0. + period: 2026-01 + input: + people: + person1: + age: 30 + person2: + age: 0 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + ga_caps_age_group: [PRESCHOOL, INFANT] + +- name: Case 2, toddler age 1. + period: 2026-01 + input: + people: + person1: + age: 30 + person2: + age: 1 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + ga_caps_age_group: [PRESCHOOL, TODDLER] + +- name: Case 3, toddler age 2. + period: 2026-01 + input: + people: + person1: + age: 30 + person2: + age: 2 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + ga_caps_age_group: [PRESCHOOL, TODDLER] + +- name: Case 4, preschool age 3. + period: 2026-01 + input: + people: + person1: + age: 30 + person2: + age: 3 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + ga_caps_age_group: [PRESCHOOL, PRESCHOOL] + +- name: Case 5, preschool age 5. + period: 2026-01 + input: + people: + person1: + age: 30 + person2: + age: 5 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + ga_caps_age_group: [PRESCHOOL, PRESCHOOL] + +- name: Case 6, school age 6. + period: 2026-01 + input: + people: + person1: + age: 30 + person2: + age: 6 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + ga_caps_age_group: [PRESCHOOL, SCHOOL_AGE] + +- name: Case 7, school age 10. + period: 2026-01 + input: + people: + person1: + age: 30 + person2: + age: 10 + is_tax_unit_dependent: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + ga_caps_age_group: [PRESCHOOL, SCHOOL_AGE] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/payment/ga_caps_maximum_weekly_benefit.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/payment/ga_caps_maximum_weekly_benefit.yaml new file mode 100644 index 00000000000..1f2185e88b2 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/payment/ga_caps_maximum_weekly_benefit.yaml @@ -0,0 +1,327 @@ +# GA CAPS maximum reimbursement rate lookup +# Rates from Appendix C (effective March 2, 2026) +# Person-level variable; parent output is 0, child gets rate + +- name: Case 1, Zone 1 center full-time infant. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 0 + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + county_str: FULTON_COUNTY_GA + output: + # Zone 1, Center, Infant, Full-time = $260/week + ga_caps_maximum_weekly_benefit: [0, 260] + +- name: Case 2, Zone 1 center full-time toddler. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 2 + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + county_str: COBB_COUNTY_GA + output: + # Zone 1, Center, Toddler, Full-time = $248/week + ga_caps_maximum_weekly_benefit: [0, 248] + +- name: Case 3, Zone 1 center full-time preschool. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 4 + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + county_str: DEKALB_COUNTY_GA + output: + # Zone 1, Center, Preschool, Full-time = $221/week + ga_caps_maximum_weekly_benefit: [0, 221] + +- name: Case 4, Zone 1 center full-time school age. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 8 + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + county_str: GWINNETT_COUNTY_GA + output: + # Zone 1, Center, School Age, Full-time = $185/week + ga_caps_maximum_weekly_benefit: [0, 185] + +- name: Case 5, Zone 2 center full-time infant. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 0 + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + county_str: CHATHAM_COUNTY_GA + output: + # Zone 2, Center, Infant, Full-time = $165/week + ga_caps_maximum_weekly_benefit: [0, 165] + +- name: Case 6, Zone 3 center full-time school age. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 8 + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + county_str: APPLING_COUNTY_GA + output: + # Zone 3, Center, School Age, Full-time = $115/week + ga_caps_maximum_weekly_benefit: [0, 115] + +- name: Case 7, Zone 1 family full-time infant. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 0 + ga_caps_provider_type: FAMILY + ga_caps_care_type: FULL_TIME + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + county_str: FULTON_COUNTY_GA + output: + # Zone 1, Family, Infant, Full-time = $199/week + ga_caps_maximum_weekly_benefit: [0, 199] + +- name: Case 8, Zone 2 family full-time toddler. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 2 + ga_caps_provider_type: FAMILY + ga_caps_care_type: FULL_TIME + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + county_str: BIBB_COUNTY_GA + output: + # Zone 2, Family, Toddler, Full-time = $140/week + ga_caps_maximum_weekly_benefit: [0, 140] + +- name: Case 9, Zone 3 informal full-time preschool. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 4 + ga_caps_provider_type: INFORMAL + ga_caps_care_type: FULL_TIME + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + county_str: APPLING_COUNTY_GA + output: + # Zone 3, Informal, Preschool, Full-time = $105/week + ga_caps_maximum_weekly_benefit: [0, 105] + +- name: Case 10, Zone 1 center part-time. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 4 + ga_caps_provider_type: CENTER + ga_caps_care_type: PART_TIME + childcare_days_per_week: 1 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + county_str: FULTON_COUNTY_GA + output: + # Zone 1, Center, Part-time = $65/day * 1 day = $65/week + ga_caps_maximum_weekly_benefit: [0, 65] + +- name: Case 11, Zone 2 family part-time. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 2 + ga_caps_provider_type: FAMILY + ga_caps_care_type: PART_TIME + childcare_days_per_week: 1 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + county_str: CHATHAM_COUNTY_GA + output: + # Zone 2, Family, Part-time = $40/day * 1 day = $40/week + ga_caps_maximum_weekly_benefit: [0, 40] + +- name: Case 12, Zone 1 center before-after school. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 8 + ga_caps_provider_type: CENTER + ga_caps_care_type: BEFORE_AFTER_SCHOOL + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + county_str: FULTON_COUNTY_GA + output: + # Zone 1, Center, Before/After School = $84/week + ga_caps_maximum_weekly_benefit: [0, 84] + +- name: Case 13, Zone 3 informal before-after school. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 7 + ga_caps_provider_type: INFORMAL + ga_caps_care_type: BEFORE_AFTER_SCHOOL + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + county_str: APPLING_COUNTY_GA + output: + # Zone 3, Informal, Before/After School = $47/week + ga_caps_maximum_weekly_benefit: [0, 47] + +- name: Case 14, Zone 3 family full-time school age. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 10 + ga_caps_provider_type: FAMILY + ga_caps_care_type: FULL_TIME + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + county_str: APPLING_COUNTY_GA + output: + # Zone 3, Family, School Age, Full-time = $94/week + ga_caps_maximum_weekly_benefit: [0, 94] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/payment/ga_caps_maximum_weekly_benefit_edge.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/payment/ga_caps_maximum_weekly_benefit_edge.yaml new file mode 100644 index 00000000000..4ac7ae5839b --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/payment/ga_caps_maximum_weekly_benefit_edge.yaml @@ -0,0 +1,172 @@ +# GA CAPS maximum weekly benefit - edge cases +# Part-time rates are daily; weekly = daily * childcare_days_per_week +# Tests for part-time day conversion and provider type coverage + +- name: Case 1, Zone 1 center part-time infant 3 days per week. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 0 + ga_caps_provider_type: CENTER + ga_caps_care_type: PART_TIME + childcare_days_per_week: 3 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + county_str: FULTON_COUNTY_GA + output: + # Zone 1, Center, Infant, Part-time = $65/day + # Weekly = 65 * 3 = $195 + ga_caps_maximum_weekly_benefit: [0, 195] + +- name: Case 2, Zone 1 center part-time infant 5 days per week. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 0 + ga_caps_provider_type: CENTER + ga_caps_care_type: PART_TIME + childcare_days_per_week: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + county_str: FULTON_COUNTY_GA + output: + # Zone 1, Center, Infant, Part-time = $65/day + # Weekly = 65 * 5 = $325 + ga_caps_maximum_weekly_benefit: [0, 325] + +- name: Case 3, Zone 3 informal part-time school-age 2 days per week. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 8 + ga_caps_provider_type: INFORMAL + ga_caps_care_type: PART_TIME + childcare_days_per_week: 2 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + county_str: APPLING_COUNTY_GA + output: + # Zone 3, Informal, School Age, Part-time = $35/day + # Weekly = 35 * 2 = $70 + ga_caps_maximum_weekly_benefit: [0, 70] + +- name: Case 4, Zone 2 family before-after school toddler. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 2 + ga_caps_provider_type: FAMILY + ga_caps_care_type: BEFORE_AFTER_SCHOOL + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + county_str: CHATHAM_COUNTY_GA + output: + # Zone 2, Family, Toddler, Before-After-School = $58/week (not daily) + ga_caps_maximum_weekly_benefit: [0, 58] + +- name: Case 5, Zone 1 center full-time infant highest rate. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 0 + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + county_str: FULTON_COUNTY_GA + output: + # Zone 1, Center, Infant, Full-time = $260/week (highest rate in table) + ga_caps_maximum_weekly_benefit: [0, 260] + +- name: Case 6, Zone 3 family full-time school-age lowest full-time rate. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 8 + ga_caps_provider_type: FAMILY + ga_caps_care_type: FULL_TIME + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + county_str: APPLING_COUNTY_GA + output: + # Zone 3, Family, School Age, Full-time = $94/week (lowest FT rate) + ga_caps_maximum_weekly_benefit: [0, 94] + +- name: Case 7, part-time with 1 day per week minimum. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 4 + ga_caps_provider_type: CENTER + ga_caps_care_type: PART_TIME + childcare_days_per_week: 1 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + county_str: FULTON_COUNTY_GA + output: + # Zone 1, Center, Preschool, Part-time = $65/day + # Weekly = 65 * 1 = $65 + ga_caps_maximum_weekly_benefit: [0, 65] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/payment/ga_caps_zone.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/payment/ga_caps_zone.yaml new file mode 100644 index 00000000000..c9f57d7d7df --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/payment/ga_caps_zone.yaml @@ -0,0 +1,103 @@ +# GA CAPS zone assignment +# Zone 1: 14 counties (Fulton, Cobb, DeKalb, etc.) +# Zone 2: 46 counties (Chatham, Bibb, etc.) +# Zone 3: all remaining counties (default) + +- name: Case 1, Fulton County is Zone 1. + period: 2026-01 + input: + people: + person1: + age: 30 + households: + household: + members: [person1] + state_code: GA + county_str: FULTON_COUNTY_GA + output: + ga_caps_zone: ZONE_1 + +- name: Case 2, Cobb County is Zone 1. + period: 2026-01 + input: + people: + person1: + age: 30 + households: + household: + members: [person1] + state_code: GA + county_str: COBB_COUNTY_GA + output: + ga_caps_zone: ZONE_1 + +- name: Case 3, Chatham County is Zone 2. + period: 2026-01 + input: + people: + person1: + age: 30 + households: + household: + members: [person1] + state_code: GA + county_str: CHATHAM_COUNTY_GA + output: + ga_caps_zone: ZONE_2 + +- name: Case 4, Bibb County is Zone 2. + period: 2026-01 + input: + people: + person1: + age: 30 + households: + household: + members: [person1] + state_code: GA + county_str: BIBB_COUNTY_GA + output: + ga_caps_zone: ZONE_2 + +- name: Case 5, Appling County is Zone 3. + period: 2026-01 + input: + people: + person1: + age: 30 + households: + household: + members: [person1] + state_code: GA + county_str: APPLING_COUNTY_GA + output: + # Not in Zone 1 or Zone 2 -> Zone 3 (default) + ga_caps_zone: ZONE_3 + +- name: Case 6, Camden County is Zone 1. + period: 2026-01 + input: + people: + person1: + age: 30 + households: + household: + members: [person1] + state_code: GA + county_str: CAMDEN_COUNTY_GA + output: + ga_caps_zone: ZONE_1 + +- name: Case 7, Tift County is Zone 2. + period: 2026-01 + input: + people: + person1: + age: 30 + households: + household: + members: [person1] + state_code: GA + county_str: TIFT_COUNTY_GA + output: + ga_caps_zone: ZONE_2 diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/copay/ga_caps_family_fee.py b/policyengine_us/variables/gov/states/ga/decal/caps/copay/ga_caps_family_fee.py new file mode 100644 index 00000000000..2651b099c5b --- /dev/null +++ b/policyengine_us/variables/gov/states/ga/decal/caps/copay/ga_caps_family_fee.py @@ -0,0 +1,38 @@ +from policyengine_us.model_api import * + + +class ga_caps_family_fee(Variable): + value_type = float + entity = SPMUnit + unit = USD + label = "Georgia CAPS family fee (co-payment)" + definition_period = MONTH + defined_for = StateCode.GA + reference = ( + "https://caps.decal.ga.gov/assets/downloads/CAPS/Appendix_D-CAPS_Family_Fee_702.pdf#page=2", + "https://www.acf.hhs.gov/sites/default/files/documents/occ/georgia_2025_2027_ccdf_state_plan.pdf#page=117", + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ga.decal.caps.family_fee + # Minor parent fee waiver: parents age <= 17 have no fee. + person = spm_unit.members + is_head_or_spouse = person("is_tax_unit_head_or_spouse", period.this_year) + age = person("age", period.this_year) + has_minor_parent = spm_unit.any(is_head_or_spouse & (age <= p.minor_parent_age)) + # Compute fee from FPL-ratio scale bracket. + countable_income = spm_unit("ga_caps_countable_income", period) + fpg = spm_unit("spm_unit_fpg", period) + mask = fpg > 0 + fpl_ratio = np.divide( + countable_income, + fpg, + out=np.zeros_like(countable_income), + where=mask, + ) + fee_rate = p.rate.calc(fpl_ratio) + # Weekly fee = floor(annual income * rate / 52), then convert to monthly. + annual_income = countable_income * MONTHS_IN_YEAR + weekly_fee = np.floor(annual_income * fee_rate / WEEKS_IN_YEAR) + monthly_fee = weekly_fee * (WEEKS_IN_YEAR / MONTHS_IN_YEAR) + return where(has_minor_parent, 0, monthly_fee) diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_activity_eligible.py b/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_activity_eligible.py new file mode 100644 index 00000000000..1884bce7169 --- /dev/null +++ b/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_activity_eligible.py @@ -0,0 +1,20 @@ +from policyengine_us.model_api import * + + +class ga_caps_activity_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Eligible for Georgia CAPS based on activity requirements" + definition_period = MONTH + defined_for = StateCode.GA + reference = "https://caps.decal.ga.gov/assets/downloads/CAPS/02-CAPS_Policy-Chapter_6.pdf#page=4" + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ga.decal.caps.activity_requirements + person = spm_unit.members + is_head_or_spouse = person("is_tax_unit_head_or_spouse", period.this_year) + hours_worked = person("weekly_hours_worked", period.this_year) + meets_work_requirement = hours_worked >= p.weekly_hours + is_student = person("is_full_time_student", period.this_year) + individually_eligible = meets_work_requirement | is_student + return spm_unit.sum(is_head_or_spouse & ~individually_eligible) == 0 diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_eligible.py b/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_eligible.py new file mode 100644 index 00000000000..9e94bd09742 --- /dev/null +++ b/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_eligible.py @@ -0,0 +1,17 @@ +from policyengine_us.model_api import * + + +class ga_caps_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Eligible for Georgia CAPS" + definition_period = MONTH + defined_for = StateCode.GA + reference = "https://caps.decal.ga.gov/assets/downloads/CAPS/02-CAPS_Policy-Chapter_6.pdf#page=3" + + def formula(spm_unit, period, parameters): + has_eligible_child = add(spm_unit, period, ["ga_caps_eligible_child"]) > 0 + income_eligible = spm_unit("ga_caps_income_eligible", period) + asset_eligible = spm_unit("is_ccdf_asset_eligible", period.this_year) + activity_eligible = spm_unit("ga_caps_activity_eligible", period) + return has_eligible_child & income_eligible & asset_eligible & activity_eligible diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_eligible_child.py b/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_eligible_child.py new file mode 100644 index 00000000000..08491d098f9 --- /dev/null +++ b/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_eligible_child.py @@ -0,0 +1,24 @@ +from policyengine_us.model_api import * + + +class ga_caps_eligible_child(Variable): + value_type = bool + entity = Person + label = "Eligible child for Georgia CAPS" + definition_period = MONTH + defined_for = StateCode.GA + reference = ( + "https://caps.decal.ga.gov/assets/downloads/CAPS/02-CAPS_Policy-Chapter_6.pdf#page=3", + "https://www.acf.hhs.gov/sites/default/files/documents/occ/georgia_2025_2027_ccdf_state_plan.pdf#page=49", + ) + + def formula(person, period, parameters): + p = parameters(period).gov.states.ga.decal.caps.age_threshold + age = person("age", period.this_year) + is_disabled = person("is_disabled", period.this_year) + age_eligible = where(is_disabled, age <= p.disabled_child, age < p.child) + is_dependent = person("is_tax_unit_dependent", period.this_year) + immigration_eligible = person( + "is_ccdf_immigration_eligible_child", period.this_year + ) + return age_eligible & is_dependent & immigration_eligible diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_income_eligible.py b/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_income_eligible.py new file mode 100644 index 00000000000..87f5608b601 --- /dev/null +++ b/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_income_eligible.py @@ -0,0 +1,23 @@ +from policyengine_us.model_api import * + + +class ga_caps_income_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Eligible for Georgia CAPS based on income" + definition_period = MONTH + defined_for = StateCode.GA + reference = ( + "https://caps.decal.ga.gov/assets/downloads/CAPS/04-CAPS_Policy-Chapter_8.pdf#page=2", + "https://caps.decal.ga.gov/assets/downloads/CAPS/Appendix_A-CAPS_702_Income_Limits.pdf#page=2", + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ga.decal.caps.income.smi_rate + countable_income = spm_unit("ga_caps_countable_income", period) + smi = spm_unit("hhs_smi", period) + enrolled = spm_unit("ga_caps_enrolled", period) + initial_limit = smi * p.initial_eligibility + ongoing_limit = smi * p.ongoing_eligibility + income_limit = where(enrolled, ongoing_limit, initial_limit) + return countable_income <= income_limit diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/ga_caps.py b/policyengine_us/variables/gov/states/ga/decal/caps/ga_caps.py new file mode 100644 index 00000000000..c0125a4d1a6 --- /dev/null +++ b/policyengine_us/variables/gov/states/ga/decal/caps/ga_caps.py @@ -0,0 +1,51 @@ +from policyengine_us.model_api import * +from policyengine_us.variables.gov.states.ga.decal.caps.payment.ga_caps_quality_rating import ( + GACAPSQualityRating, +) + + +class ga_caps(Variable): + value_type = float + entity = SPMUnit + unit = USD + label = "Georgia CAPS benefit amount" + definition_period = MONTH + defined_for = "ga_caps_eligible" + reference = ( + "https://caps.decal.ga.gov/assets/downloads/CAPS/Appendix_C-CAPS_Reimbursement_Rates.pdf#page=2", + "https://www.acf.hhs.gov/sites/default/files/documents/occ/georgia_2025_2027_ccdf_state_plan.pdf#page=110", + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ga.decal.caps + family_fee = spm_unit("ga_caps_family_fee", period) + + # Sum per-child weekly max rates (base, without quality). + base_max_weekly = add(spm_unit, period, ["ga_caps_maximum_weekly_benefit"]) + base_max_monthly = base_max_weekly * (WEEKS_IN_YEAR / MONTHS_IN_YEAR) + + # Quality bonus: per-child, applied to the net base payment. + person = spm_unit.members + weekly_rate = person("ga_caps_maximum_weekly_benefit", period) + quality_rating = person("ga_caps_quality_rating", period) + star_count = select( + [ + quality_rating == GACAPSQualityRating.ONE_STAR, + quality_rating == GACAPSQualityRating.TWO_STAR, + quality_rating == GACAPSQualityRating.THREE_STAR, + ], + [1, 2, 3], + default=0, + ) + bonus_rate = p.quality_rated.bonus_rate.calc(star_count) + quality_enhanced_weekly = weekly_rate * (1 + bonus_rate) + quality_max_monthly = spm_unit.sum(quality_enhanced_weekly) * ( + WEEKS_IN_YEAR / MONTHS_IN_YEAR + ) + + # Subsidy = min(expenses - fee, base max) floored at 0. + # Quality bonus on the net base payment. + pre_subsidy = spm_unit("spm_unit_pre_subsidy_childcare_expenses", period) + base_subsidy = max_(min_(pre_subsidy - family_fee, base_max_monthly), 0) + quality_bonus = quality_max_monthly - base_max_monthly + return base_subsidy + where(base_subsidy > 0, quality_bonus, 0) diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/ga_caps_enrolled.py b/policyengine_us/variables/gov/states/ga/decal/caps/ga_caps_enrolled.py new file mode 100644 index 00000000000..2727868d864 --- /dev/null +++ b/policyengine_us/variables/gov/states/ga/decal/caps/ga_caps_enrolled.py @@ -0,0 +1,9 @@ +from policyengine_us.model_api import * + + +class ga_caps_enrolled(Variable): + value_type = bool + entity = SPMUnit + definition_period = MONTH + label = "Whether the family is currently enrolled in Georgia CAPS" + defined_for = StateCode.GA diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/ga_child_care_subsidies.py b/policyengine_us/variables/gov/states/ga/decal/caps/ga_child_care_subsidies.py new file mode 100644 index 00000000000..8da965033d6 --- /dev/null +++ b/policyengine_us/variables/gov/states/ga/decal/caps/ga_child_care_subsidies.py @@ -0,0 +1,11 @@ +from policyengine_us.model_api import * + + +class ga_child_care_subsidies(Variable): + value_type = float + entity = SPMUnit + label = "Georgia child care subsidies" + unit = USD + definition_period = YEAR + defined_for = StateCode.GA + adds = ["ga_caps"] diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/income/ga_caps_countable_income.py b/policyengine_us/variables/gov/states/ga/decal/caps/income/ga_caps_countable_income.py new file mode 100644 index 00000000000..25059d4e463 --- /dev/null +++ b/policyengine_us/variables/gov/states/ga/decal/caps/income/ga_caps_countable_income.py @@ -0,0 +1,13 @@ +from policyengine_us.model_api import * + + +class ga_caps_countable_income(Variable): + value_type = float + entity = SPMUnit + label = "Georgia CAPS countable income" + definition_period = MONTH + unit = USD + defined_for = StateCode.GA + reference = "https://caps.decal.ga.gov/assets/downloads/CAPS/04-CAPS_Policy-Chapter_8.pdf#page=3" + + adds = "gov.states.ga.decal.caps.income.countable_income.sources" diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_age_group.py b/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_age_group.py new file mode 100644 index 00000000000..78894bbf8c1 --- /dev/null +++ b/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_age_group.py @@ -0,0 +1,36 @@ +from policyengine_us.model_api import * + + +class GACAPSAgeGroup(Enum): + INFANT = "Infant" + TODDLER = "Toddler" + PRESCHOOL = "Preschool" + SCHOOL_AGE = "School Age" + + +class ga_caps_age_group(Variable): + value_type = Enum + entity = Person + possible_values = GACAPSAgeGroup + default_value = GACAPSAgeGroup.PRESCHOOL + definition_period = MONTH + defined_for = "ga_caps_eligible_child" + label = "Georgia CAPS child age group" + reference = "https://caps.decal.ga.gov/assets/downloads/CAPS/Appendix_C-CAPS_Reimbursement_Rates.pdf#page=2" + + def formula(person, period, parameters): + age = person("age", period.this_year) + p = parameters(period).gov.states.ga.decal.caps.age_group + return select( + [ + age < p.toddler_min, + age < p.preschool_min, + age < p.school_age_min, + ], + [ + GACAPSAgeGroup.INFANT, + GACAPSAgeGroup.TODDLER, + GACAPSAgeGroup.PRESCHOOL, + ], + default=GACAPSAgeGroup.SCHOOL_AGE, + ) diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_care_type.py b/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_care_type.py new file mode 100644 index 00000000000..23538ddf5ed --- /dev/null +++ b/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_care_type.py @@ -0,0 +1,18 @@ +from policyengine_us.model_api import * + + +class GACAPSCareType(Enum): + FULL_TIME = "Full Time" + PART_TIME = "Part Time" + BEFORE_AFTER_SCHOOL = "Before and After School" + + +class ga_caps_care_type(Variable): + value_type = Enum + entity = Person + possible_values = GACAPSCareType + default_value = GACAPSCareType.FULL_TIME + definition_period = MONTH + label = "Georgia CAPS care type" + defined_for = StateCode.GA + reference = "https://caps.decal.ga.gov/assets/downloads/CAPS/Appendix_C-CAPS_Reimbursement_Rates.pdf#page=2" diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_maximum_weekly_benefit.py b/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_maximum_weekly_benefit.py new file mode 100644 index 00000000000..0dbea86879f --- /dev/null +++ b/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_maximum_weekly_benefit.py @@ -0,0 +1,40 @@ +from policyengine_us.model_api import * +from policyengine_us.variables.gov.states.ga.decal.caps.payment.ga_caps_provider_type import ( + GACAPSProviderType, +) + + +class ga_caps_maximum_weekly_benefit(Variable): + value_type = float + entity = Person + unit = USD + label = "Georgia CAPS maximum weekly benefit per child" + definition_period = MONTH + defined_for = "ga_caps_eligible_child" + reference = "https://caps.decal.ga.gov/assets/downloads/CAPS/Appendix_C-CAPS_Reimbursement_Rates.pdf#page=2" + + def formula(person, period, parameters): + p = parameters(period).gov.states.ga.decal.caps.rates + zone = person.household("ga_caps_zone", period) + age_group = person("ga_caps_age_group", period) + care_type = person("ga_caps_care_type", period) + provider_type = person("ga_caps_provider_type", period) + + center_rate = p.center[zone][age_group][care_type] + family_rate = p.family[zone][age_group][care_type] + informal_rate = p.informal[zone][age_group][care_type] + + rate = select( + [ + provider_type == GACAPSProviderType.CENTER, + provider_type == GACAPSProviderType.FAMILY, + provider_type == GACAPSProviderType.INFORMAL, + ], + [center_rate, family_rate, informal_rate], + default=center_rate, + ) + + # Part-time rates are daily; convert to weekly using days per week. + is_part_time = care_type == care_type.possible_values.PART_TIME + days_per_week = person("childcare_days_per_week", period.this_year) + return where(is_part_time, rate * days_per_week, rate) diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_provider_type.py b/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_provider_type.py new file mode 100644 index 00000000000..56c025ab5d4 --- /dev/null +++ b/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_provider_type.py @@ -0,0 +1,18 @@ +from policyengine_us.model_api import * + + +class GACAPSProviderType(Enum): + CENTER = "Center" + FAMILY = "Family" + INFORMAL = "Informal" + + +class ga_caps_provider_type(Variable): + value_type = Enum + entity = Person + possible_values = GACAPSProviderType + default_value = GACAPSProviderType.CENTER + definition_period = MONTH + label = "Georgia CAPS child care provider type" + defined_for = StateCode.GA + reference = "https://caps.decal.ga.gov/assets/downloads/CAPS/Appendix_C-CAPS_Reimbursement_Rates.pdf#page=2" diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_quality_rating.py b/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_quality_rating.py new file mode 100644 index 00000000000..b069a99c660 --- /dev/null +++ b/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_quality_rating.py @@ -0,0 +1,19 @@ +from policyengine_us.model_api import * + + +class GACAPSQualityRating(Enum): + ONE_STAR = "1 Star" + TWO_STAR = "2 Stars" + THREE_STAR = "3 Stars" + NONE = "None" + + +class ga_caps_quality_rating(Variable): + value_type = Enum + entity = Person + possible_values = GACAPSQualityRating + default_value = GACAPSQualityRating.NONE + definition_period = MONTH + label = "Georgia CAPS provider Quality Rated designation" + defined_for = StateCode.GA + reference = "https://www.acf.hhs.gov/sites/default/files/documents/occ/georgia_2025_2027_ccdf_state_plan.pdf#page=110" diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_zone.py b/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_zone.py new file mode 100644 index 00000000000..d3b8882e1aa --- /dev/null +++ b/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_zone.py @@ -0,0 +1,29 @@ +from policyengine_us.model_api import * + + +class GACAPSZone(Enum): + ZONE_1 = "Zone 1" + ZONE_2 = "Zone 2" + ZONE_3 = "Zone 3" + + +class ga_caps_zone(Variable): + value_type = Enum + entity = Household + possible_values = GACAPSZone + default_value = GACAPSZone.ZONE_3 + definition_period = MONTH + defined_for = StateCode.GA + label = "Georgia CAPS geographic zone" + reference = "https://caps.decal.ga.gov/assets/downloads/CAPS/Appendix_C-CAPS_Reimbursement_Rates.pdf#page=2" + + def formula(household, period, parameters): + county = household("county_str", period) + p = parameters(period).gov.states.ga.decal.caps + is_zone_1 = np.isin(county, p.zone_1_counties) + is_zone_2 = np.isin(county, p.zone_2_counties) + return select( + [is_zone_1, is_zone_2], + [GACAPSZone.ZONE_1, GACAPSZone.ZONE_2], + default=GACAPSZone.ZONE_3, + ) diff --git a/sources/working_references.md b/sources/working_references.md index 6567b9debfb..444ddc9a21d 100644 --- a/sources/working_references.md +++ b/sources/working_references.md @@ -1,230 +1,237 @@ -# Delaware State Supplementary Payment (SSP) - Working References +# Georgia CAPS (Childcare and Parent Services) - Working References ## Program Overview -Delaware provides an optional State Supplementary Payment (SSP) to SSI recipients -residing in certified adult residential care facilities. The program has dual -administration: SSA administers the federally-administered optional supplement for -facility residents, and the Delaware Division of Social Services (DSS) administers -a separate $5/month supplement for individuals losing SSI due to SSDI (MAT program). +Georgia's child care subsidy program is called CAPS (Childcare and Parent Services), +administered by the Georgia Department of Early Care and Learning (DECAL), also known +as "Bright from the Start." The program assists low-income families with the cost of +child care while they work, go to school or training, or participate in other +work-related activities. -**Official program name**: State Supplement Payment / Optional State Supplementary Payment -**Administering agency**: SSA (federal portion) + Delaware DSS (state portion) -**Administration classification**: F (mandatory) / F/S (optional) per SI 01415.010 +**Official program name**: Childcare and Parent Services (CAPS) +**Administering agency**: Georgia Department of Early Care and Learning (DECAL) +**Federal funding source**: Child Care and Development Fund (CCDF) +**Legal authority**: 45 CFR 98 and 99; Immigration and Naturalization Act (INA) 300 et seq. ## Primary Sources -### 1. SSA POMS SI PHI01415.008 - Delaware-Specific Administration -- **URL**: https://secure.ssa.gov/poms.nsf/lnx/0501415008PHI -- **Title**: Administration of State Supplementary Programs -- Delaware (RTN 61 -- 12/2015) -- **Content**: Complete historical payment levels from 1992-2016, living arrangement - definitions, certification requirements, income limitation rules -- **Key data**: - - State supplement for certified residential care home: $140/month (individual), $448/month (couple) - - These amounts have been frozen since at least 1992 - - Effective March 1, 2003: "Residential Care Homes" include Adult Foster Care Homes, - Adult Residential Care Facilities, and Assisted Living Facilities - - Eligibility requires Adult Residential Care Certification Form - -### 2. SSA POMS SI 01415.058 - January 2026 Payment Levels -- **URL**: https://secure.ssa.gov/poms.nsf/lnx/0501415058 -- **Title**: Federally Administered Optional Supplementary Payment Programs for January 2026 -- **Content**: Current payment levels effective January 1, 2026 -- **Delaware data**: - - Individual (OS Code A): FBR $994 + supplement $140 = $1,134 total - - Couple (OS Code A): FBR $1,491 + supplement $448 = $1,939 total - - OS Code Z (non-facility): $0 supplement - - OS Code Y: waived supplementation - -### 3. SSA POMS SI 01415.057 - January 2025 Payment Levels -- **URL**: https://secure.ssa.gov/POMS.NSF/lnx/0501415057 -- **Title**: Federally Administered Optional Supplementary Payment Programs for January 2025 -- **Content**: Payment levels effective January 1, 2025 -- **Delaware data**: - - Individual (OS Code A): FBR $967 + supplement $140 = $1,107 total - - Couple (OS Code A): FBR $1,450 + supplement $448 = $1,898 total - -### 4. SSA POMS SI 01415.056 - January 2024 Payment Levels -- **URL**: https://secure.ssa.gov/apps10/poms.nsf/lnx/0501415056 -- **Title**: Federally Administered Optional Supplementary Payment Programs for January 2024 -- **Delaware data**: - - Individual (OS Code A): FBR $943 + supplement $140 = $1,083 total - - Couple (OS Code A): FBR $1,415 + supplement $448 = $1,863 total - -### 5. SSA POMS SI 01415.055 - January 2023 Payment Levels -- **URL**: https://secure.ssa.gov/poms.NSF/lnx/0501415055 -- **Delaware data**: - - Individual (OS Code A): FBR $914 + supplement $140 = $1,054 total - - Couple (OS Code A): FBR $1,371 + supplement $448 = $1,819 total - -### 6. SSA POMS SI 01415.054 - January 2022 Payment Levels -- **URL**: https://secure.ssa.gov/apps10/poms.nsf/lnx/0501415054 -- **Delaware data**: - - Individual (OS Code A): FBR $841 + supplement $140 = $981 total - - Couple (OS Code A): FBR $1,261 + supplement $448 = $1,709 total - -### 7. SSA POMS SI 01415.053 - January 2021 Payment Levels -- **URL**: https://secure.ssa.gov/apps10/poms.nsf/lnx/0501415053 -- **Delaware data**: - - Individual (OS Code A): FBR $794 + supplement $140 = $934 total - - Couple (OS Code A): FBR $1,191 + supplement $448 = $1,639 total - -### 8. SSA POMS SI 01415.052 - January 2020 Payment Levels -- **URL**: https://secure.ssa.gov/poms.nsf/lnx/0501415052 -- **Delaware data**: - - Individual (OS Code A): FBR $783 + supplement $140 = $923 total - - Couple (OS Code A): FBR $1,175 + supplement $448 = $1,623 total - -### 9. SSA POMS SI 01415.051 - January 2019 Payment Levels -- **URL**: https://secure.ssa.gov/apps10/poms.nsf/lnx/0501415051 -- **Delaware data**: - - Individual (OS Code A): FBR $771 + supplement $140 = $911 total - - Couple (OS Code A): FBR $1,157 + supplement $448 = $1,605 total - -### 10. SSA POMS SI 01415.050 - January 2018 Payment Levels -- **URL**: https://secure.ssa.gov/poms.nsf/lnx/0501415050 -- **Delaware data**: - - Individual (OS Code A): FBR $750 + supplement $140 = $890 total - - Couple (OS Code A): FBR $1,125 + supplement $448 = $1,573 total - -### 11. SSA POMS SI 01415.049 - January 2017 Payment Levels -- **URL**: https://secure.ssa.gov/poms.nsf/lnx/0501415049 -- **Delaware data**: - - Individual (OS Code A): FBR $735 + supplement $140 = $875 total - - Couple (OS Code A): FBR $1,103 + supplement $448 = $1,551 total - -### 12. SSA POMS SI 01415.047 - January 2015 Payment Levels -- **URL**: https://secure.ssa.gov/poms.nsf/lnx/0501415047 -- **Delaware data**: - - Individual (OS Code A): FBR $733 + supplement $140 = $873 total - - Couple (OS Code A): FBR $1,100 + supplement $448 = $1,548 total - -### 13. SSA POMS SI 01415.046 - January 2014 Payment Levels -- **URL**: https://secure.ssa.gov/poms.nsf/lnx/0501415046 -- **Delaware data**: - - Individual (OS Code A): FBR $721 + supplement $140 = $861 total - - Couple (OS Code A): FBR $1,082 + supplement $448 = $1,530 total - -### 14. SSA POMS SI 01415.045 - January 2013 Payment Levels -- **URL**: https://secure.ssa.gov/apps10/poms.nsf/links/0501415045 -- **Delaware data**: - - Individual (OS Code A): FBR $710 + supplement $140 = $850 total - - Couple (OS Code A): FBR $1,066 + supplement $448 = $1,514 total - -### 15. SSA POMS SI 01415.044 - January 2012 Payment Levels -- **URL**: https://secure.ssa.gov/poms.nsf/lnx/0501415044 -- **Delaware data**: - - Individual (OS Code A): FBR $698 + supplement $140 = $838 total - - Couple (OS Code A): FBR $1,048 + supplement $448 = $1,496 total - -### 16. SSA POMS SI 01415.040 - January 2008 Payment Levels -- **URL**: https://secure.ssa.gov/POMS.nsf/lnx/0501415040 -- **Delaware data**: - - Individual (OS Code A): FBR $637 + supplement $140 = $777 total - - Couple (OS Code A): FBR $956 + supplement $448 = $1,404 total - -### 17. SSA POMS SI 01415.036 - January 2004 Payment Levels -- **URL**: https://secure.ssa.gov/poms.nsf/lnx/0501415036 -- **Delaware data**: - - Individual (OS Code A): FBR $564 + supplement $140 = $704 total - - Couple (OS Code A): FBR $846 + supplement $448 = $1,294 total - -### 18. SSA POMS SI 01415.032 - January 2000 Payment Levels -- **URL**: https://secure.ssa.gov/poms.nsf/lnx/0501415032 -- **Delaware data**: - - Individual (OS Code A): FBR $512 + supplement $140 = $652 total - - Couple (OS Code A): FBR $769 + supplement $448 = $1,217 total - -### 19. SSA POMS SI 01415.031 - January 1999 Payment Levels -- **URL**: https://secure.ssa.gov/apps10/poms.nsf/lnx/0501415031 -- **Delaware data**: - - Individual (OS Code A): FBR $500 + supplement $140 = $640 total - - Couple (OS Code A): FBR $751 + supplement $448 = $1,199 total - -### 20. SSA POMS SI 01415.010 - Administration Classification -- **URL**: https://secure.ssa.gov/poms.nsf/lnx/0501415010 -- **Title**: Administration of State Supplementary Programs -- **Delaware classification**: F (mandatory) / F/S (optional) - -## Secondary Sources - -### 21. WorkWorld - SSI State Supplement Delaware -- **URL**: https://help.workworldapp.com/wwwebhelp/ssi_state_supplement_delaware.htm -- **Content**: Program overview with 2010 payment amounts -- **Key data**: - - Adult Residential Care Facility: Individual $140 supplement / Couple $448 supplement - - Special category (losing SSI due to SSDI): Individual $5 supplement (state-administered) - - Children under 18 are ineligible - - No additional income disregards beyond federal SSI limits - - Federal resource limitations apply - - Data reflects CY2010 payment levels - -### 22. Delaware Admin Code 16 Del. Admin. Code SS 13000-13640 -- **URL**: https://www.law.cornell.edu/regulations/delaware/16-Del-Admin-Code-SS-13000-13640 -- **Title**: The Social Security Administration (SSA) -- Delaware Social Services Manual -- **Content**: SSA determines eligibility for SSP for individuals in adult residential care -- **Source regulation**: 15 DE Reg. 202, 08/01/11 - -### 23. SSA State Assistance Programs for SSI Recipients, January 2011 - Delaware -- **URL**: https://www.ssa.gov/policy/docs/progdesc/ssi_st_asst/2011/de.html -- **Status**: 403 FORBIDDEN (SSA blocks automated access -- per memory note) -- **Note**: This is the discontinued 2011 SSA report. Last published edition. - -## Summary of State Supplement Amounts (FROZEN) - -The Delaware state supplement amounts have been unchanged since at least 1992: - -| Claim Type | Monthly Supplement | -|---|---| -| Individual in certified residential care | $140 | -| Couple (both eligible) in certified residential care | $448 | -| Individual losing SSI due to SSDI (MAT, state-administered) | $5 | - -## Living Arrangement / OS Code Definitions - -| OS Code | Description | Supplement? | -|---|---|---| -| A | Adult residential care facility, assisted living facility, or adult foster care home | Yes ($140 individual / $448 couple) | -| Y | Eligible but waived supplementation | No | -| Z | All other recipients (independent living, household of another, Medicaid facility) | No | - -## Federal Living Arrangement Code Mapping - -| Federal Code | Description | State Supplement When OS=A | -|---|---|---| -| A | Own household / independent living | $140 / $448 | -| B | Household of another (reduced FBR) | N/A (only OS=Z) | -| C | Parental household (child) | N/A (children ineligible) | -| D | Medicaid facility ($30 personal needs) | N/A (only OS=Z) | - -Note: Federal Code A with OS Code A is the only combination that receives a state supplement. -This means the recipient must be in a certified residential care facility AND classified as -independent living (Federal Code A) rather than in a Medicaid facility (Federal Code D). - -## Eligibility Requirements - -1. Must be SSI-eligible (aged, blind, or disabled) -- adults only (18+) -2. Must reside in Delaware -3. Must reside in a certified adult residential care facility, assisted living facility, - or adult foster care home -4. State must provide certification documentation (Adult Residential Care Certification Form) -5. No additional state income disregards beyond federal SSI rules -6. Federal SSI resource limits apply ($2,000 individual / $3,000 couple) - -## State-Administered Portion (MAT) - -The state-administered portion is specifically for: -- Individuals who lost SSI eligibility due to SSDI receipt -- $5/month supplement to maintain Medicaid eligibility during transition to Medicare -- Administered by Delaware Division of Social Services (DSS) -- Established March 1, 2001 per DSSM 17800 -- Extended September 1, 2008 to cover individuals who lost Medicaid on/after January 1, 2008 - -## Key Dates - -- **Pre-1992**: Program existed but specific amounts before 1992 not documented in POMS -- **1992-present**: $140 individual / $448 couple (frozen, no COLA) -- **March 1, 2001**: MAT program established ($5 state supplement) -- **March 1, 2003**: "Residential Care Homes" definition expanded to include Adult Foster - Care Homes, Adult Residential Care Facilities, and Assisted Living Facilities -- **September 1, 2008**: MAT coverage extended +### 1. CAPS Policy Manual (Full) +- **URL**: https://caps.decal.ga.gov/assets/downloads/CAPS/0-CAPS_Policy-Manual.pdf +- **Title**: The Childcare and Parent Services Program (CAPS) Georgia's Subsidy Program - Policy Manual +- **Content**: Complete policy manual covering all program rules (109 pages) +- **Key sections**: + - Chapter 5: Family Unit (who counts in family size) + - Chapter 6: Eligibility Requirements (residency, age, citizenship, activity requirements) + - Chapter 7: Priority Groups (13 priority categories for initial eligibility) + - Chapter 8: Income Calculations (applicable/non-applicable income, calculation methodology) + - Chapter 9: Family Fees (co-payment tiers based on FPL ratio) + - Chapter 10: Purchase of Child Care Through Scholarships (reimbursement rates, scholarship types) + - Chapter 11: Participating Providers (licensed, license-exempt, informal) +- **Downloaded to**: /tmp/ga-caps-policy-manual.pdf, text at /tmp/ga-caps-policy-manual.txt +- **Screenshots**: N/A (text extraction successful) + +### 2. Appendix A - CAPS Maximum Income Limits by Family Size +- **URL**: https://caps.decal.ga.gov/assets/downloads/CAPS/AppendixA-CAPS%20Maximum%20Income%20Limits%20by%20Family%20Size.pdf +- **Title**: CAPS Maximum Income Limits +- **Effective date**: March 2, 2026 +- **Content**: Income limits for family sizes 1-14, three thresholds: + - Very Low-Income Priority Group: 50% FPL + - Initial Eligibility: 50% SMI + - Ongoing Eligibility and Redetermination: 85% SMI +- **Key data** (family of 4): + - Very Low-Income: $16,500/year + - Initial Eligibility: $55,368/year (50% SMI) + - Ongoing/Redetermination: $94,126/year (85% SMI) +- **Downloaded to**: /tmp/ga-caps-appendix-a.pdf, text at /tmp/ga-caps-appendix-a.txt +- **Screenshot verified at 600 DPI**: /tmp/ga-caps-appendix-a-page-1.png + +### 3. Appendix C - CAPS Reimbursement Rates +- **URL**: https://caps.decal.ga.gov/assets/downloads/CAPS/AppendixC-CAPS%20Reimbursement%20Rates.pdf +- **Title**: CAPS Reimbursement Rates +- **Effective date**: March 2, 2026 +- **Content**: Weekly/daily reimbursement rates by zone (1-3), provider type (Center, Family, Informal), age group, and care type +- **Age groups**: Infant (birth-12 months), Toddler (1-2 years), Preschool (3-5 years), School age (6+ years) +- **Care types**: Full-time (per week), Part-time (per day), Before and after school (per week) +- **Key data - Zone 1 full-time weekly rates**: + | Age Group | Center | Family | Informal | + |---|---|---|---| + | Infant | $260 | $199 | $199 | + | Toddler | $248 | $188 | $188 | + | Preschool | $221 | $180 | $180 | + | School age | $185 | $156 | $156 | +- **Key data - Zone 2 full-time weekly rates**: + | Age Group | Center | Family | Informal | + |---|---|---|---| + | Infant | $165 | $145 | $145 | + | Toddler | $160 | $140 | $140 | + | Preschool | $150 | $135 | $135 | + | School age | $140 | $135 | $135 | +- **Key data - Zone 3 full-time weekly rates**: + | Age Group | Center | Family | Informal | + |---|---|---|---| + | Infant | $130 | $120 | $120 | + | Toddler | $125 | $110 | $110 | + | Preschool | $120 | $105 | $105 | + | School age | $115 | $94 | $94 | +- **Part-time (per day, all ages)**: Zone 1: $65/$53/$53, Zone 2: $45/$40/$40, Zone 3: $38/$35/$35 +- **Before/after school (per week, all ages)**: Zone 1: $84/$68/$68, Zone 2: $68/$58/$58, Zone 3: $53/$47/$47 +- **Zone 1 counties**: Camden, Cherokee, Clayton, Cobb, DeKalb, Douglas, Fayette, Forsyth, Fulton, Gwinnett, Hall, Henry, Paulding, Rockdale +- **Zone 2 counties**: Baldwin, Barrow, Bartow, Bibb, Bryan, Bulloch, Butts, Catoosa, Chatham, Clarke, Columbia, Coweta, Dawson, Dougherty, Effingham, Floyd, Glynn, Gordon, Harris, Hart, Houston, Jackson, Jones, Lamar, Lee, Liberty, Lowndes, Lumpkin, Madison, McDuffie, Meriwether, Morgan, Murray, Muscogee, Newton, Oconee, Peach, Pike, Pulaski, Putnam, Richmond, Spalding, Tift, Troup, Walton, Whitfield +- **Zone 3 counties**: All remaining counties (largest group) +- **Downloaded to**: /tmp/ga-caps-appendix-c.pdf, text at /tmp/ga-caps-appendix-c.txt +- **Screenshot verified at 600 DPI**: /tmp/ga-caps-appendix-c-page-1.png, /tmp/ga-caps-appendix-c-page-2.png + +### 4. Appendix D - Family Fee Assessment Chart +- **URL**: https://caps.decal.ga.gov/assets/downloads/CAPS/AppendixD-Family%20Fee%20Assessment%20Chart.pdf +- **Title**: CAPS Family Fee +- **Effective date**: March 2, 2026 +- **Content**: Family fee (co-payment) tiers based on ratio of income to federal poverty guidelines +- **Co-payment tiers**: + | Income-to-Poverty Ratio | Family Fee | + |---|---| + | 10% or less | No family fee | + | Over 10% to 50% | 3% of income | + | Over 50% to 100% | 5% of income | + | Over 100% | 7% of income | +- **Key rules**: + - Fee is per family (all children), NOT per child + - Weekly fee = annual gross applicable income x rate / 52, rounded down to whole dollar + - Max copay is always 7% (federal cap) + - Based on 2026 FPL guidelines +- **Income ranges for family of 4**: + - $0 to $3,300: No fee (at or below 10% FPL) + - $3,301 to $16,500: 3% (over 10% to 50% FPL) + - $16,501 to $33,000: 5% (over 50% to 100% FPL) + - $33,001 or more: 7% (over 100% FPL) +- **Downloaded to**: /tmp/ga-caps-appendix-d.pdf, text at /tmp/ga-caps-appendix-d.txt +- **Screenshot verified at 600 DPI**: /tmp/ga-caps-appendix-d-page-1.png + +### 5. CCDF State Plan FFY 2025-2027 +- **URL**: https://www.decal.ga.gov/documents/attachments/CCDFStatePlan25-27.pdf +- **Title**: Child Care and Development Fund (CCDF) Plan for Georgia FFY 2025-2027 +- **Content**: Complete federal CCDF plan describing Georgia's administration of child care subsidies +- **Key data extracted**: + - Initial eligibility: 50% SMI (increased from 40% SMI in CCDF plan period) + - Ongoing eligibility: 85% SMI (federal maximum) + - Payment rates effective 9/29/2024 (based on 2024 Market Rate Survey) + - Three market rate zones + - Quality Rated add-ons: 2-star = 5% bonus, 3-star = 10% bonus (on net base payment) + - Sliding fee scale effective March 1, 2024 + - Co-payment based on income-to-poverty ratio (4 tiers) + - Family fee waived for: DFCS custody children, minor parents (17 or younger), income at/below 10% FPL + - Asset limit: $1,000,000 (self-certified) + - Providers allowed to charge difference between published rate and subsidy amount +- **Downloaded to**: /tmp/ga-ccdf-plan-2025-27.pdf, text at /tmp/ga-ccdf-plan-2025-27.txt + +### 6. Georgia.gov CAPS Application Page +- **URL**: https://georgia.gov/apply-childcare-and-parent-services-caps-program +- **Content**: Overview of eligibility requirements for public +- **Key data**: Confirms residency, age (12 or younger / 17 with disability), citizenship, immunization, income (50% SMI), activity requirements + +### 7. CAPS Eligibility Requirements Page +- **URL**: https://caps.decal.ga.gov/en/EligibilityRequirements +- **Content**: Detailed eligibility breakdown for new applicants vs current recipients +- **Key data**: Priority group required for new applicants; 24 hours/week activity minimum; initial = 50% SMI; redetermination = 85% SMI + +### 8. GEEARS CAPS Two-Pager +- **URL**: https://geears.org/wp-content/uploads/GEEARS_CAPS_TwoPagerExtended.pdf +- **Content**: Advocacy summary of CAPS program + +## Eligibility Tests Identified + +1. **Georgia residency** (parent) +2. **Child age**: 12 or younger (17 with disability/court order) +3. **Child citizenship**: U.S. citizen or lawfully admitted qualified alien +4. **Immunization**: Current immunizations (with exceptions) +5. **Proof of identity** (parent) +6. **Priority group membership** (initial eligibility only, 13 categories) +7. **Income test - initial**: Gross applicable income <= 50% SMI +8. **Income test - ongoing**: Gross applicable income <= 85% SMI +9. **Activity requirement**: 24 hours/week average in state-approved activities (employment, education, training) +10. **Asset test**: Family assets < $1,000,000 (self-certified) + +## Income Rules + +### Applicable (counted) income: +- Gross wages/salary of all adults in family unit +- Base pay for military +- Net self-employment income +- Unemployment compensation +- Worker's compensation +- Alimony +- Child support (regular/ongoing) +- Veteran's benefits, military allotments +- Capital gains +- Rental income, dividends (regular/ongoing) +- Retirement/pension +- Commission, cash bonuses +- Lottery payments + +### Non-applicable (excluded) income: +- TANF cash assistance +- SSI benefits / disability/survivors from SSA +- Adoption supplements +- LIHEAP +- Census Bureau income +- In-kind donations +- Tax refunds +- Cash gifts +- Disaster Relief Assistance +- Relative care subsidy +- Guaranteed Basic Income (GBI) / Universal Basic Income (UBI) +- AmeriCorps unearned income +- Stipends issued by DECAL +- Income from children 17 or younger + +### Income calculation method: +- Review 4 weeks of earnings prior to determination +- Convert to monthly: weekly x 4.3333, bi-weekly x 2.1666, semi-monthly x 2 +- Convert monthly to annual: monthly x 12 +- Compare annual to Appendix A income limits + +## Family Unit Rules + +Family unit includes: +- Biological, adopted, or step children 17 or younger +- Children under legal/physical guardianship +- Spouse/parent in home +- Unmarried adults with mutual biological/legal children +- Spouse/parent temporarily absent (employment, military, training, education) + +NOT included: +- Grandparents (when parent retains custody) +- Unrelated adults without mutual children + +## Benefit Calculation + +**Subsidy = min(CAPS max reimbursement rate, provider published rate) - family fee** + +The subsidy is NOT a flat amount — it depends on: +1. Child's age group (infant/toddler/preschool/school-age) +2. Provider type (center, family home, informal) +3. Geographic zone (1, 2, or 3) +4. Care type (full-time, part-time, before/after school) +5. Provider's published rate (subsidy capped at provider's actual price) +6. Family fee (co-payment based on income-to-FPL ratio) + +**Quality Rated add-ons** (effective 9/29/2024): +- 2-star Quality Rated: 5% bonus on net base payment (base payment minus family fee) +- 3-star Quality Rated: 10% bonus on net base payment +- 1-star: No add-on + +## Key Policy Notes + +1. **Priority groups**: New applicants MUST belong to at least one of 13 priority groups. This is NOT required at redetermination. +2. **12-month eligibility period**: Once approved, families get a minimum 12-month eligibility period. +3. **Fee protection**: Family fee may decrease but NOT increase during eligibility period; can increase at redetermination. +4. **Graduated phase-out**: Families whose income exceeds initial threshold (50% SMI) but stays below 85% SMI remain eligible at redetermination. +5. **Registration fees**: CAPS authorizes up to $65/child in registration fees. +6. **Age transitions**: Rate changes at child's 1st and 3rd birthday take effect Monday following birthday. +7. **DFCS custody**: Children in foster care get subsidy at provider's full published rate; no family fee assessed. +8. **Children with disabilities**: May receive subsidy at provider's full published rate; DECAL may approve negotiated rate above published rate. +9. **Minor parents**: Parents 17 or younger have no family fee and no additional activity requirement if in school. +10. **15% QR discount removed**: As of 10/06/2025, the 15% Quality Rated discount to family fees was removed. + +## Failed Fetches + +None — all primary sources were successfully downloaded and verified. From 744e72068347e2afdd27226e08a7e6334ddfcfdb Mon Sep 17 00:00:00 2001 From: Ziming Date: Thu, 9 Apr 2026 00:43:25 -0400 Subject: [PATCH 04/11] Update changelog fragment for Georgia CAPS Co-Authored-By: Claude Opus 4.6 (1M context) --- changelog.d/ga-ccap.added.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.d/ga-ccap.added.md b/changelog.d/ga-ccap.added.md index f4a1f3c8f69..0e09b57b64c 100644 --- a/changelog.d/ga-ccap.added.md +++ b/changelog.d/ga-ccap.added.md @@ -1 +1 @@ -Implement Georgia CCAP (Childcare and Parent Services - CAPS). Closes #7957. +Implement Georgia CAPS (Childcare and Parent Services) child care subsidy program. From a4b4aa49b6afe825b4274ece97708f5ebc183fb5 Mon Sep 17 00:00:00 2001 From: Ziming Date: Thu, 9 Apr 2026 01:20:45 -0400 Subject: [PATCH 05/11] Review-fix round 1: address 4 critical issues from /review-program MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove is_tax_unit_dependent from child eligibility (use age-based check only) - Exclude children's income from countable income (CAPS Manual §8.4.3) - Apply quality bonus to net base payment, not gross rate (CCDF Plan §4767) - Correct quality bonus effective date to 2024-09-29 Co-Authored-By: Claude Opus 4.6 (1M context) --- .../decal/caps/quality_rated/bonus_rate.yaml | 6 + .../caps/eligibility/ga_caps_eligible.yaml | 10 +- .../eligibility/ga_caps_eligible_child.yaml | 38 +------ .../ga_caps_eligible_child_edge.yaml | 18 +-- .../states/ga/decal/caps/ga_caps_edge.yaml | 104 +++++++++--------- .../gov/states/ga/decal/caps/integration.yaml | 81 +++++++------- .../ga/decal/caps/integration_edge.yaml | 92 ++++++++-------- .../decal/caps/payment/ga_caps_age_group.yaml | 14 +-- .../eligibility/ga_caps_eligible_child.py | 3 +- .../gov/states/ga/decal/caps/ga_caps.py | 26 +++-- .../caps/income/ga_caps_countable_income.py | 8 +- 11 files changed, 187 insertions(+), 213 deletions(-) diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/quality_rated/bonus_rate.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/quality_rated/bonus_rate.yaml index c741a7da071..fb42477b4ce 100644 --- a/policyengine_us/parameters/gov/states/ga/decal/caps/quality_rated/bonus_rate.yaml +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/quality_rated/bonus_rate.yaml @@ -11,14 +11,20 @@ metadata: brackets: - threshold: + 2024-09-29: 0 2026-03-02: 0 amount: + 2024-09-29: 0 2026-03-02: 0 - threshold: + 2024-09-29: 2 2026-03-02: 2 amount: + 2024-09-29: 0.05 2026-03-02: 0.05 - threshold: + 2024-09-29: 3 2026-03-02: 3 amount: + 2024-09-29: 0.10 2026-03-02: 0.10 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_eligible.yaml index ef2641a5b9e..e414f1f5c4d 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_eligible.yaml @@ -15,7 +15,7 @@ immigration_status: CITIZEN person2: age: 5 - is_tax_unit_dependent: true + immigration_status: CITIZEN tax_units: tax_unit: @@ -40,7 +40,7 @@ immigration_status: CITIZEN person2: age: 5 - is_tax_unit_dependent: true + immigration_status: CITIZEN tax_units: tax_unit: @@ -88,7 +88,7 @@ immigration_status: CITIZEN person2: age: 5 - is_tax_unit_dependent: true + immigration_status: CITIZEN tax_units: tax_unit: @@ -114,7 +114,7 @@ immigration_status: CITIZEN person2: age: 5 - is_tax_unit_dependent: true + immigration_status: UNDOCUMENTED tax_units: tax_unit: @@ -141,7 +141,7 @@ is_full_time_student: false person2: age: 5 - is_tax_unit_dependent: true + immigration_status: CITIZEN tax_units: tax_unit: diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_eligible_child.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_eligible_child.yaml index 275fdc276e4..4663b7b4c3a 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_eligible_child.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_eligible_child.yaml @@ -1,9 +1,9 @@ # GA CAPS child eligibility # Standard: age < 13 (12 or younger) # Disabled: age <= 17 -# Must be tax unit dependent and immigration eligible +# Must be immigration eligible (CCDF) -- name: Case 1, child under 13 who is a citizen and dependent. +- name: Case 1, child under 13 who is a citizen. period: 2026-01 input: people: @@ -11,7 +11,6 @@ age: 30 person2: age: 5 - is_tax_unit_dependent: true immigration_status: CITIZEN tax_units: tax_unit: @@ -34,7 +33,6 @@ age: 35 person2: age: 12 - is_tax_unit_dependent: true immigration_status: CITIZEN tax_units: tax_unit: @@ -58,7 +56,6 @@ age: 35 person2: age: 13 - is_tax_unit_dependent: true immigration_status: CITIZEN tax_units: tax_unit: @@ -82,7 +79,6 @@ age: 40 person2: age: 15 - is_tax_unit_dependent: true is_disabled: true immigration_status: CITIZEN tax_units: @@ -107,7 +103,6 @@ age: 45 person2: age: 17 - is_tax_unit_dependent: true is_disabled: true immigration_status: CITIZEN tax_units: @@ -132,7 +127,6 @@ age: 45 person2: age: 18 - is_tax_unit_dependent: true is_disabled: true immigration_status: CITIZEN tax_units: @@ -149,30 +143,7 @@ # disabled, age 18 > 17 -> ineligible ga_caps_eligible_child: [false, false] -- name: Case 7, child who is not a dependent is ineligible. - period: 2026-01 - input: - people: - person1: - age: 30 - person2: - age: 8 - is_tax_unit_dependent: false - immigration_status: CITIZEN - tax_units: - tax_unit: - members: [person1, person2] - spm_units: - spm_unit: - members: [person1, person2] - households: - household: - members: [person1, person2] - state_code: GA - output: - ga_caps_eligible_child: [false, false] - -- name: Case 8, undocumented child ineligible. +- name: Case 7, undocumented child ineligible. period: 2026-01 input: people: @@ -180,7 +151,6 @@ age: 30 person2: age: 5 - is_tax_unit_dependent: true immigration_status: UNDOCUMENTED tax_units: tax_unit: @@ -195,7 +165,7 @@ output: ga_caps_eligible_child: [false, false] -- name: Case 9, adult is never an eligible child. +- name: Case 8, adult is never an eligible child. period: 2026-01 input: people: diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_eligible_child_edge.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_eligible_child_edge.yaml index 347a59e7032..baf5ed2395c 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_eligible_child_edge.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_eligible_child_edge.yaml @@ -11,7 +11,7 @@ age: 25 person2: age: 0 - is_tax_unit_dependent: true + immigration_status: CITIZEN tax_units: tax_unit: @@ -35,7 +35,7 @@ age: 25 person2: age: 1 - is_tax_unit_dependent: true + immigration_status: CITIZEN tax_units: tax_unit: @@ -59,7 +59,7 @@ age: 30 person2: age: 3 - is_tax_unit_dependent: true + immigration_status: CITIZEN tax_units: tax_unit: @@ -83,7 +83,7 @@ age: 35 person2: age: 6 - is_tax_unit_dependent: true + immigration_status: CITIZEN tax_units: tax_unit: @@ -107,7 +107,7 @@ age: 40 person2: age: 13 - is_tax_unit_dependent: true + is_disabled: true immigration_status: CITIZEN tax_units: @@ -132,7 +132,7 @@ age: 40 person2: age: 13 - is_tax_unit_dependent: true + is_disabled: false immigration_status: CITIZEN tax_units: @@ -157,11 +157,11 @@ age: 40 person2: age: 10 - is_tax_unit_dependent: true + immigration_status: CITIZEN person3: age: 14 - is_tax_unit_dependent: true + immigration_status: CITIZEN tax_units: tax_unit: @@ -186,7 +186,7 @@ age: 30 person2: age: 5 - is_tax_unit_dependent: true + immigration_status: LEGAL_PERMANENT_RESIDENT tax_units: tax_unit: diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/ga_caps_edge.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/ga_caps_edge.yaml index 4aa83ea4656..896882919af 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/ga_caps_edge.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/ga_caps_edge.yaml @@ -1,6 +1,5 @@ # GA CAPS benefit - edge cases -# Subsidy = min(expenses - fee, base_max) floored at 0 -# Quality bonus applied to net base payment when base_subsidy > 0 +# Subsidy = max(min(expenses, base_max) - fee, 0) * (1 + quality_bonus_rate) # # 2026 FPG (Contiguous US): # first_person = 15,960, additional = 5,680 @@ -21,7 +20,7 @@ immigration_status: CITIZEN person2: age: 4 - is_tax_unit_dependent: true + immigration_status: CITIZEN ga_caps_provider_type: CENTER ga_caps_care_type: FULL_TIME @@ -63,7 +62,7 @@ immigration_status: CITIZEN person2: age: 4 - is_tax_unit_dependent: true + immigration_status: CITIZEN ga_caps_provider_type: CENTER ga_caps_care_type: FULL_TIME @@ -109,7 +108,7 @@ immigration_status: CITIZEN person2: age: 4 - is_tax_unit_dependent: true + immigration_status: CITIZEN ga_caps_provider_type: CENTER ga_caps_care_type: FULL_TIME @@ -131,13 +130,12 @@ # Same income/fee as Case 2 ga_caps_family_fee: 82.33 # base_max_monthly = 221 * 52 / 12 = $957.67 - # base_subsidy = min(max(10,000 - 988, 0), 957.67 * 12) / 12 - # = min(9,012, 11,492) / 12 = $751.00 - # quality_enhanced_weekly = 221 * 1.05 = $232.05 - # quality_max_monthly = 232.05 * 52 / 12 = $1,005.55 - # quality_bonus = 1,005.55 - 957.67 = $47.88 - # total = 751.00 + 47.88 = $798.88 - ga_caps: 798.88 + # pre_subsidy_monthly = 10,000 / 12 = $833.33 + # base_payment = min(833.33, 957.67) = $833.33 + # net_base = max(833.33 - 82.33, 0) = $751.00 + # effective_bonus = (221 * 0.05) / 221 = 0.05 + # subsidy = 751.00 * 1.05 = $788.55 + ga_caps: 788.55 - name: Case 4, quality bonus 3-star gives 10 percent. period: 2026-01 @@ -150,7 +148,7 @@ immigration_status: CITIZEN person2: age: 4 - is_tax_unit_dependent: true + immigration_status: CITIZEN ga_caps_provider_type: CENTER ga_caps_care_type: FULL_TIME @@ -170,12 +168,10 @@ output: ga_caps_eligible: true ga_caps_family_fee: 82.33 - # base_subsidy = $751.00 (same as Cases 2-3) - # quality_enhanced_weekly = 221 * 1.10 = $243.10 - # quality_max_monthly = 243.10 * 52 / 12 = $1,053.43 - # quality_bonus = 1,053.43 - 957.67 = $95.77 - # total = 751.00 + 95.77 = $846.77 - ga_caps: 846.77 + # net_base = $751.00 (same as Cases 2-3) + # effective_bonus = (221 * 0.10) / 221 = 0.10 + # subsidy = 751.00 * 1.10 = $826.10 + ga_caps: 826.10 - name: Case 5, expenses capped at max rate. period: 2026-01 @@ -188,7 +184,7 @@ immigration_status: CITIZEN person2: age: 4 - is_tax_unit_dependent: true + immigration_status: CITIZEN ga_caps_provider_type: CENTER ga_caps_care_type: FULL_TIME @@ -212,12 +208,13 @@ # weekly fee = floor(5,000 * 0.03 / 52) = floor(2.88) = $2 # monthly fee = 2 * 52 / 12 = $8.67 ga_caps_family_fee: 8.67 - # base_max annual = 221 * 52 = $11,492 - # annual fee = 2 * 52 = $104 - # uncapped = max(25,000 - 104, 0) = $24,896 - # base_subsidy = min(24,896, 11,492) = $11,492 (capped at max) - # monthly = 11,492 / 12 = $957.67 - ga_caps: 957.67 + # base_max_monthly = 221 * 52 / 12 = $957.67 + # pre_subsidy_monthly = 25,000 / 12 = $2,083.33 + # base_payment = min(2,083.33, 957.67) = $957.67 + # net_base = max(957.67 - 8.67, 0) = $949.00 + # no quality bonus (NONE rating) + # subsidy = $949.00 + ga_caps: 949.00 - name: Case 6, minor parent with zero fee and quality bonus. period: 2026-01 @@ -231,7 +228,7 @@ is_tax_unit_head: true person2: age: 0 - is_tax_unit_dependent: true + immigration_status: CITIZEN ga_caps_provider_type: CENTER ga_caps_care_type: FULL_TIME @@ -253,15 +250,13 @@ # Minor parent -> $0 fee ga_caps_family_fee: 0 # Zone 1, Center, Infant, FT = $260/week - # base_max annual = 260 * 52 = $13,520 - # uncapped = max(10,000 - 0, 0) = $10,000 - # base_subsidy = min(10,000, 13,520) = $10,000 # base_max_monthly = 260 * 52 / 12 = $1,126.67 - # quality_enhanced_weekly = 260 * 1.10 = $286 - # quality_max_monthly = 286 * 52 / 12 = $1,239.33 - # quality_bonus = 1,239.33 - 1,126.67 = $112.67 - # monthly = 10,000/12 + 112.67 = $833.33 + $112.67 = $946.00 - ga_caps: 946.00 + # pre_subsidy_monthly = 10,000 / 12 = $833.33 + # base_payment = min(833.33, 1,126.67) = $833.33 + # net_base = max(833.33 - 0, 0) = $833.33 + # effective_bonus = (260 * 0.10) / 260 = 0.10 + # subsidy = 833.33 * 1.10 = $916.67 + ga_caps: 916.67 - name: Case 7, two children different age groups and care types. period: 2026-01 @@ -274,14 +269,14 @@ immigration_status: CITIZEN person2: age: 0 - is_tax_unit_dependent: true + immigration_status: CITIZEN ga_caps_provider_type: FAMILY ga_caps_care_type: FULL_TIME ga_caps_quality_rating: NONE person3: age: 7 - is_tax_unit_dependent: true + immigration_status: CITIZEN ga_caps_provider_type: CENTER ga_caps_care_type: BEFORE_AFTER_SCHOOL @@ -310,13 +305,13 @@ # weekly fee = floor(15,000 * 0.05 / 52) = floor(14.42) = $14 # monthly fee = 14 * 52 / 12 = $60.67 ga_caps_family_fee: 60.67 - # base_max annual = (145 + 68) * 52 = 213 * 52 = $11,076 - # annual fee = 14 * 52 = $728 - # uncapped = max(12,000 - 728, 0) = $11,272 - # base_subsidy = min(11,272, 11,076) = $11,076 - # quality bonus = 0 (NONE rating) - # monthly = 11,076 / 12 = $923.00 - ga_caps: 923.00 + # base_max_monthly = (145 + 68) * 52 / 12 = 213 * 52 / 12 = $923.00 + # pre_subsidy_monthly = 12,000 / 12 = $1,000 + # base_payment = min(1,000, 923.00) = $923.00 + # net_base = max(923.00 - 60.67, 0) = $862.33 + # no quality bonus (NONE rating) + # subsidy = $862.33 + ga_caps: 862.33 - name: Case 8, zero income family gets maximum subsidy up to expenses. period: 2026-01 @@ -329,7 +324,7 @@ immigration_status: CITIZEN person2: age: 4 - is_tax_unit_dependent: true + immigration_status: CITIZEN ga_caps_provider_type: CENTER ga_caps_care_type: FULL_TIME @@ -368,7 +363,7 @@ immigration_status: CITIZEN person2: age: 8 - is_tax_unit_dependent: true + immigration_status: CITIZEN ga_caps_provider_type: INFORMAL ga_caps_care_type: FULL_TIME @@ -393,12 +388,13 @@ # monthly fee = 5 * 52 / 12 = $21.67 ga_caps_family_fee: 21.67 # Zone 3, Informal, School Age, FT = $94/week - # base_max annual = 94 * 52 = $4,888 - # annual fee = 5 * 52 = $260 - # uncapped = max(6,000 - 260, 0) = $5,740 - # base_subsidy = min(5,740, 4,888) = $4,888 (capped at max rate) - # monthly = 4,888 / 12 = $407.33 - ga_caps: 407.33 + # base_max_monthly = 94 * 52 / 12 = $407.33 + # pre_subsidy_monthly = 6,000 / 12 = $500 + # base_payment = min(500, 407.33) = $407.33 + # net_base = max(407.33 - 21.67, 0) = $385.67 + # no quality bonus (NONE rating) + # subsidy = $385.67 + ga_caps: 385.67 - name: Case 10, zero childcare expenses means zero benefit. period: 2026-01 @@ -411,7 +407,7 @@ immigration_status: CITIZEN person2: age: 4 - is_tax_unit_dependent: true + immigration_status: CITIZEN ga_caps_provider_type: CENTER ga_caps_care_type: FULL_TIME @@ -446,7 +442,7 @@ immigration_status: CITIZEN person2: age: 2 - is_tax_unit_dependent: true + immigration_status: CITIZEN ga_caps_provider_type: CENTER ga_caps_care_type: PART_TIME diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/integration.yaml index f7ca781158b..5922b383053 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/integration.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/integration.yaml @@ -22,7 +22,7 @@ immigration_status: CITIZEN person2: age: 4 - is_tax_unit_dependent: true + immigration_status: CITIZEN ga_caps_provider_type: CENTER ga_caps_care_type: FULL_TIME @@ -43,7 +43,6 @@ # === Eligibility === # Child age 4 < 13 -> age eligible # Citizen -> immigration eligible - # Dependent -> eligible child ga_caps_eligible_child: [false, true] # income 30,000 <= 39,702.88 (50% SMI for family of 2) -> income eligible @@ -67,12 +66,12 @@ ga_caps_family_fee: 173.33 # === Benefit === - # max annual = 221 * 52 = $11,492 - # annual fee = 40 * 52 = $2,080 - # uncapped = max(11,000 - 2,080, 0) = $8,920 - # annual benefit = min(8,920, 11,492) = $8,920 - # quality bonus = 0 (NONE rating) - # monthly = 8,920 / 12 = $743.33 + # base_max_monthly = 221 * 52 / 12 = $957.67 + # pre_subsidy_monthly = 11,000 / 12 = $916.67 + # base_payment = min(916.67, 957.67) = $916.67 + # net_base = max(916.67 - 173.33, 0) = $743.33 + # no quality bonus (NONE rating) + # subsidy = $743.33 ga_caps: 743.33 - name: Case 2, low income family with zero fee. @@ -86,7 +85,7 @@ immigration_status: CITIZEN person2: age: 0 - is_tax_unit_dependent: true + immigration_status: CITIZEN ga_caps_provider_type: FAMILY ga_caps_care_type: FULL_TIME @@ -120,11 +119,12 @@ ga_caps_family_fee: 0 # === Benefit === - # max annual = 199 * 52 = $10,348 - # annual fee = $0 - # uncapped = max(8,000 - 0, 0) = $8,000 - # annual benefit = min(8,000, 10,348) = $8,000 - # monthly = 8,000 / 12 = $666.67 + # base_max_monthly = 199 * 52 / 12 = $862.33 + # pre_subsidy_monthly = 8,000 / 12 = $666.67 + # base_payment = min(666.67, 862.33) = $666.67 + # net_base = max(666.67 - 0, 0) = $666.67 + # no quality bonus (NONE rating) + # subsidy = $666.67 ga_caps: 666.67 - name: Case 3, enrolled family at ongoing threshold with quality bonus. @@ -138,7 +138,7 @@ immigration_status: CITIZEN person2: age: 2 - is_tax_unit_dependent: true + immigration_status: CITIZEN ga_caps_provider_type: CENTER ga_caps_care_type: FULL_TIME @@ -180,15 +180,13 @@ ga_caps_family_fee: 346.67 # === Benefit === - # Monthly expenses = 12,000 / 12 = $1,000 - # Monthly fee = $346.67 # base_max_monthly = 160 * 52 / 12 = $693.33 - # base_subsidy = min(1,000 - 346.67, 693.33) = $653.33 - # quality_enhanced_weekly = 160 * 1.10 = $176 - # quality_max_monthly = 176 * 52 / 12 = $762.67 - # quality_bonus = 762.67 - 693.33 = $69.33 - # total = 653.33 + 69.33 = $722.67 - ga_caps: 722.67 + # pre_subsidy_monthly = 12,000 / 12 = $1,000 + # base_payment = min(1,000, 693.33) = $693.33 + # net_base = max(693.33 - 346.67, 0) = $346.67 + # effective_bonus = (160 * 0.10) / 160 = 0.10 + # subsidy = 346.67 * 1.10 = $381.33 + ga_caps: 381.33 - name: Case 4, ineligible family gets zero benefit. period: 2026-01 @@ -201,7 +199,7 @@ immigration_status: CITIZEN person2: age: 4 - is_tax_unit_dependent: true + immigration_status: CITIZEN ga_caps_provider_type: CENTER ga_caps_care_type: FULL_TIME @@ -235,14 +233,14 @@ immigration_status: CITIZEN person2: age: 0 - is_tax_unit_dependent: true + immigration_status: CITIZEN ga_caps_provider_type: CENTER ga_caps_care_type: FULL_TIME ga_caps_quality_rating: TWO_STAR person3: age: 8 - is_tax_unit_dependent: true + immigration_status: CITIZEN ga_caps_provider_type: CENTER ga_caps_care_type: BEFORE_AFTER_SCHOOL @@ -284,15 +282,13 @@ ga_caps_family_fee: 82.33 # === Benefit === - # Monthly expenses = 10,000 / 12 = $833.33 - # Monthly fee = $82.33 - # base_max_monthly = 183 * 52 / 12 = $793.00 - # base_subsidy = min(833.33 - 82.33, 793.00) = $751.00 - # quality_enhanced: 130*1.05 + 53*1.05 = 192.15 - # quality_max_monthly = 192.15 * 52 / 12 = $832.65 - # quality_bonus = 832.65 - 793.00 = $39.65 - # total = 751.00 + 39.65 = $790.65 - ga_caps: 790.65 + # base_max_monthly = (130 + 53) * 52 / 12 = 183 * 52 / 12 = $793.00 + # pre_subsidy_monthly = 10,000 / 12 = $833.33 + # base_payment = min(833.33, 793.00) = $793.00 + # net_base = max(793.00 - 82.33, 0) = $710.67 + # effective_bonus = (130*0.05 + 53*0.05) / 183 = 9.15 / 183 = 0.05 + # subsidy = 710.67 * 1.05 = $746.20 + ga_caps: 746.20 - name: Case 6, disabled teenager with family care in Zone 2. period: 2026-01 @@ -305,7 +301,7 @@ immigration_status: CITIZEN person2: age: 15 - is_tax_unit_dependent: true + is_disabled: true immigration_status: CITIZEN ga_caps_provider_type: FAMILY @@ -348,11 +344,12 @@ ga_caps_family_fee: 203.67 # === Benefit === - # max annual = 135 * 52 = $7,020 - # annual fee = 47 * 52 = $2,444 - # uncapped = max(7,000 - 2,444, 0) = $4,556 - # annual benefit = min(4,556, 7,020) = $4,556 - # monthly = 4,556 / 12 = $379.67 + # base_max_monthly = 135 * 52 / 12 = $585.00 + # pre_subsidy_monthly = 7,000 / 12 = $583.33 + # base_payment = min(583.33, 585.00) = $583.33 + # net_base = max(583.33 - 203.67, 0) = $379.67 + # no quality bonus (NONE rating) + # subsidy = $379.67 ga_caps: 379.67 - name: Case 7, non-Georgia family gets zero benefit. @@ -365,7 +362,7 @@ employment_income: 20_000 person2: age: 4 - is_tax_unit_dependent: true + ga_caps_provider_type: CENTER ga_caps_care_type: FULL_TIME tax_units: diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/integration_edge.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/integration_edge.yaml index 495bf4aad06..d3cdcda24fb 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/integration_edge.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/integration_edge.yaml @@ -28,28 +28,28 @@ immigration_status: CITIZEN person3: age: 10 - is_tax_unit_dependent: true + immigration_status: CITIZEN ga_caps_provider_type: CENTER ga_caps_care_type: BEFORE_AFTER_SCHOOL ga_caps_quality_rating: NONE person4: age: 3 - is_tax_unit_dependent: true + immigration_status: CITIZEN ga_caps_provider_type: FAMILY ga_caps_care_type: FULL_TIME ga_caps_quality_rating: TWO_STAR person5: age: 0 - is_tax_unit_dependent: true + immigration_status: CITIZEN ga_caps_provider_type: CENTER ga_caps_care_type: FULL_TIME ga_caps_quality_rating: TWO_STAR person6: age: 14 - is_tax_unit_dependent: true + immigration_status: CITIZEN tax_units: tax_unit: @@ -93,19 +93,17 @@ ga_caps_family_fee: 424.67 # === Benefit === - # base_max weekly = 84 + 180 + 260 = $524 - # base_max annual = 524 * 52 = $27,248 - # annual fee = 98 * 52 = $5,096 - # uncapped = max(20,000 - 5,096, 0) = $14,904 - # base_subsidy = min(14,904, 27,248) = $14,904 + # base_max_weekly = 84 + 180 + 260 = $524 # base_max_monthly = 524 * 52 / 12 = $2,270.67 + # pre_subsidy_monthly = 20,000 / 12 = $1,666.67 + # base_payment = min(1,666.67, 2,270.67) = $1,666.67 + # net_base = max(1,666.67 - 424.67, 0) = $1,242.00 # # quality: person3 NONE (0%), person4 TWO_STAR (5%), person5 TWO_STAR (5%) - # quality_enhanced: 84*1.00 + 180*1.05 + 260*1.05 = 84 + 189 + 273 = 546 - # quality_max_monthly = 546 * 52 / 12 = $2,366.00 - # quality_bonus = 2,366.00 - 2,270.67 = $95.33 - # monthly = 14,904/12 + 95.33 = $1,242.00 + $95.33 = $1,337.33 - ga_caps: 1_337.33 + # weighted_bonus = 84*0 + 180*0.05 + 260*0.05 = 0 + 9 + 13 = 22 + # effective_bonus = 22 / 524 = 0.04198 + # subsidy = 1,242.00 * 1.04198 = $1,294.15 + ga_caps: 1_294.15 - name: Case 2, enrolled family between 50 and 85 percent SMI. period: 2026-01 @@ -118,7 +116,7 @@ immigration_status: CITIZEN person2: age: 1 - is_tax_unit_dependent: true + immigration_status: CITIZEN ga_caps_provider_type: CENTER ga_caps_care_type: FULL_TIME @@ -159,16 +157,13 @@ ga_caps_family_fee: 290.33 # === Benefit === - # base_max annual = 248 * 52 = $12,896 - # annual fee = 67 * 52 = $3,484 - # uncapped = max(15,000 - 3,484, 0) = $11,516 - # base_subsidy = min(11,516, 12,896) = $11,516 # base_max_monthly = 248 * 52 / 12 = $1,074.67 - # quality_enhanced_weekly = 248 * 1.10 = $272.80 - # quality_max_monthly = 272.80 * 52 / 12 = $1,182.13 - # quality_bonus = 1,182.13 - 1,074.67 = $107.47 - # monthly = 11,516/12 + 107.47 = $959.67 + $107.47 = $1,067.13 - ga_caps: 1_067.13 + # pre_subsidy_monthly = 15,000 / 12 = $1,250.00 + # base_payment = min(1,250.00, 1,074.67) = $1,074.67 + # net_base = max(1,074.67 - 290.33, 0) = $784.33 + # effective_bonus = (248 * 0.10) / 248 = 0.10 + # subsidy = 784.33 * 1.10 = $862.77 + ga_caps: 862.77 - name: Case 3, non-enrolled family at 50 percent SMI plus 1 dollar is ineligible. period: 2026-01 @@ -181,7 +176,7 @@ immigration_status: CITIZEN person2: age: 4 - is_tax_unit_dependent: true + immigration_status: CITIZEN ga_caps_provider_type: CENTER ga_caps_care_type: FULL_TIME @@ -216,14 +211,14 @@ immigration_status: CITIZEN person2: age: 5 - is_tax_unit_dependent: true + immigration_status: CITIZEN ga_caps_provider_type: CENTER ga_caps_care_type: FULL_TIME ga_caps_quality_rating: NONE person3: age: 14 - is_tax_unit_dependent: true + immigration_status: CITIZEN tax_units: tax_unit: @@ -252,12 +247,13 @@ # weekly fee = floor(30,000 * 0.07 / 52) = floor(40.38) = $40 # monthly fee = 40 * 52 / 12 = $173.33 ga_caps_family_fee: 173.33 - # base_max annual = 150 * 52 = $7,800 - # annual fee = 40 * 52 = $2,080 - # uncapped = max(10,000 - 2,080, 0) = $7,920 - # base_subsidy = min(7,920, 7,800) = $7,800 - # monthly = 7,800 / 12 = $650.00 - ga_caps: 650.00 + # base_max_monthly = 150 * 52 / 12 = $650.00 + # pre_subsidy_monthly = 10,000 / 12 = $833.33 + # base_payment = min(833.33, 650.00) = $650.00 + # net_base = max(650.00 - 173.33, 0) = $476.67 + # no quality bonus (NONE rating) + # subsidy = $476.67 + ga_caps: 476.67 - name: Case 5, disabled child age 16 with family provider in Zone 3. period: 2026-01 @@ -270,7 +266,7 @@ immigration_status: CITIZEN person2: age: 16 - is_tax_unit_dependent: true + is_disabled: true immigration_status: CITIZEN ga_caps_provider_type: FAMILY @@ -301,16 +297,13 @@ # weekly fee = floor(20,000 * 0.05 / 52) = floor(19.23) = $19 # monthly fee = 19 * 52 / 12 = $82.33 ga_caps_family_fee: 82.33 - # base_max annual = 94 * 52 = $4,888 - # annual fee = 19 * 52 = $988 - # uncapped = max(5,000 - 988, 0) = $4,012 - # base_subsidy = min(4,012, 4,888) = $4,012 # base_max_monthly = 94 * 52 / 12 = $407.33 - # quality_enhanced = 94 * 1.05 = $98.70 - # quality_max_monthly = 98.70 * 52 / 12 = $427.70 - # quality_bonus = 427.70 - 407.33 = $20.37 - # monthly = 4,012/12 + 20.37 = $334.33 + $20.37 = $354.70 - ga_caps: 354.70 + # pre_subsidy_monthly = 5,000 / 12 = $416.67 + # base_payment = min(416.67, 407.33) = $407.33 + # net_base = max(407.33 - 82.33, 0) = $325.00 + # effective_bonus = (94 * 0.05) / 94 = 0.05 + # subsidy = 325.00 * 1.05 = $341.25 + ga_caps: 341.25 - name: Case 6, two-parent family where one is a student. period: 2026-01 @@ -329,7 +322,7 @@ is_full_time_student: true person3: age: 4 - is_tax_unit_dependent: true + immigration_status: CITIZEN ga_caps_provider_type: CENTER ga_caps_care_type: FULL_TIME @@ -359,9 +352,10 @@ # weekly fee = floor(20,000 * 0.05 / 52) = floor(19.23) = $19 # monthly fee = 19 * 52 / 12 = $82.33 ga_caps_family_fee: 82.33 - # base_max annual = 221 * 52 = $11,492 - # annual fee = 19 * 52 = $988 - # uncapped = max(10,000 - 988, 0) = $9,012 - # base_subsidy = min(9,012, 11,492) = $9,012 - # monthly = 9,012 / 12 = $751.00 + # base_max_monthly = 221 * 52 / 12 = $957.67 + # pre_subsidy_monthly = 10,000 / 12 = $833.33 + # base_payment = min(833.33, 957.67) = $833.33 + # net_base = max(833.33 - 82.33, 0) = $751.00 + # no quality bonus (NONE rating) + # subsidy = $751.00 ga_caps: 751.00 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/payment/ga_caps_age_group.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/payment/ga_caps_age_group.yaml index e0be26ab74b..1cb9caaec3b 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/payment/ga_caps_age_group.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/payment/ga_caps_age_group.yaml @@ -14,7 +14,7 @@ age: 30 person2: age: 0 - is_tax_unit_dependent: true + immigration_status: CITIZEN tax_units: tax_unit: @@ -37,7 +37,7 @@ age: 30 person2: age: 1 - is_tax_unit_dependent: true + immigration_status: CITIZEN tax_units: tax_unit: @@ -60,7 +60,7 @@ age: 30 person2: age: 2 - is_tax_unit_dependent: true + immigration_status: CITIZEN tax_units: tax_unit: @@ -83,7 +83,7 @@ age: 30 person2: age: 3 - is_tax_unit_dependent: true + immigration_status: CITIZEN tax_units: tax_unit: @@ -106,7 +106,7 @@ age: 30 person2: age: 5 - is_tax_unit_dependent: true + immigration_status: CITIZEN tax_units: tax_unit: @@ -129,7 +129,7 @@ age: 30 person2: age: 6 - is_tax_unit_dependent: true + immigration_status: CITIZEN tax_units: tax_unit: @@ -152,7 +152,7 @@ age: 30 person2: age: 10 - is_tax_unit_dependent: true + immigration_status: CITIZEN tax_units: tax_unit: diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_eligible_child.py b/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_eligible_child.py index 08491d098f9..9fd1749beb3 100644 --- a/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_eligible_child.py +++ b/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_eligible_child.py @@ -17,8 +17,7 @@ def formula(person, period, parameters): age = person("age", period.this_year) is_disabled = person("is_disabled", period.this_year) age_eligible = where(is_disabled, age <= p.disabled_child, age < p.child) - is_dependent = person("is_tax_unit_dependent", period.this_year) immigration_eligible = person( "is_ccdf_immigration_eligible_child", period.this_year ) - return age_eligible & is_dependent & immigration_eligible + return age_eligible & immigration_eligible diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/ga_caps.py b/policyengine_us/variables/gov/states/ga/decal/caps/ga_caps.py index c0125a4d1a6..a6ca88cc09e 100644 --- a/policyengine_us/variables/gov/states/ga/decal/caps/ga_caps.py +++ b/policyengine_us/variables/gov/states/ga/decal/caps/ga_caps.py @@ -24,7 +24,14 @@ def formula(spm_unit, period, parameters): base_max_weekly = add(spm_unit, period, ["ga_caps_maximum_weekly_benefit"]) base_max_monthly = base_max_weekly * (WEEKS_IN_YEAR / MONTHS_IN_YEAR) - # Quality bonus: per-child, applied to the net base payment. + # Base payment capped at actual expenses. + pre_subsidy = spm_unit("spm_unit_pre_subsidy_childcare_expenses", period) + base_payment = min_(pre_subsidy, base_max_monthly) + + # Net base payment = base payment less family fee, floored at 0. + net_base = max_(base_payment - family_fee, 0) + + # Quality bonus: per-child weighted average bonus rate. person = spm_unit.members weekly_rate = person("ga_caps_maximum_weekly_benefit", period) quality_rating = person("ga_caps_quality_rating", period) @@ -38,14 +45,13 @@ def formula(spm_unit, period, parameters): default=0, ) bonus_rate = p.quality_rated.bonus_rate.calc(star_count) - quality_enhanced_weekly = weekly_rate * (1 + bonus_rate) - quality_max_monthly = spm_unit.sum(quality_enhanced_weekly) * ( - WEEKS_IN_YEAR / MONTHS_IN_YEAR + weighted_bonus = spm_unit.sum(weekly_rate * bonus_rate) + effective_bonus_rate = np.divide( + weighted_bonus, + base_max_weekly, + out=np.zeros_like(weighted_bonus), + where=base_max_weekly > 0, ) - # Subsidy = min(expenses - fee, base max) floored at 0. - # Quality bonus on the net base payment. - pre_subsidy = spm_unit("spm_unit_pre_subsidy_childcare_expenses", period) - base_subsidy = max_(min_(pre_subsidy - family_fee, base_max_monthly), 0) - quality_bonus = quality_max_monthly - base_max_monthly - return base_subsidy + where(base_subsidy > 0, quality_bonus, 0) + # Subsidy = net base payment * (1 + effective quality bonus rate). + return net_base * (1 + effective_bonus_rate) diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/income/ga_caps_countable_income.py b/policyengine_us/variables/gov/states/ga/decal/caps/income/ga_caps_countable_income.py index 25059d4e463..bdee8fd03e5 100644 --- a/policyengine_us/variables/gov/states/ga/decal/caps/income/ga_caps_countable_income.py +++ b/policyengine_us/variables/gov/states/ga/decal/caps/income/ga_caps_countable_income.py @@ -10,4 +10,10 @@ class ga_caps_countable_income(Variable): defined_for = StateCode.GA reference = "https://caps.decal.ga.gov/assets/downloads/CAPS/04-CAPS_Policy-Chapter_8.pdf#page=3" - adds = "gov.states.ga.decal.caps.income.countable_income.sources" + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ga.decal.caps.income.countable_income + sources = p.sources + person = spm_unit.members + is_adult = person("is_adult", period.this_year) + adult_income = sum(person(source, period) * is_adult for source in sources) + return spm_unit.sum(adult_income) From a34677a09e2efb4750b1ae6d2a90e4ac515f6c53 Mon Sep 17 00:00:00 2001 From: Ziming Date: Thu, 9 Apr 2026 01:26:22 -0400 Subject: [PATCH 06/11] Add lessons from Georgia CAPS implementation Co-Authored-By: Claude Opus 4.6 (1M context) --- lessons/agent-lessons.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 lessons/agent-lessons.md diff --git a/lessons/agent-lessons.md b/lessons/agent-lessons.md new file mode 100644 index 00000000000..014f4f7f252 --- /dev/null +++ b/lessons/agent-lessons.md @@ -0,0 +1,13 @@ +# Agent Lessons Learned + +Accumulated from /encode-policy-v2 and /backdate-program runs across all contributors. +Loaded by implementation agents on future runs. + +## New Lessons from Georgia CAPS (2026-04-09) + +### FORMULA +- When a program defines countable income at the family/unit level using an `adds` list, verify which household members' income the regulation includes; do not assume all members contribute -- regulations often exclude income from minors (e.g., children 17 or younger), requiring a formula that filters by age before summing. +- When a quality bonus or supplement is defined as a percentage of "base payment," verify whether the regulation means the gross rate or the net amount after subtracting copays/fees; applying a percentage to the wrong base (gross vs net-of-fee) systematically over- or understates the subsidy for every recipient. + +### WORKFLOW +- When a requirements document includes priority/triage categorization flags (e.g., "very low income priority") that do not gate eligibility or change benefit amounts, explicitly mark them as deferrable in the coverage report rather than treating them as missing implementation; priority flags affect waitlist ordering, not the benefit calculation pipeline. From fb18fe1e01384f969b69eb97763bb2a7eb5697e8 Mon Sep 17 00:00:00 2001 From: Ziming Date: Thu, 9 Apr 2026 15:30:22 -0400 Subject: [PATCH 07/11] Add meets_ccdf_activity_test fallback to CAPS activity eligibility Co-Authored-By: Claude Opus 4.6 (1M context) --- .../ga/decal/caps/eligibility/ga_caps_activity_eligible.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_activity_eligible.py b/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_activity_eligible.py index 1884bce7169..4ce43b4cfdd 100644 --- a/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_activity_eligible.py +++ b/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_activity_eligible.py @@ -17,4 +17,6 @@ def formula(spm_unit, period, parameters): meets_work_requirement = hours_worked >= p.weekly_hours is_student = person("is_full_time_student", period.this_year) individually_eligible = meets_work_requirement | is_student - return spm_unit.sum(is_head_or_spouse & ~individually_eligible) == 0 + all_heads_meet = spm_unit.sum(is_head_or_spouse & ~individually_eligible) == 0 + meets_ccdf = spm_unit("meets_ccdf_activity_test", period.this_year) + return all_heads_meet | meets_ccdf From 16c9545ebeaa613ea4bc03619dcdda56dea30700 Mon Sep 17 00:00:00 2001 From: Ziming Date: Thu, 14 May 2026 16:50:42 -0400 Subject: [PATCH 08/11] remove --- lessons/agent-lessons.md | 13 -- sources/working_references.md | 237 ---------------------------------- 2 files changed, 250 deletions(-) delete mode 100644 lessons/agent-lessons.md delete mode 100644 sources/working_references.md diff --git a/lessons/agent-lessons.md b/lessons/agent-lessons.md deleted file mode 100644 index 014f4f7f252..00000000000 --- a/lessons/agent-lessons.md +++ /dev/null @@ -1,13 +0,0 @@ -# Agent Lessons Learned - -Accumulated from /encode-policy-v2 and /backdate-program runs across all contributors. -Loaded by implementation agents on future runs. - -## New Lessons from Georgia CAPS (2026-04-09) - -### FORMULA -- When a program defines countable income at the family/unit level using an `adds` list, verify which household members' income the regulation includes; do not assume all members contribute -- regulations often exclude income from minors (e.g., children 17 or younger), requiring a formula that filters by age before summing. -- When a quality bonus or supplement is defined as a percentage of "base payment," verify whether the regulation means the gross rate or the net amount after subtracting copays/fees; applying a percentage to the wrong base (gross vs net-of-fee) systematically over- or understates the subsidy for every recipient. - -### WORKFLOW -- When a requirements document includes priority/triage categorization flags (e.g., "very low income priority") that do not gate eligibility or change benefit amounts, explicitly mark them as deferrable in the coverage report rather than treating them as missing implementation; priority flags affect waitlist ordering, not the benefit calculation pipeline. diff --git a/sources/working_references.md b/sources/working_references.md deleted file mode 100644 index 444ddc9a21d..00000000000 --- a/sources/working_references.md +++ /dev/null @@ -1,237 +0,0 @@ -# Georgia CAPS (Childcare and Parent Services) - Working References - -## Program Overview - -Georgia's child care subsidy program is called CAPS (Childcare and Parent Services), -administered by the Georgia Department of Early Care and Learning (DECAL), also known -as "Bright from the Start." The program assists low-income families with the cost of -child care while they work, go to school or training, or participate in other -work-related activities. - -**Official program name**: Childcare and Parent Services (CAPS) -**Administering agency**: Georgia Department of Early Care and Learning (DECAL) -**Federal funding source**: Child Care and Development Fund (CCDF) -**Legal authority**: 45 CFR 98 and 99; Immigration and Naturalization Act (INA) 300 et seq. - -## Primary Sources - -### 1. CAPS Policy Manual (Full) -- **URL**: https://caps.decal.ga.gov/assets/downloads/CAPS/0-CAPS_Policy-Manual.pdf -- **Title**: The Childcare and Parent Services Program (CAPS) Georgia's Subsidy Program - Policy Manual -- **Content**: Complete policy manual covering all program rules (109 pages) -- **Key sections**: - - Chapter 5: Family Unit (who counts in family size) - - Chapter 6: Eligibility Requirements (residency, age, citizenship, activity requirements) - - Chapter 7: Priority Groups (13 priority categories for initial eligibility) - - Chapter 8: Income Calculations (applicable/non-applicable income, calculation methodology) - - Chapter 9: Family Fees (co-payment tiers based on FPL ratio) - - Chapter 10: Purchase of Child Care Through Scholarships (reimbursement rates, scholarship types) - - Chapter 11: Participating Providers (licensed, license-exempt, informal) -- **Downloaded to**: /tmp/ga-caps-policy-manual.pdf, text at /tmp/ga-caps-policy-manual.txt -- **Screenshots**: N/A (text extraction successful) - -### 2. Appendix A - CAPS Maximum Income Limits by Family Size -- **URL**: https://caps.decal.ga.gov/assets/downloads/CAPS/AppendixA-CAPS%20Maximum%20Income%20Limits%20by%20Family%20Size.pdf -- **Title**: CAPS Maximum Income Limits -- **Effective date**: March 2, 2026 -- **Content**: Income limits for family sizes 1-14, three thresholds: - - Very Low-Income Priority Group: 50% FPL - - Initial Eligibility: 50% SMI - - Ongoing Eligibility and Redetermination: 85% SMI -- **Key data** (family of 4): - - Very Low-Income: $16,500/year - - Initial Eligibility: $55,368/year (50% SMI) - - Ongoing/Redetermination: $94,126/year (85% SMI) -- **Downloaded to**: /tmp/ga-caps-appendix-a.pdf, text at /tmp/ga-caps-appendix-a.txt -- **Screenshot verified at 600 DPI**: /tmp/ga-caps-appendix-a-page-1.png - -### 3. Appendix C - CAPS Reimbursement Rates -- **URL**: https://caps.decal.ga.gov/assets/downloads/CAPS/AppendixC-CAPS%20Reimbursement%20Rates.pdf -- **Title**: CAPS Reimbursement Rates -- **Effective date**: March 2, 2026 -- **Content**: Weekly/daily reimbursement rates by zone (1-3), provider type (Center, Family, Informal), age group, and care type -- **Age groups**: Infant (birth-12 months), Toddler (1-2 years), Preschool (3-5 years), School age (6+ years) -- **Care types**: Full-time (per week), Part-time (per day), Before and after school (per week) -- **Key data - Zone 1 full-time weekly rates**: - | Age Group | Center | Family | Informal | - |---|---|---|---| - | Infant | $260 | $199 | $199 | - | Toddler | $248 | $188 | $188 | - | Preschool | $221 | $180 | $180 | - | School age | $185 | $156 | $156 | -- **Key data - Zone 2 full-time weekly rates**: - | Age Group | Center | Family | Informal | - |---|---|---|---| - | Infant | $165 | $145 | $145 | - | Toddler | $160 | $140 | $140 | - | Preschool | $150 | $135 | $135 | - | School age | $140 | $135 | $135 | -- **Key data - Zone 3 full-time weekly rates**: - | Age Group | Center | Family | Informal | - |---|---|---|---| - | Infant | $130 | $120 | $120 | - | Toddler | $125 | $110 | $110 | - | Preschool | $120 | $105 | $105 | - | School age | $115 | $94 | $94 | -- **Part-time (per day, all ages)**: Zone 1: $65/$53/$53, Zone 2: $45/$40/$40, Zone 3: $38/$35/$35 -- **Before/after school (per week, all ages)**: Zone 1: $84/$68/$68, Zone 2: $68/$58/$58, Zone 3: $53/$47/$47 -- **Zone 1 counties**: Camden, Cherokee, Clayton, Cobb, DeKalb, Douglas, Fayette, Forsyth, Fulton, Gwinnett, Hall, Henry, Paulding, Rockdale -- **Zone 2 counties**: Baldwin, Barrow, Bartow, Bibb, Bryan, Bulloch, Butts, Catoosa, Chatham, Clarke, Columbia, Coweta, Dawson, Dougherty, Effingham, Floyd, Glynn, Gordon, Harris, Hart, Houston, Jackson, Jones, Lamar, Lee, Liberty, Lowndes, Lumpkin, Madison, McDuffie, Meriwether, Morgan, Murray, Muscogee, Newton, Oconee, Peach, Pike, Pulaski, Putnam, Richmond, Spalding, Tift, Troup, Walton, Whitfield -- **Zone 3 counties**: All remaining counties (largest group) -- **Downloaded to**: /tmp/ga-caps-appendix-c.pdf, text at /tmp/ga-caps-appendix-c.txt -- **Screenshot verified at 600 DPI**: /tmp/ga-caps-appendix-c-page-1.png, /tmp/ga-caps-appendix-c-page-2.png - -### 4. Appendix D - Family Fee Assessment Chart -- **URL**: https://caps.decal.ga.gov/assets/downloads/CAPS/AppendixD-Family%20Fee%20Assessment%20Chart.pdf -- **Title**: CAPS Family Fee -- **Effective date**: March 2, 2026 -- **Content**: Family fee (co-payment) tiers based on ratio of income to federal poverty guidelines -- **Co-payment tiers**: - | Income-to-Poverty Ratio | Family Fee | - |---|---| - | 10% or less | No family fee | - | Over 10% to 50% | 3% of income | - | Over 50% to 100% | 5% of income | - | Over 100% | 7% of income | -- **Key rules**: - - Fee is per family (all children), NOT per child - - Weekly fee = annual gross applicable income x rate / 52, rounded down to whole dollar - - Max copay is always 7% (federal cap) - - Based on 2026 FPL guidelines -- **Income ranges for family of 4**: - - $0 to $3,300: No fee (at or below 10% FPL) - - $3,301 to $16,500: 3% (over 10% to 50% FPL) - - $16,501 to $33,000: 5% (over 50% to 100% FPL) - - $33,001 or more: 7% (over 100% FPL) -- **Downloaded to**: /tmp/ga-caps-appendix-d.pdf, text at /tmp/ga-caps-appendix-d.txt -- **Screenshot verified at 600 DPI**: /tmp/ga-caps-appendix-d-page-1.png - -### 5. CCDF State Plan FFY 2025-2027 -- **URL**: https://www.decal.ga.gov/documents/attachments/CCDFStatePlan25-27.pdf -- **Title**: Child Care and Development Fund (CCDF) Plan for Georgia FFY 2025-2027 -- **Content**: Complete federal CCDF plan describing Georgia's administration of child care subsidies -- **Key data extracted**: - - Initial eligibility: 50% SMI (increased from 40% SMI in CCDF plan period) - - Ongoing eligibility: 85% SMI (federal maximum) - - Payment rates effective 9/29/2024 (based on 2024 Market Rate Survey) - - Three market rate zones - - Quality Rated add-ons: 2-star = 5% bonus, 3-star = 10% bonus (on net base payment) - - Sliding fee scale effective March 1, 2024 - - Co-payment based on income-to-poverty ratio (4 tiers) - - Family fee waived for: DFCS custody children, minor parents (17 or younger), income at/below 10% FPL - - Asset limit: $1,000,000 (self-certified) - - Providers allowed to charge difference between published rate and subsidy amount -- **Downloaded to**: /tmp/ga-ccdf-plan-2025-27.pdf, text at /tmp/ga-ccdf-plan-2025-27.txt - -### 6. Georgia.gov CAPS Application Page -- **URL**: https://georgia.gov/apply-childcare-and-parent-services-caps-program -- **Content**: Overview of eligibility requirements for public -- **Key data**: Confirms residency, age (12 or younger / 17 with disability), citizenship, immunization, income (50% SMI), activity requirements - -### 7. CAPS Eligibility Requirements Page -- **URL**: https://caps.decal.ga.gov/en/EligibilityRequirements -- **Content**: Detailed eligibility breakdown for new applicants vs current recipients -- **Key data**: Priority group required for new applicants; 24 hours/week activity minimum; initial = 50% SMI; redetermination = 85% SMI - -### 8. GEEARS CAPS Two-Pager -- **URL**: https://geears.org/wp-content/uploads/GEEARS_CAPS_TwoPagerExtended.pdf -- **Content**: Advocacy summary of CAPS program - -## Eligibility Tests Identified - -1. **Georgia residency** (parent) -2. **Child age**: 12 or younger (17 with disability/court order) -3. **Child citizenship**: U.S. citizen or lawfully admitted qualified alien -4. **Immunization**: Current immunizations (with exceptions) -5. **Proof of identity** (parent) -6. **Priority group membership** (initial eligibility only, 13 categories) -7. **Income test - initial**: Gross applicable income <= 50% SMI -8. **Income test - ongoing**: Gross applicable income <= 85% SMI -9. **Activity requirement**: 24 hours/week average in state-approved activities (employment, education, training) -10. **Asset test**: Family assets < $1,000,000 (self-certified) - -## Income Rules - -### Applicable (counted) income: -- Gross wages/salary of all adults in family unit -- Base pay for military -- Net self-employment income -- Unemployment compensation -- Worker's compensation -- Alimony -- Child support (regular/ongoing) -- Veteran's benefits, military allotments -- Capital gains -- Rental income, dividends (regular/ongoing) -- Retirement/pension -- Commission, cash bonuses -- Lottery payments - -### Non-applicable (excluded) income: -- TANF cash assistance -- SSI benefits / disability/survivors from SSA -- Adoption supplements -- LIHEAP -- Census Bureau income -- In-kind donations -- Tax refunds -- Cash gifts -- Disaster Relief Assistance -- Relative care subsidy -- Guaranteed Basic Income (GBI) / Universal Basic Income (UBI) -- AmeriCorps unearned income -- Stipends issued by DECAL -- Income from children 17 or younger - -### Income calculation method: -- Review 4 weeks of earnings prior to determination -- Convert to monthly: weekly x 4.3333, bi-weekly x 2.1666, semi-monthly x 2 -- Convert monthly to annual: monthly x 12 -- Compare annual to Appendix A income limits - -## Family Unit Rules - -Family unit includes: -- Biological, adopted, or step children 17 or younger -- Children under legal/physical guardianship -- Spouse/parent in home -- Unmarried adults with mutual biological/legal children -- Spouse/parent temporarily absent (employment, military, training, education) - -NOT included: -- Grandparents (when parent retains custody) -- Unrelated adults without mutual children - -## Benefit Calculation - -**Subsidy = min(CAPS max reimbursement rate, provider published rate) - family fee** - -The subsidy is NOT a flat amount — it depends on: -1. Child's age group (infant/toddler/preschool/school-age) -2. Provider type (center, family home, informal) -3. Geographic zone (1, 2, or 3) -4. Care type (full-time, part-time, before/after school) -5. Provider's published rate (subsidy capped at provider's actual price) -6. Family fee (co-payment based on income-to-FPL ratio) - -**Quality Rated add-ons** (effective 9/29/2024): -- 2-star Quality Rated: 5% bonus on net base payment (base payment minus family fee) -- 3-star Quality Rated: 10% bonus on net base payment -- 1-star: No add-on - -## Key Policy Notes - -1. **Priority groups**: New applicants MUST belong to at least one of 13 priority groups. This is NOT required at redetermination. -2. **12-month eligibility period**: Once approved, families get a minimum 12-month eligibility period. -3. **Fee protection**: Family fee may decrease but NOT increase during eligibility period; can increase at redetermination. -4. **Graduated phase-out**: Families whose income exceeds initial threshold (50% SMI) but stays below 85% SMI remain eligible at redetermination. -5. **Registration fees**: CAPS authorizes up to $65/child in registration fees. -6. **Age transitions**: Rate changes at child's 1st and 3rd birthday take effect Monday following birthday. -7. **DFCS custody**: Children in foster care get subsidy at provider's full published rate; no family fee assessed. -8. **Children with disabilities**: May receive subsidy at provider's full published rate; DECAL may approve negotiated rate above published rate. -9. **Minor parents**: Parents 17 or younger have no family fee and no additional activity requirement if in school. -10. **15% QR discount removed**: As of 10/06/2025, the 15% Quality Rated discount to family fees was removed. - -## Failed Fetches - -None — all primary sources were successfully downloaded and verified. From d28fd90843cafbe4967e5312a4a1d7895ef3f254 Mon Sep 17 00:00:00 2001 From: Ziming Date: Thu, 14 May 2026 18:00:03 -0400 Subject: [PATCH 09/11] Review-fix round 2: address all 10 critical issues from /review-program MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Rewrite ga_caps.py formula with per-child min(state max, provider published rate); add ga_caps_provider_published_rate input variable (defaults to per-child share of spm_unit_pre_subsidy_childcare_expenses). Replace np.divide(out=..., where=...) workaround with idiomatic where(). - Fix income source: military_retirement_pay -> military_basic_pay; note military_allotments has no matching PolicyEngine variable. - Register ga_caps in programs.yaml under CCDF (coverage + state_implementations). - Replace 17 broken caps.decal.ga.gov reference URLs with working ones (0-CAPS_Policy-Manual.pdf and renamed appendix files). - Correct Policy Manual, Appendix C/D, and CCDF State Plan page anchors; CCDF State Plan now references working decal.ga.gov URL with §4.3.3 (was wrongly §4.3.2 / #page=110). - Merge integration_edge.yaml into integration.yaml (Cases 8-13). - Rename ga_caps_edge.yaml -> ga_caps.yaml; merge five other *_edge.yaml files into their canonical counterparts. - Pin meets_ccdf_activity_test=false in activity tests to isolate the GA-specific 24-hour rule from the federal CCDF fallback. - Remove duplicate-date entries in quality_rated/bonus_rate.yaml. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../activity_requirements/weekly_hours.yaml | 8 +- .../decal/caps/age_group/preschool_min.yaml | 2 +- .../decal/caps/age_group/school_age_min.yaml | 2 +- .../ga/decal/caps/age_group/toddler_min.yaml | 2 +- .../ga/decal/caps/age_threshold/child.yaml | 8 +- .../caps/age_threshold/disabled_child.yaml | 8 +- .../caps/family_fee/minor_parent_age.yaml | 8 +- .../states/ga/decal/caps/family_fee/rate.yaml | 8 +- .../caps/income/countable_income/sources.yaml | 9 +- .../income/smi_rate/initial_eligibility.yaml | 8 +- .../income/smi_rate/ongoing_eligibility.yaml | 8 +- .../decal/caps/quality_rated/bonus_rate.yaml | 12 +- .../states/ga/decal/caps/rates/center.yaml | 2 +- .../states/ga/decal/caps/rates/family.yaml | 2 +- .../states/ga/decal/caps/rates/informal.yaml | 2 +- .../states/ga/decal/caps/zone_1_counties.yaml | 4 +- .../states/ga/decal/caps/zone_2_counties.yaml | 4 +- policyengine_us/programs.yaml | 8 +- .../decal/caps/copay/ga_caps_family_fee.yaml | 201 ++++++++++ .../caps/copay/ga_caps_family_fee_edge.yaml | 215 ---------- .../ga_caps_activity_eligible.yaml | 180 ++++++++- .../ga_caps_activity_eligible_edge.yaml | 146 ------- .../eligibility/ga_caps_eligible_child.yaml | 198 ++++++++++ .../ga_caps_eligible_child_edge.yaml | 202 ---------- .../eligibility/ga_caps_income_eligible.yaml | 207 ++++++++++ .../ga_caps_income_eligible_edge.yaml | 215 ---------- .../caps/{ga_caps_edge.yaml => ga_caps.yaml} | 21 +- .../gov/states/ga/decal/caps/integration.yaml | 368 +++++++++++++++++- .../ga/decal/caps/integration_edge.yaml | 361 ----------------- .../ga_caps_maximum_weekly_benefit.yaml | 98 +++++ .../ga_caps_maximum_weekly_benefit_edge.yaml | 172 -------- .../ga/decal/caps/copay/ga_caps_family_fee.py | 4 +- .../eligibility/ga_caps_activity_eligible.py | 2 +- .../caps/eligibility/ga_caps_eligible.py | 2 +- .../eligibility/ga_caps_eligible_child.py | 4 +- .../eligibility/ga_caps_income_eligible.py | 4 +- .../gov/states/ga/decal/caps/ga_caps.py | 37 +- .../caps/income/ga_caps_countable_income.py | 2 +- .../decal/caps/payment/ga_caps_age_group.py | 2 +- .../decal/caps/payment/ga_caps_care_type.py | 2 +- .../payment/ga_caps_maximum_weekly_benefit.py | 2 +- .../ga_caps_provider_published_rate.py | 24 ++ .../caps/payment/ga_caps_provider_type.py | 2 +- .../caps/payment/ga_caps_quality_rating.py | 4 +- .../ga/decal/caps/payment/ga_caps_zone.py | 2 +- uv.lock | 2 +- 46 files changed, 1367 insertions(+), 1417 deletions(-) delete mode 100644 policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/copay/ga_caps_family_fee_edge.yaml delete mode 100644 policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_activity_eligible_edge.yaml delete mode 100644 policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_eligible_child_edge.yaml delete mode 100644 policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_income_eligible_edge.yaml rename policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/{ga_caps_edge.yaml => ga_caps.yaml} (94%) delete mode 100644 policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/integration_edge.yaml delete mode 100644 policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/payment/ga_caps_maximum_weekly_benefit_edge.yaml create mode 100644 policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_provider_published_rate.py diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/activity_requirements/weekly_hours.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/activity_requirements/weekly_hours.yaml index 959f78d501d..9fed6b0d3a5 100644 --- a/policyengine_us/parameters/gov/states/ga/decal/caps/activity_requirements/weekly_hours.yaml +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/activity_requirements/weekly_hours.yaml @@ -7,7 +7,7 @@ metadata: period: year label: Georgia CAPS minimum weekly activity hours reference: - - title: Georgia CAPS Policy Manual, Chapter 6 (Eligibility Requirements) - href: https://caps.decal.ga.gov/assets/downloads/CAPS/02-CAPS_Policy-Chapter_6.pdf#page=4 - - title: Georgia CCDF Plan FFY 2025-2027, Section 3.2.2 - href: https://www.acf.hhs.gov/sites/default/files/documents/occ/georgia_2025_2027_ccdf_state_plan.pdf#page=56 + - title: Georgia CAPS Policy Manual, Section 6.8 (State-Approved Activities) + href: https://caps.decal.ga.gov/assets/downloads/CAPS/0-CAPS_Policy-Manual.pdf#page=33 + - title: Georgia CCDF Plan FFY 2025-2027, Section 3.1.1(d) (Minimum weekly hours) + href: https://www.decal.ga.gov/documents/attachments/CCDFStatePlan25-27.pdf#page=19 diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/age_group/preschool_min.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/age_group/preschool_min.yaml index 230804f58a1..5e066a0859a 100644 --- a/policyengine_us/parameters/gov/states/ga/decal/caps/age_group/preschool_min.yaml +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/age_group/preschool_min.yaml @@ -8,4 +8,4 @@ metadata: label: Georgia CAPS preschool minimum age reference: - title: Georgia CAPS Appendix C - Reimbursement Rates (effective March 2, 2026) - href: https://caps.decal.ga.gov/assets/downloads/CAPS/Appendix_C-CAPS_Reimbursement_Rates.pdf#page=2 + href: https://caps.decal.ga.gov/assets/downloads/CAPS/AppendixC-CAPS%20Reimbursement%20Rates.pdf#page=1 diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/age_group/school_age_min.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/age_group/school_age_min.yaml index ad3372601f5..956df4c37c7 100644 --- a/policyengine_us/parameters/gov/states/ga/decal/caps/age_group/school_age_min.yaml +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/age_group/school_age_min.yaml @@ -8,4 +8,4 @@ metadata: label: Georgia CAPS school age minimum age reference: - title: Georgia CAPS Appendix C - Reimbursement Rates (effective March 2, 2026) - href: https://caps.decal.ga.gov/assets/downloads/CAPS/Appendix_C-CAPS_Reimbursement_Rates.pdf#page=2 + href: https://caps.decal.ga.gov/assets/downloads/CAPS/AppendixC-CAPS%20Reimbursement%20Rates.pdf#page=1 diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/age_group/toddler_min.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/age_group/toddler_min.yaml index 6df555fce0a..7a070ed6d6b 100644 --- a/policyengine_us/parameters/gov/states/ga/decal/caps/age_group/toddler_min.yaml +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/age_group/toddler_min.yaml @@ -8,4 +8,4 @@ metadata: label: Georgia CAPS toddler minimum age reference: - title: Georgia CAPS Appendix C - Reimbursement Rates (effective March 2, 2026) - href: https://caps.decal.ga.gov/assets/downloads/CAPS/Appendix_C-CAPS_Reimbursement_Rates.pdf#page=2 + href: https://caps.decal.ga.gov/assets/downloads/CAPS/AppendixC-CAPS%20Reimbursement%20Rates.pdf#page=1 diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/age_threshold/child.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/age_threshold/child.yaml index 82cf42f1cbf..9e04b43ef40 100644 --- a/policyengine_us/parameters/gov/states/ga/decal/caps/age_threshold/child.yaml +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/age_threshold/child.yaml @@ -7,7 +7,7 @@ metadata: period: year label: Georgia CAPS child age threshold reference: - - title: Georgia CAPS Policy Manual, Chapter 6 (Eligibility Requirements) - href: https://caps.decal.ga.gov/assets/downloads/CAPS/02-CAPS_Policy-Chapter_6.pdf#page=3 - - title: Georgia CCDF Plan FFY 2025-2027, Section 3.1.1 - href: https://www.acf.hhs.gov/sites/default/files/documents/occ/georgia_2025_2027_ccdf_state_plan.pdf#page=49 + - title: Georgia CAPS Policy Manual, Section 6.4 (Age Requirement) + href: https://caps.decal.ga.gov/assets/downloads/CAPS/0-CAPS_Policy-Manual.pdf#page=29 + - title: Georgia CCDF Plan FFY 2025-2027, Section 3.1.1 (Age of children served) + href: https://www.decal.ga.gov/documents/attachments/CCDFStatePlan25-27.pdf#page=16 diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/age_threshold/disabled_child.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/age_threshold/disabled_child.yaml index 999e0ec310b..4e93c682bd4 100644 --- a/policyengine_us/parameters/gov/states/ga/decal/caps/age_threshold/disabled_child.yaml +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/age_threshold/disabled_child.yaml @@ -7,7 +7,7 @@ metadata: period: year label: Georgia CAPS disabled child age threshold reference: - - title: Georgia CAPS Policy Manual, Chapter 6 (Eligibility Requirements) - href: https://caps.decal.ga.gov/assets/downloads/CAPS/02-CAPS_Policy-Chapter_6.pdf#page=3 - - title: Georgia CCDF Plan FFY 2025-2027, Section 3.1.1 - href: https://www.acf.hhs.gov/sites/default/files/documents/occ/georgia_2025_2027_ccdf_state_plan.pdf#page=49 + - title: Georgia CAPS Policy Manual, Section 6.4 (Age Requirement) + href: https://caps.decal.ga.gov/assets/downloads/CAPS/0-CAPS_Policy-Manual.pdf#page=29 + - title: Georgia CCDF Plan FFY 2025-2027, Section 3.1.1 (Age of children served) + href: https://www.decal.ga.gov/documents/attachments/CCDFStatePlan25-27.pdf#page=16 diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/family_fee/minor_parent_age.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/family_fee/minor_parent_age.yaml index 8f5d08014a4..a98883d8c9b 100644 --- a/policyengine_us/parameters/gov/states/ga/decal/caps/family_fee/minor_parent_age.yaml +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/family_fee/minor_parent_age.yaml @@ -7,7 +7,7 @@ metadata: period: year label: Georgia CAPS minor parent age threshold for fee waiver reference: - - title: Georgia CAPS Policy Manual, Chapter 6 (Eligibility Requirements) - href: https://caps.decal.ga.gov/assets/downloads/CAPS/02-CAPS_Policy-Chapter_6.pdf#page=5 - - title: Georgia CCDF Plan FFY 2025-2027, Section 4.3.2 - href: https://www.acf.hhs.gov/sites/default/files/documents/occ/georgia_2025_2027_ccdf_state_plan.pdf#page=117 + - title: Georgia CAPS Policy Manual, Section 9.5 (When Family Fees Are Not Assessed) + href: https://caps.decal.ga.gov/assets/downloads/CAPS/0-CAPS_Policy-Manual.pdf#page=54 + - title: Georgia CCDF Plan FFY 2025-2027, Section 3.3.1 (Family Co-payment Waiver) + href: https://www.decal.ga.gov/documents/attachments/CCDFStatePlan25-27.pdf#page=49 diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/family_fee/rate.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/family_fee/rate.yaml index b2391beaaff..95ce6e56375 100644 --- a/policyengine_us/parameters/gov/states/ga/decal/caps/family_fee/rate.yaml +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/family_fee/rate.yaml @@ -6,10 +6,10 @@ metadata: period: year label: Georgia CAPS family fee rate by FPL ratio reference: - - title: Georgia CAPS Appendix D - Family Fee Schedule (effective March 2, 2026) - href: https://caps.decal.ga.gov/assets/downloads/CAPS/Appendix_D-CAPS_Family_Fee_702.pdf#page=2 - - title: Georgia CCDF Plan FFY 2025-2027, Section 4.3.2 - href: https://www.acf.hhs.gov/sites/default/files/documents/occ/georgia_2025_2027_ccdf_state_plan.pdf#page=117 + - title: Georgia CAPS Appendix D - Family Fee Assessment Chart (effective March 2, 2026) + href: https://caps.decal.ga.gov/assets/downloads/CAPS/AppendixD-Family%20Fee%20Assessment%20Chart.pdf + - title: Georgia CCDF Plan FFY 2025-2027, Section 3.3.1 (Family Co-payment Waiver) + href: https://www.decal.ga.gov/documents/attachments/CCDFStatePlan25-27.pdf#page=49 brackets: - threshold: diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/income/countable_income/sources.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/income/countable_income/sources.yaml index cc438c7c072..05147856921 100644 --- a/policyengine_us/parameters/gov/states/ga/decal/caps/income/countable_income/sources.yaml +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/income/countable_income/sources.yaml @@ -12,9 +12,10 @@ values: - rental_income - dividend_income - pension_income - - military_retirement_pay - # The following are counted per CAPS Policy Manual Ch.8 but have + - military_basic_pay + # The following are counted per CAPS Policy Manual §8.4 but have # no matching variables: + # - military_allotments # - lottery_payments # - commissions (included in employment_income) # - cash_bonuses (included in employment_income) @@ -24,5 +25,5 @@ metadata: period: year label: Georgia CAPS countable income sources reference: - - title: Georgia CAPS Policy Manual, Chapter 8 (Income) - href: https://caps.decal.ga.gov/assets/downloads/CAPS/04-CAPS_Policy-Chapter_8.pdf#page=3 + - title: Georgia CAPS Policy Manual, Section 8.4 (Applicable Income) + href: https://caps.decal.ga.gov/assets/downloads/CAPS/0-CAPS_Policy-Manual.pdf#page=48 diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/income/smi_rate/initial_eligibility.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/income/smi_rate/initial_eligibility.yaml index 0ef8f887bb0..c189db0160b 100644 --- a/policyengine_us/parameters/gov/states/ga/decal/caps/income/smi_rate/initial_eligibility.yaml +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/income/smi_rate/initial_eligibility.yaml @@ -7,7 +7,7 @@ metadata: period: year label: Georgia CAPS initial eligibility SMI rate reference: - - title: Georgia CAPS Policy Manual, Chapter 8 (Income) - href: https://caps.decal.ga.gov/assets/downloads/CAPS/04-CAPS_Policy-Chapter_8.pdf#page=2 - - title: Georgia CAPS Appendix A - Income Limits (effective March 2, 2026) - href: https://caps.decal.ga.gov/assets/downloads/CAPS/Appendix_A-CAPS_702_Income_Limits.pdf#page=2 + - title: Georgia CAPS Policy Manual, Section 8.3 (Gross Income) + href: https://caps.decal.ga.gov/assets/downloads/CAPS/0-CAPS_Policy-Manual.pdf#page=48 + - title: Georgia CAPS Appendix A - Maximum Income Limits by Family Size (effective March 2, 2026) + href: https://caps.decal.ga.gov/assets/downloads/CAPS/AppendixA-CAPS%20Maximum%20Income%20Limits%20by%20Family%20Size.pdf diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/income/smi_rate/ongoing_eligibility.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/income/smi_rate/ongoing_eligibility.yaml index 84a2814468d..5031d4d77e6 100644 --- a/policyengine_us/parameters/gov/states/ga/decal/caps/income/smi_rate/ongoing_eligibility.yaml +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/income/smi_rate/ongoing_eligibility.yaml @@ -7,7 +7,7 @@ metadata: period: year label: Georgia CAPS ongoing eligibility SMI rate reference: - - title: Georgia CAPS Policy Manual, Chapter 8 (Income) - href: https://caps.decal.ga.gov/assets/downloads/CAPS/04-CAPS_Policy-Chapter_8.pdf#page=2 - - title: Georgia CAPS Appendix A - Income Limits (effective March 2, 2026) - href: https://caps.decal.ga.gov/assets/downloads/CAPS/Appendix_A-CAPS_702_Income_Limits.pdf#page=2 + - title: Georgia CAPS Policy Manual, Section 8.3 (Gross Income) + href: https://caps.decal.ga.gov/assets/downloads/CAPS/0-CAPS_Policy-Manual.pdf#page=48 + - title: Georgia CAPS Appendix A - Maximum Income Limits by Family Size (effective March 2, 2026) + href: https://caps.decal.ga.gov/assets/downloads/CAPS/AppendixA-CAPS%20Maximum%20Income%20Limits%20by%20Family%20Size.pdf diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/quality_rated/bonus_rate.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/quality_rated/bonus_rate.yaml index fb42477b4ce..82fa6bddc9a 100644 --- a/policyengine_us/parameters/gov/states/ga/decal/caps/quality_rated/bonus_rate.yaml +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/quality_rated/bonus_rate.yaml @@ -6,25 +6,19 @@ metadata: period: year label: Georgia CAPS Quality Rated bonus rate reference: - - title: Georgia CCDF Plan FFY 2025-2027, Section 4.2.4 (Quality Rated Differential) - href: https://www.acf.hhs.gov/sites/default/files/documents/occ/georgia_2025_2027_ccdf_state_plan.pdf#page=110 + - title: Georgia CCDF Plan FFY 2025-2027, Section 4.3.3 (Quality Rated Differential) + href: https://www.decal.ga.gov/documents/attachments/CCDFStatePlan25-27.pdf#page=69 brackets: - threshold: 2024-09-29: 0 - 2026-03-02: 0 amount: 2024-09-29: 0 - 2026-03-02: 0 - threshold: 2024-09-29: 2 - 2026-03-02: 2 amount: 2024-09-29: 0.05 - 2026-03-02: 0.05 - threshold: 2024-09-29: 3 - 2026-03-02: 3 amount: - 2024-09-29: 0.10 - 2026-03-02: 0.10 + 2024-09-29: 0.1 diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/rates/center.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/rates/center.yaml index 42f557f11bd..d5cb45106ac 100644 --- a/policyengine_us/parameters/gov/states/ga/decal/caps/rates/center.yaml +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/rates/center.yaml @@ -9,7 +9,7 @@ metadata: - ga_caps_care_type reference: - title: Georgia CAPS Appendix C - Reimbursement Rates (effective March 2, 2026) - href: https://caps.decal.ga.gov/assets/downloads/CAPS/Appendix_C-CAPS_Reimbursement_Rates.pdf#page=2 + href: https://caps.decal.ga.gov/assets/downloads/CAPS/AppendixC-CAPS%20Reimbursement%20Rates.pdf#page=1 ZONE_1: INFANT: diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/rates/family.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/rates/family.yaml index d94158d1268..83299c97c4d 100644 --- a/policyengine_us/parameters/gov/states/ga/decal/caps/rates/family.yaml +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/rates/family.yaml @@ -9,7 +9,7 @@ metadata: - ga_caps_care_type reference: - title: Georgia CAPS Appendix C - Reimbursement Rates (effective March 2, 2026) - href: https://caps.decal.ga.gov/assets/downloads/CAPS/Appendix_C-CAPS_Reimbursement_Rates.pdf#page=2 + href: https://caps.decal.ga.gov/assets/downloads/CAPS/AppendixC-CAPS%20Reimbursement%20Rates.pdf#page=1 ZONE_1: INFANT: diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/rates/informal.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/rates/informal.yaml index c25c57042db..f3dc7ac1f0e 100644 --- a/policyengine_us/parameters/gov/states/ga/decal/caps/rates/informal.yaml +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/rates/informal.yaml @@ -9,7 +9,7 @@ metadata: - ga_caps_care_type reference: - title: Georgia CAPS Appendix C - Reimbursement Rates (effective March 2, 2026) - href: https://caps.decal.ga.gov/assets/downloads/CAPS/Appendix_C-CAPS_Reimbursement_Rates.pdf#page=2 + href: https://caps.decal.ga.gov/assets/downloads/CAPS/AppendixC-CAPS%20Reimbursement%20Rates.pdf#page=1 ZONE_1: INFANT: diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/zone_1_counties.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/zone_1_counties.yaml index e930a4c8a05..fd9e02f6b8d 100644 --- a/policyengine_us/parameters/gov/states/ga/decal/caps/zone_1_counties.yaml +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/zone_1_counties.yaml @@ -21,5 +21,5 @@ metadata: period: year label: Georgia CAPS Zone 1 counties reference: - - title: Georgia CAPS Appendix C - Reimbursement Rates (effective March 2, 2026) - href: https://caps.decal.ga.gov/assets/downloads/CAPS/Appendix_C-CAPS_Reimbursement_Rates.pdf#page=2 + - title: Georgia CAPS Appendix C - Reimbursement Rates, Zone Map (effective March 2, 2026) + href: https://caps.decal.ga.gov/assets/downloads/CAPS/AppendixC-CAPS%20Reimbursement%20Rates.pdf#page=2 diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/zone_2_counties.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/zone_2_counties.yaml index 6ab70c09c79..4594e8ae28b 100644 --- a/policyengine_us/parameters/gov/states/ga/decal/caps/zone_2_counties.yaml +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/zone_2_counties.yaml @@ -53,5 +53,5 @@ metadata: period: year label: Georgia CAPS Zone 2 counties reference: - - title: Georgia CAPS Appendix C - Reimbursement Rates (effective March 2, 2026) - href: https://caps.decal.ga.gov/assets/downloads/CAPS/Appendix_C-CAPS_Reimbursement_Rates.pdf#page=2 + - title: Georgia CAPS Appendix C - Reimbursement Rates, Zone Map (effective March 2, 2026) + href: https://caps.decal.ga.gov/assets/downloads/CAPS/AppendixC-CAPS%20Reimbursement%20Rates.pdf#page=2 diff --git a/policyengine_us/programs.yaml b/policyengine_us/programs.yaml index 76b5377b5f3..66b13d48387 100644 --- a/policyengine_us/programs.yaml +++ b/policyengine_us/programs.yaml @@ -460,7 +460,7 @@ programs: category: Benefits agency: HHS status: partial - coverage: CA, CO, CT, DE, DC, IL, MA, MD, ME, NC, NH, NJ, PA, RI, SC, TX, VA, VT, WV + coverage: CA, CO, CT, DE, DC, GA, IL, MA, MD, ME, NC, NH, NJ, PA, RI, SC, TX, VA, VT, WV state_implementations: - state: CA status: complete @@ -553,6 +553,12 @@ programs: status: in_progress name: West Virginia CCAP full_name: West Virginia Child Care Assistance Program + - state: GA + status: complete + name: Georgia CAPS + full_name: Georgia Childcare and Parent Services + variable: ga_caps + parameter_prefix: gov.states.ga.decal.caps - id: head_start name: Head Start diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/copay/ga_caps_family_fee.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/copay/ga_caps_family_fee.yaml index c6fa27ae095..104a1d43cfe 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/copay/ga_caps_family_fee.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/copay/ga_caps_family_fee.yaml @@ -178,3 +178,204 @@ # FPL ratio = 2,732 / 27,320 = 0.10 -> 0% rate (at or below 10%) # fee = 0 ga_caps_family_fee: 0 + +- name: Case 8, FPL ratio just above 10 percent boundary still in zero tier. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + # 10% of FPG for family of 2 = 21,640 * 0.10 = $2,164 + # Just above: $2,165 + employment_income: 2_165 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # FPL ratio = 2,165 / 21,640 = 0.10005 -> < 0.1001 (still in 0% tier) + ga_caps_family_fee: 0 + +- name: Case 9, FPL ratio just crossing into 3 percent tier. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + # 0.1001 * 21,640 = $2,166.16. So income $2,167 crosses. + employment_income: 2_167 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # FPL ratio = 2,167 / 21,640 = 0.10014 -> >= 0.1001 -> 3% rate + # weekly fee = floor(2,167 * 0.03 / 52) = floor(1.25) = $1 + # monthly fee = 1 * 52 / 12 = $4.33 + ga_caps_family_fee: 4.33 + +- name: Case 10, FPL ratio exactly at 50 percent boundary. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + # 50% of FPG for family of 2 = 21,640 * 0.50 = $10,820 + employment_income: 10_820 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # FPL ratio = 10,820 / 21,640 = 0.5000 -> < 0.5001 -> 3% rate + # weekly fee = floor(10,820 * 0.03 / 52) = floor(6.24) = $6 + # monthly fee = 6 * 52 / 12 = $26.00 + ga_caps_family_fee: 26.00 + +- name: Case 11, FPL ratio just crossing into 5 percent tier. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + # 0.5001 * 21,640 = $10,822.16. So income $10,823 crosses. + employment_income: 10_823 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # FPL ratio = 10,823 / 21,640 = 0.50014 -> >= 0.5001 -> 5% rate + # weekly fee = floor(10,823 * 0.05 / 52) = floor(10.41) = $10 + # monthly fee = 10 * 52 / 12 = $43.33 + ga_caps_family_fee: 43.33 + +- name: Case 12, FPL ratio exactly at 100 percent boundary. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + # 100% of FPG for family of 2 = $21,640 + employment_income: 21_640 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # FPL ratio = 21,640 / 21,640 = 1.0000 -> < 1.0001 -> 5% rate + # weekly fee = floor(21,640 * 0.05 / 52) = floor(20.81) = $20 + # monthly fee = 20 * 52 / 12 = $86.67 + ga_caps_family_fee: 86.67 + +- name: Case 13, FPL ratio just crossing into 7 percent tier. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + # 1.0001 * 21,640 = $21,642.16. So income $21,643 crosses. + employment_income: 21_643 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # FPL ratio = 21,643 / 21,640 = 1.00014 -> >= 1.0001 -> 7% rate + # weekly fee = floor(21,643 * 0.07 / 52) = floor(29.12) = $29 + # monthly fee = 29 * 52 / 12 = $125.67 + ga_caps_family_fee: 125.67 + +- name: Case 14, parent age 18 does not get minor parent fee waiver. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 18 + employment_income: 30_000 + person2: + age: 1 + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # Parent age 18 > 17 -> no fee waiver + # FPG family of 2: $21,640 + # FPL ratio = 30,000 / 21,640 = 1.387 -> 7% rate + # weekly fee = floor(30,000 * 0.07 / 52) = floor(40.38) = $40 + # monthly fee = 40 * 52 / 12 = $173.33 + ga_caps_family_fee: 173.33 + +- name: Case 15, larger family of 5 with lower FPL ratio. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + employment_income: 20_000 + person2: + age: 30 + person3: + age: 10 + person4: + age: 7 + person5: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5] + households: + household: + members: [person1, person2, person3, person4, person5] + state_code: GA + output: + # FPG family of 5: 15,960 + 5,680 * 4 = $38,680 + # FPL ratio = 20,000 / 38,680 = 0.5171 -> >= 0.5001 -> 5% rate + # weekly fee = floor(20,000 * 0.05 / 52) = floor(19.23) = $19 + # monthly fee = 19 * 52 / 12 = $82.33 + ga_caps_family_fee: 82.33 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/copay/ga_caps_family_fee_edge.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/copay/ga_caps_family_fee_edge.yaml deleted file mode 100644 index f68052a449f..00000000000 --- a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/copay/ga_caps_family_fee_edge.yaml +++ /dev/null @@ -1,215 +0,0 @@ -# GA CAPS family fee - edge cases -# Tiers by FPL ratio: -# <= 10% FPL: 0% (no fee) -# > 10% to 50% FPL: 3% of income -# > 50% to 100% FPL: 5% of income -# > 100% FPL: 7% of income -# Weekly fee = floor(annual_income * rate / 52) -# Monthly fee = weekly_fee * 52 / 12 -# Fee waived for minor parents (age <= 17) -# -# 2026 FPG family of 2: $21,640 -# 2026 FPG family of 3: $27,320 - -- name: Case 1, FPL ratio just above 10 percent boundary. - period: 2026-01 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 30 - # 10% of FPG for family of 2 = 21,640 * 0.10 = $2,164 - # Just above: $2,165 - employment_income: 2_165 - person2: - age: 5 - spm_units: - spm_unit: - members: [person1, person2] - households: - household: - members: [person1, person2] - state_code: GA - output: - # FPL ratio = 2,165 / 21,640 = 0.10005 -> > 0.1001? No, 0.10005 < 0.1001 - # Still in 0% tier - ga_caps_family_fee: 0 - -- name: Case 2, FPL ratio just crossing into 3 percent tier. - period: 2026-01 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 30 - # Threshold is 0.1001 of FPG - # 0.1001 * 21,640 = $2,166.16. So income $2,167 crosses. - employment_income: 2_167 - person2: - age: 5 - spm_units: - spm_unit: - members: [person1, person2] - households: - household: - members: [person1, person2] - state_code: GA - output: - # FPL ratio = 2,167 / 21,640 = 0.10014 -> >= 0.1001 -> 3% rate - # weekly fee = floor(2,167 * 0.03 / 52) = floor(1.25) = $1 - # monthly fee = 1 * 52 / 12 = $4.33 - ga_caps_family_fee: 4.33 - -- name: Case 3, FPL ratio exactly at 50 percent boundary. - period: 2026-01 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 30 - # 50% of FPG for family of 2 = 21,640 * 0.50 = $10,820 - employment_income: 10_820 - person2: - age: 5 - spm_units: - spm_unit: - members: [person1, person2] - households: - household: - members: [person1, person2] - state_code: GA - output: - # FPL ratio = 10,820 / 21,640 = 0.5000 -> < 0.5001 -> 3% rate - # weekly fee = floor(10,820 * 0.03 / 52) = floor(6.24) = $6 - # monthly fee = 6 * 52 / 12 = $26.00 - ga_caps_family_fee: 26.00 - -- name: Case 4, FPL ratio just crossing into 5 percent tier. - period: 2026-01 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 30 - # 0.5001 * 21,640 = $10,822.16. So income $10,823 crosses. - employment_income: 10_823 - person2: - age: 5 - spm_units: - spm_unit: - members: [person1, person2] - households: - household: - members: [person1, person2] - state_code: GA - output: - # FPL ratio = 10,823 / 21,640 = 0.50014 -> >= 0.5001 -> 5% rate - # weekly fee = floor(10,823 * 0.05 / 52) = floor(10.41) = $10 - # monthly fee = 10 * 52 / 12 = $43.33 - ga_caps_family_fee: 43.33 - -- name: Case 5, FPL ratio exactly at 100 percent boundary. - period: 2026-01 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 30 - # 100% of FPG for family of 2 = $21,640 - employment_income: 21_640 - person2: - age: 5 - spm_units: - spm_unit: - members: [person1, person2] - households: - household: - members: [person1, person2] - state_code: GA - output: - # FPL ratio = 21,640 / 21,640 = 1.0000 -> < 1.0001 -> 5% rate - # weekly fee = floor(21,640 * 0.05 / 52) = floor(20.81) = $20 - # monthly fee = 20 * 52 / 12 = $86.67 - ga_caps_family_fee: 86.67 - -- name: Case 6, FPL ratio just crossing into 7 percent tier. - period: 2026-01 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 30 - # 1.0001 * 21,640 = $21,642.16. So income $21,643 crosses. - employment_income: 21_643 - person2: - age: 5 - spm_units: - spm_unit: - members: [person1, person2] - households: - household: - members: [person1, person2] - state_code: GA - output: - # FPL ratio = 21,643 / 21,640 = 1.00014 -> >= 1.0001 -> 7% rate - # weekly fee = floor(21,643 * 0.07 / 52) = floor(29.12) = $29 - # monthly fee = 29 * 52 / 12 = $125.67 - ga_caps_family_fee: 125.67 - -- name: Case 7, minor parent age 18 does not get fee waiver. - period: 2026-01 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 18 - employment_income: 30_000 - person2: - age: 1 - tax_units: - tax_unit: - members: [person1, person2] - spm_units: - spm_unit: - members: [person1, person2] - households: - household: - members: [person1, person2] - state_code: GA - output: - # Parent age 18 > 17 -> no fee waiver - # FPG family of 2: $21,640 - # FPL ratio = 30,000 / 21,640 = 1.387 -> 7% rate - # weekly fee = floor(30,000 * 0.07 / 52) = floor(40.38) = $40 - # monthly fee = 40 * 52 / 12 = $173.33 - ga_caps_family_fee: 173.33 - -- name: Case 8, larger family of 5 with lower FPG threshold. - period: 2026-01 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 35 - employment_income: 20_000 - person2: - age: 30 - person3: - age: 10 - person4: - age: 7 - person5: - age: 3 - spm_units: - spm_unit: - members: [person1, person2, person3, person4, person5] - households: - household: - members: [person1, person2, person3, person4, person5] - state_code: GA - output: - # FPG family of 5: 15,960 + 5,680 * 4 = $38,680 - # FPL ratio = 20,000 / 38,680 = 0.5171 -> >= 0.5001 -> 5% rate - # weekly fee = floor(20,000 * 0.05 / 52) = floor(19.23) = $19 - # monthly fee = 19 * 52 / 12 = $82.33 - ga_caps_family_fee: 82.33 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_activity_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_activity_eligible.yaml index 3b9a6c59de6..b6521a05e15 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_activity_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_activity_eligible.yaml @@ -1,6 +1,8 @@ # GA CAPS activity eligibility # Parent must average 24 hours/week in approved activities -# (employment or full-time student) +# (employment or full-time student). +# All cases pin meets_ccdf_activity_test: false to isolate the GA-specific +# 24-hour rule from the federal CCDF fallback (added in ga_caps_activity_eligible.py). - name: Case 1, single parent working 24 hours meets requirement. period: 2026-01 @@ -14,6 +16,7 @@ spm_units: spm_unit: members: [person1, person2] + meets_ccdf_activity_test: false households: household: members: [person1, person2] @@ -34,6 +37,7 @@ spm_units: spm_unit: members: [person1, person2] + meets_ccdf_activity_test: false households: household: members: [person1, person2] @@ -54,6 +58,7 @@ spm_units: spm_unit: members: [person1, person2] + meets_ccdf_activity_test: false households: household: members: [person1, person2] @@ -79,6 +84,7 @@ spm_units: spm_unit: members: [person1, person2, person3] + meets_ccdf_activity_test: false households: household: members: [person1, person2, person3] @@ -105,6 +111,7 @@ spm_units: spm_unit: members: [person1, person2, person3] + meets_ccdf_activity_test: false households: household: members: [person1, person2, person3] @@ -131,9 +138,180 @@ spm_units: spm_unit: members: [person1, person2, person3] + meets_ccdf_activity_test: false households: household: members: [person1, person2, person3] state_code: GA output: ga_caps_activity_eligible: true + +- name: Case 7, single parent working exactly 25 hours just above threshold. + period: 2026-01 + input: + people: + person1: + age: 30 + weekly_hours_worked: 25 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + meets_ccdf_activity_test: false + households: + household: + members: [person1, person2] + state_code: GA + output: + # 25 >= 24 -> eligible + ga_caps_activity_eligible: true + +- name: Case 8, single parent working zero hours and not a student. + period: 2026-01 + input: + people: + person1: + age: 30 + weekly_hours_worked: 0 + is_full_time_student: false + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + meets_ccdf_activity_test: false + households: + household: + members: [person1, person2] + state_code: GA + output: + # 0 < 24 and not a student -> ineligible + ga_caps_activity_eligible: false + +- name: Case 9, two parents both full-time students. + period: 2026-01 + input: + people: + person1: + age: 22 + weekly_hours_worked: 0 + is_full_time_student: true + person2: + age: 21 + weekly_hours_worked: 0 + is_full_time_student: true + person3: + age: 2 + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + meets_ccdf_activity_test: false + households: + household: + members: [person1, person2, person3] + state_code: GA + output: + # Both are students -> both individually eligible + ga_caps_activity_eligible: true + +- name: Case 10, two parents both below 24 hours and not students. + period: 2026-01 + input: + people: + person1: + age: 30 + weekly_hours_worked: 20 + is_full_time_student: false + person2: + age: 28 + weekly_hours_worked: 15 + is_full_time_student: false + person3: + age: 4 + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + meets_ccdf_activity_test: false + households: + household: + members: [person1, person2, person3] + state_code: GA + output: + # Both below 24 hrs and not students -> ineligible + ga_caps_activity_eligible: false + +- name: Case 11, single parent working 40 hours per week. + period: 2026-01 + input: + people: + person1: + age: 30 + weekly_hours_worked: 40 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + meets_ccdf_activity_test: false + households: + household: + members: [person1, person2] + state_code: GA + output: + # 40 >= 24 -> eligible + ga_caps_activity_eligible: true + +- name: Case 12, child hours do not matter for activity requirement. + period: 2026-01 + input: + people: + person1: + age: 30 + weekly_hours_worked: 24 + person2: + age: 10 + weekly_hours_worked: 0 + is_full_time_student: false + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + meets_ccdf_activity_test: false + households: + household: + members: [person1, person2] + state_code: GA + output: + # Only heads/spouses checked; child's hours irrelevant + ga_caps_activity_eligible: true + +- name: Case 13, federal CCDF fallback approves when GA 24-hour rule fails. + period: 2026-01 + input: + people: + person1: + age: 30 + weekly_hours_worked: 10 + is_full_time_student: false + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + meets_ccdf_activity_test: true + households: + household: + members: [person1, person2] + state_code: GA + output: + # GA gate fails (10 < 24, not student), but federal CCDF fallback approves + ga_caps_activity_eligible: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_activity_eligible_edge.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_activity_eligible_edge.yaml deleted file mode 100644 index eb6dd547951..00000000000 --- a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_activity_eligible_edge.yaml +++ /dev/null @@ -1,146 +0,0 @@ -# GA CAPS activity eligibility - edge cases -# Parent must average 24 hours/week in approved activities -# (employment or full-time student) -# Existing tests cover: 24, 23, student, two-parent both pass/one fail - -- name: Case 1, single parent working exactly 25 hours just above threshold. - period: 2026-01 - input: - people: - person1: - age: 30 - weekly_hours_worked: 25 - person2: - age: 5 - spm_units: - spm_unit: - members: [person1, person2] - households: - household: - members: [person1, person2] - state_code: GA - output: - # 25 >= 24 -> eligible - ga_caps_activity_eligible: true - -- name: Case 2, single parent working zero hours and not a student. - period: 2026-01 - input: - people: - person1: - age: 30 - weekly_hours_worked: 0 - is_full_time_student: false - person2: - age: 5 - spm_units: - spm_unit: - members: [person1, person2] - households: - household: - members: [person1, person2] - state_code: GA - output: - # 0 < 24 and not a student -> ineligible - ga_caps_activity_eligible: false - -- name: Case 3, two parents both full-time students. - period: 2026-01 - input: - people: - person1: - age: 22 - weekly_hours_worked: 0 - is_full_time_student: true - person2: - age: 21 - weekly_hours_worked: 0 - is_full_time_student: true - person3: - age: 2 - tax_units: - tax_unit: - members: [person1, person2, person3] - spm_units: - spm_unit: - members: [person1, person2, person3] - households: - household: - members: [person1, person2, person3] - state_code: GA - output: - # Both are students -> both individually eligible - ga_caps_activity_eligible: true - -- name: Case 4, two parents both below 24 hours and not students. - period: 2026-01 - input: - people: - person1: - age: 30 - weekly_hours_worked: 20 - is_full_time_student: false - person2: - age: 28 - weekly_hours_worked: 15 - is_full_time_student: false - person3: - age: 4 - tax_units: - tax_unit: - members: [person1, person2, person3] - spm_units: - spm_unit: - members: [person1, person2, person3] - households: - household: - members: [person1, person2, person3] - state_code: GA - output: - # Both below 24 hrs and not students -> ineligible - ga_caps_activity_eligible: false - -- name: Case 5, single parent working 40 hours per week. - period: 2026-01 - input: - people: - person1: - age: 30 - weekly_hours_worked: 40 - person2: - age: 5 - spm_units: - spm_unit: - members: [person1, person2] - households: - household: - members: [person1, person2] - state_code: GA - output: - # 40 >= 24 -> eligible - ga_caps_activity_eligible: true - -- name: Case 6, child hours do not matter for activity requirement. - period: 2026-01 - input: - people: - person1: - age: 30 - weekly_hours_worked: 24 - person2: - age: 10 - weekly_hours_worked: 0 - is_full_time_student: false - tax_units: - tax_unit: - members: [person1, person2] - spm_units: - spm_unit: - members: [person1, person2] - households: - household: - members: [person1, person2] - state_code: GA - output: - # Only heads/spouses checked; child's hours irrelevant - ga_caps_activity_eligible: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_eligible_child.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_eligible_child.yaml index 4663b7b4c3a..ea57bbce23f 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_eligible_child.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_eligible_child.yaml @@ -184,3 +184,201 @@ state_code: GA output: ga_caps_eligible_child: [false] + +- name: Case 9, infant age 0 is eligible. + period: 2026-01 + input: + people: + person1: + age: 25 + person2: + age: 0 + + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # age 0 < 13 -> eligible + ga_caps_eligible_child: [false, true] + +- name: Case 10, toddler age 1 is eligible. + period: 2026-01 + input: + people: + person1: + age: 25 + person2: + age: 1 + + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # age 1 < 13 -> eligible + ga_caps_eligible_child: [false, true] + +- name: Case 11, preschool age 3 at boundary. + period: 2026-01 + input: + people: + person1: + age: 30 + person2: + age: 3 + + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # age 3 < 13 -> eligible + ga_caps_eligible_child: [false, true] + +- name: Case 12, school-age 6 at boundary. + period: 2026-01 + input: + people: + person1: + age: 35 + person2: + age: 6 + + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # age 6 < 13 -> eligible + ga_caps_eligible_child: [false, true] + +- name: Case 13, disabled child age 13 eligible with disability. + period: 2026-01 + input: + people: + person1: + age: 40 + person2: + age: 13 + + is_disabled: true + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # disabled, age 13 <= 17 -> eligible + ga_caps_eligible_child: [false, true] + +- name: Case 14, non-disabled child age 13 ineligible contrasted with disabled. + period: 2026-01 + input: + people: + person1: + age: 40 + person2: + age: 13 + + is_disabled: false + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # not disabled, age 13 >= 13 -> ineligible + ga_caps_eligible_child: [false, false] + +- name: Case 15, two children one eligible and one over age limit. + period: 2026-01 + input: + people: + person1: + age: 40 + person2: + age: 10 + + immigration_status: CITIZEN + person3: + age: 14 + + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: GA + output: + # person2: age 10 < 13 -> eligible + # person3: age 14 >= 13, not disabled -> ineligible + ga_caps_eligible_child: [false, true, false] + +- name: Case 16, legal permanent resident child is eligible. + period: 2026-01 + input: + people: + person1: + age: 30 + person2: + age: 5 + + immigration_status: LEGAL_PERMANENT_RESIDENT + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + ga_caps_eligible_child: [false, true] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_eligible_child_edge.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_eligible_child_edge.yaml deleted file mode 100644 index baf5ed2395c..00000000000 --- a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_eligible_child_edge.yaml +++ /dev/null @@ -1,202 +0,0 @@ -# GA CAPS eligible child - edge cases -# Standard: age < 13 (12 or younger) -# Disabled: age <= 17 -# Tests focus on age boundaries not already covered in ga_caps_eligible_child.yaml - -- name: Case 1, infant age 0 is eligible. - period: 2026-01 - input: - people: - person1: - age: 25 - person2: - age: 0 - - immigration_status: CITIZEN - tax_units: - tax_unit: - members: [person1, person2] - spm_units: - spm_unit: - members: [person1, person2] - households: - household: - members: [person1, person2] - state_code: GA - output: - # age 0 < 13 -> eligible - ga_caps_eligible_child: [false, true] - -- name: Case 2, toddler age 1 is eligible. - period: 2026-01 - input: - people: - person1: - age: 25 - person2: - age: 1 - - immigration_status: CITIZEN - tax_units: - tax_unit: - members: [person1, person2] - spm_units: - spm_unit: - members: [person1, person2] - households: - household: - members: [person1, person2] - state_code: GA - output: - # age 1 < 13 -> eligible - ga_caps_eligible_child: [false, true] - -- name: Case 3, preschool age 3 at boundary. - period: 2026-01 - input: - people: - person1: - age: 30 - person2: - age: 3 - - immigration_status: CITIZEN - tax_units: - tax_unit: - members: [person1, person2] - spm_units: - spm_unit: - members: [person1, person2] - households: - household: - members: [person1, person2] - state_code: GA - output: - # age 3 < 13 -> eligible - ga_caps_eligible_child: [false, true] - -- name: Case 4, school-age 6 at boundary. - period: 2026-01 - input: - people: - person1: - age: 35 - person2: - age: 6 - - immigration_status: CITIZEN - tax_units: - tax_unit: - members: [person1, person2] - spm_units: - spm_unit: - members: [person1, person2] - households: - household: - members: [person1, person2] - state_code: GA - output: - # age 6 < 13 -> eligible - ga_caps_eligible_child: [false, true] - -- name: Case 5, disabled child age 13 eligible with disability. - period: 2026-01 - input: - people: - person1: - age: 40 - person2: - age: 13 - - is_disabled: true - immigration_status: CITIZEN - tax_units: - tax_unit: - members: [person1, person2] - spm_units: - spm_unit: - members: [person1, person2] - households: - household: - members: [person1, person2] - state_code: GA - output: - # disabled, age 13 <= 17 -> eligible - ga_caps_eligible_child: [false, true] - -- name: Case 6, non-disabled child age 13 ineligible contrasted with disabled. - period: 2026-01 - input: - people: - person1: - age: 40 - person2: - age: 13 - - is_disabled: false - immigration_status: CITIZEN - tax_units: - tax_unit: - members: [person1, person2] - spm_units: - spm_unit: - members: [person1, person2] - households: - household: - members: [person1, person2] - state_code: GA - output: - # not disabled, age 13 >= 13 -> ineligible - ga_caps_eligible_child: [false, false] - -- name: Case 7, two children one eligible and one over age limit. - period: 2026-01 - input: - people: - person1: - age: 40 - person2: - age: 10 - - immigration_status: CITIZEN - person3: - age: 14 - - immigration_status: CITIZEN - tax_units: - tax_unit: - members: [person1, person2, person3] - spm_units: - spm_unit: - members: [person1, person2, person3] - households: - household: - members: [person1, person2, person3] - state_code: GA - output: - # person2: age 10 < 13 -> eligible - # person3: age 14 >= 13, not disabled -> ineligible - ga_caps_eligible_child: [false, true, false] - -- name: Case 8, legal permanent resident child is eligible. - period: 2026-01 - input: - people: - person1: - age: 30 - person2: - age: 5 - - immigration_status: LEGAL_PERMANENT_RESIDENT - tax_units: - tax_unit: - members: [person1, person2] - spm_units: - spm_unit: - members: [person1, person2] - households: - household: - members: [person1, person2] - state_code: GA - output: - ga_caps_eligible_child: [false, true] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_income_eligible.yaml index 1811883eb8b..7d6805cbd93 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_income_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_income_eligible.yaml @@ -127,3 +127,210 @@ state_code: GA output: ga_caps_income_eligible: true + +# Additional family sizes for boundary tests: +# Family of 3: 116,773.19 * 0.84 = $98,089.48 +# 50% SMI = $49,044.74; 85% SMI = $83,376.06 +# Family of 5: 116,773.19 * 1.16 = $135,456.90 +# 50% SMI = $67,728.45; 85% SMI = $115,138.36 + +- name: Case 7, income exactly at 50 percent SMI threshold for family of 2. + period: 2026-01 + input: + people: + person1: + age: 30 + # 50% SMI for family of 2 is $39,702.88/yr + employment_income: 39_702 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # income 39,702 <= 39,702.88 -> eligible (just at threshold) + ga_caps_income_eligible: true + +- name: Case 8, income one dollar above 50 percent SMI threshold. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 39_703 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # income 39,703 > 39,702.88 -> ineligible + ga_caps_income_eligible: false + +- name: Case 9, enrolled income exactly at 85 percent SMI threshold. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 67_494 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + ga_caps_enrolled: true + households: + household: + members: [person1, person2] + state_code: GA + output: + # enrolled: income 67,494 <= 67,494.90 -> eligible + ga_caps_income_eligible: true + +- name: Case 10, enrolled income one dollar above 85 percent SMI. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 67_495 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + ga_caps_enrolled: true + households: + household: + members: [person1, person2] + state_code: GA + output: + # enrolled: income 67,495 > 67,494.90 -> ineligible + ga_caps_income_eligible: false + +- name: Case 11, very high income family ineligible. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 200_000 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + ga_caps_income_eligible: false + +- name: Case 12, larger family of 5 at 50 percent SMI threshold. + period: 2026-01 + input: + people: + person1: + age: 35 + employment_income: 67_728 + person2: + age: 30 + person3: + age: 10 + person4: + age: 7 + person5: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5] + households: + household: + members: [person1, person2, person3, person4, person5] + state_code: GA + output: + # 50% SMI family of 5 = $67,728.45 + # income 67,728 <= 67,728.45 -> eligible + ga_caps_income_eligible: true + +- name: Case 13, larger family of 5 one dollar over threshold. + period: 2026-01 + input: + people: + person1: + age: 35 + employment_income: 67_729 + person2: + age: 30 + person3: + age: 10 + person4: + age: 7 + person5: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5] + households: + household: + members: [person1, person2, person3, person4, person5] + state_code: GA + output: + # 50% SMI family of 5 = $67,728.45 + # income 67,729 > 67,728.45 -> ineligible + ga_caps_income_eligible: false + +- name: Case 14, enrolled family of 3 at ongoing threshold. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 83_376 + person2: + age: 28 + person3: + age: 5 + spm_units: + spm_unit: + members: [person1, person2, person3] + ga_caps_enrolled: true + households: + household: + members: [person1, person2, person3] + state_code: GA + output: + # 85% SMI family of 3 = $83,376.06 + # enrolled: income 83,376 <= 83,376.06 -> eligible + ga_caps_income_eligible: true + +- name: Case 15, multiple income sources combined. + period: 2026-01 + input: + people: + person1: + age: 30 + employment_income: 25_000 + self_employment_income: 10_000 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + output: + # total income = 25,000 + 10,000 = 35,000 <= 39,702.88 -> eligible + ga_caps_income_eligible: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_income_eligible_edge.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_income_eligible_edge.yaml deleted file mode 100644 index c1735399e50..00000000000 --- a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_income_eligible_edge.yaml +++ /dev/null @@ -1,215 +0,0 @@ -# GA CAPS income eligibility - edge cases -# Initial (not enrolled): income <= 50% SMI -# Ongoing (enrolled): income <= 85% SMI -# -# GA SMI for 4-person household at 2026-01: $116,773.19 (uprated) -# Family of 2: 116,773.19 * 0.68 = $79,405.77 -# 50% SMI = $39,702.88 -# 85% SMI = $67,494.90 -# Family of 3: 116,773.19 * 0.84 = $98,089.48 -# 50% SMI = $49,044.74 -# 85% SMI = $83,376.06 -# Family of 5: 116,773.19 * 1.16 = $135,456.90 -# 50% SMI = $67,728.45 -# 85% SMI = $115,138.36 - -- name: Case 1, income exactly at 50 percent SMI threshold for family of 2. - period: 2026-01 - input: - people: - person1: - age: 30 - # 50% SMI for family of 2 is $39,702.88/yr - employment_income: 39_702 - person2: - age: 5 - spm_units: - spm_unit: - members: [person1, person2] - households: - household: - members: [person1, person2] - state_code: GA - output: - # income 39,702 <= 39,702.88 -> eligible (just at threshold) - ga_caps_income_eligible: true - -- name: Case 2, income one dollar above 50 percent SMI threshold. - period: 2026-01 - input: - people: - person1: - age: 30 - employment_income: 39_703 - person2: - age: 5 - spm_units: - spm_unit: - members: [person1, person2] - households: - household: - members: [person1, person2] - state_code: GA - output: - # income 39,703 > 39,702.88 -> ineligible - ga_caps_income_eligible: false - -- name: Case 3, enrolled income exactly at 85 percent SMI threshold. - period: 2026-01 - input: - people: - person1: - age: 30 - employment_income: 67_494 - person2: - age: 5 - spm_units: - spm_unit: - members: [person1, person2] - ga_caps_enrolled: true - households: - household: - members: [person1, person2] - state_code: GA - output: - # enrolled: income 67,494 <= 67,494.90 -> eligible - ga_caps_income_eligible: true - -- name: Case 4, enrolled income one dollar above 85 percent SMI. - period: 2026-01 - input: - people: - person1: - age: 30 - employment_income: 67_495 - person2: - age: 5 - spm_units: - spm_unit: - members: [person1, person2] - ga_caps_enrolled: true - households: - household: - members: [person1, person2] - state_code: GA - output: - # enrolled: income 67,495 > 67,494.90 -> ineligible - ga_caps_income_eligible: false - -- name: Case 5, very high income family ineligible. - period: 2026-01 - input: - people: - person1: - age: 30 - employment_income: 200_000 - person2: - age: 5 - spm_units: - spm_unit: - members: [person1, person2] - households: - household: - members: [person1, person2] - state_code: GA - output: - ga_caps_income_eligible: false - -- name: Case 6, larger family of 5 at 50 percent SMI threshold. - period: 2026-01 - input: - people: - person1: - age: 35 - employment_income: 67_728 - person2: - age: 30 - person3: - age: 10 - person4: - age: 7 - person5: - age: 3 - spm_units: - spm_unit: - members: [person1, person2, person3, person4, person5] - households: - household: - members: [person1, person2, person3, person4, person5] - state_code: GA - output: - # 50% SMI family of 5 = $67,728.45 - # income 67,728 <= 67,728.45 -> eligible - ga_caps_income_eligible: true - -- name: Case 7, larger family of 5 one dollar over threshold. - period: 2026-01 - input: - people: - person1: - age: 35 - employment_income: 67_729 - person2: - age: 30 - person3: - age: 10 - person4: - age: 7 - person5: - age: 3 - spm_units: - spm_unit: - members: [person1, person2, person3, person4, person5] - households: - household: - members: [person1, person2, person3, person4, person5] - state_code: GA - output: - # 50% SMI family of 5 = $67,728.45 - # income 67,729 > 67,728.45 -> ineligible - ga_caps_income_eligible: false - -- name: Case 8, enrolled family of 3 at ongoing threshold. - period: 2026-01 - input: - people: - person1: - age: 30 - employment_income: 83_376 - person2: - age: 28 - person3: - age: 5 - spm_units: - spm_unit: - members: [person1, person2, person3] - ga_caps_enrolled: true - households: - household: - members: [person1, person2, person3] - state_code: GA - output: - # 85% SMI family of 3 = $83,376.06 - # enrolled: income 83,376 <= 83,376.06 -> eligible - ga_caps_income_eligible: true - -- name: Case 9, multiple income sources combined. - period: 2026-01 - input: - people: - person1: - age: 30 - employment_income: 25_000 - self_employment_income: 10_000 - person2: - age: 5 - spm_units: - spm_unit: - members: [person1, person2] - households: - household: - members: [person1, person2] - state_code: GA - output: - # total income = 25,000 + 10,000 = 35,000 <= 39,702.88 -> eligible - ga_caps_income_eligible: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/ga_caps_edge.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/ga_caps.yaml similarity index 94% rename from policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/ga_caps_edge.yaml rename to policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/ga_caps.yaml index 896882919af..23bcf5c9bcb 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/ga_caps_edge.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/ga_caps.yaml @@ -1,5 +1,8 @@ -# GA CAPS benefit - edge cases -# Subsidy = max(min(expenses, base_max) - fee, 0) * (1 + quality_bonus_rate) +# GA CAPS benefit +# Per-child weekly subsidy = min(state max rate, provider published rate). +# When ga_caps_provider_published_rate is not provided, it defaults to an +# even share of spm_unit_pre_subsidy_childcare_expenses across eligible children. +# Subsidy = max(sum(per_child_weekly) * 52/12 - family_fee, 0) * (1 + weighted_quality_bonus_rate) # # 2026 FPG (Contiguous US): # first_person = 15,960, additional = 5,680 @@ -305,13 +308,15 @@ # weekly fee = floor(15,000 * 0.05 / 52) = floor(14.42) = $14 # monthly fee = 14 * 52 / 12 = $60.67 ga_caps_family_fee: 60.67 - # base_max_monthly = (145 + 68) * 52 / 12 = 213 * 52 / 12 = $923.00 - # pre_subsidy_monthly = 12,000 / 12 = $1,000 - # base_payment = min(1,000, 923.00) = $923.00 - # net_base = max(923.00 - 60.67, 0) = $862.33 + # pre_subsidy_weekly_per_child = 12,000 / 52 / 2 = $115.38 + # person2 (infant family FT, max $145): min($145, $115.38) = $115.38 + # person3 (school B/A, max $68): min($68, $115.38) = $68 + # total_weekly_base = $115.38 + $68 = $183.38 + # base_monthly = $183.38 * 52/12 = $794.65 + # net_base = max($794.65 - $60.67, 0) = $733.98 # no quality bonus (NONE rating) - # subsidy = $862.33 - ga_caps: 862.33 + # subsidy = $733.98 + ga_caps: 733.98 - name: Case 8, zero income family gets maximum subsidy up to expenses. period: 2026-01 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/integration.yaml index 5922b383053..0d2bac83f3a 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/integration.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/integration.yaml @@ -282,13 +282,16 @@ ga_caps_family_fee: 82.33 # === Benefit === - # base_max_monthly = (130 + 53) * 52 / 12 = 183 * 52 / 12 = $793.00 - # pre_subsidy_monthly = 10,000 / 12 = $833.33 - # base_payment = min(833.33, 793.00) = $793.00 - # net_base = max(793.00 - 82.33, 0) = $710.67 - # effective_bonus = (130*0.05 + 53*0.05) / 183 = 9.15 / 183 = 0.05 - # subsidy = 710.67 * 1.05 = $746.20 - ga_caps: 746.20 + # pre_subsidy_weekly_per_child = 10,000 / 52 / 2 = $96.15 + # person2 (infant FT, max $130): min($130, $96.15) = $96.15 + # person3 (school B/A, max $53): min($53, $96.15) = $53 + # total_weekly_base = $96.15 + $53 = $149.15 + # base_monthly = $149.15 * 52/12 = $646.32 + # net_base = max($646.32 - $82.33, 0) = $563.99 + # weighted_bonus = $96.15 * 0.05 + $53 * 0.05 = $7.46 + # weighted_bonus_rate = $7.46 / $149.15 = 0.05 + # subsidy = $563.99 * 1.05 = $592.19 + ga_caps: 592.19 - name: Case 6, disabled teenager with family care in Zone 2. period: 2026-01 @@ -360,9 +363,11 @@ person1: age: 35 employment_income: 20_000 + immigration_status: CITIZEN person2: age: 4 + immigration_status: CITIZEN ga_caps_provider_type: CENTER ga_caps_care_type: FULL_TIME tax_units: @@ -378,3 +383,352 @@ state_code: FL output: ga_caps: 0 + +# 2026 FPG family of 5: 38,680; family of 6: 44,360 +# 50% SMI family of 5 = $67,728.45; family of 6 = $77,070.30 + +- name: Case 8, large family of 6 at income threshold boundary. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income: 73_085 + immigration_status: CITIZEN + person2: + age: 38 + immigration_status: CITIZEN + person3: + age: 10 + + immigration_status: CITIZEN + ga_caps_provider_type: CENTER + ga_caps_care_type: BEFORE_AFTER_SCHOOL + ga_caps_quality_rating: NONE + person4: + age: 3 + + immigration_status: CITIZEN + ga_caps_provider_type: FAMILY + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: TWO_STAR + person5: + age: 0 + + immigration_status: CITIZEN + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: TWO_STAR + person6: + age: 14 + + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2, person3, person4, person5, person6] + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5, person6] + spm_unit_pre_subsidy_childcare_expenses: 20_000 + households: + household: + members: [person1, person2, person3, person4, person5, person6] + state_code: GA + county_str: COBB_COUNTY_GA + output: + # === Eligibility === + # person3 (10): age < 13 -> eligible + # person4 (3): age < 13 -> eligible + # person5 (0): age < 13 -> eligible + # person6 (14): age >= 13, not disabled -> ineligible + ga_caps_eligible_child: [false, false, true, true, true, false] + + # 50% SMI family of 6 = $77,070.30 + # income 73,085 <= 77,070.30 -> eligible + ga_caps_income_eligible: true + ga_caps_eligible: true + + # === Zone and rates === + # Cobb County -> Zone 1 + ga_caps_zone: ZONE_1 + # person3 (10): SCHOOL_AGE, Zone 1 Center B/A School = $84/week + # person4 (3): PRESCHOOL, Zone 1 Family FT = $180/week + # person5 (0): INFANT, Zone 1 Center FT = $260/week + ga_caps_age_group: [PRESCHOOL, PRESCHOOL, SCHOOL_AGE, PRESCHOOL, INFANT, PRESCHOOL] + ga_caps_maximum_weekly_benefit: [0, 0, 84, 180, 260, 0] + + # === Family fee === + # FPG family of 6: $44,360 + # FPL ratio = 73,085 / 44,360 = 1.648 -> 7% rate + # weekly fee = floor(73,085 * 0.07 / 52) = floor(98.38) = $98 + # monthly fee = 98 * 52 / 12 = $424.67 + ga_caps_family_fee: 424.67 + + # === Benefit === + # pre_subsidy_weekly_per_child = 20,000 / 52 / 3 = $128.21 + # person3: min($84, $128.21) = $84 + # person4: min($180, $128.21) = $128.21 + # person5: min($260, $128.21) = $128.21 + # total_weekly_base = $84 + $128.21 + $128.21 = $340.42 + # base_monthly = $340.42 * 52/12 = $1,475.16 + # net_base = max($1,475.16 - $424.67, 0) = $1,050.49 + # weighted_bonus = $84*0 + $128.21*0.05 + $128.21*0.05 = $12.82 + # weighted_bonus_rate = $12.82 / $340.42 = 0.0377 + # subsidy = $1,050.49 * 1.0377 = $1,090.10 + ga_caps: 1_090.10 + +- name: Case 9, enrolled family between 50 and 85 percent SMI. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + employment_income: 50_000 + immigration_status: CITIZEN + person2: + age: 1 + + immigration_status: CITIZEN + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: THREE_STAR + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + ga_caps_enrolled: true + spm_unit_pre_subsidy_childcare_expenses: 15_000 + households: + household: + members: [person1, person2] + state_code: GA + county_str: DEKALB_COUNTY_GA + output: + # === Eligibility === + ga_caps_eligible_child: [false, true] + # enrolled: 50,000 <= 67,494.90 (85% SMI) -> eligible + # NOT eligible as new applicant: 50,000 > 39,702.88 (50% SMI) + ga_caps_income_eligible: true + ga_caps_eligible: true + + # === Zone and rates === + # DeKalb County -> Zone 1 + ga_caps_zone: ZONE_1 + # Age 1 -> TODDLER, Zone 1 Center FT = $248/week + ga_caps_age_group: [PRESCHOOL, TODDLER] + ga_caps_maximum_weekly_benefit: [0, 248] + + # === Family fee === + # FPG family of 2: $21,640 + # FPL ratio = 50,000 / 21,640 = 2.311 -> 7% rate + # weekly fee = floor(50,000 * 0.07 / 52) = floor(67.31) = $67 + # monthly fee = 67 * 52 / 12 = $290.33 + ga_caps_family_fee: 290.33 + + # === Benefit === + # pre_subsidy_weekly = 15,000 / 52 = $288.46 + # per_child = min($248, $288.46) = $248 + # base_monthly = $248 * 52/12 = $1,074.67 + # net_base = max($1,074.67 - $290.33, 0) = $784.33 + # weighted_bonus_rate = ($248 * 0.10) / $248 = 0.10 + # subsidy = $784.33 * 1.10 = $862.77 + ga_caps: 862.77 + +- name: Case 10, non-enrolled family at 50 percent SMI plus 1 dollar is ineligible. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + employment_income: 39_703 + immigration_status: CITIZEN + person2: + age: 4 + + immigration_status: CITIZEN + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: THREE_STAR + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 12_000 + households: + household: + members: [person1, person2] + state_code: GA + county_str: FULTON_COUNTY_GA + output: + ga_caps_eligible_child: [false, true] + # 39,703 > 39,702.88 (50% SMI for family of 2) -> ineligible + ga_caps_income_eligible: false + ga_caps_eligible: false + ga_caps: 0 + +- name: Case 11, mixed eligible and ineligible children in family. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 45 + employment_income: 30_000 + immigration_status: CITIZEN + person2: + age: 5 + + immigration_status: CITIZEN + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: NONE + person3: + age: 14 + + immigration_status: CITIZEN + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + spm_unit_pre_subsidy_childcare_expenses: 10_000 + households: + household: + members: [person1, person2, person3] + state_code: GA + county_str: BIBB_COUNTY_GA + output: + # person2 (5): eligible, person3 (14): ineligible (not disabled) + ga_caps_eligible_child: [false, true, false] + # Family has at least one eligible child -> eligible + ga_caps_eligible: true + # Bibb -> Zone 2 + ga_caps_zone: ZONE_2 + # Only person2 gets a rate: Zone 2 Center Preschool FT = $150/week + # person3 is not an eligible child -> 0 rate + ga_caps_maximum_weekly_benefit: [0, 150, 0] + # FPG family of 3 = $27,320 + # FPL ratio = 30,000 / 27,320 = 1.098 -> 7% rate + # weekly fee = floor(30,000 * 0.07 / 52) = floor(40.38) = $40 + # monthly fee = 40 * 52 / 12 = $173.33 + ga_caps_family_fee: 173.33 + # pre_subsidy_weekly = 10,000 / 52 / 1 = $192.31 (only 1 eligible child) + # per_child = min($150, $192.31) = $150 + # base_monthly = $150 * 52/12 = $650 + # net_base = max($650 - $173.33, 0) = $476.67 + # no quality bonus (NONE) + ga_caps: 476.67 + +- name: Case 12, disabled child age 16 with family provider in Zone 3. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 50 + employment_income: 20_000 + immigration_status: CITIZEN + person2: + age: 16 + + is_disabled: true + immigration_status: CITIZEN + ga_caps_provider_type: FAMILY + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: TWO_STAR + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_pre_subsidy_childcare_expenses: 5_000 + households: + household: + members: [person1, person2] + state_code: GA + county_str: APPLING_COUNTY_GA + output: + # disabled child age 16 <= 17 -> eligible + ga_caps_eligible_child: [false, true] + ga_caps_eligible: true + # Appling -> Zone 3 + ga_caps_zone: ZONE_3 + # Age 16 -> SCHOOL_AGE, Zone 3 Family FT = $94/week + ga_caps_maximum_weekly_benefit: [0, 94] + # FPG family of 2 = $21,640 + # FPL ratio = 20,000 / 21,640 = 0.924 -> 5% rate + # weekly fee = floor(20,000 * 0.05 / 52) = floor(19.23) = $19 + # monthly fee = 19 * 52 / 12 = $82.33 + ga_caps_family_fee: 82.33 + # pre_subsidy_weekly = 5,000 / 52 = $96.15 + # per_child = min($94, $96.15) = $94 + # base_monthly = $94 * 52/12 = $407.33 + # net_base = max($407.33 - $82.33, 0) = $325.00 + # weighted_bonus_rate = ($94 * 0.05) / $94 = 0.05 + # subsidy = $325.00 * 1.05 = $341.25 + ga_caps: 341.25 + +- name: Case 13, two-parent family where one is a student. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 20_000 + immigration_status: CITIZEN + weekly_hours_worked: 24 + person2: + age: 28 + immigration_status: CITIZEN + weekly_hours_worked: 0 + is_full_time_student: true + person3: + age: 4 + + immigration_status: CITIZEN + ga_caps_provider_type: CENTER + ga_caps_care_type: FULL_TIME + ga_caps_quality_rating: NONE + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + meets_ccdf_activity_test: false + spm_unit_pre_subsidy_childcare_expenses: 10_000 + households: + household: + members: [person1, person2, person3] + state_code: GA + county_str: FULTON_COUNTY_GA + output: + ga_caps_eligible_child: [false, false, true] + # parent1: 24 hrs >= 24 -> ok + # parent2: student -> ok + # GA-specific activity gate isolated by pinning meets_ccdf_activity_test=false + ga_caps_activity_eligible: true + ga_caps_eligible: true + # Zone 1, Center, Preschool, FT = $221/week + ga_caps_maximum_weekly_benefit: [0, 0, 221] + # FPG family of 3 = $27,320 + # FPL ratio = 20,000 / 27,320 = 0.732 -> 5% rate + # weekly fee = floor(20,000 * 0.05 / 52) = floor(19.23) = $19 + # monthly fee = 19 * 52 / 12 = $82.33 + ga_caps_family_fee: 82.33 + # pre_subsidy_weekly = 10,000 / 52 = $192.31 + # per_child = min($221, $192.31) = $192.31 + # base_monthly = $192.31 * 52/12 = $833.33 + # net_base = max($833.33 - $82.33, 0) = $751.00 + # no quality bonus (NONE) + ga_caps: 751.00 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/integration_edge.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/integration_edge.yaml deleted file mode 100644 index d3cdcda24fb..00000000000 --- a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/integration_edge.yaml +++ /dev/null @@ -1,361 +0,0 @@ -# GA CAPS Integration Edge Cases -# -# 2026 FPG (Contiguous US): -# first_person = 15,960, additional = 5,680 -# Family of 2: 21,640 -# Family of 3: 27,320 -# Family of 4: 33,000 -# Family of 5: 38,680 -# Family of 6: 44,360 -# -# GA SMI 4-person at 2026-01: $116,773.19 (uprated) -# Family of 2: 116,773.19 * 0.68 = $79,405.77 -> 50% = $39,702.88 -# Family of 3: 116,773.19 * 0.84 = $98,089.48 -> 50% = $49,044.74 -# Family of 5: 116,773.19 * 1.16 = $135,456.90 -> 50% = $67,728.45 -# Family of 6: 116,773.19 * 1.32 = $154,140.61 -> 50% = $77,070.30 - -- name: Case 1, large family of 6 at income threshold boundary. - period: 2026-01 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 40 - employment_income: 73_085 - immigration_status: CITIZEN - person2: - age: 38 - immigration_status: CITIZEN - person3: - age: 10 - - immigration_status: CITIZEN - ga_caps_provider_type: CENTER - ga_caps_care_type: BEFORE_AFTER_SCHOOL - ga_caps_quality_rating: NONE - person4: - age: 3 - - immigration_status: CITIZEN - ga_caps_provider_type: FAMILY - ga_caps_care_type: FULL_TIME - ga_caps_quality_rating: TWO_STAR - person5: - age: 0 - - immigration_status: CITIZEN - ga_caps_provider_type: CENTER - ga_caps_care_type: FULL_TIME - ga_caps_quality_rating: TWO_STAR - person6: - age: 14 - - immigration_status: CITIZEN - tax_units: - tax_unit: - members: [person1, person2, person3, person4, person5, person6] - spm_units: - spm_unit: - members: [person1, person2, person3, person4, person5, person6] - spm_unit_pre_subsidy_childcare_expenses: 20_000 - households: - household: - members: [person1, person2, person3, person4, person5, person6] - state_code: GA - county_str: COBB_COUNTY_GA - output: - # === Eligibility === - # person3 (10): age < 13 -> eligible - # person4 (3): age < 13 -> eligible - # person5 (0): age < 13 -> eligible - # person6 (14): age >= 13, not disabled -> ineligible - ga_caps_eligible_child: [false, false, true, true, true, false] - - # 50% SMI family of 6 = $77,070.30 - # income 73,085 <= 77,070.30 -> eligible - ga_caps_income_eligible: true - ga_caps_eligible: true - - # === Zone and rates === - # Cobb County -> Zone 1 - ga_caps_zone: ZONE_1 - # person3 (10): SCHOOL_AGE, Zone 1 Center B/A School = $84/week - # person4 (3): PRESCHOOL, Zone 1 Family FT = $180/week - # person5 (0): INFANT, Zone 1 Center FT = $260/week - ga_caps_age_group: [PRESCHOOL, PRESCHOOL, SCHOOL_AGE, PRESCHOOL, INFANT, PRESCHOOL] - ga_caps_maximum_weekly_benefit: [0, 0, 84, 180, 260, 0] - - # === Family fee === - # FPG family of 6: $44,360 - # FPL ratio = 73,085 / 44,360 = 1.648 -> 7% rate - # weekly fee = floor(73,085 * 0.07 / 52) = floor(98.38) = $98 - # monthly fee = 98 * 52 / 12 = $424.67 - ga_caps_family_fee: 424.67 - - # === Benefit === - # base_max_weekly = 84 + 180 + 260 = $524 - # base_max_monthly = 524 * 52 / 12 = $2,270.67 - # pre_subsidy_monthly = 20,000 / 12 = $1,666.67 - # base_payment = min(1,666.67, 2,270.67) = $1,666.67 - # net_base = max(1,666.67 - 424.67, 0) = $1,242.00 - # - # quality: person3 NONE (0%), person4 TWO_STAR (5%), person5 TWO_STAR (5%) - # weighted_bonus = 84*0 + 180*0.05 + 260*0.05 = 0 + 9 + 13 = 22 - # effective_bonus = 22 / 524 = 0.04198 - # subsidy = 1,242.00 * 1.04198 = $1,294.15 - ga_caps: 1_294.15 - -- name: Case 2, enrolled family between 50 and 85 percent SMI. - period: 2026-01 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 35 - employment_income: 50_000 - immigration_status: CITIZEN - person2: - age: 1 - - immigration_status: CITIZEN - ga_caps_provider_type: CENTER - ga_caps_care_type: FULL_TIME - ga_caps_quality_rating: THREE_STAR - tax_units: - tax_unit: - members: [person1, person2] - spm_units: - spm_unit: - members: [person1, person2] - ga_caps_enrolled: true - spm_unit_pre_subsidy_childcare_expenses: 15_000 - households: - household: - members: [person1, person2] - state_code: GA - county_str: DEKALB_COUNTY_GA - output: - # === Eligibility === - ga_caps_eligible_child: [false, true] - # enrolled: 50,000 <= 67,494.90 (85% SMI) -> eligible - # NOT eligible as new applicant: 50,000 > 39,702.88 (50% SMI) - ga_caps_income_eligible: true - ga_caps_eligible: true - - # === Zone and rates === - # DeKalb County -> Zone 1 - ga_caps_zone: ZONE_1 - # Age 1 -> TODDLER, Zone 1 Center FT = $248/week - ga_caps_age_group: [PRESCHOOL, TODDLER] - ga_caps_maximum_weekly_benefit: [0, 248] - - # === Family fee === - # FPG family of 2: $21,640 - # FPL ratio = 50,000 / 21,640 = 2.311 -> 7% rate - # weekly fee = floor(50,000 * 0.07 / 52) = floor(67.31) = $67 - # monthly fee = 67 * 52 / 12 = $290.33 - ga_caps_family_fee: 290.33 - - # === Benefit === - # base_max_monthly = 248 * 52 / 12 = $1,074.67 - # pre_subsidy_monthly = 15,000 / 12 = $1,250.00 - # base_payment = min(1,250.00, 1,074.67) = $1,074.67 - # net_base = max(1,074.67 - 290.33, 0) = $784.33 - # effective_bonus = (248 * 0.10) / 248 = 0.10 - # subsidy = 784.33 * 1.10 = $862.77 - ga_caps: 862.77 - -- name: Case 3, non-enrolled family at 50 percent SMI plus 1 dollar is ineligible. - period: 2026-01 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 35 - employment_income: 39_703 - immigration_status: CITIZEN - person2: - age: 4 - - immigration_status: CITIZEN - ga_caps_provider_type: CENTER - ga_caps_care_type: FULL_TIME - ga_caps_quality_rating: THREE_STAR - tax_units: - tax_unit: - members: [person1, person2] - spm_units: - spm_unit: - members: [person1, person2] - spm_unit_pre_subsidy_childcare_expenses: 12_000 - households: - household: - members: [person1, person2] - state_code: GA - county_str: FULTON_COUNTY_GA - output: - ga_caps_eligible_child: [false, true] - # 39,703 > 39,702.88 (50% SMI for family of 2) -> ineligible - ga_caps_income_eligible: false - ga_caps_eligible: false - ga_caps: 0 - -- name: Case 4, mixed eligible and ineligible children in family. - period: 2026-01 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 45 - employment_income: 30_000 - immigration_status: CITIZEN - person2: - age: 5 - - immigration_status: CITIZEN - ga_caps_provider_type: CENTER - ga_caps_care_type: FULL_TIME - ga_caps_quality_rating: NONE - person3: - age: 14 - - immigration_status: CITIZEN - tax_units: - tax_unit: - members: [person1, person2, person3] - spm_units: - spm_unit: - members: [person1, person2, person3] - spm_unit_pre_subsidy_childcare_expenses: 10_000 - households: - household: - members: [person1, person2, person3] - state_code: GA - county_str: BIBB_COUNTY_GA - output: - # person2 (5): eligible, person3 (14): ineligible (not disabled) - ga_caps_eligible_child: [false, true, false] - # Family has at least one eligible child -> eligible - ga_caps_eligible: true - # Bibb -> Zone 2 - ga_caps_zone: ZONE_2 - # Only person2 gets a rate: Zone 2 Center Preschool FT = $150/week - # person3 is not an eligible child -> 0 rate - ga_caps_maximum_weekly_benefit: [0, 150, 0] - # FPG family of 3 = $27,320 - # FPL ratio = 30,000 / 27,320 = 1.098 -> 7% rate - # weekly fee = floor(30,000 * 0.07 / 52) = floor(40.38) = $40 - # monthly fee = 40 * 52 / 12 = $173.33 - ga_caps_family_fee: 173.33 - # base_max_monthly = 150 * 52 / 12 = $650.00 - # pre_subsidy_monthly = 10,000 / 12 = $833.33 - # base_payment = min(833.33, 650.00) = $650.00 - # net_base = max(650.00 - 173.33, 0) = $476.67 - # no quality bonus (NONE rating) - # subsidy = $476.67 - ga_caps: 476.67 - -- name: Case 5, disabled child age 16 with family provider in Zone 3. - period: 2026-01 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 50 - employment_income: 20_000 - immigration_status: CITIZEN - person2: - age: 16 - - is_disabled: true - immigration_status: CITIZEN - ga_caps_provider_type: FAMILY - ga_caps_care_type: FULL_TIME - ga_caps_quality_rating: TWO_STAR - tax_units: - tax_unit: - members: [person1, person2] - spm_units: - spm_unit: - members: [person1, person2] - spm_unit_pre_subsidy_childcare_expenses: 5_000 - households: - household: - members: [person1, person2] - state_code: GA - county_str: APPLING_COUNTY_GA - output: - # disabled child age 16 <= 17 -> eligible - ga_caps_eligible_child: [false, true] - ga_caps_eligible: true - # Appling -> Zone 3 - ga_caps_zone: ZONE_3 - # Age 16 -> SCHOOL_AGE, Zone 3 Family FT = $94/week - ga_caps_maximum_weekly_benefit: [0, 94] - # FPG family of 2 = $21,640 - # FPL ratio = 20,000 / 21,640 = 0.924 -> 5% rate - # weekly fee = floor(20,000 * 0.05 / 52) = floor(19.23) = $19 - # monthly fee = 19 * 52 / 12 = $82.33 - ga_caps_family_fee: 82.33 - # base_max_monthly = 94 * 52 / 12 = $407.33 - # pre_subsidy_monthly = 5,000 / 12 = $416.67 - # base_payment = min(416.67, 407.33) = $407.33 - # net_base = max(407.33 - 82.33, 0) = $325.00 - # effective_bonus = (94 * 0.05) / 94 = 0.05 - # subsidy = 325.00 * 1.05 = $341.25 - ga_caps: 341.25 - -- name: Case 6, two-parent family where one is a student. - period: 2026-01 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 30 - employment_income: 20_000 - immigration_status: CITIZEN - weekly_hours_worked: 24 - person2: - age: 28 - immigration_status: CITIZEN - weekly_hours_worked: 0 - is_full_time_student: true - person3: - age: 4 - - immigration_status: CITIZEN - ga_caps_provider_type: CENTER - ga_caps_care_type: FULL_TIME - ga_caps_quality_rating: NONE - tax_units: - tax_unit: - members: [person1, person2, person3] - spm_units: - spm_unit: - members: [person1, person2, person3] - spm_unit_pre_subsidy_childcare_expenses: 10_000 - households: - household: - members: [person1, person2, person3] - state_code: GA - county_str: FULTON_COUNTY_GA - output: - ga_caps_eligible_child: [false, false, true] - # parent1: 24 hrs >= 24 -> ok - # parent2: student -> ok - ga_caps_activity_eligible: true - ga_caps_eligible: true - # Zone 1, Center, Preschool, FT = $221/week - ga_caps_maximum_weekly_benefit: [0, 0, 221] - # FPG family of 3 = $27,320 - # FPL ratio = 20,000 / 27,320 = 0.732 -> 5% rate - # weekly fee = floor(20,000 * 0.05 / 52) = floor(19.23) = $19 - # monthly fee = 19 * 52 / 12 = $82.33 - ga_caps_family_fee: 82.33 - # base_max_monthly = 221 * 52 / 12 = $957.67 - # pre_subsidy_monthly = 10,000 / 12 = $833.33 - # base_payment = min(833.33, 957.67) = $833.33 - # net_base = max(833.33 - 82.33, 0) = $751.00 - # no quality bonus (NONE rating) - # subsidy = $751.00 - ga_caps: 751.00 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/payment/ga_caps_maximum_weekly_benefit.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/payment/ga_caps_maximum_weekly_benefit.yaml index 1f2185e88b2..bb04ce7ebf5 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/payment/ga_caps_maximum_weekly_benefit.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/payment/ga_caps_maximum_weekly_benefit.yaml @@ -325,3 +325,101 @@ output: # Zone 3, Family, School Age, Full-time = $94/week ga_caps_maximum_weekly_benefit: [0, 94] + +- name: Case 15, Zone 1 center part-time infant 3 days per week. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 0 + ga_caps_provider_type: CENTER + ga_caps_care_type: PART_TIME + childcare_days_per_week: 3 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + county_str: FULTON_COUNTY_GA + output: + # Zone 1, Center, Infant, Part-time = $65/day + # Weekly = 65 * 3 = $195 + ga_caps_maximum_weekly_benefit: [0, 195] + +- name: Case 16, Zone 1 center part-time infant 5 days per week. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 0 + ga_caps_provider_type: CENTER + ga_caps_care_type: PART_TIME + childcare_days_per_week: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + county_str: FULTON_COUNTY_GA + output: + # Zone 1, Center, Infant, Part-time = $65/day + # Weekly = 65 * 5 = $325 + ga_caps_maximum_weekly_benefit: [0, 325] + +- name: Case 17, Zone 3 informal part-time school-age 2 days per week. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 8 + ga_caps_provider_type: INFORMAL + ga_caps_care_type: PART_TIME + childcare_days_per_week: 2 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + county_str: APPLING_COUNTY_GA + output: + # Zone 3, Informal, School Age, Part-time = $35/day + # Weekly = 35 * 2 = $70 + ga_caps_maximum_weekly_benefit: [0, 70] + +- name: Case 18, Zone 2 family before-after school toddler. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + person2: + age: 2 + ga_caps_provider_type: FAMILY + ga_caps_care_type: BEFORE_AFTER_SCHOOL + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: GA + county_str: CHATHAM_COUNTY_GA + output: + # Zone 2, Family, Toddler, Before-After-School = $58/week (not daily) + ga_caps_maximum_weekly_benefit: [0, 58] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/payment/ga_caps_maximum_weekly_benefit_edge.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/payment/ga_caps_maximum_weekly_benefit_edge.yaml deleted file mode 100644 index 4ac7ae5839b..00000000000 --- a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/payment/ga_caps_maximum_weekly_benefit_edge.yaml +++ /dev/null @@ -1,172 +0,0 @@ -# GA CAPS maximum weekly benefit - edge cases -# Part-time rates are daily; weekly = daily * childcare_days_per_week -# Tests for part-time day conversion and provider type coverage - -- name: Case 1, Zone 1 center part-time infant 3 days per week. - period: 2026-01 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 30 - person2: - age: 0 - ga_caps_provider_type: CENTER - ga_caps_care_type: PART_TIME - childcare_days_per_week: 3 - spm_units: - spm_unit: - members: [person1, person2] - households: - household: - members: [person1, person2] - state_code: GA - county_str: FULTON_COUNTY_GA - output: - # Zone 1, Center, Infant, Part-time = $65/day - # Weekly = 65 * 3 = $195 - ga_caps_maximum_weekly_benefit: [0, 195] - -- name: Case 2, Zone 1 center part-time infant 5 days per week. - period: 2026-01 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 30 - person2: - age: 0 - ga_caps_provider_type: CENTER - ga_caps_care_type: PART_TIME - childcare_days_per_week: 5 - spm_units: - spm_unit: - members: [person1, person2] - households: - household: - members: [person1, person2] - state_code: GA - county_str: FULTON_COUNTY_GA - output: - # Zone 1, Center, Infant, Part-time = $65/day - # Weekly = 65 * 5 = $325 - ga_caps_maximum_weekly_benefit: [0, 325] - -- name: Case 3, Zone 3 informal part-time school-age 2 days per week. - period: 2026-01 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 30 - person2: - age: 8 - ga_caps_provider_type: INFORMAL - ga_caps_care_type: PART_TIME - childcare_days_per_week: 2 - spm_units: - spm_unit: - members: [person1, person2] - households: - household: - members: [person1, person2] - state_code: GA - county_str: APPLING_COUNTY_GA - output: - # Zone 3, Informal, School Age, Part-time = $35/day - # Weekly = 35 * 2 = $70 - ga_caps_maximum_weekly_benefit: [0, 70] - -- name: Case 4, Zone 2 family before-after school toddler. - period: 2026-01 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 30 - person2: - age: 2 - ga_caps_provider_type: FAMILY - ga_caps_care_type: BEFORE_AFTER_SCHOOL - spm_units: - spm_unit: - members: [person1, person2] - households: - household: - members: [person1, person2] - state_code: GA - county_str: CHATHAM_COUNTY_GA - output: - # Zone 2, Family, Toddler, Before-After-School = $58/week (not daily) - ga_caps_maximum_weekly_benefit: [0, 58] - -- name: Case 5, Zone 1 center full-time infant highest rate. - period: 2026-01 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 30 - person2: - age: 0 - ga_caps_provider_type: CENTER - ga_caps_care_type: FULL_TIME - spm_units: - spm_unit: - members: [person1, person2] - households: - household: - members: [person1, person2] - state_code: GA - county_str: FULTON_COUNTY_GA - output: - # Zone 1, Center, Infant, Full-time = $260/week (highest rate in table) - ga_caps_maximum_weekly_benefit: [0, 260] - -- name: Case 6, Zone 3 family full-time school-age lowest full-time rate. - period: 2026-01 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 30 - person2: - age: 8 - ga_caps_provider_type: FAMILY - ga_caps_care_type: FULL_TIME - spm_units: - spm_unit: - members: [person1, person2] - households: - household: - members: [person1, person2] - state_code: GA - county_str: APPLING_COUNTY_GA - output: - # Zone 3, Family, School Age, Full-time = $94/week (lowest FT rate) - ga_caps_maximum_weekly_benefit: [0, 94] - -- name: Case 7, part-time with 1 day per week minimum. - period: 2026-01 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 30 - person2: - age: 4 - ga_caps_provider_type: CENTER - ga_caps_care_type: PART_TIME - childcare_days_per_week: 1 - spm_units: - spm_unit: - members: [person1, person2] - households: - household: - members: [person1, person2] - state_code: GA - county_str: FULTON_COUNTY_GA - output: - # Zone 1, Center, Preschool, Part-time = $65/day - # Weekly = 65 * 1 = $65 - ga_caps_maximum_weekly_benefit: [0, 65] diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/copay/ga_caps_family_fee.py b/policyengine_us/variables/gov/states/ga/decal/caps/copay/ga_caps_family_fee.py index 2651b099c5b..8bd0eb2cfc7 100644 --- a/policyengine_us/variables/gov/states/ga/decal/caps/copay/ga_caps_family_fee.py +++ b/policyengine_us/variables/gov/states/ga/decal/caps/copay/ga_caps_family_fee.py @@ -9,8 +9,8 @@ class ga_caps_family_fee(Variable): definition_period = MONTH defined_for = StateCode.GA reference = ( - "https://caps.decal.ga.gov/assets/downloads/CAPS/Appendix_D-CAPS_Family_Fee_702.pdf#page=2", - "https://www.acf.hhs.gov/sites/default/files/documents/occ/georgia_2025_2027_ccdf_state_plan.pdf#page=117", + "https://caps.decal.ga.gov/assets/downloads/CAPS/AppendixD-Family%20Fee%20Assessment%20Chart.pdf", + "https://www.decal.ga.gov/documents/attachments/CCDFStatePlan25-27.pdf#page=49", ) def formula(spm_unit, period, parameters): diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_activity_eligible.py b/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_activity_eligible.py index 4ce43b4cfdd..d34e7ca6309 100644 --- a/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_activity_eligible.py +++ b/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_activity_eligible.py @@ -7,7 +7,7 @@ class ga_caps_activity_eligible(Variable): label = "Eligible for Georgia CAPS based on activity requirements" definition_period = MONTH defined_for = StateCode.GA - reference = "https://caps.decal.ga.gov/assets/downloads/CAPS/02-CAPS_Policy-Chapter_6.pdf#page=4" + reference = "https://caps.decal.ga.gov/assets/downloads/CAPS/0-CAPS_Policy-Manual.pdf#page=33" def formula(spm_unit, period, parameters): p = parameters(period).gov.states.ga.decal.caps.activity_requirements diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_eligible.py b/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_eligible.py index 9e94bd09742..113bc8e6911 100644 --- a/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_eligible.py +++ b/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_eligible.py @@ -7,7 +7,7 @@ class ga_caps_eligible(Variable): label = "Eligible for Georgia CAPS" definition_period = MONTH defined_for = StateCode.GA - reference = "https://caps.decal.ga.gov/assets/downloads/CAPS/02-CAPS_Policy-Chapter_6.pdf#page=3" + reference = "https://caps.decal.ga.gov/assets/downloads/CAPS/0-CAPS_Policy-Manual.pdf#page=29" def formula(spm_unit, period, parameters): has_eligible_child = add(spm_unit, period, ["ga_caps_eligible_child"]) > 0 diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_eligible_child.py b/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_eligible_child.py index 9fd1749beb3..8fc436499bf 100644 --- a/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_eligible_child.py +++ b/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_eligible_child.py @@ -8,8 +8,8 @@ class ga_caps_eligible_child(Variable): definition_period = MONTH defined_for = StateCode.GA reference = ( - "https://caps.decal.ga.gov/assets/downloads/CAPS/02-CAPS_Policy-Chapter_6.pdf#page=3", - "https://www.acf.hhs.gov/sites/default/files/documents/occ/georgia_2025_2027_ccdf_state_plan.pdf#page=49", + "https://caps.decal.ga.gov/assets/downloads/CAPS/0-CAPS_Policy-Manual.pdf#page=29", + "https://www.decal.ga.gov/documents/attachments/CCDFStatePlan25-27.pdf#page=16", ) def formula(person, period, parameters): diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_income_eligible.py b/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_income_eligible.py index 87f5608b601..652a64c41f0 100644 --- a/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_income_eligible.py +++ b/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_income_eligible.py @@ -8,8 +8,8 @@ class ga_caps_income_eligible(Variable): definition_period = MONTH defined_for = StateCode.GA reference = ( - "https://caps.decal.ga.gov/assets/downloads/CAPS/04-CAPS_Policy-Chapter_8.pdf#page=2", - "https://caps.decal.ga.gov/assets/downloads/CAPS/Appendix_A-CAPS_702_Income_Limits.pdf#page=2", + "https://caps.decal.ga.gov/assets/downloads/CAPS/0-CAPS_Policy-Manual.pdf#page=48", + "https://caps.decal.ga.gov/assets/downloads/CAPS/AppendixA-CAPS%20Maximum%20Income%20Limits%20by%20Family%20Size.pdf", ) def formula(spm_unit, period, parameters): diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/ga_caps.py b/policyengine_us/variables/gov/states/ga/decal/caps/ga_caps.py index a6ca88cc09e..63ef89402f8 100644 --- a/policyengine_us/variables/gov/states/ga/decal/caps/ga_caps.py +++ b/policyengine_us/variables/gov/states/ga/decal/caps/ga_caps.py @@ -12,28 +12,24 @@ class ga_caps(Variable): definition_period = MONTH defined_for = "ga_caps_eligible" reference = ( - "https://caps.decal.ga.gov/assets/downloads/CAPS/Appendix_C-CAPS_Reimbursement_Rates.pdf#page=2", - "https://www.acf.hhs.gov/sites/default/files/documents/occ/georgia_2025_2027_ccdf_state_plan.pdf#page=110", + "https://caps.decal.ga.gov/assets/downloads/CAPS/0-CAPS_Policy-Manual.pdf#page=55", + "https://www.decal.ga.gov/documents/attachments/CCDFStatePlan25-27.pdf#page=69", ) def formula(spm_unit, period, parameters): p = parameters(period).gov.states.ga.decal.caps - family_fee = spm_unit("ga_caps_family_fee", period) + person = spm_unit.members - # Sum per-child weekly max rates (base, without quality). - base_max_weekly = add(spm_unit, period, ["ga_caps_maximum_weekly_benefit"]) - base_max_monthly = base_max_weekly * (WEEKS_IN_YEAR / MONTHS_IN_YEAR) + max_weekly = person("ga_caps_maximum_weekly_benefit", period) + published_weekly = person("ga_caps_provider_published_rate", period) + per_child_weekly = min_(max_weekly, published_weekly) - # Base payment capped at actual expenses. - pre_subsidy = spm_unit("spm_unit_pre_subsidy_childcare_expenses", period) - base_payment = min_(pre_subsidy, base_max_monthly) + total_weekly_base = spm_unit.sum(per_child_weekly) + base_monthly = total_weekly_base * (WEEKS_IN_YEAR / MONTHS_IN_YEAR) - # Net base payment = base payment less family fee, floored at 0. - net_base = max_(base_payment - family_fee, 0) + family_fee = spm_unit("ga_caps_family_fee", period) + net_base = max_(base_monthly - family_fee, 0) - # Quality bonus: per-child weighted average bonus rate. - person = spm_unit.members - weekly_rate = person("ga_caps_maximum_weekly_benefit", period) quality_rating = person("ga_caps_quality_rating", period) star_count = select( [ @@ -45,13 +41,10 @@ def formula(spm_unit, period, parameters): default=0, ) bonus_rate = p.quality_rated.bonus_rate.calc(star_count) - weighted_bonus = spm_unit.sum(weekly_rate * bonus_rate) - effective_bonus_rate = np.divide( - weighted_bonus, - base_max_weekly, - out=np.zeros_like(weighted_bonus), - where=base_max_weekly > 0, + weighted_bonus = spm_unit.sum(per_child_weekly * bonus_rate) + effective_bonus_rate = where( + total_weekly_base > 0, + weighted_bonus / total_weekly_base, + 0, ) - - # Subsidy = net base payment * (1 + effective quality bonus rate). return net_base * (1 + effective_bonus_rate) diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/income/ga_caps_countable_income.py b/policyengine_us/variables/gov/states/ga/decal/caps/income/ga_caps_countable_income.py index bdee8fd03e5..d737a5237f7 100644 --- a/policyengine_us/variables/gov/states/ga/decal/caps/income/ga_caps_countable_income.py +++ b/policyengine_us/variables/gov/states/ga/decal/caps/income/ga_caps_countable_income.py @@ -8,7 +8,7 @@ class ga_caps_countable_income(Variable): definition_period = MONTH unit = USD defined_for = StateCode.GA - reference = "https://caps.decal.ga.gov/assets/downloads/CAPS/04-CAPS_Policy-Chapter_8.pdf#page=3" + reference = "https://caps.decal.ga.gov/assets/downloads/CAPS/0-CAPS_Policy-Manual.pdf#page=48" def formula(spm_unit, period, parameters): p = parameters(period).gov.states.ga.decal.caps.income.countable_income diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_age_group.py b/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_age_group.py index 78894bbf8c1..f141b5ee267 100644 --- a/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_age_group.py +++ b/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_age_group.py @@ -16,7 +16,7 @@ class ga_caps_age_group(Variable): definition_period = MONTH defined_for = "ga_caps_eligible_child" label = "Georgia CAPS child age group" - reference = "https://caps.decal.ga.gov/assets/downloads/CAPS/Appendix_C-CAPS_Reimbursement_Rates.pdf#page=2" + reference = "https://caps.decal.ga.gov/assets/downloads/CAPS/AppendixC-CAPS%20Reimbursement%20Rates.pdf#page=1" def formula(person, period, parameters): age = person("age", period.this_year) diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_care_type.py b/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_care_type.py index 23538ddf5ed..1a343d704b7 100644 --- a/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_care_type.py +++ b/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_care_type.py @@ -15,4 +15,4 @@ class ga_caps_care_type(Variable): definition_period = MONTH label = "Georgia CAPS care type" defined_for = StateCode.GA - reference = "https://caps.decal.ga.gov/assets/downloads/CAPS/Appendix_C-CAPS_Reimbursement_Rates.pdf#page=2" + reference = "https://caps.decal.ga.gov/assets/downloads/CAPS/AppendixC-CAPS%20Reimbursement%20Rates.pdf#page=1" diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_maximum_weekly_benefit.py b/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_maximum_weekly_benefit.py index 0dbea86879f..8455e3182a1 100644 --- a/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_maximum_weekly_benefit.py +++ b/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_maximum_weekly_benefit.py @@ -11,7 +11,7 @@ class ga_caps_maximum_weekly_benefit(Variable): label = "Georgia CAPS maximum weekly benefit per child" definition_period = MONTH defined_for = "ga_caps_eligible_child" - reference = "https://caps.decal.ga.gov/assets/downloads/CAPS/Appendix_C-CAPS_Reimbursement_Rates.pdf#page=2" + reference = "https://caps.decal.ga.gov/assets/downloads/CAPS/AppendixC-CAPS%20Reimbursement%20Rates.pdf#page=1" def formula(person, period, parameters): p = parameters(period).gov.states.ga.decal.caps.rates diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_provider_published_rate.py b/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_provider_published_rate.py new file mode 100644 index 00000000000..3434b16b592 --- /dev/null +++ b/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_provider_published_rate.py @@ -0,0 +1,24 @@ +from policyengine_us.model_api import * + + +class ga_caps_provider_published_rate(Variable): + value_type = float + entity = Person + definition_period = MONTH + unit = USD + label = "Georgia CAPS provider published weekly rate per child" + defined_for = "ga_caps_eligible_child" + reference = "https://caps.decal.ga.gov/assets/downloads/CAPS/0-CAPS_Policy-Manual.pdf#page=55" + + def formula(person, period, parameters): + spm_unit = person.spm_unit + annual_expenses = spm_unit( + "spm_unit_pre_subsidy_childcare_expenses", period.this_year + ) + num_eligible = add(spm_unit, period, ["ga_caps_eligible_child"]) + weekly_per_child = where( + num_eligible > 0, + annual_expenses / num_eligible / WEEKS_IN_YEAR, + 0, + ) + return spm_unit.project(weekly_per_child) diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_provider_type.py b/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_provider_type.py index 56c025ab5d4..24c0c549d22 100644 --- a/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_provider_type.py +++ b/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_provider_type.py @@ -15,4 +15,4 @@ class ga_caps_provider_type(Variable): definition_period = MONTH label = "Georgia CAPS child care provider type" defined_for = StateCode.GA - reference = "https://caps.decal.ga.gov/assets/downloads/CAPS/Appendix_C-CAPS_Reimbursement_Rates.pdf#page=2" + reference = "https://caps.decal.ga.gov/assets/downloads/CAPS/AppendixC-CAPS%20Reimbursement%20Rates.pdf#page=1" diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_quality_rating.py b/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_quality_rating.py index b069a99c660..54996cc9dc8 100644 --- a/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_quality_rating.py +++ b/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_quality_rating.py @@ -16,4 +16,6 @@ class ga_caps_quality_rating(Variable): definition_period = MONTH label = "Georgia CAPS provider Quality Rated designation" defined_for = StateCode.GA - reference = "https://www.acf.hhs.gov/sites/default/files/documents/occ/georgia_2025_2027_ccdf_state_plan.pdf#page=110" + reference = ( + "https://www.decal.ga.gov/documents/attachments/CCDFStatePlan25-27.pdf#page=69" + ) diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_zone.py b/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_zone.py index d3b8882e1aa..61cb98c5f76 100644 --- a/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_zone.py +++ b/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_zone.py @@ -15,7 +15,7 @@ class ga_caps_zone(Variable): definition_period = MONTH defined_for = StateCode.GA label = "Georgia CAPS geographic zone" - reference = "https://caps.decal.ga.gov/assets/downloads/CAPS/Appendix_C-CAPS_Reimbursement_Rates.pdf#page=2" + reference = "https://caps.decal.ga.gov/assets/downloads/CAPS/AppendixC-CAPS%20Reimbursement%20Rates.pdf#page=2" def formula(household, period, parameters): county = household("county_str", period) diff --git a/uv.lock b/uv.lock index 76042ff3b95..040a348fa5b 100644 --- a/uv.lock +++ b/uv.lock @@ -2974,7 +2974,7 @@ wheels = [ [[package]] name = "policyengine-us" -version = "1.691.7" +version = "1.691.10" source = { editable = "." } dependencies = [ { name = "microdf-python" }, From 797492b36ca482130b44ec6260eb6a432af8f2e8 Mon Sep 17 00:00:00 2001 From: Ziming Date: Thu, 14 May 2026 18:25:18 -0400 Subject: [PATCH 10/11] Simplify ga_caps formula: SPMUnit-level cap, drop ga_caps_provider_published_rate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reverts the per-child lesser-of attempt from review round 2: without per-child provider published rate data, the "even share of pre_subsidy expenses" default was just a derived value from spm_unit_pre_subsidy_childcare_expenses with no new information. Matches the SPMUnit-level pattern used by RI CCAP, MA CCFA, and CO CCAP. Keeps the idiomatic where(denom > 0, ...) fix from round 2 (replaces the np.divide(out=..., where=...) workaround for the weighted-average bonus rate). Per-child lesser-of with §9.6.1's exact regulatory semantics is now unmodeled — PolicyEngine doesn't track per-child provider published rates. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../gov/states/ga/decal/caps/ga_caps.yaml | 19 ++++------ .../gov/states/ga/decal/caps/integration.yaml | 37 ++++++++----------- .../gov/states/ga/decal/caps/ga_caps.py | 14 +++---- .../ga_caps_provider_published_rate.py | 24 ------------ 4 files changed, 30 insertions(+), 64 deletions(-) delete mode 100644 policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_provider_published_rate.py diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/ga_caps.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/ga_caps.yaml index 23bcf5c9bcb..82276e1ec19 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/ga_caps.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/ga_caps.yaml @@ -1,8 +1,5 @@ # GA CAPS benefit -# Per-child weekly subsidy = min(state max rate, provider published rate). -# When ga_caps_provider_published_rate is not provided, it defaults to an -# even share of spm_unit_pre_subsidy_childcare_expenses across eligible children. -# Subsidy = max(sum(per_child_weekly) * 52/12 - family_fee, 0) * (1 + weighted_quality_bonus_rate) +# Subsidy = max(min(expenses, sum_of_max_rates) - fee, 0) * (1 + weighted_quality_bonus_rate) # # 2026 FPG (Contiguous US): # first_person = 15,960, additional = 5,680 @@ -308,15 +305,13 @@ # weekly fee = floor(15,000 * 0.05 / 52) = floor(14.42) = $14 # monthly fee = 14 * 52 / 12 = $60.67 ga_caps_family_fee: 60.67 - # pre_subsidy_weekly_per_child = 12,000 / 52 / 2 = $115.38 - # person2 (infant family FT, max $145): min($145, $115.38) = $115.38 - # person3 (school B/A, max $68): min($68, $115.38) = $68 - # total_weekly_base = $115.38 + $68 = $183.38 - # base_monthly = $183.38 * 52/12 = $794.65 - # net_base = max($794.65 - $60.67, 0) = $733.98 + # sum_max_weekly = 145 + 68 = $213 + # sum_max_monthly = $213 * 52/12 = $923.00 + # expenses_monthly = 12,000 / 12 = $1,000 + # base = min($1,000, $923) = $923 + # net_base = max($923 - $60.67, 0) = $862.33 # no quality bonus (NONE rating) - # subsidy = $733.98 - ga_caps: 733.98 + ga_caps: 862.33 - name: Case 8, zero income family gets maximum subsidy up to expenses. period: 2026-01 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/integration.yaml index 0d2bac83f3a..311bf8128f5 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/integration.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/integration.yaml @@ -282,16 +282,14 @@ ga_caps_family_fee: 82.33 # === Benefit === - # pre_subsidy_weekly_per_child = 10,000 / 52 / 2 = $96.15 - # person2 (infant FT, max $130): min($130, $96.15) = $96.15 - # person3 (school B/A, max $53): min($53, $96.15) = $53 - # total_weekly_base = $96.15 + $53 = $149.15 - # base_monthly = $149.15 * 52/12 = $646.32 - # net_base = max($646.32 - $82.33, 0) = $563.99 - # weighted_bonus = $96.15 * 0.05 + $53 * 0.05 = $7.46 - # weighted_bonus_rate = $7.46 / $149.15 = 0.05 - # subsidy = $563.99 * 1.05 = $592.19 - ga_caps: 592.19 + # sum_max_weekly = 130 + 53 = $183 + # sum_max_monthly = $183 * 52/12 = $793.00 + # expenses_monthly = 10,000 / 12 = $833.33 + # base = min($833.33, $793) = $793.00 + # net_base = max($793 - $82.33, 0) = $710.67 + # weighted_bonus_rate = (130*0.05 + 53*0.05) / 183 = 0.05 + # subsidy = $710.67 * 1.05 = $746.20 + ga_caps: 746.20 - name: Case 6, disabled teenager with family care in Zone 2. period: 2026-01 @@ -466,17 +464,14 @@ ga_caps_family_fee: 424.67 # === Benefit === - # pre_subsidy_weekly_per_child = 20,000 / 52 / 3 = $128.21 - # person3: min($84, $128.21) = $84 - # person4: min($180, $128.21) = $128.21 - # person5: min($260, $128.21) = $128.21 - # total_weekly_base = $84 + $128.21 + $128.21 = $340.42 - # base_monthly = $340.42 * 52/12 = $1,475.16 - # net_base = max($1,475.16 - $424.67, 0) = $1,050.49 - # weighted_bonus = $84*0 + $128.21*0.05 + $128.21*0.05 = $12.82 - # weighted_bonus_rate = $12.82 / $340.42 = 0.0377 - # subsidy = $1,050.49 * 1.0377 = $1,090.10 - ga_caps: 1_090.10 + # sum_max_weekly = 84 + 180 + 260 = $524 + # sum_max_monthly = $524 * 52/12 = $2,270.67 + # expenses_monthly = 20,000 / 12 = $1,666.67 + # base = min($1,666.67, $2,270.67) = $1,666.67 + # net_base = max($1,666.67 - $424.67, 0) = $1,242.00 + # weighted_bonus_rate = (84*0 + 180*0.05 + 260*0.05) / 524 = 0.04198 + # subsidy = $1,242.00 * 1.04198 = $1,294.14 + ga_caps: 1_294.14 - name: Case 9, enrolled family between 50 and 85 percent SMI. period: 2026-01 diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/ga_caps.py b/policyengine_us/variables/gov/states/ga/decal/caps/ga_caps.py index 63ef89402f8..5a08d46f624 100644 --- a/policyengine_us/variables/gov/states/ga/decal/caps/ga_caps.py +++ b/policyengine_us/variables/gov/states/ga/decal/caps/ga_caps.py @@ -21,11 +21,11 @@ def formula(spm_unit, period, parameters): person = spm_unit.members max_weekly = person("ga_caps_maximum_weekly_benefit", period) - published_weekly = person("ga_caps_provider_published_rate", period) - per_child_weekly = min_(max_weekly, published_weekly) + sum_max_weekly = spm_unit.sum(max_weekly) + sum_max_monthly = sum_max_weekly * (WEEKS_IN_YEAR / MONTHS_IN_YEAR) - total_weekly_base = spm_unit.sum(per_child_weekly) - base_monthly = total_weekly_base * (WEEKS_IN_YEAR / MONTHS_IN_YEAR) + expenses_monthly = spm_unit("spm_unit_pre_subsidy_childcare_expenses", period) + base_monthly = min_(expenses_monthly, sum_max_monthly) family_fee = spm_unit("ga_caps_family_fee", period) net_base = max_(base_monthly - family_fee, 0) @@ -41,10 +41,10 @@ def formula(spm_unit, period, parameters): default=0, ) bonus_rate = p.quality_rated.bonus_rate.calc(star_count) - weighted_bonus = spm_unit.sum(per_child_weekly * bonus_rate) + weighted_bonus = spm_unit.sum(max_weekly * bonus_rate) effective_bonus_rate = where( - total_weekly_base > 0, - weighted_bonus / total_weekly_base, + sum_max_weekly > 0, + weighted_bonus / sum_max_weekly, 0, ) return net_base * (1 + effective_bonus_rate) diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_provider_published_rate.py b/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_provider_published_rate.py deleted file mode 100644 index 3434b16b592..00000000000 --- a/policyengine_us/variables/gov/states/ga/decal/caps/payment/ga_caps_provider_published_rate.py +++ /dev/null @@ -1,24 +0,0 @@ -from policyengine_us.model_api import * - - -class ga_caps_provider_published_rate(Variable): - value_type = float - entity = Person - definition_period = MONTH - unit = USD - label = "Georgia CAPS provider published weekly rate per child" - defined_for = "ga_caps_eligible_child" - reference = "https://caps.decal.ga.gov/assets/downloads/CAPS/0-CAPS_Policy-Manual.pdf#page=55" - - def formula(person, period, parameters): - spm_unit = person.spm_unit - annual_expenses = spm_unit( - "spm_unit_pre_subsidy_childcare_expenses", period.this_year - ) - num_eligible = add(spm_unit, period, ["ga_caps_eligible_child"]) - weekly_per_child = where( - num_eligible > 0, - annual_expenses / num_eligible / WEEKS_IN_YEAR, - 0, - ) - return spm_unit.project(weekly_per_child) From d852b150a39d66dcb2038a7dce387eaebfcee19a Mon Sep 17 00:00:00 2001 From: Ziming Date: Thu, 14 May 2026 18:43:31 -0400 Subject: [PATCH 11/11] Address review feedback: disabled-parent activity exception and exact fee cutoffs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Exempt disabled heads/spouses from the GA 24-hour activity gate per Policy Manual §6.8.1.8 (disabled parent counts as care provider). Previously, two-parent units with one disabled spouse failed the GA gate and relied on the federal CCDF fallback. Also tightens `sum(...) == 0` -> `~any(...)`. - Remove 0.0001 threshold shifts in family_fee/rate.yaml. The shifted thresholds (0.1001 / 0.5001 / 1.0001) created multi-dollar gaps where income just above 10% / 50% / 100% FPL incorrectly stayed in the lower bracket (e.g., a family of 2 with $2,165 income, which is 10.005% FPL, was charged $0 instead of 3%). Now uses exact 0.1 / 0.5 / 1.0 thresholds, matching how the rest of PE encodes FPL-percentage brackets. - Add tests: disabled-parent activity Cases 14-15; refactor family_fee Cases 7-13 to test "$1 above/below" boundary behavior. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../states/ga/decal/caps/family_fee/rate.yaml | 6 +- .../decal/caps/copay/ga_caps_family_fee.yaml | 69 ++++++++++--------- .../ga_caps_activity_eligible.yaml | 53 ++++++++++++++ .../eligibility/ga_caps_activity_eligible.py | 8 ++- 4 files changed, 97 insertions(+), 39 deletions(-) diff --git a/policyengine_us/parameters/gov/states/ga/decal/caps/family_fee/rate.yaml b/policyengine_us/parameters/gov/states/ga/decal/caps/family_fee/rate.yaml index 95ce6e56375..785c56a9d42 100644 --- a/policyengine_us/parameters/gov/states/ga/decal/caps/family_fee/rate.yaml +++ b/policyengine_us/parameters/gov/states/ga/decal/caps/family_fee/rate.yaml @@ -17,14 +17,14 @@ brackets: amount: 2026-03-02: 0 - threshold: - 2026-03-02: 0.1001 + 2026-03-02: 0.1 amount: 2026-03-02: 0.03 - threshold: - 2026-03-02: 0.5001 + 2026-03-02: 0.5 amount: 2026-03-02: 0.05 - threshold: - 2026-03-02: 1.0001 + 2026-03-02: 1.0 amount: 2026-03-02: 0.07 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/copay/ga_caps_family_fee.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/copay/ga_caps_family_fee.yaml index 104a1d43cfe..13e0d14c608 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/copay/ga_caps_family_fee.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/copay/ga_caps_family_fee.yaml @@ -155,14 +155,14 @@ # Parent age 17 <= 17 -> minor parent fee waiver -> $0 ga_caps_family_fee: 0 -- name: Case 7, income exactly at 10 percent FPL boundary. +- name: Case 7, income just below 10 percent FPL boundary. period: 2026-01 absolute_error_margin: 0.01 input: people: person1: age: 30 - employment_income: 2_732 + employment_income: 2_731 person2: age: 5 person3: @@ -175,11 +175,10 @@ members: [person1, person2, person3] state_code: GA output: - # FPL ratio = 2,732 / 27,320 = 0.10 -> 0% rate (at or below 10%) - # fee = 0 + # FPL ratio = 2,731 / 27,320 = 0.09996 -> < 0.1 -> 0% rate ga_caps_family_fee: 0 -- name: Case 8, FPL ratio just above 10 percent boundary still in zero tier. +- name: Case 8, income one dollar above 10 percent FPL enters 3 percent tier. period: 2026-01 absolute_error_margin: 0.01 input: @@ -187,7 +186,7 @@ person1: age: 30 # 10% of FPG for family of 2 = 21,640 * 0.10 = $2,164 - # Just above: $2,165 + # One dollar above: $2,165 employment_income: 2_165 person2: age: 5 @@ -199,18 +198,19 @@ members: [person1, person2] state_code: GA output: - # FPL ratio = 2,165 / 21,640 = 0.10005 -> < 0.1001 (still in 0% tier) - ga_caps_family_fee: 0 + # FPL ratio = 2,165 / 21,640 = 0.10005 -> > 0.1 -> 3% rate + # weekly fee = floor(2,165 * 0.03 / 52) = floor(1.25) = $1 + # monthly fee = 1 * 52 / 12 = $4.33 + ga_caps_family_fee: 4.33 -- name: Case 9, FPL ratio just crossing into 3 percent tier. +- name: Case 9, mid-range income in 3 percent tier. period: 2026-01 absolute_error_margin: 0.01 input: people: person1: age: 30 - # 0.1001 * 21,640 = $2,166.16. So income $2,167 crosses. - employment_income: 2_167 + employment_income: 5_000 person2: age: 5 spm_units: @@ -221,12 +221,12 @@ members: [person1, person2] state_code: GA output: - # FPL ratio = 2,167 / 21,640 = 0.10014 -> >= 0.1001 -> 3% rate - # weekly fee = floor(2,167 * 0.03 / 52) = floor(1.25) = $1 - # monthly fee = 1 * 52 / 12 = $4.33 - ga_caps_family_fee: 4.33 + # FPL ratio = 5,000 / 21,640 = 0.231 -> > 0.1, < 0.5 -> 3% rate + # weekly fee = floor(5,000 * 0.03 / 52) = floor(2.88) = $2 + # monthly fee = 2 * 52 / 12 = $8.67 + ga_caps_family_fee: 8.67 -- name: Case 10, FPL ratio exactly at 50 percent boundary. +- name: Case 10, income one dollar below 50 percent FPL stays in 3 percent tier. period: 2026-01 absolute_error_margin: 0.01 input: @@ -234,7 +234,8 @@ person1: age: 30 # 50% of FPG for family of 2 = 21,640 * 0.50 = $10,820 - employment_income: 10_820 + # One dollar below: $10,819 + employment_income: 10_819 person2: age: 5 spm_units: @@ -245,20 +246,20 @@ members: [person1, person2] state_code: GA output: - # FPL ratio = 10,820 / 21,640 = 0.5000 -> < 0.5001 -> 3% rate - # weekly fee = floor(10,820 * 0.03 / 52) = floor(6.24) = $6 + # FPL ratio = 10,819 / 21,640 = 0.49995 -> < 0.5 -> 3% rate + # weekly fee = floor(10,819 * 0.03 / 52) = floor(6.24) = $6 # monthly fee = 6 * 52 / 12 = $26.00 ga_caps_family_fee: 26.00 -- name: Case 11, FPL ratio just crossing into 5 percent tier. +- name: Case 11, income one dollar above 50 percent FPL enters 5 percent tier. period: 2026-01 absolute_error_margin: 0.01 input: people: person1: age: 30 - # 0.5001 * 21,640 = $10,822.16. So income $10,823 crosses. - employment_income: 10_823 + # One dollar above 50% FPG (family of 2): $10,821 + employment_income: 10_821 person2: age: 5 spm_units: @@ -269,20 +270,20 @@ members: [person1, person2] state_code: GA output: - # FPL ratio = 10,823 / 21,640 = 0.50014 -> >= 0.5001 -> 5% rate - # weekly fee = floor(10,823 * 0.05 / 52) = floor(10.41) = $10 + # FPL ratio = 10,821 / 21,640 = 0.50005 -> > 0.5 -> 5% rate + # weekly fee = floor(10,821 * 0.05 / 52) = floor(10.40) = $10 # monthly fee = 10 * 52 / 12 = $43.33 ga_caps_family_fee: 43.33 -- name: Case 12, FPL ratio exactly at 100 percent boundary. +- name: Case 12, income one dollar below 100 percent FPL stays in 5 percent tier. period: 2026-01 absolute_error_margin: 0.01 input: people: person1: age: 30 - # 100% of FPG for family of 2 = $21,640 - employment_income: 21_640 + # 100% of FPG for family of 2 = $21,640; one dollar below: $21,639 + employment_income: 21_639 person2: age: 5 spm_units: @@ -293,20 +294,20 @@ members: [person1, person2] state_code: GA output: - # FPL ratio = 21,640 / 21,640 = 1.0000 -> < 1.0001 -> 5% rate - # weekly fee = floor(21,640 * 0.05 / 52) = floor(20.81) = $20 + # FPL ratio = 21,639 / 21,640 = 0.99995 -> < 1.0 -> 5% rate + # weekly fee = floor(21,639 * 0.05 / 52) = floor(20.80) = $20 # monthly fee = 20 * 52 / 12 = $86.67 ga_caps_family_fee: 86.67 -- name: Case 13, FPL ratio just crossing into 7 percent tier. +- name: Case 13, income one dollar above 100 percent FPL enters 7 percent tier. period: 2026-01 absolute_error_margin: 0.01 input: people: person1: age: 30 - # 1.0001 * 21,640 = $21,642.16. So income $21,643 crosses. - employment_income: 21_643 + # One dollar above 100% FPG: $21,641 + employment_income: 21_641 person2: age: 5 spm_units: @@ -317,8 +318,8 @@ members: [person1, person2] state_code: GA output: - # FPL ratio = 21,643 / 21,640 = 1.00014 -> >= 1.0001 -> 7% rate - # weekly fee = floor(21,643 * 0.07 / 52) = floor(29.12) = $29 + # FPL ratio = 21,641 / 21,640 = 1.00005 -> > 1.0 -> 7% rate + # weekly fee = floor(21,641 * 0.07 / 52) = floor(29.13) = $29 # monthly fee = 29 * 52 / 12 = $125.67 ga_caps_family_fee: 125.67 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_activity_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_activity_eligible.yaml index b6521a05e15..5775c67525b 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_activity_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ga/decal/caps/eligibility/ga_caps_activity_eligible.yaml @@ -315,3 +315,56 @@ output: # GA gate fails (10 < 24, not student), but federal CCDF fallback approves ga_caps_activity_eligible: true + +- name: Case 14, two-parent family with one disabled spouse passes GA gate. + period: 2026-01 + input: + people: + person1: + age: 35 + weekly_hours_worked: 30 + person2: + age: 33 + weekly_hours_worked: 0 + is_disabled: true + is_full_time_student: false + person3: + age: 4 + tax_units: + tax_unit: + members: [person1, person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + meets_ccdf_activity_test: false + households: + household: + members: [person1, person2, person3] + state_code: GA + output: + # Per Policy Manual §6.8.1.8, disabled spouse is exempt from activity gate; + # non-disabled parent works 30 >= 24 -> family eligible without federal fallback. + ga_caps_activity_eligible: true + +- name: Case 15, single disabled parent passes GA gate. + period: 2026-01 + input: + people: + person1: + age: 40 + weekly_hours_worked: 0 + is_disabled: true + is_full_time_student: false + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + meets_ccdf_activity_test: false + households: + household: + members: [person1, person2] + state_code: GA + output: + # Single disabled head exempt from activity gate per §6.8.1.8 + ga_caps_activity_eligible: true diff --git a/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_activity_eligible.py b/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_activity_eligible.py index d34e7ca6309..263747726d5 100644 --- a/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_activity_eligible.py +++ b/policyengine_us/variables/gov/states/ga/decal/caps/eligibility/ga_caps_activity_eligible.py @@ -16,7 +16,11 @@ def formula(spm_unit, period, parameters): hours_worked = person("weekly_hours_worked", period.this_year) meets_work_requirement = hours_worked >= p.weekly_hours is_student = person("is_full_time_student", period.this_year) - individually_eligible = meets_work_requirement | is_student - all_heads_meet = spm_unit.sum(is_head_or_spouse & ~individually_eligible) == 0 + is_disabled = person("is_disabled", period.this_year) + # Per Policy Manual §6.8.1.8, a disabled parent who cannot provide care + # is exempt from the activity requirement; authorization is based on + # the non-disabled parent's activity. + individually_eligible = meets_work_requirement | is_student | is_disabled + all_heads_meet = ~spm_unit.any(is_head_or_spouse & ~individually_eligible) meets_ccdf = spm_unit("meets_ccdf_activity_test", period.this_year) return all_heads_meet | meets_ccdf