From a62ef54a936992bbdd180c74b2550118aac837c3 Mon Sep 17 00:00:00 2001 From: Ziming Date: Tue, 23 Dec 2025 19:44:19 -0500 Subject: [PATCH 1/8] Initial commit for Nebraska TANF implementation Starting implementation of Nebraska TANF (Aid to Dependent Children). Documentation and parallel development will follow. From c62a94de20bbbd23fba0a0c3f962fb6032956fbe Mon Sep 17 00:00:00 2001 From: Ziming Date: Tue, 23 Dec 2025 20:49:14 -0500 Subject: [PATCH 2/8] Add Nebraska Aid to Dependent Children (ADC) program implementation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implements Nebraska's ADC program with: - Income eligibility based on need standard - Resource eligibility with $6,000 limit - Earned income disregard (50%) - Payment standard calculation - Benefit calculation with minimum payment threshold Includes parameters, variables, and comprehensive YAML tests. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- changelog_entry.yaml | 6 + .../adc/income/earned_income_disregard.yaml | 12 + .../gov/states/ne/dhhs/adc/min_payment.yaml | 12 + .../gov/states/ne/dhhs/adc/need_standard.yaml | 42 + .../ne/dhhs/adc/payment_standard_rate.yaml | 12 + .../states/ne/dhhs/adc/resource_limit.yaml | 42 + .../gov/states/ne/dhhs/adc/edge_cases.yaml | 721 ++++++++++++++++++ .../gov/states/ne/dhhs/adc/integration.yaml | 268 +++++++ .../gov/states/ne/dhhs/adc/ne_adc.yaml | 159 ++++ .../adc/ne_adc_countable_earned_income.yaml | 85 +++ .../states/ne/dhhs/adc/ne_adc_eligible.yaml | 130 ++++ .../ne/dhhs/adc/ne_adc_need_standard.yaml | 114 +++ .../ne/dhhs/adc/ne_adc_payment_standard.yaml | 88 +++ .../gov/states/ne/dhhs/adc/ne_adc.py | 28 + .../adc/ne_adc_countable_earned_income.py | 20 + .../gov/states/ne/dhhs/adc/ne_adc_eligible.py | 33 + .../ne/dhhs/adc/ne_adc_income_eligible.py | 21 + .../ne/dhhs/adc/ne_adc_maximum_benefit.py | 23 + .../ne/dhhs/adc/ne_adc_need_standard.py | 21 + .../ne/dhhs/adc/ne_adc_payment_standard.py | 20 + .../ne/dhhs/adc/ne_adc_resources_eligible.py | 23 + 21 files changed, 1880 insertions(+) create mode 100644 policyengine_us/parameters/gov/states/ne/dhhs/adc/income/earned_income_disregard.yaml create mode 100644 policyengine_us/parameters/gov/states/ne/dhhs/adc/min_payment.yaml create mode 100644 policyengine_us/parameters/gov/states/ne/dhhs/adc/need_standard.yaml create mode 100644 policyengine_us/parameters/gov/states/ne/dhhs/adc/payment_standard_rate.yaml create mode 100644 policyengine_us/parameters/gov/states/ne/dhhs/adc/resource_limit.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/edge_cases.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/integration.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_countable_earned_income.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_eligible.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_need_standard.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_payment_standard.yaml create mode 100644 policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc.py create mode 100644 policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_countable_earned_income.py create mode 100644 policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_eligible.py create mode 100644 policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_income_eligible.py create mode 100644 policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_maximum_benefit.py create mode 100644 policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_need_standard.py create mode 100644 policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_payment_standard.py create mode 100644 policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_resources_eligible.py diff --git a/changelog_entry.yaml b/changelog_entry.yaml index e69de29bb2d..e092f5a7315 100644 --- a/changelog_entry.yaml +++ b/changelog_entry.yaml @@ -0,0 +1,6 @@ +- bump: minor + changes: + added: + - Nebraska Aid to Dependent Children (ADC) program + changed: [] + fixed: [] diff --git a/policyengine_us/parameters/gov/states/ne/dhhs/adc/income/earned_income_disregard.yaml b/policyengine_us/parameters/gov/states/ne/dhhs/adc/income/earned_income_disregard.yaml new file mode 100644 index 00000000000..59370cd806e --- /dev/null +++ b/policyengine_us/parameters/gov/states/ne/dhhs/adc/income/earned_income_disregard.yaml @@ -0,0 +1,12 @@ +description: Nebraska excludes this share of gross earned income from countable income under the Aid to Dependent Children program. + +values: + 2021-07-01: 0.5 + +metadata: + unit: /1 + period: month + label: Nebraska ADC earned income disregard rate + reference: + - title: Neb. Rev. Stat. 68-1726(3)(a)(ii) + href: https://nebraskalegislature.gov/laws/statutes.php?statute=68-1726 diff --git a/policyengine_us/parameters/gov/states/ne/dhhs/adc/min_payment.yaml b/policyengine_us/parameters/gov/states/ne/dhhs/adc/min_payment.yaml new file mode 100644 index 00000000000..b067b996805 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ne/dhhs/adc/min_payment.yaml @@ -0,0 +1,12 @@ +description: Nebraska provides at least this amount as the minimum monthly payment under the Aid to Dependent Children program. + +values: + 2021-07-01: 10 + +metadata: + unit: currency-USD + period: month + label: Nebraska ADC minimum payment + reference: + - title: Neb. Rev. Stat. 43-512 + href: https://nebraskalegislature.gov/laws/statutes.php?statute=43-512 diff --git a/policyengine_us/parameters/gov/states/ne/dhhs/adc/need_standard.yaml b/policyengine_us/parameters/gov/states/ne/dhhs/adc/need_standard.yaml new file mode 100644 index 00000000000..59df372f8df --- /dev/null +++ b/policyengine_us/parameters/gov/states/ne/dhhs/adc/need_standard.yaml @@ -0,0 +1,42 @@ +description: Nebraska sets this amount as the standard of need under the Aid to Dependent Children program. + +metadata: + unit: currency-USD + period: month + breakdown: + - range(1, 15) + label: Nebraska ADC standard of need + reference: + - title: Neb. Rev. Stat. 43-513 + href: https://nebraskalegislature.gov/laws/statutes.php?statute=43-513 + - title: Title 468 NAC Chapter 3 + href: https://dhhs.ne.gov/Pages/Title-468.aspx + +1: + 2021-07-01: 601 +2: + 2021-07-01: 741 +3: + 2021-07-01: 881 +4: + 2021-07-01: 1_021 +5: + 2021-07-01: 1_161 +6: + 2021-07-01: 1_301 +7: + 2021-07-01: 1_441 +8: + 2021-07-01: 1_581 +9: + 2021-07-01: 1_721 +10: + 2021-07-01: 1_861 +11: + 2021-07-01: 2_001 +12: + 2021-07-01: 2_141 +13: + 2021-07-01: 2_281 +14: + 2021-07-01: 2_421 diff --git a/policyengine_us/parameters/gov/states/ne/dhhs/adc/payment_standard_rate.yaml b/policyengine_us/parameters/gov/states/ne/dhhs/adc/payment_standard_rate.yaml new file mode 100644 index 00000000000..23af4e6ba58 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ne/dhhs/adc/payment_standard_rate.yaml @@ -0,0 +1,12 @@ +description: Nebraska provides this share of the standard of need as the payment standard under the Aid to Dependent Children program. + +values: + 2015-09-01: 0.55 + +metadata: + unit: /1 + period: month + label: Nebraska ADC payment standard rate + reference: + - title: Neb. Rev. Stat. 43-512 + href: https://nebraskalegislature.gov/laws/statutes.php?statute=43-512 diff --git a/policyengine_us/parameters/gov/states/ne/dhhs/adc/resource_limit.yaml b/policyengine_us/parameters/gov/states/ne/dhhs/adc/resource_limit.yaml new file mode 100644 index 00000000000..e9c650f6c77 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ne/dhhs/adc/resource_limit.yaml @@ -0,0 +1,42 @@ +description: Nebraska limits countable resources to this amount under the Aid to Dependent Children program. + +metadata: + unit: currency-USD + period: month + breakdown: + - range(1, 15) + label: Nebraska ADC resource limit + reference: + - title: Neb. Rev. Stat. 68-1726 + href: https://nebraskalegislature.gov/laws/statutes.php?statute=68-1726 + - title: Neb. Rev. Stat. 68-1713 + href: https://nebraskalegislature.gov/laws/statutes.php?statute=68-1713 + +1: + 2021-07-01: 4_000 +2: + 2021-07-01: 6_000 +3: + 2021-07-01: 6_000 +4: + 2021-07-01: 6_000 +5: + 2021-07-01: 6_000 +6: + 2021-07-01: 6_000 +7: + 2021-07-01: 6_000 +8: + 2021-07-01: 6_000 +9: + 2021-07-01: 6_000 +10: + 2021-07-01: 6_000 +11: + 2021-07-01: 6_000 +12: + 2021-07-01: 6_000 +13: + 2021-07-01: 6_000 +14: + 2021-07-01: 6_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/edge_cases.yaml b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/edge_cases.yaml new file mode 100644 index 00000000000..e152032f5ad --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/edge_cases.yaml @@ -0,0 +1,721 @@ +# Nebraska ADC Edge Case Tests +# Auto-generated edge case tests for comprehensive boundary coverage +# +# Key Formulas: +# Need Standard: Lookup by family size (1-14), capped at 14 +# Payment Standard: Need Standard * 0.55 +# Countable Earned: Gross Earned * 0.50 (50% disregard) +# Income Eligible: (countable_earned + unearned) < need_standard +# Resources Eligible: resources <= limit ($4,000 for 1, $6,000 for 2+) +# Maximum Benefit: min(gap, payment_standard) where gap = need_standard - countable_earned +# Final Benefit: max(max_benefit - unearned, 0) +# Minimum Rule: If final_benefit < $10, return $0 + +# ============================================================================= +# INCOME BOUNDARY TESTS +# ============================================================================= + +- name: Case 1, income exactly at need standard threshold is ineligible. + # Tests strict less-than comparison: countable_income < need_standard + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 17_784 # $1,482/month -> $741 countable + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 1_000 + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc_need_standard: 741 + ne_adc_countable_earned_income: 741 + # Gross: $17,784/12 = $1,482/month + # After 50% disregard: $1,482 * 0.50 = $741 + ne_adc_income_eligible: false + # Countable ($741) < Need Standard ($741) -> false (not strictly less) + ne_adc_eligible: false + ne_adc: 0 + +- name: Case 2, income one dollar below need standard threshold. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 17_760 # $1,480/month -> $740 countable + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 1_000 + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc_need_standard: 741 + ne_adc_countable_earned_income: 740 + # Gross: $17,760/12 = $1,480/month + # After 50% disregard: $1,480 * 0.50 = $740 + ne_adc_income_eligible: true + # Countable ($740) < Need Standard ($741) -> true + ne_adc_eligible: true + +- name: Case 3, income one dollar above need standard threshold. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 17_808 # $1,484/month -> $742 countable + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 1_000 + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc_need_standard: 741 + ne_adc_countable_earned_income: 742 + # Gross: $17,808/12 = $1,484/month + # After 50% disregard: $1,484 * 0.50 = $742 + ne_adc_income_eligible: false + # Countable ($742) < Need Standard ($741) -> false + ne_adc_eligible: false + ne_adc: 0 + +# ============================================================================= +# RESOURCE BOUNDARY TESTS - SINGLE PERSON ($4,000 limit) +# ============================================================================= + +- name: Case 4, resources exactly at $4,000 limit for single person. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 0 + spm_units: + spm_unit: + members: [person1] + spm_unit_assets: 4_000 + households: + household: + members: [person1] + state_code: NE + output: + spm_unit_size: 1 + ne_adc_resources_eligible: true + # Resources ($4,000) <= Limit ($4,000) -> true + +- name: Case 5, resources one dollar above $4,000 limit for single person. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 0 + spm_units: + spm_unit: + members: [person1] + spm_unit_assets: 4_001 + households: + household: + members: [person1] + state_code: NE + output: + spm_unit_size: 1 + ne_adc_resources_eligible: false + # Resources ($4,001) <= Limit ($4,000) -> false + ne_adc_eligible: false + +# ============================================================================= +# RESOURCE BOUNDARY TESTS - TWO+ PERSONS ($6,000 limit) +# ============================================================================= + +- name: Case 6, resources exactly at $6,000 limit for family of 2. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 0 + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 6_000 + households: + household: + members: [person1, person2] + state_code: NE + output: + spm_unit_size: 2 + ne_adc_resources_eligible: true + # Resources ($6,000) <= Limit ($6,000) -> true + ne_adc_eligible: true + +- name: Case 7, resources one dollar above $6,000 limit for family of 2. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 0 + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 6_001 + households: + household: + members: [person1, person2] + state_code: NE + output: + spm_unit_size: 2 + ne_adc_resources_eligible: false + # Resources ($6,001) <= Limit ($6,000) -> false + ne_adc_eligible: false + +# ============================================================================= +# ZERO VALUE TESTS +# ============================================================================= + +- name: Case 8, zero earned income. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 0 + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 1_000 + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc_countable_earned_income: 0 + ne_adc_income_eligible: true + ne_adc_eligible: true + +- name: Case 9, zero resources. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 0 + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 0 + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc_resources_eligible: true + # Resources ($0) <= Limit ($6,000) -> true + ne_adc_eligible: true + +# ============================================================================= +# FAMILY SIZE BOUNDARY TESTS +# ============================================================================= + +- name: Case 10, minimum family size of 1. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 0 + spm_units: + spm_unit: + members: [person1] + spm_unit_assets: 1_000 + households: + household: + members: [person1] + state_code: NE + output: + spm_unit_size: 1 + ne_adc_need_standard: 601 + # Need standard for size 1 = $601 + ne_adc_payment_standard: 331 + # Payment standard = $601 * 0.55 = $330.55, rounded up to $331 + +- name: Case 11, maximum family size of 14. + period: 2024-01 + input: + people: + person1: + age: 35 + person2: + age: 33 + person3: + age: 17 + person4: + age: 16 + person5: + age: 15 + person6: + age: 14 + person7: + age: 13 + person8: + age: 12 + person9: + age: 11 + person10: + age: 10 + person11: + age: 9 + person12: + age: 8 + person13: + age: 7 + person14: + age: 6 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10, person11, person12, person13, person14] + spm_unit_assets: 1_000 + households: + household: + members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10, person11, person12, person13, person14] + state_code: NE + output: + spm_unit_size: 14 + ne_adc_need_standard: 2_421 + # Need standard for size 14 = $2,421 + ne_adc_payment_standard: 1_332 + # Payment standard = $2,421 * 0.55 = $1,331.55, rounded up to $1,332 + +- name: Case 12, family size 15 exceeds parameter table caps at 14. + period: 2024-01 + input: + people: + person1: + age: 35 + person2: + age: 33 + person3: + age: 17 + person4: + age: 16 + person5: + age: 15 + person6: + age: 14 + person7: + age: 13 + person8: + age: 12 + person9: + age: 11 + person10: + age: 10 + person11: + age: 9 + person12: + age: 8 + person13: + age: 7 + person14: + age: 6 + person15: + age: 5 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10, person11, person12, person13, person14, person15] + spm_unit_assets: 1_000 + households: + household: + members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10, person11, person12, person13, person14, person15] + state_code: NE + output: + spm_unit_size: 15 + ne_adc_need_standard: 2_421 + # Size 15 capped to 14, need standard for size 14 = $2,421 + ne_adc_payment_standard: 1_332 + # Payment standard = $2,421 * 0.55 = $1,331.55, rounded up to $1,332 + +# ============================================================================= +# MINIMUM PAYMENT RULE TESTS +# ============================================================================= + +- name: Case 13, benefit exactly at $10 minimum threshold. + period: 2024-01 + absolute_error_margin: 0.1 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 0 + social_security: 3_846.60 # $320.55/month unearned + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 1_000 + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc_need_standard: 741 + ne_adc_payment_standard: 408 + # Payment standard = $741 * 0.55 = $407.55, rounded up to $408 + ne_adc_maximum_benefit: 408 + # Gap = $741 - $0 = $741 + # Benefit = min($741, $408) = $408 + ne_adc: 87.45 + # Final = $408 - $320.55 = $87.45 + # $87.45 >= $10 minimum -> $87.45 + +- name: Case 14, benefit below $10 minimum rounds up to $10. + # Per Neb. Rev. Stat. 43-512: no payments less than $10/month + # If benefit > 0 but < $10, return $10 + period: 2024-01 + absolute_error_margin: 0.1 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 0 + social_security: 4_800 # $400/month unearned + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 1_000 + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc_need_standard: 741 + ne_adc_payment_standard: 408 + # Payment standard = $741 * 0.55 = $407.55, rounded up to $408 + ne_adc_maximum_benefit: 408 + ne_adc: 10 + # Final = $408 - $400 = $8 + # $8 < $10 minimum, but > $0 -> rounds up to $10 + +- name: Case 15, calculated benefit of $5 is below minimum rounds up to $10. + period: 2024-01 + absolute_error_margin: 0.1 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 0 + social_security: 4_836 # $403/month unearned + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 1_000 + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc_payment_standard: 408 + # Payment standard = $741 * 0.55 = $407.55, rounded up to $408 + ne_adc_maximum_benefit: 408 + ne_adc: 10 + # Final = $408 - $403 = $5 + # $5 < $10 minimum, but > $0 -> rounds up to $10 + +- name: Case 16, zero benefit from ineligibility stays zero not minimum. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 24_000 # $2,000/month -> $1,000 countable + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 1_000 + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc_need_standard: 741 + ne_adc_countable_earned_income: 1_000 + ne_adc_income_eligible: false + # Countable ($1,000) >= Need Standard ($741) -> ineligible + ne_adc_eligible: false + ne_adc: 0 + # Zero from ineligibility, not from minimum payment rule + +# ============================================================================= +# GAP BUDGETING EDGE CASES +# ============================================================================= + +- name: Case 17, gap less than payment standard benefit equals gap. + period: 2024-01 + absolute_error_margin: 1 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 8_400 # $700/month -> $350 countable + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 1_000 + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc_need_standard: 741 + ne_adc_payment_standard: 408 + # Payment standard = $741 * 0.55 = $407.55 ~ $408 + ne_adc_countable_earned_income: 350 + # Gross = $700, after 50% disregard = $350 + ne_adc_maximum_benefit: 391 + # Gap = $741 - $350 = $391 + # Benefit = min($391, $408) = $391 (gap < payment standard) + ne_adc: 391 + # Final = $391 - $0 = $391 + +- name: Case 18, gap greater than payment standard benefit equals payment standard. + period: 2024-01 + absolute_error_margin: 1 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 0 + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 1_000 + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc_need_standard: 741 + ne_adc_payment_standard: 408 + ne_adc_countable_earned_income: 0 + ne_adc_maximum_benefit: 408 + # Gap = $741 - $0 = $741 + # Benefit = min($741, $408) = $408 (gap > payment standard) + ne_adc: 408 + # Final = $408 - $0 = $408 + +- name: Case 19, gap equals payment standard exactly. + # Need to find earned income where gap = payment_standard + # For size 2: need_standard = $741, payment_standard = $407.55 + # Gap = need_standard - countable_earned = payment_standard + # $741 - countable = $407.55 + # countable = $333.45 + # gross * 0.50 = $333.45 -> gross = $666.90/month = $8,002.80/year + period: 2024-01 + absolute_error_margin: 1 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 8_004 # $667/month -> $333.50 countable + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 1_000 + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc_need_standard: 741 + ne_adc_payment_standard: 408 + ne_adc_countable_earned_income: 333.5 + # Gross = $667, after 50% disregard = $333.50 + ne_adc_maximum_benefit: 407.5 + # Gap = $741 - $333.50 = $407.50 + # Benefit = min($407.50, $407.55) = $407.50 (gap ~ payment standard) + ne_adc: 407.5 + # Final = $407.50 - $0 = $407.50 + +# ============================================================================= +# EARNED INCOME DISREGARD EDGE CASES +# ============================================================================= + +- name: Case 20, very small earned income disregard applied. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 24 # $2/month gross + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 1_000 + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc_countable_earned_income: 1 + # Gross = $2, after 50% disregard = $1 + ne_adc_income_eligible: true + +- name: Case 21, large earned income 50 percent disregard. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 60_000 # $5,000/month gross + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 1_000 + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc_countable_earned_income: 2_500 + # Gross = $5,000, after 50% disregard = $2,500 + ne_adc_income_eligible: false + # Countable ($2,500) >= Need Standard ($741) -> ineligible + ne_adc_eligible: false + +# ============================================================================= +# UNEARNED INCOME EDGE CASES +# ============================================================================= + +- name: Case 22, unearned income exactly wipes out max benefit. + period: 2024-01 + absolute_error_margin: 1 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 0 + social_security: 4_896 # $408/month unearned = payment standard + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 1_000 + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc_payment_standard: 408 + ne_adc_maximum_benefit: 408 + # Gap = $741 - $0 = $741 + # Benefit = min($741, $408) = $408 + ne_adc: 0 + # Final = $408 - $408 = $0 + # Would be $0 anyway (no negative benefits) + +- name: Case 23, unearned income exceeds max benefit no negative. + period: 2024-01 + absolute_error_margin: 1 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 0 + social_security: 6_000 # $500/month unearned > payment standard + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 1_000 + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc_payment_standard: 408 + ne_adc_maximum_benefit: 408 + ne_adc: 0 + # Final = $408 - $500 = -$92 -> $0 (no negative benefits) + +# ============================================================================= +# MIXED INCOME BOUNDARY TESTS +# ============================================================================= + +- name: Case 24, mixed income exactly at threshold. + # Countable = earned_after_disregard + unearned = need_standard + # For size 3: need_standard = $881 + # Say earned = $600/month -> countable_earned = $300 + # Need unearned = $881 - $300 = $581, but that makes countable >= need_standard + # For strict <, need total < $881 + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 8_400 # $700/month -> $350 countable earned + social_security: 6_372 # $531/month unearned + person2: + age: 10 + person3: + age: 8 + spm_units: + spm_unit: + members: [person1, person2, person3] + spm_unit_assets: 1_000 + households: + household: + members: [person1, person2, person3] + state_code: NE + output: + ne_adc_need_standard: 881 + ne_adc_countable_earned_income: 350 + # Gross = $700, after 50% disregard = $350 + ne_adc_income_eligible: false + # Total countable = $350 + $531 = $881 + # Countable ($881) < Need Standard ($881) -> false + ne_adc_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/integration.yaml new file mode 100644 index 00000000000..2be998f8881 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/integration.yaml @@ -0,0 +1,268 @@ +# Nebraska ADC (Aid to Dependent Children) Integration Tests +# Gap Budgeting Methodology: +# Step 1: Net Earned Income = Gross Earned * (1 - 0.50) = Gross Earned * 0.50 +# Step 2: Gap = Need Standard - Net Earned Income +# Step 3: Benefit = min(Gap, Payment Standard) +# Step 4: Final Benefit = Benefit - Unearned Income +# Step 5: Apply minimum payment ($10) if benefit > 0 but < $10 +# +# Income Standards (July 2021): +# Size 2: Need Standard = $741, Payment Standard = $408 +# Size 3: Need Standard = $881, Payment Standard = $485 +# Size 4: Need Standard = $1,021, Payment Standard = $562 + +- name: Case 1, family of 3 with no income receives maximum benefit. + period: 2024-01 + input: + people: + person1: + age: 30 + is_tax_unit_head_or_spouse: true + employment_income_before_lsr: 0 + person2: + age: 10 + person3: + age: 8 + spm_units: + spm_unit: + members: [person1, person2, person3] + spm_unit_assets: 1_000 + households: + household: + members: [person1, person2, person3] + state_code: NE + output: + spm_unit_size: 3 + ne_adc_need_standard: 881 + # Need standard for size 3 = $881 + ne_adc_payment_standard: 485 + # Payment standard = $881 * 0.55 = $484.55, rounded to $485 + ne_adc_countable_earned_income: 0 + # No earned income, no unearned income + ne_adc_income_eligible: true + # Countable income ($0) < Need standard ($881) -> Eligible + ne_adc_eligible: true + ne_adc: 485 + # Gap = $881 - $0 = $881 + # Benefit = min($881, $485) = $485 + # Final = $485 - $0 = $485 + +- name: Case 2, family of 3 with earned income receives partial benefit. + period: 2024-01 + input: + people: + person1: + age: 30 + is_tax_unit_head_or_spouse: true + employment_income_before_lsr: 12_000 # $1,000/month + person2: + age: 10 + person3: + age: 8 + spm_units: + spm_unit: + members: [person1, person2, person3] + spm_unit_assets: 2_000 + households: + household: + members: [person1, person2, person3] + state_code: NE + output: + spm_unit_size: 3 + ne_adc_need_standard: 881 + ne_adc_payment_standard: 485 + ne_adc_countable_earned_income: 500 + # Gross earned = $1,000/month + # After 50% disregard: $1,000 * 0.50 = $500 + # Countable income = Earned ($500) + Unearned ($0) = $500 + ne_adc_income_eligible: true + # Countable income ($500) < Need standard ($881) -> Eligible + ne_adc_eligible: true + ne_adc: 381 + # Gap = $881 - $500 = $381 + # Benefit = min($381, $485) = $381 + # Final = $381 - $0 = $381 + +- name: Case 3, family of 4 with unearned income. + period: 2024-01 + input: + people: + person1: + age: 30 + is_tax_unit_head_or_spouse: true + employment_income_before_lsr: 0 + social_security: 6_000 # $500/month unearned + person2: + age: 29 + is_tax_unit_head_or_spouse: true + person3: + age: 10 + person4: + age: 8 + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + spm_unit_assets: 3_000 + households: + household: + members: [person1, person2, person3, person4] + state_code: NE + output: + spm_unit_size: 4 + ne_adc_need_standard: 1_021 + # Need standard for size 4 = $1,021 + ne_adc_payment_standard: 562 + # Payment standard = $1,021 * 0.55 = $561.55, rounded to $562 + ne_adc_countable_earned_income: 0 + # Social security: $6,000/12 = $500/month unearned + # Countable income = Earned ($0) + Unearned ($500) = $500 + ne_adc_income_eligible: true + ne_adc_eligible: true + ne_adc: 62 + # Gap = $1,021 - $0 = $1,021 + # Benefit = min($1,021, $562) = $562 + # Final = $562 - $500 = $62 + +- name: Case 4, family above income limit is ineligible. + period: 2024-01 + input: + people: + person1: + age: 30 + is_tax_unit_head_or_spouse: true + employment_income_before_lsr: 24_000 # $2,000/month + person2: + age: 10 + person3: + age: 8 + spm_units: + spm_unit: + members: [person1, person2, person3] + spm_unit_assets: 1_000 + households: + household: + members: [person1, person2, person3] + state_code: NE + output: + spm_unit_size: 3 + ne_adc_need_standard: 881 + ne_adc_payment_standard: 485 + ne_adc_countable_earned_income: 1_000 + # Gross earned = $2,000/month + # After 50% disregard: $2,000 * 0.50 = $1,000 + # Countable income = $1,000 + ne_adc_income_eligible: false + # Countable income ($1,000) > Need standard ($881) -> Ineligible + ne_adc_eligible: false + ne_adc: 0 + # Gap = $881 - $1,000 = -$119 (negative, not eligible) + +- name: Case 5, family of 2 near income threshold. + period: 2024-01 + input: + people: + person1: + age: 30 + is_tax_unit_head_or_spouse: true + employment_income_before_lsr: 16_800 # $1,400/month + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 1_000 + households: + household: + members: [person1, person2] + state_code: NE + output: + spm_unit_size: 2 + ne_adc_need_standard: 741 + # Need standard for size 2 = $741 + ne_adc_payment_standard: 408 + # Payment standard = $741 * 0.55 = $407.55, rounded to $408 + ne_adc_countable_earned_income: 700 + # Gross earned = $1,400/month + # After 50% disregard: $1,400 * 0.50 = $700 + # Countable income = $700 + ne_adc_income_eligible: true + # Countable income ($700) < Need standard ($741) -> Eligible + ne_adc_eligible: true + ne_adc: 41 + # Gap = $741 - $700 = $41 + # Benefit = min($41, $408) = $41 + # $41 > $10 minimum, so benefit = $41 + +- name: Case 6, family with both earned and unearned income. + period: 2024-01 + input: + people: + person1: + age: 30 + is_tax_unit_head_or_spouse: true + employment_income_before_lsr: 7_200 # $600/month earned + social_security: 2_400 # $200/month unearned + person2: + age: 10 + person3: + age: 8 + spm_units: + spm_unit: + members: [person1, person2, person3] + spm_unit_assets: 2_000 + households: + household: + members: [person1, person2, person3] + state_code: NE + output: + spm_unit_size: 3 + ne_adc_need_standard: 881 + ne_adc_payment_standard: 485 + ne_adc_countable_earned_income: 300 + # Gross earned = $600/month + # After 50% disregard: $600 * 0.50 = $300 + # Unearned: $2,400/12 = $200/month + # Countable income = Earned ($300) + Unearned ($200) = $500 + ne_adc_income_eligible: true + ne_adc_eligible: true + ne_adc: 285 + # Gap = $881 - $300 = $581 + # Benefit = min($581, $485) = $485 + # Final = $485 - $200 = $285 + +- name: Case 7, minimum payment rule applies. + period: 2024-01 + input: + people: + person1: + age: 30 + is_tax_unit_head_or_spouse: true + employment_income_before_lsr: 7_920 # $660/month earned + social_security: 4_800 # $400/month unearned + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 1_000 + households: + household: + members: [person1, person2] + state_code: NE + output: + spm_unit_size: 2 + ne_adc_need_standard: 741 + ne_adc_payment_standard: 408 + ne_adc_countable_earned_income: 330 + # Gross earned = $660/month + # After 50% disregard: $660 * 0.50 = $330 + # Unearned: $4,800/12 = $400/month + # Countable income = Earned ($330) + Unearned ($400) = $730 + ne_adc_income_eligible: true + # Countable income ($730) < Need standard ($741) -> Eligible + ne_adc_eligible: true + ne_adc: 10 + # Gap = $741 - $330 = $411 + # Benefit = min($411, $408) = $408 + # Final = $408 - $400 = $8 + # $8 < $10 minimum, so benefit = $10 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc.yaml b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc.yaml new file mode 100644 index 00000000000..bb13366769d --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc.yaml @@ -0,0 +1,159 @@ +# Nebraska ADC Benefit Amount Tests +# Gap Budgeting Methodology: +# Step 1: Net Earned Income = Gross Earned * 0.50 +# Step 2: Gap = Need Standard - Net Earned Income +# Step 3: Benefit = min(Gap, Payment Standard) +# Step 4: Final Benefit = Benefit - Unearned Income +# Step 5: Apply minimum payment ($10) if benefit > 0 but < $10 + +- name: Case 1, no income receives maximum benefit. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 0 + person2: + age: 10 + person3: + age: 8 + spm_units: + spm_unit: + members: [person1, person2, person3] + spm_unit_cash_assets: 1_000 + households: + household: + members: [person1, person2, person3] + state_code: NE + output: + ne_adc: 485 + # Gap = $881 - $0 = $881 + # Benefit = min($881, $485) = $485 + # Final = $485 - $0 = $485 + +- name: Case 2, earned income reduces benefit. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 12_000 # $1,000/month + person2: + age: 10 + person3: + age: 8 + spm_units: + spm_unit: + members: [person1, person2, person3] + spm_unit_cash_assets: 1_000 + households: + household: + members: [person1, person2, person3] + state_code: NE + output: + ne_adc: 381 + # Countable earned = $1,000 * 0.50 = $500 + # Gap = $881 - $500 = $381 + # Benefit = min($381, $485) = $381 + # Final = $381 - $0 = $381 + +- name: Case 3, unearned income reduces benefit. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 0 + social_security: 6_000 # $500/month + person2: + age: 10 + person3: + age: 8 + spm_units: + spm_unit: + members: [person1, person2, person3] + spm_unit_cash_assets: 1_000 + households: + household: + members: [person1, person2, person3] + state_code: NE + output: + ne_adc: 0 + # Gap = $881 - $0 = $881 + # Benefit = min($881, $485) = $485 + # Final = $485 - $500 = -$15 -> $0 (can't be negative) + +- name: Case 4, income too high gets zero benefit. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 24_000 # $2,000/month + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_cash_assets: 1_000 + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc: 0 + # Countable earned = $2,000 * 0.50 = $1,000 + # Gap = $741 - $1,000 = -$259 (negative, not eligible) + # Benefit = $0 + +- name: Case 5, minimum payment rule applies. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 7_920 # $660/month earned + social_security: 4_800 # $400/month unearned + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_cash_assets: 1_000 + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc: 10 + # Countable earned = $660 * 0.50 = $330 + # Gap = $741 - $330 = $411 + # Benefit = min($411, $408) = $408 + # Final = $408 - $400 = $8 + # $8 < $10 minimum, so benefit = $10 + +- name: Case 6, benefit just above minimum. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 7_920 # $660/month earned + social_security: 4_680 # $390/month unearned + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_cash_assets: 1_000 + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc: 18 + # Countable earned = $660 * 0.50 = $330 + # Gap = $741 - $330 = $411 + # Benefit = min($411, $408) = $408 + # Final = $408 - $390 = $18 + # $18 > $10 minimum, so benefit = $18 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_countable_earned_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_countable_earned_income.yaml new file mode 100644 index 00000000000..7abad1d5fff --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_countable_earned_income.yaml @@ -0,0 +1,85 @@ +# Nebraska ADC Countable Earned Income Tests +# Earned Income Disregard: 50% of gross earned income +# Countable Earned = Gross Earned * (1 - 0.50) = Gross Earned * 0.50 + +- name: Case 1, no earned income. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 0 + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc_countable_earned_income: 0 + +- name: Case 2, earned income with 50 percent disregard. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 12_000 # $1,000/month + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc_countable_earned_income: 500 + # Gross earned: $12,000/12 = $1,000/month + # After 50% disregard: $1,000 * 0.50 = $500 + +- name: Case 3, moderate earned income. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 7_200 # $600/month + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc_countable_earned_income: 300 + # Gross earned: $7,200/12 = $600/month + # After 50% disregard: $600 * 0.50 = $300 + +- name: Case 4, high earned income. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 24_000 # $2,000/month + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc_countable_earned_income: 1_000 + # Gross earned: $24,000/12 = $2,000/month + # After 50% disregard: $2,000 * 0.50 = $1,000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_eligible.yaml new file mode 100644 index 00000000000..01defee9fa6 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_eligible.yaml @@ -0,0 +1,130 @@ +# Nebraska ADC Eligibility Tests +# Eligibility requires: +# 1. Net earned income (after 50% disregard) < Need Standard +# 2. Resources within limits ($4,000 for 1 person, $6,000 for 2+) + +- name: Case 1, no income is eligible. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 0 + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_cash_assets: 1_000 + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc_income_eligible: true + # Countable income ($0) < Need standard ($741) + ne_adc_eligible: true + +- name: Case 2, income below threshold is eligible. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 12_000 # $1,000/month gross + person2: + age: 10 + person3: + age: 8 + spm_units: + spm_unit: + members: [person1, person2, person3] + spm_unit_cash_assets: 2_000 + households: + household: + members: [person1, person2, person3] + state_code: NE + output: + ne_adc_countable_earned_income: 500 + # After 50% disregard: $1,000 * 0.50 = $500 + # Countable income = $500 + ne_adc_income_eligible: true + # Countable income ($500) < Need standard ($881) + ne_adc_eligible: true + +- name: Case 3, income above threshold is ineligible. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 24_000 # $2,000/month gross + person2: + age: 10 + person3: + age: 8 + spm_units: + spm_unit: + members: [person1, person2, person3] + spm_unit_cash_assets: 1_000 + households: + household: + members: [person1, person2, person3] + state_code: NE + output: + ne_adc_countable_earned_income: 1_000 + # After 50% disregard: $2,000 * 0.50 = $1,000 + # Countable income = $1,000 + ne_adc_income_eligible: false + # Countable income ($1,000) > Need standard ($881) + ne_adc_eligible: false + +- name: Case 4, income exactly at threshold. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 17_640 # $1,470/month -> $735 countable + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_cash_assets: 1_000 + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc_countable_earned_income: 735 + # After 50% disregard: $1,470 * 0.50 = $735 + # Countable income = $735 + ne_adc_income_eligible: true + # Countable income ($735) < Need standard ($741) + ne_adc_eligible: true + +- name: Case 5, income just above threshold. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 17_880 # $1,490/month -> $745 countable + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_cash_assets: 1_000 + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc_countable_earned_income: 745 + # After 50% disregard: $1,490 * 0.50 = $745 + # Countable income = $745 + ne_adc_income_eligible: false + # Countable income ($745) > Need standard ($741) + ne_adc_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_need_standard.yaml b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_need_standard.yaml new file mode 100644 index 00000000000..852e7d0b5b7 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_need_standard.yaml @@ -0,0 +1,114 @@ +# Nebraska ADC Need Standard Tests +# The need standard is a lookup by family size +# Values effective July 1, 2021: +# Size 1: $601, Size 2: $741, Size 3: $881, Size 4: $1,021, etc. +# Formula: $601 + ($140 * (size - 1)) + +- name: Case 1, single person household. + period: 2024-01 + input: + people: + person1: + age: 30 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: NE + output: + ne_adc_need_standard: 601 + # Need standard for size 1 = $601 + +- name: Case 2, family of 2. + period: 2024-01 + input: + people: + person1: + age: 30 + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc_need_standard: 741 + # Need standard for size 2 = $741 + +- name: Case 3, family of 3. + period: 2024-01 + input: + people: + person1: + age: 30 + person2: + age: 10 + person3: + age: 8 + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: NE + output: + ne_adc_need_standard: 881 + # Need standard for size 3 = $881 + +- name: Case 4, family of 4. + period: 2024-01 + input: + people: + person1: + age: 30 + person2: + age: 29 + person3: + age: 10 + person4: + age: 8 + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + households: + household: + members: [person1, person2, person3, person4] + state_code: NE + output: + ne_adc_need_standard: 1_021 + # Need standard for size 4 = $1,021 + +- name: Case 5, large family of 7. + period: 2024-01 + input: + people: + person1: + age: 35 + person2: + age: 33 + person3: + age: 15 + person4: + age: 12 + person5: + age: 10 + person6: + age: 8 + person7: + age: 5 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5, person6, person7] + households: + household: + members: [person1, person2, person3, person4, person5, person6, person7] + state_code: NE + output: + ne_adc_need_standard: 1_441 + # Need standard for size 7 = $1,441 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_payment_standard.yaml b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_payment_standard.yaml new file mode 100644 index 00000000000..23c6f59c595 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_payment_standard.yaml @@ -0,0 +1,88 @@ +# Nebraska ADC Payment Standard Tests +# Payment standard = Need Standard * 0.55 (55%) +# Values effective September 1, 2015: +# Size 1: $331, Size 2: $408, Size 3: $485, Size 4: $562, etc. + +- name: Case 1, single person household. + period: 2024-01 + absolute_error_margin: 1 + input: + people: + person1: + age: 30 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: NE + output: + ne_adc_payment_standard: 331 + # Need standard $601 * 0.55 = $330.55, rounded to $331 + +- name: Case 2, family of 2. + period: 2024-01 + absolute_error_margin: 1 + input: + people: + person1: + age: 30 + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc_payment_standard: 408 + # Need standard $741 * 0.55 = $407.55, rounded to $408 + +- name: Case 3, family of 3. + period: 2024-01 + absolute_error_margin: 1 + input: + people: + person1: + age: 30 + person2: + age: 10 + person3: + age: 8 + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: NE + output: + ne_adc_payment_standard: 485 + # Need standard $881 * 0.55 = $484.55, rounded to $485 + +- name: Case 4, family of 4. + period: 2024-01 + absolute_error_margin: 1 + input: + people: + person1: + age: 30 + person2: + age: 29 + person3: + age: 10 + person4: + age: 8 + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + households: + household: + members: [person1, person2, person3, person4] + state_code: NE + output: + ne_adc_payment_standard: 562 + # Need standard $1,021 * 0.55 = $561.55, rounded to $562 diff --git a/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc.py b/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc.py new file mode 100644 index 00000000000..ed9b91d7a92 --- /dev/null +++ b/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc.py @@ -0,0 +1,28 @@ +from policyengine_us.model_api import * + + +class ne_adc(Variable): + value_type = float + entity = SPMUnit + label = "Nebraska Aid to Dependent Children (ADC)" + unit = USD + definition_period = MONTH + reference = ( + "https://nebraskalegislature.gov/laws/statutes.php?statute=43-512", + "https://nebraskalegislature.gov/laws/statutes.php?statute=68-1713", + ) + defined_for = "ne_adc_eligible" + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ne.dhhs.adc + maximum_benefit = spm_unit("ne_adc_maximum_benefit", period) + unearned = add(spm_unit, period, ["tanf_gross_unearned_income"]) + # Final benefit = max benefit - unearned income + benefit_before_minimum = max_(maximum_benefit - unearned, 0) + # Per Neb. Rev. Stat. 43-512: no payments less than $10/month + # If benefit > 0 but < $10, return $10; if benefit = 0, return 0 + return where( + benefit_before_minimum > 0, + max_(benefit_before_minimum, p.min_payment), + 0, + ) diff --git a/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_countable_earned_income.py b/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_countable_earned_income.py new file mode 100644 index 00000000000..549cf193233 --- /dev/null +++ b/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_countable_earned_income.py @@ -0,0 +1,20 @@ +from policyengine_us.model_api import * + + +class ne_adc_countable_earned_income(Variable): + value_type = float + entity = SPMUnit + label = "Nebraska ADC countable earned income" + unit = USD + definition_period = MONTH + reference = ( + "https://nebraskalegislature.gov/laws/statutes.php?statute=68-1726" + ) + defined_for = StateCode.NE + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ne.dhhs.adc.income + gross_earned = add(spm_unit, period, ["tanf_gross_earned_income"]) + # Per Neb. Rev. Stat. 68-1726(3)(a)(ii): 50% of gross earned income + # is disregarded for recipients + return gross_earned * (1 - p.earned_income_disregard) diff --git a/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_eligible.py b/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_eligible.py new file mode 100644 index 00000000000..3823d8fcd4f --- /dev/null +++ b/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_eligible.py @@ -0,0 +1,33 @@ +from policyengine_us.model_api import * + + +class ne_adc_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Nebraska ADC eligible" + definition_period = MONTH + reference = ( + "https://dhhs.ne.gov/Pages/TANF.aspx", + "https://dhhs.ne.gov/Pages/Title-468.aspx", + ) + defined_for = StateCode.NE + + def formula(spm_unit, period, parameters): + # Use federal demographic eligibility baseline + demographic_eligible = spm_unit("is_demographic_tanf_eligible", period) + # Check immigration eligibility (at least one citizen/legal immigrant) + immigration_eligible = ( + add(spm_unit, period, ["is_citizen_or_legal_immigrant"]) > 0 + ) + # Income eligibility + income_eligible = spm_unit("ne_adc_income_eligible", period) + # Resource eligibility (YEAR variable) + resources_eligible = spm_unit( + "ne_adc_resources_eligible", period.this_year + ) + return ( + demographic_eligible + & immigration_eligible + & income_eligible + & resources_eligible + ) diff --git a/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_income_eligible.py b/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_income_eligible.py new file mode 100644 index 00000000000..54eea4857fd --- /dev/null +++ b/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_income_eligible.py @@ -0,0 +1,21 @@ +from policyengine_us.model_api import * + + +class ne_adc_income_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Nebraska ADC income eligible" + definition_period = MONTH + reference = ( + "https://nebraskalegislature.gov/laws/statutes.php?statute=68-1726", + "https://dhhs.ne.gov/Pages/Title-468.aspx", + ) + defined_for = StateCode.NE + + def formula(spm_unit, period, parameters): + # Per 468 NAC: countable income must be below standard of need + countable_earned = spm_unit("ne_adc_countable_earned_income", period) + unearned = add(spm_unit, period, ["tanf_gross_unearned_income"]) + countable_income = countable_earned + unearned + need_standard = spm_unit("ne_adc_need_standard", period) + return countable_income < need_standard diff --git a/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_maximum_benefit.py b/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_maximum_benefit.py new file mode 100644 index 00000000000..63d557068ab --- /dev/null +++ b/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_maximum_benefit.py @@ -0,0 +1,23 @@ +from policyengine_us.model_api import * + + +class ne_adc_maximum_benefit(Variable): + value_type = float + entity = SPMUnit + label = "Nebraska ADC maximum benefit before unearned income deduction" + unit = USD + definition_period = MONTH + reference = ( + "https://nebraskalegislature.gov/laws/statutes.php?statute=68-1713", + "https://dhhs.ne.gov/Pages/Title-468.aspx", + ) + defined_for = StateCode.NE + + def formula(spm_unit, period, parameters): + need_standard = spm_unit("ne_adc_need_standard", period) + countable_earned = spm_unit("ne_adc_countable_earned_income", period) + payment_standard = spm_unit("ne_adc_payment_standard", period) + # Gap budgeting: Gap = Standard of Need - Net Earned Income + gap = max_(need_standard - countable_earned, 0) + # Benefit = min(Gap, Payment Standard) + return min_(gap, payment_standard) diff --git a/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_need_standard.py b/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_need_standard.py new file mode 100644 index 00000000000..481c70d0d3c --- /dev/null +++ b/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_need_standard.py @@ -0,0 +1,21 @@ +from policyengine_us.model_api import * + + +class ne_adc_need_standard(Variable): + value_type = float + entity = SPMUnit + label = "Nebraska ADC standard of need" + unit = USD + definition_period = MONTH + reference = ( + "https://nebraskalegislature.gov/laws/statutes.php?statute=43-513", + "https://dhhs.ne.gov/Pages/Title-468.aspx", + ) + defined_for = StateCode.NE + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ne.dhhs.adc + size = spm_unit("spm_unit_size", period) + # Cap size at maximum defined in parameter table (14) + capped_size = min_(size, 14) + return p.need_standard[capped_size] diff --git a/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_payment_standard.py b/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_payment_standard.py new file mode 100644 index 00000000000..57d304b1582 --- /dev/null +++ b/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_payment_standard.py @@ -0,0 +1,20 @@ +from policyengine_us.model_api import * + + +class ne_adc_payment_standard(Variable): + value_type = float + entity = SPMUnit + label = "Nebraska ADC payment standard" + unit = USD + definition_period = MONTH + reference = ( + "https://nebraskalegislature.gov/laws/statutes.php?statute=43-512" + ) + defined_for = StateCode.NE + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ne.dhhs.adc + need_standard = spm_unit("ne_adc_need_standard", period) + # Per Neb. Rev. Stat. 43-512: payment is 55% of standard of need + # Rounded to whole dollars + return np.ceil(need_standard * p.payment_standard_rate) diff --git a/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_resources_eligible.py b/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_resources_eligible.py new file mode 100644 index 00000000000..203aa442f7d --- /dev/null +++ b/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_resources_eligible.py @@ -0,0 +1,23 @@ +from policyengine_us.model_api import * + + +class ne_adc_resources_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Nebraska ADC resources eligible" + definition_period = YEAR + reference = ( + "https://nebraskalegislature.gov/laws/statutes.php?statute=68-1726", + "https://nebraskalegislature.gov/laws/statutes.php?statute=68-1713", + ) + defined_for = StateCode.NE + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ne.dhhs.adc + # spm_unit_assets is a YEAR variable + countable_resources = spm_unit("spm_unit_assets", period) + size = spm_unit("spm_unit_size", period) + # Resource limits: $4,000 for 1 person, $6,000 for 2+ persons + capped_size = min_(size, 14) + limit = p.resource_limit[capped_size] + return countable_resources <= limit From daed422239dc4f19a0a3ca6519d11d72deda1609 Mon Sep 17 00:00:00 2001 From: Ziming Date: Tue, 23 Dec 2025 21:21:38 -0500 Subject: [PATCH 3/8] draft --- .../{income => }/earned_income_disregard.yaml | 0 .../gov/states/ne/dhhs/adc/max_unit_size.yaml | 14 + .../gov/states/ne/dhhs/adc/min_payment.yaml | 2 +- .../gov/states/ne/dhhs/adc/need_standard.yaml | 2 +- .../ne/dhhs/adc/payment_standard_rate.yaml | 2 +- .../states/ne/dhhs/adc/resource_limit.yaml | 2 +- .../gov/states/ne/dhhs/adc/edge_cases.yaml | 107 +++++ .../adc/ne_adc_countable_earned_income.py | 6 +- .../ne/dhhs/adc/ne_adc_need_standard.py | 4 +- .../ne/dhhs/adc/ne_adc_payment_standard.py | 4 +- .../ne/dhhs/adc/ne_adc_resources_eligible.py | 2 +- sources/working_references.md | 440 ++++++++++++++++++ 12 files changed, 571 insertions(+), 14 deletions(-) rename policyengine_us/parameters/gov/states/ne/dhhs/adc/{income => }/earned_income_disregard.yaml (100%) create mode 100644 policyengine_us/parameters/gov/states/ne/dhhs/adc/max_unit_size.yaml create mode 100644 sources/working_references.md diff --git a/policyengine_us/parameters/gov/states/ne/dhhs/adc/income/earned_income_disregard.yaml b/policyengine_us/parameters/gov/states/ne/dhhs/adc/earned_income_disregard.yaml similarity index 100% rename from policyengine_us/parameters/gov/states/ne/dhhs/adc/income/earned_income_disregard.yaml rename to policyengine_us/parameters/gov/states/ne/dhhs/adc/earned_income_disregard.yaml diff --git a/policyengine_us/parameters/gov/states/ne/dhhs/adc/max_unit_size.yaml b/policyengine_us/parameters/gov/states/ne/dhhs/adc/max_unit_size.yaml new file mode 100644 index 00000000000..eb4b0a645f9 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ne/dhhs/adc/max_unit_size.yaml @@ -0,0 +1,14 @@ +description: Nebraska sets this as the maximum unit size for benefit calculations under the Aid to Dependent Children program. + +values: + 2021-07-01: 14 + +metadata: + unit: /1 + period: year + label: Nebraska ADC maximum unit size + reference: + - title: Title 468 NAC Chapter 3 + href: https://dhhs.ne.gov/Pages/Title-468.aspx + - title: Neb. Rev. Stat. 43-513 + href: https://nebraskalegislature.gov/laws/statutes.php?statute=43-513 diff --git a/policyengine_us/parameters/gov/states/ne/dhhs/adc/min_payment.yaml b/policyengine_us/parameters/gov/states/ne/dhhs/adc/min_payment.yaml index b067b996805..7cd413696c4 100644 --- a/policyengine_us/parameters/gov/states/ne/dhhs/adc/min_payment.yaml +++ b/policyengine_us/parameters/gov/states/ne/dhhs/adc/min_payment.yaml @@ -8,5 +8,5 @@ metadata: period: month label: Nebraska ADC minimum payment reference: - - title: Neb. Rev. Stat. 43-512 + - title: Neb. Rev. Stat. 43-512(1) href: https://nebraskalegislature.gov/laws/statutes.php?statute=43-512 diff --git a/policyengine_us/parameters/gov/states/ne/dhhs/adc/need_standard.yaml b/policyengine_us/parameters/gov/states/ne/dhhs/adc/need_standard.yaml index 59df372f8df..d719ba708ef 100644 --- a/policyengine_us/parameters/gov/states/ne/dhhs/adc/need_standard.yaml +++ b/policyengine_us/parameters/gov/states/ne/dhhs/adc/need_standard.yaml @@ -7,7 +7,7 @@ metadata: - range(1, 15) label: Nebraska ADC standard of need reference: - - title: Neb. Rev. Stat. 43-513 + - title: Neb. Rev. Stat. 43-513(1) href: https://nebraskalegislature.gov/laws/statutes.php?statute=43-513 - title: Title 468 NAC Chapter 3 href: https://dhhs.ne.gov/Pages/Title-468.aspx diff --git a/policyengine_us/parameters/gov/states/ne/dhhs/adc/payment_standard_rate.yaml b/policyengine_us/parameters/gov/states/ne/dhhs/adc/payment_standard_rate.yaml index 23af4e6ba58..d480ff2244b 100644 --- a/policyengine_us/parameters/gov/states/ne/dhhs/adc/payment_standard_rate.yaml +++ b/policyengine_us/parameters/gov/states/ne/dhhs/adc/payment_standard_rate.yaml @@ -8,5 +8,5 @@ metadata: period: month label: Nebraska ADC payment standard rate reference: - - title: Neb. Rev. Stat. 43-512 + - title: Neb. Rev. Stat. 43-512(1) href: https://nebraskalegislature.gov/laws/statutes.php?statute=43-512 diff --git a/policyengine_us/parameters/gov/states/ne/dhhs/adc/resource_limit.yaml b/policyengine_us/parameters/gov/states/ne/dhhs/adc/resource_limit.yaml index e9c650f6c77..5ef4574192f 100644 --- a/policyengine_us/parameters/gov/states/ne/dhhs/adc/resource_limit.yaml +++ b/policyengine_us/parameters/gov/states/ne/dhhs/adc/resource_limit.yaml @@ -7,7 +7,7 @@ metadata: - range(1, 15) label: Nebraska ADC resource limit reference: - - title: Neb. Rev. Stat. 68-1726 + - title: Neb. Rev. Stat. 68-1726(1) href: https://nebraskalegislature.gov/laws/statutes.php?statute=68-1726 - title: Neb. Rev. Stat. 68-1713 href: https://nebraskalegislature.gov/laws/statutes.php?statute=68-1713 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/edge_cases.yaml b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/edge_cases.yaml index e152032f5ad..557cc58bc74 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/edge_cases.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/edge_cases.yaml @@ -719,3 +719,110 @@ # Total countable = $350 + $531 = $881 # Countable ($881) < Need Standard ($881) -> false ne_adc_eligible: false + +# ============================================================================= +# RESOURCE BOUNDARY TESTS - ONE DOLLAR BELOW THRESHOLD +# ============================================================================= + +- name: Case 25, resources one dollar below $4,000 limit for single person. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 0 + spm_units: + spm_unit: + members: [person1] + spm_unit_assets: 3_999 + households: + household: + members: [person1] + state_code: NE + output: + spm_unit_size: 1 + ne_adc_resources_eligible: true + # Resources ($3,999) <= Limit ($4,000) -> true + +- name: Case 26, resources one dollar below $6,000 limit for family of 2. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 0 + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 5_999 + households: + household: + members: [person1, person2] + state_code: NE + output: + spm_unit_size: 2 + ne_adc_resources_eligible: true + # Resources ($5,999) <= Limit ($6,000) -> true + ne_adc_eligible: true + +# ============================================================================= +# DEMOGRAPHIC ELIGIBILITY EDGE CASES +# ============================================================================= + +- name: Case 27, household with only adults fails demographic eligibility. + # Two adults (ages 30 and 35) with no children or pregnant persons + # Fails is_demographic_tanf_eligible because no one meets age limit + period: 2024-01 + input: + people: + person1: + age: 30 + is_pregnant: false + employment_income_before_lsr: 0 + person2: + age: 35 + is_pregnant: false + employment_income_before_lsr: 0 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 1_000 + households: + household: + members: [person1, person2] + state_code: NE + output: + is_demographic_tanf_eligible: false + # No eligible children (both adults over age limit) and no pregnant persons + ne_adc_eligible: false + # Fails demographic eligibility even if income/resources pass + ne_adc: 0 + +# ============================================================================= +# STATE RESIDENCY EDGE CASES +# ============================================================================= + +- name: Case 28, non-Nebraska state returns zero benefit. + # Family in Texas should get zero Nebraska ADC benefit + # The defined_for = StateCode.NE constraint applies + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 0 + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 1_000 + households: + household: + members: [person1, person2] + state_code: TX + output: + ne_adc: 0 + # Family in Texas, not Nebraska -> ne_adc benefit is $0 diff --git a/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_countable_earned_income.py b/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_countable_earned_income.py index 549cf193233..a1a1267434c 100644 --- a/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_countable_earned_income.py +++ b/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_countable_earned_income.py @@ -7,13 +7,11 @@ class ne_adc_countable_earned_income(Variable): label = "Nebraska ADC countable earned income" unit = USD definition_period = MONTH - reference = ( - "https://nebraskalegislature.gov/laws/statutes.php?statute=68-1726" - ) + reference = "https://nebraskalegislature.gov/laws/statutes.php?statute=68-1726" defined_for = StateCode.NE def formula(spm_unit, period, parameters): - p = parameters(period).gov.states.ne.dhhs.adc.income + p = parameters(period).gov.states.ne.dhhs.adc gross_earned = add(spm_unit, period, ["tanf_gross_earned_income"]) # Per Neb. Rev. Stat. 68-1726(3)(a)(ii): 50% of gross earned income # is disregarded for recipients diff --git a/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_need_standard.py b/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_need_standard.py index 481c70d0d3c..9ecde4817f8 100644 --- a/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_need_standard.py +++ b/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_need_standard.py @@ -16,6 +16,6 @@ class ne_adc_need_standard(Variable): def formula(spm_unit, period, parameters): p = parameters(period).gov.states.ne.dhhs.adc size = spm_unit("spm_unit_size", period) - # Cap size at maximum defined in parameter table (14) - capped_size = min_(size, 14) + # Cap size at maximum defined in parameter table + capped_size = min_(size, p.max_unit_size) return p.need_standard[capped_size] diff --git a/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_payment_standard.py b/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_payment_standard.py index 57d304b1582..394ce8742e2 100644 --- a/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_payment_standard.py +++ b/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_payment_standard.py @@ -7,9 +7,7 @@ class ne_adc_payment_standard(Variable): label = "Nebraska ADC payment standard" unit = USD definition_period = MONTH - reference = ( - "https://nebraskalegislature.gov/laws/statutes.php?statute=43-512" - ) + reference = "https://nebraskalegislature.gov/laws/statutes.php?statute=43-512" defined_for = StateCode.NE def formula(spm_unit, period, parameters): diff --git a/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_resources_eligible.py b/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_resources_eligible.py index 203aa442f7d..644d40f990c 100644 --- a/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_resources_eligible.py +++ b/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_resources_eligible.py @@ -18,6 +18,6 @@ def formula(spm_unit, period, parameters): countable_resources = spm_unit("spm_unit_assets", period) size = spm_unit("spm_unit_size", period) # Resource limits: $4,000 for 1 person, $6,000 for 2+ persons - capped_size = min_(size, 14) + capped_size = min_(size, p.max_unit_size) limit = p.resource_limit[capped_size] return countable_resources <= limit diff --git a/sources/working_references.md b/sources/working_references.md new file mode 100644 index 00000000000..b3b04f7f7fa --- /dev/null +++ b/sources/working_references.md @@ -0,0 +1,440 @@ +# Collected Documentation + +## Nebraska Aid to Dependent Children (ADC) - TANF Implementation +**Collected**: 2025-12-23 +**Implementation Task**: Implement Nebraska ADC (TANF) cash assistance program + +--- + +## Official Program Name + +**Federal Program**: Temporary Assistance for Needy Families (TANF) +**State's Official Name**: Aid to Dependent Children (ADC) +**Abbreviation**: ADC +**Source**: Nebraska Revised Statutes Section 43-512, Title 468 NAC + +**Variable Prefix**: `ne_adc` + +--- + +## Regulatory Authority + +### Primary Legal Sources + +1. **Nebraska Revised Statutes** + - Section 43-504: Definition of dependent child (age requirements) + - Section 43-512: ADC application, payment level (55% of Standard of Need) + - Section 43-513: Standard of Need, CPI adjustment methodology + - Section 68-1713: Welfare Reform Act implementation requirements + - Section 68-1726: Earned income disregard, resource limits, eligibility factors + +2. **Nebraska Administrative Code Title 468** + - Chapter 1: General Background + - Chapter 2: Eligibility Requirements + - Chapter 3: Calculation of ADC Benefits + - Chapter 4: Employment First Self-Sufficiency Program + - Chapter 5: Emergency Assistance to Needy Families with Children + +### Source URLs + +- Nebraska DHHS TANF Page: https://dhhs.ne.gov/Pages/TANF.aspx +- Title 468 Overview: https://dhhs.ne.gov/Pages/Title-468.aspx +- Statute 43-504: https://nebraskalegislature.gov/laws/statutes.php?statute=43-504 +- Statute 43-512: https://nebraskalegislature.gov/laws/statutes.php?statute=43-512 +- Statute 43-513: https://nebraskalegislature.gov/laws/statutes.php?statute=43-513 +- Statute 68-1713: https://nebraskalegislature.gov/laws/statutes.php?statute=68-1713 +- Statute 68-1726: https://nebraskalegislature.gov/laws/statutes.php?statute=68-1726 + +--- + +## Demographic Eligibility + +### Eligible Children (468 NAC 2-007, Neb. Rev. Stat. 43-504) + +**Age Thresholds:** +- Children under age 19 meeting specific residency and support conditions (per 43-504) +- In practice for ADC cash assistance: + - Children age 18 or younger + - Children age 18 who are full-time students in secondary school (or equivalent vocational/technical training) and reasonably expected to complete before age 19 + - **Note**: College-level education does NOT qualify for the extended age limit + +**Pregnancy:** +- Unborn children are counted beginning the first day of the month of the mother's third trimester +- Pregnant women in final trimester qualify as "families with dependent children" +- Pregnancy must be medically verified +- Even for twins/multiples, ADC grant only reflects needs of ONE unborn child (Medical Assistance can reflect multiples) + +**Source**: 468 NAC 2-007, 3-004; Neb. Rev. Stat. 43-504 +- https://nebraskalegislature.gov/laws/statutes.php?statute=43-504 +- https://public-dhhs.ne.gov/nfocus/Manuals/APX468/apx468/eligibility_of_a_pregant_woman_for_a_grant.htm + +### Deprivation Requirement - NONE + +**IMPORTANT**: Nebraska does NOT require deprivation of parental support or care as an eligibility factor. Unmarried parents living together as a family are considered a family unit when paternity has been acknowledged or established. + +This is notable as many states require demonstration of parental absence, incapacity, or unemployment. + +**Source**: Nebraska DHHS TANF documentation + +### Implementation Approach + +- [ ] Use federal demographic eligibility (if age thresholds match federal 18/19) +- [x] Create state-specific age thresholds (Nebraska has specific student requirements - secondary school only, not college) + +--- + +## Immigration Eligibility + +**Implementation approach:** +- [x] Use federal immigration eligibility (state follows federal rules) +- Nebraska requires U.S. citizenship or qualifying alien status per 468 NAC 2-002 +- Any individual born in the United States is considered a U.S. citizen (including children of undocumented parents) + +**Source**: 468 NAC 2-002 + +--- + +## Resource Limits + +### Limits by Unit Size (Neb. Rev. Stat. 68-1726, 68-1713) + +| Unit Size | Resource Limit | +|-----------|----------------| +| 1 person | $4,000 | +| 2+ persons | $6,000 | + +### Excluded Resources + +- Primary home and furnishings +- Primary automobile (one vehicle per family - value excluded) +- Cash value of life insurance policies +- Up to $3,000 set aside for burial (pre-need burial trust or insurance policy) +- School grants, scholarships, vocational rehabilitation payments +- Job Training Partnership Act payments +- Education-related loans expected to be repaid + +### Counted Resources + +- Cash on hand +- Money in checking and savings accounts +- Savings certificates +- Stocks or bonds +- Credit card company gift card balances +- Nonrecurring lump sum payments +- Any burial funds over $3,000 + +**Source**: Nebraska Revised Statutes 68-1726, 68-1713; 468 NAC 2 (Resources) +- https://nebraskalegislature.gov/laws/statutes.php?statute=68-1726 +- https://nebraskalegislature.gov/laws/statutes.php?statute=68-1713 + +--- + +## Income Eligibility Tests + +### Test 1: Initial Eligibility (Standard of Need Test) + +For initial ADC eligibility, the family's **net earned income** must be below the **Standard of Need** for their unit size. + +**Earned Income Disregard for Applicants**: 20% of gross earned income +**Source**: Neb. Rev. Stat. 68-1726(3)(a)(i) + +### Test 2: Ongoing Eligibility + +For ongoing recipients: +**Earned Income Disregard**: 50% of gross earned income +**Source**: Neb. Rev. Stat. 68-1726(3)(a)(ii) + +### Test 3: Transitional Eligibility (185% FPL Test) + +If a family's income increases above the Standard of Need but remains below **185% of the Federal Poverty Level** for their unit size, the family may remain eligible for up to 5 months of transitional ADC grants. + +**Source**: 468 NAC 2-024.01 + +--- + +## Income Disregards and Deductions + +### Earned Income Disregard (Neb. Rev. Stat. 68-1726) + +| Status | Disregard Rate | Level | +|--------|----------------|-------| +| Applicants (initial eligibility testing) | 20% of gross earned income | Per GROUP | +| Recipients (after eligibility established) | 50% of gross earned income | Per GROUP | + +**Legal Citation**: Neb. Rev. Stat. 68-1726(3)(a): +> "(i) Twenty percent of gross earned income shall be disregarded to test for eligibility during the application process for aid to dependent children assistance; and +> (ii) For aid to dependent children program participants and for applicants after eligibility has been established, fifty percent of the gross earned income shall be disregarded" + +**Source**: https://nebraskalegislature.gov/laws/statutes.php?statute=68-1726 + +### Child Care Disregard + +A child care disregard is applied "when appropriate" according to 468 NAC documentation. The specific amount or methodology is documented in the Title 468 PDF. + +**Note**: Families receiving ADC are eligible for child care subsidy at no cost. + +### Income Exclusions + +The following are NOT counted as income: +- Financial assistance intended for books, tuition, or self-sufficiency related expenses +- School grants and scholarships +- Vocational rehabilitation payments +- Job Training Partnership Act payments +- Education-related loans expected to be repaid +- Income earned by children attending school (excluded from family income) + +**Source**: Neb. Rev. Stat. 68-1726 + +--- + +## Child Support Treatment + +### Current Rules (Until June 30, 2027) + +- Child support is assigned to the state when receiving ADC +- If average monthly child support collection exceeds the ADC payment amount, the case is closed +- Child support is either: + - Compared to budgetary need (if less than need, it's assigned and doesn't count) + - Counted as unearned income (if greater than need, case closes) + +### LB233 - Child Support Passthrough (Effective July 1, 2027) + +Beginning July 1, 2027, Nebraska will implement a child support passthrough: +- **$100 passthrough** for families with ONE child +- **$200 passthrough** for families with TWO or more children +- Passthrough amount is **disregarded** when calculating ADC eligibility and benefits + +**Source**: +- https://www.nebraskalegislature.gov/bills/view_bill.php?DocumentID=50212 +- LB233 passed 46-0 on April 11, 2024 + +--- + +## Income Standards + +### Standard of Need (468 NAC 3, Statute 43-513) + +The Standard of Need is the initial income test in ADC "gap" budgeting. It represents the monthly combined cost of food, clothing, sundries, home supplies, utilities, laundry, and shelter including taxes and insurance. + +**Effective July 1, 2021** (values adjusted biennially per CPI): + +| Unit Size | Standard of Need | +|-----------|------------------| +| 1 | $601 | +| 2 | $741 | +| 3 | $881 | +| 4 | $1,021 | +| 5 | $1,161 | +| 6 | $1,301 | +| 7 | $1,441 | +| 8 | $1,581 | +| 9 | $1,721 | +| 10 | $1,861 | +| Each additional person | +$140 | + +**CPI Adjustment**: Values are adjusted biennially (every 2 years) on July 1, using the Consumer Price Index (CPI) for the previous two calendar years, per statute 43-513. + +**Note**: Values shown are from July 1, 2021 adjustment. Some sources indicate these may have been updated. The formula is: +- Base (1 person): $601 +- Each additional person: +$140 + +**Source**: Nebraska Appleseed chart; Neb. Rev. Stat. 43-513; 468 NAC 3 +- https://neappleseed.org/wp-content/uploads/2023/03/Chart_-ADC-Standard-of-Need-and-Payment-Maximum.pdf +- https://dhhs.ne.gov/Documents/468-000-209.pdf + +### Payment Standard (Maximum Benefit) + +Effective **September 1, 2015**, the maximum ADC payment is **55% of the Standard of Need** (Neb. Rev. Stat. 43-512). + +| Unit Size | Standard of Need | Payment Standard (55%) | +|-----------|------------------|------------------------| +| 1 | $601 | $331 | +| 2 | $741 | $408 | +| 3 | $881 | $485 | +| 4 | $1,021 | $562 | +| 5 | $1,161 | $639 | +| 6 | $1,301 | $716 | +| 7 | $1,441 | $793 | +| Each additional person | +$140 | +$77 | + +**Payment Standard Rate**: 0.55 (55%) + +**Note**: There has been legislative effort (LB 310) to increase the maximum ADC payment from 55% to 85% of standard of need, but as of this documentation, 55% remains in effect. + +**Source**: Neb. Rev. Stat. 43-512; Nebraska Appleseed chart + +--- + +## Benefit Calculation + +### Gap Budgeting Methodology (468 NAC 3, Neb. Rev. Stat. 68-1713) + +Nebraska uses "Budget the Gap" methodology: + +**Step 1**: Calculate **Net Earned Income**: +- For applicants: Gross Earned Income x (1 - 0.20) = Gross Earned Income x 0.80 +- For recipients: Gross Earned Income x (1 - 0.50) = Gross Earned Income x 0.50 +- Subtract child care disregard if applicable + +**Step 2**: Calculate **"Gap"**: +- Gap = Standard of Need - Net Earned Income + +**Step 3**: Determine **Benefit Amount**: +- Benefit = min(Gap, Payment Standard) + +**Step 4**: Subtract **Unearned Income**: +- Final Benefit = Benefit - Unearned Income + +**Step 5**: Apply **Minimum Payment Rule**: +- No payments less than $10/month (except for overpayment recovery) + +**Legal Citation**: Neb. Rev. Stat. 68-1713(1)(p): "Budget the Gap Methodology Whereby Countable Earned Income is Subtracted from the Standard of the Need and Payment is Based on the Difference or Maximum Payment Level, Whichever is Less" + +**Source**: https://nebraskalegislature.gov/laws/statutes.php?statute=68-1713 + +--- + +## Transitional Grants (468 NAC 2-024.01) + +### Eligibility Requirements + +Families may receive up to **5 transitional grants** if they: +1. Lost ADC eligibility specifically due to increased earnings or hours of employment +2. Qualify for Transitional Medical Assistance (TMA) +3. Actually received an ADC grant in the month immediately before losing eligibility +4. Received or were eligible for grants in at least 3 of the 6 months preceding ineligibility + +### Grant Amount + +Each transitional grant equals **1/5 of the ADC Payment Standard** for the family's size. + +### Ongoing Requirements + +To continue receiving transitional grants, families must: +- Maintain earned income not exceeding **185% of the Federal Poverty Level** +- Maintain active employment +- Remain Nebraska residents +- Include a dependent child +- Remain ineligible for regular ADC grants + +**Source**: https://publictest-dhhs.ne.gov/nfocus/stg/Manuals/NAC468/nac468/2_024_01_transitional_grant.htm + +--- + +## Non-Simulatable Rules (Architecture Limitation) + +### Time Limits - CANNOT ENFORCE + +- **60-Month Lifetime Limit**: ADC families where parent(s) are capable of attaining independence are limited to 60 months of cash assistance in a lifetime +- **Exception**: Families where adults are not the parent of the child, or parent is disabled/unable to work, are NOT time-limited +- **Hardship Review**: After 56 months, recipients participate in a hardship review; if hardship is found, one 3-month extension may be granted + +**Note**: PolicyEngine's single-period architecture cannot track lifetime benefit receipt. + +### Work Requirements - NOT MODELED + +Nebraska's Employment First (EF) program requires participation for work-eligible adults. This is not modeled in PolicyEngine. + +### Waiting Periods - CANNOT TRACK + +- Redetermination every 6 months +- Transitional benefit requirements for prior receipt + +--- + +## Summary of Implementation Parameters + +### Parameters to Create + +| Parameter | Value | Unit | Source | +|-----------|-------|------|--------| +| Standard of Need (base, 1 person) | 601 | USD/month | 43-513, 468 NAC 3 | +| Standard of Need (additional person) | 140 | USD/month | 43-513, 468 NAC 3 | +| Payment Standard Rate | 0.55 | rate | 43-512 | +| Earned Income Disregard (applicant) | 0.20 | rate | 68-1726(3)(a)(i) | +| Earned Income Disregard (recipient) | 0.50 | rate | 68-1726(3)(a)(ii) | +| Resource Limit (1 person) | 4_000 | USD | 68-1726 | +| Resource Limit (2+ persons) | 6_000 | USD | 68-1726 | +| Minimum Payment | 10 | USD/month | 43-512 | +| Minor Child Age Threshold | 18 | years | 468 NAC 2-007, 43-504 | +| Student Age Threshold | 19 | years | 468 NAC 2-007, 43-504 | +| Transitional Eligibility FPL Rate | 1.85 | rate | 468 NAC 2-024.01 | +| Child Support Passthrough (1 child) | 100 | USD/month | LB233 (eff. 2027-07-01) | +| Child Support Passthrough (2+ children) | 200 | USD/month | LB233 (eff. 2027-07-01) | + +--- + +## Simplified Implementation Approach + +Given the complexity of Nebraska ADC with applicant vs. recipient distinctions, consider implementing: + +1. **Simplified version**: Use recipient disregard rate (50%) for all cases + - This is more generous and represents ongoing eligibility + - Avoids needing to track applicant vs. recipient status + +2. **Full version**: Implement both rates with a parameter or variable to distinguish + +**Recommendation**: Start with simplified version using 50% disregard for initial implementation. + +--- + +## References for Metadata + +### For Parameters + +```yaml +reference: + - title: Nebraska Revised Statutes 43-512 + href: https://nebraskalegislature.gov/laws/statutes.php?statute=43-512 + - title: Nebraska Revised Statutes 68-1726 + href: https://nebraskalegislature.gov/laws/statutes.php?statute=68-1726 +``` + +### For Variables + +```python +reference = "https://nebraskalegislature.gov/laws/statutes.php?statute=43-512" +# or for regulations: +reference = "https://dhhs.ne.gov/Pages/Title-468.aspx" +``` + +--- + +## PDFs for Future Reference + +The following PDFs contain additional information but could not be fully extracted: + +1. **Title 468 - Aid to Dependent Children (Complete)** + - URL: https://dhhs.ne.gov/Documents/Title-468-Complete.pdf + - Expected content: Complete ADC regulations including detailed benefit calculation, child care disregard amounts, all eligibility rules + - Note: This is the authoritative source for Nebraska ADC regulations + +2. **Title 468 Guidance Document** + - URL: https://dhhs.ne.gov/Guidance%20Docs/Title%20468%20-%20Aid%20to%20Dependent%20Children.pdf + - Expected content: Implementation guidance for ADC program + +3. **ADC Standard of Need and Payment Maximum Chart** + - URL: https://neappleseed.org/wp-content/uploads/2023/03/Chart_-ADC-Standard-of-Need-and-Payment-Maximum.pdf + - Expected content: Current Standard of Need and Payment Maximum amounts by household size + - Key information: Standard of Need table with payment standards + +4. **Nebraska TANF State Plan 2024** + - URL: https://dhhs.ne.gov/Documents/Nebraska-State-TANF-Plan-2024.pdf + - Expected content: Current TANF state plan with benefit methodology, eligibility criteria + +5. **468-000-209 Appendix Material** + - URL: https://dhhs.ne.gov/Documents/468-000-209.pdf + - Expected content: Standard of Need charts, effective July 1, 2021 + +6. **Nebraska TANF Expenditures Report 2024** + - URL: https://nebraskalegislature.gov/pdf/reports/fiscal/2024_tanf_report.pdf + - Expected content: TANF fund usage and program statistics + +--- + +## Open Questions for Implementation + +1. **Child Care Disregard Amount**: The specific child care disregard amount/methodology needs to be confirmed from Title 468 PDF +2. **Current Standard of Need Values**: Values may have been adjusted since July 2021 per CPI methodology - need to verify current amounts +3. **Simplified vs Full Implementation**: Decision on whether to implement applicant/recipient distinction or use single rate +4. **Unearned Income Treatment**: Current child support assignment rules vs. future passthrough (2027) From fd217042eb4df2d15297e10fafe40ab1abd04090 Mon Sep 17 00:00:00 2001 From: Ziming Date: Tue, 23 Dec 2025 21:43:51 -0500 Subject: [PATCH 4/8] Reorganize Nebraska ADC folder structure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move parameters and variables into logical subfolders following patterns used by other state TANF implementations (IL, OR, CO): Parameters: - benefit/ - need_standard, payment_standard_rate - income/ - earned_income_disregard - resources/ - limit (renamed from resource_limit) Variables: - benefit/ - need_standard, payment_standard, maximum_benefit - eligibility/ - eligible, income_eligible, resources_eligible - income/ - countable_earned_income 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../gov/states/ne/dhhs/adc/{ => benefit}/need_standard.yaml | 0 .../ne/dhhs/adc/{ => benefit}/payment_standard_rate.yaml | 0 .../ne/dhhs/adc/{ => income}/earned_income_disregard.yaml | 0 .../dhhs/adc/{resource_limit.yaml => resources/limit.yaml} | 0 .../ne/dhhs/adc/{ => benefit}/ne_adc_maximum_benefit.py | 0 .../ne/dhhs/adc/{ => benefit}/ne_adc_need_standard.py | 2 +- .../ne/dhhs/adc/{ => benefit}/ne_adc_payment_standard.py | 6 ++++-- .../states/ne/dhhs/adc/{ => eligibility}/ne_adc_eligible.py | 0 .../ne/dhhs/adc/{ => eligibility}/ne_adc_income_eligible.py | 0 .../dhhs/adc/{ => eligibility}/ne_adc_resources_eligible.py | 2 +- .../dhhs/adc/{ => income}/ne_adc_countable_earned_income.py | 6 ++++-- 11 files changed, 10 insertions(+), 6 deletions(-) rename policyengine_us/parameters/gov/states/ne/dhhs/adc/{ => benefit}/need_standard.yaml (100%) rename policyengine_us/parameters/gov/states/ne/dhhs/adc/{ => benefit}/payment_standard_rate.yaml (100%) rename policyengine_us/parameters/gov/states/ne/dhhs/adc/{ => income}/earned_income_disregard.yaml (100%) rename policyengine_us/parameters/gov/states/ne/dhhs/adc/{resource_limit.yaml => resources/limit.yaml} (100%) rename policyengine_us/variables/gov/states/ne/dhhs/adc/{ => benefit}/ne_adc_maximum_benefit.py (100%) rename policyengine_us/variables/gov/states/ne/dhhs/adc/{ => benefit}/ne_adc_need_standard.py (92%) rename policyengine_us/variables/gov/states/ne/dhhs/adc/{ => benefit}/ne_adc_payment_standard.py (75%) rename policyengine_us/variables/gov/states/ne/dhhs/adc/{ => eligibility}/ne_adc_eligible.py (100%) rename policyengine_us/variables/gov/states/ne/dhhs/adc/{ => eligibility}/ne_adc_income_eligible.py (100%) rename policyengine_us/variables/gov/states/ne/dhhs/adc/{ => eligibility}/ne_adc_resources_eligible.py (94%) rename policyengine_us/variables/gov/states/ne/dhhs/adc/{ => income}/ne_adc_countable_earned_income.py (76%) diff --git a/policyengine_us/parameters/gov/states/ne/dhhs/adc/need_standard.yaml b/policyengine_us/parameters/gov/states/ne/dhhs/adc/benefit/need_standard.yaml similarity index 100% rename from policyengine_us/parameters/gov/states/ne/dhhs/adc/need_standard.yaml rename to policyengine_us/parameters/gov/states/ne/dhhs/adc/benefit/need_standard.yaml diff --git a/policyengine_us/parameters/gov/states/ne/dhhs/adc/payment_standard_rate.yaml b/policyengine_us/parameters/gov/states/ne/dhhs/adc/benefit/payment_standard_rate.yaml similarity index 100% rename from policyengine_us/parameters/gov/states/ne/dhhs/adc/payment_standard_rate.yaml rename to policyengine_us/parameters/gov/states/ne/dhhs/adc/benefit/payment_standard_rate.yaml diff --git a/policyengine_us/parameters/gov/states/ne/dhhs/adc/earned_income_disregard.yaml b/policyengine_us/parameters/gov/states/ne/dhhs/adc/income/earned_income_disregard.yaml similarity index 100% rename from policyengine_us/parameters/gov/states/ne/dhhs/adc/earned_income_disregard.yaml rename to policyengine_us/parameters/gov/states/ne/dhhs/adc/income/earned_income_disregard.yaml diff --git a/policyengine_us/parameters/gov/states/ne/dhhs/adc/resource_limit.yaml b/policyengine_us/parameters/gov/states/ne/dhhs/adc/resources/limit.yaml similarity index 100% rename from policyengine_us/parameters/gov/states/ne/dhhs/adc/resource_limit.yaml rename to policyengine_us/parameters/gov/states/ne/dhhs/adc/resources/limit.yaml diff --git a/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_maximum_benefit.py b/policyengine_us/variables/gov/states/ne/dhhs/adc/benefit/ne_adc_maximum_benefit.py similarity index 100% rename from policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_maximum_benefit.py rename to policyengine_us/variables/gov/states/ne/dhhs/adc/benefit/ne_adc_maximum_benefit.py diff --git a/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_need_standard.py b/policyengine_us/variables/gov/states/ne/dhhs/adc/benefit/ne_adc_need_standard.py similarity index 92% rename from policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_need_standard.py rename to policyengine_us/variables/gov/states/ne/dhhs/adc/benefit/ne_adc_need_standard.py index 9ecde4817f8..543c7c7c2b5 100644 --- a/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_need_standard.py +++ b/policyengine_us/variables/gov/states/ne/dhhs/adc/benefit/ne_adc_need_standard.py @@ -18,4 +18,4 @@ def formula(spm_unit, period, parameters): size = spm_unit("spm_unit_size", period) # Cap size at maximum defined in parameter table capped_size = min_(size, p.max_unit_size) - return p.need_standard[capped_size] + return p.benefit.need_standard[capped_size] diff --git a/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_payment_standard.py b/policyengine_us/variables/gov/states/ne/dhhs/adc/benefit/ne_adc_payment_standard.py similarity index 75% rename from policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_payment_standard.py rename to policyengine_us/variables/gov/states/ne/dhhs/adc/benefit/ne_adc_payment_standard.py index 394ce8742e2..5d147eee891 100644 --- a/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_payment_standard.py +++ b/policyengine_us/variables/gov/states/ne/dhhs/adc/benefit/ne_adc_payment_standard.py @@ -7,7 +7,9 @@ class ne_adc_payment_standard(Variable): label = "Nebraska ADC payment standard" unit = USD definition_period = MONTH - reference = "https://nebraskalegislature.gov/laws/statutes.php?statute=43-512" + reference = ( + "https://nebraskalegislature.gov/laws/statutes.php?statute=43-512" + ) defined_for = StateCode.NE def formula(spm_unit, period, parameters): @@ -15,4 +17,4 @@ def formula(spm_unit, period, parameters): need_standard = spm_unit("ne_adc_need_standard", period) # Per Neb. Rev. Stat. 43-512: payment is 55% of standard of need # Rounded to whole dollars - return np.ceil(need_standard * p.payment_standard_rate) + return np.ceil(need_standard * p.benefit.payment_standard_rate) diff --git a/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_eligible.py b/policyengine_us/variables/gov/states/ne/dhhs/adc/eligibility/ne_adc_eligible.py similarity index 100% rename from policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_eligible.py rename to policyengine_us/variables/gov/states/ne/dhhs/adc/eligibility/ne_adc_eligible.py diff --git a/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_income_eligible.py b/policyengine_us/variables/gov/states/ne/dhhs/adc/eligibility/ne_adc_income_eligible.py similarity index 100% rename from policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_income_eligible.py rename to policyengine_us/variables/gov/states/ne/dhhs/adc/eligibility/ne_adc_income_eligible.py diff --git a/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_resources_eligible.py b/policyengine_us/variables/gov/states/ne/dhhs/adc/eligibility/ne_adc_resources_eligible.py similarity index 94% rename from policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_resources_eligible.py rename to policyengine_us/variables/gov/states/ne/dhhs/adc/eligibility/ne_adc_resources_eligible.py index 644d40f990c..12e52afd90f 100644 --- a/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_resources_eligible.py +++ b/policyengine_us/variables/gov/states/ne/dhhs/adc/eligibility/ne_adc_resources_eligible.py @@ -19,5 +19,5 @@ def formula(spm_unit, period, parameters): size = spm_unit("spm_unit_size", period) # Resource limits: $4,000 for 1 person, $6,000 for 2+ persons capped_size = min_(size, p.max_unit_size) - limit = p.resource_limit[capped_size] + limit = p.resources.limit[capped_size] return countable_resources <= limit diff --git a/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_countable_earned_income.py b/policyengine_us/variables/gov/states/ne/dhhs/adc/income/ne_adc_countable_earned_income.py similarity index 76% rename from policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_countable_earned_income.py rename to policyengine_us/variables/gov/states/ne/dhhs/adc/income/ne_adc_countable_earned_income.py index a1a1267434c..de264674e9b 100644 --- a/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc_countable_earned_income.py +++ b/policyengine_us/variables/gov/states/ne/dhhs/adc/income/ne_adc_countable_earned_income.py @@ -7,7 +7,9 @@ class ne_adc_countable_earned_income(Variable): label = "Nebraska ADC countable earned income" unit = USD definition_period = MONTH - reference = "https://nebraskalegislature.gov/laws/statutes.php?statute=68-1726" + reference = ( + "https://nebraskalegislature.gov/laws/statutes.php?statute=68-1726" + ) defined_for = StateCode.NE def formula(spm_unit, period, parameters): @@ -15,4 +17,4 @@ def formula(spm_unit, period, parameters): gross_earned = add(spm_unit, period, ["tanf_gross_earned_income"]) # Per Neb. Rev. Stat. 68-1726(3)(a)(ii): 50% of gross earned income # is disregarded for recipients - return gross_earned * (1 - p.earned_income_disregard) + return gross_earned * (1 - p.income.earned_income_disregard) From a02398a51c376afd3940466801633b864793cbdb Mon Sep 17 00:00:00 2001 From: Ziming Date: Tue, 23 Dec 2025 22:10:28 -0500 Subject: [PATCH 5/8] minor --- .../gov/states/ne/dhhs/adc/edge_cases.yaml | 26 ++++++++++++++++--- .../gov/states/ne/dhhs/adc/integration.yaml | 7 +++++ .../gov/states/ne/dhhs/adc/ne_adc.yaml | 6 +++++ .../adc/benefit/ne_adc_payment_standard.py | 3 +-- .../adc/eligibility/ne_adc_income_eligible.py | 4 +-- .../adc/income/ne_adc_countable_income.py | 18 +++++++++++++ 6 files changed, 56 insertions(+), 8 deletions(-) create mode 100644 policyengine_us/variables/gov/states/ne/dhhs/adc/income/ne_adc_countable_income.py diff --git a/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/edge_cases.yaml b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/edge_cases.yaml index 557cc58bc74..85fc62c9ece 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/edge_cases.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/edge_cases.yaml @@ -18,6 +18,7 @@ - name: Case 1, income exactly at need standard threshold is ineligible. # Tests strict less-than comparison: countable_income < need_standard period: 2024-01 + absolute_error_margin: 0.5 input: people: person1: @@ -45,6 +46,7 @@ - name: Case 2, income one dollar below need standard threshold. period: 2024-01 + absolute_error_margin: 0.5 input: people: person1: @@ -71,6 +73,7 @@ - name: Case 3, income one dollar above need standard threshold. period: 2024-01 + absolute_error_margin: 0.5 input: people: person1: @@ -102,6 +105,7 @@ - name: Case 4, resources exactly at $4,000 limit for single person. period: 2024-01 + absolute_error_margin: 0.5 input: people: person1: @@ -122,6 +126,7 @@ - name: Case 5, resources one dollar above $4,000 limit for single person. period: 2024-01 + absolute_error_margin: 0.5 input: people: person1: @@ -147,6 +152,7 @@ - name: Case 6, resources exactly at $6,000 limit for family of 2. period: 2024-01 + absolute_error_margin: 0.5 input: people: person1: @@ -170,6 +176,7 @@ - name: Case 7, resources one dollar above $6,000 limit for family of 2. period: 2024-01 + absolute_error_margin: 0.5 input: people: person1: @@ -197,6 +204,7 @@ - name: Case 8, zero earned income. period: 2024-01 + absolute_error_margin: 0.5 input: people: person1: @@ -219,6 +227,7 @@ - name: Case 9, zero resources. period: 2024-01 + absolute_error_margin: 0.5 input: people: person1: @@ -245,6 +254,7 @@ - name: Case 10, minimum family size of 1. period: 2024-01 + absolute_error_margin: 0.5 input: people: person1: @@ -267,6 +277,7 @@ - name: Case 11, maximum family size of 14. period: 2024-01 + absolute_error_margin: 0.5 input: people: person1: @@ -314,6 +325,7 @@ - name: Case 12, family size 15 exceeds parameter table caps at 14. period: 2024-01 + absolute_error_margin: 0.5 input: people: person1: @@ -367,7 +379,7 @@ - name: Case 13, benefit exactly at $10 minimum threshold. period: 2024-01 - absolute_error_margin: 0.1 + absolute_error_margin: 0.5 input: people: person1: @@ -399,7 +411,7 @@ # Per Neb. Rev. Stat. 43-512: no payments less than $10/month # If benefit > 0 but < $10, return $10 period: 2024-01 - absolute_error_margin: 0.1 + absolute_error_margin: 0.5 input: people: person1: @@ -427,7 +439,7 @@ - name: Case 15, calculated benefit of $5 is below minimum rounds up to $10. period: 2024-01 - absolute_error_margin: 0.1 + absolute_error_margin: 0.5 input: people: person1: @@ -454,6 +466,7 @@ - name: Case 16, zero benefit from ineligibility stays zero not minimum. period: 2024-01 + absolute_error_margin: 0.5 input: people: person1: @@ -581,6 +594,7 @@ - name: Case 20, very small earned income disregard applied. period: 2024-01 + absolute_error_margin: 0.5 input: people: person1: @@ -603,6 +617,7 @@ - name: Case 21, large earned income 50 percent disregard. period: 2024-01 + absolute_error_margin: 0.5 input: people: person1: @@ -693,6 +708,7 @@ # Need unearned = $881 - $300 = $581, but that makes countable >= need_standard # For strict <, need total < $881 period: 2024-01 + absolute_error_margin: 0.5 input: people: person1: @@ -726,6 +742,7 @@ - name: Case 25, resources one dollar below $4,000 limit for single person. period: 2024-01 + absolute_error_margin: 0.5 input: people: person1: @@ -746,6 +763,7 @@ - name: Case 26, resources one dollar below $6,000 limit for family of 2. period: 2024-01 + absolute_error_margin: 0.5 input: people: person1: @@ -775,6 +793,7 @@ # Two adults (ages 30 and 35) with no children or pregnant persons # Fails is_demographic_tanf_eligible because no one meets age limit period: 2024-01 + absolute_error_margin: 0.5 input: people: person1: @@ -808,6 +827,7 @@ # Family in Texas should get zero Nebraska ADC benefit # The defined_for = StateCode.NE constraint applies period: 2024-01 + absolute_error_margin: 0.5 input: people: person1: diff --git a/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/integration.yaml index 2be998f8881..d62fb587d19 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/integration.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/integration.yaml @@ -13,6 +13,7 @@ - name: Case 1, family of 3 with no income receives maximum benefit. period: 2024-01 + absolute_error_margin: 0.5 input: people: person1: @@ -49,6 +50,7 @@ - name: Case 2, family of 3 with earned income receives partial benefit. period: 2024-01 + absolute_error_margin: 0.5 input: people: person1: @@ -85,6 +87,7 @@ - name: Case 3, family of 4 with unearned income. period: 2024-01 + absolute_error_margin: 0.5 input: people: person1: @@ -125,6 +128,7 @@ - name: Case 4, family above income limit is ineligible. period: 2024-01 + absolute_error_margin: 0.5 input: people: person1: @@ -159,6 +163,7 @@ - name: Case 5, family of 2 near income threshold. period: 2024-01 + absolute_error_margin: 0.5 input: people: person1: @@ -195,6 +200,7 @@ - name: Case 6, family with both earned and unearned income. period: 2024-01 + absolute_error_margin: 0.5 input: people: person1: @@ -232,6 +238,7 @@ - name: Case 7, minimum payment rule applies. period: 2024-01 + absolute_error_margin: 0.5 input: people: person1: diff --git a/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc.yaml b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc.yaml index bb13366769d..3066743708c 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc.yaml @@ -8,6 +8,7 @@ - name: Case 1, no income receives maximum benefit. period: 2024-01 + absolute_error_margin: 0.5 input: people: person1: @@ -33,6 +34,7 @@ - name: Case 2, earned income reduces benefit. period: 2024-01 + absolute_error_margin: 0.5 input: people: person1: @@ -59,6 +61,7 @@ - name: Case 3, unearned income reduces benefit. period: 2024-01 + absolute_error_margin: 0.5 input: people: person1: @@ -85,6 +88,7 @@ - name: Case 4, income too high gets zero benefit. period: 2024-01 + absolute_error_margin: 0.5 input: people: person1: @@ -108,6 +112,7 @@ - name: Case 5, minimum payment rule applies. period: 2024-01 + absolute_error_margin: 0.5 input: people: person1: @@ -134,6 +139,7 @@ - name: Case 6, benefit just above minimum. period: 2024-01 + absolute_error_margin: 0.5 input: people: person1: diff --git a/policyengine_us/variables/gov/states/ne/dhhs/adc/benefit/ne_adc_payment_standard.py b/policyengine_us/variables/gov/states/ne/dhhs/adc/benefit/ne_adc_payment_standard.py index 5d147eee891..e56001a3b23 100644 --- a/policyengine_us/variables/gov/states/ne/dhhs/adc/benefit/ne_adc_payment_standard.py +++ b/policyengine_us/variables/gov/states/ne/dhhs/adc/benefit/ne_adc_payment_standard.py @@ -16,5 +16,4 @@ def formula(spm_unit, period, parameters): p = parameters(period).gov.states.ne.dhhs.adc need_standard = spm_unit("ne_adc_need_standard", period) # Per Neb. Rev. Stat. 43-512: payment is 55% of standard of need - # Rounded to whole dollars - return np.ceil(need_standard * p.benefit.payment_standard_rate) + return need_standard * p.benefit.payment_standard_rate diff --git a/policyengine_us/variables/gov/states/ne/dhhs/adc/eligibility/ne_adc_income_eligible.py b/policyengine_us/variables/gov/states/ne/dhhs/adc/eligibility/ne_adc_income_eligible.py index 54eea4857fd..da10b768533 100644 --- a/policyengine_us/variables/gov/states/ne/dhhs/adc/eligibility/ne_adc_income_eligible.py +++ b/policyengine_us/variables/gov/states/ne/dhhs/adc/eligibility/ne_adc_income_eligible.py @@ -14,8 +14,6 @@ class ne_adc_income_eligible(Variable): def formula(spm_unit, period, parameters): # Per 468 NAC: countable income must be below standard of need - countable_earned = spm_unit("ne_adc_countable_earned_income", period) - unearned = add(spm_unit, period, ["tanf_gross_unearned_income"]) - countable_income = countable_earned + unearned + countable_income = spm_unit("ne_adc_countable_income", period) need_standard = spm_unit("ne_adc_need_standard", period) return countable_income < need_standard diff --git a/policyengine_us/variables/gov/states/ne/dhhs/adc/income/ne_adc_countable_income.py b/policyengine_us/variables/gov/states/ne/dhhs/adc/income/ne_adc_countable_income.py new file mode 100644 index 00000000000..6344071ac7f --- /dev/null +++ b/policyengine_us/variables/gov/states/ne/dhhs/adc/income/ne_adc_countable_income.py @@ -0,0 +1,18 @@ +from policyengine_us.model_api import * + + +class ne_adc_countable_income(Variable): + value_type = float + entity = SPMUnit + label = "Nebraska ADC countable income" + unit = USD + definition_period = MONTH + reference = ( + "https://nebraskalegislature.gov/laws/statutes.php?statute=68-1726", + "https://nebraskalegislature.gov/laws/statutes.php?statute=68-1713", + ) + defined_for = StateCode.NE + adds = [ + "ne_adc_countable_earned_income", + "tanf_gross_unearned_income", + ] From a848a267a1ef54fde3c113038ecb90aafc2b4e24 Mon Sep 17 00:00:00 2001 From: Ziming Date: Thu, 25 Dec 2025 12:14:15 -0500 Subject: [PATCH 6/8] adjustments --- changelog_entry.yaml | 4 +- .../adc/benefit/payment_standard_rate.yaml | 4 +- .../standard_of_need/additional_person.yaml | 17 + .../amount.yaml} | 26 +- .../earned_income_disregard/initial.yaml | 12 + .../ongoing.yaml} | 4 +- .../gov/states/ne/dhhs/adc/max_unit_size.yaml | 2 +- .../gov/states/ne/dhhs/adc/min_payment.yaml | 12 - .../states/ne/dhhs/adc/resources/limit.yaml | 45 +- .../gov/states/ne/dhhs/adc/edge_cases.yaml | 848 ------------------ .../gov/states/ne/dhhs/adc/integration.yaml | 198 +++- .../gov/states/ne/dhhs/adc/ne_adc.yaml | 165 +++- .../adc/ne_adc_countable_earned_income.yaml | 160 +++- .../states/ne/dhhs/adc/ne_adc_eligible.yaml | 188 +++- .../ne/dhhs/adc/ne_adc_need_standard.yaml | 125 +++ .../dhhs/adc/benefit/ne_adc_need_standard.py | 12 +- .../eligibility/ne_adc_resources_eligible.py | 3 +- .../income/ne_adc_countable_earned_income.py | 13 +- .../gov/states/ne/dhhs/adc/ne_adc.py | 11 +- sources/working_references.md | 440 --------- 20 files changed, 899 insertions(+), 1390 deletions(-) create mode 100644 policyengine_us/parameters/gov/states/ne/dhhs/adc/benefit/standard_of_need/additional_person.yaml rename policyengine_us/parameters/gov/states/ne/dhhs/adc/benefit/{need_standard.yaml => standard_of_need/amount.yaml} (55%) create mode 100644 policyengine_us/parameters/gov/states/ne/dhhs/adc/income/earned_income_disregard/initial.yaml rename policyengine_us/parameters/gov/states/ne/dhhs/adc/income/{earned_income_disregard.yaml => earned_income_disregard/ongoing.yaml} (50%) delete mode 100644 policyengine_us/parameters/gov/states/ne/dhhs/adc/min_payment.yaml delete mode 100644 policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/edge_cases.yaml delete mode 100644 sources/working_references.md diff --git a/changelog_entry.yaml b/changelog_entry.yaml index e092f5a7315..1a7aa318281 100644 --- a/changelog_entry.yaml +++ b/changelog_entry.yaml @@ -1,6 +1,4 @@ - bump: minor changes: added: - - Nebraska Aid to Dependent Children (ADC) program - changed: [] - fixed: [] + - Nebraska Aid to Dependent Children (ADC) program. diff --git a/policyengine_us/parameters/gov/states/ne/dhhs/adc/benefit/payment_standard_rate.yaml b/policyengine_us/parameters/gov/states/ne/dhhs/adc/benefit/payment_standard_rate.yaml index d480ff2244b..555ebd2abe9 100644 --- a/policyengine_us/parameters/gov/states/ne/dhhs/adc/benefit/payment_standard_rate.yaml +++ b/policyengine_us/parameters/gov/states/ne/dhhs/adc/benefit/payment_standard_rate.yaml @@ -1,12 +1,12 @@ description: Nebraska provides this share of the standard of need as the payment standard under the Aid to Dependent Children program. values: - 2015-09-01: 0.55 + 2015-07-01: 0.55 metadata: unit: /1 period: month label: Nebraska ADC payment standard rate reference: - - title: Neb. Rev. Stat. 43-512(1) + - title: Neb. Rev. Stat. 43-512(3) href: https://nebraskalegislature.gov/laws/statutes.php?statute=43-512 diff --git a/policyengine_us/parameters/gov/states/ne/dhhs/adc/benefit/standard_of_need/additional_person.yaml b/policyengine_us/parameters/gov/states/ne/dhhs/adc/benefit/standard_of_need/additional_person.yaml new file mode 100644 index 00000000000..ba0a6327c0e --- /dev/null +++ b/policyengine_us/parameters/gov/states/ne/dhhs/adc/benefit/standard_of_need/additional_person.yaml @@ -0,0 +1,17 @@ +description: Nebraska adds this amount to the standard of need for each person beyond unit size 10 under the Aid to Dependent Children program. + +values: + 2021-07-01: 140 + 2025-07-01: 170 + +metadata: + unit: currency-USD + period: month + label: Nebraska ADC standard of need additional person increment + reference: + - title: Neb. Rev. Stat. 43-513(1) + href: https://nebraskalegislature.gov/laws/statutes.php?statute=43-513 + - title: 468-000-209 (2021) + href: https://dhhs.ne.gov/Documents/468-000-209.pdf + - title: Title 468 NAC Chapter 3 (2025) + href: https://dhhs.ne.gov/Guidance%20Docs/Title%20468%20-%20Aid%20to%20Dependent%20Children.pdf#page=9 diff --git a/policyengine_us/parameters/gov/states/ne/dhhs/adc/benefit/need_standard.yaml b/policyengine_us/parameters/gov/states/ne/dhhs/adc/benefit/standard_of_need/amount.yaml similarity index 55% rename from policyengine_us/parameters/gov/states/ne/dhhs/adc/benefit/need_standard.yaml rename to policyengine_us/parameters/gov/states/ne/dhhs/adc/benefit/standard_of_need/amount.yaml index d719ba708ef..3ef597ae90f 100644 --- a/policyengine_us/parameters/gov/states/ne/dhhs/adc/benefit/need_standard.yaml +++ b/policyengine_us/parameters/gov/states/ne/dhhs/adc/benefit/standard_of_need/amount.yaml @@ -4,39 +4,43 @@ metadata: unit: currency-USD period: month breakdown: - - range(1, 15) + - range(1, 11) label: Nebraska ADC standard of need reference: - title: Neb. Rev. Stat. 43-513(1) href: https://nebraskalegislature.gov/laws/statutes.php?statute=43-513 - - title: Title 468 NAC Chapter 3 - href: https://dhhs.ne.gov/Pages/Title-468.aspx + - title: 468-000-209 (2021) + href: https://dhhs.ne.gov/Documents/468-000-209.pdf + - title: Title 468 NAC Chapter 3 (2025) + href: https://dhhs.ne.gov/Guidance%20Docs/Title%20468%20-%20Aid%20to%20Dependent%20Children.pdf#page=9 1: 2021-07-01: 601 + 2025-07-01: 727 2: 2021-07-01: 741 + 2025-07-01: 897 3: 2021-07-01: 881 + 2025-07-01: 1_067 4: 2021-07-01: 1_021 + 2025-07-01: 1_237 5: 2021-07-01: 1_161 + 2025-07-01: 1_407 6: 2021-07-01: 1_301 + 2025-07-01: 1_577 7: 2021-07-01: 1_441 + 2025-07-01: 1_747 8: 2021-07-01: 1_581 + 2025-07-01: 1_917 9: 2021-07-01: 1_721 + 2025-07-01: 2_087 10: 2021-07-01: 1_861 -11: - 2021-07-01: 2_001 -12: - 2021-07-01: 2_141 -13: - 2021-07-01: 2_281 -14: - 2021-07-01: 2_421 + 2025-07-01: 2_257 diff --git a/policyengine_us/parameters/gov/states/ne/dhhs/adc/income/earned_income_disregard/initial.yaml b/policyengine_us/parameters/gov/states/ne/dhhs/adc/income/earned_income_disregard/initial.yaml new file mode 100644 index 00000000000..f80f0f0048c --- /dev/null +++ b/policyengine_us/parameters/gov/states/ne/dhhs/adc/income/earned_income_disregard/initial.yaml @@ -0,0 +1,12 @@ +description: Nebraska excludes this share of earnings from countable income for initial applicants under the Aid to Dependent Children program. + +values: + 2021-07-01: 0.2 + +metadata: + unit: /1 + period: month + label: Nebraska ADC initial earned income disregard rate + reference: + - title: Neb. Rev. Stat. 68-1726(3)(a)(i) + href: https://nebraskalegislature.gov/laws/statutes.php?statute=68-1726 diff --git a/policyengine_us/parameters/gov/states/ne/dhhs/adc/income/earned_income_disregard.yaml b/policyengine_us/parameters/gov/states/ne/dhhs/adc/income/earned_income_disregard/ongoing.yaml similarity index 50% rename from policyengine_us/parameters/gov/states/ne/dhhs/adc/income/earned_income_disregard.yaml rename to policyengine_us/parameters/gov/states/ne/dhhs/adc/income/earned_income_disregard/ongoing.yaml index 59370cd806e..90388af8b53 100644 --- a/policyengine_us/parameters/gov/states/ne/dhhs/adc/income/earned_income_disregard.yaml +++ b/policyengine_us/parameters/gov/states/ne/dhhs/adc/income/earned_income_disregard/ongoing.yaml @@ -1,4 +1,4 @@ -description: Nebraska excludes this share of gross earned income from countable income under the Aid to Dependent Children program. +description: Nebraska excludes this share of earnings from countable income for ongoing recipients under the Aid to Dependent Children program. values: 2021-07-01: 0.5 @@ -6,7 +6,7 @@ values: metadata: unit: /1 period: month - label: Nebraska ADC earned income disregard rate + label: Nebraska ADC ongoing earned income disregard rate reference: - title: Neb. Rev. Stat. 68-1726(3)(a)(ii) href: https://nebraskalegislature.gov/laws/statutes.php?statute=68-1726 diff --git a/policyengine_us/parameters/gov/states/ne/dhhs/adc/max_unit_size.yaml b/policyengine_us/parameters/gov/states/ne/dhhs/adc/max_unit_size.yaml index eb4b0a645f9..ff6d5daa7ce 100644 --- a/policyengine_us/parameters/gov/states/ne/dhhs/adc/max_unit_size.yaml +++ b/policyengine_us/parameters/gov/states/ne/dhhs/adc/max_unit_size.yaml @@ -1,7 +1,7 @@ description: Nebraska sets this as the maximum unit size for benefit calculations under the Aid to Dependent Children program. values: - 2021-07-01: 14 + 2021-07-01: 10 metadata: unit: /1 diff --git a/policyengine_us/parameters/gov/states/ne/dhhs/adc/min_payment.yaml b/policyengine_us/parameters/gov/states/ne/dhhs/adc/min_payment.yaml deleted file mode 100644 index 7cd413696c4..00000000000 --- a/policyengine_us/parameters/gov/states/ne/dhhs/adc/min_payment.yaml +++ /dev/null @@ -1,12 +0,0 @@ -description: Nebraska provides at least this amount as the minimum monthly payment under the Aid to Dependent Children program. - -values: - 2021-07-01: 10 - -metadata: - unit: currency-USD - period: month - label: Nebraska ADC minimum payment - reference: - - title: Neb. Rev. Stat. 43-512(1) - href: https://nebraskalegislature.gov/laws/statutes.php?statute=43-512 diff --git a/policyengine_us/parameters/gov/states/ne/dhhs/adc/resources/limit.yaml b/policyengine_us/parameters/gov/states/ne/dhhs/adc/resources/limit.yaml index 5ef4574192f..57ff15172ad 100644 --- a/policyengine_us/parameters/gov/states/ne/dhhs/adc/resources/limit.yaml +++ b/policyengine_us/parameters/gov/states/ne/dhhs/adc/resources/limit.yaml @@ -1,42 +1,21 @@ description: Nebraska limits countable resources to this amount under the Aid to Dependent Children program. metadata: - unit: currency-USD + type: single_amount + threshold_unit: person + amount_unit: currency-USD period: month - breakdown: - - range(1, 15) label: Nebraska ADC resource limit reference: - title: Neb. Rev. Stat. 68-1726(1) href: https://nebraskalegislature.gov/laws/statutes.php?statute=68-1726 - - title: Neb. Rev. Stat. 68-1713 - href: https://nebraskalegislature.gov/laws/statutes.php?statute=68-1713 -1: - 2021-07-01: 4_000 -2: - 2021-07-01: 6_000 -3: - 2021-07-01: 6_000 -4: - 2021-07-01: 6_000 -5: - 2021-07-01: 6_000 -6: - 2021-07-01: 6_000 -7: - 2021-07-01: 6_000 -8: - 2021-07-01: 6_000 -9: - 2021-07-01: 6_000 -10: - 2021-07-01: 6_000 -11: - 2021-07-01: 6_000 -12: - 2021-07-01: 6_000 -13: - 2021-07-01: 6_000 -14: - 2021-07-01: 6_000 +brackets: + - threshold: + 2021-07-01: 1 + amount: + 2021-07-01: 4_000 + - threshold: + 2021-07-01: 2 + amount: + 2021-07-01: 6_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/edge_cases.yaml b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/edge_cases.yaml deleted file mode 100644 index 85fc62c9ece..00000000000 --- a/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/edge_cases.yaml +++ /dev/null @@ -1,848 +0,0 @@ -# Nebraska ADC Edge Case Tests -# Auto-generated edge case tests for comprehensive boundary coverage -# -# Key Formulas: -# Need Standard: Lookup by family size (1-14), capped at 14 -# Payment Standard: Need Standard * 0.55 -# Countable Earned: Gross Earned * 0.50 (50% disregard) -# Income Eligible: (countable_earned + unearned) < need_standard -# Resources Eligible: resources <= limit ($4,000 for 1, $6,000 for 2+) -# Maximum Benefit: min(gap, payment_standard) where gap = need_standard - countable_earned -# Final Benefit: max(max_benefit - unearned, 0) -# Minimum Rule: If final_benefit < $10, return $0 - -# ============================================================================= -# INCOME BOUNDARY TESTS -# ============================================================================= - -- name: Case 1, income exactly at need standard threshold is ineligible. - # Tests strict less-than comparison: countable_income < need_standard - period: 2024-01 - absolute_error_margin: 0.5 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 17_784 # $1,482/month -> $741 countable - person2: - age: 10 - spm_units: - spm_unit: - members: [person1, person2] - spm_unit_assets: 1_000 - households: - household: - members: [person1, person2] - state_code: NE - output: - ne_adc_need_standard: 741 - ne_adc_countable_earned_income: 741 - # Gross: $17,784/12 = $1,482/month - # After 50% disregard: $1,482 * 0.50 = $741 - ne_adc_income_eligible: false - # Countable ($741) < Need Standard ($741) -> false (not strictly less) - ne_adc_eligible: false - ne_adc: 0 - -- name: Case 2, income one dollar below need standard threshold. - period: 2024-01 - absolute_error_margin: 0.5 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 17_760 # $1,480/month -> $740 countable - person2: - age: 10 - spm_units: - spm_unit: - members: [person1, person2] - spm_unit_assets: 1_000 - households: - household: - members: [person1, person2] - state_code: NE - output: - ne_adc_need_standard: 741 - ne_adc_countable_earned_income: 740 - # Gross: $17,760/12 = $1,480/month - # After 50% disregard: $1,480 * 0.50 = $740 - ne_adc_income_eligible: true - # Countable ($740) < Need Standard ($741) -> true - ne_adc_eligible: true - -- name: Case 3, income one dollar above need standard threshold. - period: 2024-01 - absolute_error_margin: 0.5 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 17_808 # $1,484/month -> $742 countable - person2: - age: 10 - spm_units: - spm_unit: - members: [person1, person2] - spm_unit_assets: 1_000 - households: - household: - members: [person1, person2] - state_code: NE - output: - ne_adc_need_standard: 741 - ne_adc_countable_earned_income: 742 - # Gross: $17,808/12 = $1,484/month - # After 50% disregard: $1,484 * 0.50 = $742 - ne_adc_income_eligible: false - # Countable ($742) < Need Standard ($741) -> false - ne_adc_eligible: false - ne_adc: 0 - -# ============================================================================= -# RESOURCE BOUNDARY TESTS - SINGLE PERSON ($4,000 limit) -# ============================================================================= - -- name: Case 4, resources exactly at $4,000 limit for single person. - period: 2024-01 - absolute_error_margin: 0.5 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 0 - spm_units: - spm_unit: - members: [person1] - spm_unit_assets: 4_000 - households: - household: - members: [person1] - state_code: NE - output: - spm_unit_size: 1 - ne_adc_resources_eligible: true - # Resources ($4,000) <= Limit ($4,000) -> true - -- name: Case 5, resources one dollar above $4,000 limit for single person. - period: 2024-01 - absolute_error_margin: 0.5 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 0 - spm_units: - spm_unit: - members: [person1] - spm_unit_assets: 4_001 - households: - household: - members: [person1] - state_code: NE - output: - spm_unit_size: 1 - ne_adc_resources_eligible: false - # Resources ($4,001) <= Limit ($4,000) -> false - ne_adc_eligible: false - -# ============================================================================= -# RESOURCE BOUNDARY TESTS - TWO+ PERSONS ($6,000 limit) -# ============================================================================= - -- name: Case 6, resources exactly at $6,000 limit for family of 2. - period: 2024-01 - absolute_error_margin: 0.5 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 0 - person2: - age: 10 - spm_units: - spm_unit: - members: [person1, person2] - spm_unit_assets: 6_000 - households: - household: - members: [person1, person2] - state_code: NE - output: - spm_unit_size: 2 - ne_adc_resources_eligible: true - # Resources ($6,000) <= Limit ($6,000) -> true - ne_adc_eligible: true - -- name: Case 7, resources one dollar above $6,000 limit for family of 2. - period: 2024-01 - absolute_error_margin: 0.5 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 0 - person2: - age: 10 - spm_units: - spm_unit: - members: [person1, person2] - spm_unit_assets: 6_001 - households: - household: - members: [person1, person2] - state_code: NE - output: - spm_unit_size: 2 - ne_adc_resources_eligible: false - # Resources ($6,001) <= Limit ($6,000) -> false - ne_adc_eligible: false - -# ============================================================================= -# ZERO VALUE TESTS -# ============================================================================= - -- name: Case 8, zero earned income. - period: 2024-01 - absolute_error_margin: 0.5 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 0 - person2: - age: 10 - spm_units: - spm_unit: - members: [person1, person2] - spm_unit_assets: 1_000 - households: - household: - members: [person1, person2] - state_code: NE - output: - ne_adc_countable_earned_income: 0 - ne_adc_income_eligible: true - ne_adc_eligible: true - -- name: Case 9, zero resources. - period: 2024-01 - absolute_error_margin: 0.5 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 0 - person2: - age: 10 - spm_units: - spm_unit: - members: [person1, person2] - spm_unit_assets: 0 - households: - household: - members: [person1, person2] - state_code: NE - output: - ne_adc_resources_eligible: true - # Resources ($0) <= Limit ($6,000) -> true - ne_adc_eligible: true - -# ============================================================================= -# FAMILY SIZE BOUNDARY TESTS -# ============================================================================= - -- name: Case 10, minimum family size of 1. - period: 2024-01 - absolute_error_margin: 0.5 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 0 - spm_units: - spm_unit: - members: [person1] - spm_unit_assets: 1_000 - households: - household: - members: [person1] - state_code: NE - output: - spm_unit_size: 1 - ne_adc_need_standard: 601 - # Need standard for size 1 = $601 - ne_adc_payment_standard: 331 - # Payment standard = $601 * 0.55 = $330.55, rounded up to $331 - -- name: Case 11, maximum family size of 14. - period: 2024-01 - absolute_error_margin: 0.5 - input: - people: - person1: - age: 35 - person2: - age: 33 - person3: - age: 17 - person4: - age: 16 - person5: - age: 15 - person6: - age: 14 - person7: - age: 13 - person8: - age: 12 - person9: - age: 11 - person10: - age: 10 - person11: - age: 9 - person12: - age: 8 - person13: - age: 7 - person14: - age: 6 - spm_units: - spm_unit: - members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10, person11, person12, person13, person14] - spm_unit_assets: 1_000 - households: - household: - members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10, person11, person12, person13, person14] - state_code: NE - output: - spm_unit_size: 14 - ne_adc_need_standard: 2_421 - # Need standard for size 14 = $2,421 - ne_adc_payment_standard: 1_332 - # Payment standard = $2,421 * 0.55 = $1,331.55, rounded up to $1,332 - -- name: Case 12, family size 15 exceeds parameter table caps at 14. - period: 2024-01 - absolute_error_margin: 0.5 - input: - people: - person1: - age: 35 - person2: - age: 33 - person3: - age: 17 - person4: - age: 16 - person5: - age: 15 - person6: - age: 14 - person7: - age: 13 - person8: - age: 12 - person9: - age: 11 - person10: - age: 10 - person11: - age: 9 - person12: - age: 8 - person13: - age: 7 - person14: - age: 6 - person15: - age: 5 - spm_units: - spm_unit: - members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10, person11, person12, person13, person14, person15] - spm_unit_assets: 1_000 - households: - household: - members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10, person11, person12, person13, person14, person15] - state_code: NE - output: - spm_unit_size: 15 - ne_adc_need_standard: 2_421 - # Size 15 capped to 14, need standard for size 14 = $2,421 - ne_adc_payment_standard: 1_332 - # Payment standard = $2,421 * 0.55 = $1,331.55, rounded up to $1,332 - -# ============================================================================= -# MINIMUM PAYMENT RULE TESTS -# ============================================================================= - -- name: Case 13, benefit exactly at $10 minimum threshold. - period: 2024-01 - absolute_error_margin: 0.5 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 0 - social_security: 3_846.60 # $320.55/month unearned - person2: - age: 10 - spm_units: - spm_unit: - members: [person1, person2] - spm_unit_assets: 1_000 - households: - household: - members: [person1, person2] - state_code: NE - output: - ne_adc_need_standard: 741 - ne_adc_payment_standard: 408 - # Payment standard = $741 * 0.55 = $407.55, rounded up to $408 - ne_adc_maximum_benefit: 408 - # Gap = $741 - $0 = $741 - # Benefit = min($741, $408) = $408 - ne_adc: 87.45 - # Final = $408 - $320.55 = $87.45 - # $87.45 >= $10 minimum -> $87.45 - -- name: Case 14, benefit below $10 minimum rounds up to $10. - # Per Neb. Rev. Stat. 43-512: no payments less than $10/month - # If benefit > 0 but < $10, return $10 - period: 2024-01 - absolute_error_margin: 0.5 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 0 - social_security: 4_800 # $400/month unearned - person2: - age: 10 - spm_units: - spm_unit: - members: [person1, person2] - spm_unit_assets: 1_000 - households: - household: - members: [person1, person2] - state_code: NE - output: - ne_adc_need_standard: 741 - ne_adc_payment_standard: 408 - # Payment standard = $741 * 0.55 = $407.55, rounded up to $408 - ne_adc_maximum_benefit: 408 - ne_adc: 10 - # Final = $408 - $400 = $8 - # $8 < $10 minimum, but > $0 -> rounds up to $10 - -- name: Case 15, calculated benefit of $5 is below minimum rounds up to $10. - period: 2024-01 - absolute_error_margin: 0.5 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 0 - social_security: 4_836 # $403/month unearned - person2: - age: 10 - spm_units: - spm_unit: - members: [person1, person2] - spm_unit_assets: 1_000 - households: - household: - members: [person1, person2] - state_code: NE - output: - ne_adc_payment_standard: 408 - # Payment standard = $741 * 0.55 = $407.55, rounded up to $408 - ne_adc_maximum_benefit: 408 - ne_adc: 10 - # Final = $408 - $403 = $5 - # $5 < $10 minimum, but > $0 -> rounds up to $10 - -- name: Case 16, zero benefit from ineligibility stays zero not minimum. - period: 2024-01 - absolute_error_margin: 0.5 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 24_000 # $2,000/month -> $1,000 countable - person2: - age: 10 - spm_units: - spm_unit: - members: [person1, person2] - spm_unit_assets: 1_000 - households: - household: - members: [person1, person2] - state_code: NE - output: - ne_adc_need_standard: 741 - ne_adc_countable_earned_income: 1_000 - ne_adc_income_eligible: false - # Countable ($1,000) >= Need Standard ($741) -> ineligible - ne_adc_eligible: false - ne_adc: 0 - # Zero from ineligibility, not from minimum payment rule - -# ============================================================================= -# GAP BUDGETING EDGE CASES -# ============================================================================= - -- name: Case 17, gap less than payment standard benefit equals gap. - period: 2024-01 - absolute_error_margin: 1 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 8_400 # $700/month -> $350 countable - person2: - age: 10 - spm_units: - spm_unit: - members: [person1, person2] - spm_unit_assets: 1_000 - households: - household: - members: [person1, person2] - state_code: NE - output: - ne_adc_need_standard: 741 - ne_adc_payment_standard: 408 - # Payment standard = $741 * 0.55 = $407.55 ~ $408 - ne_adc_countable_earned_income: 350 - # Gross = $700, after 50% disregard = $350 - ne_adc_maximum_benefit: 391 - # Gap = $741 - $350 = $391 - # Benefit = min($391, $408) = $391 (gap < payment standard) - ne_adc: 391 - # Final = $391 - $0 = $391 - -- name: Case 18, gap greater than payment standard benefit equals payment standard. - period: 2024-01 - absolute_error_margin: 1 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 0 - person2: - age: 10 - spm_units: - spm_unit: - members: [person1, person2] - spm_unit_assets: 1_000 - households: - household: - members: [person1, person2] - state_code: NE - output: - ne_adc_need_standard: 741 - ne_adc_payment_standard: 408 - ne_adc_countable_earned_income: 0 - ne_adc_maximum_benefit: 408 - # Gap = $741 - $0 = $741 - # Benefit = min($741, $408) = $408 (gap > payment standard) - ne_adc: 408 - # Final = $408 - $0 = $408 - -- name: Case 19, gap equals payment standard exactly. - # Need to find earned income where gap = payment_standard - # For size 2: need_standard = $741, payment_standard = $407.55 - # Gap = need_standard - countable_earned = payment_standard - # $741 - countable = $407.55 - # countable = $333.45 - # gross * 0.50 = $333.45 -> gross = $666.90/month = $8,002.80/year - period: 2024-01 - absolute_error_margin: 1 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 8_004 # $667/month -> $333.50 countable - person2: - age: 10 - spm_units: - spm_unit: - members: [person1, person2] - spm_unit_assets: 1_000 - households: - household: - members: [person1, person2] - state_code: NE - output: - ne_adc_need_standard: 741 - ne_adc_payment_standard: 408 - ne_adc_countable_earned_income: 333.5 - # Gross = $667, after 50% disregard = $333.50 - ne_adc_maximum_benefit: 407.5 - # Gap = $741 - $333.50 = $407.50 - # Benefit = min($407.50, $407.55) = $407.50 (gap ~ payment standard) - ne_adc: 407.5 - # Final = $407.50 - $0 = $407.50 - -# ============================================================================= -# EARNED INCOME DISREGARD EDGE CASES -# ============================================================================= - -- name: Case 20, very small earned income disregard applied. - period: 2024-01 - absolute_error_margin: 0.5 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 24 # $2/month gross - person2: - age: 10 - spm_units: - spm_unit: - members: [person1, person2] - spm_unit_assets: 1_000 - households: - household: - members: [person1, person2] - state_code: NE - output: - ne_adc_countable_earned_income: 1 - # Gross = $2, after 50% disregard = $1 - ne_adc_income_eligible: true - -- name: Case 21, large earned income 50 percent disregard. - period: 2024-01 - absolute_error_margin: 0.5 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 60_000 # $5,000/month gross - person2: - age: 10 - spm_units: - spm_unit: - members: [person1, person2] - spm_unit_assets: 1_000 - households: - household: - members: [person1, person2] - state_code: NE - output: - ne_adc_countable_earned_income: 2_500 - # Gross = $5,000, after 50% disregard = $2,500 - ne_adc_income_eligible: false - # Countable ($2,500) >= Need Standard ($741) -> ineligible - ne_adc_eligible: false - -# ============================================================================= -# UNEARNED INCOME EDGE CASES -# ============================================================================= - -- name: Case 22, unearned income exactly wipes out max benefit. - period: 2024-01 - absolute_error_margin: 1 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 0 - social_security: 4_896 # $408/month unearned = payment standard - person2: - age: 10 - spm_units: - spm_unit: - members: [person1, person2] - spm_unit_assets: 1_000 - households: - household: - members: [person1, person2] - state_code: NE - output: - ne_adc_payment_standard: 408 - ne_adc_maximum_benefit: 408 - # Gap = $741 - $0 = $741 - # Benefit = min($741, $408) = $408 - ne_adc: 0 - # Final = $408 - $408 = $0 - # Would be $0 anyway (no negative benefits) - -- name: Case 23, unearned income exceeds max benefit no negative. - period: 2024-01 - absolute_error_margin: 1 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 0 - social_security: 6_000 # $500/month unearned > payment standard - person2: - age: 10 - spm_units: - spm_unit: - members: [person1, person2] - spm_unit_assets: 1_000 - households: - household: - members: [person1, person2] - state_code: NE - output: - ne_adc_payment_standard: 408 - ne_adc_maximum_benefit: 408 - ne_adc: 0 - # Final = $408 - $500 = -$92 -> $0 (no negative benefits) - -# ============================================================================= -# MIXED INCOME BOUNDARY TESTS -# ============================================================================= - -- name: Case 24, mixed income exactly at threshold. - # Countable = earned_after_disregard + unearned = need_standard - # For size 3: need_standard = $881 - # Say earned = $600/month -> countable_earned = $300 - # Need unearned = $881 - $300 = $581, but that makes countable >= need_standard - # For strict <, need total < $881 - period: 2024-01 - absolute_error_margin: 0.5 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 8_400 # $700/month -> $350 countable earned - social_security: 6_372 # $531/month unearned - person2: - age: 10 - person3: - age: 8 - spm_units: - spm_unit: - members: [person1, person2, person3] - spm_unit_assets: 1_000 - households: - household: - members: [person1, person2, person3] - state_code: NE - output: - ne_adc_need_standard: 881 - ne_adc_countable_earned_income: 350 - # Gross = $700, after 50% disregard = $350 - ne_adc_income_eligible: false - # Total countable = $350 + $531 = $881 - # Countable ($881) < Need Standard ($881) -> false - ne_adc_eligible: false - -# ============================================================================= -# RESOURCE BOUNDARY TESTS - ONE DOLLAR BELOW THRESHOLD -# ============================================================================= - -- name: Case 25, resources one dollar below $4,000 limit for single person. - period: 2024-01 - absolute_error_margin: 0.5 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 0 - spm_units: - spm_unit: - members: [person1] - spm_unit_assets: 3_999 - households: - household: - members: [person1] - state_code: NE - output: - spm_unit_size: 1 - ne_adc_resources_eligible: true - # Resources ($3,999) <= Limit ($4,000) -> true - -- name: Case 26, resources one dollar below $6,000 limit for family of 2. - period: 2024-01 - absolute_error_margin: 0.5 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 0 - person2: - age: 10 - spm_units: - spm_unit: - members: [person1, person2] - spm_unit_assets: 5_999 - households: - household: - members: [person1, person2] - state_code: NE - output: - spm_unit_size: 2 - ne_adc_resources_eligible: true - # Resources ($5,999) <= Limit ($6,000) -> true - ne_adc_eligible: true - -# ============================================================================= -# DEMOGRAPHIC ELIGIBILITY EDGE CASES -# ============================================================================= - -- name: Case 27, household with only adults fails demographic eligibility. - # Two adults (ages 30 and 35) with no children or pregnant persons - # Fails is_demographic_tanf_eligible because no one meets age limit - period: 2024-01 - absolute_error_margin: 0.5 - input: - people: - person1: - age: 30 - is_pregnant: false - employment_income_before_lsr: 0 - person2: - age: 35 - is_pregnant: false - employment_income_before_lsr: 0 - spm_units: - spm_unit: - members: [person1, person2] - spm_unit_assets: 1_000 - households: - household: - members: [person1, person2] - state_code: NE - output: - is_demographic_tanf_eligible: false - # No eligible children (both adults over age limit) and no pregnant persons - ne_adc_eligible: false - # Fails demographic eligibility even if income/resources pass - ne_adc: 0 - -# ============================================================================= -# STATE RESIDENCY EDGE CASES -# ============================================================================= - -- name: Case 28, non-Nebraska state returns zero benefit. - # Family in Texas should get zero Nebraska ADC benefit - # The defined_for = StateCode.NE constraint applies - period: 2024-01 - absolute_error_margin: 0.5 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 0 - person2: - age: 10 - spm_units: - spm_unit: - members: [person1, person2] - spm_unit_assets: 1_000 - households: - household: - members: [person1, person2] - state_code: TX - output: - ne_adc: 0 - # Family in Texas, not Nebraska -> ne_adc benefit is $0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/integration.yaml index d62fb587d19..afc772a54bc 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/integration.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/integration.yaml @@ -1,15 +1,19 @@ # Nebraska ADC (Aid to Dependent Children) Integration Tests # Gap Budgeting Methodology: -# Step 1: Net Earned Income = Gross Earned * (1 - 0.50) = Gross Earned * 0.50 +# Step 1: Net Earned Income = Gross Earned * (1 - disregard_rate) +# - Initial applicants: 20% disregard (countable = 80%) +# - Ongoing recipients: 50% disregard (countable = 50%) # Step 2: Gap = Need Standard - Net Earned Income # Step 3: Benefit = min(Gap, Payment Standard) # Step 4: Final Benefit = Benefit - Unearned Income -# Step 5: Apply minimum payment ($10) if benefit > 0 but < $10 # # Income Standards (July 2021): # Size 2: Need Standard = $741, Payment Standard = $408 # Size 3: Need Standard = $881, Payment Standard = $485 # Size 4: Need Standard = $1,021, Payment Standard = $562 +# +# NOTE: These tests model ONGOING recipients (is_tanf_enrolled: true) +# who receive the 50% earned income disregard. - name: Case 1, family of 3 with no income receives maximum benefit. period: 2024-01 @@ -28,6 +32,7 @@ spm_unit: members: [person1, person2, person3] spm_unit_assets: 1_000 + is_tanf_enrolled: true households: household: members: [person1, person2, person3] @@ -65,6 +70,7 @@ spm_unit: members: [person1, person2, person3] spm_unit_assets: 2_000 + is_tanf_enrolled: true households: household: members: [person1, person2, person3] @@ -106,6 +112,7 @@ spm_unit: members: [person1, person2, person3, person4] spm_unit_assets: 3_000 + is_tanf_enrolled: true households: household: members: [person1, person2, person3, person4] @@ -143,6 +150,7 @@ spm_unit: members: [person1, person2, person3] spm_unit_assets: 1_000 + is_tanf_enrolled: true households: household: members: [person1, person2, person3] @@ -176,6 +184,7 @@ spm_unit: members: [person1, person2] spm_unit_assets: 1_000 + is_tanf_enrolled: true households: household: members: [person1, person2] @@ -196,7 +205,6 @@ ne_adc: 41 # Gap = $741 - $700 = $41 # Benefit = min($41, $408) = $41 - # $41 > $10 minimum, so benefit = $41 - name: Case 6, family with both earned and unearned income. period: 2024-01 @@ -216,6 +224,7 @@ spm_unit: members: [person1, person2, person3] spm_unit_assets: 2_000 + is_tanf_enrolled: true households: household: members: [person1, person2, person3] @@ -236,7 +245,7 @@ # Benefit = min($581, $485) = $485 # Final = $485 - $200 = $285 -- name: Case 7, minimum payment rule applies. +- name: Case 7, small benefit after unearned income deduction. period: 2024-01 absolute_error_margin: 0.5 input: @@ -252,6 +261,7 @@ spm_unit: members: [person1, person2] spm_unit_assets: 1_000 + is_tanf_enrolled: true households: household: members: [person1, person2] @@ -268,8 +278,184 @@ ne_adc_income_eligible: true # Countable income ($730) < Need standard ($741) -> Eligible ne_adc_eligible: true - ne_adc: 10 + ne_adc: 8 # Gap = $741 - $330 = $411 # Benefit = min($411, $408) = $408 # Final = $408 - $400 = $8 - # $8 < $10 minimum, so benefit = $10 + +# ============================================================================= +# EDGE CASES - INCOME BOUNDARY TESTS +# ============================================================================= + +- name: Edge case, income exactly at need standard threshold is ineligible. + # Tests strict less-than comparison: countable_income < need_standard + period: 2024-01 + absolute_error_margin: 0.5 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 17_784 # $1,482/month -> $741 countable + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 1_000 + is_tanf_enrolled: true + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc_need_standard: 741 + ne_adc_countable_earned_income: 741 + # Gross: $17,784/12 = $1,482/month + # After 50% disregard (ongoing recipient): $1,482 * 0.50 = $741 + ne_adc_income_eligible: false + # Countable ($741) < Need Standard ($741) -> false (not strictly less) + ne_adc_eligible: false + ne_adc: 0 + +- name: Edge case, income one dollar below need standard threshold. + period: 2024-01 + absolute_error_margin: 0.5 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 17_760 # $1,480/month -> $740 countable + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 1_000 + is_tanf_enrolled: true + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc_need_standard: 741 + ne_adc_countable_earned_income: 740 + # Gross: $17,760/12 = $1,480/month + # After 50% disregard (ongoing recipient): $1,480 * 0.50 = $740 + ne_adc_income_eligible: true + # Countable ($740) < Need Standard ($741) -> true + ne_adc_eligible: true + +- name: Edge case, income one dollar above need standard threshold. + period: 2024-01 + absolute_error_margin: 0.5 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 17_808 # $1,484/month -> $742 countable + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 1_000 + is_tanf_enrolled: true + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc_need_standard: 741 + ne_adc_countable_earned_income: 742 + # Gross: $17,808/12 = $1,484/month + # After 50% disregard (ongoing recipient): $1,484 * 0.50 = $742 + ne_adc_income_eligible: false + # Countable ($742) < Need Standard ($741) -> false + ne_adc_eligible: false + ne_adc: 0 + +# ============================================================================= +# EDGE CASES - ZERO VALUE TESTS +# ============================================================================= + +- name: Edge case, zero earned income. + period: 2024-01 + absolute_error_margin: 0.5 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 0 + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 1_000 + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc_countable_earned_income: 0 + ne_adc_income_eligible: true + ne_adc_eligible: true + +- name: Edge case, zero resources. + period: 2024-01 + absolute_error_margin: 0.5 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 0 + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 0 + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc_resources_eligible: true + # Resources ($0) <= Limit ($6,000) -> true + ne_adc_eligible: true + +# ============================================================================= +# EDGE CASES - MIXED INCOME BOUNDARY +# ============================================================================= + +- name: Edge case, mixed income exactly at threshold. + # Countable = earned_after_disregard + unearned = need_standard + period: 2024-01 + absolute_error_margin: 0.5 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 8_400 # $700/month -> $350 countable earned + social_security: 6_372 # $531/month unearned + person2: + age: 10 + person3: + age: 8 + spm_units: + spm_unit: + members: [person1, person2, person3] + spm_unit_assets: 1_000 + is_tanf_enrolled: true + households: + household: + members: [person1, person2, person3] + state_code: NE + output: + ne_adc_need_standard: 881 + ne_adc_countable_earned_income: 350 + # Gross = $700, after 50% disregard (ongoing recipient) = $350 + ne_adc_income_eligible: false + # Total countable = $350 + $531 = $881 + # Countable ($881) < Need Standard ($881) -> false + ne_adc_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc.yaml b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc.yaml index 3066743708c..c6e02809c88 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc.yaml @@ -1,10 +1,14 @@ # Nebraska ADC Benefit Amount Tests # Gap Budgeting Methodology: -# Step 1: Net Earned Income = Gross Earned * 0.50 +# Step 1: Net Earned Income = Gross Earned * (1 - disregard_rate) +# - Initial applicants: 20% disregard (countable = 80%) +# - Ongoing recipients: 50% disregard (countable = 50%) # Step 2: Gap = Need Standard - Net Earned Income # Step 3: Benefit = min(Gap, Payment Standard) # Step 4: Final Benefit = Benefit - Unearned Income -# Step 5: Apply minimum payment ($10) if benefit > 0 but < $10 +# +# NOTE: These tests model ONGOING recipients (is_tanf_enrolled: true) +# who receive the 50% earned income disregard. - name: Case 1, no income receives maximum benefit. period: 2024-01 @@ -22,6 +26,7 @@ spm_unit: members: [person1, person2, person3] spm_unit_cash_assets: 1_000 + is_tanf_enrolled: true households: household: members: [person1, person2, person3] @@ -48,6 +53,7 @@ spm_unit: members: [person1, person2, person3] spm_unit_cash_assets: 1_000 + is_tanf_enrolled: true households: household: members: [person1, person2, person3] @@ -76,6 +82,7 @@ spm_unit: members: [person1, person2, person3] spm_unit_cash_assets: 1_000 + is_tanf_enrolled: true households: household: members: [person1, person2, person3] @@ -100,6 +107,7 @@ spm_unit: members: [person1, person2] spm_unit_cash_assets: 1_000 + is_tanf_enrolled: true households: household: members: [person1, person2] @@ -110,7 +118,7 @@ # Gap = $741 - $1,000 = -$259 (negative, not eligible) # Benefit = $0 -- name: Case 5, minimum payment rule applies. +- name: Case 5, small benefit after unearned income deduction. period: 2024-01 absolute_error_margin: 0.5 input: @@ -125,19 +133,19 @@ spm_unit: members: [person1, person2] spm_unit_cash_assets: 1_000 + is_tanf_enrolled: true households: household: members: [person1, person2] state_code: NE output: - ne_adc: 10 + ne_adc: 8 # Countable earned = $660 * 0.50 = $330 # Gap = $741 - $330 = $411 # Benefit = min($411, $408) = $408 # Final = $408 - $400 = $8 - # $8 < $10 minimum, so benefit = $10 -- name: Case 6, benefit just above minimum. +- name: Case 6, moderate benefit after unearned income deduction. period: 2024-01 absolute_error_margin: 0.5 input: @@ -152,6 +160,7 @@ spm_unit: members: [person1, person2] spm_unit_cash_assets: 1_000 + is_tanf_enrolled: true households: household: members: [person1, person2] @@ -162,4 +171,146 @@ # Gap = $741 - $330 = $411 # Benefit = min($411, $408) = $408 # Final = $408 - $390 = $18 - # $18 > $10 minimum, so benefit = $18 + +# ============================================================================= +# EDGE CASES - GAP BUDGETING +# ============================================================================= + +- name: Edge case, gap less than payment standard benefit equals gap. + period: 2024-01 + absolute_error_margin: 1 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 8_400 # $700/month -> $350 countable + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 1_000 + is_tanf_enrolled: true + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc_need_standard: 741 + ne_adc_payment_standard: 408 + ne_adc_countable_earned_income: 350 + # Gross = $700, after 50% disregard = $350 + ne_adc_maximum_benefit: 391 + # Gap = $741 - $350 = $391 + # Benefit = min($391, $408) = $391 (gap < payment standard) + ne_adc: 391 + +- name: Edge case, gap greater than payment standard benefit equals payment standard. + period: 2024-01 + absolute_error_margin: 1 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 0 + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 1_000 + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc_need_standard: 741 + ne_adc_payment_standard: 408 + ne_adc_countable_earned_income: 0 + ne_adc_maximum_benefit: 408 + # Gap = $741 - $0 = $741 + # Benefit = min($741, $408) = $408 (gap > payment standard) + ne_adc: 408 + +# ============================================================================= +# EDGE CASES - UNEARNED INCOME +# ============================================================================= + +- name: Edge case, unearned income exactly wipes out max benefit. + period: 2024-01 + absolute_error_margin: 1 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 0 + social_security: 4_896 # $408/month unearned = payment standard + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 1_000 + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc_payment_standard: 408 + ne_adc_maximum_benefit: 408 + # Gap = $741 - $0 = $741 + # Benefit = min($741, $408) = $408 + ne_adc: 0 + # Final = $408 - $408 = $0 + +- name: Edge case, unearned income exceeds max benefit no negative. + period: 2024-01 + absolute_error_margin: 1 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 0 + social_security: 6_000 # $500/month unearned > payment standard + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 1_000 + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc_payment_standard: 408 + ne_adc_maximum_benefit: 408 + ne_adc: 0 + # Final = $408 - $500 = -$92 -> $0 (no negative benefits) + +# ============================================================================= +# EDGE CASES - STATE RESIDENCY +# ============================================================================= + +- name: Edge case, non-Nebraska state returns zero benefit. + # Family in Texas should get zero Nebraska ADC benefit + period: 2024-01 + absolute_error_margin: 0.5 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 0 + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 1_000 + households: + household: + members: [person1, person2] + state_code: TX + output: + ne_adc: 0 + # Family in Texas, not Nebraska -> ne_adc benefit is $0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_countable_earned_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_countable_earned_income.yaml index 7abad1d5fff..375af7f552f 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_countable_earned_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_countable_earned_income.yaml @@ -1,9 +1,16 @@ # Nebraska ADC Countable Earned Income Tests -# Earned Income Disregard: 50% of gross earned income +# Per Neb. Rev. Stat. 68-1726(3)(a): +# - (i) Initial applicants: 20% disregard +# - (ii) Ongoing recipients: 50% disregard + +# ============================================================================= +# ONGOING RECIPIENT TESTS (is_tanf_enrolled: true, 50% disregard) # Countable Earned = Gross Earned * (1 - 0.50) = Gross Earned * 0.50 +# ============================================================================= -- name: Case 1, no earned income. +- name: Case 1, ongoing recipient with no earned income. period: 2024-01 + absolute_error_margin: 0.5 input: people: person1: @@ -14,6 +21,7 @@ spm_units: spm_unit: members: [person1, person2] + is_tanf_enrolled: true households: household: members: [person1, person2] @@ -21,7 +29,7 @@ output: ne_adc_countable_earned_income: 0 -- name: Case 2, earned income with 50 percent disregard. +- name: Case 2, ongoing recipient with earned income 50 percent disregard. period: 2024-01 input: people: @@ -33,6 +41,7 @@ spm_units: spm_unit: members: [person1, person2] + is_tanf_enrolled: true households: household: members: [person1, person2] @@ -42,7 +51,7 @@ # Gross earned: $12,000/12 = $1,000/month # After 50% disregard: $1,000 * 0.50 = $500 -- name: Case 3, moderate earned income. +- name: Case 3, ongoing recipient with moderate earned income. period: 2024-01 input: people: @@ -54,6 +63,7 @@ spm_units: spm_unit: members: [person1, person2] + is_tanf_enrolled: true households: household: members: [person1, person2] @@ -63,7 +73,7 @@ # Gross earned: $7,200/12 = $600/month # After 50% disregard: $600 * 0.50 = $300 -- name: Case 4, high earned income. +- name: Case 4, ongoing recipient with high earned income. period: 2024-01 input: people: @@ -75,6 +85,7 @@ spm_units: spm_unit: members: [person1, person2] + is_tanf_enrolled: true households: household: members: [person1, person2] @@ -83,3 +94,142 @@ ne_adc_countable_earned_income: 1_000 # Gross earned: $24,000/12 = $2,000/month # After 50% disregard: $2,000 * 0.50 = $1,000 + +# ============================================================================= +# INITIAL APPLICANT TESTS (is_tanf_enrolled: false, 20% disregard) +# Countable Earned = Gross Earned * (1 - 0.20) = Gross Earned * 0.80 +# ============================================================================= + +- name: Case 5, initial applicant with no earned income. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 0 + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + is_tanf_enrolled: false + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc_countable_earned_income: 0 + +- name: Case 6, initial applicant with earned income 20 percent disregard. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 12_000 # $1,000/month + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + is_tanf_enrolled: false + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc_countable_earned_income: 800 + # Gross earned: $12,000/12 = $1,000/month + # After 20% disregard: $1,000 * 0.80 = $800 + +- name: Case 7, initial applicant with moderate earned income. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 7_200 # $600/month + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + is_tanf_enrolled: false + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc_countable_earned_income: 480 + # Gross earned: $7,200/12 = $600/month + # After 20% disregard: $600 * 0.80 = $480 + +- name: Case 8, initial applicant with high earned income. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 24_000 # $2,000/month + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + is_tanf_enrolled: false + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc_countable_earned_income: 1_600 + # Gross earned: $24,000/12 = $2,000/month + # After 20% disregard: $2,000 * 0.80 = $1,600 + +# ============================================================================= +# EDGE CASES - EARNED INCOME DISREGARD +# ============================================================================= + +- name: Edge case, very small earned income disregard applied. + period: 2024-01 + absolute_error_margin: 0.5 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 24 # $2/month gross + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + is_tanf_enrolled: true + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc_countable_earned_income: 1 + # Gross = $2, after 50% disregard (ongoing recipient) = $1 + +- name: Edge case, large earned income 50 percent disregard. + period: 2024-01 + absolute_error_margin: 0.5 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 60_000 # $5,000/month gross + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + is_tanf_enrolled: true + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc_countable_earned_income: 2_500 + # Gross = $5,000, after 50% disregard (ongoing recipient) = $2,500 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_eligible.yaml index 01defee9fa6..2d33d5d4021 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_eligible.yaml @@ -1,7 +1,12 @@ # Nebraska ADC Eligibility Tests # Eligibility requires: -# 1. Net earned income (after 50% disregard) < Need Standard +# 1. Net earned income (after disregard) < Need Standard +# - Initial applicants: 20% disregard (countable = 80%) +# - Ongoing recipients: 50% disregard (countable = 50%) # 2. Resources within limits ($4,000 for 1 person, $6,000 for 2+) +# +# NOTE: These tests model ONGOING recipients (is_tanf_enrolled: true) +# who receive the 50% earned income disregard. - name: Case 1, no income is eligible. period: 2024-01 @@ -16,6 +21,7 @@ spm_unit: members: [person1, person2] spm_unit_cash_assets: 1_000 + is_tanf_enrolled: true households: household: members: [person1, person2] @@ -40,6 +46,7 @@ spm_unit: members: [person1, person2, person3] spm_unit_cash_assets: 2_000 + is_tanf_enrolled: true households: household: members: [person1, person2, person3] @@ -67,6 +74,7 @@ spm_unit: members: [person1, person2, person3] spm_unit_cash_assets: 1_000 + is_tanf_enrolled: true households: household: members: [person1, person2, person3] @@ -92,6 +100,7 @@ spm_unit: members: [person1, person2] spm_unit_cash_assets: 1_000 + is_tanf_enrolled: true households: household: members: [person1, person2] @@ -117,6 +126,7 @@ spm_unit: members: [person1, person2] spm_unit_cash_assets: 1_000 + is_tanf_enrolled: true households: household: members: [person1, person2] @@ -128,3 +138,179 @@ ne_adc_income_eligible: false # Countable income ($745) > Need standard ($741) ne_adc_eligible: false + +# ============================================================================= +# EDGE CASES - RESOURCE BOUNDARIES (SINGLE PERSON $4,000 LIMIT) +# ============================================================================= + +- name: Edge case, resources exactly at $4,000 limit for single person. + period: 2024-01 + absolute_error_margin: 0.5 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 0 + spm_units: + spm_unit: + members: [person1] + spm_unit_assets: 4_000 + households: + household: + members: [person1] + state_code: NE + output: + spm_unit_size: 1 + ne_adc_resources_eligible: true + # Resources ($4,000) <= Limit ($4,000) -> true + +- name: Edge case, resources one dollar above $4,000 limit for single person. + period: 2024-01 + absolute_error_margin: 0.5 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 0 + spm_units: + spm_unit: + members: [person1] + spm_unit_assets: 4_001 + households: + household: + members: [person1] + state_code: NE + output: + spm_unit_size: 1 + ne_adc_resources_eligible: false + # Resources ($4,001) <= Limit ($4,000) -> false + ne_adc_eligible: false + +- name: Edge case, resources one dollar below $4,000 limit for single person. + period: 2024-01 + absolute_error_margin: 0.5 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 0 + spm_units: + spm_unit: + members: [person1] + spm_unit_assets: 3_999 + households: + household: + members: [person1] + state_code: NE + output: + spm_unit_size: 1 + ne_adc_resources_eligible: true + # Resources ($3,999) <= Limit ($4,000) -> true + +# ============================================================================= +# EDGE CASES - RESOURCE BOUNDARIES (TWO+ PERSONS $6,000 LIMIT) +# ============================================================================= + +- name: Edge case, resources exactly at $6,000 limit for family of 2. + period: 2024-01 + absolute_error_margin: 0.5 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 0 + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 6_000 + households: + household: + members: [person1, person2] + state_code: NE + output: + spm_unit_size: 2 + ne_adc_resources_eligible: true + # Resources ($6,000) <= Limit ($6,000) -> true + ne_adc_eligible: true + +- name: Edge case, resources one dollar above $6,000 limit for family of 2. + period: 2024-01 + absolute_error_margin: 0.5 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 0 + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 6_001 + households: + household: + members: [person1, person2] + state_code: NE + output: + spm_unit_size: 2 + ne_adc_resources_eligible: false + # Resources ($6,001) <= Limit ($6,000) -> false + ne_adc_eligible: false + +- name: Edge case, resources one dollar below $6,000 limit for family of 2. + period: 2024-01 + absolute_error_margin: 0.5 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 0 + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 5_999 + households: + household: + members: [person1, person2] + state_code: NE + output: + spm_unit_size: 2 + ne_adc_resources_eligible: true + # Resources ($5,999) <= Limit ($6,000) -> true + ne_adc_eligible: true + +# ============================================================================= +# EDGE CASES - DEMOGRAPHIC ELIGIBILITY +# ============================================================================= + +- name: Edge case, household with only adults fails demographic eligibility. + # Two adults (ages 30 and 35) with no children or pregnant persons + period: 2024-01 + absolute_error_margin: 0.5 + input: + people: + person1: + age: 30 + is_pregnant: false + employment_income_before_lsr: 0 + person2: + age: 35 + is_pregnant: false + employment_income_before_lsr: 0 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 1_000 + households: + household: + members: [person1, person2] + state_code: NE + output: + is_demographic_tanf_eligible: false + # No eligible children (both adults over age limit) and no pregnant persons + ne_adc_eligible: false + ne_adc: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_need_standard.yaml b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_need_standard.yaml index 852e7d0b5b7..8b112ad6353 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_need_standard.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_need_standard.yaml @@ -112,3 +112,128 @@ output: ne_adc_need_standard: 1_441 # Need standard for size 7 = $1,441 + +# ============================================================================= +# EDGE CASES - FAMILY SIZE BOUNDARIES +# ============================================================================= + +- name: Edge case, family size 10 at table maximum. + period: 2024-01 + absolute_error_margin: 0.5 + input: + people: + person1: + age: 35 + person2: + age: 33 + person3: + age: 17 + person4: + age: 16 + person5: + age: 15 + person6: + age: 14 + person7: + age: 13 + person8: + age: 12 + person9: + age: 11 + person10: + age: 10 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10] + households: + household: + members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10] + state_code: NE + output: + spm_unit_size: 10 + ne_adc_need_standard: 1_861 + # Need standard for size 10 = $1,861 + +- name: Edge case, family size 11 uses additional person increment. + period: 2024-01 + absolute_error_margin: 0.5 + input: + people: + person1: + age: 35 + person2: + age: 33 + person3: + age: 17 + person4: + age: 16 + person5: + age: 15 + person6: + age: 14 + person7: + age: 13 + person8: + age: 12 + person9: + age: 11 + person10: + age: 10 + person11: + age: 9 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10, person11] + households: + household: + members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10, person11] + state_code: NE + output: + spm_unit_size: 11 + ne_adc_need_standard: 2_001 + # Need standard for size 11 = $1,861 + $140 = $2,001 + +- name: Edge case, family size 14 uses additional person increment. + period: 2024-01 + absolute_error_margin: 0.5 + input: + people: + person1: + age: 35 + person2: + age: 33 + person3: + age: 17 + person4: + age: 16 + person5: + age: 15 + person6: + age: 14 + person7: + age: 13 + person8: + age: 12 + person9: + age: 11 + person10: + age: 10 + person11: + age: 9 + person12: + age: 8 + person13: + age: 7 + person14: + age: 6 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10, person11, person12, person13, person14] + households: + household: + members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10, person11, person12, person13, person14] + state_code: NE + output: + spm_unit_size: 14 + ne_adc_need_standard: 2_421 + # Need standard for size 14 = $1,861 + 4*$140 = $2,421 diff --git a/policyengine_us/variables/gov/states/ne/dhhs/adc/benefit/ne_adc_need_standard.py b/policyengine_us/variables/gov/states/ne/dhhs/adc/benefit/ne_adc_need_standard.py index 543c7c7c2b5..74d9d8045ed 100644 --- a/policyengine_us/variables/gov/states/ne/dhhs/adc/benefit/ne_adc_need_standard.py +++ b/policyengine_us/variables/gov/states/ne/dhhs/adc/benefit/ne_adc_need_standard.py @@ -16,6 +16,12 @@ class ne_adc_need_standard(Variable): def formula(spm_unit, period, parameters): p = parameters(period).gov.states.ne.dhhs.adc size = spm_unit("spm_unit_size", period) - # Cap size at maximum defined in parameter table - capped_size = min_(size, p.max_unit_size) - return p.benefit.need_standard[capped_size] + # Parameter table defines sizes 1-10; for larger sizes, add increment per person + max_table_size = p.max_unit_size + capped_size = min_(size, max_table_size) + base_amount = p.benefit.standard_of_need.amount[capped_size] + additional_persons = max_(size - max_table_size, 0) + additional_amount = ( + additional_persons * p.benefit.standard_of_need.additional_person + ) + return base_amount + additional_amount diff --git a/policyengine_us/variables/gov/states/ne/dhhs/adc/eligibility/ne_adc_resources_eligible.py b/policyengine_us/variables/gov/states/ne/dhhs/adc/eligibility/ne_adc_resources_eligible.py index 12e52afd90f..5556c4c8c75 100644 --- a/policyengine_us/variables/gov/states/ne/dhhs/adc/eligibility/ne_adc_resources_eligible.py +++ b/policyengine_us/variables/gov/states/ne/dhhs/adc/eligibility/ne_adc_resources_eligible.py @@ -18,6 +18,5 @@ def formula(spm_unit, period, parameters): countable_resources = spm_unit("spm_unit_assets", period) size = spm_unit("spm_unit_size", period) # Resource limits: $4,000 for 1 person, $6,000 for 2+ persons - capped_size = min_(size, p.max_unit_size) - limit = p.resources.limit[capped_size] + limit = p.resources.limit.calc(size) return countable_resources <= limit diff --git a/policyengine_us/variables/gov/states/ne/dhhs/adc/income/ne_adc_countable_earned_income.py b/policyengine_us/variables/gov/states/ne/dhhs/adc/income/ne_adc_countable_earned_income.py index de264674e9b..781454a5e02 100644 --- a/policyengine_us/variables/gov/states/ne/dhhs/adc/income/ne_adc_countable_earned_income.py +++ b/policyengine_us/variables/gov/states/ne/dhhs/adc/income/ne_adc_countable_earned_income.py @@ -13,8 +13,13 @@ class ne_adc_countable_earned_income(Variable): defined_for = StateCode.NE def formula(spm_unit, period, parameters): - p = parameters(period).gov.states.ne.dhhs.adc + p = parameters( + period + ).gov.states.ne.dhhs.adc.income.earned_income_disregard gross_earned = add(spm_unit, period, ["tanf_gross_earned_income"]) - # Per Neb. Rev. Stat. 68-1726(3)(a)(ii): 50% of gross earned income - # is disregarded for recipients - return gross_earned * (1 - p.income.earned_income_disregard) + is_enrolled = spm_unit("is_tanf_enrolled", period) + # Per Neb. Rev. Stat. 68-1726(3)(a): + # (i) 20% disregard for initial applicants + # (ii) 50% disregard for ongoing recipients + disregard_rate = where(is_enrolled, p.ongoing, p.initial) + return gross_earned * (1 - disregard_rate) diff --git a/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc.py b/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc.py index ed9b91d7a92..0733ab3216e 100644 --- a/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc.py +++ b/policyengine_us/variables/gov/states/ne/dhhs/adc/ne_adc.py @@ -14,15 +14,6 @@ class ne_adc(Variable): defined_for = "ne_adc_eligible" def formula(spm_unit, period, parameters): - p = parameters(period).gov.states.ne.dhhs.adc maximum_benefit = spm_unit("ne_adc_maximum_benefit", period) unearned = add(spm_unit, period, ["tanf_gross_unearned_income"]) - # Final benefit = max benefit - unearned income - benefit_before_minimum = max_(maximum_benefit - unearned, 0) - # Per Neb. Rev. Stat. 43-512: no payments less than $10/month - # If benefit > 0 but < $10, return $10; if benefit = 0, return 0 - return where( - benefit_before_minimum > 0, - max_(benefit_before_minimum, p.min_payment), - 0, - ) + return max_(maximum_benefit - unearned, 0) diff --git a/sources/working_references.md b/sources/working_references.md deleted file mode 100644 index b3b04f7f7fa..00000000000 --- a/sources/working_references.md +++ /dev/null @@ -1,440 +0,0 @@ -# Collected Documentation - -## Nebraska Aid to Dependent Children (ADC) - TANF Implementation -**Collected**: 2025-12-23 -**Implementation Task**: Implement Nebraska ADC (TANF) cash assistance program - ---- - -## Official Program Name - -**Federal Program**: Temporary Assistance for Needy Families (TANF) -**State's Official Name**: Aid to Dependent Children (ADC) -**Abbreviation**: ADC -**Source**: Nebraska Revised Statutes Section 43-512, Title 468 NAC - -**Variable Prefix**: `ne_adc` - ---- - -## Regulatory Authority - -### Primary Legal Sources - -1. **Nebraska Revised Statutes** - - Section 43-504: Definition of dependent child (age requirements) - - Section 43-512: ADC application, payment level (55% of Standard of Need) - - Section 43-513: Standard of Need, CPI adjustment methodology - - Section 68-1713: Welfare Reform Act implementation requirements - - Section 68-1726: Earned income disregard, resource limits, eligibility factors - -2. **Nebraska Administrative Code Title 468** - - Chapter 1: General Background - - Chapter 2: Eligibility Requirements - - Chapter 3: Calculation of ADC Benefits - - Chapter 4: Employment First Self-Sufficiency Program - - Chapter 5: Emergency Assistance to Needy Families with Children - -### Source URLs - -- Nebraska DHHS TANF Page: https://dhhs.ne.gov/Pages/TANF.aspx -- Title 468 Overview: https://dhhs.ne.gov/Pages/Title-468.aspx -- Statute 43-504: https://nebraskalegislature.gov/laws/statutes.php?statute=43-504 -- Statute 43-512: https://nebraskalegislature.gov/laws/statutes.php?statute=43-512 -- Statute 43-513: https://nebraskalegislature.gov/laws/statutes.php?statute=43-513 -- Statute 68-1713: https://nebraskalegislature.gov/laws/statutes.php?statute=68-1713 -- Statute 68-1726: https://nebraskalegislature.gov/laws/statutes.php?statute=68-1726 - ---- - -## Demographic Eligibility - -### Eligible Children (468 NAC 2-007, Neb. Rev. Stat. 43-504) - -**Age Thresholds:** -- Children under age 19 meeting specific residency and support conditions (per 43-504) -- In practice for ADC cash assistance: - - Children age 18 or younger - - Children age 18 who are full-time students in secondary school (or equivalent vocational/technical training) and reasonably expected to complete before age 19 - - **Note**: College-level education does NOT qualify for the extended age limit - -**Pregnancy:** -- Unborn children are counted beginning the first day of the month of the mother's third trimester -- Pregnant women in final trimester qualify as "families with dependent children" -- Pregnancy must be medically verified -- Even for twins/multiples, ADC grant only reflects needs of ONE unborn child (Medical Assistance can reflect multiples) - -**Source**: 468 NAC 2-007, 3-004; Neb. Rev. Stat. 43-504 -- https://nebraskalegislature.gov/laws/statutes.php?statute=43-504 -- https://public-dhhs.ne.gov/nfocus/Manuals/APX468/apx468/eligibility_of_a_pregant_woman_for_a_grant.htm - -### Deprivation Requirement - NONE - -**IMPORTANT**: Nebraska does NOT require deprivation of parental support or care as an eligibility factor. Unmarried parents living together as a family are considered a family unit when paternity has been acknowledged or established. - -This is notable as many states require demonstration of parental absence, incapacity, or unemployment. - -**Source**: Nebraska DHHS TANF documentation - -### Implementation Approach - -- [ ] Use federal demographic eligibility (if age thresholds match federal 18/19) -- [x] Create state-specific age thresholds (Nebraska has specific student requirements - secondary school only, not college) - ---- - -## Immigration Eligibility - -**Implementation approach:** -- [x] Use federal immigration eligibility (state follows federal rules) -- Nebraska requires U.S. citizenship or qualifying alien status per 468 NAC 2-002 -- Any individual born in the United States is considered a U.S. citizen (including children of undocumented parents) - -**Source**: 468 NAC 2-002 - ---- - -## Resource Limits - -### Limits by Unit Size (Neb. Rev. Stat. 68-1726, 68-1713) - -| Unit Size | Resource Limit | -|-----------|----------------| -| 1 person | $4,000 | -| 2+ persons | $6,000 | - -### Excluded Resources - -- Primary home and furnishings -- Primary automobile (one vehicle per family - value excluded) -- Cash value of life insurance policies -- Up to $3,000 set aside for burial (pre-need burial trust or insurance policy) -- School grants, scholarships, vocational rehabilitation payments -- Job Training Partnership Act payments -- Education-related loans expected to be repaid - -### Counted Resources - -- Cash on hand -- Money in checking and savings accounts -- Savings certificates -- Stocks or bonds -- Credit card company gift card balances -- Nonrecurring lump sum payments -- Any burial funds over $3,000 - -**Source**: Nebraska Revised Statutes 68-1726, 68-1713; 468 NAC 2 (Resources) -- https://nebraskalegislature.gov/laws/statutes.php?statute=68-1726 -- https://nebraskalegislature.gov/laws/statutes.php?statute=68-1713 - ---- - -## Income Eligibility Tests - -### Test 1: Initial Eligibility (Standard of Need Test) - -For initial ADC eligibility, the family's **net earned income** must be below the **Standard of Need** for their unit size. - -**Earned Income Disregard for Applicants**: 20% of gross earned income -**Source**: Neb. Rev. Stat. 68-1726(3)(a)(i) - -### Test 2: Ongoing Eligibility - -For ongoing recipients: -**Earned Income Disregard**: 50% of gross earned income -**Source**: Neb. Rev. Stat. 68-1726(3)(a)(ii) - -### Test 3: Transitional Eligibility (185% FPL Test) - -If a family's income increases above the Standard of Need but remains below **185% of the Federal Poverty Level** for their unit size, the family may remain eligible for up to 5 months of transitional ADC grants. - -**Source**: 468 NAC 2-024.01 - ---- - -## Income Disregards and Deductions - -### Earned Income Disregard (Neb. Rev. Stat. 68-1726) - -| Status | Disregard Rate | Level | -|--------|----------------|-------| -| Applicants (initial eligibility testing) | 20% of gross earned income | Per GROUP | -| Recipients (after eligibility established) | 50% of gross earned income | Per GROUP | - -**Legal Citation**: Neb. Rev. Stat. 68-1726(3)(a): -> "(i) Twenty percent of gross earned income shall be disregarded to test for eligibility during the application process for aid to dependent children assistance; and -> (ii) For aid to dependent children program participants and for applicants after eligibility has been established, fifty percent of the gross earned income shall be disregarded" - -**Source**: https://nebraskalegislature.gov/laws/statutes.php?statute=68-1726 - -### Child Care Disregard - -A child care disregard is applied "when appropriate" according to 468 NAC documentation. The specific amount or methodology is documented in the Title 468 PDF. - -**Note**: Families receiving ADC are eligible for child care subsidy at no cost. - -### Income Exclusions - -The following are NOT counted as income: -- Financial assistance intended for books, tuition, or self-sufficiency related expenses -- School grants and scholarships -- Vocational rehabilitation payments -- Job Training Partnership Act payments -- Education-related loans expected to be repaid -- Income earned by children attending school (excluded from family income) - -**Source**: Neb. Rev. Stat. 68-1726 - ---- - -## Child Support Treatment - -### Current Rules (Until June 30, 2027) - -- Child support is assigned to the state when receiving ADC -- If average monthly child support collection exceeds the ADC payment amount, the case is closed -- Child support is either: - - Compared to budgetary need (if less than need, it's assigned and doesn't count) - - Counted as unearned income (if greater than need, case closes) - -### LB233 - Child Support Passthrough (Effective July 1, 2027) - -Beginning July 1, 2027, Nebraska will implement a child support passthrough: -- **$100 passthrough** for families with ONE child -- **$200 passthrough** for families with TWO or more children -- Passthrough amount is **disregarded** when calculating ADC eligibility and benefits - -**Source**: -- https://www.nebraskalegislature.gov/bills/view_bill.php?DocumentID=50212 -- LB233 passed 46-0 on April 11, 2024 - ---- - -## Income Standards - -### Standard of Need (468 NAC 3, Statute 43-513) - -The Standard of Need is the initial income test in ADC "gap" budgeting. It represents the monthly combined cost of food, clothing, sundries, home supplies, utilities, laundry, and shelter including taxes and insurance. - -**Effective July 1, 2021** (values adjusted biennially per CPI): - -| Unit Size | Standard of Need | -|-----------|------------------| -| 1 | $601 | -| 2 | $741 | -| 3 | $881 | -| 4 | $1,021 | -| 5 | $1,161 | -| 6 | $1,301 | -| 7 | $1,441 | -| 8 | $1,581 | -| 9 | $1,721 | -| 10 | $1,861 | -| Each additional person | +$140 | - -**CPI Adjustment**: Values are adjusted biennially (every 2 years) on July 1, using the Consumer Price Index (CPI) for the previous two calendar years, per statute 43-513. - -**Note**: Values shown are from July 1, 2021 adjustment. Some sources indicate these may have been updated. The formula is: -- Base (1 person): $601 -- Each additional person: +$140 - -**Source**: Nebraska Appleseed chart; Neb. Rev. Stat. 43-513; 468 NAC 3 -- https://neappleseed.org/wp-content/uploads/2023/03/Chart_-ADC-Standard-of-Need-and-Payment-Maximum.pdf -- https://dhhs.ne.gov/Documents/468-000-209.pdf - -### Payment Standard (Maximum Benefit) - -Effective **September 1, 2015**, the maximum ADC payment is **55% of the Standard of Need** (Neb. Rev. Stat. 43-512). - -| Unit Size | Standard of Need | Payment Standard (55%) | -|-----------|------------------|------------------------| -| 1 | $601 | $331 | -| 2 | $741 | $408 | -| 3 | $881 | $485 | -| 4 | $1,021 | $562 | -| 5 | $1,161 | $639 | -| 6 | $1,301 | $716 | -| 7 | $1,441 | $793 | -| Each additional person | +$140 | +$77 | - -**Payment Standard Rate**: 0.55 (55%) - -**Note**: There has been legislative effort (LB 310) to increase the maximum ADC payment from 55% to 85% of standard of need, but as of this documentation, 55% remains in effect. - -**Source**: Neb. Rev. Stat. 43-512; Nebraska Appleseed chart - ---- - -## Benefit Calculation - -### Gap Budgeting Methodology (468 NAC 3, Neb. Rev. Stat. 68-1713) - -Nebraska uses "Budget the Gap" methodology: - -**Step 1**: Calculate **Net Earned Income**: -- For applicants: Gross Earned Income x (1 - 0.20) = Gross Earned Income x 0.80 -- For recipients: Gross Earned Income x (1 - 0.50) = Gross Earned Income x 0.50 -- Subtract child care disregard if applicable - -**Step 2**: Calculate **"Gap"**: -- Gap = Standard of Need - Net Earned Income - -**Step 3**: Determine **Benefit Amount**: -- Benefit = min(Gap, Payment Standard) - -**Step 4**: Subtract **Unearned Income**: -- Final Benefit = Benefit - Unearned Income - -**Step 5**: Apply **Minimum Payment Rule**: -- No payments less than $10/month (except for overpayment recovery) - -**Legal Citation**: Neb. Rev. Stat. 68-1713(1)(p): "Budget the Gap Methodology Whereby Countable Earned Income is Subtracted from the Standard of the Need and Payment is Based on the Difference or Maximum Payment Level, Whichever is Less" - -**Source**: https://nebraskalegislature.gov/laws/statutes.php?statute=68-1713 - ---- - -## Transitional Grants (468 NAC 2-024.01) - -### Eligibility Requirements - -Families may receive up to **5 transitional grants** if they: -1. Lost ADC eligibility specifically due to increased earnings or hours of employment -2. Qualify for Transitional Medical Assistance (TMA) -3. Actually received an ADC grant in the month immediately before losing eligibility -4. Received or were eligible for grants in at least 3 of the 6 months preceding ineligibility - -### Grant Amount - -Each transitional grant equals **1/5 of the ADC Payment Standard** for the family's size. - -### Ongoing Requirements - -To continue receiving transitional grants, families must: -- Maintain earned income not exceeding **185% of the Federal Poverty Level** -- Maintain active employment -- Remain Nebraska residents -- Include a dependent child -- Remain ineligible for regular ADC grants - -**Source**: https://publictest-dhhs.ne.gov/nfocus/stg/Manuals/NAC468/nac468/2_024_01_transitional_grant.htm - ---- - -## Non-Simulatable Rules (Architecture Limitation) - -### Time Limits - CANNOT ENFORCE - -- **60-Month Lifetime Limit**: ADC families where parent(s) are capable of attaining independence are limited to 60 months of cash assistance in a lifetime -- **Exception**: Families where adults are not the parent of the child, or parent is disabled/unable to work, are NOT time-limited -- **Hardship Review**: After 56 months, recipients participate in a hardship review; if hardship is found, one 3-month extension may be granted - -**Note**: PolicyEngine's single-period architecture cannot track lifetime benefit receipt. - -### Work Requirements - NOT MODELED - -Nebraska's Employment First (EF) program requires participation for work-eligible adults. This is not modeled in PolicyEngine. - -### Waiting Periods - CANNOT TRACK - -- Redetermination every 6 months -- Transitional benefit requirements for prior receipt - ---- - -## Summary of Implementation Parameters - -### Parameters to Create - -| Parameter | Value | Unit | Source | -|-----------|-------|------|--------| -| Standard of Need (base, 1 person) | 601 | USD/month | 43-513, 468 NAC 3 | -| Standard of Need (additional person) | 140 | USD/month | 43-513, 468 NAC 3 | -| Payment Standard Rate | 0.55 | rate | 43-512 | -| Earned Income Disregard (applicant) | 0.20 | rate | 68-1726(3)(a)(i) | -| Earned Income Disregard (recipient) | 0.50 | rate | 68-1726(3)(a)(ii) | -| Resource Limit (1 person) | 4_000 | USD | 68-1726 | -| Resource Limit (2+ persons) | 6_000 | USD | 68-1726 | -| Minimum Payment | 10 | USD/month | 43-512 | -| Minor Child Age Threshold | 18 | years | 468 NAC 2-007, 43-504 | -| Student Age Threshold | 19 | years | 468 NAC 2-007, 43-504 | -| Transitional Eligibility FPL Rate | 1.85 | rate | 468 NAC 2-024.01 | -| Child Support Passthrough (1 child) | 100 | USD/month | LB233 (eff. 2027-07-01) | -| Child Support Passthrough (2+ children) | 200 | USD/month | LB233 (eff. 2027-07-01) | - ---- - -## Simplified Implementation Approach - -Given the complexity of Nebraska ADC with applicant vs. recipient distinctions, consider implementing: - -1. **Simplified version**: Use recipient disregard rate (50%) for all cases - - This is more generous and represents ongoing eligibility - - Avoids needing to track applicant vs. recipient status - -2. **Full version**: Implement both rates with a parameter or variable to distinguish - -**Recommendation**: Start with simplified version using 50% disregard for initial implementation. - ---- - -## References for Metadata - -### For Parameters - -```yaml -reference: - - title: Nebraska Revised Statutes 43-512 - href: https://nebraskalegislature.gov/laws/statutes.php?statute=43-512 - - title: Nebraska Revised Statutes 68-1726 - href: https://nebraskalegislature.gov/laws/statutes.php?statute=68-1726 -``` - -### For Variables - -```python -reference = "https://nebraskalegislature.gov/laws/statutes.php?statute=43-512" -# or for regulations: -reference = "https://dhhs.ne.gov/Pages/Title-468.aspx" -``` - ---- - -## PDFs for Future Reference - -The following PDFs contain additional information but could not be fully extracted: - -1. **Title 468 - Aid to Dependent Children (Complete)** - - URL: https://dhhs.ne.gov/Documents/Title-468-Complete.pdf - - Expected content: Complete ADC regulations including detailed benefit calculation, child care disregard amounts, all eligibility rules - - Note: This is the authoritative source for Nebraska ADC regulations - -2. **Title 468 Guidance Document** - - URL: https://dhhs.ne.gov/Guidance%20Docs/Title%20468%20-%20Aid%20to%20Dependent%20Children.pdf - - Expected content: Implementation guidance for ADC program - -3. **ADC Standard of Need and Payment Maximum Chart** - - URL: https://neappleseed.org/wp-content/uploads/2023/03/Chart_-ADC-Standard-of-Need-and-Payment-Maximum.pdf - - Expected content: Current Standard of Need and Payment Maximum amounts by household size - - Key information: Standard of Need table with payment standards - -4. **Nebraska TANF State Plan 2024** - - URL: https://dhhs.ne.gov/Documents/Nebraska-State-TANF-Plan-2024.pdf - - Expected content: Current TANF state plan with benefit methodology, eligibility criteria - -5. **468-000-209 Appendix Material** - - URL: https://dhhs.ne.gov/Documents/468-000-209.pdf - - Expected content: Standard of Need charts, effective July 1, 2021 - -6. **Nebraska TANF Expenditures Report 2024** - - URL: https://nebraskalegislature.gov/pdf/reports/fiscal/2024_tanf_report.pdf - - Expected content: TANF fund usage and program statistics - ---- - -## Open Questions for Implementation - -1. **Child Care Disregard Amount**: The specific child care disregard amount/methodology needs to be confirmed from Title 468 PDF -2. **Current Standard of Need Values**: Values may have been adjusted since July 2021 per CPI methodology - need to verify current amounts -3. **Simplified vs Full Implementation**: Decision on whether to implement applicant/recipient distinction or use single rate -4. **Unearned Income Treatment**: Current child support assignment rules vs. future passthrough (2027) From 81505fef2ed2c3aca81e32e3238f034497d8ee2c Mon Sep 17 00:00:00 2001 From: Ziming Date: Thu, 25 Dec 2025 15:12:58 -0500 Subject: [PATCH 7/8] test cases --- .../gov/states/ne/dhhs/adc/max_unit_size.yaml | 6 +- .../gov/states/ne/dhhs/adc/integration.yaml | 209 +---------------- .../gov/states/ne/dhhs/adc/ne_adc.yaml | 171 +------------- .../adc/ne_adc_countable_earned_income.yaml | 162 ++----------- .../states/ne/dhhs/adc/ne_adc_eligible.yaml | 219 +++--------------- .../ne/dhhs/adc/ne_adc_income_eligible.yaml | 120 ++++++++++ .../ne/dhhs/adc/ne_adc_maximum_benefit.yaml | 110 +++++++++ .../ne/dhhs/adc/ne_adc_need_standard.yaml | 80 ------- .../dhhs/adc/ne_adc_resources_eligible.yaml | 86 +++++++ .../dhhs/adc/benefit/ne_adc_need_standard.py | 2 +- 10 files changed, 377 insertions(+), 788 deletions(-) create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_income_eligible.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_maximum_benefit.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_resources_eligible.yaml diff --git a/policyengine_us/parameters/gov/states/ne/dhhs/adc/max_unit_size.yaml b/policyengine_us/parameters/gov/states/ne/dhhs/adc/max_unit_size.yaml index ff6d5daa7ce..fe917551b2d 100644 --- a/policyengine_us/parameters/gov/states/ne/dhhs/adc/max_unit_size.yaml +++ b/policyengine_us/parameters/gov/states/ne/dhhs/adc/max_unit_size.yaml @@ -8,7 +8,5 @@ metadata: period: year label: Nebraska ADC maximum unit size reference: - - title: Title 468 NAC Chapter 3 - href: https://dhhs.ne.gov/Pages/Title-468.aspx - - title: Neb. Rev. Stat. 43-513 - href: https://nebraskalegislature.gov/laws/statutes.php?statute=43-513 + - title: Title 468 NAC Chapter 3 (2025) + href: https://dhhs.ne.gov/Guidance%20Docs/Title%20468%20-%20Aid%20to%20Dependent%20Children.pdf#page=9 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/integration.yaml index afc772a54bc..718352d4698 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/integration.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/integration.yaml @@ -1,4 +1,6 @@ # Nebraska ADC (Aid to Dependent Children) Integration Tests +# These tests verify the FULL calculation pipeline with all intermediate values. +# # Gap Budgeting Methodology: # Step 1: Net Earned Income = Gross Earned * (1 - disregard_rate) # - Initial applicants: 20% disregard (countable = 80%) @@ -40,18 +42,13 @@ output: spm_unit_size: 3 ne_adc_need_standard: 881 - # Need standard for size 3 = $881 ne_adc_payment_standard: 485 - # Payment standard = $881 * 0.55 = $484.55, rounded to $485 ne_adc_countable_earned_income: 0 - # No earned income, no unearned income ne_adc_income_eligible: true - # Countable income ($0) < Need standard ($881) -> Eligible ne_adc_eligible: true ne_adc: 485 # Gap = $881 - $0 = $881 # Benefit = min($881, $485) = $485 - # Final = $485 - $0 = $485 - name: Case 2, family of 3 with earned income receives partial benefit. period: 2024-01 @@ -80,16 +77,12 @@ ne_adc_need_standard: 881 ne_adc_payment_standard: 485 ne_adc_countable_earned_income: 500 - # Gross earned = $1,000/month # After 50% disregard: $1,000 * 0.50 = $500 - # Countable income = Earned ($500) + Unearned ($0) = $500 ne_adc_income_eligible: true - # Countable income ($500) < Need standard ($881) -> Eligible ne_adc_eligible: true ne_adc: 381 # Gap = $881 - $500 = $381 # Benefit = min($381, $485) = $381 - # Final = $381 - $0 = $381 - name: Case 3, family of 4 with unearned income. period: 2024-01 @@ -120,12 +113,8 @@ output: spm_unit_size: 4 ne_adc_need_standard: 1_021 - # Need standard for size 4 = $1,021 ne_adc_payment_standard: 562 - # Payment standard = $1,021 * 0.55 = $561.55, rounded to $562 ne_adc_countable_earned_income: 0 - # Social security: $6,000/12 = $500/month unearned - # Countable income = Earned ($0) + Unearned ($500) = $500 ne_adc_income_eligible: true ne_adc_eligible: true ne_adc: 62 @@ -160,14 +149,11 @@ ne_adc_need_standard: 881 ne_adc_payment_standard: 485 ne_adc_countable_earned_income: 1_000 - # Gross earned = $2,000/month # After 50% disregard: $2,000 * 0.50 = $1,000 - # Countable income = $1,000 ne_adc_income_eligible: false - # Countable income ($1,000) > Need standard ($881) -> Ineligible + # Countable ($1,000) > Need Standard ($881) ne_adc_eligible: false ne_adc: 0 - # Gap = $881 - $1,000 = -$119 (negative, not eligible) - name: Case 5, family of 2 near income threshold. period: 2024-01 @@ -192,15 +178,10 @@ output: spm_unit_size: 2 ne_adc_need_standard: 741 - # Need standard for size 2 = $741 ne_adc_payment_standard: 408 - # Payment standard = $741 * 0.55 = $407.55, rounded to $408 ne_adc_countable_earned_income: 700 - # Gross earned = $1,400/month # After 50% disregard: $1,400 * 0.50 = $700 - # Countable income = $700 ne_adc_income_eligible: true - # Countable income ($700) < Need standard ($741) -> Eligible ne_adc_eligible: true ne_adc: 41 # Gap = $741 - $700 = $41 @@ -234,10 +215,7 @@ ne_adc_need_standard: 881 ne_adc_payment_standard: 485 ne_adc_countable_earned_income: 300 - # Gross earned = $600/month # After 50% disregard: $600 * 0.50 = $300 - # Unearned: $2,400/12 = $200/month - # Countable income = Earned ($300) + Unearned ($200) = $500 ne_adc_income_eligible: true ne_adc_eligible: true ne_adc: 285 @@ -271,191 +249,10 @@ ne_adc_need_standard: 741 ne_adc_payment_standard: 408 ne_adc_countable_earned_income: 330 - # Gross earned = $660/month # After 50% disregard: $660 * 0.50 = $330 - # Unearned: $4,800/12 = $400/month - # Countable income = Earned ($330) + Unearned ($400) = $730 ne_adc_income_eligible: true - # Countable income ($730) < Need standard ($741) -> Eligible ne_adc_eligible: true ne_adc: 8 # Gap = $741 - $330 = $411 # Benefit = min($411, $408) = $408 # Final = $408 - $400 = $8 - -# ============================================================================= -# EDGE CASES - INCOME BOUNDARY TESTS -# ============================================================================= - -- name: Edge case, income exactly at need standard threshold is ineligible. - # Tests strict less-than comparison: countable_income < need_standard - period: 2024-01 - absolute_error_margin: 0.5 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 17_784 # $1,482/month -> $741 countable - person2: - age: 10 - spm_units: - spm_unit: - members: [person1, person2] - spm_unit_assets: 1_000 - is_tanf_enrolled: true - households: - household: - members: [person1, person2] - state_code: NE - output: - ne_adc_need_standard: 741 - ne_adc_countable_earned_income: 741 - # Gross: $17,784/12 = $1,482/month - # After 50% disregard (ongoing recipient): $1,482 * 0.50 = $741 - ne_adc_income_eligible: false - # Countable ($741) < Need Standard ($741) -> false (not strictly less) - ne_adc_eligible: false - ne_adc: 0 - -- name: Edge case, income one dollar below need standard threshold. - period: 2024-01 - absolute_error_margin: 0.5 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 17_760 # $1,480/month -> $740 countable - person2: - age: 10 - spm_units: - spm_unit: - members: [person1, person2] - spm_unit_assets: 1_000 - is_tanf_enrolled: true - households: - household: - members: [person1, person2] - state_code: NE - output: - ne_adc_need_standard: 741 - ne_adc_countable_earned_income: 740 - # Gross: $17,760/12 = $1,480/month - # After 50% disregard (ongoing recipient): $1,480 * 0.50 = $740 - ne_adc_income_eligible: true - # Countable ($740) < Need Standard ($741) -> true - ne_adc_eligible: true - -- name: Edge case, income one dollar above need standard threshold. - period: 2024-01 - absolute_error_margin: 0.5 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 17_808 # $1,484/month -> $742 countable - person2: - age: 10 - spm_units: - spm_unit: - members: [person1, person2] - spm_unit_assets: 1_000 - is_tanf_enrolled: true - households: - household: - members: [person1, person2] - state_code: NE - output: - ne_adc_need_standard: 741 - ne_adc_countable_earned_income: 742 - # Gross: $17,808/12 = $1,484/month - # After 50% disregard (ongoing recipient): $1,484 * 0.50 = $742 - ne_adc_income_eligible: false - # Countable ($742) < Need Standard ($741) -> false - ne_adc_eligible: false - ne_adc: 0 - -# ============================================================================= -# EDGE CASES - ZERO VALUE TESTS -# ============================================================================= - -- name: Edge case, zero earned income. - period: 2024-01 - absolute_error_margin: 0.5 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 0 - person2: - age: 10 - spm_units: - spm_unit: - members: [person1, person2] - spm_unit_assets: 1_000 - households: - household: - members: [person1, person2] - state_code: NE - output: - ne_adc_countable_earned_income: 0 - ne_adc_income_eligible: true - ne_adc_eligible: true - -- name: Edge case, zero resources. - period: 2024-01 - absolute_error_margin: 0.5 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 0 - person2: - age: 10 - spm_units: - spm_unit: - members: [person1, person2] - spm_unit_assets: 0 - households: - household: - members: [person1, person2] - state_code: NE - output: - ne_adc_resources_eligible: true - # Resources ($0) <= Limit ($6,000) -> true - ne_adc_eligible: true - -# ============================================================================= -# EDGE CASES - MIXED INCOME BOUNDARY -# ============================================================================= - -- name: Edge case, mixed income exactly at threshold. - # Countable = earned_after_disregard + unearned = need_standard - period: 2024-01 - absolute_error_margin: 0.5 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 8_400 # $700/month -> $350 countable earned - social_security: 6_372 # $531/month unearned - person2: - age: 10 - person3: - age: 8 - spm_units: - spm_unit: - members: [person1, person2, person3] - spm_unit_assets: 1_000 - is_tanf_enrolled: true - households: - household: - members: [person1, person2, person3] - state_code: NE - output: - ne_adc_need_standard: 881 - ne_adc_countable_earned_income: 350 - # Gross = $700, after 50% disregard (ongoing recipient) = $350 - ne_adc_income_eligible: false - # Total countable = $350 + $531 = $881 - # Countable ($881) < Need Standard ($881) -> false - ne_adc_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc.yaml b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc.yaml index c6e02809c88..03e6d81b00e 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc.yaml @@ -1,176 +1,11 @@ -# Nebraska ADC Benefit Amount Tests +# Nebraska ADC Benefit Amount Edge Cases +# These test specific edge cases NOT covered in integration.yaml +# # Gap Budgeting Methodology: # Step 1: Net Earned Income = Gross Earned * (1 - disregard_rate) -# - Initial applicants: 20% disregard (countable = 80%) -# - Ongoing recipients: 50% disregard (countable = 50%) # Step 2: Gap = Need Standard - Net Earned Income # Step 3: Benefit = min(Gap, Payment Standard) # Step 4: Final Benefit = Benefit - Unearned Income -# -# NOTE: These tests model ONGOING recipients (is_tanf_enrolled: true) -# who receive the 50% earned income disregard. - -- name: Case 1, no income receives maximum benefit. - period: 2024-01 - absolute_error_margin: 0.5 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 0 - person2: - age: 10 - person3: - age: 8 - spm_units: - spm_unit: - members: [person1, person2, person3] - spm_unit_cash_assets: 1_000 - is_tanf_enrolled: true - households: - household: - members: [person1, person2, person3] - state_code: NE - output: - ne_adc: 485 - # Gap = $881 - $0 = $881 - # Benefit = min($881, $485) = $485 - # Final = $485 - $0 = $485 - -- name: Case 2, earned income reduces benefit. - period: 2024-01 - absolute_error_margin: 0.5 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 12_000 # $1,000/month - person2: - age: 10 - person3: - age: 8 - spm_units: - spm_unit: - members: [person1, person2, person3] - spm_unit_cash_assets: 1_000 - is_tanf_enrolled: true - households: - household: - members: [person1, person2, person3] - state_code: NE - output: - ne_adc: 381 - # Countable earned = $1,000 * 0.50 = $500 - # Gap = $881 - $500 = $381 - # Benefit = min($381, $485) = $381 - # Final = $381 - $0 = $381 - -- name: Case 3, unearned income reduces benefit. - period: 2024-01 - absolute_error_margin: 0.5 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 0 - social_security: 6_000 # $500/month - person2: - age: 10 - person3: - age: 8 - spm_units: - spm_unit: - members: [person1, person2, person3] - spm_unit_cash_assets: 1_000 - is_tanf_enrolled: true - households: - household: - members: [person1, person2, person3] - state_code: NE - output: - ne_adc: 0 - # Gap = $881 - $0 = $881 - # Benefit = min($881, $485) = $485 - # Final = $485 - $500 = -$15 -> $0 (can't be negative) - -- name: Case 4, income too high gets zero benefit. - period: 2024-01 - absolute_error_margin: 0.5 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 24_000 # $2,000/month - person2: - age: 10 - spm_units: - spm_unit: - members: [person1, person2] - spm_unit_cash_assets: 1_000 - is_tanf_enrolled: true - households: - household: - members: [person1, person2] - state_code: NE - output: - ne_adc: 0 - # Countable earned = $2,000 * 0.50 = $1,000 - # Gap = $741 - $1,000 = -$259 (negative, not eligible) - # Benefit = $0 - -- name: Case 5, small benefit after unearned income deduction. - period: 2024-01 - absolute_error_margin: 0.5 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 7_920 # $660/month earned - social_security: 4_800 # $400/month unearned - person2: - age: 10 - spm_units: - spm_unit: - members: [person1, person2] - spm_unit_cash_assets: 1_000 - is_tanf_enrolled: true - households: - household: - members: [person1, person2] - state_code: NE - output: - ne_adc: 8 - # Countable earned = $660 * 0.50 = $330 - # Gap = $741 - $330 = $411 - # Benefit = min($411, $408) = $408 - # Final = $408 - $400 = $8 - -- name: Case 6, moderate benefit after unearned income deduction. - period: 2024-01 - absolute_error_margin: 0.5 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 7_920 # $660/month earned - social_security: 4_680 # $390/month unearned - person2: - age: 10 - spm_units: - spm_unit: - members: [person1, person2] - spm_unit_cash_assets: 1_000 - is_tanf_enrolled: true - households: - household: - members: [person1, person2] - state_code: NE - output: - ne_adc: 18 - # Countable earned = $660 * 0.50 = $330 - # Gap = $741 - $330 = $411 - # Benefit = min($411, $408) = $408 - # Final = $408 - $390 = $18 # ============================================================================= # EDGE CASES - GAP BUDGETING diff --git a/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_countable_earned_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_countable_earned_income.yaml index 375af7f552f..a3398aaa3d3 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_countable_earned_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_countable_earned_income.yaml @@ -1,35 +1,9 @@ # Nebraska ADC Countable Earned Income Tests # Per Neb. Rev. Stat. 68-1726(3)(a): -# - (i) Initial applicants: 20% disregard -# - (ii) Ongoing recipients: 50% disregard +# - (i) Initial applicants: 20% disregard (countable = 80%) +# - (ii) Ongoing recipients: 50% disregard (countable = 50%) -# ============================================================================= -# ONGOING RECIPIENT TESTS (is_tanf_enrolled: true, 50% disregard) -# Countable Earned = Gross Earned * (1 - 0.50) = Gross Earned * 0.50 -# ============================================================================= - -- name: Case 1, ongoing recipient with no earned income. - period: 2024-01 - absolute_error_margin: 0.5 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 0 - person2: - age: 10 - spm_units: - spm_unit: - members: [person1, person2] - is_tanf_enrolled: true - households: - household: - members: [person1, person2] - state_code: NE - output: - ne_adc_countable_earned_income: 0 - -- name: Case 2, ongoing recipient with earned income 50 percent disregard. +- name: Case 1, ongoing recipient 50 percent disregard. period: 2024-01 input: people: @@ -48,79 +22,9 @@ state_code: NE output: ne_adc_countable_earned_income: 500 - # Gross earned: $12,000/12 = $1,000/month - # After 50% disregard: $1,000 * 0.50 = $500 - -- name: Case 3, ongoing recipient with moderate earned income. - period: 2024-01 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 7_200 # $600/month - person2: - age: 10 - spm_units: - spm_unit: - members: [person1, person2] - is_tanf_enrolled: true - households: - household: - members: [person1, person2] - state_code: NE - output: - ne_adc_countable_earned_income: 300 - # Gross earned: $7,200/12 = $600/month - # After 50% disregard: $600 * 0.50 = $300 - -- name: Case 4, ongoing recipient with high earned income. - period: 2024-01 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 24_000 # $2,000/month - person2: - age: 10 - spm_units: - spm_unit: - members: [person1, person2] - is_tanf_enrolled: true - households: - household: - members: [person1, person2] - state_code: NE - output: - ne_adc_countable_earned_income: 1_000 - # Gross earned: $24,000/12 = $2,000/month - # After 50% disregard: $2,000 * 0.50 = $1,000 - -# ============================================================================= -# INITIAL APPLICANT TESTS (is_tanf_enrolled: false, 20% disregard) -# Countable Earned = Gross Earned * (1 - 0.20) = Gross Earned * 0.80 -# ============================================================================= - -- name: Case 5, initial applicant with no earned income. - period: 2024-01 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 0 - person2: - age: 10 - spm_units: - spm_unit: - members: [person1, person2] - is_tanf_enrolled: false - households: - household: - members: [person1, person2] - state_code: NE - output: - ne_adc_countable_earned_income: 0 + # Gross: $1,000/month * 0.50 = $500 -- name: Case 6, initial applicant with earned income 20 percent disregard. +- name: Case 2, initial applicant 20 percent disregard. period: 2024-01 input: people: @@ -139,65 +43,35 @@ state_code: NE output: ne_adc_countable_earned_income: 800 - # Gross earned: $12,000/12 = $1,000/month - # After 20% disregard: $1,000 * 0.80 = $800 + # Gross: $1,000/month * 0.80 = $800 -- name: Case 7, initial applicant with moderate earned income. +- name: Case 3, zero income. period: 2024-01 input: people: person1: age: 30 - employment_income_before_lsr: 7_200 # $600/month - person2: - age: 10 - spm_units: - spm_unit: - members: [person1, person2] - is_tanf_enrolled: false - households: - household: - members: [person1, person2] - state_code: NE - output: - ne_adc_countable_earned_income: 480 - # Gross earned: $7,200/12 = $600/month - # After 20% disregard: $600 * 0.80 = $480 - -- name: Case 8, initial applicant with high earned income. - period: 2024-01 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 24_000 # $2,000/month + employment_income_before_lsr: 0 person2: age: 10 spm_units: spm_unit: members: [person1, person2] - is_tanf_enrolled: false households: household: members: [person1, person2] state_code: NE output: - ne_adc_countable_earned_income: 1_600 - # Gross earned: $24,000/12 = $2,000/month - # After 20% disregard: $2,000 * 0.80 = $1,600 - -# ============================================================================= -# EDGE CASES - EARNED INCOME DISREGARD -# ============================================================================= + ne_adc_countable_earned_income: 0 -- name: Edge case, very small earned income disregard applied. +- name: Edge case, ongoing recipient large income. period: 2024-01 absolute_error_margin: 0.5 input: people: person1: age: 30 - employment_income_before_lsr: 24 # $2/month gross + employment_income_before_lsr: 60_000 # $5,000/month person2: age: 10 spm_units: @@ -209,27 +83,27 @@ members: [person1, person2] state_code: NE output: - ne_adc_countable_earned_income: 1 - # Gross = $2, after 50% disregard (ongoing recipient) = $1 + ne_adc_countable_earned_income: 2_500 + # Gross: $5,000/month * 0.50 = $2,500 -- name: Edge case, large earned income 50 percent disregard. +- name: Edge case, initial applicant large income. period: 2024-01 absolute_error_margin: 0.5 input: people: person1: age: 30 - employment_income_before_lsr: 60_000 # $5,000/month gross + employment_income_before_lsr: 60_000 # $5,000/month person2: age: 10 spm_units: spm_unit: members: [person1, person2] - is_tanf_enrolled: true + is_tanf_enrolled: false households: household: members: [person1, person2] state_code: NE output: - ne_adc_countable_earned_income: 2_500 - # Gross = $5,000, after 50% disregard (ongoing recipient) = $2,500 + ne_adc_countable_earned_income: 4_000 + # Gross: $5,000/month * 0.80 = $4,000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_eligible.yaml index 2d33d5d4021..1fa4c4288de 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_eligible.yaml @@ -1,12 +1,12 @@ # Nebraska ADC Eligibility Tests # Eligibility requires: -# 1. Net earned income (after disregard) < Need Standard -# - Initial applicants: 20% disregard (countable = 80%) -# - Ongoing recipients: 50% disregard (countable = 50%) -# 2. Resources within limits ($4,000 for 1 person, $6,000 for 2+) +# 1. Demographic eligibility (children or pregnant) +# 2. Immigration eligibility (citizen or legal immigrant) +# 3. Income eligibility (countable income < need standard) +# 4. Resource eligibility ($4,000 for 1 person, $6,000 for 2+) # -# NOTE: These tests model ONGOING recipients (is_tanf_enrolled: true) -# who receive the 50% earned income disregard. +# NOTE: These tests focus on COMBINED eligibility checks. +# Individual component tests are in their respective files. - name: Case 1, no income is eligible. period: 2024-01 @@ -28,259 +28,108 @@ state_code: NE output: ne_adc_income_eligible: true - # Countable income ($0) < Need standard ($741) - ne_adc_eligible: true - -- name: Case 2, income below threshold is eligible. - period: 2024-01 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 12_000 # $1,000/month gross - person2: - age: 10 - person3: - age: 8 - spm_units: - spm_unit: - members: [person1, person2, person3] - spm_unit_cash_assets: 2_000 - is_tanf_enrolled: true - households: - household: - members: [person1, person2, person3] - state_code: NE - output: - ne_adc_countable_earned_income: 500 - # After 50% disregard: $1,000 * 0.50 = $500 - # Countable income = $500 - ne_adc_income_eligible: true - # Countable income ($500) < Need standard ($881) + ne_adc_resources_eligible: true ne_adc_eligible: true -- name: Case 3, income above threshold is ineligible. +- name: Case 2, income ineligible fails overall. period: 2024-01 input: people: person1: age: 30 - employment_income_before_lsr: 24_000 # $2,000/month gross + employment_income_before_lsr: 24_000 # $2,000/month -> $1,000 countable person2: age: 10 - person3: - age: 8 spm_units: spm_unit: - members: [person1, person2, person3] + members: [person1, person2] spm_unit_cash_assets: 1_000 is_tanf_enrolled: true households: household: - members: [person1, person2, person3] + members: [person1, person2] state_code: NE output: - ne_adc_countable_earned_income: 1_000 - # After 50% disregard: $2,000 * 0.50 = $1,000 - # Countable income = $1,000 ne_adc_income_eligible: false - # Countable income ($1,000) > Need standard ($881) + ne_adc_resources_eligible: true ne_adc_eligible: false -- name: Case 4, income exactly at threshold. +- name: Case 3, resources ineligible fails overall. period: 2024-01 input: people: person1: age: 30 - employment_income_before_lsr: 17_640 # $1,470/month -> $735 countable + employment_income_before_lsr: 0 person2: age: 10 spm_units: spm_unit: members: [person1, person2] - spm_unit_cash_assets: 1_000 - is_tanf_enrolled: true + spm_unit_assets: 7_000 # Above $6,000 limit households: household: members: [person1, person2] state_code: NE output: - ne_adc_countable_earned_income: 735 - # After 50% disregard: $1,470 * 0.50 = $735 - # Countable income = $735 ne_adc_income_eligible: true - # Countable income ($735) < Need standard ($741) - ne_adc_eligible: true - -- name: Case 5, income just above threshold. - period: 2024-01 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 17_880 # $1,490/month -> $745 countable - person2: - age: 10 - spm_units: - spm_unit: - members: [person1, person2] - spm_unit_cash_assets: 1_000 - is_tanf_enrolled: true - households: - household: - members: [person1, person2] - state_code: NE - output: - ne_adc_countable_earned_income: 745 - # After 50% disregard: $1,490 * 0.50 = $745 - # Countable income = $745 - ne_adc_income_eligible: false - # Countable income ($745) > Need standard ($741) - ne_adc_eligible: false - -# ============================================================================= -# EDGE CASES - RESOURCE BOUNDARIES (SINGLE PERSON $4,000 LIMIT) -# ============================================================================= - -- name: Edge case, resources exactly at $4,000 limit for single person. - period: 2024-01 - absolute_error_margin: 0.5 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 0 - spm_units: - spm_unit: - members: [person1] - spm_unit_assets: 4_000 - households: - household: - members: [person1] - state_code: NE - output: - spm_unit_size: 1 - ne_adc_resources_eligible: true - # Resources ($4,000) <= Limit ($4,000) -> true - -- name: Edge case, resources one dollar above $4,000 limit for single person. - period: 2024-01 - absolute_error_margin: 0.5 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 0 - spm_units: - spm_unit: - members: [person1] - spm_unit_assets: 4_001 - households: - household: - members: [person1] - state_code: NE - output: - spm_unit_size: 1 ne_adc_resources_eligible: false - # Resources ($4,001) <= Limit ($4,000) -> false ne_adc_eligible: false -- name: Edge case, resources one dollar below $4,000 limit for single person. - period: 2024-01 - absolute_error_margin: 0.5 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 0 - spm_units: - spm_unit: - members: [person1] - spm_unit_assets: 3_999 - households: - household: - members: [person1] - state_code: NE - output: - spm_unit_size: 1 - ne_adc_resources_eligible: true - # Resources ($3,999) <= Limit ($4,000) -> true - # ============================================================================= -# EDGE CASES - RESOURCE BOUNDARIES (TWO+ PERSONS $6,000 LIMIT) +# EDGE CASES - INITIAL VS ONGOING RECIPIENT DISREGARD # ============================================================================= -- name: Edge case, resources exactly at $6,000 limit for family of 2. +- name: Edge case, initial applicant fails but ongoing recipient would pass. + # Same income: initial applicant (80% countable) fails, ongoing (50% countable) passes period: 2024-01 - absolute_error_margin: 0.5 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 0 - person2: - age: 10 - spm_units: - spm_unit: - members: [person1, person2] - spm_unit_assets: 6_000 - households: - household: - members: [person1, person2] - state_code: NE - output: - spm_unit_size: 2 - ne_adc_resources_eligible: true - # Resources ($6,000) <= Limit ($6,000) -> true - ne_adc_eligible: true - -- name: Edge case, resources one dollar above $6,000 limit for family of 2. - period: 2024-01 - absolute_error_margin: 0.5 input: people: person1: age: 30 - employment_income_before_lsr: 0 + employment_income_before_lsr: 14_400 # $1,200/month gross person2: age: 10 spm_units: spm_unit: members: [person1, person2] - spm_unit_assets: 6_001 + spm_unit_cash_assets: 1_000 + is_tanf_enrolled: false # Initial applicant households: household: members: [person1, person2] state_code: NE output: - spm_unit_size: 2 - ne_adc_resources_eligible: false - # Resources ($6,001) <= Limit ($6,000) -> false + ne_adc_countable_earned_income: 960 + # After 20% disregard: $1,200 * 0.80 = $960 + ne_adc_income_eligible: false + # Countable ($960) > Need Standard ($741) -> FAILS ne_adc_eligible: false -- name: Edge case, resources one dollar below $6,000 limit for family of 2. +- name: Edge case, ongoing recipient passes with same income as failing initial applicant. + # Same income as above: ongoing recipient (50% countable) passes period: 2024-01 - absolute_error_margin: 0.5 input: people: person1: age: 30 - employment_income_before_lsr: 0 + employment_income_before_lsr: 14_400 # $1,200/month gross person2: age: 10 spm_units: spm_unit: members: [person1, person2] - spm_unit_assets: 5_999 + spm_unit_cash_assets: 1_000 + is_tanf_enrolled: true # Ongoing recipient households: household: members: [person1, person2] state_code: NE output: - spm_unit_size: 2 - ne_adc_resources_eligible: true - # Resources ($5,999) <= Limit ($6,000) -> true + ne_adc_countable_earned_income: 600 + # After 50% disregard: $1,200 * 0.50 = $600 + ne_adc_income_eligible: true + # Countable ($600) < Need Standard ($741) -> PASSES ne_adc_eligible: true # ============================================================================= diff --git a/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_income_eligible.yaml new file mode 100644 index 00000000000..8841e66a750 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_income_eligible.yaml @@ -0,0 +1,120 @@ +# Nebraska ADC Income Eligibility Tests +# Per 468 NAC: countable income must be strictly less than need standard +# Countable income = countable earned + unearned income + +- name: Case 1, zero income is eligible. + period: 2024-01 + input: + people: + person1: + age: 30 + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc_countable_income: 0 + ne_adc_need_standard: 741 + ne_adc_income_eligible: true + # Countable ($0) < Need Standard ($741) -> true + +- name: Case 2, income below threshold is eligible. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 12_000 # $1,000/month -> $500 countable + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + is_tanf_enrolled: true + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc_countable_income: 500 + ne_adc_need_standard: 741 + ne_adc_income_eligible: true + # Countable ($500) < Need Standard ($741) -> true + +- name: Case 3, income above threshold is ineligible. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 24_000 # $2,000/month -> $1,000 countable + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + is_tanf_enrolled: true + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc_countable_income: 1_000 + ne_adc_need_standard: 741 + ne_adc_income_eligible: false + # Countable ($1,000) < Need Standard ($741) -> false + +- name: Case 4, income exactly at threshold is ineligible. + # Tests strict less-than comparison + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 17_784 # $1,482/month -> $741 countable + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + is_tanf_enrolled: true + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc_countable_income: 741 + ne_adc_need_standard: 741 + ne_adc_income_eligible: false + # Countable ($741) < Need Standard ($741) -> false (not strictly less) + +- name: Case 5, mixed income at threshold is ineligible. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 6_000 # $500/month -> $250 countable earned + social_security: 5_892 # $491/month unearned + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + is_tanf_enrolled: true + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc_countable_earned_income: 250 + ne_adc_countable_income: 741 + # Total = $250 + $491 = $741 + ne_adc_need_standard: 741 + ne_adc_income_eligible: false + # Countable ($741) < Need Standard ($741) -> false diff --git a/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_maximum_benefit.yaml b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_maximum_benefit.yaml new file mode 100644 index 00000000000..da32ac8df4d --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_maximum_benefit.yaml @@ -0,0 +1,110 @@ +# Nebraska ADC Maximum Benefit Tests +# Gap Budgeting Formula: +# Gap = max(Need Standard - Countable Earned Income, 0) +# Maximum Benefit = min(Gap, Payment Standard) +# +# NOTE: This is BEFORE unearned income deduction (final benefit subtracts unearned) + +- name: Case 1, zero income gap exceeds payment standard. + period: 2024-01 + absolute_error_margin: 1 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 0 + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc_need_standard: 741 + ne_adc_payment_standard: 408 + ne_adc_countable_earned_income: 0 + ne_adc_maximum_benefit: 408 + # Gap = $741 - $0 = $741 + # Benefit = min($741, $408) = $408 + +- name: Case 2, income reduces gap below payment standard. + period: 2024-01 + absolute_error_margin: 1 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 8_400 # $700/month -> $350 countable + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + is_tanf_enrolled: true + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc_need_standard: 741 + ne_adc_payment_standard: 408 + ne_adc_countable_earned_income: 350 + ne_adc_maximum_benefit: 391 + # Gap = $741 - $350 = $391 + # Benefit = min($391, $408) = $391 + +- name: Case 3, high income negative gap becomes zero. + period: 2024-01 + absolute_error_margin: 1 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 24_000 # $2,000/month -> $1,000 countable + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + is_tanf_enrolled: true + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_adc_need_standard: 741 + ne_adc_countable_earned_income: 1_000 + ne_adc_maximum_benefit: 0 + # Gap = $741 - $1,000 = -$259 -> max(-259, 0) = $0 + # Benefit = min($0, $408) = $0 + +- name: Case 4, larger family higher standards. + period: 2024-01 + absolute_error_margin: 1 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 12_000 # $1,000/month -> $500 countable + person2: + age: 10 + person3: + age: 8 + spm_units: + spm_unit: + members: [person1, person2, person3] + is_tanf_enrolled: true + households: + household: + members: [person1, person2, person3] + state_code: NE + output: + ne_adc_need_standard: 881 + ne_adc_payment_standard: 485 + ne_adc_countable_earned_income: 500 + ne_adc_maximum_benefit: 381 + # Gap = $881 - $500 = $381 + # Benefit = min($381, $485) = $381 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_need_standard.yaml b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_need_standard.yaml index 8b112ad6353..f580e8d7c41 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_need_standard.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_need_standard.yaml @@ -113,86 +113,6 @@ ne_adc_need_standard: 1_441 # Need standard for size 7 = $1,441 -# ============================================================================= -# EDGE CASES - FAMILY SIZE BOUNDARIES -# ============================================================================= - -- name: Edge case, family size 10 at table maximum. - period: 2024-01 - absolute_error_margin: 0.5 - input: - people: - person1: - age: 35 - person2: - age: 33 - person3: - age: 17 - person4: - age: 16 - person5: - age: 15 - person6: - age: 14 - person7: - age: 13 - person8: - age: 12 - person9: - age: 11 - person10: - age: 10 - spm_units: - spm_unit: - members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10] - households: - household: - members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10] - state_code: NE - output: - spm_unit_size: 10 - ne_adc_need_standard: 1_861 - # Need standard for size 10 = $1,861 - -- name: Edge case, family size 11 uses additional person increment. - period: 2024-01 - absolute_error_margin: 0.5 - input: - people: - person1: - age: 35 - person2: - age: 33 - person3: - age: 17 - person4: - age: 16 - person5: - age: 15 - person6: - age: 14 - person7: - age: 13 - person8: - age: 12 - person9: - age: 11 - person10: - age: 10 - person11: - age: 9 - spm_units: - spm_unit: - members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10, person11] - households: - household: - members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10, person11] - state_code: NE - output: - spm_unit_size: 11 - ne_adc_need_standard: 2_001 - # Need standard for size 11 = $1,861 + $140 = $2,001 - - name: Edge case, family size 14 uses additional person increment. period: 2024-01 absolute_error_margin: 0.5 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_resources_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_resources_eligible.yaml new file mode 100644 index 00000000000..2d33d23ca33 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/adc/ne_adc_resources_eligible.yaml @@ -0,0 +1,86 @@ +# Nebraska ADC Resources Eligibility Tests +# Per Neb. Rev. Stat. 68-1726(1): +# - $4,000 limit for single person +# - $6,000 limit for 2+ persons + +- name: Case 1, single person at resource limit. + period: 2024-01 + input: + people: + person1: + age: 30 + is_pregnant: true + spm_units: + spm_unit: + members: [person1] + spm_unit_assets: 4_000 + households: + household: + members: [person1] + state_code: NE + output: + spm_unit_size: 1 + ne_adc_resources_eligible: true + # Resources ($4,000) <= Limit ($4,000) -> true + +- name: Case 2, single person above resource limit. + period: 2024-01 + input: + people: + person1: + age: 30 + is_pregnant: true + spm_units: + spm_unit: + members: [person1] + spm_unit_assets: 4_001 + households: + household: + members: [person1] + state_code: NE + output: + spm_unit_size: 1 + ne_adc_resources_eligible: false + # Resources ($4,001) > Limit ($4,000) -> false + +- name: Case 3, family at resource limit. + period: 2024-01 + input: + people: + person1: + age: 30 + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 6_000 + households: + household: + members: [person1, person2] + state_code: NE + output: + spm_unit_size: 2 + ne_adc_resources_eligible: true + # Resources ($6,000) <= Limit ($6,000) -> true + +- name: Case 4, family above resource limit. + period: 2024-01 + input: + people: + person1: + age: 30 + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 6_001 + households: + household: + members: [person1, person2] + state_code: NE + output: + spm_unit_size: 2 + ne_adc_resources_eligible: false + # Resources ($6,001) > Limit ($6,000) -> false diff --git a/policyengine_us/variables/gov/states/ne/dhhs/adc/benefit/ne_adc_need_standard.py b/policyengine_us/variables/gov/states/ne/dhhs/adc/benefit/ne_adc_need_standard.py index 74d9d8045ed..3afa90eb505 100644 --- a/policyengine_us/variables/gov/states/ne/dhhs/adc/benefit/ne_adc_need_standard.py +++ b/policyengine_us/variables/gov/states/ne/dhhs/adc/benefit/ne_adc_need_standard.py @@ -15,7 +15,7 @@ class ne_adc_need_standard(Variable): def formula(spm_unit, period, parameters): p = parameters(period).gov.states.ne.dhhs.adc - size = spm_unit("spm_unit_size", period) + size = spm_unit("spm_unit_size", period.this_year) # Parameter table defines sizes 1-10; for larger sizes, add increment per person max_table_size = p.max_unit_size capped_size = min_(size, max_table_size) From 343b3818bdc709d70717b7f1821533418417f024 Mon Sep 17 00:00:00 2001 From: Ziming Date: Thu, 25 Dec 2025 15:13:13 -0500 Subject: [PATCH 8/8] uv --- uv.lock | 143 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 71 insertions(+), 72 deletions(-) diff --git a/uv.lock b/uv.lock index 0c06d6e488c..8b7ecb78323 100644 --- a/uv.lock +++ b/uv.lock @@ -586,7 +586,7 @@ version = "3.15.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, - { name = "numpy", version = "2.3.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "numpy", version = "2.4.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/4d/6a/0d79de0b025aa85dc8864de8e97659c94cf3d23148394a954dc5ca52f8c8/h5py-3.15.1.tar.gz", hash = "sha256:c86e3ed45c4473564de55aa83b6fc9e5ead86578773dfbd93047380042e26b69", size = 426236, upload-time = "2025-10-16T10:35:27.404Z" } wheels = [ @@ -714,14 +714,14 @@ wheels = [ [[package]] name = "importlib-metadata" -version = "8.7.0" +version = "8.7.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "zipp" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/76/66/650a33bd90f786193e4de4b3ad86ea60b53c89b669a5c7be931fac31cdb0/importlib_metadata-8.7.0.tar.gz", hash = "sha256:d13b81ad223b890aa16c5471f2ac3056cf76c5f10f82d6f9292f0b415f389000", size = 56641, upload-time = "2025-04-27T15:29:01.736Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f3/49/3b30cad09e7771a4982d9975a8cbf64f00d4a1ececb53297f1d9a7be1b10/importlib_metadata-8.7.1.tar.gz", hash = "sha256:49fef1ae6440c182052f407c8d34a68f72efc36db9ca90dc0113398f2fdde8bb", size = 57107, upload-time = "2025-12-21T10:00:19.278Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/20/b0/36bd937216ec521246249be3bf9855081de4c5e06a0c9b4219dbeda50373/importlib_metadata-8.7.0-py3-none-any.whl", hash = "sha256:e5dd1551894c77868a30651cef00984d50e1002d06942a7101d34870c5f02afd", size = 27656, upload-time = "2025-04-27T15:29:00.214Z" }, + { url = "https://files.pythonhosted.org/packages/fa/5e/f8e9a1d23b9c20a551a8a02ea3637b4642e22c2626e3a13a9a29cdea99eb/importlib_metadata-8.7.1-py3-none-any.whl", hash = "sha256:5a1f80bf1daa489495071efbb095d75a634cf28a8bc299581244063b53176151", size = 27865, upload-time = "2025-12-21T10:00:18.329Z" }, ] [[package]] @@ -1079,7 +1079,7 @@ version = "1.1.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, - { name = "numpy", version = "2.3.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "numpy", version = "2.4.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "pandas" }, ] sdist = { url = "https://files.pythonhosted.org/packages/31/e9/7f77ee19b2d3dcdb561ceaeb915ef6a944eb315412d0e8065c12817b7ff4/microdf_python-1.1.1.tar.gz", hash = "sha256:97dd0cb8562d98a32bbd35861719ae565544143e2ad8a462d6f6261058d9c469", size = 17290, upload-time = "2025-12-01T14:13:57.131Z" } @@ -1089,19 +1089,19 @@ wheels = [ [[package]] name = "mistune" -version = "3.1.4" +version = "3.2.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d7/02/a7fb8b21d4d55ac93cdcde9d3638da5dd0ebdd3a4fed76c7725e10b81cbe/mistune-3.1.4.tar.gz", hash = "sha256:b5a7f801d389f724ec702840c11d8fc48f2b33519102fc7ee739e8177b672164", size = 94588, upload-time = "2025-08-29T07:20:43.594Z" } +sdist = { url = "https://files.pythonhosted.org/packages/9d/55/d01f0c4b45ade6536c51170b9043db8b2ec6ddf4a35c7ea3f5f559ac935b/mistune-3.2.0.tar.gz", hash = "sha256:708487c8a8cdd99c9d90eb3ed4c3ed961246ff78ac82f03418f5183ab70e398a", size = 95467, upload-time = "2025-12-23T11:36:34.994Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/7a/f0/8282d9641415e9e33df173516226b404d367a0fc55e1a60424a152913abc/mistune-3.1.4-py3-none-any.whl", hash = "sha256:93691da911e5d9d2e23bc54472892aff676df27a75274962ff9edc210364266d", size = 53481, upload-time = "2025-08-29T07:20:42.218Z" }, + { url = "https://files.pythonhosted.org/packages/9b/f7/4a5e785ec9fbd65146a27b6b70b6cdc161a66f2024e4b04ac06a67f5578b/mistune-3.2.0-py3-none-any.whl", hash = "sha256:febdc629a3c78616b94393c6580551e0e34cc289987ec6c35ed3f4be42d0eee1", size = 53598, upload-time = "2025-12-23T11:36:33.211Z" }, ] [[package]] name = "nbclient" -version = "0.10.3" +version = "0.10.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "jupyter-client" }, @@ -1109,9 +1109,9 @@ dependencies = [ { name = "nbformat" }, { name = "traitlets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/8d/f3/1f6cf2ede4b026bc5f0b424cb41adf22f9c804e90a4dbd4fdb42291a35d5/nbclient-0.10.3.tar.gz", hash = "sha256:0baf171ee246e3bb2391da0635e719f27dc77d99aef59e0b04dcb935ee04c575", size = 62564, upload-time = "2025-12-19T15:50:09.331Z" } +sdist = { url = "https://files.pythonhosted.org/packages/56/91/1c1d5a4b9a9ebba2b4e32b8c852c2975c872aec1fe42ab5e516b2cecd193/nbclient-0.10.4.tar.gz", hash = "sha256:1e54091b16e6da39e297b0ece3e10f6f29f4ac4e8ee515d29f8a7099bd6553c9", size = 62554, upload-time = "2025-12-23T07:45:46.369Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b2/77/0c73678f5260501a271fd7342bee5d639440f2e9e07d590f1100a056d87c/nbclient-0.10.3-py3-none-any.whl", hash = "sha256:39e9bd403504dd2484dd0fd25235bb6a683ce8cd9873356e40d880696adc9e35", size = 25473, upload-time = "2025-12-19T15:50:07.671Z" }, + { url = "https://files.pythonhosted.org/packages/83/a0/5b0c2f11142ed1dddec842457d3f65eaf71a0080894eb6f018755b319c3a/nbclient-0.10.4-py3-none-any.whl", hash = "sha256:9162df5a7373d70d606527300a95a975a47c137776cd942e52d9c7e29ff83440", size = 25465, upload-time = "2025-12-23T07:45:44.51Z" }, ] [[package]] @@ -1203,7 +1203,7 @@ version = "2.14.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, - { name = "numpy", version = "2.3.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "numpy", version = "2.4.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/cb/2f/fdba158c9dbe5caca9c3eca3eaffffb251f2fb8674bf8e2d0aed5f38d319/numexpr-2.14.1.tar.gz", hash = "sha256:4be00b1086c7b7a5c32e31558122b7b80243fe098579b170967da83f3152b48b", size = 119400, upload-time = "2025-10-13T16:17:27.351Z" } wheels = [ @@ -1316,65 +1316,64 @@ wheels = [ [[package]] name = "numpy" -version = "2.3.5" +version = "2.4.0" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.12'", "python_full_version == '3.11.*'", ] -sdist = { url = "https://files.pythonhosted.org/packages/76/65/21b3bc86aac7b8f2862db1e808f1ea22b028e30a225a34a5ede9bf8678f2/numpy-2.3.5.tar.gz", hash = "sha256:784db1dcdab56bf0517743e746dfb0f885fc68d948aba86eeec2cba234bdf1c0", size = 20584950, upload-time = "2025-11-16T22:52:42.067Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/43/77/84dd1d2e34d7e2792a236ba180b5e8fcc1e3e414e761ce0253f63d7f572e/numpy-2.3.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:de5672f4a7b200c15a4127042170a694d4df43c992948f5e1af57f0174beed10", size = 17034641, upload-time = "2025-11-16T22:49:19.336Z" }, - { url = "https://files.pythonhosted.org/packages/2a/ea/25e26fa5837106cde46ae7d0b667e20f69cbbc0efd64cba8221411ab26ae/numpy-2.3.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:acfd89508504a19ed06ef963ad544ec6664518c863436306153e13e94605c218", size = 12528324, upload-time = "2025-11-16T22:49:22.582Z" }, - { url = "https://files.pythonhosted.org/packages/4d/1a/e85f0eea4cf03d6a0228f5c0256b53f2df4bc794706e7df019fc622e47f1/numpy-2.3.5-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:ffe22d2b05504f786c867c8395de703937f934272eb67586817b46188b4ded6d", size = 5356872, upload-time = "2025-11-16T22:49:25.408Z" }, - { url = "https://files.pythonhosted.org/packages/5c/bb/35ef04afd567f4c989c2060cde39211e4ac5357155c1833bcd1166055c61/numpy-2.3.5-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:872a5cf366aec6bb1147336480fef14c9164b154aeb6542327de4970282cd2f5", size = 6893148, upload-time = "2025-11-16T22:49:27.549Z" }, - { url = "https://files.pythonhosted.org/packages/f2/2b/05bbeb06e2dff5eab512dfc678b1cc5ee94d8ac5956a0885c64b6b26252b/numpy-2.3.5-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3095bdb8dd297e5920b010e96134ed91d852d81d490e787beca7e35ae1d89cf7", size = 14557282, upload-time = "2025-11-16T22:49:30.964Z" }, - { url = "https://files.pythonhosted.org/packages/65/fb/2b23769462b34398d9326081fad5655198fcf18966fcb1f1e49db44fbf31/numpy-2.3.5-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8cba086a43d54ca804ce711b2a940b16e452807acebe7852ff327f1ecd49b0d4", size = 16897903, upload-time = "2025-11-16T22:49:34.191Z" }, - { url = "https://files.pythonhosted.org/packages/ac/14/085f4cf05fc3f1e8aa95e85404e984ffca9b2275a5dc2b1aae18a67538b8/numpy-2.3.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6cf9b429b21df6b99f4dee7a1218b8b7ffbbe7df8764dc0bd60ce8a0708fed1e", size = 16341672, upload-time = "2025-11-16T22:49:37.2Z" }, - { url = "https://files.pythonhosted.org/packages/6f/3b/1f73994904142b2aa290449b3bb99772477b5fd94d787093e4f24f5af763/numpy-2.3.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:396084a36abdb603546b119d96528c2f6263921c50df3c8fd7cb28873a237748", size = 18838896, upload-time = "2025-11-16T22:49:39.727Z" }, - { url = "https://files.pythonhosted.org/packages/cd/b9/cf6649b2124f288309ffc353070792caf42ad69047dcc60da85ee85fea58/numpy-2.3.5-cp311-cp311-win32.whl", hash = "sha256:b0c7088a73aef3d687c4deef8452a3ac7c1be4e29ed8bf3b366c8111128ac60c", size = 6563608, upload-time = "2025-11-16T22:49:42.079Z" }, - { url = "https://files.pythonhosted.org/packages/aa/44/9fe81ae1dcc29c531843852e2874080dc441338574ccc4306b39e2ff6e59/numpy-2.3.5-cp311-cp311-win_amd64.whl", hash = "sha256:a414504bef8945eae5f2d7cb7be2d4af77c5d1cb5e20b296c2c25b61dff2900c", size = 13078442, upload-time = "2025-11-16T22:49:43.99Z" }, - { url = "https://files.pythonhosted.org/packages/6d/a7/f99a41553d2da82a20a2f22e93c94f928e4490bb447c9ff3c4ff230581d3/numpy-2.3.5-cp311-cp311-win_arm64.whl", hash = "sha256:0cd00b7b36e35398fa2d16af7b907b65304ef8bb4817a550e06e5012929830fa", size = 10458555, upload-time = "2025-11-16T22:49:47.092Z" }, - { url = "https://files.pythonhosted.org/packages/44/37/e669fe6cbb2b96c62f6bbedc6a81c0f3b7362f6a59230b23caa673a85721/numpy-2.3.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:74ae7b798248fe62021dbf3c914245ad45d1a6b0cb4a29ecb4b31d0bfbc4cc3e", size = 16733873, upload-time = "2025-11-16T22:49:49.84Z" }, - { url = "https://files.pythonhosted.org/packages/c5/65/df0db6c097892c9380851ab9e44b52d4f7ba576b833996e0080181c0c439/numpy-2.3.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ee3888d9ff7c14604052b2ca5535a30216aa0a58e948cdd3eeb8d3415f638769", size = 12259838, upload-time = "2025-11-16T22:49:52.863Z" }, - { url = "https://files.pythonhosted.org/packages/5b/e1/1ee06e70eb2136797abe847d386e7c0e830b67ad1d43f364dd04fa50d338/numpy-2.3.5-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:612a95a17655e213502f60cfb9bf9408efdc9eb1d5f50535cc6eb365d11b42b5", size = 5088378, upload-time = "2025-11-16T22:49:55.055Z" }, - { url = "https://files.pythonhosted.org/packages/6d/9c/1ca85fb86708724275103b81ec4cf1ac1d08f465368acfc8da7ab545bdae/numpy-2.3.5-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:3101e5177d114a593d79dd79658650fe28b5a0d8abeb8ce6f437c0e6df5be1a4", size = 6628559, upload-time = "2025-11-16T22:49:57.371Z" }, - { url = "https://files.pythonhosted.org/packages/74/78/fcd41e5a0ce4f3f7b003da85825acddae6d7ecb60cf25194741b036ca7d6/numpy-2.3.5-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b973c57ff8e184109db042c842423ff4f60446239bd585a5131cc47f06f789d", size = 14250702, upload-time = "2025-11-16T22:49:59.632Z" }, - { url = "https://files.pythonhosted.org/packages/b6/23/2a1b231b8ff672b4c450dac27164a8b2ca7d9b7144f9c02d2396518352eb/numpy-2.3.5-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0d8163f43acde9a73c2a33605353a4f1bc4798745a8b1d73183b28e5b435ae28", size = 16606086, upload-time = "2025-11-16T22:50:02.127Z" }, - { url = "https://files.pythonhosted.org/packages/a0/c5/5ad26fbfbe2012e190cc7d5003e4d874b88bb18861d0829edc140a713021/numpy-2.3.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:51c1e14eb1e154ebd80e860722f9e6ed6ec89714ad2db2d3aa33c31d7c12179b", size = 16025985, upload-time = "2025-11-16T22:50:04.536Z" }, - { url = "https://files.pythonhosted.org/packages/d2/fa/dd48e225c46c819288148d9d060b047fd2a6fb1eb37eae25112ee4cb4453/numpy-2.3.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b46b4ec24f7293f23adcd2d146960559aaf8020213de8ad1909dba6c013bf89c", size = 18542976, upload-time = "2025-11-16T22:50:07.557Z" }, - { url = "https://files.pythonhosted.org/packages/05/79/ccbd23a75862d95af03d28b5c6901a1b7da4803181513d52f3b86ed9446e/numpy-2.3.5-cp312-cp312-win32.whl", hash = "sha256:3997b5b3c9a771e157f9aae01dd579ee35ad7109be18db0e85dbdbe1de06e952", size = 6285274, upload-time = "2025-11-16T22:50:10.746Z" }, - { url = "https://files.pythonhosted.org/packages/2d/57/8aeaf160312f7f489dea47ab61e430b5cb051f59a98ae68b7133ce8fa06a/numpy-2.3.5-cp312-cp312-win_amd64.whl", hash = "sha256:86945f2ee6d10cdfd67bcb4069c1662dd711f7e2a4343db5cecec06b87cf31aa", size = 12782922, upload-time = "2025-11-16T22:50:12.811Z" }, - { url = "https://files.pythonhosted.org/packages/78/a6/aae5cc2ca78c45e64b9ef22f089141d661516856cf7c8a54ba434576900d/numpy-2.3.5-cp312-cp312-win_arm64.whl", hash = "sha256:f28620fe26bee16243be2b7b874da327312240a7cdc38b769a697578d2100013", size = 10194667, upload-time = "2025-11-16T22:50:16.16Z" }, - { url = "https://files.pythonhosted.org/packages/db/69/9cde09f36da4b5a505341180a3f2e6fadc352fd4d2b7096ce9778db83f1a/numpy-2.3.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:d0f23b44f57077c1ede8c5f26b30f706498b4862d3ff0a7298b8411dd2f043ff", size = 16728251, upload-time = "2025-11-16T22:50:19.013Z" }, - { url = "https://files.pythonhosted.org/packages/79/fb/f505c95ceddd7027347b067689db71ca80bd5ecc926f913f1a23e65cf09b/numpy-2.3.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:aa5bc7c5d59d831d9773d1170acac7893ce3a5e130540605770ade83280e7188", size = 12254652, upload-time = "2025-11-16T22:50:21.487Z" }, - { url = "https://files.pythonhosted.org/packages/78/da/8c7738060ca9c31b30e9301ee0cf6c5ffdbf889d9593285a1cead337f9a5/numpy-2.3.5-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:ccc933afd4d20aad3c00bcef049cb40049f7f196e0397f1109dba6fed63267b0", size = 5083172, upload-time = "2025-11-16T22:50:24.562Z" }, - { url = "https://files.pythonhosted.org/packages/a4/b4/ee5bb2537fb9430fd2ef30a616c3672b991a4129bb1c7dcc42aa0abbe5d7/numpy-2.3.5-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:afaffc4393205524af9dfa400fa250143a6c3bc646c08c9f5e25a9f4b4d6a903", size = 6622990, upload-time = "2025-11-16T22:50:26.47Z" }, - { url = "https://files.pythonhosted.org/packages/95/03/dc0723a013c7d7c19de5ef29e932c3081df1c14ba582b8b86b5de9db7f0f/numpy-2.3.5-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9c75442b2209b8470d6d5d8b1c25714270686f14c749028d2199c54e29f20b4d", size = 14248902, upload-time = "2025-11-16T22:50:28.861Z" }, - { url = "https://files.pythonhosted.org/packages/f5/10/ca162f45a102738958dcec8023062dad0cbc17d1ab99d68c4e4a6c45fb2b/numpy-2.3.5-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:11e06aa0af8c0f05104d56450d6093ee639e15f24ecf62d417329d06e522e017", size = 16597430, upload-time = "2025-11-16T22:50:31.56Z" }, - { url = "https://files.pythonhosted.org/packages/2a/51/c1e29be863588db58175175f057286900b4b3327a1351e706d5e0f8dd679/numpy-2.3.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ed89927b86296067b4f81f108a2271d8926467a8868e554eaf370fc27fa3ccaf", size = 16024551, upload-time = "2025-11-16T22:50:34.242Z" }, - { url = "https://files.pythonhosted.org/packages/83/68/8236589d4dbb87253d28259d04d9b814ec0ecce7cb1c7fed29729f4c3a78/numpy-2.3.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:51c55fe3451421f3a6ef9a9c1439e82101c57a2c9eab9feb196a62b1a10b58ce", size = 18533275, upload-time = "2025-11-16T22:50:37.651Z" }, - { url = "https://files.pythonhosted.org/packages/40/56/2932d75b6f13465239e3b7b7e511be27f1b8161ca2510854f0b6e521c395/numpy-2.3.5-cp313-cp313-win32.whl", hash = "sha256:1978155dd49972084bd6ef388d66ab70f0c323ddee6f693d539376498720fb7e", size = 6277637, upload-time = "2025-11-16T22:50:40.11Z" }, - { url = "https://files.pythonhosted.org/packages/0c/88/e2eaa6cffb115b85ed7c7c87775cb8bcf0816816bc98ca8dbfa2ee33fe6e/numpy-2.3.5-cp313-cp313-win_amd64.whl", hash = "sha256:00dc4e846108a382c5869e77c6ed514394bdeb3403461d25a829711041217d5b", size = 12779090, upload-time = "2025-11-16T22:50:42.503Z" }, - { url = "https://files.pythonhosted.org/packages/8f/88/3f41e13a44ebd4034ee17baa384acac29ba6a4fcc2aca95f6f08ca0447d1/numpy-2.3.5-cp313-cp313-win_arm64.whl", hash = "sha256:0472f11f6ec23a74a906a00b48a4dcf3849209696dff7c189714511268d103ae", size = 10194710, upload-time = "2025-11-16T22:50:44.971Z" }, - { url = "https://files.pythonhosted.org/packages/13/cb/71744144e13389d577f867f745b7df2d8489463654a918eea2eeb166dfc9/numpy-2.3.5-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:414802f3b97f3c1eef41e530aaba3b3c1620649871d8cb38c6eaff034c2e16bd", size = 16827292, upload-time = "2025-11-16T22:50:47.715Z" }, - { url = "https://files.pythonhosted.org/packages/71/80/ba9dc6f2a4398e7f42b708a7fdc841bb638d353be255655498edbf9a15a8/numpy-2.3.5-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:5ee6609ac3604fa7780e30a03e5e241a7956f8e2fcfe547d51e3afa5247ac47f", size = 12378897, upload-time = "2025-11-16T22:50:51.327Z" }, - { url = "https://files.pythonhosted.org/packages/2e/6d/db2151b9f64264bcceccd51741aa39b50150de9b602d98ecfe7e0c4bff39/numpy-2.3.5-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:86d835afea1eaa143012a2d7a3f45a3adce2d7adc8b4961f0b362214d800846a", size = 5207391, upload-time = "2025-11-16T22:50:54.542Z" }, - { url = "https://files.pythonhosted.org/packages/80/ae/429bacace5ccad48a14c4ae5332f6aa8ab9f69524193511d60ccdfdc65fa/numpy-2.3.5-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:30bc11310e8153ca664b14c5f1b73e94bd0503681fcf136a163de856f3a50139", size = 6721275, upload-time = "2025-11-16T22:50:56.794Z" }, - { url = "https://files.pythonhosted.org/packages/74/5b/1919abf32d8722646a38cd527bc3771eb229a32724ee6ba340ead9b92249/numpy-2.3.5-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1062fde1dcf469571705945b0f221b73928f34a20c904ffb45db101907c3454e", size = 14306855, upload-time = "2025-11-16T22:50:59.208Z" }, - { url = "https://files.pythonhosted.org/packages/a5/87/6831980559434973bebc30cd9c1f21e541a0f2b0c280d43d3afd909b66d0/numpy-2.3.5-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ce581db493ea1a96c0556360ede6607496e8bf9b3a8efa66e06477267bc831e9", size = 16657359, upload-time = "2025-11-16T22:51:01.991Z" }, - { url = "https://files.pythonhosted.org/packages/dd/91/c797f544491ee99fd00495f12ebb7802c440c1915811d72ac5b4479a3356/numpy-2.3.5-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:cc8920d2ec5fa99875b670bb86ddeb21e295cb07aa331810d9e486e0b969d946", size = 16093374, upload-time = "2025-11-16T22:51:05.291Z" }, - { url = "https://files.pythonhosted.org/packages/74/a6/54da03253afcbe7a72785ec4da9c69fb7a17710141ff9ac5fcb2e32dbe64/numpy-2.3.5-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:9ee2197ef8c4f0dfe405d835f3b6a14f5fee7782b5de51ba06fb65fc9b36e9f1", size = 18594587, upload-time = "2025-11-16T22:51:08.585Z" }, - { url = "https://files.pythonhosted.org/packages/80/e9/aff53abbdd41b0ecca94285f325aff42357c6b5abc482a3fcb4994290b18/numpy-2.3.5-cp313-cp313t-win32.whl", hash = "sha256:70b37199913c1bd300ff6e2693316c6f869c7ee16378faf10e4f5e3275b299c3", size = 6405940, upload-time = "2025-11-16T22:51:11.541Z" }, - { url = "https://files.pythonhosted.org/packages/d5/81/50613fec9d4de5480de18d4f8ef59ad7e344d497edbef3cfd80f24f98461/numpy-2.3.5-cp313-cp313t-win_amd64.whl", hash = "sha256:b501b5fa195cc9e24fe102f21ec0a44dffc231d2af79950b451e0d99cea02234", size = 12920341, upload-time = "2025-11-16T22:51:14.312Z" }, - { url = "https://files.pythonhosted.org/packages/bb/ab/08fd63b9a74303947f34f0bd7c5903b9c5532c2d287bead5bdf4c556c486/numpy-2.3.5-cp313-cp313t-win_arm64.whl", hash = "sha256:a80afd79f45f3c4a7d341f13acbe058d1ca8ac017c165d3fa0d3de6bc1a079d7", size = 10262507, upload-time = "2025-11-16T22:51:16.846Z" }, - { url = "https://files.pythonhosted.org/packages/c6/65/f9dea8e109371ade9c782b4e4756a82edf9d3366bca495d84d79859a0b79/numpy-2.3.5-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:f0963b55cdd70fad460fa4c1341f12f976bb26cb66021a5580329bd498988310", size = 16910689, upload-time = "2025-11-16T22:52:23.247Z" }, - { url = "https://files.pythonhosted.org/packages/00/4f/edb00032a8fb92ec0a679d3830368355da91a69cab6f3e9c21b64d0bb986/numpy-2.3.5-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:f4255143f5160d0de972d28c8f9665d882b5f61309d8362fdd3e103cf7bf010c", size = 12457053, upload-time = "2025-11-16T22:52:26.367Z" }, - { url = "https://files.pythonhosted.org/packages/16/a4/e8a53b5abd500a63836a29ebe145fc1ab1f2eefe1cfe59276020373ae0aa/numpy-2.3.5-pp311-pypy311_pp73-macosx_14_0_arm64.whl", hash = "sha256:a4b9159734b326535f4dd01d947f919c6eefd2d9827466a696c44ced82dfbc18", size = 5285635, upload-time = "2025-11-16T22:52:29.266Z" }, - { url = "https://files.pythonhosted.org/packages/a3/2f/37eeb9014d9c8b3e9c55bc599c68263ca44fdbc12a93e45a21d1d56df737/numpy-2.3.5-pp311-pypy311_pp73-macosx_14_0_x86_64.whl", hash = "sha256:2feae0d2c91d46e59fcd62784a3a83b3fb677fead592ce51b5a6fbb4f95965ff", size = 6801770, upload-time = "2025-11-16T22:52:31.421Z" }, - { url = "https://files.pythonhosted.org/packages/7d/e4/68d2f474df2cb671b2b6c2986a02e520671295647dad82484cde80ca427b/numpy-2.3.5-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ffac52f28a7849ad7576293c0cb7b9f08304e8f7d738a8cb8a90ec4c55a998eb", size = 14391768, upload-time = "2025-11-16T22:52:33.593Z" }, - { url = "https://files.pythonhosted.org/packages/b8/50/94ccd8a2b141cb50651fddd4f6a48874acb3c91c8f0842b08a6afc4b0b21/numpy-2.3.5-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:63c0e9e7eea69588479ebf4a8a270d5ac22763cc5854e9a7eae952a3908103f7", size = 16729263, upload-time = "2025-11-16T22:52:36.369Z" }, - { url = "https://files.pythonhosted.org/packages/2d/ee/346fa473e666fe14c52fcdd19ec2424157290a032d4c41f98127bfb31ac7/numpy-2.3.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:f16417ec91f12f814b10bafe79ef77e70113a2f5f7018640e7425ff979253425", size = 12967213, upload-time = "2025-11-16T22:52:39.38Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/a4/7a/6a3d14e205d292b738db449d0de649b373a59edb0d0b4493821d0a3e8718/numpy-2.4.0.tar.gz", hash = "sha256:6e504f7b16118198f138ef31ba24d985b124c2c469fe8467007cf30fd992f934", size = 20685720, upload-time = "2025-12-20T16:18:19.023Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/26/7e/7bae7cbcc2f8132271967aa03e03954fc1e48aa1f3bf32b29ca95fbef352/numpy-2.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:316b2f2584682318539f0bcaca5a496ce9ca78c88066579ebd11fd06f8e4741e", size = 16940166, upload-time = "2025-12-20T16:15:43.434Z" }, + { url = "https://files.pythonhosted.org/packages/0f/27/6c13f5b46776d6246ec884ac5817452672156a506d08a1f2abb39961930a/numpy-2.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a2718c1de8504121714234b6f8241d0019450353276c88b9453c9c3d92e101db", size = 12641781, upload-time = "2025-12-20T16:15:45.701Z" }, + { url = "https://files.pythonhosted.org/packages/14/1c/83b4998d4860d15283241d9e5215f28b40ac31f497c04b12fa7f428ff370/numpy-2.4.0-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:21555da4ec4a0c942520ead42c3b0dc9477441e085c42b0fbdd6a084869a6f6b", size = 5470247, upload-time = "2025-12-20T16:15:47.943Z" }, + { url = "https://files.pythonhosted.org/packages/54/08/cbce72c835d937795571b0464b52069f869c9e78b0c076d416c5269d2718/numpy-2.4.0-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:413aa561266a4be2d06cd2b9665e89d9f54c543f418773076a76adcf2af08bc7", size = 6799807, upload-time = "2025-12-20T16:15:49.795Z" }, + { url = "https://files.pythonhosted.org/packages/ff/be/2e647961cd8c980591d75cdcd9e8f647d69fbe05e2a25613dc0a2ea5fb1a/numpy-2.4.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0feafc9e03128074689183031181fac0897ff169692d8492066e949041096548", size = 14701992, upload-time = "2025-12-20T16:15:51.615Z" }, + { url = "https://files.pythonhosted.org/packages/a2/fb/e1652fb8b6fd91ce6ed429143fe2e01ce714711e03e5b762615e7b36172c/numpy-2.4.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a8fdfed3deaf1928fb7667d96e0567cdf58c2b370ea2ee7e586aa383ec2cb346", size = 16646871, upload-time = "2025-12-20T16:15:54.129Z" }, + { url = "https://files.pythonhosted.org/packages/62/23/d841207e63c4322842f7cd042ae981cffe715c73376dcad8235fb31debf1/numpy-2.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e06a922a469cae9a57100864caf4f8a97a1026513793969f8ba5b63137a35d25", size = 16487190, upload-time = "2025-12-20T16:15:56.147Z" }, + { url = "https://files.pythonhosted.org/packages/bc/a0/6a842c8421ebfdec0a230e65f61e0dabda6edbef443d999d79b87c273965/numpy-2.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:927ccf5cd17c48f801f4ed43a7e5673a2724bd2171460be3e3894e6e332ef83a", size = 18580762, upload-time = "2025-12-20T16:15:58.524Z" }, + { url = "https://files.pythonhosted.org/packages/0a/d1/c79e0046641186f2134dde05e6181825b911f8bdcef31b19ddd16e232847/numpy-2.4.0-cp311-cp311-win32.whl", hash = "sha256:882567b7ae57c1b1a0250208cc21a7976d8cbcc49d5a322e607e6f09c9e0bd53", size = 6233359, upload-time = "2025-12-20T16:16:00.938Z" }, + { url = "https://files.pythonhosted.org/packages/fc/f0/74965001d231f28184d6305b8cdc1b6fcd4bf23033f6cb039cfe76c9fca7/numpy-2.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:8b986403023c8f3bf8f487c2e6186afda156174d31c175f747d8934dfddf3479", size = 12601132, upload-time = "2025-12-20T16:16:02.484Z" }, + { url = "https://files.pythonhosted.org/packages/65/32/55408d0f46dfebce38017f5bd931affa7256ad6beac1a92a012e1fbc67a7/numpy-2.4.0-cp311-cp311-win_arm64.whl", hash = "sha256:3f3096405acc48887458bbf9f6814d43785ac7ba2a57ea6442b581dedbc60ce6", size = 10573977, upload-time = "2025-12-20T16:16:04.77Z" }, + { url = "https://files.pythonhosted.org/packages/8b/ff/f6400ffec95de41c74b8e73df32e3fff1830633193a7b1e409be7fb1bb8c/numpy-2.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2a8b6bb8369abefb8bd1801b054ad50e02b3275c8614dc6e5b0373c305291037", size = 16653117, upload-time = "2025-12-20T16:16:06.709Z" }, + { url = "https://files.pythonhosted.org/packages/fd/28/6c23e97450035072e8d830a3c411bf1abd1f42c611ff9d29e3d8f55c6252/numpy-2.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2e284ca13d5a8367e43734148622caf0b261b275673823593e3e3634a6490f83", size = 12369711, upload-time = "2025-12-20T16:16:08.758Z" }, + { url = "https://files.pythonhosted.org/packages/bc/af/acbef97b630ab1bb45e6a7d01d1452e4251aa88ce680ac36e56c272120ec/numpy-2.4.0-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:49ff32b09f5aa0cd30a20c2b39db3e669c845589f2b7fc910365210887e39344", size = 5198355, upload-time = "2025-12-20T16:16:10.902Z" }, + { url = "https://files.pythonhosted.org/packages/c1/c8/4e0d436b66b826f2e53330adaa6311f5cac9871a5b5c31ad773b27f25a74/numpy-2.4.0-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:36cbfb13c152b1c7c184ddac43765db8ad672567e7bafff2cc755a09917ed2e6", size = 6545298, upload-time = "2025-12-20T16:16:12.607Z" }, + { url = "https://files.pythonhosted.org/packages/ef/27/e1f5d144ab54eac34875e79037011d511ac57b21b220063310cb96c80fbc/numpy-2.4.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:35ddc8f4914466e6fc954c76527aa91aa763682a4f6d73249ef20b418fe6effb", size = 14398387, upload-time = "2025-12-20T16:16:14.257Z" }, + { url = "https://files.pythonhosted.org/packages/67/64/4cb909dd5ab09a9a5d086eff9586e69e827b88a5585517386879474f4cf7/numpy-2.4.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dc578891de1db95b2a35001b695451767b580bb45753717498213c5ff3c41d63", size = 16363091, upload-time = "2025-12-20T16:16:17.32Z" }, + { url = "https://files.pythonhosted.org/packages/9d/9c/8efe24577523ec6809261859737cf117b0eb6fdb655abdfdc81b2e468ce4/numpy-2.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:98e81648e0b36e325ab67e46b5400a7a6d4a22b8a7c8e8bbfe20e7db7906bf95", size = 16176394, upload-time = "2025-12-20T16:16:19.524Z" }, + { url = "https://files.pythonhosted.org/packages/61/f0/1687441ece7b47a62e45a1f82015352c240765c707928edd8aef875d5951/numpy-2.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d57b5046c120561ba8fa8e4030fbb8b822f3063910fa901ffadf16e2b7128ad6", size = 18287378, upload-time = "2025-12-20T16:16:22.866Z" }, + { url = "https://files.pythonhosted.org/packages/d3/6f/f868765d44e6fc466467ed810ba9d8d6db1add7d4a748abfa2a4c99a3194/numpy-2.4.0-cp312-cp312-win32.whl", hash = "sha256:92190db305a6f48734d3982f2c60fa30d6b5ee9bff10f2887b930d7b40119f4c", size = 5955432, upload-time = "2025-12-20T16:16:25.06Z" }, + { url = "https://files.pythonhosted.org/packages/d4/b5/94c1e79fcbab38d1ca15e13777477b2914dd2d559b410f96949d6637b085/numpy-2.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:680060061adb2d74ce352628cb798cfdec399068aa7f07ba9fb818b2b3305f98", size = 12306201, upload-time = "2025-12-20T16:16:26.979Z" }, + { url = "https://files.pythonhosted.org/packages/70/09/c39dadf0b13bb0768cd29d6a3aaff1fb7c6905ac40e9aaeca26b1c086e06/numpy-2.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:39699233bc72dd482da1415dcb06076e32f60eddc796a796c5fb6c5efce94667", size = 10308234, upload-time = "2025-12-20T16:16:29.417Z" }, + { url = "https://files.pythonhosted.org/packages/a7/0d/853fd96372eda07c824d24adf02e8bc92bb3731b43a9b2a39161c3667cc4/numpy-2.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a152d86a3ae00ba5f47b3acf3b827509fd0b6cb7d3259665e63dafbad22a75ea", size = 16649088, upload-time = "2025-12-20T16:16:31.421Z" }, + { url = "https://files.pythonhosted.org/packages/e3/37/cc636f1f2a9f585434e20a3e6e63422f70bfe4f7f6698e941db52ea1ac9a/numpy-2.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:39b19251dec4de8ff8496cd0806cbe27bf0684f765abb1f4809554de93785f2d", size = 12364065, upload-time = "2025-12-20T16:16:33.491Z" }, + { url = "https://files.pythonhosted.org/packages/ed/69/0b78f37ca3690969beee54103ce5f6021709134e8020767e93ba691a72f1/numpy-2.4.0-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:009bd0ea12d3c784b6639a8457537016ce5172109e585338e11334f6a7bb88ee", size = 5192640, upload-time = "2025-12-20T16:16:35.636Z" }, + { url = "https://files.pythonhosted.org/packages/1d/2a/08569f8252abf590294dbb09a430543ec8f8cc710383abfb3e75cc73aeda/numpy-2.4.0-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:5fe44e277225fd3dff6882d86d3d447205d43532c3627313d17e754fb3905a0e", size = 6541556, upload-time = "2025-12-20T16:16:37.276Z" }, + { url = "https://files.pythonhosted.org/packages/93/e9/a949885a4e177493d61519377952186b6cbfdf1d6002764c664ba28349b5/numpy-2.4.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f935c4493eda9069851058fa0d9e39dbf6286be690066509305e52912714dbb2", size = 14396562, upload-time = "2025-12-20T16:16:38.953Z" }, + { url = "https://files.pythonhosted.org/packages/99/98/9d4ad53b0e9ef901c2ef1d550d2136f5ac42d3fd2988390a6def32e23e48/numpy-2.4.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8cfa5f29a695cb7438965e6c3e8d06e0416060cf0d709c1b1c1653a939bf5c2a", size = 16351719, upload-time = "2025-12-20T16:16:41.503Z" }, + { url = "https://files.pythonhosted.org/packages/28/de/5f3711a38341d6e8dd619f6353251a0cdd07f3d6d101a8fd46f4ef87f895/numpy-2.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ba0cb30acd3ef11c94dc27fbfba68940652492bc107075e7ffe23057f9425681", size = 16176053, upload-time = "2025-12-20T16:16:44.552Z" }, + { url = "https://files.pythonhosted.org/packages/2a/5b/2a3753dc43916501b4183532e7ace862e13211042bceafa253afb5c71272/numpy-2.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:60e8c196cd82cbbd4f130b5290007e13e6de3eca79f0d4d38014769d96a7c475", size = 18277859, upload-time = "2025-12-20T16:16:47.174Z" }, + { url = "https://files.pythonhosted.org/packages/2c/c5/a18bcdd07a941db3076ef489d036ab16d2bfc2eae0cf27e5a26e29189434/numpy-2.4.0-cp313-cp313-win32.whl", hash = "sha256:5f48cb3e88fbc294dc90e215d86fbaf1c852c63dbdb6c3a3e63f45c4b57f7344", size = 5953849, upload-time = "2025-12-20T16:16:49.554Z" }, + { url = "https://files.pythonhosted.org/packages/4f/f1/719010ff8061da6e8a26e1980cf090412d4f5f8060b31f0c45d77dd67a01/numpy-2.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:a899699294f28f7be8992853c0c60741f16ff199205e2e6cdca155762cbaa59d", size = 12302840, upload-time = "2025-12-20T16:16:51.227Z" }, + { url = "https://files.pythonhosted.org/packages/f5/5a/b3d259083ed8b4d335270c76966cb6cf14a5d1b69e1a608994ac57a659e6/numpy-2.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:9198f447e1dc5647d07c9a6bbe2063cc0132728cc7175b39dbc796da5b54920d", size = 10308509, upload-time = "2025-12-20T16:16:53.313Z" }, + { url = "https://files.pythonhosted.org/packages/31/01/95edcffd1bb6c0633df4e808130545c4f07383ab629ac7e316fb44fff677/numpy-2.4.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:74623f2ab5cc3f7c886add4f735d1031a1d2be4a4ae63c0546cfd74e7a31ddf6", size = 12491815, upload-time = "2025-12-20T16:16:55.496Z" }, + { url = "https://files.pythonhosted.org/packages/59/ea/5644b8baa92cc1c7163b4b4458c8679852733fa74ca49c942cfa82ded4e0/numpy-2.4.0-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:0804a8e4ab070d1d35496e65ffd3cf8114c136a2b81f61dfab0de4b218aacfd5", size = 5320321, upload-time = "2025-12-20T16:16:57.468Z" }, + { url = "https://files.pythonhosted.org/packages/26/4e/e10938106d70bc21319bd6a86ae726da37edc802ce35a3a71ecdf1fdfe7f/numpy-2.4.0-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:02a2038eb27f9443a8b266a66911e926566b5a6ffd1a689b588f7f35b81e7dc3", size = 6641635, upload-time = "2025-12-20T16:16:59.379Z" }, + { url = "https://files.pythonhosted.org/packages/b3/8d/a8828e3eaf5c0b4ab116924df82f24ce3416fa38d0674d8f708ddc6c8aac/numpy-2.4.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1889b3a3f47a7b5bee16bc25a2145bd7cb91897f815ce3499db64c7458b6d91d", size = 14456053, upload-time = "2025-12-20T16:17:01.768Z" }, + { url = "https://files.pythonhosted.org/packages/68/a1/17d97609d87d4520aa5ae2dcfb32305654550ac6a35effb946d303e594ce/numpy-2.4.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:85eef4cb5625c47ee6425c58a3502555e10f45ee973da878ac8248ad58c136f3", size = 16401702, upload-time = "2025-12-20T16:17:04.235Z" }, + { url = "https://files.pythonhosted.org/packages/18/32/0f13c1b2d22bea1118356b8b963195446f3af124ed7a5adfa8fdecb1b6ca/numpy-2.4.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6dc8b7e2f4eb184b37655195f421836cfae6f58197b67e3ffc501f1333d993fa", size = 16242493, upload-time = "2025-12-20T16:17:06.856Z" }, + { url = "https://files.pythonhosted.org/packages/ae/23/48f21e3d309fbc137c068a1475358cbd3a901b3987dcfc97a029ab3068e2/numpy-2.4.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:44aba2f0cafd287871a495fb3163408b0bd25bbce135c6f621534a07f4f7875c", size = 18324222, upload-time = "2025-12-20T16:17:09.392Z" }, + { url = "https://files.pythonhosted.org/packages/ac/52/41f3d71296a3dcaa4f456aaa3c6fc8e745b43d0552b6bde56571bb4b4a0f/numpy-2.4.0-cp313-cp313t-win32.whl", hash = "sha256:20c115517513831860c573996e395707aa9fb691eb179200125c250e895fcd93", size = 6076216, upload-time = "2025-12-20T16:17:11.437Z" }, + { url = "https://files.pythonhosted.org/packages/35/ff/46fbfe60ab0710d2a2b16995f708750307d30eccbb4c38371ea9e986866e/numpy-2.4.0-cp313-cp313t-win_amd64.whl", hash = "sha256:b48e35f4ab6f6a7597c46e301126ceba4c44cd3280e3750f85db48b082624fa4", size = 12444263, upload-time = "2025-12-20T16:17:13.182Z" }, + { url = "https://files.pythonhosted.org/packages/a3/e3/9189ab319c01d2ed556c932ccf55064c5d75bb5850d1df7a482ce0badead/numpy-2.4.0-cp313-cp313t-win_arm64.whl", hash = "sha256:4d1cfce39e511069b11e67cd0bd78ceff31443b7c9e5c04db73c7a19f572967c", size = 10378265, upload-time = "2025-12-20T16:17:15.211Z" }, + { url = "https://files.pythonhosted.org/packages/4b/ef/088e7c7342f300aaf3ee5f2c821c4b9996a1bef2aaf6a49cc8ab4883758e/numpy-2.4.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:b54c83f1c0c0f1d748dca0af516062b8829d53d1f0c402be24b4257a9c48ada6", size = 16819003, upload-time = "2025-12-20T16:18:03.41Z" }, + { url = "https://files.pythonhosted.org/packages/ff/ce/a53017b5443b4b84517182d463fc7bcc2adb4faa8b20813f8e5f5aeb5faa/numpy-2.4.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:aabb081ca0ec5d39591fc33018cd4b3f96e1a2dd6756282029986d00a785fba4", size = 12567105, upload-time = "2025-12-20T16:18:05.594Z" }, + { url = "https://files.pythonhosted.org/packages/77/58/5ff91b161f2ec650c88a626c3905d938c89aaadabd0431e6d9c1330c83e2/numpy-2.4.0-pp311-pypy311_pp73-macosx_14_0_arm64.whl", hash = "sha256:8eafe7c36c8430b7794edeab3087dec7bf31d634d92f2af9949434b9d1964cba", size = 5395590, upload-time = "2025-12-20T16:18:08.031Z" }, + { url = "https://files.pythonhosted.org/packages/1d/4e/f1a084106df8c2df8132fc437e56987308e0524836aa7733721c8429d4fe/numpy-2.4.0-pp311-pypy311_pp73-macosx_14_0_x86_64.whl", hash = "sha256:2f585f52b2baf07ff3356158d9268ea095e221371f1074fadea2f42544d58b4d", size = 6709947, upload-time = "2025-12-20T16:18:09.836Z" }, + { url = "https://files.pythonhosted.org/packages/63/09/3d8aeb809c0332c3f642da812ac2e3d74fc9252b3021f8c30c82e99e3f3d/numpy-2.4.0-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:32ed06d0fe9cae27d8fb5f400c63ccee72370599c75e683a6358dd3a4fb50aaf", size = 14535119, upload-time = "2025-12-20T16:18:12.105Z" }, + { url = "https://files.pythonhosted.org/packages/fd/7f/68f0fc43a2cbdc6bb239160c754d87c922f60fbaa0fa3cd3d312b8a7f5ee/numpy-2.4.0-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:57c540ed8fb1f05cb997c6761cd56db72395b0d6985e90571ff660452ade4f98", size = 16475815, upload-time = "2025-12-20T16:18:14.433Z" }, + { url = "https://files.pythonhosted.org/packages/11/73/edeacba3167b1ca66d51b1a5a14697c2c40098b5ffa01811c67b1785a5ab/numpy-2.4.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:a39fb973a726e63223287adc6dafe444ce75af952d711e400f3bf2b36ef55a7b", size = 12489376, upload-time = "2025-12-20T16:18:16.524Z" }, ] [[package]] @@ -1401,7 +1400,7 @@ version = "2.3.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, - { name = "numpy", version = "2.3.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "numpy", version = "2.4.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "python-dateutil" }, { name = "pytz" }, { name = "tzdata" }, @@ -1517,7 +1516,7 @@ dependencies = [ { name = "microdf-python" }, { name = "numexpr" }, { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, - { name = "numpy", version = "2.3.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "numpy", version = "2.4.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "pandas" }, { name = "plotly" }, { name = "psutil" }, @@ -1535,7 +1534,7 @@ wheels = [ [[package]] name = "policyengine-us" -version = "1.469.0" +version = "1.470.1" source = { editable = "." } dependencies = [ { name = "microdf-python" }, @@ -2321,15 +2320,15 @@ wheels = [ [[package]] name = "typer-slim" -version = "0.20.1" +version = "0.21.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "click" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/3f/3d/6a4ec47010e8de34dade20c8e7bce90502b173f62a6b41619523a3fcf562/typer_slim-0.20.1.tar.gz", hash = "sha256:bb9e4f7e6dc31551c8a201383df322b81b0ce37239a5ead302598a2ebb6f7c9c", size = 106113, upload-time = "2025-12-19T16:48:54.206Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f9/3b/2f60ce16f578b1db5b8816d37d6a4d9786b33b76407fc8c13b0b86312c31/typer_slim-0.21.0.tar.gz", hash = "sha256:f2dbd150cfa0fead2242e21fa9f654dfc64773763ddf07c6be9a49ad34f79557", size = 106841, upload-time = "2025-12-25T09:54:55.998Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d8/f9/a273c8b57c69ac1b90509ebda204972265fdc978fbbecc25980786f8c038/typer_slim-0.20.1-py3-none-any.whl", hash = "sha256:8e89c5dbaffe87a4f86f4c7a9e2f7059b5b68c66f558f298969d42ce34f10122", size = 47440, upload-time = "2025-12-19T16:48:52.678Z" }, + { url = "https://files.pythonhosted.org/packages/b4/84/e97abf10e4a699194ff07fd586ec7f4cf867d9d04bead559a65f9e7aff84/typer_slim-0.21.0-py3-none-any.whl", hash = "sha256:92aee2188ac6fc2b2924bd75bb61a340b78bd8cd51fd9735533ce5a856812c8e", size = 47174, upload-time = "2025-12-25T09:54:54.609Z" }, ] [[package]]