From a0b6dcf82f85d5aa44d907b83c20cd066b66afbc Mon Sep 17 00:00:00 2001 From: Ziming Date: Sat, 3 Oct 2026 20:13:13 -0400 Subject: [PATCH 01/16] Add Alaska HAP household and income components --- changelog.d/ak-liheap-wave2b.added.md | 1 + .../gov/states/ak/dpa/hap/fpg_rate.yaml | 13 + .../gov/states/ak/dpa/hap/fpg_year_lag.yaml | 11 + .../ak/dpa/hap/income/business_sources.yaml | 18 + .../hap/income/child_earnings_age_limit.yaml | 11 + .../hap/income/gift_exemption_threshold.yaml | 11 + .../ak/dpa/hap/income/unearned_sources.yaml | 45 + .../ak/dpa/hap/ak_hap_countable_income.yaml | 906 ++++++++++++ .../ak/dpa/hap/ak_hap_household_size.yaml | 281 ++++ .../ak/dpa/hap/ak_hap_income_limit.yaml | 1223 +++++++++++++++++ .../ak/dpa/hap/ak_hap_countable_income.py | 72 + .../ak/dpa/hap/ak_hap_household_size.py | 17 + .../states/ak/dpa/hap/ak_hap_income_limit.py | 29 + 13 files changed, 2638 insertions(+) create mode 100644 changelog.d/ak-liheap-wave2b.added.md create mode 100644 policyengine_us/parameters/gov/states/ak/dpa/hap/fpg_rate.yaml create mode 100644 policyengine_us/parameters/gov/states/ak/dpa/hap/fpg_year_lag.yaml create mode 100644 policyengine_us/parameters/gov/states/ak/dpa/hap/income/business_sources.yaml create mode 100644 policyengine_us/parameters/gov/states/ak/dpa/hap/income/child_earnings_age_limit.yaml create mode 100644 policyengine_us/parameters/gov/states/ak/dpa/hap/income/gift_exemption_threshold.yaml create mode 100644 policyengine_us/parameters/gov/states/ak/dpa/hap/income/unearned_sources.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_countable_income.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_household_size.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_income_limit.yaml create mode 100644 policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_countable_income.py create mode 100644 policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_household_size.py create mode 100644 policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_income_limit.py diff --git a/changelog.d/ak-liheap-wave2b.added.md b/changelog.d/ak-liheap-wave2b.added.md new file mode 100644 index 00000000000..77540172394 --- /dev/null +++ b/changelog.d/ak-liheap-wave2b.added.md @@ -0,0 +1 @@ +Add Alaska HAP household size, countable income and income ceiling components for the FY2027 regular heating rules. diff --git a/policyengine_us/parameters/gov/states/ak/dpa/hap/fpg_rate.yaml b/policyengine_us/parameters/gov/states/ak/dpa/hap/fpg_rate.yaml new file mode 100644 index 00000000000..309ed26afdd --- /dev/null +++ b/policyengine_us/parameters/gov/states/ak/dpa/hap/fpg_rate.yaml @@ -0,0 +1,13 @@ +description: Alaska limits income to this share of federal poverty guidelines for the federal LIHEAP component of its Heating Assistance Program. +values: + 2026-10-01: 1.5 + +metadata: + unit: /1 + period: year + label: Alaska HAP federal LIHEAP income limit FPG rate + reference: + - title: Alaska HAP Manual 3000, Federal LIHEAP and State-funded AAHP Boundaries + href: http://dpaweb.hss.state.ak.us/manuals/HAP/3000/3000_introductions_and_definitions.htm + - title: Alaska HAP Manual Addendum E, FFY2027 Alaska Federal Poverty Income Guidelines + href: http://dpaweb.hss.state.ak.us/manuals/HAP/addendum/addendum_e.htm diff --git a/policyengine_us/parameters/gov/states/ak/dpa/hap/fpg_year_lag.yaml b/policyengine_us/parameters/gov/states/ak/dpa/hap/fpg_year_lag.yaml new file mode 100644 index 00000000000..9fbff890583 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ak/dpa/hap/fpg_year_lag.yaml @@ -0,0 +1,11 @@ +description: Alaska uses federal poverty guidelines from this many years before the modeled heating season under the Heating Assistance Program. +values: + 2026-10-01: 1 + +metadata: + unit: year + period: year + label: Alaska HAP federal poverty guideline year lag + reference: + - title: Alaska HAP Manual Addendum E, FFY2027 Guidelines Based on January 2026 Federal Register Notice + href: http://dpaweb.hss.state.ak.us/manuals/HAP/addendum/addendum_e.htm diff --git a/policyengine_us/parameters/gov/states/ak/dpa/hap/income/business_sources.yaml b/policyengine_us/parameters/gov/states/ak/dpa/hap/income/business_sources.yaml new file mode 100644 index 00000000000..c3df298a23d --- /dev/null +++ b/policyengine_us/parameters/gov/states/ak/dpa/hap/income/business_sources.yaml @@ -0,0 +1,18 @@ +description: Alaska includes these supplied net business income sources under the Heating Assistance Program. +values: + 2026-10-01: + - self_employment_income + - sstb_self_employment_income + - farm_operations_income + - partnership_s_corp_income + +# Existing signed net sources stand in for gross less allowable current costs. +# No second 50% standard expense deduction is applied. Partnership/S-corporation +# aggregate includes its components, which must not also be added separately. +metadata: + unit: list + period: year + label: Alaska HAP supplied net business income sources + reference: + - title: Alaska HAP Manual 3003-4 A-D, Income From Self-Employment + href: http://dpaweb.hss.state.ak.us/manuals/HAP/3003/3003-4_income_from_self-employment.htm diff --git a/policyengine_us/parameters/gov/states/ak/dpa/hap/income/child_earnings_age_limit.yaml b/policyengine_us/parameters/gov/states/ak/dpa/hap/income/child_earnings_age_limit.yaml new file mode 100644 index 00000000000..73fb81677ef --- /dev/null +++ b/policyengine_us/parameters/gov/states/ak/dpa/hap/income/child_earnings_age_limit.yaml @@ -0,0 +1,11 @@ +description: Alaska excludes earnings of qualifying dependent students below this age under the Heating Assistance Program. +values: + 2026-10-01: 18 + +metadata: + unit: year + period: year + label: Alaska HAP child earnings exclusion age limit + reference: + - title: Alaska HAP Manual 3003-2 A(15), Earnings of Elementary and Secondary Students Under Age 18 + href: http://dpaweb.hss.state.ak.us/manuals/HAP/3003/3003-2_noncountable_(exempt)_income.htm diff --git a/policyengine_us/parameters/gov/states/ak/dpa/hap/income/gift_exemption_threshold.yaml b/policyengine_us/parameters/gov/states/ak/dpa/hap/income/gift_exemption_threshold.yaml new file mode 100644 index 00000000000..e8efe76295e --- /dev/null +++ b/policyengine_us/parameters/gov/states/ak/dpa/hap/income/gift_exemption_threshold.yaml @@ -0,0 +1,11 @@ +description: Alaska excludes cash gifts strictly below this monthly amount per person under the Heating Assistance Program. +values: + 2026-10-01: 20 + +metadata: + unit: currency-USD + period: month + label: Alaska HAP monthly cash gift exemption threshold + reference: + - title: Alaska HAP Manual 3003-2 A(24), Cash Gifts + href: http://dpaweb.hss.state.ak.us/manuals/HAP/3003/3003-2_noncountable_(exempt)_income.htm diff --git a/policyengine_us/parameters/gov/states/ak/dpa/hap/income/unearned_sources.yaml b/policyengine_us/parameters/gov/states/ak/dpa/hap/income/unearned_sources.yaml new file mode 100644 index 00000000000..12390f9bee3 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ak/dpa/hap/income/unearned_sources.yaml @@ -0,0 +1,45 @@ +description: Alaska includes these ordinary unearned cash receipts under the Heating Assistance Program. +values: + 2026-10-01: + - social_security + - ssi + - ak_ssp + - pension_income + - retirement_distributions + - railroad_benefits + - survivor_benefits + - veterans_benefits + - disability_benefits + - unemployment_compensation + - workers_compensation + - general_assistance + - strike_benefits + - alimony_income + - child_support_received + - interest_income + - ordinary_dividend_income + - estate_income + - capital_gains + - gambling_winnings + +# ATAP is added once separately. ak_ssp is Alaska Adult Public Assistance, +# distinct from exempt Senior Benefits. General assistance approximates other +# cash public assistance, not exempt vendor-paid relief. PFD, Senior Benefits, SNAP, +# in-kind/vendor benefits, tax refunds and balances are excluded. +# Broad VA/compensation inputs lack exempt-subtype detail. Generic dividends +# cannot identify fully exempt ANCSA payments. Estate income excludes separately +# reported interest/dividends/capital gains, avoiding component duplication. +# Education grants, royalties, foster/adoption receipts, excess reimbursements +# and cash utility reimbursements lack the detail required by the manual. +# A HUD utility allowance alone does not establish a cash reimbursement. +# Military wages must be reported once in employment income; its separate tax +# subset inputs are not added. Combat/work-study/MASST exceptions are unobserved. +metadata: + unit: list + period: year + label: Alaska HAP ordinary unearned income sources + reference: + - title: Alaska HAP Manual 3003-1 B, Countable Unearned Income + href: http://dpaweb.hss.state.ak.us/manuals/HAP/3003/3003-1_countable_income.htm + - title: Alaska HAP Manual 3003-2 A, Non-countable Income + href: http://dpaweb.hss.state.ak.us/manuals/HAP/3003/3003-2_noncountable_(exempt)_income.htm diff --git a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_countable_income.yaml new file mode 100644 index 00000000000..327ed262a84 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_countable_income.yaml @@ -0,0 +1,906 @@ +# Adopted FY2027 HAP manual; supported income components only. +# These tests do not assert final eligibility, heating points or an award. +# Sources: +# http://dpaweb.hss.state.ak.us/manuals/HAP/3003/3003-1_countable_income.htm +# http://dpaweb.hss.state.ak.us/manuals/HAP/3003/3003-2_noncountable_(exempt)_income.htm +# http://dpaweb.hss.state.ak.us/manuals/HAP/3003/3003-4_income_from_self-employment.htm +# http://dpaweb.hss.state.ak.us/manuals/HAP/3003/3003-6_guidelines_for_computing_income.htm +# Annual receipts approximate the application-month rules; computed benefits are supplied. + +# MS 3003-1 A.1 counts gross wages before deductions or garnishments. +- name: "Case 1, gross wages receive no general earned-income deduction." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + employment_income: 12_000 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + households: + household1: + members: ["person1"] + state_code: "AK" + output: + ak_hap_countable_income: 12_000 + +# MS 3003-4 A.7 defines gross less allowable costs; contract accepts already-net input, so no second standard expense deduction. +- name: "Case 2, supplied net self-employment is not reduced by another fifty percent." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + self_employment_income: 6_000 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + households: + household1: + members: ["person1"] + state_code: "AK" + output: + ak_hap_countable_income: 6_000 + +# MS 3003-4 A.7 and supplied-net approximation: 12,000 - 3,000 = 9,000. Prior-period losses and disallowed expenses cannot be reconstructed. +- name: "Case 3, a signed current net business loss can offset other current income." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + employment_income: 12_000 + self_employment_income: -3_000 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + households: + household1: + members: ["person1"] + state_code: "AK" + output: + ak_hap_countable_income: 9_000 + +# MS 3003-4 A.7 and D.2: 2,000 - 600 + 800 + 600 + 400 = 3,200. Use canonical partnership and S-corporation components. +- name: "Case 4, separate supplied business sources count once without another expense deduction." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + self_employment_income: 2_000 + sstb_self_employment_income: -600 + farm_operations_income: 800 + partnership_income: 600 + s_corp_income: 400 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + households: + household1: + members: ["person1"] + state_code: "AK" + output: + ak_hap_countable_income: 3_200 + +# MS 3003-1 B.6.f and contract nonnegative rental streams: 10,000 + 0 + 600. +- name: "Case 5, negative rental income does not offset positive farm rental income." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + employment_income: 10_000 + rental_income: -300 + farm_rent_income: 600 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + households: + household1: + members: ["person1"] + state_code: "AK" + output: + ak_hap_countable_income: 10_600 + +# Contract floors each reported rental source separately; no extra expense deduction from supplied net rent. +- name: "Case 6, negative farm rental income does not reduce positive rental income." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + rental_income: 1_000 + farm_rent_income: -300 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + households: + household1: + members: ["person1"] + state_code: "AK" + output: + ak_hap_countable_income: 1_000 + +# Contract final household floor after the signed supplied-net approximation. +- name: "Case 7, final household income cannot become negative." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + employment_income: 100 + self_employment_income: -1_000 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + households: + household1: + members: ["person1"] + state_code: "AK" + output: + ak_hap_countable_income: 0 + +# MS 3003-6 E includes otherwise countable income of ineligible aliens without proration. +- name: "Case 8, all members income counts in a mixed-status household." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + employment_income: 12_000 + person2: + age: 40 + immigration_status: "UNDOCUMENTED" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + employment_income: 12_000 + spm_units: + spm_unit1: + members: ["person1", "person2"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + households: + household1: + members: ["person1", "person2"] + state_code: "AK" + output: + ak_hap_countable_income: 24_000 + +# MS 3003-2 A.15; existing dependency and school facts approximate parental control and at-least-half-time enrollment. +- name: "Case 9, dependent elementary student earnings are excluded." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + employment_income: 24_000 + person2: + age: 12 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + is_tax_unit_dependent: true + is_in_k12_school: true + is_in_secondary_school: false + employment_income: 1_200 + spm_units: + spm_unit1: + members: ["person1", "person2"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + households: + household1: + members: ["person1", "person2"] + state_code: "AK" + output: + ak_hap_countable_income: 24_000 + +# MS 3003-2 A.15 excludes earned income under age 18; reported secondary-school attendance satisfies the available-input approximation. +- name: "Case 10, dependent secondary student wages and net business income are excluded." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + employment_income: 24_000 + person2: + age: 17 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + is_tax_unit_dependent: true + is_in_k12_school: false + is_in_secondary_school: true + employment_income: 12_000 + self_employment_income: 2_000 + spm_units: + spm_unit1: + members: ["person1", "person2"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + households: + household1: + members: ["person1", "person2"] + state_code: "AK" + output: + ak_hap_countable_income: 24_000 + +# MS 3003-2 A.15 exclusion requires age under 18. +- name: "Case 11, school attendance does not exclude earnings at age eighteen." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + employment_income: 24_000 + person2: + age: 18 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + is_tax_unit_dependent: true + is_in_k12_school: false + is_in_secondary_school: true + employment_income: 12_000 + spm_units: + spm_unit1: + members: ["person1", "person2"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + households: + household1: + members: ["person1", "person2"] + state_code: "AK" + output: + ak_hap_countable_income: 36_000 + +# MS 3003-2 A.15 requires qualifying school attendance. +- name: "Case 12, earnings of a dependent minor outside school count." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + employment_income: 24_000 + person2: + age: 17 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + is_tax_unit_dependent: true + is_in_k12_school: false + is_in_secondary_school: false + employment_income: 12_000 + spm_units: + spm_unit1: + members: ["person1", "person2"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + households: + household1: + members: ["person1", "person2"] + state_code: "AK" + output: + ak_hap_countable_income: 36_000 + +# MS 3003-6 E and contract dependent-child approximation do not exclude a minor household head's earnings. +- name: "Case 13, an independent minor student has countable earnings." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 17 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + is_tax_unit_dependent: false + is_in_k12_school: true + is_in_secondary_school: true + employment_income: 12_000 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + households: + household1: + members: ["person1"] + state_code: "AK" + output: + ak_hap_countable_income: 12_000 + +# MS 3003-1 B.2 and 3003-6 E: 24,000 + 2,400 + 600 + 1,200; school exclusion applies only to earnings. +- name: "Case 14, unearned income of a dependent child remains countable." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + employment_income: 24_000 + person2: + age: 17 + immigration_status: "CITIZEN" + ssi: 2_400 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + is_tax_unit_dependent: true + is_in_secondary_school: true + social_security: 600 + pension_income: 1_200 + spm_units: + spm_unit1: + members: ["person1", "person2"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + households: + household1: + members: ["person1", "person2"] + state_code: "AK" + output: + ak_hap_countable_income: 28_200 + +# MS 3003-1 B.2.c counts gross SSA including Medicare withholding. Contract adds no general medical, childcare or support deduction. +- name: "Case 15, gross Social Security is not reduced by reported medical or support expenses." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + social_security: 18_000 + medicare_part_b_premiums_reported: 2_400 + health_insurance_premiums: 1_200 + other_medical_expenses: 900 + child_support_expense: 600 + alimony_expense: 300 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + childcare_expenses: 1_000 + households: + household1: + members: ["person1"] + state_code: "AK" + output: + ak_hap_countable_income: 18_000 + +# MS 3003-1 B.2 and B.6.c list these ordinary unearned receipts; inputs represent distinct payments. +- name: "Case 16, retirement and regular disability or survivor receipts count." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + pension_income: 2_400 + retirement_distributions: 1_200 + disability_benefits: 600 + survivor_benefits: 600 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + households: + household1: + members: ["person1"] + state_code: "AK" + output: + ak_hap_countable_income: 4_800 + +# MS 3003-1 B.2 and B.6.a,b,j,o: ordinary nonexempt cash receipts. General assistance represents cash paid to the household, not a vendor payment. +- name: "Case 17, ordinary cash assistance and compensation receipts count." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + unemployment_compensation: 600 + workers_compensation: 600 + veterans_benefits: 600 + strike_benefits: 600 + general_assistance: 600 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + households: + household1: + members: ["person1"] + state_code: "AK" + output: + ak_hap_countable_income: 3_000 + +# MS 3003-1 B.6.h; ordinary receipts have no NH-style $50 disregard. Generic dividends cannot identify exempt ANCSA payments. +- name: "Case 18, ordinary interest dividends and estate payments count in full." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + interest_income: 120 + ordinary_dividend_income: 240 + estate_income: 120 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + households: + household1: + members: ["person1"] + state_code: "AK" + output: + ak_hap_countable_income: 480 + +# MS 3003-1 B.6.h. Canonical ordinary dividends aggregate the two components; do not count the aggregate and components again. +- name: "Case 19, canonical dividend components are counted once." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + qualified_dividend_income: 120 + non_qualified_dividend_income: 240 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + households: + household1: + members: ["person1"] + state_code: "AK" + output: + ak_hap_countable_income: 360 + +# MS 3003-1 B.6.v explicitly lists capital gains. +- name: "Case 20, capital gains are countable." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + short_term_capital_gains: 1_000 + long_term_capital_gains: 2_000 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + households: + household1: + members: ["person1"] + state_code: "AK" + output: + ak_hap_countable_income: 3_000 + +# MS 3003-1 B.3 and B.6.e; contract treats support as actually retained and does not impose an unsupported blanket $50 pass-through cap. 600 + 1,200 + 2,400 ATAP. +- name: "Case 21, retained child support and alimony are countable." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + alimony_income: 600 + child_support_received: 1_200 + person2: + age: 4 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + is_tax_unit_dependent: true + spm_units: + spm_unit1: + members: ["person1", "person2"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 2_400 + households: + household1: + members: ["person1", "person2"] + state_code: "AK" + output: + ak_hap_countable_income: 4_200 + +# MS 3003-1 B.1 and 3003-2 A.14; caretaker and children are included. Annual household ATAP of 2,400 counts once. +- name: "Case 22, Alaska Temporary Assistance is counted once per household." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + employment_income: 6_000 + person2: + age: 4 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + is_tax_unit_dependent: true + person3: + age: 2 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + is_tax_unit_dependent: true + spm_units: + spm_unit1: + members: ["person1", "person2", "person3"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 2_400 + households: + household1: + members: ["person1", "person2", "person3"] + state_code: "AK" + output: + ak_hap_countable_income: 8_400 + +# MS 3003-1 B.1 and B.2: supplied annual APA 2,400 plus SSI 6,000. Existing ak_ssp is APA, not exempt Senior Benefits. +- name: "Case 23, Adult Public Assistance and federal SSI are distinct countable receipts." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 68 + immigration_status: "CITIZEN" + ssi: 6_000 + ak_ssp: 2_400 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + households: + household1: + members: ["person1"] + state_code: "AK" + output: + ak_hap_countable_income: 8_400 + +# MS 3003-2 A.24: 239.88 / 12 = 19.99 each month under the authorized constant-receipt proxy. +- name: "Case 24, regular cash gifts strictly below twenty dollars monthly are excluded." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + financial_assistance: 239.88 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + households: + household1: + members: ["person1"] + state_code: "AK" + output: + ak_hap_countable_income: 0 + +# MS 3003-2 A.24 excludes only amounts under $20; contract retains the whole gift at 240 / 12 = 20. +- name: "Case 25, regular cash gifts at twenty dollars monthly count in full." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + financial_assistance: 240 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + households: + household1: + members: ["person1"] + state_code: "AK" + output: + ak_hap_countable_income: 240 + +# MS 3003-1 B.6.r and 3003-2 A.24: 240.12 / 12 = 20.01; this is an exclusion threshold, not a $20 deduction. +- name: "Case 26, regular cash gifts above twenty dollars monthly count in full." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + financial_assistance: 240.12 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + households: + household1: + members: ["person1"] + state_code: "AK" + output: + ak_hap_countable_income: 240.12 + +# MS 3003-2 A.24: each person receives 15 per month, so the annual household sum of 360 remains exempt. +- name: "Case 27, the gift exclusion is per person rather than per household." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + financial_assistance: 180 + person2: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + financial_assistance: 180 + spm_units: + spm_unit1: + members: ["person1", "person2"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + households: + household1: + members: ["person1", "person2"] + state_code: "AK" + output: + ak_hap_countable_income: 0 + +# MS 3003-2 A.1,6,9,30 and the shared contract exclude the household member's PFD, Pell, SNAP and vendor housing benefit. +- name: "Case 28, household PFD and vendor or education benefits are excluded." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 3_000 + employment_income: 10_000 + pell_grant: 2_000 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + snap: 6_000 + housing_assistance: 6_000 + households: + household1: + members: ["person1"] + state_code: "AK" + output: + ak_hap_countable_income: 10_000 + +# MS 3003-2 A.9 counts actual cash utility reimbursement; contract does not infer that a HUD allowance was paid in cash. +- name: "Case 29, a utility allowance is not automatically treated as a cash reimbursement." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + employment_income: 10_000 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + households: + household1: + members: ["person1"] + state_code: "AK" + hud_utility_allowance: 1_200 + output: + ak_hap_countable_income: 10_000 + +# All calculated SSI, APA and ATAP receipts are supplied as zero; no PFD or in-kind income is counted. +- name: "Case 30, zero supplied receipts produce zero countable income." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + households: + household1: + members: ["person1"] + state_code: "AK" + output: + ak_hap_countable_income: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_household_size.yaml b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_household_size.yaml new file mode 100644 index 00000000000..7ed25675136 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_household_size.yaml @@ -0,0 +1,281 @@ +# Adopted FY2027 HAP manual; supported income components only. +# These tests do not assert final eligibility, heating points or an award. +# Sources: +# http://dpaweb.hss.state.ak.us/manuals/HAP/3002/3002-1_households.htm +# http://dpaweb.hss.state.ak.us/manuals/HAP/3003/3003-6_guidelines_for_computing_income.htm +# Annual receipts approximate the application-month rules; computed benefits are supplied. + +# MS 3002-1 A.10 and D: existing qualified-status mapping; finer COFA, battered-person and other unavailable categories remain documented limits. +- name: "Case 1, citizens and existing qualified immigration categories count without a five-year wait." + period: 2027 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + years_since_us_entry: 0 + person2: + age: 40 + immigration_status: "LEGAL_PERMANENT_RESIDENT" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + years_since_us_entry: 0 + person3: + age: 40 + immigration_status: "REFUGEE" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + years_since_us_entry: 0 + person4: + age: 40 + immigration_status: "ASYLEE" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + years_since_us_entry: 0 + person5: + age: 40 + immigration_status: "PAROLED_ONE_YEAR" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + years_since_us_entry: 0 + person6: + age: 40 + immigration_status: "DEPORTATION_WITHHELD" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + years_since_us_entry: 0 + person7: + age: 40 + immigration_status: "CONDITIONAL_ENTRANT" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + years_since_us_entry: 0 + person8: + age: 40 + immigration_status: "CUBAN_HAITIAN_ENTRANT" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + years_since_us_entry: 0 + person9: + age: 40 + immigration_status: "UNDOCUMENTED" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + years_since_us_entry: 0 + person10: + age: 40 + immigration_status: "DACA" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + years_since_us_entry: 0 + person11: + age: 40 + immigration_status: "TPS" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + years_since_us_entry: 0 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + spm_unit2: + members: ["person2"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + spm_unit3: + members: ["person3"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + spm_unit4: + members: ["person4"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + spm_unit5: + members: ["person5"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + spm_unit6: + members: ["person6"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + spm_unit7: + members: ["person7"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + spm_unit8: + members: ["person8"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + spm_unit9: + members: ["person9"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + spm_unit10: + members: ["person10"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + spm_unit11: + members: ["person11"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + households: + household1: + members: ["person1"] + state_code: "AK" + household2: + members: ["person2"] + state_code: "AK" + household3: + members: ["person3"] + state_code: "AK" + household4: + members: ["person4"] + state_code: "AK" + household5: + members: ["person5"] + state_code: "AK" + household6: + members: ["person6"] + state_code: "AK" + household7: + members: ["person7"] + state_code: "AK" + household8: + members: ["person8"] + state_code: "AK" + household9: + members: ["person9"] + state_code: "AK" + household10: + members: ["person10"] + state_code: "AK" + household11: + members: ["person11"] + state_code: "AK" + output: + ak_hap_household_size: [1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0] + +# MS 3002-1 A.10 and D.6: citizen adult, citizen child and refugee count; undocumented adult does not. +- name: "Case 2, mixed status excludes only unqualified members from household size." + period: 2027 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person2: + age: 17 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + is_tax_unit_dependent: true + person3: + age: 40 + immigration_status: "UNDOCUMENTED" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person4: + age: 40 + immigration_status: "REFUGEE" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + years_since_us_entry: 0 + spm_units: + spm_unit1: + members: ["person1", "person2", "person3", "person4"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + households: + household1: + members: ["person1", "person2", "person3", "person4"] + state_code: "AK" + output: + ak_hap_household_size: 3 + +# No final eligibility is asserted. MS 3003-6 E still counts all members' income; contract returns a zero limit for zero qualified size. +- name: "Case 3, an Alaska household without a qualified member has no income ceiling." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "UNDOCUMENTED" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + employment_income: 12_000 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + households: + household1: + members: ["person1"] + state_code: "AK" + output: + ak_hap_household_size: 0 + ak_hap_countable_income: 12_000 + ak_hap_income_limit: 0 + +# Shared contract masks all three components to Alaska; MS 3002-1 B requires Alaska residence. +- name: "Case 4, all supported HAP components are zero outside Alaska." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + employment_income: 12_000 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + households: + household1: + members: ["person1"] + state_code: "WA" + output: + ak_hap_household_size: 0 + ak_hap_countable_income: 0 + ak_hap_income_limit: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_income_limit.yaml b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_income_limit.yaml new file mode 100644 index 00000000000..b9955dd64ae --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_income_limit.yaml @@ -0,0 +1,1223 @@ +# Adopted FY2027 HAP manual; supported income components only. +# These tests do not assert final eligibility, heating points or an award. +# Sources: +# http://dpaweb.hss.state.ak.us/manuals/HAP/addendum/addendum_e.htm +# http://dpaweb.hss.state.ak.us/manuals/HAP/3002/3002-1_households.htm +# Annual receipts approximate the application-month rules; computed benefits are supplied. + +# Addendum E FY2027 150% monthly ceilings, sizes 1–18: 2,493; 3,381; 4,267; 5,155; 6,043; 6,930; 7,818; 8,706; 9,592; 10,480; 11,368; 12,255; 13,143; 14,031; 14,917; 15,805; 16,693; 17,580. Each expected annual amount is this published amount times 12. +- name: "Case 1, all eighteen published FY2027 federal LIHEAP ceilings annualize the literal monthly column." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person2: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person3: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person4: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person5: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person6: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person7: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person8: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person9: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person10: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person11: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person12: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person13: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person14: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person15: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person16: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person17: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person18: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person19: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person20: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person21: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person22: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person23: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person24: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person25: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person26: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person27: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person28: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person29: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person30: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person31: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person32: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person33: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person34: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person35: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person36: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person37: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person38: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person39: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person40: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person41: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person42: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person43: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person44: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person45: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person46: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person47: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person48: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person49: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person50: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person51: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person52: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person53: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person54: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person55: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person56: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person57: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person58: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person59: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person60: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person61: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person62: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person63: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person64: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person65: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person66: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person67: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person68: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person69: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person70: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person71: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person72: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person73: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person74: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person75: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person76: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person77: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person78: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person79: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person80: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person81: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person82: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person83: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person84: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person85: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person86: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person87: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person88: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person89: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person90: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person91: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person92: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person93: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person94: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person95: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person96: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person97: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person98: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person99: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person100: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person101: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person102: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person103: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person104: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person105: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person106: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person107: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person108: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person109: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person110: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person111: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person112: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person113: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person114: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person115: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person116: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person117: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person118: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person119: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person120: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person121: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person122: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person123: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person124: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person125: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person126: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person127: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person128: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person129: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person130: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person131: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person132: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person133: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person134: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person135: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person136: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person137: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person138: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person139: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person140: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person141: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person142: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person143: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person144: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person145: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person146: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person147: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person148: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person149: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person150: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person151: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person152: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person153: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person154: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person155: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person156: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person157: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person158: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person159: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person160: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person161: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person162: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person163: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person164: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person165: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person166: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person167: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person168: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person169: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person170: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person171: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + spm_unit2: + members: ["person2", "person3"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + spm_unit4: + members: ["person4", "person5", "person6"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + spm_unit7: + members: ["person7", "person8", "person9", "person10"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + spm_unit11: + members: ["person11", "person12", "person13", "person14", "person15"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + spm_unit16: + members: ["person16", "person17", "person18", "person19", "person20", "person21"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + spm_unit22: + members: ["person22", "person23", "person24", "person25", "person26", "person27", "person28"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + spm_unit29: + members: ["person29", "person30", "person31", "person32", "person33", "person34", "person35", "person36"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + spm_unit37: + members: ["person37", "person38", "person39", "person40", "person41", "person42", "person43", "person44", "person45"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + spm_unit46: + members: ["person46", "person47", "person48", "person49", "person50", "person51", "person52", "person53", "person54", "person55"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + spm_unit56: + members: ["person56", "person57", "person58", "person59", "person60", "person61", "person62", "person63", "person64", "person65", "person66"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + spm_unit67: + members: ["person67", "person68", "person69", "person70", "person71", "person72", "person73", "person74", "person75", "person76", "person77", "person78"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + spm_unit79: + members: ["person79", "person80", "person81", "person82", "person83", "person84", "person85", "person86", "person87", "person88", "person89", "person90", "person91"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + spm_unit92: + members: ["person92", "person93", "person94", "person95", "person96", "person97", "person98", "person99", "person100", "person101", "person102", "person103", "person104", "person105"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + spm_unit106: + members: ["person106", "person107", "person108", "person109", "person110", "person111", "person112", "person113", "person114", "person115", "person116", "person117", "person118", "person119", "person120"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + spm_unit121: + members: ["person121", "person122", "person123", "person124", "person125", "person126", "person127", "person128", "person129", "person130", "person131", "person132", "person133", "person134", "person135", "person136"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + spm_unit137: + members: ["person137", "person138", "person139", "person140", "person141", "person142", "person143", "person144", "person145", "person146", "person147", "person148", "person149", "person150", "person151", "person152", "person153"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + spm_unit154: + members: ["person154", "person155", "person156", "person157", "person158", "person159", "person160", "person161", "person162", "person163", "person164", "person165", "person166", "person167", "person168", "person169", "person170", "person171"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + households: + household1: + members: ["person1"] + state_code: "AK" + household2: + members: ["person2", "person3"] + state_code: "AK" + household4: + members: ["person4", "person5", "person6"] + state_code: "AK" + household7: + members: ["person7", "person8", "person9", "person10"] + state_code: "AK" + household11: + members: ["person11", "person12", "person13", "person14", "person15"] + state_code: "AK" + household16: + members: ["person16", "person17", "person18", "person19", "person20", "person21"] + state_code: "AK" + household22: + members: ["person22", "person23", "person24", "person25", "person26", "person27", "person28"] + state_code: "AK" + household29: + members: ["person29", "person30", "person31", "person32", "person33", "person34", "person35", "person36"] + state_code: "AK" + household37: + members: ["person37", "person38", "person39", "person40", "person41", "person42", "person43", "person44", "person45"] + state_code: "AK" + household46: + members: ["person46", "person47", "person48", "person49", "person50", "person51", "person52", "person53", "person54", "person55"] + state_code: "AK" + household56: + members: ["person56", "person57", "person58", "person59", "person60", "person61", "person62", "person63", "person64", "person65", "person66"] + state_code: "AK" + household67: + members: ["person67", "person68", "person69", "person70", "person71", "person72", "person73", "person74", "person75", "person76", "person77", "person78"] + state_code: "AK" + household79: + members: ["person79", "person80", "person81", "person82", "person83", "person84", "person85", "person86", "person87", "person88", "person89", "person90", "person91"] + state_code: "AK" + household92: + members: ["person92", "person93", "person94", "person95", "person96", "person97", "person98", "person99", "person100", "person101", "person102", "person103", "person104", "person105"] + state_code: "AK" + household106: + members: ["person106", "person107", "person108", "person109", "person110", "person111", "person112", "person113", "person114", "person115", "person116", "person117", "person118", "person119", "person120"] + state_code: "AK" + household121: + members: ["person121", "person122", "person123", "person124", "person125", "person126", "person127", "person128", "person129", "person130", "person131", "person132", "person133", "person134", "person135", "person136"] + state_code: "AK" + household137: + members: ["person137", "person138", "person139", "person140", "person141", "person142", "person143", "person144", "person145", "person146", "person147", "person148", "person149", "person150", "person151", "person152", "person153"] + state_code: "AK" + household154: + members: ["person154", "person155", "person156", "person157", "person158", "person159", "person160", "person161", "person162", "person163", "person164", "person165", "person166", "person167", "person168", "person169", "person170", "person171"] + state_code: "AK" + output: + ak_hap_household_size: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18] + ak_hap_income_limit: [29_916, 40_572, 51_204, 61_860, 72_516, 83_160, 93_816, 104_472, 115_104, 125_760, 136_416, 147_060, 157_716, 168_372, 179_004, 189_660, 200_316, 210_960] + +# MS 3002-1 A.10 and 3003-6 E include both incomes but one qualified member. Addendum E size 1: 2,493 x 12. +- name: "Case 2, mixed status uses the qualified size for the federal ceiling." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + employment_income: 12_000 + person2: + age: 40 + immigration_status: "UNDOCUMENTED" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + employment_income: 12_000 + spm_units: + spm_unit1: + members: ["person1", "person2"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + households: + household1: + members: ["person1", "person2"] + state_code: "AK" + output: + ak_hap_household_size: 1 + ak_hap_countable_income: 24_000 + ak_hap_income_limit: 29_916 diff --git a/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_countable_income.py b/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_countable_income.py new file mode 100644 index 00000000000..8402ea62d54 --- /dev/null +++ b/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_countable_income.py @@ -0,0 +1,72 @@ +from policyengine_us.model_api import * + + +class ak_hap_countable_income(Variable): + value_type = float + entity = SPMUnit + definition_period = YEAR + unit = USD + label = "Alaska HAP countable income" + reference = ( + "http://dpaweb.hss.state.ak.us/manuals/HAP/3003/3003-1_countable_income.htm", + "http://dpaweb.hss.state.ak.us/manuals/HAP/3003/3003-2_noncountable_(exempt)_income.htm", + "http://dpaweb.hss.state.ak.us/manuals/HAP/3003/3003-4_income_from_self-employment.htm", + "http://dpaweb.hss.state.ak.us/manuals/HAP/3003/3003-6_guidelines_for_computing_income.htm", + ) + defined_for = StateCode.AK + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ak.dpa.hap.income + person = spm_unit.members + # Annual inputs approximate prior-month receipts and the alternative + # seasonal/business annualization rules. Include income of all members, + # regardless of whether immigration status permits counting their size. + school = person("is_in_k12_school", period) | person( + "is_in_secondary_school", period + ) + # Dependency and schooling approximate parental control and at least + # half-time elementary/high-school/GED attendance; those details are + # not separately observed. This exclusion applies only to earnings. + exempt_child = ( + (person("age", period) < p.child_earnings_age_limit) + & person("is_tax_unit_dependent", period) + & school + ) + # Supplied signed net business income approximates gross receipts less + # allowable current costs. Do not deduct the 50% expense standard again. + # Prior-period losses, disallowed tax expenses and multiple businesses + # within a source cannot be separated. Partnership/S-corp metadata is + # broader than policy net income; no expense reconstruction is imputed. + earned = max_(person("employment_income", period), 0) + add( + person, period, p.business_sources + ) + countable_earned = spm_unit.sum(where(exempt_child, 0, earned)) + # These are cash receipts, so a tax loss in an unearned source does not + # offset other income. Net rental sources are separately nonnegative. + unearned = spm_unit.sum( + sum(max_(person(source, period), 0) for source in p.unearned_sources) + ) + rental = spm_unit.sum( + max_(person("rental_income", period), 0) + + max_(person("farm_rent_income", period), 0) + ) + gifts = person("financial_assistance", period) + # Existing outside cash support approximates gifts received at a + # constant monthly rate. The manual excludes strictly under $20 per + # person per month; annual data cannot identify irregular receipt dates. + countable_gifts = spm_unit.sum( + where(gifts / MONTHS_IN_YEAR < p.gift_exemption_threshold, 0, gifts) + ) + # Reported support represents retained receipts; assignment/payment + # routes are unavailable, so no ATAP pass-through cap is imputed. + # Gross SSA includes Medicare withholding. No general medical, care, + # support-paid or earned-income deduction is authorized by these rules. + # ATAP is an SPM-unit benefit: count its annual flow exactly once. + total = ( + countable_earned + + unearned + + rental + + countable_gifts + + spm_unit("ak_atap", period) + ) + return max_(total, 0) diff --git a/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_household_size.py b/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_household_size.py new file mode 100644 index 00000000000..356b46cdf6d --- /dev/null +++ b/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_household_size.py @@ -0,0 +1,17 @@ +from policyengine_us.model_api import * + + +class ak_hap_household_size(Variable): + value_type = int + entity = SPMUnit + definition_period = YEAR + label = "Alaska HAP household size" + reference = "http://dpaweb.hss.state.ak.us/manuals/HAP/3002/3002-1_households.htm" + defined_for = StateCode.AK + + # The SPM unit approximates the economic household sharing heating costs. + # Citizenship/status inputs lack finer qualified categories, COFA status, + # documentation and SSN rules. No five-year waiting rule is applied. + # Custody, foster arrangements and separate room-renter households are + # not fully observed. Excluded members' otherwise countable income remains. + adds = ["is_citizen_or_legal_immigrant"] diff --git a/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_income_limit.py b/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_income_limit.py new file mode 100644 index 00000000000..5942ddcd7ed --- /dev/null +++ b/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_income_limit.py @@ -0,0 +1,29 @@ +from policyengine_us.model_api import * +from policyengine_us.variables.gov.hhs.tax_unit_fpg import fpg + + +class ak_hap_income_limit(Variable): + value_type = float + entity = SPMUnit + definition_period = YEAR + unit = USD + label = "Alaska HAP federal LIHEAP income limit" + reference = ( + "http://dpaweb.hss.state.ak.us/manuals/HAP/3000/3000_introductions_and_definitions.htm", + "http://dpaweb.hss.state.ak.us/manuals/HAP/addendum/addendum_e.htm", + ) + defined_for = StateCode.AK + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ak.dpa.hap + size = spm_unit("ak_hap_household_size", period) + state_group = spm_unit.household("state_group_str", period) + guideline = fpg(size, state_group, period, parameters, year_lag=p.fpg_year_lag) + # Numerical reconciliation of all 18 FY2027 published 150% ceilings: + # floor the monthly FPG, apply the rate, then floor the monthly limit. + # The source requires downward rounding but does not state this order. + monthly_limit = np.floor(np.floor(guideline / MONTHS_IN_YEAR) * p.fpg_rate) + # Return the annual equivalent of the published monthly ceiling. + # Beyond published sizes, retain the federal additional-person rule; + # state rounding there and backfilled historical years are unverified. + return where(size > 0, monthly_limit * MONTHS_IN_YEAR, 0) From 5f48a292554abeca0d27b0eab531301a67f285b1 Mon Sep 17 00:00:00 2001 From: Ziming Date: Sat, 3 Oct 2026 21:58:52 -0400 Subject: [PATCH 02/16] Add Alaska HAP base heating benefit components --- changelog.d/ak-liheap-base-benefit.added.md | 1 + .../ak/dpa/hap/benefit/child_age_limit.yaml | 11 + .../benefit/community_points/natural_gas.yaml | 731 +++++ .../dpa/hap/benefit/community_points/oil.yaml | 540 ++++ .../ak/dpa/hap/benefit/dwelling_factor.yaml | 27 + .../ak/dpa/hap/benefit/elderly_age.yaml | 11 + .../ak/dpa/hap/benefit/maximum_points.yaml | 11 + .../ak/dpa/hap/benefit/minimum_expense.yaml | 11 + .../ak/dpa/hap/benefit/minimum_points.yaml | 11 + .../ak/dpa/hap/benefit/point_value.yaml | 11 + .../hap/benefit/tribal_service_places.yaml | 15 + .../dpa/hap/benefit/vulnerability_points.yaml | 11 + .../ak/dpa/hap/income_factor/factors.yaml | 11 + .../ak/dpa/hap/income_factor/fpg_rates.yaml | 11 + .../ak/dpa/hap/ak_hap_base_benefit.yaml | 2412 +++++++++++++++++ .../ak/dpa/hap/ak_hap_income_factor.yaml | 716 +++++ .../states/ak/dpa/hap/ak_hap_base_benefit.py | 92 + .../states/ak/dpa/hap/ak_hap_dwelling_type.py | 33 + .../states/ak/dpa/hap/ak_hap_income_factor.py | 35 + 19 files changed, 4701 insertions(+) create mode 100644 changelog.d/ak-liheap-base-benefit.added.md create mode 100644 policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/child_age_limit.yaml create mode 100644 policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/community_points/natural_gas.yaml create mode 100644 policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/community_points/oil.yaml create mode 100644 policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/dwelling_factor.yaml create mode 100644 policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/elderly_age.yaml create mode 100644 policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/maximum_points.yaml create mode 100644 policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/minimum_expense.yaml create mode 100644 policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/minimum_points.yaml create mode 100644 policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/point_value.yaml create mode 100644 policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/tribal_service_places.yaml create mode 100644 policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/vulnerability_points.yaml create mode 100644 policyengine_us/parameters/gov/states/ak/dpa/hap/income_factor/factors.yaml create mode 100644 policyengine_us/parameters/gov/states/ak/dpa/hap/income_factor/fpg_rates.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_base_benefit.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_income_factor.yaml create mode 100644 policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_base_benefit.py create mode 100644 policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_dwelling_type.py create mode 100644 policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_income_factor.py diff --git a/changelog.d/ak-liheap-base-benefit.added.md b/changelog.d/ak-liheap-base-benefit.added.md new file mode 100644 index 00000000000..d014b943372 --- /dev/null +++ b/changelog.d/ak-liheap-base-benefit.added.md @@ -0,0 +1 @@ +Add Alaska HAP income-band and base heating benefit calculations with dwelling and community points, before household-sharing and utility-allowance adjustments. diff --git a/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/child_age_limit.yaml b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/child_age_limit.yaml new file mode 100644 index 00000000000..e332f608135 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/child_age_limit.yaml @@ -0,0 +1,11 @@ +description: Alaska treats children younger than this age as vulnerable under the Heating Assistance Program. +values: + 2026-10-01: 6 + +metadata: + unit: year + period: year + label: Alaska HAP vulnerable child age limit + reference: + - title: Alaska HAP Manual 3000-2, Vulnerable Populations + href: http://dpaweb.hss.state.ak.us/manuals/HAP/3000/3000-2_definitions.htm diff --git a/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/community_points/natural_gas.yaml b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/community_points/natural_gas.yaml new file mode 100644 index 00000000000..c9c7d3ec6a6 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/community_points/natural_gas.yaml @@ -0,0 +1,731 @@ +description: Alaska assigns these natural gas heating points by Census place under the Heating Assistance Program. +# Derived place crosswalk: 25 direct published matches and 330 nearest-community +# approximations. Great-circle distances use Census internal points, four DEC +# settlement coordinates and five containing-Anchorage-point proxies among +# the 34 published gas communities. This is not a state-issued crosswalk. +"00065": # Adak city + 2026-10-01: 6 +"00650": # Akhiok city + 2026-10-01: 6 +"00760": # Akiachak CDP + 2026-10-01: 6 +"00870": # Akiak city + 2026-10-01: 6 +"01090": # Akutan city + 2026-10-01: 6 +"01200": # Alakanuk city + 2026-10-01: 6 +"01305": # Alatna CDP + 2026-10-01: 8 +"01390": # Alcan Border CDP + 2026-10-01: 8 +"01420": # Aleknagik city + 2026-10-01: 6 +"01560": # Aleneva CDP + 2026-10-01: 6 +"01860": # Allakaket city + 2026-10-01: 8 +"01970": # Ambler city + 2026-10-01: 6 +"02080": # Anaktuvuk Pass city + 2026-10-01: 6 +"03000": # Anchorage municipality + 2026-10-01: 5 +"03110": # Anchor Point CDP + 2026-10-01: 6 +"03220": # Anderson city + 2026-10-01: 8 +"03440": # Angoon city + 2026-10-01: 5 +"03550": # Aniak city + 2026-10-01: 6 +"03880": # Anvik city + 2026-10-01: 6 +"03990": # Arctic Village CDP + 2026-10-01: 8 +"04210": # Atka city + 2026-10-01: 6 +"04430": # Atmautluak CDP + 2026-10-01: 6 +"04500": # Atqasuk city + 2026-10-01: 6 +"04670": # Attu Station CDP + 2026-10-01: 6 +"05000": # Badger CDP + 2026-10-01: 8 +"05585": # Bear Creek CDP + 2026-10-01: 6 +"05750": # Beaver CDP + 2026-10-01: 8 +"06245": # Beluga CDP + 2026-10-01: 6 +"06520": # Bethel city + 2026-10-01: 6 +"06630": # Bettles city + 2026-10-01: 8 +"06850": # Big Delta CDP + 2026-10-01: 8 +"07070": # Big Lake CDP + 2026-10-01: 5 +"07620": # Birch Creek CDP + 2026-10-01: 8 +"08740": # Brevig Mission city + 2026-10-01: 6 +"09600": # Buckland city + 2026-10-01: 6 +"09657": # Buffalo Soapstone CDP + 2026-10-01: 5 +"09710": # Butte CDP + 2026-10-01: 5 +"10150": # Cantwell CDP + 2026-10-01: 8 +"11690": # Central CDP + 2026-10-01: 8 +"11800": # Chalkyitsik CDP + 2026-10-01: 8 +"12350": # Chase CDP + 2026-10-01: 5 +"12680": # Chefornak city + 2026-10-01: 6 +"12920": # Chena Ridge CDP + 2026-10-01: 8 +"12970": # Chenega CDP + 2026-10-01: 5 +"13230": # Chevak city + 2026-10-01: 6 +"13340": # Chickaloon CDP + 2026-10-01: 5 +"13450": # Chicken CDP + 2026-10-01: 8 +"13550": # Chignik city + 2026-10-01: 6 +"13670": # Chignik Lagoon CDP + 2026-10-01: 6 +"13780": # Chignik Lake CDP + 2026-10-01: 6 +"13860": # Chiniak CDP + 2026-10-01: 6 +"13890": # Chisana CDP + 2026-10-01: 5 +"14000": # Chistochina CDP + 2026-10-01: 5 +"14110": # Chitina CDP + 2026-10-01: 5 +"14330": # Chuathbaluk city + 2026-10-01: 6 +"14880": # Circle CDP + 2026-10-01: 8 +"15320": # Clam Gulch CDP + 2026-10-01: 6 +"15430": # Clark's Point city + 2026-10-01: 6 +"16360": # Coffman Cove city + 2026-10-01: 5 +"16420": # Cohoe CDP + 2026-10-01: 6 +"16530": # Cold Bay city + 2026-10-01: 6 +"16630": # Coldfoot CDP + 2026-10-01: 8 +"16750": # College CDP + 2026-10-01: 8 +"17190": # Cooper Landing CDP + 2026-10-01: 6 +"17300": # Copper Center CDP + 2026-10-01: 5 +"17410": # Cordova city + 2026-10-01: 5 +"17670": # Covenant Life CDP + 2026-10-01: 5 +"17740": # Craig city + 2026-10-01: 5 +"17850": # Crooked Creek CDP + 2026-10-01: 6 +"17960": # Crown Point CDP + 2026-10-01: 6 +"18510": # Deering city + 2026-10-01: 6 +"18620": # Delta Junction city + 2026-10-01: 8 +"18675": # Deltana CDP + 2026-10-01: 8 +"18805": # Denali Park CDP + 2026-10-01: 8 +"18925": # Diamond Ridge CDP + 2026-10-01: 6 +"18950": # Dillingham city + 2026-10-01: 6 +"19060": # Diomede city + 2026-10-01: 6 +"19720": # Dot Lake CDP + 2026-10-01: 8 +"19750": # Dot Lake Village CDP + 2026-10-01: 8 +"20020": # Dry Creek CDP + 2026-10-01: 8 +"20380": # Eagle city + 2026-10-01: 8 +"20600": # Eagle Village CDP + 2026-10-01: 8 +"20716": # Eareckson Station CDP + 2026-10-01: 6 +"20970": # Edna Bay city + 2026-10-01: 5 +"21040": # Eek city + 2026-10-01: 6 +"21150": # Egegik city + 2026-10-01: 6 +"21370": # Eielson AFB CDP + 2026-10-01: 8 +"21810": # Ekwok city + 2026-10-01: 6 +"22140": # Elfin Cove CDP + 2026-10-01: 5 +"22250": # Elim city + 2026-10-01: 6 +"22910": # Emmonak city + 2026-10-01: 6 +"23460": # Ester CDP + 2026-10-01: 8 +"23720": # Eureka Roadhouse CDP + 2026-10-01: 5 +"23790": # Evansville CDP + 2026-10-01: 8 +"23900": # Excursion Inlet CDP + 2026-10-01: 5 +"24230": # Fairbanks city + 2026-10-01: 8 +"24660": # False Pass city + 2026-10-01: 6 +"24980": # Farmers Loop CDP + 2026-10-01: 8 +"25000": # Farm Loop CDP + 2026-10-01: 5 +"25220": # Ferry CDP + 2026-10-01: 8 +"25550": # Fishhook CDP + 2026-10-01: 5 +"25880": # Flat CDP + 2026-10-01: 6 +"26100": # Fort Greely CDP + 2026-10-01: 8 +"26760": # Fort Yukon city + 2026-10-01: 8 +"26835": # Four Mile Road CDP + 2026-10-01: 8 +"26870": # Fox CDP + 2026-10-01: 8 +"26910": # Fox River CDP + 2026-10-01: 6 +"27090": # Fritz Creek CDP + 2026-10-01: 6 +"27145": # Funny River CDP + 2026-10-01: 6 +"27420": # Gakona CDP + 2026-10-01: 5 +"27530": # Galena city + 2026-10-01: 8 +"27640": # Gambell city + 2026-10-01: 6 +"27700": # Game Creek CDP + 2026-10-01: 5 +"28200": # Gateway CDP + 2026-10-01: 5 +"28590": # Glacier View CDP + 2026-10-01: 5 +"28740": # Glennallen CDP + 2026-10-01: 5 +"29130": # Goldstream CDP + 2026-10-01: 8 +"29180": # Golovin city + 2026-10-01: 6 +"29290": # Goodnews Bay city + 2026-10-01: 6 +"30060": # Grayling city + 2026-10-01: 6 +"30500": # Gulkana CDP + 2026-10-01: 5 +"30940": # Gustavus city + 2026-10-01: 5 +"31050": # Haines CDP + 2026-10-01: 5 +"31270": # Halibut Cove CDP + 2026-10-01: 6 +"31710": # Happy Valley CDP + 2026-10-01: 6 +"31765": # Harding-Birch Lakes CDP + 2026-10-01: 8 +"32150": # Healy CDP + 2026-10-01: 8 +"32310": # Healy Lake CDP + 2026-10-01: 8 +"32550": # Hobart Bay CDP + 2026-10-01: 5 +"32810": # Hollis CDP + 2026-10-01: 5 +"33030": # Holy Cross city + 2026-10-01: 6 +"33140": # Homer city + 2026-10-01: 6 +"33360": # Hoonah city + 2026-10-01: 5 +"33470": # Hooper Bay city + 2026-10-01: 6 +"33580": # Hope CDP + 2026-10-01: 5 +"33800": # Houston city + 2026-10-01: 5 +"33910": # Hughes city + 2026-10-01: 8 +"34350": # Huslia city + 2026-10-01: 8 +"34460": # Hydaburg city + 2026-10-01: 5 +"34570": # Hyder CDP + 2026-10-01: 5 +"34790": # Igiugig CDP + 2026-10-01: 6 +"35120": # Iliamna CDP + 2026-10-01: 6 +"35890": # Ivanof Bay CDP + 2026-10-01: 6 +"36400": # Juneau city and borough + 2026-10-01: 5 +"36540": # Kachemak city + 2026-10-01: 6 +"36770": # Kake city + 2026-10-01: 5 +"36990": # Kaktovik city + 2026-10-01: 6 +"37250": # Kalifornsky CDP + 2026-10-01: 6 +"37430": # Kaltag city + 2026-10-01: 6 +"37540": # Karluk CDP + 2026-10-01: 6 +"37650": # Kasaan city + 2026-10-01: 5 +"37975": # Kasigluk CDP + 2026-10-01: 6 +"38090": # Kasilof CDP + 2026-10-01: 6 +"38420": # Kenai city + 2026-10-01: 6 +"38910": # Kenny Lake CDP + 2026-10-01: 5 +"38970": # Ketchikan city + 2026-10-01: 5 +"39300": # Kiana city + 2026-10-01: 6 +"39410": # King Cove city + 2026-10-01: 6 +"39630": # King Salmon CDP + 2026-10-01: 6 +"39740": # Kipnuk CDP + 2026-10-01: 6 +"39960": # Kivalina city + 2026-10-01: 6 +"40400": # Klawock city + 2026-10-01: 5 +"40510": # Klukwan CDP + 2026-10-01: 5 +"40645": # Knik-Fairview CDP + 2026-10-01: 5 +"40670": # Knik River CDP + 2026-10-01: 5 +"40840": # Kobuk city + 2026-10-01: 8 +"40950": # Kodiak city + 2026-10-01: 6 +"41210": # Kodiak Station CDP + 2026-10-01: 6 +"41280": # Kokhanok CDP + 2026-10-01: 6 +"41500": # Koliganek CDP + 2026-10-01: 6 +"41610": # Kongiganak CDP + 2026-10-01: 6 +"41720": # Kotlik city + 2026-10-01: 6 +"41830": # Kotzebue city + 2026-10-01: 6 +"41940": # Koyuk city + 2026-10-01: 8 +"42050": # Koyukuk city + 2026-10-01: 8 +"42160": # Kupreanof city + 2026-10-01: 5 +"42380": # Kwethluk city + 2026-10-01: 6 +"42490": # Kwigillingok CDP + 2026-10-01: 6 +"42805": # Lake Louise CDP + 2026-10-01: 5 +"42820": # Lake Minchumina CDP + 2026-10-01: 8 +"43040": # Larsen Bay city + 2026-10-01: 6 +"43260": # Lazy Mountain CDP + 2026-10-01: 5 +"43810": # Levelock CDP + 2026-10-01: 6 +"44030": # Lime Village CDP + 2026-10-01: 6 +"44580": # Livengood CDP + 2026-10-01: 8 +"45020": # Loring CDP + 2026-10-01: 5 +"45295": # Lowell Point CDP + 2026-10-01: 6 +"45460": # Lower Kalskag city + 2026-10-01: 6 +"45700": # Lutak CDP + 2026-10-01: 5 +"45790": # McCarthy CDP + 2026-10-01: 5 +"46010": # McGrath city + 2026-10-01: 6 +"46780": # Manley Hot Springs CDP + 2026-10-01: 8 +"46890": # Manokotak city + 2026-10-01: 6 +"47000": # Marshall city + 2026-10-01: 6 +"47735": # Meadow Lakes CDP + 2026-10-01: 5 +"47990": # Mekoryuk city + 2026-10-01: 6 +"48200": # Mendeltna CDP + 2026-10-01: 5 +"48540": # Mentasta Lake CDP + 2026-10-01: 8 +"48590": # Mertarvik CDP + 2026-10-01: 6 +"48870": # Metlakatla CDP + 2026-10-01: 5 +"49200": # Mill Bay CDP + 2026-10-01: 6 +"49530": # Minto CDP + 2026-10-01: 8 +"50080": # Moose Creek CDP + 2026-10-01: 8 +"50190": # Moose Pass CDP + 2026-10-01: 6 +"50800": # Mosquito Lake CDP + 2026-10-01: 5 +"51180": # Mountain Village city + 2026-10-01: 6 +"51455": # Mud Bay CDP + 2026-10-01: 5 +"51960": # Nabesna CDP + 2026-10-01: 5 +"52060": # Naknek CDP + 2026-10-01: 6 +"52210": # Nanwalek CDP + 2026-10-01: 6 +"52390": # Napakiak city + 2026-10-01: 6 +"52720": # Napaskiak city + 2026-10-01: 6 +"52845": # Naukati Bay CDP + 2026-10-01: 5 +"52915": # Nelchina CDP + 2026-10-01: 5 +"52940": # Nelson Lagoon CDP + 2026-10-01: 6 +"53050": # Nenana city + 2026-10-01: 8 +"53270": # Newhalen city + 2026-10-01: 6 +"53710": # New Stuyahok city + 2026-10-01: 6 +"53820": # Newtok CDP + 2026-10-01: 6 +"53930": # Nightmute city + 2026-10-01: 6 +"54050": # Nikiski CDP + 2026-10-01: 6 +"54085": # Nikolaevsk CDP + 2026-10-01: 6 +"54150": # Nikolai city + 2026-10-01: 6 +"54260": # Nikolski CDP + 2026-10-01: 6 +"54480": # Ninilchik CDP + 2026-10-01: 6 +"54700": # Noatak CDP + 2026-10-01: 6 +"54920": # Nome city + 2026-10-01: 6 +"55030": # Nondalton city + 2026-10-01: 6 +"55140": # Noorvik city + 2026-10-01: 6 +"55745": # North Lakes CDP + 2026-10-01: 5 +"55910": # North Pole city + 2026-10-01: 8 +"56220": # Northway CDP + 2026-10-01: 8 +"56320": # Nuiqsut city + 2026-10-01: 6 +"56350": # Nulato city + 2026-10-01: 8 +"56600": # Nunam Iqua city + 2026-10-01: 6 +"56680": # Nunapitchuk city + 2026-10-01: 6 +"57340": # Old Harbor city + 2026-10-01: 6 +"58330": # Oscarville CDP + 2026-10-01: 6 +"58550": # Ouzinkie city + 2026-10-01: 6 +"58660": # Palmer city + 2026-10-01: 5 +"59320": # Paxson CDP + 2026-10-01: 5 +"59540": # Pedro Bay CDP + 2026-10-01: 6 +"59650": # Pelican city + 2026-10-01: 5 +"60200": # Perryville CDP + 2026-10-01: 6 +"60310": # Petersburg CDP + 2026-10-01: 5 +"60460": # Petersville CDP + 2026-10-01: 5 +"60640": # Pilot Point city + 2026-10-01: 6 +"60750": # Pilot Station city + 2026-10-01: 6 +"60860": # Pitkas Point CDP + 2026-10-01: 6 +"61080": # Platinum city + 2026-10-01: 6 +"61120": # Pleasant Valley CDP + 2026-10-01: 8 +"61190": # Point Baker CDP + 2026-10-01: 5 +"61630": # Point Hope city + 2026-10-01: 6 +"61700": # Point Lay CDP + 2026-10-01: 6 +"61788": # Point MacKenzie CDP + 2026-10-01: 5 +"61825": # Point Possession CDP + 2026-10-01: 6 +"62125": # Pope-Vannoy Landing CDP + 2026-10-01: 6 +"62285": # Portage Creek CDP + 2026-10-01: 6 +"62510": # Port Alexander city + 2026-10-01: 5 +"62620": # Port Alsworth CDP + 2026-10-01: 6 +"63170": # Port Clarence CDP + 2026-10-01: 6 +"63280": # Port Graham CDP + 2026-10-01: 6 +"63390": # Port Heiden city + 2026-10-01: 6 +"63610": # Port Lions city + 2026-10-01: 6 +"63870": # Port Protection CDP + 2026-10-01: 5 +"64240": # Primrose CDP + 2026-10-01: 6 +"64380": # Prudhoe Bay CDP + 2026-10-01: 6 +"64600": # Quinhagak city + 2026-10-01: 6 +"64820": # Rampart CDP + 2026-10-01: 8 +"64930": # Red Devil CDP + 2026-10-01: 6 +"64980": # Red Dog Mine CDP + 2026-10-01: 6 +"65345": # Ridgeway CDP + 2026-10-01: 6 +"65590": # Ruby city + 2026-10-01: 8 +"65700": # Russian Mission city + 2026-10-01: 6 +"65800": # St. George city + 2026-10-01: 6 +"66140": # St. Mary's city + 2026-10-01: 6 +"66360": # St. Michael city + 2026-10-01: 6 +"66470": # St. Paul city + 2026-10-01: 6 +"66510": # Salamatof CDP + 2026-10-01: 6 +"66550": # Salcha CDP + 2026-10-01: 8 +"67020": # Sand Point city + 2026-10-01: 6 +"67460": # Savoonga city + 2026-10-01: 6 +"67570": # Saxman city + 2026-10-01: 5 +"67680": # Scammon Bay city + 2026-10-01: 6 +"68230": # Selawik city + 2026-10-01: 6 +"68340": # Seldovia city + 2026-10-01: 6 +"68370": # Seldovia Village CDP + 2026-10-01: 6 +"68560": # Seward city + 2026-10-01: 6 +"68670": # Shageluk city + 2026-10-01: 6 +"68890": # Shaktoolik city + 2026-10-01: 6 +"69770": # Shishmaref city + 2026-10-01: 6 +"70100": # Shungnak city + 2026-10-01: 6 +"70320": # Silver Springs CDP + 2026-10-01: 5 +"70540": # Sitka city and borough + 2026-10-01: 5 +"70760": # Skagway CDP + 2026-10-01: 5 +"70870": # Skwentna CDP + 2026-10-01: 5 +"70930": # Slana CDP + 2026-10-01: 5 +"71090": # Sleetmute CDP + 2026-10-01: 6 +"71640": # Soldotna city + 2026-10-01: 6 +"72135": # South Lakes CDP + 2026-10-01: 5 +"72190": # South Naknek CDP + 2026-10-01: 6 +"72230": # South Van Horn CDP + 2026-10-01: 8 +"72960": # Stebbins city + 2026-10-01: 6 +"72985": # Steele Creek CDP + 2026-10-01: 8 +"73070": # Sterling CDP + 2026-10-01: 6 +"73290": # Stevens Village CDP + 2026-10-01: 8 +"73400": # Stony River CDP + 2026-10-01: 6 +"73950": # Sunrise CDP + 2026-10-01: 5 +"74340": # Susitna CDP + 2026-10-01: 5 +"74350": # Susitna North CDP + 2026-10-01: 5 +"74525": # Sutton-Alpine CDP + 2026-10-01: 5 +"74610": # Takotna CDP + 2026-10-01: 6 +"74830": # Talkeetna CDP + 2026-10-01: 5 +"75050": # Tanacross CDP + 2026-10-01: 8 +"75077": # Tanaina CDP + 2026-10-01: 5 +"75160": # Tanana city + 2026-10-01: 8 +"75380": # Tatitlek CDP + 2026-10-01: 5 +"75480": # Tazlina CDP + 2026-10-01: 5 +"75930": # Teller city + 2026-10-01: 6 +"76260": # Tenakee Springs city + 2026-10-01: 5 +"76590": # Tetlin CDP + 2026-10-01: 8 +"77140": # Thorne Bay city + 2026-10-01: 5 +"77690": # Togiak city + 2026-10-01: 6 +"77800": # Tok CDP + 2026-10-01: 8 +"78240": # Toksook Bay city + 2026-10-01: 6 +"78297": # Tolsona CDP + 2026-10-01: 5 +"78350": # Tonsina CDP + 2026-10-01: 5 +"78680": # Trapper Creek CDP + 2026-10-01: 5 +"78790": # Tuluksak CDP + 2026-10-01: 6 +"79120": # Tuntutuliak CDP + 2026-10-01: 6 +"79230": # Tununak CDP + 2026-10-01: 6 +"79780": # Twin Hills CDP + 2026-10-01: 6 +"79830": # Two Rivers CDP + 2026-10-01: 8 +"79890": # Tyonek CDP + 2026-10-01: 6 +"80100": # Ugashik CDP + 2026-10-01: 6 +"80660": # Unalakleet city + 2026-10-01: 6 +"80770": # Unalaska city + 2026-10-01: 6 +"81320": # Upper Kalskag city + 2026-10-01: 6 +"81920": # Utqiaġvik city + 2026-10-01: 6 +"82200": # Valdez city + 2026-10-01: 5 +"82420": # Venetie CDP + 2026-10-01: 8 +"82750": # Wainwright city + 2026-10-01: 6 +"82860": # Wales city + 2026-10-01: 6 +"83080": # Wasilla city + 2026-10-01: 5 +"84000": # Whale Pass city + 2026-10-01: 5 +"84070": # White Mountain city + 2026-10-01: 6 +"84120": # Whitestone CDP + 2026-10-01: 8 +"84200": # Whitestone Logging Camp CDP + 2026-10-01: 5 +"84510": # Whittier city + 2026-10-01: 5 +"85280": # Willow CDP + 2026-10-01: 5 +"85290": # Willow Creek CDP + 2026-10-01: 5 +"85610": # Wiseman CDP + 2026-10-01: 8 +"85680": # Womens Bay CDP + 2026-10-01: 6 +"86380": # Wrangell city and borough + 2026-10-01: 5 +"86490": # Yakutat CDP + 2026-10-01: 5 +UNAVAILABLE: + 2026-10-01: 0 + +metadata: + unit: /1 + period: year + label: Alaska HAP natural gas community heating points + reference: + - title: Alaska HAP Manual Addendum A, FFY2027 Community Listing + href: http://dpaweb.hss.state.ak.us/manuals/HAP/addendum/addendum_a.htm + - title: Alaska HAP Manual 3004-5, Step 1 nearest gas community rule + href: http://dpaweb.hss.state.ak.us/manuals/HAP/3004/3004-5_grant_computation.htm + - title: Census 2025 Alaska Places Gazetteer + href: https://www2.census.gov/geo/docs/maps-data/data/gazetteer/2025_Gazetteer/2025_gaz_place_02.txt + - title: Alaska DEC Cook Inlet Community Profiles, pages 11, 19, 27, 29, 34, 54, 89 + href: https://dec.alaska.gov/media/8211/ciscp-b-resources.pdf#page=11 diff --git a/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/community_points/oil.yaml b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/community_points/oil.yaml new file mode 100644 index 00000000000..b6c25981991 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/community_points/oil.yaml @@ -0,0 +1,540 @@ +description: Alaska assigns these oil heating points by Census place under the Heating Assistance Program. +# Derived Census place crosswalk; unknown or ambiguous places are absent. +# Anchorage oil is ambiguous. FY2027 Loring 4 / Tetlin 12 disagree with +# the older regulatory Appendix values 5 / 16; use this annual manual. +"00650": # Akhiok city + 2026-10-01: 8 +"00760": # Akiachak CDP + 2026-10-01: 21 +"00870": # Akiak city + 2026-10-01: 21 +"01090": # Akutan city + 2026-10-01: 11 +"01200": # Alakanuk city + 2026-10-01: 21 +"01305": # Alatna CDP + 2026-10-01: 27 +"01420": # Aleknagik city + 2026-10-01: 13 +"01860": # Allakaket city + 2026-10-01: 27 +"01970": # Ambler city + 2026-10-01: 35 +"02080": # Anaktuvuk Pass city + 2026-10-01: 16 +"03110": # Anchor Point CDP + 2026-10-01: 6 +"03220": # Anderson city + 2026-10-01: 11 +"03440": # Angoon city + 2026-10-01: 8 +"03550": # Aniak city + 2026-10-01: 21 +"03880": # Anvik city + 2026-10-01: 19 +"03990": # Arctic Village CDP + 2026-10-01: 32 +"04210": # Atka city + 2026-10-01: 6 +"04430": # Atmautluak CDP + 2026-10-01: 19 +"04500": # Atqasuk city + 2026-10-01: 24 +"05750": # Beaver CDP + 2026-10-01: 24 +"06245": # Beluga CDP + 2026-10-01: 7 +"06520": # Bethel city + 2026-10-01: 16 +"06630": # Bettles city + 2026-10-01: 29 +"07070": # Big Lake CDP + 2026-10-01: 7 +"07620": # Birch Creek CDP + 2026-10-01: 27 +"08740": # Brevig Mission city + 2026-10-01: 23 +"09600": # Buckland city + 2026-10-01: 33 +"10150": # Cantwell CDP + 2026-10-01: 11 +"11690": # Central CDP + 2026-10-01: 23 +"11800": # Chalkyitsik CDP + 2026-10-01: 28 +"12350": # Chase CDP + 2026-10-01: 8 +"12680": # Chefornak city + 2026-10-01: 20 +"13230": # Chevak city + 2026-10-01: 25 +"13340": # Chickaloon CDP + 2026-10-01: 8 +"13450": # Chicken CDP + 2026-10-01: 19 +"13550": # Chignik city + 2026-10-01: 9 +"13670": # Chignik Lagoon CDP + 2026-10-01: 9 +"13780": # Chignik Lake CDP + 2026-10-01: 9 +"13860": # Chiniak CDP + 2026-10-01: 6 +"14000": # Chistochina CDP + 2026-10-01: 12 +"14110": # Chitina CDP + 2026-10-01: 11 +"14330": # Chuathbaluk city + 2026-10-01: 21 +"14880": # Circle CDP + 2026-10-01: 23 +"15320": # Clam Gulch CDP + 2026-10-01: 7 +"16360": # Coffman Cove city + 2026-10-01: 6 +"16530": # Cold Bay city + 2026-10-01: 11 +"16630": # Coldfoot CDP + 2026-10-01: 19 +"16750": # College CDP + 2026-10-01: 10 +"17190": # Cooper Landing CDP + 2026-10-01: 9 +"17300": # Copper Center CDP + 2026-10-01: 11 +"17410": # Cordova city + 2026-10-01: 7 +"17740": # Craig city + 2026-10-01: 5 +"17850": # Crooked Creek CDP + 2026-10-01: 26 +"18510": # Deering city + 2026-10-01: 31 +"18620": # Delta Junction city + 2026-10-01: 11 +"18805": # Denali Park CDP + 2026-10-01: 10 +"18950": # Dillingham city + 2026-10-01: 11 +"19060": # Diomede city + 2026-10-01: 27 +"19720": # Dot Lake CDP + 2026-10-01: 12 +"20380": # Eagle city + 2026-10-01: 19 +"20970": # Edna Bay city + 2026-10-01: 11 +"21040": # Eek city + 2026-10-01: 22 +"21150": # Egegik city + 2026-10-01: 15 +"21810": # Ekwok city + 2026-10-01: 14 +"22140": # Elfin Cove CDP + 2026-10-01: 6 +"22250": # Elim city + 2026-10-01: 26 +"22910": # Emmonak city + 2026-10-01: 24 +"23460": # Ester CDP + 2026-10-01: 11 +"23790": # Evansville CDP + 2026-10-01: 29 +"23900": # Excursion Inlet CDP + 2026-10-01: 7 +"24230": # Fairbanks city + 2026-10-01: 10 +"24660": # False Pass city + 2026-10-01: 11 +"26100": # Fort Greely CDP + 2026-10-01: 11 +"26760": # Fort Yukon city + 2026-10-01: 23 +"26870": # Fox CDP + 2026-10-01: 11 +"27090": # Fritz Creek CDP + 2026-10-01: 7 +"27420": # Gakona CDP + 2026-10-01: 11 +"27530": # Galena city + 2026-10-01: 20 +"27640": # Gambell city + 2026-10-01: 27 +"28740": # Glennallen CDP + 2026-10-01: 11 +"29180": # Golovin city + 2026-10-01: 26 +"29290": # Goodnews Bay city + 2026-10-01: 20 +"30060": # Grayling city + 2026-10-01: 22 +"30500": # Gulkana CDP + 2026-10-01: 11 +"30940": # Gustavus city + 2026-10-01: 6 +"31050": # Haines CDP + 2026-10-01: 6 +"31270": # Halibut Cove CDP + 2026-10-01: 7 +"32150": # Healy CDP + 2026-10-01: 10 +"32310": # Healy Lake CDP + 2026-10-01: 13 +"32810": # Hollis CDP + 2026-10-01: 5 +"33030": # Holy Cross city + 2026-10-01: 21 +"33140": # Homer city + 2026-10-01: 7 +"33360": # Hoonah city + 2026-10-01: 7 +"33470": # Hooper Bay city + 2026-10-01: 25 +"33580": # Hope CDP + 2026-10-01: 7 +"33800": # Houston city + 2026-10-01: 7 +"33910": # Hughes city + 2026-10-01: 33 +"34350": # Huslia city + 2026-10-01: 30 +"34460": # Hydaburg city + 2026-10-01: 5 +"34570": # Hyder CDP + 2026-10-01: 4 +"34790": # Igiugig CDP + 2026-10-01: 12 +"35120": # Iliamna CDP + 2026-10-01: 19 +"35890": # Ivanof Bay CDP + 2026-10-01: 12 +"36400": # Juneau city and borough + 2026-10-01: 5 +"36770": # Kake city + 2026-10-01: 6 +"36990": # Kaktovik city + 2026-10-01: 24 +"37430": # Kaltag city + 2026-10-01: 22 +"37540": # Karluk CDP + 2026-10-01: 10 +"37650": # Kasaan city + 2026-10-01: 5 +"37975": # Kasigluk CDP + 2026-10-01: 19 +"38090": # Kasilof CDP + 2026-10-01: 7 +"38420": # Kenai city + 2026-10-01: 8 +"38970": # Ketchikan city + 2026-10-01: 4 +"39300": # Kiana city + 2026-10-01: 26 +"39410": # King Cove city + 2026-10-01: 11 +"39630": # King Salmon CDP + 2026-10-01: 13 +"39740": # Kipnuk CDP + 2026-10-01: 20 +"39960": # Kivalina city + 2026-10-01: 28 +"40400": # Klawock city + 2026-10-01: 5 +"40510": # Klukwan CDP + 2026-10-01: 8 +"40645": # Knik-Fairview CDP + 2026-10-01: 7 +"40840": # Kobuk city + 2026-10-01: 35 +"40950": # Kodiak city + 2026-10-01: 6 +"41280": # Kokhanok CDP + 2026-10-01: 19 +"41500": # Koliganek CDP + 2026-10-01: 16 +"41610": # Kongiganak CDP + 2026-10-01: 22 +"41720": # Kotlik city + 2026-10-01: 24 +"41830": # Kotzebue city + 2026-10-01: 21 +"41940": # Koyuk city + 2026-10-01: 25 +"42050": # Koyukuk city + 2026-10-01: 20 +"42380": # Kwethluk city + 2026-10-01: 20 +"42490": # Kwigillingok CDP + 2026-10-01: 22 +"42820": # Lake Minchumina CDP + 2026-10-01: 27 +"43040": # Larsen Bay city + 2026-10-01: 7 +"43810": # Levelock CDP + 2026-10-01: 12 +"44030": # Lime Village CDP + 2026-10-01: 26 +"44580": # Livengood CDP + 2026-10-01: 14 +"45020": # Loring CDP + 2026-10-01: 4 +"45790": # McCarthy CDP + 2026-10-01: 11 +"46010": # McGrath city + 2026-10-01: 22 +"46780": # Manley Hot Springs CDP + 2026-10-01: 13 +"46890": # Manokotak city + 2026-10-01: 16 +"47000": # Marshall city + 2026-10-01: 25 +"47990": # Mekoryuk city + 2026-10-01: 21 +"48540": # Mentasta Lake CDP + 2026-10-01: 12 +"48870": # Metlakatla CDP + 2026-10-01: 6 +"49530": # Minto CDP + 2026-10-01: 16 +"50080": # Moose Creek CDP + 2026-10-01: 11 +"50190": # Moose Pass CDP + 2026-10-01: 6 +"51180": # Mountain Village city + 2026-10-01: 25 +"52060": # Naknek CDP + 2026-10-01: 13 +"52210": # Nanwalek CDP + 2026-10-01: 8 +"52390": # Napakiak city + 2026-10-01: 11 +"52720": # Napaskiak city + 2026-10-01: 20 +"52940": # Nelson Lagoon CDP + 2026-10-01: 8 +"53050": # Nenana city + 2026-10-01: 11 +"53270": # Newhalen city + 2026-10-01: 19 +"53710": # New Stuyahok city + 2026-10-01: 16 +"53820": # Newtok CDP + 2026-10-01: 25 +"53930": # Nightmute city + 2026-10-01: 21 +"54050": # Nikiski CDP + 2026-10-01: 7 +"54085": # Nikolaevsk CDP + 2026-10-01: 6 +"54150": # Nikolai city + 2026-10-01: 27 +"54260": # Nikolski CDP + 2026-10-01: 6 +"54480": # Ninilchik CDP + 2026-10-01: 8 +"54700": # Noatak CDP + 2026-10-01: 32 +"54920": # Nome city + 2026-10-01: 17 +"55030": # Nondalton city + 2026-10-01: 19 +"55140": # Noorvik city + 2026-10-01: 26 +"55910": # North Pole city + 2026-10-01: 11 +"56220": # Northway CDP + 2026-10-01: 12 +"56320": # Nuiqsut city + 2026-10-01: 20 +"56350": # Nulato city + 2026-10-01: 24 +"56680": # Nunapitchuk city + 2026-10-01: 19 +"57340": # Old Harbor city + 2026-10-01: 7 +"58330": # Oscarville CDP + 2026-10-01: 20 +"58550": # Ouzinkie city + 2026-10-01: 6 +"58660": # Palmer city + 2026-10-01: 7 +"59320": # Paxson CDP + 2026-10-01: 12 +"59540": # Pedro Bay CDP + 2026-10-01: 19 +"59650": # Pelican city + 2026-10-01: 7 +"60200": # Perryville CDP + 2026-10-01: 9 +"60310": # Petersburg CDP + 2026-10-01: 5 +"60640": # Pilot Point city + 2026-10-01: 12 +"60750": # Pilot Station city + 2026-10-01: 25 +"61080": # Platinum city + 2026-10-01: 20 +"61120": # Pleasant Valley CDP + 2026-10-01: 11 +"61190": # Point Baker CDP + 2026-10-01: 11 +"61630": # Point Hope city + 2026-10-01: 23 +"61700": # Point Lay CDP + 2026-10-01: 18 +"62285": # Portage Creek CDP + 2026-10-01: 14 +"62510": # Port Alexander city + 2026-10-01: 11 +"62620": # Port Alsworth CDP + 2026-10-01: 19 +"63280": # Port Graham CDP + 2026-10-01: 8 +"63390": # Port Heiden city + 2026-10-01: 12 +"63610": # Port Lions city + 2026-10-01: 8 +"63870": # Port Protection CDP + 2026-10-01: 11 +"64600": # Quinhagak city + 2026-10-01: 20 +"64820": # Rampart CDP + 2026-10-01: 20 +"64930": # Red Devil CDP + 2026-10-01: 26 +"65590": # Ruby city + 2026-10-01: 19 +"65700": # Russian Mission city + 2026-10-01: 25 +"66550": # Salcha CDP + 2026-10-01: 11 +"67020": # Sand Point city + 2026-10-01: 8 +"67460": # Savoonga city + 2026-10-01: 27 +"67570": # Saxman city + 2026-10-01: 4 +"67680": # Scammon Bay city + 2026-10-01: 22 +"68230": # Selawik city + 2026-10-01: 29 +"68340": # Seldovia city + 2026-10-01: 9 +"68560": # Seward city + 2026-10-01: 6 +"68670": # Shageluk city + 2026-10-01: 24 +"68890": # Shaktoolik city + 2026-10-01: 21 +"69770": # Shishmaref city + 2026-10-01: 29 +"70100": # Shungnak city + 2026-10-01: 35 +"70540": # Sitka city and borough + 2026-10-01: 6 +"70760": # Skagway CDP + 2026-10-01: 8 +"70870": # Skwentna CDP + 2026-10-01: 11 +"70930": # Slana CDP + 2026-10-01: 12 +"71090": # Sleetmute CDP + 2026-10-01: 26 +"71640": # Soldotna city + 2026-10-01: 9 +"72190": # South Naknek CDP + 2026-10-01: 13 +"72960": # Stebbins city + 2026-10-01: 21 +"73070": # Sterling CDP + 2026-10-01: 9 +"73290": # Stevens Village CDP + 2026-10-01: 23 +"73400": # Stony River CDP + 2026-10-01: 26 +"74340": # Susitna CDP + 2026-10-01: 10 +"74525": # Sutton-Alpine CDP + 2026-10-01: 7 +"74610": # Takotna CDP + 2026-10-01: 20 +"74830": # Talkeetna CDP + 2026-10-01: 8 +"75050": # Tanacross CDP + 2026-10-01: 12 +"75160": # Tanana city + 2026-10-01: 20 +"75380": # Tatitlek CDP + 2026-10-01: 11 +"75930": # Teller city + 2026-10-01: 23 +"76590": # Tetlin CDP + 2026-10-01: 12 +"77140": # Thorne Bay city + 2026-10-01: 5 +"77690": # Togiak city + 2026-10-01: 17 +"77800": # Tok CDP + 2026-10-01: 12 +"78240": # Toksook Bay city + 2026-10-01: 21 +"78350": # Tonsina CDP + 2026-10-01: 11 +"78680": # Trapper Creek CDP + 2026-10-01: 8 +"78790": # Tuluksak CDP + 2026-10-01: 21 +"79120": # Tuntutuliak CDP + 2026-10-01: 20 +"79230": # Tununak CDP + 2026-10-01: 20 +"79780": # Twin Hills CDP + 2026-10-01: 17 +"79830": # Two Rivers CDP + 2026-10-01: 11 +"79890": # Tyonek CDP + 2026-10-01: 7 +"80100": # Ugashik CDP + 2026-10-01: 12 +"80660": # Unalakleet city + 2026-10-01: 21 +"80770": # Unalaska city + 2026-10-01: 6 +"81920": # Utqiaġvik city + 2026-10-01: 21 +"82200": # Valdez city + 2026-10-01: 8 +"82420": # Venetie CDP + 2026-10-01: 23 +"82750": # Wainwright city + 2026-10-01: 21 +"82860": # Wales city + 2026-10-01: 27 +"83080": # Wasilla city + 2026-10-01: 7 +"84000": # Whale Pass city + 2026-10-01: 6 +"84070": # White Mountain city + 2026-10-01: 26 +"84510": # Whittier city + 2026-10-01: 8 +"85280": # Willow CDP + 2026-10-01: 7 +"85610": # Wiseman CDP + 2026-10-01: 19 +"86380": # Wrangell city and borough + 2026-10-01: 5 +"86490": # Yakutat CDP + 2026-10-01: 6 +UNAVAILABLE: + 2026-10-01: 0 + +metadata: + unit: /1 + period: year + label: Alaska HAP oil community heating points + reference: + - title: Alaska HAP Manual Addendum A, FFY2027 Community Listing + href: http://dpaweb.hss.state.ak.us/manuals/HAP/addendum/addendum_a.htm + - title: Census 2025 Alaska Places Gazetteer + href: https://www2.census.gov/geo/docs/maps-data/data/gazetteer/2025_Gazetteer/2025_gaz_place_02.txt diff --git a/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/dwelling_factor.yaml b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/dwelling_factor.yaml new file mode 100644 index 00000000000..b663ac4d854 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/dwelling_factor.yaml @@ -0,0 +1,27 @@ +description: Alaska applies these heating point factors by dwelling type under the Heating Assistance Program. +LARGE_MOBILE_HOME_OR_BOAT: + 2026-10-01: 1.4 +RV_TENT_OR_CAMPER: + 2026-10-01: 0.4 +STUDIO_HOTEL_OR_BOARDING_ROOM: + 2026-10-01: 0.15 +SMALL_BOAT: + 2026-10-01: 0.35 +ONE_BEDROOM_OR_ONE_ROOM_HOUSE: + 2026-10-01: 0.55 +THREE_PLUS_BEDROOM_HOUSE: + 2026-10-01: 1.3 +TWO_BEDROOM_LARGE_APARTMENT_OR_SMALL_MOBILE: + 2026-10-01: 0.7 +TWO_BEDROOM_HOUSE: + 2026-10-01: 1 + +metadata: + unit: /1 + period: year + label: Alaska HAP dwelling heating point factor + breakdown: + - ak_hap_dwelling_type + reference: + - title: Alaska HAP Manual 3004-5, Grant Computation + href: http://dpaweb.hss.state.ak.us/manuals/HAP/3004/3004-5_grant_computation.htm diff --git a/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/elderly_age.yaml b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/elderly_age.yaml new file mode 100644 index 00000000000..dd55a70110d --- /dev/null +++ b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/elderly_age.yaml @@ -0,0 +1,11 @@ +description: Alaska treats people at least this age as elderly under the Heating Assistance Program. +values: + 2026-10-01: 60 + +metadata: + unit: year + period: year + label: Alaska HAP elderly age + reference: + - title: Alaska HAP Manual 3000-2, Elderly + href: http://dpaweb.hss.state.ak.us/manuals/HAP/3000/3000-2_definitions.htm diff --git a/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/maximum_points.yaml b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/maximum_points.yaml new file mode 100644 index 00000000000..ce147f3dd86 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/maximum_points.yaml @@ -0,0 +1,11 @@ +description: Alaska limits rounded heating points to this amount under the Heating Assistance Program. +values: + 2026-10-01: 35 + +metadata: + unit: /1 + period: year + label: Alaska HAP maximum heating points + reference: + - title: Alaska HAP Manual 3004-5, Grant Computation + href: http://dpaweb.hss.state.ak.us/manuals/HAP/3004/3004-5_grant_computation.htm diff --git a/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/minimum_expense.yaml b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/minimum_expense.yaml new file mode 100644 index 00000000000..46b12ce4aa5 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/minimum_expense.yaml @@ -0,0 +1,11 @@ +description: Alaska requires annual heating expenses to exceed this amount under the Heating Assistance Program. +values: + 2026-10-01: 200 + +metadata: + unit: currency-USD + period: year + label: Alaska HAP annual heating expense threshold + reference: + - title: Alaska HAP Manual 3002-1 A.1, Eligible Household + href: http://dpaweb.hss.state.ak.us/manuals/HAP/3002/3002-1_households.htm diff --git a/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/minimum_points.yaml b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/minimum_points.yaml new file mode 100644 index 00000000000..255f4584d49 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/minimum_points.yaml @@ -0,0 +1,11 @@ +description: Alaska requires at least this many unrounded heating points under the Heating Assistance Program. +values: + 2026-10-01: 2 + +metadata: + unit: /1 + period: year + label: Alaska HAP minimum heating points + reference: + - title: Alaska HAP Manual 3004-5, Grant Computation + href: http://dpaweb.hss.state.ak.us/manuals/HAP/3004/3004-5_grant_computation.htm diff --git a/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/point_value.yaml b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/point_value.yaml new file mode 100644 index 00000000000..f7c605d29a6 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/point_value.yaml @@ -0,0 +1,11 @@ +description: Alaska pays this amount per heating point under the federal Heating Assistance Program. +values: + 2026-10-01: 175 + +metadata: + unit: currency-USD + period: year + label: Alaska HAP federal benefit per point + reference: + - title: Alaska HAP Manual 3004-5, Grant Computation + href: http://dpaweb.hss.state.ak.us/manuals/HAP/3004/3004-5_grant_computation.htm diff --git a/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/tribal_service_places.yaml b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/tribal_service_places.yaml new file mode 100644 index 00000000000..1127549942e --- /dev/null +++ b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/tribal_service_places.yaml @@ -0,0 +1,15 @@ +description: Alaska routes all residents of these represented Census places to tribal heating assistance providers under the ordinary state Heating Assistance Program rules. +values: + 2026-10-01: ["00760", "00870", "01200", "01305", "01420", "01860", "03440", "03550", "03880", "03990", "04430", "05750", "06520", "06630", "07620", "11690", "11800", "12680", "13230", "13450", "13550", "13670", "13780", "14330", "14880", "16630", "17740", "18950", "19720", "20380", "21040", "21150", "21810", "22910", "23790", "26760", "27530", "29290", "30060", "32310", "33030", "33360", "33470", "33910", "34350", "34460", "34790", "35120", "35890", "36770", "37430", "37650", "37975", "39630", "39740", "40400", "40510", "41280", "41500", "41610", "41720", "42050", "42380", "42490", "42820", "43810", "44030", "46010", "46780", "46890", "47000", "47990", "48870", "49530", "51180", "52060", "52390", "52720", "53050", "53270", "53710", "53820", "53930", "54150", "55030", "56220", "56350", "56680", "58330", "60640", "60750", "61080", "62285", "63390", "64600", "64820", "64930", "65590", "65700", "67570", "67680", "68670", "71090", "72190", "73290", "74610", "75050", "75160", "76590", "77690", "78240", "78790", "79120", "79230", "79780", "80100", "82420", "85610", "86490"] + +metadata: + unit: list + period: year + label: Alaska HAP all resident tribal service places + reference: + - title: Alaska HAP Manual Addendum A, FFY2027 Community Listing and symbol key + href: http://dpaweb.hss.state.ak.us/manuals/HAP/addendum/addendum_a.htm + - title: Alaska HAP Manual 3002-1 A.2, Ineligible Household + href: http://dpaweb.hss.state.ak.us/manuals/HAP/3002/3002-1_households.htm + - title: Census 2025 Alaska Places Gazetteer + href: https://www2.census.gov/geo/docs/maps-data/data/gazetteer/2025_Gazetteer/2025_gaz_place_02.txt diff --git a/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/vulnerability_points.yaml b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/vulnerability_points.yaml new file mode 100644 index 00000000000..d7a8a64eea9 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/vulnerability_points.yaml @@ -0,0 +1,11 @@ +description: Alaska adds this many heating points for a household with at least one qualified vulnerable member under the Heating Assistance Program. +values: + 2026-10-01: 1 + +metadata: + unit: /1 + period: year + label: Alaska HAP vulnerable household points + reference: + - title: Alaska HAP Manual 3004-5, Grant Computation + href: http://dpaweb.hss.state.ak.us/manuals/HAP/3004/3004-5_grant_computation.htm diff --git a/policyengine_us/parameters/gov/states/ak/dpa/hap/income_factor/factors.yaml b/policyengine_us/parameters/gov/states/ak/dpa/hap/income_factor/factors.yaml new file mode 100644 index 00000000000..12fb8323e54 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ak/dpa/hap/income_factor/factors.yaml @@ -0,0 +1,11 @@ +description: Alaska retains these shares of heating points in ascending federal poverty guideline income bands under the federal Heating Assistance Program. +values: + 2026-10-01: [1, 0.9, 0.8, 0.7, 0.6, 0.5] + +metadata: + unit: /1 + period: year + label: Alaska HAP income band point factors + reference: + - title: Alaska HAP Manual 3004-5, Grant Computation + href: http://dpaweb.hss.state.ak.us/manuals/HAP/3004/3004-5_grant_computation.htm diff --git a/policyengine_us/parameters/gov/states/ak/dpa/hap/income_factor/fpg_rates.yaml b/policyengine_us/parameters/gov/states/ak/dpa/hap/income_factor/fpg_rates.yaml new file mode 100644 index 00000000000..d92c3f4d9f3 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ak/dpa/hap/income_factor/fpg_rates.yaml @@ -0,0 +1,11 @@ +description: Alaska assigns heating points using these inclusive upper shares of federal poverty guidelines under the federal Heating Assistance Program. +values: + 2026-10-01: [0.25, 0.5, 0.75, 1, 1.25, 1.5] + +metadata: + unit: /1 + period: year + label: Alaska HAP income band upper FPG rates + reference: + - title: Alaska HAP Manual 3004-5, Grant Computation + href: http://dpaweb.hss.state.ak.us/manuals/HAP/3004/3004-5_grant_computation.htm diff --git a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_base_benefit.yaml b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_base_benefit.yaml new file mode 100644 index 00000000000..687247da5f2 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_base_benefit.yaml @@ -0,0 +1,2412 @@ +# Independently derived from the adopted FY2027 source package and controlling contract. +# Base component precedes disputed sharing and utility-allowance adjustments. +# Sources (each URL listed once): +# http://dpaweb.hss.state.ak.us/manuals/HAP/3004/3004-5_grant_computation.htm +# http://dpaweb.hss.state.ak.us/manuals/HAP/addendum/addendum_e.htm +# http://dpaweb.hss.state.ak.us/manuals/HAP/addendum/addendum_a.htm +# http://dpaweb.hss.state.ak.us/manuals/HAP/3002/3002-1_households.htm +# https://www.akleg.gov/basis/aac.asp?media=print&secStart=7.44.010&secEnd=7.44.9001 +# Geographic/name and nearest-gas approximations are documented in the research manifest. +# 415 replaces the stale published one-person 25% cell407 under the approved reconciliation. +# Fuel, dwelling and location are explicit; no new monetary inputs or sentinel defaults. + +# GRANT: 10 oil points * 1.4; minimum 2 before half-up whole-point rounding, then $175/point. +- name: Case 1, Fairbanks dwelling large_mobile_home_or_boat uses its published factor. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: LARGE_MOBILE_HOME_OR_BOAT + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_base_benefit: 2_450 + +# GRANT: 10 oil points * 0.4; minimum 2 before half-up whole-point rounding, then $175/point. +- name: Case 2, Fairbanks dwelling rv_tent_or_camper uses its published factor. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: RV_TENT_OR_CAMPER + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_base_benefit: 700 + +# GRANT: 10 oil points * 0.15; minimum 2 before half-up whole-point rounding, then $175/point. +- name: Case 3, Fairbanks dwelling studio_hotel_or_boarding_room uses its published factor. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: STUDIO_HOTEL_OR_BOARDING_ROOM + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_base_benefit: 0 + +# GRANT: 10 oil points * 0.35; minimum 2 before half-up whole-point rounding, then $175/point. +- name: Case 4, Fairbanks dwelling small_boat uses its published factor. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: SMALL_BOAT + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_base_benefit: 700 + +# GRANT: 10 oil points * 0.55; minimum 2 before half-up whole-point rounding, then $175/point. +- name: Case 5, Fairbanks dwelling one_bedroom_or_one_room_house uses its published factor. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: ONE_BEDROOM_OR_ONE_ROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_base_benefit: 1_050 + +# GRANT: 10 oil points * 1.3; minimum 2 before half-up whole-point rounding, then $175/point. +- name: Case 6, Fairbanks dwelling three_plus_bedroom_house uses its published factor. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: THREE_PLUS_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_base_benefit: 2_275 + +# GRANT: 10 oil points * 0.7; minimum 2 before half-up whole-point rounding, then $175/point. +- name: Case 7, Fairbanks dwelling two_bedroom_large_apartment_or_small_mobile uses its published factor. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_LARGE_APARTMENT_OR_SMALL_MOBILE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_base_benefit: 1_225 + +# GRANT: 10 oil points * 1; minimum 2 before half-up whole-point rounding, then $175/point. +- name: Case 8, Fairbanks dwelling two_bedroom_house uses its published factor. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_base_benefit: 1_750 + +# REG 44.080(f), GRANT Step 1 and primary kerosene classification: Fairbanks 10 oil points * $175. +- name: Case 9, propane uses oil points and its matching bill. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: PROPANE + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + bottled_gas_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_base_benefit: 1_750 + +# REG 44.080(f), GRANT Step 1 and primary kerosene classification: Fairbanks 10 oil points * $175. +- name: Case 10, kerosene uses oil points and its matching bill. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: KEROSENE + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_base_benefit: 1_750 + +# REG 44.080(f), GRANT Step 1 and primary kerosene classification: Fairbanks 10 oil points * $175. +- name: Case 11, electricity uses oil points and its matching bill. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: ELECTRICITY + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + pre_subsidy_electricity_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_base_benefit: 1_750 + +# Current COMMUNITY table / adopted source crosswalk: 8 points * $175; Loring uses current 4 rather than legacy 5. +- name: Case 12, Fairbanks gas follows the adopted mapping. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: NATURAL_GAS + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + gas_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_base_benefit: 1_400 + +# Current COMMUNITY table / adopted source crosswalk: 5 points * $175; Loring uses current 4 rather than legacy 5. +- name: Case 13, Anchorage gas follows the adopted mapping. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: NATURAL_GAS + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + gas_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '03000' + output: + ak_hap_base_benefit: 875 + +# Current COMMUNITY table / adopted source crosswalk: 6 points * $175; Loring uses current 4 rather than legacy 5. +- name: Case 14, Utqiagvik renamed from Barrow gas follows the adopted mapping. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: NATURAL_GAS + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + gas_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '81920' + output: + ak_hap_base_benefit: 1_050 + +# Current COMMUNITY table / adopted source crosswalk: 21 points * $175; Loring uses current 4 rather than legacy 5. +- name: Case 15, Utqiagvik renamed from Barrow oil follows the adopted mapping. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '81920' + output: + ak_hap_base_benefit: 3_675 + +# Current COMMUNITY table / adopted source crosswalk: 5 points * $175; Loring uses current 4 rather than legacy 5. +- name: Case 16, Knik Fairview gas follows the adopted mapping. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: NATURAL_GAS + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + gas_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '40645' + output: + ak_hap_base_benefit: 875 + +# Current COMMUNITY table / adopted source crosswalk: 7 points * $175; Loring uses current 4 rather than legacy 5. +- name: Case 17, Knik Fairview oil follows the adopted mapping. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '40645' + output: + ak_hap_base_benefit: 1_225 + +# Current COMMUNITY table / adopted source crosswalk: 8 points * $175; Loring uses current 4 rather than legacy 5. +- name: Case 18, North Pole current gas follows the adopted mapping. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: NATURAL_GAS + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + gas_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '55910' + output: + ak_hap_base_benefit: 1_400 + +# Current COMMUNITY table / adopted source crosswalk: 5 points * $175; Loring uses current 4 rather than legacy 5. +- name: Case 19, Juneau uniform consolidated oil follows the adopted mapping. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '36400' + output: + ak_hap_base_benefit: 875 + +# Current COMMUNITY table / adopted source crosswalk: 6 points * $175; Loring uses current 4 rather than legacy 5. +- name: Case 20, Sitka uniform consolidated oil follows the adopted mapping. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '70540' + output: + ak_hap_base_benefit: 1_050 + +# Current COMMUNITY table / adopted source crosswalk: 5 points * $175; Loring uses current 4 rather than legacy 5. +- name: Case 21, Wrangell uniform consolidated oil follows the adopted mapping. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '86380' + output: + ak_hap_base_benefit: 875 + +# Current COMMUNITY table / adopted source crosswalk: 4 points * $175; Loring uses current 4 rather than legacy 5. +- name: Case 22, Loring current manual oil follows the adopted mapping. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '45020' + output: + ak_hap_base_benefit: 700 + +# Research crosswalk: Ester -> Fairbanks, 8 gas points * $175; not a direct published Ester gas entry. +- name: Case 23, Ester gas uses the adopted nearest-community approximation. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: NATURAL_GAS + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + gas_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '23460' + output: + ak_hap_base_benefit: 1_400 + +# Research edge-sensitive row: nearest Barrow gas 6 points * $175; 25 km diagnostic is not an eligibility rule. +- name: Case 24, Anaktuvuk Pass gas retains the documented spatial approximation. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: NATURAL_GAS + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + gas_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: 02080 + output: + ak_hap_base_benefit: 1_050 + +# Anchorage 5 gas * .4 dwelling = 2; 2 * $175 = $350. +- name: Case 25, gas RV at exactly two unrounded points is payable. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: NATURAL_GAS + ak_hap_dwelling_type: RV_TENT_OR_CAMPER + ak_atap: 0 + receives_housing_assistance: false + gas_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '03000' + output: + ak_hap_base_benefit: 350 + +# Anchorage 5 gas * .15 + 1 vulnerability = 1.75 < 2, even though whole-point rounding would produce 2. +- name: Case 26, points below two are denied before upward rounding. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 60 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: NATURAL_GAS + ak_hap_dwelling_type: STUDIO_HOTEL_OR_BOARDING_ROOM + ak_atap: 0 + receives_housing_assistance: false + gas_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '03000' + output: + ak_hap_base_benefit: 0 + +# Fairbanks 10 * .15 + 1 = 2.5 -> 3 points * $175. +- name: Case 27, age sixty adds one point before half-up rounding. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 60 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: STUDIO_HOTEL_OR_BOARDING_ROOM + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_base_benefit: 525 + +# Fairbanks studio remains 1.5 points at age 59.99, below the unrounded minimum. +- name: Case 28, age below sixty does not create vulnerability. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 59.99 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: STUDIO_HOTEL_OR_BOARDING_ROOM + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_base_benefit: 0 + +# 10 * .15 + 1 = 2.5 -> 3; age 5.99 is under six. +- name: Case 29, under six adds one vulnerability point. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person2: + age: 5.99 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + - person2 + heating_type: FUEL_OIL + ak_hap_dwelling_type: STUDIO_HOTEL_OR_BOARDING_ROOM + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + households: + household1: + members: + - person1 + - person2 + state_code: AK + place_fips: '24230' + output: + ak_hap_base_benefit: 525 + +# 10 * .15 = 1.5 < 2; exact age six is not under six. +- name: Case 30, exact age six does not add vulnerability. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person2: + age: 6 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + - person2 + heating_type: FUEL_OIL + ak_hap_dwelling_type: STUDIO_HOTEL_OR_BOARDING_ROOM + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + households: + household1: + members: + - person1 + - person2 + state_code: AK + place_fips: '24230' + output: + ak_hap_base_benefit: 0 + +# Approved disability approximation, GRANT Step 4: 1.5 + 1 = 2.5 -> 3. +- name: Case 31, disabled qualified adult adds the vulnerability point. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + is_disabled: true + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: STUDIO_HOTEL_OR_BOARDING_ROOM + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_base_benefit: 525 + +# Elderly, disabled and child indicators overlap; add 1 once, not per member or condition. +- name: Case 32, multiple vulnerable qualified members add only one point. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 60 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + is_disabled: true + person2: + age: 4 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + - person2 + heating_type: FUEL_OIL + ak_hap_dwelling_type: STUDIO_HOTEL_OR_BOARDING_ROOM + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + households: + household1: + members: + - person1 + - person2 + state_code: AK + place_fips: '24230' + output: + ak_hap_base_benefit: 525 + +# All 24000 income counts; qualified size 1 -> monthly 2000, factor .6; 10 * .6 = 6 points. +- name: Case 33, nonqualified elderly member cannot create vulnerability. + period: 2027 + absolute_error_margin: 0.0001 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + employment_income: 12_000 + person2: + age: 65 + immigration_status: UNDOCUMENTED + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + employment_income: 12_000 + spm_units: + spm_unit1: + members: + - person1 + - person2 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + households: + household1: + members: + - person1 + - person2 + state_code: AK + place_fips: '24230' + output: + ak_hap_base_benefit: 1_050 + ak_hap_household_size: 1 + ak_hap_countable_income: 24_000 + ak_hap_income_factor: 0.6 + +# Income 24000, qualified size 1, factor .6; 10 * .6 + 1 = 7 points. +- name: Case 34, qualified elderly member in the same mixed-status household adds one point. + period: 2027 + absolute_error_margin: 0.0001 + input: + people: + person1: + age: 65 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + employment_income: 12_000 + person2: + age: 40 + immigration_status: UNDOCUMENTED + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + employment_income: 12_000 + spm_units: + spm_unit1: + members: + - person1 + - person2 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + households: + household1: + members: + - person1 + - person2 + state_code: AK + place_fips: '24230' + output: + ak_hap_base_benefit: 1_225 + ak_hap_household_size: 1 + ak_hap_countable_income: 24_000 + ak_hap_income_factor: 0.6 + +# Qualified size 2, annual36000/month3000 -> factor .5; 10 * .7 * .5 + 1 = 4.5 -> 5. +- name: Case 35, mixed earnings and vulnerability round four and a half points upward. + period: 2027 + absolute_error_margin: 0.0001 + input: + people: + person1: + age: 60 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + employment_income: 18_000 + person2: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + employment_income: 18_000 + spm_units: + spm_unit1: + members: + - person1 + - person2 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_LARGE_APARTMENT_OR_SMALL_MOBILE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + households: + household1: + members: + - person1 + - person2 + state_code: AK + place_fips: '24230' + output: + ak_hap_base_benefit: 875 + ak_hap_household_size: 2 + ak_hap_countable_income: 36_000 + ak_hap_income_factor: 0.5 + +# 10 * .7 * .5 = 3.5 -> 4 points * $175. +- name: Case 36, same income without vulnerability rounds three and a half upward. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + employment_income: 18_000 + person2: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + employment_income: 18_000 + spm_units: + spm_unit1: + members: + - person1 + - person2 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_LARGE_APARTMENT_OR_SMALL_MOBILE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + households: + household1: + members: + - person1 + - person2 + state_code: AK + place_fips: '24230' + output: + ak_hap_base_benefit: 700 + +# Ambler35 oil * 1 * 1 = 35 points; $6125. +- name: Case 37, Ambler exactly thirty-five points reaches cap. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: 01970 + output: + ak_hap_base_benefit: 6_125 + +# Ambler35 * 1.4 + 1 = 50 points, capped35 * $175. +- name: Case 38, points above thirty-five are capped after vulnerability. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 60 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: LARGE_MOBILE_HOME_OR_BOAT + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: 01970 + output: + ak_hap_base_benefit: 6_125 + +# HH annual heating cost must exceed $200, not equal it. +- name: Case 39, annual heating expense exactly two hundred fails. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 200 + households: + household1: + members: + - person1 + state_code: AK + place_fips: 01970 + output: + ak_hap_base_benefit: 0 + +# HH expense200.01 passes; Ambler35 * $175 = 6125 with no actual-expense cap. +- name: Case 40, expense just above two hundred is not an award cap. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 200.01 + households: + household1: + members: + - person1 + state_code: AK + place_fips: 01970 + output: + ak_hap_base_benefit: 6_125 + +# Primary NATURAL_GAS bill0; secondary oil10000 cannot satisfy the primary-heating expense gate. +- name: Case 41, zero primary expense fails despite other fuel bills. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: NATURAL_GAS + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + gas_expense: 0 + fuel_oil_expense: 10_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_base_benefit: 0 + +# One qualified adult; annual payroll 24924, no general earned disregard. Apply source band to Fairbanks10 oil points. +- name: Case 42, integrated wages at exact125percent use the inclusive income boundary. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + employment_income: 24_924 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_base_benefit: 1_050 + +# One qualified adult; annual payroll 24924.12, no general earned disregard. Apply source band to Fairbanks10 oil points. +- name: Case 43, integrated wages at above125percent use the inclusive income boundary. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + employment_income: 24924.12 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_base_benefit: 875 + +# One qualified adult; annual payroll 29916, no general earned disregard. Apply source band to Fairbanks10 oil points. +- name: Case 44, integrated wages at exact150percent use the inclusive income boundary. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + employment_income: 29_916 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_base_benefit: 875 + +# One qualified adult; annual payroll 29916.12, no general earned disregard. Apply source band to Fairbanks10 oil points. +- name: Case 45, integrated wages at above150percent use the inclusive income boundary. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + employment_income: 29916.12 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_base_benefit: 0 + +# One qualified adult; annual payroll 4980, no general earned disregard. Apply source band to Fairbanks10 oil points. +- name: Case 46, integrated wages at reconciled25percent use the inclusive income boundary. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + employment_income: 4_980 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_base_benefit: 1_750 + +# One qualified adult; annual payroll 4980.12, no general earned disregard. Apply source band to Fairbanks10 oil points. +- name: Case 47, integrated wages at above25percent use the inclusive income boundary. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + employment_income: 4980.12 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_base_benefit: 1_575 + +# Unchanged income component floors total net receipts at0; income factor1 and Fairbanks10points. +- name: Case 48, negative current net business income does not inflate benefit. + period: 2027 + absolute_error_margin: 0.0001 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + self_employment_income: -12_000 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_base_benefit: 1_750 + ak_hap_countable_income: 0 + ak_hap_income_factor: 1 + +# Five qualified members, monthly2900 <=75% ceiling3021; 27 * .8 + 1 = 22.6 -> 23 * $175. +- name: Case 49, Savoonga updated five-person band supersedes stale worked label. + period: 2027 + absolute_error_margin: 0.0001 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + employment_income: 34_800 + person2: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person3: + age: 12 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person4: + age: 9 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person5: + age: 4 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + - person2 + - person3 + - person4 + - person5 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + households: + household1: + members: + - person1 + - person2 + - person3 + - person4 + - person5 + state_code: AK + place_fips: '67460' + output: + ak_hap_base_benefit: 4_025 + ak_hap_countable_income: 34_800 + ak_hap_household_size: 5 + ak_hap_income_factor: 0.8 + +# HH/VER: annual rent12000 counts for expense gate despite direct fuel bill0. +- name: Case 50, rent included heat uses full annual rent for expense gate. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + pre_subsidy_rent: 12_000 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 0 + heat_expense_included_in_rent: true + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_base_benefit: 1_750 + +# Full annual rent200 does not exceed200. +- name: Case 51, rent included heat at exact expense threshold fails. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + pre_subsidy_rent: 200 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 0 + heat_expense_included_in_rent: true + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_base_benefit: 0 + +# Annual rent200.01 passes gate; Fairbanks points amount remains1750. +- name: Case 52, rent included heat above expense threshold is not capped by rent. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + pre_subsidy_rent: 200.01 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 0 + heat_expense_included_in_rent: true + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_base_benefit: 1_750 + +# HH excludes subsidized rental housing with no direct heating cost. +- name: Case 53, subsidized rent included heat receives zero under housing exclusion. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + pre_subsidy_rent: 12_000 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: true + fuel_oil_expense: 0 + heat_expense_included_in_rent: true + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_base_benefit: 0 + +# Juneau5 * .55 * .7 + 1 = 2.925 -> 3 *175; positive allowance affects a later unresolved final adjustment only. +- name: Case 54, base amount does not apply disputed utility allowance reduction. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 60 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + employment_income: 15_552 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: ONE_BEDROOM_OR_ONE_ROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: true + fuel_oil_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '36400' + hud_utility_allowance: 1_200 + output: + ak_hap_base_benefit: 525 + +# Current COMMUNITY 0/AVCP means all residents are routed; no race-based inference. +- name: Case 55, all-resident tribal routing excludes Akiachak state component. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '00760' + output: + ak_hap_base_benefit: 0 + +# Akiachak has a nearest-gas approximation but 0/AVCP still routes all residents. +- name: Case 56, all-resident routing remains separate from gas approximation. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: NATURAL_GAS + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + gas_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '00760' + output: + ak_hap_base_benefit: 0 + +# Akutan */APIA is Native-only; absent enrollment facts do not exclude. Oil11 *175. +- name: Case 57, Native-only routing does not infer tribal eligibility. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: 01090 + output: + ak_hap_base_benefit: 1_925 + +# Fort Greely0/USA is explicitly excluded from tribal list; on-base residence is unobserved. Oil11 *175 under the ordinary location approximation. +- name: Case 58, USA marker is not an all-resident tribal provider. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '26100' + output: + ak_hap_base_benefit: 1_925 + +# Tetlin current12oil differs from legacy16, but 0/TCC routing controls this state component. +- name: Case 59, Tetlin is routed to all-resident tribal program. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '76590' + output: + ak_hap_base_benefit: 0 + +# HH requires at least one citizen or qualified noncitizen. +- name: Case 60, household with no qualified members is ineligible. + period: 2027 + absolute_error_margin: 0.0001 + input: + people: + person1: + age: 40 + immigration_status: UNDOCUMENTED + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_base_benefit: 0 + ak_hap_household_size: 0 + +# Five-digit place identifiers are only meaningful under Alaska state mask. +- name: Case 61, non Alaska state mask prevents same-place-code award. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + households: + household1: + members: + - person1 + state_code: WA + place_fips: '24230' + output: + ak_hap_base_benefit: 0 + +# Numeric0 represents unavailable supported oil geography, not statutory ineligibility. +- name: Case 62, missing place yields an unavailable modeled amount. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '' + output: + ak_hap_base_benefit: 0 + +# Numeric0 represents unavailable supported oil geography, not statutory ineligibility. +- name: Case 63, unmatched place yields an unavailable modeled amount. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '99999' + output: + ak_hap_base_benefit: 0 + +# Numeric0 represents unavailable supported oil geography, not statutory ineligibility. +- name: Case 64, seven-digit GEOID supplied instead of place yields an unavailable modeled amount. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '0224230' + output: + ak_hap_base_benefit: 0 + +# Numeric0 represents unavailable supported oil geography, not statutory ineligibility. +- name: Case 65, ambiguous Anchorage oil place yields an unavailable modeled amount. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '03000' + output: + ak_hap_base_benefit: 0 + +# Numeric0 is missing modeled fuel coverage, not a legal determination that all such households are ineligible. +- name: Case 66, wood without a supported subtype yields an unavailable modeled amount. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: WOOD + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + wood_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_base_benefit: 0 + +# Numeric0 is missing modeled fuel coverage, not a legal determination that all such households are ineligible. +- name: Case 67, coal without a supported subtype yields an unavailable modeled amount. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: COAL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + coal_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_base_benefit: 0 + +# Numeric0 is missing modeled fuel coverage, not a legal determination that all such households are ineligible. +- name: Case 68, other without a supported subtype yields an unavailable modeled amount. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: OTHER + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + other_heating_fuel_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_base_benefit: 0 + +# Numeric0 is missing modeled fuel coverage, not a legal determination that all such households are ineligible. +- name: Case 69, solar without a supported subtype yields an unavailable modeled amount. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: SOLAR + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + pre_subsidy_electricity_expense: 1_000 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_base_benefit: 0 + +# Numeric0 is missing modeled fuel coverage, not a legal determination that all such households are ineligible. +- name: Case 70, unspecified without a supported subtype yields an unavailable modeled amount. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: UNSPECIFIED + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_base_benefit: 0 + +# NONE affirmatively indicates no residential heating, unlike missing fuel coverage. +- name: Case 71, known no heating has no payable heating component. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: NONE + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_base_benefit: 0 + +# Independent SPM calculations before sharing: 10+1=11 ->1925; 10*.6=6 ->1050. Do not divide points or grants by two. +- name: Case 72, two SPM units retain their own unshared base amounts. + period: 2027 + absolute_error_margin: 0.0001 + input: + people: + person1: + age: 65 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person2: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + employment_income: 24_000 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + fuel_oil_expense: 300 + ak_atap: 0 + receives_housing_assistance: false + spm_unit2: + members: + - person2 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + fuel_oil_expense: 700 + ak_atap: 0 + receives_housing_assistance: false + households: + household1: + members: + - person1 + - person2 + state_code: AK + place_fips: '24230' + output: + ak_hap_household_size: + - 1 + - 1 + ak_hap_countable_income: + - 0 + - 24_000 + ak_hap_income_factor: + - 1 + - 0.6 + ak_hap_base_benefit: + - 1_925 + - 1_050 + +# Mixed vector: Anchorage gas5*.4=2 ->350; Ambler35*1.4=49 capped35 ->6125; no qualified member ->0. +- name: Case 73, distinct SPM units preserve geography fuel and composition gates. + period: 2027 + absolute_error_margin: 0.0001 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person2: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person3: + age: 40 + immigration_status: UNDOCUMENTED + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: NATURAL_GAS + ak_hap_dwelling_type: RV_TENT_OR_CAMPER + gas_expense: 1_000 + ak_atap: 0 + receives_housing_assistance: false + spm_unit2: + members: + - person2 + heating_type: FUEL_OIL + ak_hap_dwelling_type: LARGE_MOBILE_HOME_OR_BOAT + fuel_oil_expense: 200.01 + ak_atap: 0 + receives_housing_assistance: false + spm_unit3: + members: + - person3 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + fuel_oil_expense: 1_000 + ak_atap: 0 + receives_housing_assistance: false + households: + household1: + members: + - person1 + state_code: AK + place_fips: '03000' + household2: + members: + - person2 + state_code: AK + place_fips: 01970 + household3: + members: + - person3 + state_code: AK + place_fips: '24230' + output: + ak_hap_household_size: + - 1 + - 1 + - 0 + ak_hap_countable_income: + - 0 + - 0 + - 0 + ak_hap_income_factor: + - 1 + - 1 + - 0 + ak_hap_base_benefit: + - 350 + - 6_125 + - 0 + diff --git a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_income_factor.yaml b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_income_factor.yaml new file mode 100644 index 00000000000..f912a510f2d --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_income_factor.yaml @@ -0,0 +1,716 @@ +# Independently derived from the adopted FY2027 source package and controlling contract. +# Base component precedes disputed sharing and utility-allowance adjustments. +# Sources (each URL listed once): +# http://dpaweb.hss.state.ak.us/manuals/HAP/3004/3004-5_grant_computation.htm +# http://dpaweb.hss.state.ak.us/manuals/HAP/addendum/addendum_e.htm +# http://dpaweb.hss.state.ak.us/manuals/HAP/addendum/addendum_a.htm +# http://dpaweb.hss.state.ak.us/manuals/HAP/3002/3002-1_households.htm +# https://www.akleg.gov/basis/aac.asp?media=print&secStart=7.44.010&secEnd=7.44.9001 +# Geographic/name and nearest-gas approximations are documented in the research manifest. +# 415 replaces the stale published one-person 25% cell407 under the approved reconciliation. +# Fuel, dwelling and location are explicit; no new monetary inputs or sentinel defaults. + +# GRANT Step 3: income at or below 25% receives factor 1. +- name: Case 1, zero income receives all heating points. + period: 2027 + absolute_error_margin: 0.0001 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + ak_hap_countable_income: 0 + ak_hap_household_size: 1 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_income_factor: 1 + +# Unit robustness: negative input remains in the lowest band, whose factor is 1. +- name: Case 2, negative supplied countable income does not inflate factor. + period: 2027 + absolute_error_margin: 0.0001 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + ak_hap_countable_income: -1_200 + ak_hap_household_size: 1 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_income_factor: 1 + +# Controlling contract: positive qualified size is required. +- name: Case 3, no qualified members yields zero income factor. + period: 2027 + absolute_error_margin: 0.0001 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + ak_hap_countable_income: 0 + ak_hap_household_size: 0 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_income_factor: 0 + +# GRID discrepancy: 407/month is below adopted derived 415 ceiling. +- name: Case 4, printed stale 407 amount stays in the lowest band. + period: 2027 + absolute_error_margin: 0.0001 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + ak_hap_countable_income: 4_884 + ak_hap_household_size: 1 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_income_factor: 1 + +# floor(1662 * .25) = 415, not the stale printed 407. +- name: Case 5, 408 remains below the reconciled 25 percent ceiling. + period: 2027 + absolute_error_margin: 0.0001 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + ak_hap_countable_income: 4_896 + ak_hap_household_size: 1 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_income_factor: 1 + +# GRID + contract: monthly ceiling 415 * 12 = 4980; inclusive band top. +- name: Case 6, exact one-person band 1 ceiling is inclusive. + period: 2027 + absolute_error_margin: 0.0001 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + ak_hap_countable_income: 4_980 + ak_hap_household_size: 1 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_income_factor: 1 + +# Annual income 4980 + .12 gives monthly 415.01; next factor 0.9. +- name: Case 7, one cent monthly above band 1 enters the next band. + period: 2027 + absolute_error_margin: 0.0001 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + ak_hap_countable_income: 4980.12 + ak_hap_household_size: 1 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_income_factor: 0.9 + +# GRID + contract: monthly ceiling 831 * 12 = 9972; inclusive band top. +- name: Case 8, exact one-person band 2 ceiling is inclusive. + period: 2027 + absolute_error_margin: 0.0001 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + ak_hap_countable_income: 9_972 + ak_hap_household_size: 1 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_income_factor: 0.9 + +# Annual income 9972 + .12 gives monthly 831.01; next factor 0.8. +- name: Case 9, one cent monthly above band 2 enters the next band. + period: 2027 + absolute_error_margin: 0.0001 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + ak_hap_countable_income: 9972.12 + ak_hap_household_size: 1 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_income_factor: 0.8 + +# GRID + contract: monthly ceiling 1246 * 12 = 14952; inclusive band top. +- name: Case 10, exact one-person band 3 ceiling is inclusive. + period: 2027 + absolute_error_margin: 0.0001 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + ak_hap_countable_income: 14_952 + ak_hap_household_size: 1 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_income_factor: 0.8 + +# Annual income 14952 + .12 gives monthly 1246.01; next factor 0.7. +- name: Case 11, one cent monthly above band 3 enters the next band. + period: 2027 + absolute_error_margin: 0.0001 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + ak_hap_countable_income: 14952.12 + ak_hap_household_size: 1 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_income_factor: 0.7 + +# GRID + contract: monthly ceiling 1662 * 12 = 19944; inclusive band top. +- name: Case 12, exact one-person band 4 ceiling is inclusive. + period: 2027 + absolute_error_margin: 0.0001 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + ak_hap_countable_income: 19_944 + ak_hap_household_size: 1 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_income_factor: 0.7 + +# Annual income 19944 + .12 gives monthly 1662.01; next factor 0.6. +- name: Case 13, one cent monthly above band 4 enters the next band. + period: 2027 + absolute_error_margin: 0.0001 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + ak_hap_countable_income: 19944.12 + ak_hap_household_size: 1 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_income_factor: 0.6 + +# GRID + contract: monthly ceiling 2077 * 12 = 24924; inclusive band top. +- name: Case 14, exact one-person band 5 ceiling is inclusive. + period: 2027 + absolute_error_margin: 0.0001 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + ak_hap_countable_income: 24_924 + ak_hap_household_size: 1 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_income_factor: 0.6 + +# Annual income 24924 + .12 gives monthly 2077.01; next factor 0.5. +- name: Case 15, one cent monthly above band 5 enters the next band. + period: 2027 + absolute_error_margin: 0.0001 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + ak_hap_countable_income: 24924.12 + ak_hap_household_size: 1 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_income_factor: 0.5 + +# GRID + contract: monthly ceiling 2493 * 12 = 29916; inclusive band top. +- name: Case 16, exact one-person band 6 ceiling is inclusive. + period: 2027 + absolute_error_margin: 0.0001 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + ak_hap_countable_income: 29_916 + ak_hap_household_size: 1 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_income_factor: 0.5 + +# Annual income 29916 + .12 gives monthly 2493.01; next factor 0. +- name: Case 17, one cent monthly above band 6 enters the next band. + period: 2027 + absolute_error_margin: 0.0001 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + ak_hap_countable_income: 29916.12 + ak_hap_household_size: 1 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_income_factor: 0 + +# floor(floor(27050/12) * .25) * 12 = 563 * 12 = 6756. +- name: Case 18, two-person first ceiling uses both monthly floors. + period: 2027 + absolute_error_margin: 0.0001 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + ak_hap_countable_income: 6_756 + ak_hap_household_size: 2 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_income_factor: 1 + +# 563.01 monthly exceeds the two-person 25% ceiling 563. +- name: Case 19, above two-person first ceiling receives ninety percent. + period: 2027 + absolute_error_margin: 0.0001 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + ak_hap_countable_income: 6756.12 + ak_hap_household_size: 2 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_income_factor: 0.9 + +# GRID size 18: 125% ceiling 14650 monthly; 14650 * 12 = 175800. +- name: Case 20, eighteen-person middle-high band uses published additional members. + period: 2027 + absolute_error_margin: 0.0001 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + ak_hap_countable_income: 175_800 + ak_hap_household_size: 18 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_income_factor: 0.6 + +# GRID size 18: 14650.01 monthly is in the 125–150% band. +- name: Case 21, above eighteen-person 125 percent enters fifty percent band. + period: 2027 + absolute_error_margin: 0.0001 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + ak_hap_countable_income: 175800.12 + ak_hap_household_size: 18 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_income_factor: 0.5 + +# State mask applies even when identical income facts are supplied. +- name: Case 22, non Alaska household receives no Alaska factor. + period: 2027 + absolute_error_margin: 0.0001 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + ak_hap_countable_income: 0 + ak_hap_household_size: 1 + households: + household1: + members: + - person1 + state_code: WA + place_fips: '24230' + output: + ak_hap_income_factor: 0 + diff --git a/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_base_benefit.py b/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_base_benefit.py new file mode 100644 index 00000000000..a7a451f5528 --- /dev/null +++ b/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_base_benefit.py @@ -0,0 +1,92 @@ +from policyengine_us.model_api import * + + +class ak_hap_base_benefit(Variable): + value_type = float + entity = SPMUnit + definition_period = YEAR + unit = USD + label = "Alaska HAP base benefit before sharing and utility allowance adjustments" + reference = ( + "http://dpaweb.hss.state.ak.us/manuals/HAP/3004/3004-5_grant_computation.htm", + "http://dpaweb.hss.state.ak.us/manuals/HAP/3002/3002-1_households.htm", + "http://dpaweb.hss.state.ak.us/manuals/HAP/addendum/addendum_a.htm", + "https://www.akleg.gov/basis/aac.asp?media=print&secStart=7.44.010&secEnd=7.44.9001", + "https://cchrc.org/wp-content/uploads/media/Consumer_Guide_Home_Heating.pdf#page=23", + ) + defined_for = StateCode.AK + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ak.dpa.hap.benefit + place = spm_unit.household("place_fips", period) + fuel = spm_unit("heating_type", period) + fuels = fuel.possible_values + oil_table = p.community_points.oil + gas_table = p.community_points.natural_gas + oil_place = where( + np.isin(place, list(oil_table._children)), place, "UNAVAILABLE" + ) + gas_place = where( + np.isin(place, list(gas_table._children)), place, "UNAVAILABLE" + ) + oil_fuel = ( + (fuel == fuels.FUEL_OIL) + | (fuel == fuels.KEROSENE) + | (fuel == fuels.PROPANE) + | (fuel == fuels.ELECTRICITY) + ) + # Propane uses oil points under 7 AAC 44.080(f). Kerosene is Grade 1 + # heating oil in the AHFC-funded technical guide. Wood/coal subtypes, + # unclassified OTHER fuels and unmatched oil geography are unavailable + # modeled amounts (zero fallback), not statutory denials. Anchorage + # oil is ambiguous. The gas table uses a documented nearest-community + # approximation where a direct published place match is unavailable. + community_points = select( + [oil_fuel, fuel == fuels.NATURAL_GAS], + [oil_table[oil_place], gas_table[gas_place]], + default=0, + ) + dwelling = spm_unit("ak_hap_dwelling_type", period) + factor = spm_unit("ak_hap_income_factor", period) + person = spm_unit.members + age = person("age", period) + # Existing disability status approximates the manual's documented + # disability categories. Excluded members cannot add priority points. + vulnerable = spm_unit.any( + person("is_citizen_or_legal_immigrant", period) + & ( + (age >= p.elderly_age) + | (age < p.child_age_limit) + | person("is_disabled", period) + ) + ) + points = community_points * p.dwelling_factor[dwelling] * factor + points = points + vulnerable * p.vulnerability_points + heat_in_rent = spm_unit("heat_expense_included_in_rent", period) + subsidized = spm_unit("receives_housing_assistance", period) + # Full annual rent satisfies the expense test for nonsubsidized + # heat-in-rent households. Pre-subsidy rent avoids benefit feedback. + expense = where( + heat_in_rent, + add(spm_unit, period, ["pre_subsidy_rent"]), + spm_unit("heating_expense", period), + ) + # The table identifies all-resident tribal routing. Native-only tribal + # eligibility and contrary interagency arrangements are unobserved; + # never infer tribal enrollment from race. Finer residency, temporary + # shelter duration and vendor-credit rules are also unobserved. + state_served = ~np.isin(place, p.tribal_service_places) + eligible = ( + (factor > 0) + & (community_points > 0) + & (expense > p.minimum_expense) + & ~(heat_in_rent & subsidized) + & state_served + & (points >= p.minimum_points) + ) + # Apply the unrounded minimum before half-up whole-point rounding. + # This is the sole-household base amount: no expense cap, sharing + # division or utility-allowance reduction is applied. Those final + # adjustments remain unresolved; this is not the complete program. + rounded_points = min_(np.floor(points + 0.5), p.maximum_points) + return where(eligible, rounded_points * p.point_value, 0) diff --git a/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_dwelling_type.py b/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_dwelling_type.py new file mode 100644 index 00000000000..46d846a9623 --- /dev/null +++ b/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_dwelling_type.py @@ -0,0 +1,33 @@ +from policyengine_us.model_api import * + + +class AKHAPDwellingType(Enum): + LARGE_MOBILE_HOME_OR_BOAT = ( + "Mobile home or boat with at least 980 heated square feet" + ) + RV_TENT_OR_CAMPER = "Recreational vehicle, tent, or pickup camper" + STUDIO_HOTEL_OR_BOARDING_ROOM = "Studio apartment, hotel, or boarding room" + SMALL_BOAT = "Boat with less than 980 heated square feet" + ONE_BEDROOM_OR_ONE_ROOM_HOUSE = ( + "One-bedroom dwelling, or one-room house or cabin without bedrooms" + ) + THREE_PLUS_BEDROOM_HOUSE = ( + "Three-or-more-bedroom single family, duplex, or triplex home" + ) + TWO_BEDROOM_LARGE_APARTMENT_OR_SMALL_MOBILE = "Two-bedroom apartment in a building with four or more units, or mobile home below 980 heated square feet" + TWO_BEDROOM_HOUSE = "Two-bedroom single family, duplex, or triplex home" + + +class ak_hap_dwelling_type(Variable): + value_type = Enum + possible_values = AKHAPDwellingType + default_value = AKHAPDwellingType.TWO_BEDROOM_HOUSE + entity = SPMUnit + definition_period = YEAR + label = "Alaska HAP dwelling type" + reference = ( + "http://dpaweb.hss.state.ak.us/manuals/HAP/3004/3004-5_grant_computation.htm" + ) + # Select the first matching category in the manual; a loft is a bedroom. + # The neutral two-bedroom-house default is a modeling assumption, not a + # state policy default. Unclassified dwellings require additional facts. diff --git a/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_income_factor.py b/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_income_factor.py new file mode 100644 index 00000000000..44f76be0fd5 --- /dev/null +++ b/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_income_factor.py @@ -0,0 +1,35 @@ +from policyengine_us.model_api import * +from policyengine_us.variables.gov.hhs.tax_unit_fpg import fpg + + +class ak_hap_income_factor(Variable): + value_type = float + entity = SPMUnit + definition_period = YEAR + label = "Alaska HAP income factor" + reference = ( + "http://dpaweb.hss.state.ak.us/manuals/HAP/3004/3004-5_grant_computation.htm", + "http://dpaweb.hss.state.ak.us/manuals/HAP/addendum/addendum_e.htm", + ) + defined_for = StateCode.AK + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ak.dpa.hap + size = spm_unit("ak_hap_household_size", period) + income = spm_unit("ak_hap_countable_income", period) + state_group = spm_unit.household("state_group_str", period) + guideline = fpg(size, state_group, period, parameters, year_lag=p.fpg_year_lag) + monthly_fpg = np.floor(guideline / MONTHS_IN_YEAR) + # Reconcile the published grid by flooring the monthly FPG before each + # percentage. This gives 415, not the printed 407, at the FY2027 size-1 + # 25% ceiling. 407 matches the prior-year base; using 415 follows the + # explicit 25% rule, not an agency-issued correction. Historical years + # are unverified backfilled estimates. + limits = [ + np.floor(monthly_fpg * rate) * MONTHS_IN_YEAR + for rate in p.income_factor.fpg_rates + ] + factor = select( + [income <= limit for limit in limits], p.income_factor.factors, default=0 + ) + return where(size > 0, factor, 0) From 3a1fa024f8c42cc3e3f7667b6a6a2478039b167f Mon Sep 17 00:00:00 2001 From: Ziming Date: Sat, 3 Oct 2026 22:16:30 -0400 Subject: [PATCH 03/16] Remove extra Alaska HAP test file trailing blank lines --- .../baseline/gov/states/ak/dpa/hap/ak_hap_base_benefit.yaml | 1 - .../baseline/gov/states/ak/dpa/hap/ak_hap_income_factor.yaml | 1 - 2 files changed, 2 deletions(-) diff --git a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_base_benefit.yaml b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_base_benefit.yaml index 687247da5f2..7cbea5b3896 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_base_benefit.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_base_benefit.yaml @@ -2409,4 +2409,3 @@ - 350 - 6_125 - 0 - diff --git a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_income_factor.yaml b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_income_factor.yaml index f912a510f2d..8a04bb16dec 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_income_factor.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_income_factor.yaml @@ -713,4 +713,3 @@ place_fips: '24230' output: ak_hap_income_factor: 0 - From ed2b2d2f3c6866e6170c764e75f0cb0d67e30923 Mon Sep 17 00:00:00 2001 From: Ziming Date: Sun, 4 Oct 2026 19:59:40 -0400 Subject: [PATCH 04/16] Use purchased wood and coal default for Alaska HAP --- changelog.d/ak-liheap-purchased-fuel.added.md | 1 + .../purchased_wood_coal_multiplier.yaml | 14 + .../ak/dpa/hap/ak_hap_base_benefit.yaml | 443 +++++++++++++++++- .../states/ak/dpa/hap/ak_hap_base_benefit.py | 18 +- 4 files changed, 465 insertions(+), 11 deletions(-) create mode 100644 changelog.d/ak-liheap-purchased-fuel.added.md create mode 100644 policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/purchased_wood_coal_multiplier.yaml diff --git a/changelog.d/ak-liheap-purchased-fuel.added.md b/changelog.d/ak-liheap-purchased-fuel.added.md new file mode 100644 index 00000000000..eb4e9320c8f --- /dev/null +++ b/changelog.d/ak-liheap-purchased-fuel.added.md @@ -0,0 +1 @@ +Apply Alaska HAP purchased wood and coal points using existing heating types as a documented default. diff --git a/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/purchased_wood_coal_multiplier.yaml b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/purchased_wood_coal_multiplier.yaml new file mode 100644 index 00000000000..089fbb9ee66 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/purchased_wood_coal_multiplier.yaml @@ -0,0 +1,14 @@ +description: Alaska applies this share of community oil heating points for purchased wood or coal under the Heating Assistance Program. +# The model uses this purchased-fuel rule as an approved approximation for +# existing WOOD/COAL inputs without procurement or pellet detail. Actual +# self-harvested fuel and wood pellets use different published factors. +values: + 2026-10-01: 0.8 + +metadata: + unit: /1 + period: year + label: Alaska HAP purchased wood or coal point multiplier + reference: + - title: Alaska HAP Manual 3004-5, Grant Computation, Step 1 + href: http://dpaweb.hss.state.ak.us/manuals/HAP/3004/3004-5_grant_computation.htm diff --git a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_base_benefit.yaml b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_base_benefit.yaml index 7cbea5b3896..f82ba7c39f1 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_base_benefit.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_base_benefit.yaml @@ -2092,8 +2092,8 @@ output: ak_hap_base_benefit: 0 -# Numeric0 is missing modeled fuel coverage, not a legal determination that all such households are ineligible. -- name: Case 66, wood without a supported subtype yields an unavailable modeled amount. +# User-approved purchased-fuel default: Fairbanks oil 10 * .8 * $175 = $1400. +- name: Case 66, wood uses the purchased-fuel approximation with existing heating type. period: 2027 absolute_error_margin: 0.01 input: @@ -2120,10 +2120,10 @@ state_code: AK place_fips: '24230' output: - ak_hap_base_benefit: 0 + ak_hap_base_benefit: 1_400 -# Numeric0 is missing modeled fuel coverage, not a legal determination that all such households are ineligible. -- name: Case 67, coal without a supported subtype yields an unavailable modeled amount. +# User-approved purchased-fuel default: Fairbanks oil 10 * .8 * $175 = $1400. +- name: Case 67, coal uses the purchased-fuel approximation with existing heating type. period: 2027 absolute_error_margin: 0.01 input: @@ -2150,7 +2150,7 @@ state_code: AK place_fips: '24230' output: - ak_hap_base_benefit: 0 + ak_hap_base_benefit: 1_400 # Numeric0 is missing modeled fuel coverage, not a legal determination that all such households are ineligible. - name: Case 68, other without a supported subtype yields an unavailable modeled amount. @@ -2409,3 +2409,434 @@ - 350 - 6_125 - 0 + +# Grant steps1-4: Fairbanks oil 10 * .8 + 1 elderly point =9; 9 *175 =1575. This assumes purchased wood, not pellets or self-harvest. +- name: "Case 74, purchased wood receives the single vulnerable-household point." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 60 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "WOOD" + ak_hap_dwelling_type: "TWO_BEDROOM_HOUSE" + ak_atap: 0 + receives_housing_assistance: false + wood_expense: 1_000 + households: + household1: + members: ["person1"] + state_code: "AK" + place_fips: "24230" + output: + ak_hap_base_benefit: 1_575 + +# Fairbanks 10 * .8 * .15 =1.2 fails the unrounded 2-point minimum; an elderly member adds 1 to reach2.2, rounded2 *175=350. +- name: "Case 75, purchased fuel changes whether a studio meets minimum heating points." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person2: + age: 60 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "WOOD" + ak_hap_dwelling_type: "STUDIO_HOTEL_OR_BOARDING_ROOM" + ak_atap: 0 + receives_housing_assistance: false + wood_expense: 1_000 + spm_unit2: + members: ["person2"] + heating_type: "COAL" + ak_hap_dwelling_type: "STUDIO_HOTEL_OR_BOARDING_ROOM" + ak_atap: 0 + receives_housing_assistance: false + wood_expense: 1_000 + coal_expense: 1_000 + households: + household1: + members: ["person1"] + state_code: "AK" + place_fips: "24230" + household2: + members: ["person2"] + state_code: "AK" + place_fips: "24230" + output: + ak_hap_base_benefit: [0, 350] + +# Annual income20000 lies in the 100-125% band, factor .6. Fairbanks10 * .8 * .4 * .6 =1.92 fails before rounding; adding the elderly point makes2.92 ->3 *175=525. +- name: "Case 76, the purchased factor precedes income reduction and minimum points." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + employment_income: 20_000 + person2: + age: 60 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + employment_income: 20_000 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "WOOD" + ak_hap_dwelling_type: "RV_TENT_OR_CAMPER" + ak_atap: 0 + receives_housing_assistance: false + wood_expense: 1_000 + spm_unit2: + members: ["person2"] + heating_type: "WOOD" + ak_hap_dwelling_type: "RV_TENT_OR_CAMPER" + ak_atap: 0 + receives_housing_assistance: false + wood_expense: 1_000 + households: + household1: + members: ["person1"] + state_code: "AK" + place_fips: "24230" + household2: + members: ["person2"] + state_code: "AK" + place_fips: "24230" + output: + ak_hap_base_benefit: [0, 525] + +# Koyuk oil25 (Addendum A; Census place41940); income25000 gives .5. One-bedroom25 * .8 * .55 * .5=5.5 ->6; elderly studio25 * .8 * .15 * .5 +1=2.5 ->3. +- name: "Case 77, purchased fuel preserves half-up rounding at exact half points." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + employment_income: 25_000 + person2: + age: 60 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + employment_income: 25_000 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "COAL" + ak_hap_dwelling_type: "ONE_BEDROOM_OR_ONE_ROOM_HOUSE" + ak_atap: 0 + receives_housing_assistance: false + wood_expense: 1_000 + coal_expense: 1_000 + spm_unit2: + members: ["person2"] + heating_type: "WOOD" + ak_hap_dwelling_type: "STUDIO_HOTEL_OR_BOARDING_ROOM" + ak_atap: 0 + receives_housing_assistance: false + wood_expense: 1_000 + households: + household1: + members: ["person1"] + state_code: "AK" + place_fips: "41940" + household2: + members: ["person2"] + state_code: "AK" + place_fips: "41940" + output: + ak_hap_base_benefit: [1_050, 525] + +# Household expense requirement remains strictly above200. Unrelated oil expense cannot replace the wood bill; zero wood expense does not infer self-harvest. +- name: "Case 78, purchased wood still requires annual primary heating expense above two hundred dollars." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person2: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person3: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "WOOD" + ak_hap_dwelling_type: "TWO_BEDROOM_HOUSE" + ak_atap: 0 + receives_housing_assistance: false + wood_expense: 0 + fuel_oil_expense: 1_000 + spm_unit2: + members: ["person2"] + heating_type: "WOOD" + ak_hap_dwelling_type: "TWO_BEDROOM_HOUSE" + ak_atap: 0 + receives_housing_assistance: false + wood_expense: 200 + fuel_oil_expense: 1_000 + spm_unit3: + members: ["person3"] + heating_type: "WOOD" + ak_hap_dwelling_type: "TWO_BEDROOM_HOUSE" + ak_atap: 0 + receives_housing_assistance: false + wood_expense: 200.01 + fuel_oil_expense: 1_000 + households: + household1: + members: ["person1"] + state_code: "AK" + place_fips: "24230" + household2: + members: ["person2"] + state_code: "AK" + place_fips: "24230" + household3: + members: ["person3"] + state_code: "AK" + place_fips: "24230" + output: + ak_hap_base_benefit: [0, 0, 1_400] + +# Ambler oil35 * .8 * large dwelling1.4 =39.2 points; round39 then cap35 *175=6125. +- name: "Case 79, purchased fuel remains subject to the final heating-point cap." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "WOOD" + ak_hap_dwelling_type: "LARGE_MOBILE_HOME_OR_BOAT" + ak_atap: 0 + receives_housing_assistance: false + wood_expense: 1_000 + households: + household1: + members: ["person1"] + state_code: "AK" + place_fips: "01970" + output: + ak_hap_base_benefit: 6_125 + +# Anchorage oil mapping remains ambiguous and an unmatched place is unavailable; selecting wood or coal cannot use gas points instead. +- name: "Case 80, purchased fuel cannot resolve unavailable oil community points." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person2: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "WOOD" + ak_hap_dwelling_type: "TWO_BEDROOM_HOUSE" + ak_atap: 0 + receives_housing_assistance: false + wood_expense: 1_000 + spm_unit2: + members: ["person2"] + heating_type: "COAL" + ak_hap_dwelling_type: "TWO_BEDROOM_HOUSE" + ak_atap: 0 + receives_housing_assistance: false + wood_expense: 1_000 + coal_expense: 1_000 + households: + household1: + members: ["person1"] + state_code: "AK" + place_fips: "03000" + household2: + members: ["person2"] + state_code: "AK" + place_fips: "99999" + output: + ak_hap_base_benefit: [0, 0] + +# Akiachak0/AVCP routes all residents; an unqualified household and a non-AK household receive no state base component. +- name: "Case 81, purchased fuel preserves tribal routing qualified-person and state gates." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person2: + age: 40 + immigration_status: "UNDOCUMENTED" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person3: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "WOOD" + ak_hap_dwelling_type: "TWO_BEDROOM_HOUSE" + ak_atap: 0 + receives_housing_assistance: false + wood_expense: 1_000 + spm_unit2: + members: ["person2"] + heating_type: "WOOD" + ak_hap_dwelling_type: "TWO_BEDROOM_HOUSE" + ak_atap: 0 + receives_housing_assistance: false + wood_expense: 1_000 + spm_unit3: + members: ["person3"] + heating_type: "WOOD" + ak_hap_dwelling_type: "TWO_BEDROOM_HOUSE" + ak_atap: 0 + receives_housing_assistance: false + wood_expense: 1_000 + households: + household1: + members: ["person1"] + state_code: "AK" + place_fips: "00760" + household2: + members: ["person2"] + state_code: "AK" + place_fips: "24230" + household3: + members: ["person3"] + state_code: "NH" + place_fips: "24230" + output: + ak_hap_base_benefit: [0, 0, 0] + +# An ordinary purchased-coal calculation would yield1400, but subsidized heat in rent is excluded before payment. +- name: "Case 82, purchased coal retains the existing subsidized heat-in-rent exclusion." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + pre_subsidy_rent: 12_000 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "COAL" + ak_hap_dwelling_type: "TWO_BEDROOM_HOUSE" + ak_atap: 0 + receives_housing_assistance: true + wood_expense: 1_000 + coal_expense: 1_000 + heat_expense_included_in_rent: true + households: + household1: + members: ["person1"] + state_code: "AK" + place_fips: "24230" + output: + ak_hap_base_benefit: 0 + +# Purchased approximation is fixed for WOOD, independent of reported bill: zero wood bill plus300 annual rent meets the existing heat-in-rent expense gate; base8 *175=1400. +- name: "Case 83, unsubsidized heat in rent supplies the expense gate without inferring fuel procurement." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + pre_subsidy_rent: 300 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "WOOD" + ak_hap_dwelling_type: "TWO_BEDROOM_HOUSE" + ak_atap: 0 + receives_housing_assistance: false + wood_expense: 0 + heat_expense_included_in_rent: true + households: + household1: + members: ["person1"] + state_code: "AK" + place_fips: "24230" + output: + ak_hap_base_benefit: 1_400 diff --git a/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_base_benefit.py b/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_base_benefit.py index a7a451f5528..48dfa4d98e8 100644 --- a/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_base_benefit.py +++ b/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_base_benefit.py @@ -35,15 +35,23 @@ def formula(spm_unit, period, parameters): | (fuel == fuels.PROPANE) | (fuel == fuels.ELECTRICITY) ) + wood_or_coal = (fuel == fuels.WOOD) | (fuel == fuels.COAL) # Propane uses oil points under 7 AAC 44.080(f). Kerosene is Grade 1 - # heating oil in the AHFC-funded technical guide. Wood/coal subtypes, - # unclassified OTHER fuels and unmatched oil geography are unavailable - # modeled amounts (zero fallback), not statutory denials. Anchorage + # heating oil in the AHFC-funded technical guide. Unclassified OTHER + # fuels and unmatched oil geography yield unavailable modeled amounts + # (zero fallback), not statutory denials. Anchorage # oil is ambiguous. The gas table uses a documented nearest-community # approximation where a direct published place match is unavailable. + # Purchased wood/coal is the approved modeling default. Existing + # heating_type cannot identify self-harvest or pellets, whose factors + # differ; neither subtype is inferred from the reported expense. community_points = select( - [oil_fuel, fuel == fuels.NATURAL_GAS], - [oil_table[oil_place], gas_table[gas_place]], + [oil_fuel, fuel == fuels.NATURAL_GAS, wood_or_coal], + [ + oil_table[oil_place], + gas_table[gas_place], + oil_table[oil_place] * p.purchased_wood_coal_multiplier, + ], default=0, ) dwelling = spm_unit("ak_hap_dwelling_type", period) From c02290a59140f7763cb86665a616b0bea20e4e85 Mon Sep 17 00:00:00 2001 From: Ziming Date: Tue, 6 Oct 2026 14:44:36 -0400 Subject: [PATCH 05/16] Add Alaska HAP final sharing and utility allowance adjustments --- changelog.d/ak-hap-final-award.added.md | 1 + .../maximum_shared_household_share.yaml | 22 + .../benefit/utility_allowance_reduction.yaml | 18 + policyengine_us/programs.yaml | 10 +- .../gov/states/ak/dpa/hap/ak_hap.yaml | 597 ++++++++++++++++++ .../variables/gov/states/ak/dpa/hap/ak_hap.py | 54 ++ .../states/ak/dpa/hap/ak_hap_base_benefit.py | 6 +- 7 files changed, 704 insertions(+), 4 deletions(-) create mode 100644 changelog.d/ak-hap-final-award.added.md create mode 100644 policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/maximum_shared_household_share.yaml create mode 100644 policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/utility_allowance_reduction.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap.yaml create mode 100644 policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap.py diff --git a/changelog.d/ak-hap-final-award.added.md b/changelog.d/ak-hap-final-award.added.md new file mode 100644 index 00000000000..bded5006759 --- /dev/null +++ b/changelog.d/ak-hap-final-award.added.md @@ -0,0 +1 @@ +Add Alaska HAP final regular heating benefits with the operating manual's household-sharing and utility-allowance adjustments, and register the supported FY2027 coverage. diff --git a/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/maximum_shared_household_share.yaml b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/maximum_shared_household_share.yaml new file mode 100644 index 00000000000..b8490da7e9e --- /dev/null +++ b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/maximum_shared_household_share.yaml @@ -0,0 +1,22 @@ +description: Alaska limits a household sharing its dwelling to this share of its calculated award under the Heating Assistance Program. +# Approved manual-based convention: section 3002-1 A.3-5 divides each award +# by the number of eligible households, with this maximum share even when +# only one sharing household is eligible. Actual heating payments do not +# determine the share. This conflicts with 7 AAC 44.035(c) actual-cost sharing +# and the earlier points adjustment in 44.080(h) and grant manual step 2. +# This selection does not establish a regulatory amendment or verify +# historical years before FY2027. +values: + 2026-10-01: 0.5 + +metadata: + unit: /1 + period: year + label: Alaska HAP maximum shared household benefit share + reference: + - title: Alaska HAP Manual 3002-1, Types of Households, A.3-5 + href: http://dpaweb.hss.state.ak.us/manuals/HAP/3002/3002-1_households.htm + - title: Alaska HAP Manual 3004-5, Grant Computation, Step 2 (conflicting text) + href: http://dpaweb.hss.state.ak.us/manuals/HAP/3004/3004-5_grant_computation.htm + - title: 7 AAC 44.035(c) and 44.080(h) (conflicting text) + href: https://www.akleg.gov/basis/aac.asp?media=print&secStart=7.44.010&secEnd=7.44.9001 diff --git a/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/utility_allowance_reduction.yaml b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/utility_allowance_reduction.yaml new file mode 100644 index 00000000000..da5a5e209a2 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/utility_allowance_reduction.yaml @@ -0,0 +1,18 @@ +description: Alaska reduces the calculated benefit by this share for subsidized households paying heating costs directly and receiving a utility allowance under the Heating Assistance Program. +# Approved manual-based convention: grant manual step 8 applies this +# reduction to the dollar award, regardless of the allowance amount. +# In contrast, 7 AAC 44.080(l)-(n) halves points before the minimum and +# rounding. This selection does not establish a regulatory amendment or +# verify historical years before FY2027. +values: + 2026-10-01: 0.5 + +metadata: + unit: /1 + period: year + label: Alaska HAP utility allowance benefit reduction + reference: + - title: Alaska HAP Manual 3004-5, Grant Computation, Step 8 + href: http://dpaweb.hss.state.ak.us/manuals/HAP/3004/3004-5_grant_computation.htm + - title: 7 AAC 44.080(l)-(n) (conflicting text) + href: https://www.akleg.gov/basis/aac.asp?media=print&secStart=7.44.010&secEnd=7.44.9001 diff --git a/policyengine_us/programs.yaml b/policyengine_us/programs.yaml index 756dc2c4988..e79b1e3c33b 100644 --- a/policyengine_us/programs.yaml +++ b/policyengine_us/programs.yaml @@ -802,7 +802,7 @@ programs: category: Benefits agency: HHS status: partial - coverage: OR, DC, Riverside County, MA, IL, KS, MS, TX + coverage: OR, DC, Riverside County, MA, IL, KS, MS, TX, AK state_implementations: - state: OR status: in_progress @@ -846,6 +846,14 @@ programs: variable: tx_ceap parameter_prefix: gov.states.tx.tdhca.ceap notes: Models the FPG income limit, the FY2024-only SMI limit, benefit amounts, and categorical eligibility through TANF enrollment, SNAP eligibility, and SSI receipt. Not modeled - net rather than gross gambling winnings, the Medicare premium deduction from counted Social Security, and the exclusion of means-tested veterans' pensions from counted income (10 TAC 6.4(c)) + - state: AK + status: partial + name: Alaska HAP + full_name: Alaska Heating Assistance Program + variable: ak_hap + parameter_prefix: gov.states.ak.dpa.hap + verified_years: "2027" + notes: FY2027 regular heating assistance uses the operating manual's equal eligible-household shares and final-dollar utility-allowance reduction, despite conflicting regulatory text. SPM units approximate economic households; wood and coal default to purchased fuel. Alaska utility allowances must be supplied. Some community mappings, tribal and residency facts, owner/room-renter arrangements and housing step-down exceptions remain unmodeled. Earlier-year results are unverified historical estimates; crisis and equipment assistance are out of scope. # --- SSA programs --- - id: ssi diff --git a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap.yaml b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap.yaml new file mode 100644 index 00000000000..17fb5b8cc36 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap.yaml @@ -0,0 +1,597 @@ +# Approved manual-based convention: compute each household's base first, then +# apply equal shares and the final-dollar utility-allowance reduction. This +# conflicts with earlier points-sharing and utility-adjustment regulatory text. +# SPM units approximate separate economic households within one dwelling. +# Sources, each URL listed once: +# Household manual 3002-1 A.3-5: +# http://dpaweb.hss.state.ak.us/manuals/HAP/3002/3002-1_households.htm +# Grant manual 3004-5 steps 1-8 and FY2027 price of $175 per point: +# http://dpaweb.hss.state.ak.us/manuals/HAP/3004/3004-5_grant_computation.htm +# Community table, Fairbanks oil 10, Juneau oil 5, Ambler oil 35: +# http://dpaweb.hss.state.ak.us/manuals/HAP/addendum/addendum_a.htm +# Current income bands: +# http://dpaweb.hss.state.ak.us/manuals/HAP/addendum/addendum_e.htm + +# A single economic household retains the complete sole-household base award. +- name: Case 1, a sole household keeps its base when no allowance adjustment applies. + period: 2027 + absolute_error_margin: 0.01 + input: + state_code: AK + ak_hap_base_benefit: 1_925 + receives_housing_assistance: false + heat_expense_included_in_rent: false + hud_utility_allowance: 0 + output: + ak_hap: 1_925 + +# Fairbanks 10 oil points, ordinary two-bedroom factor 1. The first unit has +# zero income and an elderly member: (10 * 1 + 1) * 175 = 1,925. The second +# has annual income 24,000 in the 100-125% band: 10 * 0.6 * 175 = 1,050. +# A.3-5 divides each award by two despite unequal member counts and bills. +# Bills are 25%/75% of combined costs; those proportions do not set the grant. +- name: Case 2, two Fairbanks households share their independently calculated awards equally. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 65 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person2: + age: 35 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person3: + age: 8 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person4: + age: 40 + immigration_status: CITIZEN + employment_income: 24_000 + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: [person1, person2, person3] + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + fuel_oil_expense: 300 + ak_atap: 0 + receives_housing_assistance: false + heat_expense_included_in_rent: false + spm_unit2: + members: [person4] + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + fuel_oil_expense: 900 + ak_atap: 0 + receives_housing_assistance: false + heat_expense_included_in_rent: false + households: + household1: + members: [person1, person2, person3, person4] + state_code: AK + place_fips: '24230' + hud_utility_allowance: 0 + output: + ak_hap_household_size: [3, 1] + ak_hap_countable_income: [0, 24_000] + ak_hap_income_factor: [1, 0.6] + heating_expense: [300, 900] + ak_hap_base_benefit: [1_925, 1_050] + ak_hap: [962.50, 525] + +# A.5 counts eligible economic households, not people or actual expense shares. +# Each unit receives one-third of its own base; no monetary rounding follows. +# The tighter margin distinguishes the fractional award from cent rounding. +- name: Case 3, three eligible units with different sizes and bases each receive one third. + period: 2027 + absolute_error_margin: 0.0001 + input: + people: + person1: {} + person2: {} + person3: {} + person4: {} + person5: {} + person6: {} + spm_units: + spm_unit1: + members: [person1] + ak_hap_base_benefit: 1_925 + heating_expense: 300 + receives_housing_assistance: false + heat_expense_included_in_rent: false + spm_unit2: + members: [person2, person3] + ak_hap_base_benefit: 1_050 + heating_expense: 900 + receives_housing_assistance: false + heat_expense_included_in_rent: false + spm_unit3: + members: [person4, person5, person6] + ak_hap_base_benefit: 525 + heating_expense: 1_800 + receives_housing_assistance: false + heat_expense_included_in_rent: false + households: + household1: + members: [person1, person2, person3, person4, person5, person6] + state_code: AK + hud_utility_allowance: 0 + output: + ak_hap: [641.666667, 350, 175] + +# A.5 eligible-household denominator and explicit 50% maximum for house sharers. +# One positive base among three residents still receives one-half, not all or +# one-third. Two positive bases among three residents each receive one-half. +# All-zero resident units have no eligible denominator and safely return zero. +- name: Case 4, only eligible units enter the denominator and a sharer never exceeds half. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: {} + person2: {} + person3: {} + person4: {} + person5: {} + person6: {} + person7: {} + person8: {} + spm_units: + spm_unit1: + members: [person1] + ak_hap_base_benefit: 1_750 + receives_housing_assistance: false + spm_unit2: + members: [person2] + ak_hap_base_benefit: 0 + receives_housing_assistance: false + spm_unit3: + members: [person3] + ak_hap_base_benefit: 0 + receives_housing_assistance: false + spm_unit4: + members: [person4] + ak_hap_base_benefit: 1_750 + receives_housing_assistance: false + spm_unit5: + members: [person5] + ak_hap_base_benefit: 1_050 + receives_housing_assistance: false + spm_unit6: + members: [person6] + ak_hap_base_benefit: 0 + receives_housing_assistance: false + spm_unit7: + members: [person7] + ak_hap_base_benefit: 0 + receives_housing_assistance: false + spm_unit8: + members: [person8] + ak_hap_base_benefit: 0 + receives_housing_assistance: false + households: + household1: + members: [person1, person2, person3] + state_code: AK + hud_utility_allowance: 0 + household2: + members: [person4, person5, person6] + state_code: AK + hud_utility_allowance: 0 + household3: + members: [person7, person8] + state_code: AK + hud_utility_allowance: 0 + output: + ak_hap: [875, 0, 0, 875, 525, 0, 0, 0] + +# Separate homes never share a denominator. A supplied positive base outside +# Alaska cannot bypass the final variable's state restriction. +- name: Case 5, sharing remains within each physical household in a mixed state vector. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: {} + person2: {} + person3: {} + person4: {} + person5: {} + person6: {} + spm_units: + spm_unit1: + members: [person1, person2] + ak_hap_base_benefit: 1_925 + receives_housing_assistance: false + spm_unit2: + members: [person3] + ak_hap_base_benefit: 1_925 + receives_housing_assistance: false + spm_unit3: + members: [person4] + ak_hap_base_benefit: 1_925 + receives_housing_assistance: false + spm_unit4: + members: [person5] + ak_hap_base_benefit: 1_925 + receives_housing_assistance: false + spm_unit5: + members: [person6] + ak_hap_base_benefit: 1_925 + receives_housing_assistance: false + households: + household1: + members: [person1, person2, person3] + state_code: AK + hud_utility_allowance: 0 + household2: + members: [person4] + state_code: AK + hud_utility_allowance: 0 + household3: + members: [person5, person6] + state_code: NH + hud_utility_allowance: 0 + output: + ak_hap: [962.50, 962.50, 1_925, 0, 0] + +# Grant step8 requires subsidized housing, directly paid heat and a positive +# allowance. Test all Boolean combinations of those supplied facts, plus a +# second positive allowance magnitude. Fairbanks zero-income base is 1,750. +# Subsidized heat-in-rent cases remain zero through the existing base gate. +- name: Case 6, the allowance reduction requires all conditions and ignores its positive magnitude. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + pre_subsidy_rent: 12_000 + person2: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + pre_subsidy_rent: 12_000 + person3: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + pre_subsidy_rent: 12_000 + person4: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + pre_subsidy_rent: 12_000 + person5: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + pre_subsidy_rent: 12_000 + person6: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + pre_subsidy_rent: 12_000 + person7: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + pre_subsidy_rent: 12_000 + person8: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + pre_subsidy_rent: 12_000 + person9: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + pre_subsidy_rent: 12_000 + spm_units: + spm_unit1: + members: [person1] + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + fuel_oil_expense: 300 + ak_atap: 0 + receives_housing_assistance: false + heat_expense_included_in_rent: false + spm_unit2: + members: [person2] + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + fuel_oil_expense: 300 + ak_atap: 0 + receives_housing_assistance: false + heat_expense_included_in_rent: false + spm_unit3: + members: [person3] + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + fuel_oil_expense: 300 + ak_atap: 0 + receives_housing_assistance: false + heat_expense_included_in_rent: true + spm_unit4: + members: [person4] + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + fuel_oil_expense: 300 + ak_atap: 0 + receives_housing_assistance: false + heat_expense_included_in_rent: true + spm_unit5: + members: [person5] + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + fuel_oil_expense: 300 + ak_atap: 0 + receives_housing_assistance: true + heat_expense_included_in_rent: false + spm_unit6: + members: [person6] + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + fuel_oil_expense: 300 + ak_atap: 0 + receives_housing_assistance: true + heat_expense_included_in_rent: false + spm_unit7: + members: [person7] + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + fuel_oil_expense: 300 + ak_atap: 0 + receives_housing_assistance: true + heat_expense_included_in_rent: true + spm_unit8: + members: [person8] + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + fuel_oil_expense: 300 + ak_atap: 0 + receives_housing_assistance: true + heat_expense_included_in_rent: true + spm_unit9: + members: [person9] + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + fuel_oil_expense: 300 + ak_atap: 0 + receives_housing_assistance: true + heat_expense_included_in_rent: false + households: + household1: + members: [person1] + state_code: AK + place_fips: '24230' + hud_utility_allowance: 0 + household2: + members: [person2] + state_code: AK + place_fips: '24230' + hud_utility_allowance: 1 + household3: + members: [person3] + state_code: AK + place_fips: '24230' + hud_utility_allowance: 0 + household4: + members: [person4] + state_code: AK + place_fips: '24230' + hud_utility_allowance: 1 + household5: + members: [person5] + state_code: AK + place_fips: '24230' + hud_utility_allowance: 0 + household6: + members: [person6] + state_code: AK + place_fips: '24230' + hud_utility_allowance: 1 + household7: + members: [person7] + state_code: AK + place_fips: '24230' + hud_utility_allowance: 0 + household8: + members: [person8] + state_code: AK + place_fips: '24230' + hud_utility_allowance: 1 + household9: + members: [person9] + state_code: AK + place_fips: '24230' + hud_utility_allowance: 12_000 + output: + ak_hap_base_benefit: [1_750, 1_750, 1_750, 1_750, 1_750, 1_750, 0, 0, 1_750] + ak_hap: [1_750, 1_750, 1_750, 1_750, 1_750, 875, 0, 0, 875] + +# Juneau oil5 * dwelling1 * income factor0.6 =3 points, at least2; $525. +# Step8 then reduces dollars to262.50. Reducing points first would wrongly +# deny this household for having only1.5 points. +- name: Case 7, a three point Juneau household receives half the dollar award. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + employment_income: 24_000 + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: [person1] + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + fuel_oil_expense: 300 + ak_atap: 0 + receives_housing_assistance: true + heat_expense_included_in_rent: false + households: + household1: + members: [person1] + state_code: AK + place_fips: '36400' + hud_utility_allowance: 1_200 + output: + ak_hap_household_size: 1 + ak_hap_countable_income: 24_000 + ak_hap_income_factor: 0.6 + heating_expense: 300 + ak_hap_base_benefit: 525 + ak_hap: 262.50 + +# Fairbanks studio10 * .15 =1.5 points fails before rounding. The two elderly +# units each add1, reach2.5 points, and round up to3 before conversion to$525. +# The ineligible unit does not enter their two-household denominator; sharing +# gives262.50 each and the subsidized unit is halved again to131.25. +- name: Case 8, minimum points and half up rounding precede sharing and allowance adjustments. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person2: + age: 60 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person3: + age: 65 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: [person1] + heating_type: FUEL_OIL + ak_hap_dwelling_type: STUDIO_HOTEL_OR_BOARDING_ROOM + fuel_oil_expense: 300 + ak_atap: 0 + receives_housing_assistance: false + heat_expense_included_in_rent: false + spm_unit2: + members: [person2] + heating_type: FUEL_OIL + ak_hap_dwelling_type: STUDIO_HOTEL_OR_BOARDING_ROOM + fuel_oil_expense: 300 + ak_atap: 0 + receives_housing_assistance: false + heat_expense_included_in_rent: false + spm_unit3: + members: [person3] + heating_type: FUEL_OIL + ak_hap_dwelling_type: STUDIO_HOTEL_OR_BOARDING_ROOM + fuel_oil_expense: 300 + ak_atap: 0 + receives_housing_assistance: true + heat_expense_included_in_rent: false + households: + household1: + members: [person1, person2, person3] + state_code: AK + place_fips: '24230' + hud_utility_allowance: 1_200 + output: + ak_hap_household_size: [1, 1, 1] + ak_hap_countable_income: [0, 0, 0] + ak_hap_income_factor: [1, 1, 1] + ak_hap_base_benefit: [0, 525, 525] + ak_hap: [0, 262.50, 131.25] + +# Ambler oil35 * large-mobile-home1.4 =49 points, capped at35, giving$6,125. +# Both eligible resident units get3,062.50; step8 halves only the subsidized +# unit again to1,531.25. Neither benefit is capped at its $300 heating bill. +- name: Case 9, the point cap applies before sharing and final dollar reduction. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person2: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: [person1] + heating_type: FUEL_OIL + ak_hap_dwelling_type: LARGE_MOBILE_HOME_OR_BOAT + fuel_oil_expense: 300 + ak_atap: 0 + receives_housing_assistance: false + heat_expense_included_in_rent: false + spm_unit2: + members: [person2] + heating_type: FUEL_OIL + ak_hap_dwelling_type: LARGE_MOBILE_HOME_OR_BOAT + fuel_oil_expense: 300 + ak_atap: 0 + receives_housing_assistance: true + heat_expense_included_in_rent: false + households: + household1: + members: [person1, person2] + state_code: AK + place_fips: '01970' + hud_utility_allowance: 1_200 + output: + ak_hap_household_size: [1, 1] + ak_hap_countable_income: [0, 0] + ak_hap_income_factor: [1, 1] + ak_hap_base_benefit: [6_125, 6_125] + ak_hap: [3_062.50, 1_531.25] diff --git a/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap.py b/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap.py new file mode 100644 index 00000000000..d2688b1a14a --- /dev/null +++ b/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap.py @@ -0,0 +1,54 @@ +from policyengine_us.model_api import * + + +class ak_hap(Variable): + value_type = float + entity = SPMUnit + definition_period = YEAR + unit = USD + label = "Alaska Heating Assistance Program benefit" + reference = ( + "http://dpaweb.hss.state.ak.us/manuals/HAP/3002/3002-1_households.htm", + "http://dpaweb.hss.state.ak.us/manuals/HAP/3004/3004-5_grant_computation.htm", + "https://www.akleg.gov/basis/aac.asp?media=print&secStart=7.44.010&secEnd=7.44.9001", + ) + defined_for = StateCode.AK + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ak.dpa.hap.benefit + base_benefit = spm_unit("ak_hap_base_benefit", period) + # SPM units approximate separate economic households. This does not + # distinguish the manual's owner/occupant and room-renter exceptions. + # Project one first-member marker per SPM unit, regardless of its size. + first_member = spm_unit.members_position == 0 + household_count = spm_unit.household.sum(first_member) + eligible_household_count = spm_unit.household.sum( + first_member & spm_unit.project(base_benefit > 0) + ) + # Approved convention: household manual A.3-5 applies equal shares to + # dollar awards, capped at 50% for any sharer. Conflicting earlier + # points/actual-cost sharing text is documented in the parameter. + share = where( + household_count > 1, + min_( + 1 / max_(eligible_household_count, 1), + p.maximum_shared_household_share, + ), + 1, + ) + # The supplied household allowance is a proxy, not an Alaska schedule; + # its zero default cannot establish absence. Housing step-down + # exceptions are unobserved, as are the base formula's tribal, + # residency and unresolved geography limitations. + utility_adjustment = ( + spm_unit("receives_housing_assistance", period) + & ~spm_unit("heat_expense_included_in_rent", period) + & (spm_unit.household("hud_utility_allowance", period) > 0) + ) + # Manual step 8 reduces dollars after the base minimum/rounding/cap; + # 7 AAC 44.080(l)-(n) instead reduces points before the minimum. + return ( + base_benefit + * share + * where(utility_adjustment, 1 - p.utility_allowance_reduction, 1) + ) diff --git a/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_base_benefit.py b/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_base_benefit.py index 48dfa4d98e8..66c1024e6ae 100644 --- a/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_base_benefit.py +++ b/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_base_benefit.py @@ -93,8 +93,8 @@ def formula(spm_unit, period, parameters): & (points >= p.minimum_points) ) # Apply the unrounded minimum before half-up whole-point rounding. - # This is the sole-household base amount: no expense cap, sharing - # division or utility-allowance reduction is applied. Those final - # adjustments remain unresolved; this is not the complete program. + # This is the sole-household base amount, without an expense cap. + # ak_hap applies sharing and utility-allowance reductions to dollars + # under the approved manual-based modeling convention. rounded_points = min_(np.floor(points + 0.5), p.maximum_points) return where(eligible, rounded_points * p.point_value, 0) From 8ae8da1085224ce844f620dc5ea3fcc609e2837e Mon Sep 17 00:00:00 2001 From: Ziming Date: Tue, 20 Oct 2026 20:13:08 -0400 Subject: [PATCH 06/16] Normalize Alaska HAP reference page formatting --- .../states/ak/dpa/hap/benefit/community_points/natural_gas.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/community_points/natural_gas.yaml b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/community_points/natural_gas.yaml index c9c7d3ec6a6..b48981cc883 100644 --- a/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/community_points/natural_gas.yaml +++ b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/community_points/natural_gas.yaml @@ -727,5 +727,5 @@ metadata: href: http://dpaweb.hss.state.ak.us/manuals/HAP/3004/3004-5_grant_computation.htm - title: Census 2025 Alaska Places Gazetteer href: https://www2.census.gov/geo/docs/maps-data/data/gazetteer/2025_Gazetteer/2025_gaz_place_02.txt - - title: Alaska DEC Cook Inlet Community Profiles, pages 11, 19, 27, 29, 34, 54, 89 + - title: "Alaska DEC Cook Inlet Community Profiles #page 11,19,27,29,34,54,89" href: https://dec.alaska.gov/media/8211/ciscp-b-resources.pdf#page=11 From 631f621c01f5842c36425aaea8bc2eb6c49f694e Mon Sep 17 00:00:00 2001 From: Ziming Date: Tue, 20 Oct 2026 20:46:21 -0400 Subject: [PATCH 07/16] Fix Alaska heating income receipts and point rounding --- changelog.d/ak-liheap-current-income.fixed.md | 1 + .../ak/dpa/hap/income/unearned_sources.yaml | 3 +- .../gov/states/ak/dpa/hap/ak_hap.yaml | 208 ++++++++++++++++++ .../states/ak/dpa/hap/ak_hap_base_benefit.py | 6 +- .../ak/dpa/hap/ak_hap_countable_income.py | 4 +- 5 files changed, 218 insertions(+), 4 deletions(-) create mode 100644 changelog.d/ak-liheap-current-income.fixed.md diff --git a/changelog.d/ak-liheap-current-income.fixed.md b/changelog.d/ak-liheap-current-income.fixed.md new file mode 100644 index 00000000000..9b8c825da1c --- /dev/null +++ b/changelog.d/ak-liheap-current-income.fixed.md @@ -0,0 +1 @@ +Count received TANF, total unemployment compensation and ordinary military retirement in Alaska HAP, and preserve published decimal income factors when rounding heating points. diff --git a/policyengine_us/parameters/gov/states/ak/dpa/hap/income/unearned_sources.yaml b/policyengine_us/parameters/gov/states/ak/dpa/hap/income/unearned_sources.yaml index 12390f9bee3..fdd8a3508c9 100644 --- a/policyengine_us/parameters/gov/states/ak/dpa/hap/income/unearned_sources.yaml +++ b/policyengine_us/parameters/gov/states/ak/dpa/hap/income/unearned_sources.yaml @@ -5,12 +5,13 @@ values: - ssi - ak_ssp - pension_income + - military_retirement_pay - retirement_distributions - railroad_benefits - survivor_benefits - veterans_benefits - disability_benefits - - unemployment_compensation + - total_unemployment_compensation - workers_compensation - general_assistance - strike_benefits diff --git a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap.yaml b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap.yaml index 17fb5b8cc36..a28c30c3d97 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap.yaml @@ -595,3 +595,211 @@ ak_hap_income_factor: [1, 1] ak_hap_base_benefit: [6_125, 6_125] ak_hap: [3_062.50, 1_531.25] + +- name: Primary military retirement excludes its household from eligible heating shares + period: 2027 + input: + people: + retiree: + age: 40 + immigration_status: CITIZEN + years_in_military: 20 + military_retirement_pay: 36000 + neighbor1: + age: 40 + immigration_status: CITIZEN + neighbor2: + age: 40 + immigration_status: CITIZEN + tax_units: + tax_unit0: + members: + - retiree + tax_unit1: + members: + - neighbor1 + tax_unit2: + members: + - neighbor2 + spm_units: + spm_unit0: + members: + - retiree + heating_type: FUEL_OIL + fuel_oil_expense: 3000 + spm_unit1: + members: + - neighbor1 + heating_type: FUEL_OIL + fuel_oil_expense: 3000 + spm_unit2: + members: + - neighbor2 + heating_type: FUEL_OIL + fuel_oil_expense: 3000 + households: + home: + members: + - retiree + - neighbor1 + - neighbor2 + state_code: AK + place_fips: '24230' + output: + pension_income: + - 0 + - 0 + - 0 + veterans_benefits: + - 0 + - 0 + - 0 + ak_hap_countable_income: + - 36000 + - 0 + - 0 + ak_hap_income_factor: + - 0 + - 1 + - 1 + ak_hap_base_benefit: + - 0 + - 1750 + - 1750 + ak_hap: + - 0 + - 875 + - 875 +- name: Only received ATAP reduces the regular heating award + period: 2027 + input: + people: + parent0: + age: 40 + immigration_status: CITIZEN + child0: + age: 10 + immigration_status: CITIZEN + parent1: + age: 40 + immigration_status: CITIZEN + child1: + age: 10 + immigration_status: CITIZEN + tax_units: + tax_unit0: + members: &id001 + - parent0 + - child0 + tax_unit1: + members: &id002 + - parent1 + - child1 + spm_units: + spm_unit0: + members: *id001 + heating_type: FUEL_OIL + fuel_oil_expense: 3000 + takes_up_tanf_if_eligible: false + spm_unit1: + members: *id002 + heating_type: FUEL_OIL + fuel_oil_expense: 3000 + takes_up_tanf_if_eligible: true + households: + home0: + members: *id001 + state_code: AK + place_fips: '24230' + home1: + members: *id002 + state_code: AK + place_fips: '24230' + output: + tanf: + - 0 + - 9852 + ak_hap_countable_income: + - 0 + - 9852 + ak_hap_income_factor: + - 1 + - 0.9 + ak_hap: + - 1750 + - 1575 +- name: Published decimal income factors preserve half-up whole heating points + period: 2027 + input: + people: + person0: + age: 40 + immigration_status: CITIZEN + employment_income: 12000 + person1: + age: 40 + immigration_status: CITIZEN + employment_income: 18000 + person2: + age: 40 + immigration_status: CITIZEN + employment_income: 25000 + tax_units: + tax_unit0: + members: + - person0 + tax_unit1: + members: + - person1 + tax_unit2: + members: + - person2 + spm_units: + spm_unit0: + members: + - person0 + heating_type: FUEL_OIL + fuel_oil_expense: 1000 + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + fuel_oil_expense: 1000 + spm_unit2: + members: + - person2 + heating_type: FUEL_OIL + fuel_oil_expense: 1000 + households: + home0: + members: + - person0 + state_code: AK + place_fips: '36400' + home1: + members: + - person1 + state_code: AK + place_fips: '36400' + home2: + members: + - person2 + state_code: AK + place_fips: '36400' + output: + ak_hap_countable_income: + - 12000 + - 18000 + - 25000 + ak_hap_income_factor: + - 0.8 + - 0.7 + - 0.5 + ak_hap_base_benefit: + - 700 + - 700 + - 525 + ak_hap: + - 700 + - 700 + - 525 diff --git a/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_base_benefit.py b/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_base_benefit.py index 66c1024e6ae..f290a8c0f24 100644 --- a/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_base_benefit.py +++ b/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_base_benefit.py @@ -55,7 +55,11 @@ def formula(spm_unit, period, parameters): default=0, ) dwelling = spm_unit("ak_hap_dwelling_type", period) - factor = spm_unit("ak_hap_income_factor", period) + # Restore the table's decimal tenths after float32 storage so exact + # half points retain the manual's half-up rounding below. + factor = np.round( + spm_unit("ak_hap_income_factor", period).astype(np.float64), 1 + ) person = spm_unit.members age = person("age", period) # Existing disability status approximates the manual's documented diff --git a/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_countable_income.py b/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_countable_income.py index 8402ea62d54..4f2a569eb44 100644 --- a/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_countable_income.py +++ b/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_countable_income.py @@ -61,12 +61,12 @@ def formula(spm_unit, period, parameters): # routes are unavailable, so no ATAP pass-through cap is imputed. # Gross SSA includes Medicare withholding. No general medical, care, # support-paid or earned-income deduction is authorized by these rules. - # ATAP is an SPM-unit benefit: count its annual flow exactly once. + # Count the takeup-sensitive ATAP receipt once per SPM unit. total = ( countable_earned + unearned + rental + countable_gifts - + spm_unit("ak_atap", period) + + spm_unit("tanf", period) ) return max_(total, 0) From 5fb88c26403da8e74337a45669baa6235d01a875 Mon Sep 17 00:00:00 2001 From: Ziming Date: Tue, 20 Oct 2026 20:56:33 -0400 Subject: [PATCH 08/16] Honor explicit public housing in Alaska heating rules --- changelog.d/ak-liheap-current-income.fixed.md | 2 +- .../gov/states/ak/dpa/hap/ak_hap.yaml | 117 ++++++++++++++++++ .../variables/gov/states/ak/dpa/hap/ak_hap.py | 5 +- .../states/ak/dpa/hap/ak_hap_base_benefit.py | 5 +- 4 files changed, 126 insertions(+), 3 deletions(-) diff --git a/changelog.d/ak-liheap-current-income.fixed.md b/changelog.d/ak-liheap-current-income.fixed.md index 9b8c825da1c..f560659ec7f 100644 --- a/changelog.d/ak-liheap-current-income.fixed.md +++ b/changelog.d/ak-liheap-current-income.fixed.md @@ -1 +1 @@ -Count received TANF, total unemployment compensation and ordinary military retirement in Alaska HAP, and preserve published decimal income factors when rounding heating points. +Count received TANF, total unemployment compensation and ordinary military retirement in Alaska HAP, preserve published decimal income factors when rounding heating points, and recognize explicit public housing in the heating and utility-allowance rules. diff --git a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap.yaml b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap.yaml index a28c30c3d97..389d5c5df1d 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap.yaml @@ -803,3 +803,120 @@ - 700 - 700 - 525 + +- name: Explicit public housing controls included heat and reported utility allowance + period: 2027 + input: + people: + person0: + age: 40 + immigration_status: CITIZEN + pre_subsidy_rent: 12000 + person1: + age: 40 + immigration_status: CITIZEN + pre_subsidy_rent: 12000 + person2: + age: 40 + immigration_status: CITIZEN + pre_subsidy_rent: 12000 + person3: + age: 40 + immigration_status: CITIZEN + pre_subsidy_rent: 12000 + tax_units: + tax_unit0: + members: + - person0 + tax_unit1: + members: + - person1 + tax_unit2: + members: + - person2 + tax_unit3: + members: + - person3 + spm_units: + spm_unit0: + members: + - person0 + heating_type: FUEL_OIL + heat_expense_included_in_rent: true + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + heat_expense_included_in_rent: true + receives_housing_assistance: true + spm_unit2: + members: + - person2 + heating_type: FUEL_OIL + heat_expense_included_in_rent: false + fuel_oil_expense: 3000 + spm_unit3: + members: + - person3 + heating_type: FUEL_OIL + heat_expense_included_in_rent: false + receives_housing_assistance: true + fuel_oil_expense: 3000 + households: + home0: + members: + - person0 + state_code: AK + place_fips: '24230' + is_in_public_housing: true + home1: + members: + - person1 + state_code: AK + place_fips: '24230' + is_in_public_housing: true + home2: + members: + - person2 + state_code: AK + place_fips: '24230' + is_in_public_housing: true + hud_utility_allowance: 1200 + home3: + members: + - person3 + state_code: AK + place_fips: '24230' + is_in_public_housing: true + hud_utility_allowance: 1200 + output: + is_in_public_housing: + - true + - true + - true + - true + receives_housing_assistance: + - false + - true + - false + - true + housing_assistance: + - 0 + - 0 + - 0 + - 0 + ak_hap_countable_income: + - 0 + - 0 + - 0 + - 0 + ak_hap_base_benefit: + - 0 + - 0 + - 1750 + - 1750 + ak_hap: + - 0 + - 0 + - 875 + - 875 diff --git a/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap.py b/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap.py index d2688b1a14a..c7d574aa06d 100644 --- a/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap.py +++ b/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap.py @@ -40,8 +40,11 @@ def formula(spm_unit, period, parameters): # its zero default cannot establish absence. Housing step-down # exceptions are unobserved, as are the base formula's tribal, # residency and unresolved geography limitations. + subsidized = spm_unit( + "receives_housing_assistance", period + ) | spm_unit.household("is_in_public_housing", period) utility_adjustment = ( - spm_unit("receives_housing_assistance", period) + subsidized & ~spm_unit("heat_expense_included_in_rent", period) & (spm_unit.household("hud_utility_allowance", period) > 0) ) diff --git a/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_base_benefit.py b/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_base_benefit.py index f290a8c0f24..ddfb58c99b4 100644 --- a/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_base_benefit.py +++ b/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_base_benefit.py @@ -10,6 +10,7 @@ class ak_hap_base_benefit(Variable): reference = ( "http://dpaweb.hss.state.ak.us/manuals/HAP/3004/3004-5_grant_computation.htm", "http://dpaweb.hss.state.ak.us/manuals/HAP/3002/3002-1_households.htm", + "http://dpaweb.hss.state.ak.us/manuals/HAP/3007/3007-1_subsidized_heat_and_application_processing.htm", "http://dpaweb.hss.state.ak.us/manuals/HAP/addendum/addendum_a.htm", "https://www.akleg.gov/basis/aac.asp?media=print&secStart=7.44.010&secEnd=7.44.9001", "https://cchrc.org/wp-content/uploads/media/Consumer_Guide_Home_Heating.pdf#page=23", @@ -75,7 +76,9 @@ def formula(spm_unit, period, parameters): points = community_points * p.dwelling_factor[dwelling] * factor points = points + vulnerable * p.vulnerability_points heat_in_rent = spm_unit("heat_expense_included_in_rent", period) - subsidized = spm_unit("receives_housing_assistance", period) + subsidized = spm_unit( + "receives_housing_assistance", period + ) | spm_unit.household("is_in_public_housing", period) # Full annual rent satisfies the expense test for nonsubsidized # heat-in-rent households. Pre-subsidy rent avoids benefit feedback. expense = where( From 26c236d89bb5a72226b8fb91ef3aa5917b78ce6b Mon Sep 17 00:00:00 2001 From: Ziming Date: Wed, 21 Oct 2026 01:15:46 -0400 Subject: [PATCH 09/16] Consolidate Alaska LIHEAP changelog and registry note One added changelog fragment for the new program and a one- or two-sentence programs.yaml note; limitations stay in code comments and the PR body. Co-Authored-By: Claude Opus 5.5 --- changelog.d/ak-hap-final-award.added.md | 1 - changelog.d/ak-liheap-base-benefit.added.md | 1 - changelog.d/ak-liheap-current-income.fixed.md | 1 - changelog.d/ak-liheap-purchased-fuel.added.md | 1 - changelog.d/ak-liheap-wave2b.added.md | 2 +- policyengine_us/programs.yaml | 2 +- 6 files changed, 2 insertions(+), 6 deletions(-) delete mode 100644 changelog.d/ak-hap-final-award.added.md delete mode 100644 changelog.d/ak-liheap-base-benefit.added.md delete mode 100644 changelog.d/ak-liheap-current-income.fixed.md delete mode 100644 changelog.d/ak-liheap-purchased-fuel.added.md diff --git a/changelog.d/ak-hap-final-award.added.md b/changelog.d/ak-hap-final-award.added.md deleted file mode 100644 index bded5006759..00000000000 --- a/changelog.d/ak-hap-final-award.added.md +++ /dev/null @@ -1 +0,0 @@ -Add Alaska HAP final regular heating benefits with the operating manual's household-sharing and utility-allowance adjustments, and register the supported FY2027 coverage. diff --git a/changelog.d/ak-liheap-base-benefit.added.md b/changelog.d/ak-liheap-base-benefit.added.md deleted file mode 100644 index d014b943372..00000000000 --- a/changelog.d/ak-liheap-base-benefit.added.md +++ /dev/null @@ -1 +0,0 @@ -Add Alaska HAP income-band and base heating benefit calculations with dwelling and community points, before household-sharing and utility-allowance adjustments. diff --git a/changelog.d/ak-liheap-current-income.fixed.md b/changelog.d/ak-liheap-current-income.fixed.md deleted file mode 100644 index f560659ec7f..00000000000 --- a/changelog.d/ak-liheap-current-income.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Count received TANF, total unemployment compensation and ordinary military retirement in Alaska HAP, preserve published decimal income factors when rounding heating points, and recognize explicit public housing in the heating and utility-allowance rules. diff --git a/changelog.d/ak-liheap-purchased-fuel.added.md b/changelog.d/ak-liheap-purchased-fuel.added.md deleted file mode 100644 index eb4e9320c8f..00000000000 --- a/changelog.d/ak-liheap-purchased-fuel.added.md +++ /dev/null @@ -1 +0,0 @@ -Apply Alaska HAP purchased wood and coal points using existing heating types as a documented default. diff --git a/changelog.d/ak-liheap-wave2b.added.md b/changelog.d/ak-liheap-wave2b.added.md index 77540172394..78619e70b24 100644 --- a/changelog.d/ak-liheap-wave2b.added.md +++ b/changelog.d/ak-liheap-wave2b.added.md @@ -1 +1 @@ -Add Alaska HAP household size, countable income and income ceiling components for the FY2027 regular heating rules. +Add Alaska Heating Assistance Program (ak_hap): FY2027 regular heating benefit from community fuel points, dwelling and income factors up to 150% of the Alaska poverty guideline, with the operating manual's shared-household and utility-allowance adjustments. diff --git a/policyengine_us/programs.yaml b/policyengine_us/programs.yaml index 9a7b1d5c037..16fc083771b 100644 --- a/policyengine_us/programs.yaml +++ b/policyengine_us/programs.yaml @@ -967,7 +967,7 @@ programs: variable: ak_hap parameter_prefix: gov.states.ak.dpa.hap verified_years: "2027" - notes: FY2027 regular heating assistance uses the operating manual's equal eligible-household shares and final-dollar utility-allowance reduction, despite conflicting regulatory text. SPM units approximate economic households; wood and coal default to purchased fuel. Alaska utility allowances must be supplied. Some community mappings, tribal and residency facts, owner/room-renter arrangements and housing step-down exceptions remain unmodeled. Earlier-year results are unverified historical estimates; crisis and equipment assistance are out of scope. + notes: FY2027 regular heating, following the operating manual's shared-household and utility-allowance adjustments where the regulation differs. Crisis, cooling, weatherization and equipment assistance are out of scope. # --- SSA programs --- - id: ssi From fa0c83642fc34d506cc17cb1f58e2e87c708c4b0 Mon Sep 17 00:00:00 2001 From: Ziming Date: Fri, 23 Oct 2026 22:46:00 -0400 Subject: [PATCH 10/16] Address review findings for Alaska LIHEAP Co-Authored-By: Claude Opus 5.5 --- .../gov/states/ak/dpa/hap/fpg_rate.yaml | 13 - .../ak/dpa/hap/income/unearned_sources.yaml | 2 +- policyengine_us/programs.yaml | 2 +- .../gov/states/ak/dpa/hap/ak_hap.yaml | 420 +++--- .../ak/dpa/hap/ak_hap_base_benefit.yaml | 209 +-- .../ak/dpa/hap/ak_hap_household_size.yaml | 8 +- .../ak/dpa/hap/ak_hap_income_factor.yaml | 2 +- .../ak/dpa/hap/ak_hap_income_limit.yaml | 1223 ----------------- .../variables/gov/states/ak/dpa/hap/ak_hap.py | 2 +- .../states/ak/dpa/hap/ak_hap_income_limit.py | 29 - source_conflicts/candidates.yaml | 66 + 11 files changed, 315 insertions(+), 1661 deletions(-) delete mode 100644 policyengine_us/parameters/gov/states/ak/dpa/hap/fpg_rate.yaml delete mode 100644 policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_income_limit.yaml delete mode 100644 policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_income_limit.py diff --git a/policyengine_us/parameters/gov/states/ak/dpa/hap/fpg_rate.yaml b/policyengine_us/parameters/gov/states/ak/dpa/hap/fpg_rate.yaml deleted file mode 100644 index 309ed26afdd..00000000000 --- a/policyengine_us/parameters/gov/states/ak/dpa/hap/fpg_rate.yaml +++ /dev/null @@ -1,13 +0,0 @@ -description: Alaska limits income to this share of federal poverty guidelines for the federal LIHEAP component of its Heating Assistance Program. -values: - 2026-10-01: 1.5 - -metadata: - unit: /1 - period: year - label: Alaska HAP federal LIHEAP income limit FPG rate - reference: - - title: Alaska HAP Manual 3000, Federal LIHEAP and State-funded AAHP Boundaries - href: http://dpaweb.hss.state.ak.us/manuals/HAP/3000/3000_introductions_and_definitions.htm - - title: Alaska HAP Manual Addendum E, FFY2027 Alaska Federal Poverty Income Guidelines - href: http://dpaweb.hss.state.ak.us/manuals/HAP/addendum/addendum_e.htm diff --git a/policyengine_us/parameters/gov/states/ak/dpa/hap/income/unearned_sources.yaml b/policyengine_us/parameters/gov/states/ak/dpa/hap/income/unearned_sources.yaml index fdd8a3508c9..cce95b4972d 100644 --- a/policyengine_us/parameters/gov/states/ak/dpa/hap/income/unearned_sources.yaml +++ b/policyengine_us/parameters/gov/states/ak/dpa/hap/income/unearned_sources.yaml @@ -5,7 +5,7 @@ values: - ssi - ak_ssp - pension_income - - military_retirement_pay + - military_retirement_income - retirement_distributions - railroad_benefits - survivor_benefits diff --git a/policyengine_us/programs.yaml b/policyengine_us/programs.yaml index 16fc083771b..9781de1bf3e 100644 --- a/policyengine_us/programs.yaml +++ b/policyengine_us/programs.yaml @@ -967,7 +967,7 @@ programs: variable: ak_hap parameter_prefix: gov.states.ak.dpa.hap verified_years: "2027" - notes: FY2027 regular heating, following the operating manual's shared-household and utility-allowance adjustments where the regulation differs. Crisis, cooling, weatherization and equipment assistance are out of scope. + notes: FY2027 regular heating under the federal LIHEAP component (not the state-funded AAHP), following the operating manual's shared-household and utility-allowance adjustments where the regulation differs. Crisis, cooling, weatherization and equipment assistance are out of scope. # --- SSA programs --- - id: ssi diff --git a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap.yaml b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap.yaml index 389d5c5df1d..eee717cdadf 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap.yaml @@ -248,7 +248,7 @@ output: ak_hap: [962.50, 962.50, 1_925, 0, 0] -# Grant step8 requires subsidized housing, directly paid heat and a positive +# Grant step 8 requires subsidized housing, directly paid heat and a positive # allowance. Test all Boolean combinations of those supplied facts, plus a # second positive allowance magnitude. Fairbanks zero-income base is 1,750. # Subsidized heat-in-rent cases remain zero through the existing base gate. @@ -443,9 +443,9 @@ ak_hap_base_benefit: [1_750, 1_750, 1_750, 1_750, 1_750, 1_750, 0, 0, 1_750] ak_hap: [1_750, 1_750, 1_750, 1_750, 1_750, 875, 0, 0, 875] -# Juneau oil5 * dwelling1 * income factor0.6 =3 points, at least2; $525. -# Step8 then reduces dollars to262.50. Reducing points first would wrongly -# deny this household for having only1.5 points. +# Juneau oil 5 * dwelling 1 * income factor 0.6 = 3 points, at least 2; +# 3 * 175 = $525. Step 8 then reduces dollars to 262.50. Reducing points +# first would wrongly deny this household for having only 1.5 points. - name: Case 7, a three point Juneau household receives half the dollar award. period: 2027 absolute_error_margin: 0.01 @@ -481,10 +481,11 @@ ak_hap_base_benefit: 525 ak_hap: 262.50 -# Fairbanks studio10 * .15 =1.5 points fails before rounding. The two elderly -# units each add1, reach2.5 points, and round up to3 before conversion to$525. -# The ineligible unit does not enter their two-household denominator; sharing -# gives262.50 each and the subsidized unit is halved again to131.25. +# Fairbanks studio 10 * .15 = 1.5 points fails before rounding. The two +# elderly units each add 1, reach 2.5 points, and round up to 3 before +# conversion to $525. The ineligible unit does not enter their two-household +# denominator; sharing gives 262.50 each and the subsidized unit is halved +# again to 131.25. - name: Case 8, minimum points and half up rounding precede sharing and allowance adjustments. period: 2027 absolute_error_margin: 0.01 @@ -546,9 +547,10 @@ ak_hap_base_benefit: [0, 525, 525] ak_hap: [0, 262.50, 131.25] -# Ambler oil35 * large-mobile-home1.4 =49 points, capped at35, giving$6,125. -# Both eligible resident units get3,062.50; step8 halves only the subsidized -# unit again to1,531.25. Neither benefit is capped at its $300 heating bill. +# Ambler oil 35 * large mobile home 1.4 = 49 points, capped at 35, giving +# $6,125. Both eligible resident units get 3,062.50; step 8 halves only the +# subsidized unit again to 1,531.25. Neither benefit is capped at its $300 +# heating bill. - name: Case 9, the point cap applies before sharing and final dollar reduction. period: 2027 absolute_error_margin: 0.01 @@ -596,327 +598,301 @@ ak_hap_base_benefit: [6_125, 6_125] ak_hap: [3_062.50, 1_531.25] -- name: Primary military retirement excludes its household from eligible heating shares +# Fairbanks oil 10 * two-bedroom house 1. The retiree's $36,000 military +# retirement pay is above the one-person 150% ceiling of 2,493 * 12 = 29,916, +# so factor 0 and base 0; pension and veterans inputs do not count it again. +# Each zero-income neighbor has 10 * 1 * 175 = 1,750. Only the two eligible +# units enter the denominator, so each receives 1,750 / 2 = 875. +- name: Case 10, primary military retirement excludes its household from eligible heating shares. period: 2027 + absolute_error_margin: 0.01 input: people: - retiree: + person1: age: 40 immigration_status: CITIZEN years_in_military: 20 - military_retirement_pay: 36000 - neighbor1: + military_retirement_pay: 36_000 + person2: age: 40 immigration_status: CITIZEN - neighbor2: + person3: age: 40 immigration_status: CITIZEN tax_units: - tax_unit0: - members: - - retiree tax_unit1: - members: - - neighbor1 + members: [person1] tax_unit2: - members: - - neighbor2 + members: [person2] + tax_unit3: + members: [person3] spm_units: - spm_unit0: - members: - - retiree - heating_type: FUEL_OIL - fuel_oil_expense: 3000 spm_unit1: - members: - - neighbor1 + members: [person1] heating_type: FUEL_OIL - fuel_oil_expense: 3000 + fuel_oil_expense: 3_000 spm_unit2: - members: - - neighbor2 + members: [person2] heating_type: FUEL_OIL - fuel_oil_expense: 3000 + fuel_oil_expense: 3_000 + spm_unit3: + members: [person3] + heating_type: FUEL_OIL + fuel_oil_expense: 3_000 households: - home: - members: - - retiree - - neighbor1 - - neighbor2 + household1: + members: [person1, person2, person3] state_code: AK place_fips: '24230' output: - pension_income: - - 0 - - 0 - - 0 - veterans_benefits: - - 0 - - 0 - - 0 - ak_hap_countable_income: - - 36000 - - 0 - - 0 - ak_hap_income_factor: - - 0 - - 1 - - 1 - ak_hap_base_benefit: - - 0 - - 1750 - - 1750 - ak_hap: - - 0 - - 875 - - 875 -- name: Only received ATAP reduces the regular heating award + pension_income: [0, 0, 0] + veterans_benefits: [0, 0, 0] + ak_hap_countable_income: [36_000, 0, 0] + ak_hap_income_factor: [0, 1, 1] + ak_hap_base_benefit: [0, 1_750, 1_750] + ak_hap: [0, 875, 875] + +# Two Fairbanks units of a parent and a 10-year-old child, each with a $3,000 +# oil bill. The unit that does not take up ATAP counts no income: factor 1, +# 10 * 175 = 1,750. The other counts its modeled 9,852 ATAP receipt. The +# two-person guideline floor(27,050 / 12) = 2,254 a month gives a 25% ceiling +# of floor(563.5) * 12 = 6,756 and a 50% ceiling of 1,127 * 12 = 13,524, so +# factor 0.9: 10 * 0.9 = 9 points * 175 = 1,575. +- name: Case 11, only received ATAP reduces the regular heating award. period: 2027 + absolute_error_margin: 0.01 input: people: - parent0: + person1: age: 40 immigration_status: CITIZEN - child0: + person2: age: 10 immigration_status: CITIZEN - parent1: + person3: age: 40 immigration_status: CITIZEN - child1: + person4: age: 10 immigration_status: CITIZEN tax_units: - tax_unit0: - members: &id001 - - parent0 - - child0 tax_unit1: - members: &id002 - - parent1 - - child1 + members: [person1, person2] + tax_unit2: + members: [person3, person4] spm_units: - spm_unit0: - members: *id001 + spm_unit1: + members: [person1, person2] heating_type: FUEL_OIL - fuel_oil_expense: 3000 + fuel_oil_expense: 3_000 takes_up_tanf_if_eligible: false - spm_unit1: - members: *id002 + spm_unit2: + members: [person3, person4] heating_type: FUEL_OIL - fuel_oil_expense: 3000 + fuel_oil_expense: 3_000 takes_up_tanf_if_eligible: true households: - home0: - members: *id001 + household1: + members: [person1, person2] state_code: AK place_fips: '24230' - home1: - members: *id002 + household2: + members: [person3, person4] state_code: AK place_fips: '24230' output: - tanf: - - 0 - - 9852 - ak_hap_countable_income: - - 0 - - 9852 - ak_hap_income_factor: - - 1 - - 0.9 - ak_hap: - - 1750 - - 1575 -- name: Published decimal income factors preserve half-up whole heating points + tanf: [0, 9_852] + ak_hap_countable_income: [0, 9_852] + ak_hap_income_factor: [1, 0.9] + ak_hap: [1_750, 1_575] + +# Juneau oil 5 * two-bedroom house 1. One-person annual ceilings: 50% 9,972, +# 75% 14,952, 100% 19,944, 125% 24,924 and 150% 29,916. Income 12,000 gives +# factor 0.8: 5 * 0.8 = 4 points -> 700. Income 18,000 gives 0.7: 3.5 points +# round half up to 4 -> 700. Income 25,000 gives 0.5: 2.5 points, at least 2, +# round half up to 3 -> 525. +- name: Case 12, published decimal income factors preserve half-up whole heating points. period: 2027 + absolute_error_margin: 0.01 input: people: - person0: - age: 40 - immigration_status: CITIZEN - employment_income: 12000 person1: age: 40 immigration_status: CITIZEN - employment_income: 18000 + employment_income: 12_000 person2: age: 40 immigration_status: CITIZEN - employment_income: 25000 + employment_income: 18_000 + person3: + age: 40 + immigration_status: CITIZEN + employment_income: 25_000 tax_units: - tax_unit0: - members: - - person0 tax_unit1: - members: - - person1 + members: [person1] tax_unit2: - members: - - person2 + members: [person2] + tax_unit3: + members: [person3] spm_units: - spm_unit0: - members: - - person0 - heating_type: FUEL_OIL - fuel_oil_expense: 1000 spm_unit1: - members: - - person1 + members: [person1] heating_type: FUEL_OIL - fuel_oil_expense: 1000 + fuel_oil_expense: 1_000 spm_unit2: - members: - - person2 + members: [person2] heating_type: FUEL_OIL - fuel_oil_expense: 1000 + fuel_oil_expense: 1_000 + spm_unit3: + members: [person3] + heating_type: FUEL_OIL + fuel_oil_expense: 1_000 households: - home0: - members: - - person0 + household1: + members: [person1] state_code: AK place_fips: '36400' - home1: - members: - - person1 + household2: + members: [person2] state_code: AK place_fips: '36400' - home2: - members: - - person2 + household3: + members: [person3] state_code: AK place_fips: '36400' output: - ak_hap_countable_income: - - 12000 - - 18000 - - 25000 - ak_hap_income_factor: - - 0.8 - - 0.7 - - 0.5 - ak_hap_base_benefit: - - 700 - - 700 - - 525 - ak_hap: - - 700 - - 700 - - 525 + ak_hap_countable_income: [12_000, 18_000, 25_000] + ak_hap_income_factor: [0.8, 0.7, 0.5] + ak_hap_base_benefit: [700, 700, 525] + ak_hap: [700, 700, 525] -- name: Explicit public housing controls included heat and reported utility allowance +# Four zero-income Fairbanks public housing units: 10 * 175 = 1,750 when +# eligible. Heat included in subsidized rent is excluded, with or without a +# separate housing assistance flag, so the first two receive 0. The two units +# paying a $3,000 oil bill directly with a $1,200 utility allowance keep the +# 1,750 base, and step 8 halves the dollars to 875. +- name: Case 13, explicit public housing controls included heat and the reported utility allowance. period: 2027 + absolute_error_margin: 0.01 input: people: - person0: - age: 40 - immigration_status: CITIZEN - pre_subsidy_rent: 12000 person1: age: 40 immigration_status: CITIZEN - pre_subsidy_rent: 12000 + pre_subsidy_rent: 12_000 person2: age: 40 immigration_status: CITIZEN - pre_subsidy_rent: 12000 + pre_subsidy_rent: 12_000 person3: age: 40 immigration_status: CITIZEN - pre_subsidy_rent: 12000 + pre_subsidy_rent: 12_000 + person4: + age: 40 + immigration_status: CITIZEN + pre_subsidy_rent: 12_000 tax_units: - tax_unit0: - members: - - person0 tax_unit1: - members: - - person1 + members: [person1] tax_unit2: - members: - - person2 + members: [person2] tax_unit3: - members: - - person3 + members: [person3] + tax_unit4: + members: [person4] spm_units: - spm_unit0: - members: - - person0 + spm_unit1: + members: [person1] heating_type: FUEL_OIL heat_expense_included_in_rent: true - spm_unit1: - members: - - person1 + spm_unit2: + members: [person2] heating_type: FUEL_OIL heat_expense_included_in_rent: true receives_housing_assistance: true - spm_unit2: - members: - - person2 + spm_unit3: + members: [person3] heating_type: FUEL_OIL heat_expense_included_in_rent: false - fuel_oil_expense: 3000 - spm_unit3: - members: - - person3 + fuel_oil_expense: 3_000 + spm_unit4: + members: [person4] heating_type: FUEL_OIL heat_expense_included_in_rent: false receives_housing_assistance: true - fuel_oil_expense: 3000 + fuel_oil_expense: 3_000 households: - home0: - members: - - person0 + household1: + members: [person1] state_code: AK place_fips: '24230' is_in_public_housing: true - home1: - members: - - person1 + household2: + members: [person2] state_code: AK place_fips: '24230' is_in_public_housing: true - home2: - members: - - person2 + household3: + members: [person3] state_code: AK place_fips: '24230' is_in_public_housing: true - hud_utility_allowance: 1200 - home3: - members: - - person3 + hud_utility_allowance: 1_200 + household4: + members: [person4] state_code: AK place_fips: '24230' is_in_public_housing: true - hud_utility_allowance: 1200 + hud_utility_allowance: 1_200 + output: + is_in_public_housing: [true, true, true, true] + receives_housing_assistance: [false, true, false, true] + housing_assistance: [0, 0, 0, 0] + ak_hap_countable_income: [0, 0, 0, 0] + ak_hap_base_benefit: [0, 0, 1_750, 1_750] + ak_hap: [0, 0, 875, 875] + +# Manual 3003-1 B.6.c counts annuities, pensions and retirement benefits, and +# Manual 3003-2 does not exempt a military survivor annuity. An $18,000 +# Survivor Benefit Plan annuity is $1,500 a month. One-person bands use +# floor(19,950 / 12) = 1,662 a month: the 75% ceiling is floor(1,662 * 0.75) +# = 1,246 (14,952 a year) and the 100% ceiling is 1,662 (19,944 a year), so +# factor 0.7. Fairbanks oil 10 * two-bedroom house 1 * 0.7 = 7 points, plus +# 1 point for age 62 = 8 points; 8 * 175 = 1,400. Leaving the annuity out +# would give factor 1 and (10 + 1) * 175 = 1,925. +- name: Case 14, a military survivor annuity counts as unearned income. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 62 + immigration_status: CITIZEN + military_retirement_pay_survivors: 18_000 + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: [person1] + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + fuel_oil_expense: 3_000 + ak_atap: 0 + receives_housing_assistance: false + heat_expense_included_in_rent: false + households: + household1: + members: [person1] + state_code: AK + place_fips: '24230' + hud_utility_allowance: 0 output: - is_in_public_housing: - - true - - true - - true - - true - receives_housing_assistance: - - false - - true - - false - - true - housing_assistance: - - 0 - - 0 - - 0 - - 0 - ak_hap_countable_income: - - 0 - - 0 - - 0 - - 0 - ak_hap_base_benefit: - - 0 - - 0 - - 1750 - - 1750 - ak_hap: - - 0 - - 0 - - 875 - - 875 + military_retirement_income: 18_000 + ak_hap_countable_income: 18_000 + ak_hap_income_factor: 0.7 + heating_expense: 3_000 + ak_hap_base_benefit: 1_400 + ak_hap: 1_400 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_base_benefit.yaml b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_base_benefit.yaml index f82ba7c39f1..2166e80e004 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_base_benefit.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_base_benefit.yaml @@ -7,7 +7,7 @@ # http://dpaweb.hss.state.ak.us/manuals/HAP/3002/3002-1_households.htm # https://www.akleg.gov/basis/aac.asp?media=print&secStart=7.44.010&secEnd=7.44.9001 # Geographic/name and nearest-gas approximations are documented in the research manifest. -# 415 replaces the stale published one-person 25% cell407 under the approved reconciliation. +# 415 replaces the stale published one-person 25% cell 407 under the approved reconciliation. # Fuel, dwelling and location are explicit; no new monetary inputs or sentinel defaults. # GRANT: 10 oil points * 1.4; minimum 2 before half-up whole-point rounding, then $175/point. @@ -1082,7 +1082,7 @@ ak_hap_countable_income: 24_000 ak_hap_income_factor: 0.6 -# Qualified size 2, annual36000/month3000 -> factor .5; 10 * .7 * .5 + 1 = 4.5 -> 5. +# Qualified size 2, annual 36,000 (3,000 a month) -> factor .5; 10 * .7 * .5 + 1 = 4.5 -> 5. - name: Case 35, mixed earnings and vulnerability round four and a half points upward. period: 2027 absolute_error_margin: 0.0001 @@ -1165,7 +1165,7 @@ output: ak_hap_base_benefit: 700 -# Ambler35 oil * 1 * 1 = 35 points; $6125. +# Ambler 35 oil * 1 * 1 = 35 points; $6,125. - name: Case 37, Ambler exactly thirty-five points reaches cap. period: 2027 absolute_error_margin: 0.01 @@ -1195,7 +1195,7 @@ output: ak_hap_base_benefit: 6_125 -# Ambler35 * 1.4 + 1 = 50 points, capped35 * $175. +# Ambler 35 * 1.4 + 1 = 50 points, capped 35 * $175. - name: Case 38, points above thirty-five are capped after vulnerability. period: 2027 absolute_error_margin: 0.01 @@ -1255,7 +1255,7 @@ output: ak_hap_base_benefit: 0 -# HH expense200.01 passes; Ambler35 * $175 = 6125 with no actual-expense cap. +# HH expense 200.01 passes; Ambler 35 * $175 = 6,125 with no actual-expense cap. - name: Case 40, expense just above two hundred is not an award cap. period: 2027 absolute_error_margin: 0.01 @@ -1285,7 +1285,7 @@ output: ak_hap_base_benefit: 6_125 -# Primary NATURAL_GAS bill0; secondary oil10000 cannot satisfy the primary-heating expense gate. +# Primary NATURAL_GAS bill 0; secondary oil 10,000 cannot satisfy the primary-heating expense gate. - name: Case 41, zero primary expense fails despite other fuel bills. period: 2027 absolute_error_margin: 0.01 @@ -1316,8 +1316,8 @@ output: ak_hap_base_benefit: 0 -# One qualified adult; annual payroll 24924, no general earned disregard. Apply source band to Fairbanks10 oil points. -- name: Case 42, integrated wages at exact125percent use the inclusive income boundary. +# One qualified adult; annual payroll 24924, no general earned disregard. Apply source band to Fairbanks 10 oil points. +- name: Case 42, integrated wages at exact 125 percent use the inclusive income boundary. period: 2027 absolute_error_margin: 0.01 input: @@ -1347,8 +1347,8 @@ output: ak_hap_base_benefit: 1_050 -# One qualified adult; annual payroll 24924.12, no general earned disregard. Apply source band to Fairbanks10 oil points. -- name: Case 43, integrated wages at above125percent use the inclusive income boundary. +# One qualified adult; annual payroll 24924.12, no general earned disregard. Apply source band to Fairbanks 10 oil points. +- name: Case 43, integrated wages at above 125 percent use the inclusive income boundary. period: 2027 absolute_error_margin: 0.01 input: @@ -1378,8 +1378,8 @@ output: ak_hap_base_benefit: 875 -# One qualified adult; annual payroll 29916, no general earned disregard. Apply source band to Fairbanks10 oil points. -- name: Case 44, integrated wages at exact150percent use the inclusive income boundary. +# One qualified adult; annual payroll 29916, no general earned disregard. Apply source band to Fairbanks 10 oil points. +- name: Case 44, integrated wages at exact 150 percent use the inclusive income boundary. period: 2027 absolute_error_margin: 0.01 input: @@ -1409,8 +1409,8 @@ output: ak_hap_base_benefit: 875 -# One qualified adult; annual payroll 29916.12, no general earned disregard. Apply source band to Fairbanks10 oil points. -- name: Case 45, integrated wages at above150percent use the inclusive income boundary. +# One qualified adult; annual payroll 29916.12, no general earned disregard. Apply source band to Fairbanks 10 oil points. +- name: Case 45, integrated wages at above 150 percent use the inclusive income boundary. period: 2027 absolute_error_margin: 0.01 input: @@ -1440,8 +1440,8 @@ output: ak_hap_base_benefit: 0 -# One qualified adult; annual payroll 4980, no general earned disregard. Apply source band to Fairbanks10 oil points. -- name: Case 46, integrated wages at reconciled25percent use the inclusive income boundary. +# One qualified adult; annual payroll 4980, no general earned disregard. Apply source band to Fairbanks 10 oil points. +- name: Case 46, integrated wages at reconciled 25 percent use the inclusive income boundary. period: 2027 absolute_error_margin: 0.01 input: @@ -1471,8 +1471,8 @@ output: ak_hap_base_benefit: 1_750 -# One qualified adult; annual payroll 4980.12, no general earned disregard. Apply source band to Fairbanks10 oil points. -- name: Case 47, integrated wages at above25percent use the inclusive income boundary. +# One qualified adult; annual payroll 4980.12, no general earned disregard. Apply source band to Fairbanks 10 oil points. +- name: Case 47, integrated wages at above 25 percent use the inclusive income boundary. period: 2027 absolute_error_margin: 0.01 input: @@ -1502,7 +1502,7 @@ output: ak_hap_base_benefit: 1_575 -# Unchanged income component floors total net receipts at0; income factor1 and Fairbanks10points. +# Unchanged income component floors total net receipts at 0; income factor 1 and Fairbanks 10 points. - name: Case 48, negative current net business income does not inflate benefit. period: 2027 absolute_error_margin: 0.0001 @@ -1535,7 +1535,7 @@ ak_hap_countable_income: 0 ak_hap_income_factor: 1 -# Five qualified members, monthly2900 <=75% ceiling3021; 27 * .8 + 1 = 22.6 -> 23 * $175. +# Five qualified members, monthly 2,900 <= 75% ceiling 3,021; 27 * .8 + 1 = 22.6 -> 23 * $175. - name: Case 49, Savoonga updated five-person band supersedes stale worked label. period: 2027 absolute_error_margin: 0.0001 @@ -1601,7 +1601,7 @@ ak_hap_household_size: 5 ak_hap_income_factor: 0.8 -# HH/VER: annual rent12000 counts for expense gate despite direct fuel bill0. +# HH/VER: annual rent 12,000 counts for expense gate despite direct fuel bill 0. - name: Case 50, rent included heat uses full annual rent for expense gate. period: 2027 absolute_error_margin: 0.01 @@ -1633,7 +1633,7 @@ output: ak_hap_base_benefit: 1_750 -# Full annual rent200 does not exceed200. +# Full annual rent 200 does not exceed 200. - name: Case 51, rent included heat at exact expense threshold fails. period: 2027 absolute_error_margin: 0.01 @@ -1665,7 +1665,7 @@ output: ak_hap_base_benefit: 0 -# Annual rent200.01 passes gate; Fairbanks points amount remains1750. +# Annual rent 200.01 passes gate; Fairbanks points amount remains 1,750. - name: Case 52, rent included heat above expense threshold is not capped by rent. period: 2027 absolute_error_margin: 0.01 @@ -1729,7 +1729,7 @@ output: ak_hap_base_benefit: 0 -# Juneau5 * .55 * .7 + 1 = 2.925 -> 3 *175; positive allowance affects a later unresolved final adjustment only. +# Juneau 5 * .55 * .7 + 1 = 2.925 -> 3 * 175; positive allowance affects a later unresolved final adjustment only. - name: Case 54, base amount does not apply disputed utility allowance reduction. period: 2027 absolute_error_margin: 0.01 @@ -1821,7 +1821,7 @@ output: ak_hap_base_benefit: 0 -# Akutan */APIA is Native-only; absent enrollment facts do not exclude. Oil11 *175. +# Akutan */APIA is Native-only; absent enrollment facts do not exclude. Oil 11 * 175. - name: Case 57, Native-only routing does not infer tribal eligibility. period: 2027 absolute_error_margin: 0.01 @@ -1851,7 +1851,7 @@ output: ak_hap_base_benefit: 1_925 -# Fort Greely0/USA is explicitly excluded from tribal list; on-base residence is unobserved. Oil11 *175 under the ordinary location approximation. +# Fort Greely 0/USA is explicitly excluded from tribal list; on-base residence is unobserved. Oil 11 * 175 under the ordinary location approximation. - name: Case 58, USA marker is not an all-resident tribal provider. period: 2027 absolute_error_margin: 0.01 @@ -1881,7 +1881,7 @@ output: ak_hap_base_benefit: 1_925 -# Tetlin current12oil differs from legacy16, but 0/TCC routing controls this state component. +# Tetlin current 12 oil differs from legacy 16, but 0/TCC routing controls this state component. - name: Case 59, Tetlin is routed to all-resident tribal program. period: 2027 absolute_error_margin: 0.01 @@ -1972,7 +1972,7 @@ output: ak_hap_base_benefit: 0 -# Numeric0 represents unavailable supported oil geography, not statutory ineligibility. +# Numeric 0 represents unavailable supported oil geography, not statutory ineligibility. - name: Case 62, missing place yields an unavailable modeled amount. period: 2027 absolute_error_margin: 0.01 @@ -2002,7 +2002,7 @@ output: ak_hap_base_benefit: 0 -# Numeric0 represents unavailable supported oil geography, not statutory ineligibility. +# Numeric 0 represents unavailable supported oil geography, not statutory ineligibility. - name: Case 63, unmatched place yields an unavailable modeled amount. period: 2027 absolute_error_margin: 0.01 @@ -2032,7 +2032,7 @@ output: ak_hap_base_benefit: 0 -# Numeric0 represents unavailable supported oil geography, not statutory ineligibility. +# Numeric 0 represents unavailable supported oil geography, not statutory ineligibility. - name: Case 64, seven-digit GEOID supplied instead of place yields an unavailable modeled amount. period: 2027 absolute_error_margin: 0.01 @@ -2062,7 +2062,7 @@ output: ak_hap_base_benefit: 0 -# Numeric0 represents unavailable supported oil geography, not statutory ineligibility. +# Numeric 0 represents unavailable supported oil geography, not statutory ineligibility. - name: Case 65, ambiguous Anchorage oil place yields an unavailable modeled amount. period: 2027 absolute_error_margin: 0.01 @@ -2152,7 +2152,7 @@ output: ak_hap_base_benefit: 1_400 -# Numeric0 is missing modeled fuel coverage, not a legal determination that all such households are ineligible. +# Numeric 0 is missing modeled fuel coverage, not a legal determination that all such households are ineligible. - name: Case 68, other without a supported subtype yields an unavailable modeled amount. period: 2027 absolute_error_margin: 0.01 @@ -2182,7 +2182,7 @@ output: ak_hap_base_benefit: 0 -# Numeric0 is missing modeled fuel coverage, not a legal determination that all such households are ineligible. +# Numeric 0 is missing modeled fuel coverage, not a legal determination that all such households are ineligible. - name: Case 69, solar without a supported subtype yields an unavailable modeled amount. period: 2027 absolute_error_margin: 0.01 @@ -2212,7 +2212,7 @@ output: ak_hap_base_benefit: 0 -# Numeric0 is missing modeled fuel coverage, not a legal determination that all such households are ineligible. +# Numeric 0 is missing modeled fuel coverage, not a legal determination that all such households are ineligible. - name: Case 70, unspecified without a supported subtype yields an unavailable modeled amount. period: 2027 absolute_error_margin: 0.01 @@ -2270,7 +2270,7 @@ output: ak_hap_base_benefit: 0 -# Independent SPM calculations before sharing: 10+1=11 ->1925; 10*.6=6 ->1050. Do not divide points or grants by two. +# Independent SPM calculations before sharing: 10 + 1 = 11 -> 1,925; 10 * .6 = 6 -> 1,050. Do not divide points or grants by two. - name: Case 72, two SPM units retain their own unshared base amounts. period: 2027 absolute_error_margin: 0.0001 @@ -2327,7 +2327,7 @@ - 1_925 - 1_050 -# Mixed vector: Anchorage gas5*.4=2 ->350; Ambler35*1.4=49 capped35 ->6125; no qualified member ->0. +# Mixed vector: Anchorage gas 5 * .4 = 2 -> 350; Ambler 35 * 1.4 = 49 capped 35 -> 6,125; no qualified member -> 0. - name: Case 73, distinct SPM units preserve geography fuel and composition gates. period: 2027 absolute_error_margin: 0.0001 @@ -2410,7 +2410,7 @@ - 6_125 - 0 -# Grant steps1-4: Fairbanks oil 10 * .8 + 1 elderly point =9; 9 *175 =1575. This assumes purchased wood, not pellets or self-harvest. +# Grant steps 1-4: Fairbanks oil 10 * .8 + 1 elderly point = 9; 9 * 175 = 1,575. This assumes purchased wood, not pellets or self-harvest. - name: "Case 74, purchased wood receives the single vulnerable-household point." period: 2027 absolute_error_margin: 0.01 @@ -2438,7 +2438,7 @@ output: ak_hap_base_benefit: 1_575 -# Fairbanks 10 * .8 * .15 =1.2 fails the unrounded 2-point minimum; an elderly member adds 1 to reach2.2, rounded2 *175=350. +# Fairbanks 10 * .8 * .15 = 1.2 fails the unrounded 2-point minimum; an elderly member adds 1 to reach 2.2, rounded 2 * 175 = 350. - name: "Case 75, purchased fuel changes whether a studio meets minimum heating points." period: 2027 absolute_error_margin: 0.01 @@ -2484,7 +2484,7 @@ output: ak_hap_base_benefit: [0, 350] -# Annual income20000 lies in the 100-125% band, factor .6. Fairbanks10 * .8 * .4 * .6 =1.92 fails before rounding; adding the elderly point makes2.92 ->3 *175=525. +# Annual income 20,000 lies in the 100-125% band, factor .6. Fairbanks 10 * .8 * .4 * .6 = 1.92 fails before rounding; adding the elderly point makes 2.92 -> 3 * 175 = 525. - name: "Case 76, the purchased factor precedes income reduction and minimum points." period: 2027 absolute_error_margin: 0.01 @@ -2531,7 +2531,7 @@ output: ak_hap_base_benefit: [0, 525] -# Koyuk oil25 (Addendum A; Census place41940); income25000 gives .5. One-bedroom25 * .8 * .55 * .5=5.5 ->6; elderly studio25 * .8 * .15 * .5 +1=2.5 ->3. +# Koyuk oil 25 (Addendum A; Census place 41940); income 25,000 gives .5. One-bedroom 25 * .8 * .55 * .5 = 5.5 -> 6; elderly studio 25 * .8 * .15 * .5 + 1 = 2.5 -> 3. - name: "Case 77, purchased fuel preserves half-up rounding at exact half points." period: 2027 absolute_error_margin: 0.01 @@ -2579,7 +2579,7 @@ output: ak_hap_base_benefit: [1_050, 525] -# Household expense requirement remains strictly above200. Unrelated oil expense cannot replace the wood bill; zero wood expense does not infer self-harvest. +# Household expense requirement remains strictly above 200. Unrelated oil expense cannot replace the wood bill; zero wood expense does not infer self-harvest. - name: "Case 78, purchased wood still requires annual primary heating expense above two hundred dollars." period: 2027 absolute_error_margin: 0.01 @@ -2644,36 +2644,8 @@ output: ak_hap_base_benefit: [0, 0, 1_400] -# Ambler oil35 * .8 * large dwelling1.4 =39.2 points; round39 then cap35 *175=6125. -- name: "Case 79, purchased fuel remains subject to the final heating-point cap." - period: 2027 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - spm_units: - spm_unit1: - members: ["person1"] - heating_type: "WOOD" - ak_hap_dwelling_type: "LARGE_MOBILE_HOME_OR_BOAT" - ak_atap: 0 - receives_housing_assistance: false - wood_expense: 1_000 - households: - household1: - members: ["person1"] - state_code: "AK" - place_fips: "01970" - output: - ak_hap_base_benefit: 6_125 - # Anchorage oil mapping remains ambiguous and an unmatched place is unavailable; selecting wood or coal cannot use gas points instead. -- name: "Case 80, purchased fuel cannot resolve unavailable oil community points." +- name: "Case 79, purchased fuel cannot resolve unavailable oil community points." period: 2027 absolute_error_margin: 0.01 input: @@ -2718,101 +2690,8 @@ output: ak_hap_base_benefit: [0, 0] -# Akiachak0/AVCP routes all residents; an unqualified household and a non-AK household receive no state base component. -- name: "Case 81, purchased fuel preserves tribal routing qualified-person and state gates." - period: 2027 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person2: - age: 40 - immigration_status: "UNDOCUMENTED" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person3: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - spm_units: - spm_unit1: - members: ["person1"] - heating_type: "WOOD" - ak_hap_dwelling_type: "TWO_BEDROOM_HOUSE" - ak_atap: 0 - receives_housing_assistance: false - wood_expense: 1_000 - spm_unit2: - members: ["person2"] - heating_type: "WOOD" - ak_hap_dwelling_type: "TWO_BEDROOM_HOUSE" - ak_atap: 0 - receives_housing_assistance: false - wood_expense: 1_000 - spm_unit3: - members: ["person3"] - heating_type: "WOOD" - ak_hap_dwelling_type: "TWO_BEDROOM_HOUSE" - ak_atap: 0 - receives_housing_assistance: false - wood_expense: 1_000 - households: - household1: - members: ["person1"] - state_code: "AK" - place_fips: "00760" - household2: - members: ["person2"] - state_code: "AK" - place_fips: "24230" - household3: - members: ["person3"] - state_code: "NH" - place_fips: "24230" - output: - ak_hap_base_benefit: [0, 0, 0] - -# An ordinary purchased-coal calculation would yield1400, but subsidized heat in rent is excluded before payment. -- name: "Case 82, purchased coal retains the existing subsidized heat-in-rent exclusion." - period: 2027 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - pre_subsidy_rent: 12_000 - spm_units: - spm_unit1: - members: ["person1"] - heating_type: "COAL" - ak_hap_dwelling_type: "TWO_BEDROOM_HOUSE" - ak_atap: 0 - receives_housing_assistance: true - wood_expense: 1_000 - coal_expense: 1_000 - heat_expense_included_in_rent: true - households: - household1: - members: ["person1"] - state_code: "AK" - place_fips: "24230" - output: - ak_hap_base_benefit: 0 - -# Purchased approximation is fixed for WOOD, independent of reported bill: zero wood bill plus300 annual rent meets the existing heat-in-rent expense gate; base8 *175=1400. -- name: "Case 83, unsubsidized heat in rent supplies the expense gate without inferring fuel procurement." +# Purchased approximation is fixed for WOOD, independent of reported bill: zero wood bill plus 300 annual rent meets the existing heat-in-rent expense gate; base 8 * 175 = 1,400. +- name: "Case 80, unsubsidized heat in rent supplies the expense gate without inferring fuel procurement." period: 2027 absolute_error_margin: 0.01 input: diff --git a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_household_size.yaml b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_household_size.yaml index 7ed25675136..37daee2e572 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_household_size.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_household_size.yaml @@ -224,8 +224,8 @@ output: ak_hap_household_size: 3 -# No final eligibility is asserted. MS 3003-6 E still counts all members' income; contract returns a zero limit for zero qualified size. -- name: "Case 3, an Alaska household without a qualified member has no income ceiling." +# No final eligibility is asserted. MS 3003-6 E still counts all members' income when no member counts toward the household size. +- name: "Case 3, an Alaska household without a qualified member still counts its members' income." period: 2027 absolute_error_margin: 0.01 input: @@ -250,9 +250,8 @@ output: ak_hap_household_size: 0 ak_hap_countable_income: 12_000 - ak_hap_income_limit: 0 -# Shared contract masks all three components to Alaska; MS 3002-1 B requires Alaska residence. +# Shared contract masks both components to Alaska; MS 3002-1 B requires Alaska residence. - name: "Case 4, all supported HAP components are zero outside Alaska." period: 2027 absolute_error_margin: 0.01 @@ -278,4 +277,3 @@ output: ak_hap_household_size: 0 ak_hap_countable_income: 0 - ak_hap_income_limit: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_income_factor.yaml b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_income_factor.yaml index 8a04bb16dec..63eb88405ee 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_income_factor.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_income_factor.yaml @@ -7,7 +7,7 @@ # http://dpaweb.hss.state.ak.us/manuals/HAP/3002/3002-1_households.htm # https://www.akleg.gov/basis/aac.asp?media=print&secStart=7.44.010&secEnd=7.44.9001 # Geographic/name and nearest-gas approximations are documented in the research manifest. -# 415 replaces the stale published one-person 25% cell407 under the approved reconciliation. +# 415 replaces the stale published one-person 25% cell 407 under the approved reconciliation. # Fuel, dwelling and location are explicit; no new monetary inputs or sentinel defaults. # GRANT Step 3: income at or below 25% receives factor 1. diff --git a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_income_limit.yaml b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_income_limit.yaml deleted file mode 100644 index b9955dd64ae..00000000000 --- a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_income_limit.yaml +++ /dev/null @@ -1,1223 +0,0 @@ -# Adopted FY2027 HAP manual; supported income components only. -# These tests do not assert final eligibility, heating points or an award. -# Sources: -# http://dpaweb.hss.state.ak.us/manuals/HAP/addendum/addendum_e.htm -# http://dpaweb.hss.state.ak.us/manuals/HAP/3002/3002-1_households.htm -# Annual receipts approximate the application-month rules; computed benefits are supplied. - -# Addendum E FY2027 150% monthly ceilings, sizes 1–18: 2,493; 3,381; 4,267; 5,155; 6,043; 6,930; 7,818; 8,706; 9,592; 10,480; 11,368; 12,255; 13,143; 14,031; 14,917; 15,805; 16,693; 17,580. Each expected annual amount is this published amount times 12. -- name: "Case 1, all eighteen published FY2027 federal LIHEAP ceilings annualize the literal monthly column." - period: 2027 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person2: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person3: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person4: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person5: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person6: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person7: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person8: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person9: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person10: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person11: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person12: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person13: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person14: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person15: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person16: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person17: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person18: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person19: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person20: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person21: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person22: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person23: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person24: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person25: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person26: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person27: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person28: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person29: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person30: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person31: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person32: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person33: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person34: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person35: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person36: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person37: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person38: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person39: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person40: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person41: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person42: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person43: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person44: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person45: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person46: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person47: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person48: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person49: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person50: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person51: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person52: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person53: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person54: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person55: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person56: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person57: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person58: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person59: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person60: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person61: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person62: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person63: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person64: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person65: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person66: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person67: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person68: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person69: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person70: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person71: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person72: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person73: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person74: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person75: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person76: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person77: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person78: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person79: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person80: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person81: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person82: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person83: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person84: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person85: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person86: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person87: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person88: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person89: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person90: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person91: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person92: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person93: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person94: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person95: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person96: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person97: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person98: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person99: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person100: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person101: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person102: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person103: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person104: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person105: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person106: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person107: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person108: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person109: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person110: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person111: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person112: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person113: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person114: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person115: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person116: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person117: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person118: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person119: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person120: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person121: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person122: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person123: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person124: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person125: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person126: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person127: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person128: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person129: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person130: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person131: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person132: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person133: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person134: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person135: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person136: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person137: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person138: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person139: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person140: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person141: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person142: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person143: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person144: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person145: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person146: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person147: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person148: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person149: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person150: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person151: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person152: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person153: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person154: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person155: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person156: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person157: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person158: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person159: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person160: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person161: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person162: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person163: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person164: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person165: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person166: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person167: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person168: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person169: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person170: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - person171: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - spm_units: - spm_unit1: - members: ["person1"] - heating_type: "NATURAL_GAS" - gas_expense: 1_000 - ak_atap: 0 - spm_unit2: - members: ["person2", "person3"] - heating_type: "NATURAL_GAS" - gas_expense: 1_000 - ak_atap: 0 - spm_unit4: - members: ["person4", "person5", "person6"] - heating_type: "NATURAL_GAS" - gas_expense: 1_000 - ak_atap: 0 - spm_unit7: - members: ["person7", "person8", "person9", "person10"] - heating_type: "NATURAL_GAS" - gas_expense: 1_000 - ak_atap: 0 - spm_unit11: - members: ["person11", "person12", "person13", "person14", "person15"] - heating_type: "NATURAL_GAS" - gas_expense: 1_000 - ak_atap: 0 - spm_unit16: - members: ["person16", "person17", "person18", "person19", "person20", "person21"] - heating_type: "NATURAL_GAS" - gas_expense: 1_000 - ak_atap: 0 - spm_unit22: - members: ["person22", "person23", "person24", "person25", "person26", "person27", "person28"] - heating_type: "NATURAL_GAS" - gas_expense: 1_000 - ak_atap: 0 - spm_unit29: - members: ["person29", "person30", "person31", "person32", "person33", "person34", "person35", "person36"] - heating_type: "NATURAL_GAS" - gas_expense: 1_000 - ak_atap: 0 - spm_unit37: - members: ["person37", "person38", "person39", "person40", "person41", "person42", "person43", "person44", "person45"] - heating_type: "NATURAL_GAS" - gas_expense: 1_000 - ak_atap: 0 - spm_unit46: - members: ["person46", "person47", "person48", "person49", "person50", "person51", "person52", "person53", "person54", "person55"] - heating_type: "NATURAL_GAS" - gas_expense: 1_000 - ak_atap: 0 - spm_unit56: - members: ["person56", "person57", "person58", "person59", "person60", "person61", "person62", "person63", "person64", "person65", "person66"] - heating_type: "NATURAL_GAS" - gas_expense: 1_000 - ak_atap: 0 - spm_unit67: - members: ["person67", "person68", "person69", "person70", "person71", "person72", "person73", "person74", "person75", "person76", "person77", "person78"] - heating_type: "NATURAL_GAS" - gas_expense: 1_000 - ak_atap: 0 - spm_unit79: - members: ["person79", "person80", "person81", "person82", "person83", "person84", "person85", "person86", "person87", "person88", "person89", "person90", "person91"] - heating_type: "NATURAL_GAS" - gas_expense: 1_000 - ak_atap: 0 - spm_unit92: - members: ["person92", "person93", "person94", "person95", "person96", "person97", "person98", "person99", "person100", "person101", "person102", "person103", "person104", "person105"] - heating_type: "NATURAL_GAS" - gas_expense: 1_000 - ak_atap: 0 - spm_unit106: - members: ["person106", "person107", "person108", "person109", "person110", "person111", "person112", "person113", "person114", "person115", "person116", "person117", "person118", "person119", "person120"] - heating_type: "NATURAL_GAS" - gas_expense: 1_000 - ak_atap: 0 - spm_unit121: - members: ["person121", "person122", "person123", "person124", "person125", "person126", "person127", "person128", "person129", "person130", "person131", "person132", "person133", "person134", "person135", "person136"] - heating_type: "NATURAL_GAS" - gas_expense: 1_000 - ak_atap: 0 - spm_unit137: - members: ["person137", "person138", "person139", "person140", "person141", "person142", "person143", "person144", "person145", "person146", "person147", "person148", "person149", "person150", "person151", "person152", "person153"] - heating_type: "NATURAL_GAS" - gas_expense: 1_000 - ak_atap: 0 - spm_unit154: - members: ["person154", "person155", "person156", "person157", "person158", "person159", "person160", "person161", "person162", "person163", "person164", "person165", "person166", "person167", "person168", "person169", "person170", "person171"] - heating_type: "NATURAL_GAS" - gas_expense: 1_000 - ak_atap: 0 - households: - household1: - members: ["person1"] - state_code: "AK" - household2: - members: ["person2", "person3"] - state_code: "AK" - household4: - members: ["person4", "person5", "person6"] - state_code: "AK" - household7: - members: ["person7", "person8", "person9", "person10"] - state_code: "AK" - household11: - members: ["person11", "person12", "person13", "person14", "person15"] - state_code: "AK" - household16: - members: ["person16", "person17", "person18", "person19", "person20", "person21"] - state_code: "AK" - household22: - members: ["person22", "person23", "person24", "person25", "person26", "person27", "person28"] - state_code: "AK" - household29: - members: ["person29", "person30", "person31", "person32", "person33", "person34", "person35", "person36"] - state_code: "AK" - household37: - members: ["person37", "person38", "person39", "person40", "person41", "person42", "person43", "person44", "person45"] - state_code: "AK" - household46: - members: ["person46", "person47", "person48", "person49", "person50", "person51", "person52", "person53", "person54", "person55"] - state_code: "AK" - household56: - members: ["person56", "person57", "person58", "person59", "person60", "person61", "person62", "person63", "person64", "person65", "person66"] - state_code: "AK" - household67: - members: ["person67", "person68", "person69", "person70", "person71", "person72", "person73", "person74", "person75", "person76", "person77", "person78"] - state_code: "AK" - household79: - members: ["person79", "person80", "person81", "person82", "person83", "person84", "person85", "person86", "person87", "person88", "person89", "person90", "person91"] - state_code: "AK" - household92: - members: ["person92", "person93", "person94", "person95", "person96", "person97", "person98", "person99", "person100", "person101", "person102", "person103", "person104", "person105"] - state_code: "AK" - household106: - members: ["person106", "person107", "person108", "person109", "person110", "person111", "person112", "person113", "person114", "person115", "person116", "person117", "person118", "person119", "person120"] - state_code: "AK" - household121: - members: ["person121", "person122", "person123", "person124", "person125", "person126", "person127", "person128", "person129", "person130", "person131", "person132", "person133", "person134", "person135", "person136"] - state_code: "AK" - household137: - members: ["person137", "person138", "person139", "person140", "person141", "person142", "person143", "person144", "person145", "person146", "person147", "person148", "person149", "person150", "person151", "person152", "person153"] - state_code: "AK" - household154: - members: ["person154", "person155", "person156", "person157", "person158", "person159", "person160", "person161", "person162", "person163", "person164", "person165", "person166", "person167", "person168", "person169", "person170", "person171"] - state_code: "AK" - output: - ak_hap_household_size: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18] - ak_hap_income_limit: [29_916, 40_572, 51_204, 61_860, 72_516, 83_160, 93_816, 104_472, 115_104, 125_760, 136_416, 147_060, 157_716, 168_372, 179_004, 189_660, 200_316, 210_960] - -# MS 3002-1 A.10 and 3003-6 E include both incomes but one qualified member. Addendum E size 1: 2,493 x 12. -- name: "Case 2, mixed status uses the qualified size for the federal ceiling." - period: 2027 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 40 - immigration_status: "CITIZEN" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - employment_income: 12_000 - person2: - age: 40 - immigration_status: "UNDOCUMENTED" - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - employment_income: 12_000 - spm_units: - spm_unit1: - members: ["person1", "person2"] - heating_type: "NATURAL_GAS" - gas_expense: 1_000 - ak_atap: 0 - households: - household1: - members: ["person1", "person2"] - state_code: "AK" - output: - ak_hap_household_size: 1 - ak_hap_countable_income: 24_000 - ak_hap_income_limit: 29_916 diff --git a/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap.py b/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap.py index c7d574aa06d..e8efb762f2b 100644 --- a/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap.py +++ b/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap.py @@ -6,7 +6,7 @@ class ak_hap(Variable): entity = SPMUnit definition_period = YEAR unit = USD - label = "Alaska Heating Assistance Program benefit" + label = "Alaska Heating Assistance Program federal LIHEAP component benefit" reference = ( "http://dpaweb.hss.state.ak.us/manuals/HAP/3002/3002-1_households.htm", "http://dpaweb.hss.state.ak.us/manuals/HAP/3004/3004-5_grant_computation.htm", diff --git a/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_income_limit.py b/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_income_limit.py deleted file mode 100644 index 5942ddcd7ed..00000000000 --- a/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_income_limit.py +++ /dev/null @@ -1,29 +0,0 @@ -from policyengine_us.model_api import * -from policyengine_us.variables.gov.hhs.tax_unit_fpg import fpg - - -class ak_hap_income_limit(Variable): - value_type = float - entity = SPMUnit - definition_period = YEAR - unit = USD - label = "Alaska HAP federal LIHEAP income limit" - reference = ( - "http://dpaweb.hss.state.ak.us/manuals/HAP/3000/3000_introductions_and_definitions.htm", - "http://dpaweb.hss.state.ak.us/manuals/HAP/addendum/addendum_e.htm", - ) - defined_for = StateCode.AK - - def formula(spm_unit, period, parameters): - p = parameters(period).gov.states.ak.dpa.hap - size = spm_unit("ak_hap_household_size", period) - state_group = spm_unit.household("state_group_str", period) - guideline = fpg(size, state_group, period, parameters, year_lag=p.fpg_year_lag) - # Numerical reconciliation of all 18 FY2027 published 150% ceilings: - # floor the monthly FPG, apply the rate, then floor the monthly limit. - # The source requires downward rounding but does not state this order. - monthly_limit = np.floor(np.floor(guideline / MONTHS_IN_YEAR) * p.fpg_rate) - # Return the annual equivalent of the published monthly ceiling. - # Beyond published sizes, retain the federal additional-person rule; - # state rounding there and backfilled historical years are unverified. - return where(size > 0, monthly_limit * MONTHS_IN_YEAR, 0) diff --git a/source_conflicts/candidates.yaml b/source_conflicts/candidates.yaml index 7d8c41658c6..1abac1eb59d 100644 --- a/source_conflicts/candidates.yaml +++ b/source_conflicts/candidates.yaml @@ -11,6 +11,72 @@ # unreviewed. version: 1 candidates: +- id: us-ak:hap-shared-household-allocation + program: liheap + years: + from: 2027 + to: 2027 + type: federal-fiscal + question: Does Alaska split a shared dwelling's heating award equally among its eligible households or by each + household's actual share of the heating cost? + sources: + - kind: regulation + citation: 7 AAC 44.035(c) and 44.080(h) + url: https://www.akleg.gov/basis/aac.asp?media=print&secStart=7.44.010&secEnd=7.44.9001 + - kind: manual + citation: Alaska HAP Manual 3002-1 A.3 and A.5, Multiple Households Residing in the Same Dwelling and Housing + Percent Share + url: null + readings: + statute: No statute is supplied; 7 AAC 44.035(c) pays each household the percentage of its sole-household award + equal to the percentage of the dwelling's heating cost it actually pays, and 44.080(h) reduces its points to + that proportionate share. + other: The manual divides each award by the number of eligible households in the dwelling, never pays a sharer + more than 50% and disregards what each household contributes to heat or rent. + example: Two eligible Fairbanks households paying 25% and 75% of the heating bills, with sole-household awards of + $1,925 and $1,050, receive $962.50 and $525 in the PR; 7 AAC 44.035(c) would pay $481.25 and $787.50. + pe_us: + follows: conflicting-source + code: [] + prs: + - https://github.com/PolicyEngine/policyengine-us/pull/10341 + state: unreviewed + note: 'Same id as the entry proposed in draft rulespec-us PR 1846; delete this candidate when that entry registers. + The manual is served only over http, at http://dpaweb.hss.state.ak.us/manuals/HAP/3002/3002-1_households.htm. + Code not yet on main: ak_hap, gov.states.ak.dpa.hap.benefit.maximum_shared_household_share.' +- id: us-ak:hap-utility-allowance-order + program: liheap + years: + from: 2027 + to: 2027 + type: federal-fiscal + question: Does Alaska's 50% subsidized-housing utility-allowance reduction apply to heating points before the + 2.0-point minimum and rounding, or to the rounded dollar award? + sources: + - kind: regulation + citation: 7 AAC 44.080(l)-(n) + url: https://www.akleg.gov/basis/aac.asp?media=print&secStart=7.44.010&secEnd=7.44.9001 + - kind: manual + citation: Alaska HAP Manual 3004-5, Grant Computation, Step 8 + url: null + readings: + statute: No statute is supplied; the regulation halves the heating cost points before the 2.0-point minimum and + the rounding to whole points. + other: The manual applies the 2.0-point minimum, rounding, the 35-point cap and the benefit rate first, then + halves the dollar award. + example: A one-person Juneau household with 3.0 points, direct oil bills and a utility allowance receives $262.50 + ($525 halved) in the PR; under 7 AAC 44.080(l)-(m) its points halve to 1.5, below the 2.0 minimum, so it + receives $0. + pe_us: + follows: conflicting-source + code: [] + prs: + - https://github.com/PolicyEngine/policyengine-us/pull/10341 + state: unreviewed + note: 'Draft rulespec-us PR 1846 covers only the shared-household allocation; register this order separately or + extend that entry. The manual is served only over http, at + http://dpaweb.hss.state.ak.us/manuals/HAP/3004/3004-5_grant_computation.htm. Code not yet on main: ak_hap, + gov.states.ak.dpa.hap.benefit.utility_allowance_reduction.' - id: us-ak:snap-abawd-implementation-date program: snap years: From 6fb9eadb46d4e72ca6a90697dbd04e11b382c4a6 Mon Sep 17 00:00:00 2001 From: Ziming Date: Fri, 23 Oct 2026 22:46:59 -0400 Subject: [PATCH 11/16] Sum Alaska LIHEAP income without built-in sum Co-Authored-By: Claude Opus 5.5 --- .../gov/states/ak/dpa/hap/ak_hap_countable_income.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_countable_income.py b/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_countable_income.py index 4f2a569eb44..4c1915ccde0 100644 --- a/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_countable_income.py +++ b/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_countable_income.py @@ -43,9 +43,10 @@ def formula(spm_unit, period, parameters): countable_earned = spm_unit.sum(where(exempt_child, 0, earned)) # These are cash receipts, so a tax loss in an unearned source does not # offset other income. Net rental sources are separately nonnegative. - unearned = spm_unit.sum( - sum(max_(person(source, period), 0) for source in p.unearned_sources) - ) + unearned_person = 0 + for source in p.unearned_sources: + unearned_person = unearned_person + max_(person(source, period), 0) + unearned = spm_unit.sum(unearned_person) rental = spm_unit.sum( max_(person("rental_income", period), 0) + max_(person("farm_rent_income", period), 0) From 6d826ceb31d2c6f0b76619838c625847846d3223 Mon Sep 17 00:00:00 2001 From: Ziming Date: Fri, 23 Oct 2026 23:21:32 -0400 Subject: [PATCH 12/16] Floor each Alaska HAP business income source at zero Co-Authored-By: Claude Opus 5.5 --- .../ak/dpa/hap/income/business_sources.yaml | 3 ++- .../states/ak/dpa/hap/ak_hap_base_benefit.yaml | 2 +- .../ak/dpa/hap/ak_hap_countable_income.yaml | 16 ++++++++-------- .../states/ak/dpa/hap/ak_hap_countable_income.py | 16 +++++++++------- 4 files changed, 20 insertions(+), 17 deletions(-) diff --git a/policyengine_us/parameters/gov/states/ak/dpa/hap/income/business_sources.yaml b/policyengine_us/parameters/gov/states/ak/dpa/hap/income/business_sources.yaml index c3df298a23d..bd08906fca2 100644 --- a/policyengine_us/parameters/gov/states/ak/dpa/hap/income/business_sources.yaml +++ b/policyengine_us/parameters/gov/states/ak/dpa/hap/income/business_sources.yaml @@ -6,7 +6,8 @@ values: - farm_operations_income - partnership_s_corp_income -# Existing signed net sources stand in for gross less allowable current costs. +# Existing net sources, each floored at zero, stand in for gross less +# allowable current costs. # No second 50% standard expense deduction is applied. Partnership/S-corporation # aggregate includes its components, which must not also be added separately. metadata: diff --git a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_base_benefit.yaml b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_base_benefit.yaml index 2166e80e004..347bf576afb 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_base_benefit.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_base_benefit.yaml @@ -1502,7 +1502,7 @@ output: ak_hap_base_benefit: 1_575 -# Unchanged income component floors total net receipts at 0; income factor 1 and Fairbanks 10 points. +# The business loss is floored at zero, so countable income is 0; income factor 1 and Fairbanks 10 points. - name: Case 48, negative current net business income does not inflate benefit. period: 2027 absolute_error_margin: 0.0001 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_countable_income.yaml index 327ed262a84..211f860bc71 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_countable_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_countable_income.yaml @@ -59,8 +59,8 @@ output: ak_hap_countable_income: 6_000 -# MS 3003-4 A.7 and supplied-net approximation: 12,000 - 3,000 = 9,000. Prior-period losses and disallowed expenses cannot be reconstructed. -- name: "Case 3, a signed current net business loss can offset other current income." +# MS 3003-4 A.7 and supplied-net approximation: each source is floored at zero, so 12,000 + 0 = 12,000. Prior-period losses and disallowed expenses cannot be reconstructed. +- name: "Case 3, a current net business loss does not offset other income." period: 2027 absolute_error_margin: 0.01 input: @@ -84,9 +84,9 @@ members: ["person1"] state_code: "AK" output: - ak_hap_countable_income: 9_000 + ak_hap_countable_income: 12_000 -# MS 3003-4 A.7 and D.2: 2,000 - 600 + 800 + 600 + 400 = 3,200. Use canonical partnership and S-corporation components. +# MS 3003-4 A.7 and D.2: 2,000 + 0 (the 600 SSTB loss is floored) + 800 + (600 + 400) = 3,800. Use canonical partnership and S-corporation components. - name: "Case 4, separate supplied business sources count once without another expense deduction." period: 2027 absolute_error_margin: 0.01 @@ -114,7 +114,7 @@ members: ["person1"] state_code: "AK" output: - ak_hap_countable_income: 3_200 + ak_hap_countable_income: 3_800 # MS 3003-1 B.6.f and contract nonnegative rental streams: 10,000 + 0 + 600. - name: "Case 5, negative rental income does not offset positive farm rental income." @@ -171,8 +171,8 @@ output: ak_hap_countable_income: 1_000 -# Contract final household floor after the signed supplied-net approximation. -- name: "Case 7, final household income cannot become negative." +# Each source is floored at zero: 100 + 0 = 100. +- name: "Case 7, a business loss larger than wages leaves the wages counted." period: 2027 absolute_error_margin: 0.01 input: @@ -196,7 +196,7 @@ members: ["person1"] state_code: "AK" output: - ak_hap_countable_income: 0 + ak_hap_countable_income: 100 # MS 3003-6 E includes otherwise countable income of ineligible aliens without proration. - name: "Case 8, all members income counts in a mixed-status household." diff --git a/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_countable_income.py b/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_countable_income.py index 4c1915ccde0..ed5a210f36b 100644 --- a/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_countable_income.py +++ b/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_countable_income.py @@ -32,14 +32,16 @@ def formula(spm_unit, period, parameters): & person("is_tax_unit_dependent", period) & school ) - # Supplied signed net business income approximates gross receipts less + # Supplied net business income approximates gross receipts less # allowable current costs. Do not deduct the 50% expense standard again. - # Prior-period losses, disallowed tax expenses and multiple businesses - # within a source cannot be separated. Partnership/S-corp metadata is - # broader than policy net income; no expense reconstruction is imputed. - earned = max_(person("employment_income", period), 0) + add( - person, period, p.business_sources - ) + # Each source is floored at zero, so a business loss does not offset + # wages or other income. Prior-period losses, disallowed tax expenses + # and multiple businesses within a source cannot be separated. + # Partnership/S-corp metadata is broader than policy net income; no + # expense reconstruction is imputed. + earned = max_(person("employment_income", period), 0) + for source in p.business_sources: + earned = earned + max_(person(source, period), 0) countable_earned = spm_unit.sum(where(exempt_child, 0, earned)) # These are cash receipts, so a tax loss in an unearned source does not # offset other income. Net rental sources are separately nonnegative. From 4d4c959bc74412f0151fe2e43622961ccd86575c Mon Sep 17 00:00:00 2001 From: Ziming Date: Tue, 27 Oct 2026 15:56:50 -0400 Subject: [PATCH 13/16] Address review of Alaska LIHEAP Co-Authored-By: Claude Opus 5.5 --- changelog.d/ak-liheap-wave2b.added.md | 2 +- .../dpa/hap/benefit/community_points/oil.yaml | 199 ++++++- .../maximum_shared_household_share.yaml | 22 +- .../purchased_wood_coal_multiplier.yaml | 8 +- .../hap/benefit/tribal_service_places.yaml | 8 +- .../benefit/utility_allowance_reduction.yaml | 16 +- .../ak/dpa/hap/income/business_sources.yaml | 19 - .../ak/dpa/hap/income/earned_sources.yaml | 28 + .../hap/income/gift_exemption_threshold.yaml | 8 +- .../ak/dpa/hap/income/unearned_sources.yaml | 4 +- policyengine_us/programs.yaml | 2 +- .../gov/states/ak/dpa/hap/ak_hap.yaml | 535 ++++++++++-------- .../ak/dpa/hap/ak_hap_base_benefit.yaml | 222 ++++++-- .../ak/dpa/hap/ak_hap_countable_income.yaml | 40 +- .../ak/dpa/hap/ak_hap_household_size.yaml | 4 +- .../ak/dpa/hap/ak_hap_income_factor.yaml | 24 +- .../variables/gov/states/ak/dpa/hap/ak_hap.py | 49 +- .../states/ak/dpa/hap/ak_hap_base_benefit.py | 186 +++--- .../ak/dpa/hap/ak_hap_countable_income.py | 30 +- source_conflicts/candidates.yaml | 227 +++++++- 20 files changed, 1129 insertions(+), 504 deletions(-) delete mode 100644 policyengine_us/parameters/gov/states/ak/dpa/hap/income/business_sources.yaml create mode 100644 policyengine_us/parameters/gov/states/ak/dpa/hap/income/earned_sources.yaml diff --git a/changelog.d/ak-liheap-wave2b.added.md b/changelog.d/ak-liheap-wave2b.added.md index 78619e70b24..ae0e1193470 100644 --- a/changelog.d/ak-liheap-wave2b.added.md +++ b/changelog.d/ak-liheap-wave2b.added.md @@ -1 +1 @@ -Add Alaska Heating Assistance Program (ak_hap): FY2027 regular heating benefit from community fuel points, dwelling and income factors up to 150% of the Alaska poverty guideline, with the operating manual's shared-household and utility-allowance adjustments. +Add Alaska Heating Assistance Program (ak_hap): FY2027 regular heating benefit from community fuel points, dwelling and income factors up to 150% of the Alaska poverty guideline, with shared-dwelling and utility-allowance reductions applied to heating points under 7 AAC 44.080. diff --git a/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/community_points/oil.yaml b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/community_points/oil.yaml index b6c25981991..704c671c9e1 100644 --- a/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/community_points/oil.yaml +++ b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/community_points/oil.yaml @@ -1,7 +1,15 @@ description: Alaska assigns these oil heating points by Census place under the Heating Assistance Program. -# Derived Census place crosswalk; unknown or ambiguous places are absent. -# Anchorage oil is ambiguous. FY2027 Loring 4 / Tetlin 12 disagree with -# the older regulatory Appendix values 5 / 16; use this annual manual. +# Derived place crosswalk: 279 direct Addendum A matches and 76 nearest-community +# approximations. Direct matches include spelling variants such as Adak +# (Station), Chenega Bay, Kalskag (lower/upper), Eilson AFB, Harding Lake and +# Saint for St., and give the Anchorage municipality the Anchorage value of 8 +# (Chugiak, listed at 7, lies inside it). Every other place takes the points of +# the nearest listed oil community by great-circle distance between Census +# internal points. This is not a state-issued crosswalk. FY2027 Addendum A lists +# Loring at 4 and Tetlin at 12; the 7 AAC 44.080(a) Appendix A lists 5 and 16. +# This table uses the FY2027 Addendum A values. +"00065": # Adak city + 2026-10-01: 6 "00650": # Akhiok city 2026-10-01: 8 "00760": # Akiachak CDP @@ -14,14 +22,20 @@ description: Alaska assigns these oil heating points by Census place under the H 2026-10-01: 21 "01305": # Alatna CDP 2026-10-01: 27 +"01390": # Alcan Border CDP + 2026-10-01: 12 "01420": # Aleknagik city 2026-10-01: 13 +"01560": # Aleneva CDP + 2026-10-01: 8 "01860": # Allakaket city 2026-10-01: 27 "01970": # Ambler city 2026-10-01: 35 "02080": # Anaktuvuk Pass city 2026-10-01: 16 +"03000": # Anchorage municipality + 2026-10-01: 8 "03110": # Anchor Point CDP 2026-10-01: 6 "03220": # Anderson city @@ -40,6 +54,12 @@ description: Alaska assigns these oil heating points by Census place under the H 2026-10-01: 19 "04500": # Atqasuk city 2026-10-01: 24 +"04670": # Attu Station CDP + 2026-10-01: 6 +"05000": # Badger CDP + 2026-10-01: 11 +"05585": # Bear Creek CDP + 2026-10-01: 6 "05750": # Beaver CDP 2026-10-01: 24 "06245": # Beluga CDP @@ -48,6 +68,8 @@ description: Alaska assigns these oil heating points by Census place under the H 2026-10-01: 16 "06630": # Bettles city 2026-10-01: 29 +"06850": # Big Delta CDP + 2026-10-01: 11 "07070": # Big Lake CDP 2026-10-01: 7 "07620": # Birch Creek CDP @@ -56,6 +78,10 @@ description: Alaska assigns these oil heating points by Census place under the H 2026-10-01: 23 "09600": # Buckland city 2026-10-01: 33 +"09657": # Buffalo Soapstone CDP + 2026-10-01: 7 +"09710": # Butte CDP + 2026-10-01: 7 "10150": # Cantwell CDP 2026-10-01: 11 "11690": # Central CDP @@ -66,6 +92,10 @@ description: Alaska assigns these oil heating points by Census place under the H 2026-10-01: 8 "12680": # Chefornak city 2026-10-01: 20 +"12920": # Chena Ridge CDP + 2026-10-01: 11 +"12970": # Chenega CDP + 2026-10-01: 8 "13230": # Chevak city 2026-10-01: 25 "13340": # Chickaloon CDP @@ -80,6 +110,8 @@ description: Alaska assigns these oil heating points by Census place under the H 2026-10-01: 9 "13860": # Chiniak CDP 2026-10-01: 6 +"13890": # Chisana CDP + 2026-10-01: 11 "14000": # Chistochina CDP 2026-10-01: 12 "14110": # Chitina CDP @@ -90,8 +122,12 @@ description: Alaska assigns these oil heating points by Census place under the H 2026-10-01: 23 "15320": # Clam Gulch CDP 2026-10-01: 7 +"15430": # Clark's Point city + 2026-10-01: 16 "16360": # Coffman Cove city 2026-10-01: 6 +"16420": # Cohoe CDP + 2026-10-01: 7 "16530": # Cold Bay city 2026-10-01: 11 "16630": # Coldfoot CDP @@ -104,30 +140,48 @@ description: Alaska assigns these oil heating points by Census place under the H 2026-10-01: 11 "17410": # Cordova city 2026-10-01: 7 +"17670": # Covenant Life CDP + 2026-10-01: 8 "17740": # Craig city 2026-10-01: 5 "17850": # Crooked Creek CDP 2026-10-01: 26 +"17960": # Crown Point CDP + 2026-10-01: 6 "18510": # Deering city 2026-10-01: 31 "18620": # Delta Junction city 2026-10-01: 11 +"18675": # Deltana CDP + 2026-10-01: 11 "18805": # Denali Park CDP 2026-10-01: 10 +"18925": # Diamond Ridge CDP + 2026-10-01: 7 "18950": # Dillingham city 2026-10-01: 11 "19060": # Diomede city 2026-10-01: 27 "19720": # Dot Lake CDP 2026-10-01: 12 +"19750": # Dot Lake Village CDP + 2026-10-01: 12 +"20020": # Dry Creek CDP + 2026-10-01: 12 "20380": # Eagle city 2026-10-01: 19 +"20600": # Eagle Village CDP + 2026-10-01: 19 +"20716": # Eareckson Station CDP + 2026-10-01: 6 "20970": # Edna Bay city 2026-10-01: 11 "21040": # Eek city 2026-10-01: 22 "21150": # Egegik city 2026-10-01: 15 +"21370": # Eielson AFB CDP + 2026-10-01: 11 "21810": # Ekwok city 2026-10-01: 14 "22140": # Elfin Cove CDP @@ -138,6 +192,8 @@ description: Alaska assigns these oil heating points by Census place under the H 2026-10-01: 24 "23460": # Ester CDP 2026-10-01: 11 +"23720": # Eureka Roadhouse CDP + 2026-10-01: 8 "23790": # Evansville CDP 2026-10-01: 29 "23900": # Excursion Inlet CDP @@ -146,22 +202,46 @@ description: Alaska assigns these oil heating points by Census place under the H 2026-10-01: 10 "24660": # False Pass city 2026-10-01: 11 +"24980": # Farmers Loop CDP + 2026-10-01: 10 +"25000": # Farm Loop CDP + 2026-10-01: 7 +"25220": # Ferry CDP + 2026-10-01: 10 +"25550": # Fishhook CDP + 2026-10-01: 7 +"25880": # Flat CDP + 2026-10-01: 26 "26100": # Fort Greely CDP 2026-10-01: 11 "26760": # Fort Yukon city 2026-10-01: 23 +"26835": # Four Mile Road CDP + 2026-10-01: 11 "26870": # Fox CDP 2026-10-01: 11 +"26910": # Fox River CDP + 2026-10-01: 7 "27090": # Fritz Creek CDP 2026-10-01: 7 +"27145": # Funny River CDP + 2026-10-01: 9 "27420": # Gakona CDP 2026-10-01: 11 "27530": # Galena city 2026-10-01: 20 "27640": # Gambell city 2026-10-01: 27 +"27700": # Game Creek CDP + 2026-10-01: 7 +"28200": # Gateway CDP + 2026-10-01: 7 +"28590": # Glacier View CDP + 2026-10-01: 8 "28740": # Glennallen CDP 2026-10-01: 11 +"29130": # Goldstream CDP + 2026-10-01: 11 "29180": # Golovin city 2026-10-01: 26 "29290": # Goodnews Bay city @@ -176,10 +256,16 @@ description: Alaska assigns these oil heating points by Census place under the H 2026-10-01: 6 "31270": # Halibut Cove CDP 2026-10-01: 7 +"31710": # Happy Valley CDP + 2026-10-01: 6 +"31765": # Harding-Birch Lakes CDP + 2026-10-01: 11 "32150": # Healy CDP 2026-10-01: 10 "32310": # Healy Lake CDP 2026-10-01: 13 +"32550": # Hobart Bay CDP + 2026-10-01: 6 "32810": # Hollis CDP 2026-10-01: 5 "33030": # Holy Cross city @@ -210,10 +296,14 @@ description: Alaska assigns these oil heating points by Census place under the H 2026-10-01: 12 "36400": # Juneau city and borough 2026-10-01: 5 +"36540": # Kachemak city + 2026-10-01: 7 "36770": # Kake city 2026-10-01: 6 "36990": # Kaktovik city 2026-10-01: 24 +"37250": # Kalifornsky CDP + 2026-10-01: 9 "37430": # Kaltag city 2026-10-01: 22 "37540": # Karluk CDP @@ -226,6 +316,8 @@ description: Alaska assigns these oil heating points by Census place under the H 2026-10-01: 7 "38420": # Kenai city 2026-10-01: 8 +"38910": # Kenny Lake CDP + 2026-10-01: 11 "38970": # Ketchikan city 2026-10-01: 4 "39300": # Kiana city @@ -244,10 +336,14 @@ description: Alaska assigns these oil heating points by Census place under the H 2026-10-01: 8 "40645": # Knik-Fairview CDP 2026-10-01: 7 +"40670": # Knik River CDP + 2026-10-01: 7 "40840": # Kobuk city 2026-10-01: 35 "40950": # Kodiak city 2026-10-01: 6 +"41210": # Kodiak Station CDP + 2026-10-01: 6 "41280": # Kokhanok CDP 2026-10-01: 19 "41500": # Koliganek CDP @@ -262,14 +358,20 @@ description: Alaska assigns these oil heating points by Census place under the H 2026-10-01: 25 "42050": # Koyukuk city 2026-10-01: 20 +"42160": # Kupreanof city + 2026-10-01: 5 "42380": # Kwethluk city 2026-10-01: 20 "42490": # Kwigillingok CDP 2026-10-01: 22 +"42805": # Lake Louise CDP + 2026-10-01: 11 "42820": # Lake Minchumina CDP 2026-10-01: 27 "43040": # Larsen Bay city 2026-10-01: 7 +"43260": # Lazy Mountain CDP + 2026-10-01: 7 "43810": # Levelock CDP 2026-10-01: 12 "44030": # Lime Village CDP @@ -278,6 +380,12 @@ description: Alaska assigns these oil heating points by Census place under the H 2026-10-01: 14 "45020": # Loring CDP 2026-10-01: 4 +"45295": # Lowell Point CDP + 2026-10-01: 6 +"45460": # Lower Kalskag city + 2026-10-01: 23 +"45700": # Lutak CDP + 2026-10-01: 8 "45790": # McCarthy CDP 2026-10-01: 11 "46010": # McGrath city @@ -288,28 +396,47 @@ description: Alaska assigns these oil heating points by Census place under the H 2026-10-01: 16 "47000": # Marshall city 2026-10-01: 25 +"47735": # Meadow Lakes CDP + 2026-10-01: 7 "47990": # Mekoryuk city 2026-10-01: 21 +"48200": # Mendeltna CDP + 2026-10-01: 11 "48540": # Mentasta Lake CDP 2026-10-01: 12 +"48590": # Mertarvik CDP + 2026-10-01: 25 "48870": # Metlakatla CDP 2026-10-01: 6 +"49200": # Mill Bay CDP + 2026-10-01: 6 "49530": # Minto CDP 2026-10-01: 16 "50080": # Moose Creek CDP 2026-10-01: 11 "50190": # Moose Pass CDP 2026-10-01: 6 +"50800": # Mosquito Lake CDP + 2026-10-01: 8 "51180": # Mountain Village city 2026-10-01: 25 +"51455": # Mud Bay CDP + 2026-10-01: 6 +"51960": # Nabesna CDP + 2026-10-01: 12 "52060": # Naknek CDP 2026-10-01: 13 +# Addendum A also lists English Bay, the same village, at 19. "52210": # Nanwalek CDP 2026-10-01: 8 "52390": # Napakiak city 2026-10-01: 11 "52720": # Napaskiak city 2026-10-01: 20 +"52845": # Naukati Bay CDP + 2026-10-01: 6 +"52915": # Nelchina CDP + 2026-10-01: 11 "52940": # Nelson Lagoon CDP 2026-10-01: 8 "53050": # Nenana city @@ -340,6 +467,8 @@ description: Alaska assigns these oil heating points by Census place under the H 2026-10-01: 19 "55140": # Noorvik city 2026-10-01: 26 +"55745": # North Lakes CDP + 2026-10-01: 7 "55910": # North Pole city 2026-10-01: 11 "56220": # Northway CDP @@ -348,6 +477,8 @@ description: Alaska assigns these oil heating points by Census place under the H 2026-10-01: 20 "56350": # Nulato city 2026-10-01: 24 +"56600": # Nunam Iqua city + 2026-10-01: 24 "56680": # Nunapitchuk city 2026-10-01: 19 "57340": # Old Harbor city @@ -368,10 +499,14 @@ description: Alaska assigns these oil heating points by Census place under the H 2026-10-01: 9 "60310": # Petersburg CDP 2026-10-01: 5 +"60460": # Petersville CDP + 2026-10-01: 8 "60640": # Pilot Point city 2026-10-01: 12 "60750": # Pilot Station city 2026-10-01: 25 +"60860": # Pitkas Point CDP + 2026-10-01: 25 "61080": # Platinum city 2026-10-01: 20 "61120": # Pleasant Valley CDP @@ -382,12 +517,20 @@ description: Alaska assigns these oil heating points by Census place under the H 2026-10-01: 23 "61700": # Point Lay CDP 2026-10-01: 18 +"61788": # Point MacKenzie CDP + 2026-10-01: 7 +"61825": # Point Possession CDP + 2026-10-01: 7 +"62125": # Pope-Vannoy Landing CDP + 2026-10-01: 19 "62285": # Portage Creek CDP 2026-10-01: 14 "62510": # Port Alexander city 2026-10-01: 11 "62620": # Port Alsworth CDP 2026-10-01: 19 +"63170": # Port Clarence CDP + 2026-10-01: 23 "63280": # Port Graham CDP 2026-10-01: 8 "63390": # Port Heiden city @@ -396,16 +539,34 @@ description: Alaska assigns these oil heating points by Census place under the H 2026-10-01: 8 "63870": # Port Protection CDP 2026-10-01: 11 +"64240": # Primrose CDP + 2026-10-01: 6 +"64380": # Prudhoe Bay CDP + 2026-10-01: 20 "64600": # Quinhagak city 2026-10-01: 20 "64820": # Rampart CDP 2026-10-01: 20 "64930": # Red Devil CDP 2026-10-01: 26 +"64980": # Red Dog Mine CDP + 2026-10-01: 32 +"65345": # Ridgeway CDP + 2026-10-01: 9 "65590": # Ruby city 2026-10-01: 19 "65700": # Russian Mission city 2026-10-01: 25 +"65800": # St. George city + 2026-10-01: 11 +"66140": # St. Mary's city + 2026-10-01: 25 +"66360": # St. Michael city + 2026-10-01: 23 +"66470": # St. Paul city + 2026-10-01: 11 +"66510": # Salamatof CDP + 2026-10-01: 8 "66550": # Salcha CDP 2026-10-01: 11 "67020": # Sand Point city @@ -420,6 +581,8 @@ description: Alaska assigns these oil heating points by Census place under the H 2026-10-01: 29 "68340": # Seldovia city 2026-10-01: 9 +"68370": # Seldovia Village CDP + 2026-10-01: 9 "68560": # Seward city 2026-10-01: 6 "68670": # Shageluk city @@ -430,6 +593,8 @@ description: Alaska assigns these oil heating points by Census place under the H 2026-10-01: 29 "70100": # Shungnak city 2026-10-01: 35 +"70320": # Silver Springs CDP + 2026-10-01: 11 "70540": # Sitka city and borough 2026-10-01: 6 "70760": # Skagway CDP @@ -442,18 +607,28 @@ description: Alaska assigns these oil heating points by Census place under the H 2026-10-01: 26 "71640": # Soldotna city 2026-10-01: 9 +"72135": # South Lakes CDP + 2026-10-01: 7 "72190": # South Naknek CDP 2026-10-01: 13 +"72230": # South Van Horn CDP + 2026-10-01: 10 "72960": # Stebbins city 2026-10-01: 21 +"72985": # Steele Creek CDP + 2026-10-01: 11 "73070": # Sterling CDP 2026-10-01: 9 "73290": # Stevens Village CDP 2026-10-01: 23 "73400": # Stony River CDP 2026-10-01: 26 +"73950": # Sunrise CDP + 2026-10-01: 7 "74340": # Susitna CDP 2026-10-01: 10 +"74350": # Susitna North CDP + 2026-10-01: 8 "74525": # Sutton-Alpine CDP 2026-10-01: 7 "74610": # Takotna CDP @@ -462,12 +637,18 @@ description: Alaska assigns these oil heating points by Census place under the H 2026-10-01: 8 "75050": # Tanacross CDP 2026-10-01: 12 +"75077": # Tanaina CDP + 2026-10-01: 7 "75160": # Tanana city 2026-10-01: 20 "75380": # Tatitlek CDP 2026-10-01: 11 +"75480": # Tazlina CDP + 2026-10-01: 11 "75930": # Teller city 2026-10-01: 23 +"76260": # Tenakee Springs city + 2026-10-01: 7 "76590": # Tetlin CDP 2026-10-01: 12 "77140": # Thorne Bay city @@ -478,6 +659,8 @@ description: Alaska assigns these oil heating points by Census place under the H 2026-10-01: 12 "78240": # Toksook Bay city 2026-10-01: 21 +"78297": # Tolsona CDP + 2026-10-01: 11 "78350": # Tonsina CDP 2026-10-01: 11 "78680": # Trapper Creek CDP @@ -500,6 +683,8 @@ description: Alaska assigns these oil heating points by Census place under the H 2026-10-01: 21 "80770": # Unalaska city 2026-10-01: 6 +"81320": # Upper Kalskag city + 2026-10-01: 23 "81920": # Utqiaġvik city 2026-10-01: 21 "82200": # Valdez city @@ -516,12 +701,20 @@ description: Alaska assigns these oil heating points by Census place under the H 2026-10-01: 6 "84070": # White Mountain city 2026-10-01: 26 +"84120": # Whitestone CDP + 2026-10-01: 11 +"84200": # Whitestone Logging Camp CDP + 2026-10-01: 7 "84510": # Whittier city 2026-10-01: 8 "85280": # Willow CDP 2026-10-01: 7 +"85290": # Willow Creek CDP + 2026-10-01: 11 "85610": # Wiseman CDP 2026-10-01: 19 +"85680": # Womens Bay CDP + 2026-10-01: 6 "86380": # Wrangell city and borough 2026-10-01: 5 "86490": # Yakutat CDP diff --git a/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/maximum_shared_household_share.yaml b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/maximum_shared_household_share.yaml index b8490da7e9e..1db864cf3f6 100644 --- a/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/maximum_shared_household_share.yaml +++ b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/maximum_shared_household_share.yaml @@ -1,22 +1,18 @@ -description: Alaska limits a household sharing its dwelling to this share of its calculated award under the Heating Assistance Program. -# Approved manual-based convention: section 3002-1 A.3-5 divides each award -# by the number of eligible households, with this maximum share even when -# only one sharing household is eligible. Actual heating payments do not -# determine the share. This conflicts with 7 AAC 44.035(c) actual-cost sharing -# and the earlier points adjustment in 44.080(h) and grant manual step 2. -# This selection does not establish a regulatory amendment or verify -# historical years before FY2027. +description: Alaska limits a household sharing its dwelling to this share of its heating points under the Heating Assistance Program. +# 7 AAC 44.080(h) reduces a sharing household's points to its proportionate +# share of the dwelling's heating expenses. When no household in the dwelling +# reports a heating expense, as with heat included in rent, that share cannot +# be measured, so manual 3002-1 A.5 fills the gap: an equal share for each +# eligible household, at most this share. values: 2026-10-01: 0.5 metadata: unit: /1 period: year - label: Alaska HAP maximum shared household benefit share + label: Alaska HAP maximum shared household share reference: - - title: Alaska HAP Manual 3002-1, Types of Households, A.3-5 + - title: Alaska HAP Manual 3002-1 A.5, Housing Percent Share href: http://dpaweb.hss.state.ak.us/manuals/HAP/3002/3002-1_households.htm - - title: Alaska HAP Manual 3004-5, Grant Computation, Step 2 (conflicting text) - href: http://dpaweb.hss.state.ak.us/manuals/HAP/3004/3004-5_grant_computation.htm - - title: 7 AAC 44.035(c) and 44.080(h) (conflicting text) + - title: 7 AAC 44.080(h) href: https://www.akleg.gov/basis/aac.asp?media=print&secStart=7.44.010&secEnd=7.44.9001 diff --git a/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/purchased_wood_coal_multiplier.yaml b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/purchased_wood_coal_multiplier.yaml index 089fbb9ee66..6b849712500 100644 --- a/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/purchased_wood_coal_multiplier.yaml +++ b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/purchased_wood_coal_multiplier.yaml @@ -1,7 +1,7 @@ description: Alaska applies this share of community oil heating points for purchased wood or coal under the Heating Assistance Program. -# The model uses this purchased-fuel rule as an approved approximation for -# existing WOOD/COAL inputs without procurement or pellet detail. Actual -# self-harvested fuel and wood pellets use different published factors. +# The model applies this purchased-fuel factor to every WOOD or COAL +# household, since heating_type cannot identify self-harvested fuel or wood +# pellets, whose factors differ under 7 AAC 44.080(c) and (e). values: 2026-10-01: 0.8 @@ -10,5 +10,7 @@ metadata: period: year label: Alaska HAP purchased wood or coal point multiplier reference: + - title: 7 AAC 44.080(d) + href: https://www.akleg.gov/basis/aac.asp?media=print&secStart=7.44.010&secEnd=7.44.9001 - title: Alaska HAP Manual 3004-5, Grant Computation, Step 1 href: http://dpaweb.hss.state.ak.us/manuals/HAP/3004/3004-5_grant_computation.htm diff --git a/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/tribal_service_places.yaml b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/tribal_service_places.yaml index 1127549942e..d563059dcc0 100644 --- a/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/tribal_service_places.yaml +++ b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/tribal_service_places.yaml @@ -1,6 +1,10 @@ -description: Alaska routes all residents of these represented Census places to tribal heating assistance providers under the ordinary state Heating Assistance Program rules. +description: Alaska excludes all residents of these tribe-served Census places under the Heating Assistance Program. +# Places whose every Addendum A row is marked 0 (the tribe serves all +# residents), except 0/USA military bases, matched by Census place name. +# Approximated places inherit their nearest community's all-resident tribal +# routing, the same proxy used for their oil points. values: - 2026-10-01: ["00760", "00870", "01200", "01305", "01420", "01860", "03440", "03550", "03880", "03990", "04430", "05750", "06520", "06630", "07620", "11690", "11800", "12680", "13230", "13450", "13550", "13670", "13780", "14330", "14880", "16630", "17740", "18950", "19720", "20380", "21040", "21150", "21810", "22910", "23790", "26760", "27530", "29290", "30060", "32310", "33030", "33360", "33470", "33910", "34350", "34460", "34790", "35120", "35890", "36770", "37430", "37650", "37975", "39630", "39740", "40400", "40510", "41280", "41500", "41610", "41720", "42050", "42380", "42490", "42820", "43810", "44030", "46010", "46780", "46890", "47000", "47990", "48870", "49530", "51180", "52060", "52390", "52720", "53050", "53270", "53710", "53820", "53930", "54150", "55030", "56220", "56350", "56680", "58330", "60640", "60750", "61080", "62285", "63390", "64600", "64820", "64930", "65590", "65700", "67570", "67680", "68670", "71090", "72190", "73290", "74610", "75050", "75160", "76590", "77690", "78240", "78790", "79120", "79230", "79780", "80100", "82420", "85610", "86490"] + 2026-10-01: ["00760", "00870", "01200", "01305", "01390", "01420", "01860", "03440", "03550", "03880", "03990", "04430", "05750", "06520", "06630", "07620", "11690", "11800", "12680", "13230", "13450", "13550", "13670", "13780", "14330", "14880", "15430", "16630", "17670", "17740", "18950", "19720", "19750", "20020", "20380", "20600", "21040", "21150", "21810", "22910", "23790", "26760", "26835", "27530", "27700", "29290", "30060", "32310", "32550", "33030", "33360", "33470", "33910", "34350", "34460", "34790", "35120", "35890", "36770", "37430", "37650", "37975", "39630", "39740", "40400", "40510", "41280", "41500", "41610", "41720", "42050", "42380", "42490", "42820", "43810", "44030", "45460", "45700", "46010", "46780", "46890", "47000", "47990", "48590", "48870", "49530", "50800", "51180", "52060", "52390", "52720", "53050", "53270", "53710", "53820", "53930", "54150", "55030", "56220", "56350", "56600", "56680", "58330", "60640", "60750", "60860", "61080", "62125", "62285", "63390", "64600", "64820", "64930", "65590", "65700", "66140", "67570", "67680", "68670", "71090", "72190", "73290", "74610", "75050", "75160", "76590", "77690", "78240", "78790", "79120", "79230", "79780", "80100", "81320", "82420", "84200", "85610", "86490"] metadata: unit: list diff --git a/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/utility_allowance_reduction.yaml b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/utility_allowance_reduction.yaml index da5a5e209a2..b4f802d8938 100644 --- a/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/utility_allowance_reduction.yaml +++ b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/utility_allowance_reduction.yaml @@ -1,18 +1,16 @@ -description: Alaska reduces the calculated benefit by this share for subsidized households paying heating costs directly and receiving a utility allowance under the Heating Assistance Program. -# Approved manual-based convention: grant manual step 8 applies this -# reduction to the dollar award, regardless of the allowance amount. -# In contrast, 7 AAC 44.080(l)-(n) halves points before the minimum and -# rounding. This selection does not establish a regulatory amendment or -# verify historical years before FY2027. +description: Alaska deducts this share of heating points for subsidized households that pay heating costs directly under the Heating Assistance Program. +# 7 AAC 44.080(l) halves the points determined under (a)-(k), regardless of +# the allowance amount, before the 2.0-point minimum in (m) and the rounding +# in (n). values: 2026-10-01: 0.5 metadata: unit: /1 period: year - label: Alaska HAP utility allowance benefit reduction + label: Alaska HAP utility allowance point reduction reference: + - title: 7 AAC 44.080(l) + href: https://www.akleg.gov/basis/aac.asp?media=print&secStart=7.44.010&secEnd=7.44.9001 - title: Alaska HAP Manual 3004-5, Grant Computation, Step 8 href: http://dpaweb.hss.state.ak.us/manuals/HAP/3004/3004-5_grant_computation.htm - - title: 7 AAC 44.080(l)-(n) (conflicting text) - href: https://www.akleg.gov/basis/aac.asp?media=print&secStart=7.44.010&secEnd=7.44.9001 diff --git a/policyengine_us/parameters/gov/states/ak/dpa/hap/income/business_sources.yaml b/policyengine_us/parameters/gov/states/ak/dpa/hap/income/business_sources.yaml deleted file mode 100644 index bd08906fca2..00000000000 --- a/policyengine_us/parameters/gov/states/ak/dpa/hap/income/business_sources.yaml +++ /dev/null @@ -1,19 +0,0 @@ -description: Alaska includes these supplied net business income sources under the Heating Assistance Program. -values: - 2026-10-01: - - self_employment_income - - sstb_self_employment_income - - farm_operations_income - - partnership_s_corp_income - -# Existing net sources, each floored at zero, stand in for gross less -# allowable current costs. -# No second 50% standard expense deduction is applied. Partnership/S-corporation -# aggregate includes its components, which must not also be added separately. -metadata: - unit: list - period: year - label: Alaska HAP supplied net business income sources - reference: - - title: Alaska HAP Manual 3003-4 A-D, Income From Self-Employment - href: http://dpaweb.hss.state.ak.us/manuals/HAP/3003/3003-4_income_from_self-employment.htm diff --git a/policyengine_us/parameters/gov/states/ak/dpa/hap/income/earned_sources.yaml b/policyengine_us/parameters/gov/states/ak/dpa/hap/income/earned_sources.yaml new file mode 100644 index 00000000000..4a3fa11b785 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ak/dpa/hap/income/earned_sources.yaml @@ -0,0 +1,28 @@ +description: Alaska uses these sources to compute countable earned income under the Heating Assistance Program. +# Military basic pay is its own input, outside employment income, and counts +# once here as earned military pay. Business sources are supplied net amounts, +# each floored at zero; manual 3003-4 B deducts 50% of gross self-employment +# income unless actual costs are higher, so these net inputs overstate +# countable income when actual costs are under half of gross. The +# partnership/S corporation aggregate includes its components, which are not +# added separately. +values: + 2026-10-01: + - employment_income + - military_basic_pay + - self_employment_income + - sstb_self_employment_income + - farm_operations_income + - partnership_s_corp_income + +metadata: + unit: list + period: year + label: Alaska HAP countable earned income sources + reference: + - title: Alaska HAP Manual 3003-1 A.1, Wages + href: http://dpaweb.hss.state.ak.us/manuals/HAP/3003/3003-1_countable_income.htm + - title: Alaska HAP Manual 3003-4 A-D, Income From Self-Employment + href: http://dpaweb.hss.state.ak.us/manuals/HAP/3003/3003-4_income_from_self-employment.htm + - title: Alaska HAP Manual 3003-5 B.1.a, Military Pay, Countable Income + href: http://dpaweb.hss.state.ak.us/manuals/HAP/3003/3003-5_military_pay.htm diff --git a/policyengine_us/parameters/gov/states/ak/dpa/hap/income/gift_exemption_threshold.yaml b/policyengine_us/parameters/gov/states/ak/dpa/hap/income/gift_exemption_threshold.yaml index e8efe76295e..3deea664db5 100644 --- a/policyengine_us/parameters/gov/states/ak/dpa/hap/income/gift_exemption_threshold.yaml +++ b/policyengine_us/parameters/gov/states/ak/dpa/hap/income/gift_exemption_threshold.yaml @@ -1,4 +1,4 @@ -description: Alaska excludes cash gifts strictly below this monthly amount per person under the Heating Assistance Program. +description: Alaska excludes cash gifts at or below this monthly amount per person under the Heating Assistance Program. values: 2026-10-01: 20 @@ -7,5 +7,9 @@ metadata: period: month label: Alaska HAP monthly cash gift exemption threshold reference: - - title: Alaska HAP Manual 3003-2 A(24), Cash Gifts + - title: 7 AAC 44.042(16) + href: https://www.akleg.gov/basis/aac.asp?media=print&secStart=7.44.010&secEnd=7.44.9001 + - title: Alaska HAP Manual 3003-1 B.6.r, Cash Gifts + href: http://dpaweb.hss.state.ak.us/manuals/HAP/3003/3003-1_countable_income.htm + - title: Alaska HAP Manual 3003-2 A.24, Cash Gifts href: http://dpaweb.hss.state.ak.us/manuals/HAP/3003/3003-2_noncountable_(exempt)_income.htm diff --git a/policyengine_us/parameters/gov/states/ak/dpa/hap/income/unearned_sources.yaml b/policyengine_us/parameters/gov/states/ak/dpa/hap/income/unearned_sources.yaml index cce95b4972d..42b3320e48a 100644 --- a/policyengine_us/parameters/gov/states/ak/dpa/hap/income/unearned_sources.yaml +++ b/policyengine_us/parameters/gov/states/ak/dpa/hap/income/unearned_sources.yaml @@ -33,8 +33,8 @@ values: # Education grants, royalties, foster/adoption receipts, excess reimbursements # and cash utility reimbursements lack the detail required by the manual. # A HUD utility allowance alone does not establish a cash reimbursement. -# Military wages must be reported once in employment income; its separate tax -# subset inputs are not added. Combat/work-study/MASST exceptions are unobserved. +# Military basic pay is its own input and counts once, as earned income. +# Combat/work-study/MASST exceptions are unobserved. metadata: unit: list period: year diff --git a/policyengine_us/programs.yaml b/policyengine_us/programs.yaml index 9c4256b063e..251eba56444 100644 --- a/policyengine_us/programs.yaml +++ b/policyengine_us/programs.yaml @@ -1161,7 +1161,7 @@ programs: variable: ak_hap parameter_prefix: gov.states.ak.dpa.hap verified_years: "2027" - notes: FY2027 regular heating under the federal LIHEAP component (not the state-funded AAHP), following the operating manual's shared-household and utility-allowance adjustments where the regulation differs. Crisis, cooling, weatherization and equipment assistance are out of scope. + notes: FY2027 regular heating under the federal LIHEAP component (not the state-funded AAHP), with shared-dwelling and utility-allowance reductions applied to heating points as 7 AAC 44.080 directs. Crisis, cooling, weatherization and equipment assistance are out of scope. # --- SSA programs --- - id: ssi diff --git a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap.yaml b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap.yaml index eee717cdadf..81f91d0b578 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap.yaml @@ -1,8 +1,15 @@ -# Approved manual-based convention: compute each household's base first, then -# apply equal shares and the final-dollar utility-allowance reduction. This -# conflicts with earlier points-sharing and utility-adjustment regulatory text. +# 7 AAC 44.080 order: community points times the dwelling factor, reduced to +# the household's share of the dwelling's heating expenses (h), times the +# income factor (i), plus the vulnerable point (k), halved for a utility +# allowance (l), then the 2.0-point minimum (m), half-up rounding (n) and the +# 35-point cap (o). When no household in the dwelling reports a heating +# expense, as with heat in rent, manual 3002-1 A.5 gives each eligible +# household an equal share of at most one half. Subsidized households that +# pay heat directly receive a HUD utility allowance for tenant-paid utilities. # SPM units approximate separate economic households within one dwelling. # Sources, each URL listed once: +# Regulation 7 AAC 44.035-44.080: +# https://www.akleg.gov/basis/aac.asp?media=print&secStart=7.44.010&secEnd=7.44.9001 # Household manual 3002-1 A.3-5: # http://dpaweb.hss.state.ak.us/manuals/HAP/3002/3002-1_households.htm # Grant manual 3004-5 steps 1-8 and FY2027 price of $175 per point: @@ -11,26 +18,51 @@ # http://dpaweb.hss.state.ak.us/manuals/HAP/addendum/addendum_a.htm # Current income bands: # http://dpaweb.hss.state.ak.us/manuals/HAP/addendum/addendum_e.htm +# HUD utility allowances, 24 CFR 965.502 and 982.517: +# https://www.law.cornell.edu/cfr/text/24/965.502 +# https://www.law.cornell.edu/cfr/text/24/982.517 -# A single economic household retains the complete sole-household base award. +# The only SPM unit in its dwelling pays the whole heating bill, so its share +# is 1. Fairbanks oil 10 * two-bedroom house 1 * income factor 1 = 10 points, +# plus 1 for age 65 = 11; 11 * 175 = 1,925, the same as its base award. - name: Case 1, a sole household keeps its base when no allowance adjustment applies. period: 2027 absolute_error_margin: 0.01 input: - state_code: AK - ak_hap_base_benefit: 1_925 - receives_housing_assistance: false - heat_expense_included_in_rent: false - hud_utility_allowance: 0 + people: + person1: + age: 65 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: [person1] + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + fuel_oil_expense: 1_000 + ak_atap: 0 + receives_housing_assistance: false + heat_expense_included_in_rent: false + households: + household1: + members: [person1] + state_code: AK + place_fips: '24230' output: + heating_expense: 1_000 + ak_hap_base_benefit: 1_925 ak_hap: 1_925 -# Fairbanks 10 oil points, ordinary two-bedroom factor 1. The first unit has -# zero income and an elderly member: (10 * 1 + 1) * 175 = 1,925. The second -# has annual income 24,000 in the 100-125% band: 10 * 0.6 * 175 = 1,050. -# A.3-5 divides each award by two despite unequal member counts and bills. -# Bills are 25%/75% of combined costs; those proportions do not set the grant. -- name: Case 2, two Fairbanks households share their independently calculated awards equally. +# Fairbanks oil 10, two-bedroom house 1. The bills of 300 and 900 are 25% and +# 75% of the dwelling's 1,200, and 44.080(h) reduces points to those shares +# before the income factor, minimum and rounding. Unit 1 (income 0, factor 1): +# 10 * 1 * .25 * 1 = 2.5, plus 1 unshared point for age 65 = 3.5 -> 4 points +# = 700. Unit 2 (24,000 is in the 100-125% band, factor .6): +# 10 * 1 * .75 * .6 = 4.5 -> 5 points = 875. Sole-household bases stay +# (10 + 1) * 175 = 1,925 and 10 * .6 * 175 = 1,050. +- name: Case 2, two Fairbanks households receive points in proportion to their heating bills. period: 2027 absolute_error_margin: 0.01 input: @@ -82,177 +114,258 @@ members: [person1, person2, person3, person4] state_code: AK place_fips: '24230' - hud_utility_allowance: 0 output: ak_hap_household_size: [3, 1] ak_hap_countable_income: [0, 24_000] ak_hap_income_factor: [1, 0.6] heating_expense: [300, 900] ak_hap_base_benefit: [1_925, 1_050] - ak_hap: [962.50, 525] + ak_hap: [700, 875] -# A.5 counts eligible economic households, not people or actual expense shares. -# Each unit receives one-third of its own base; no monetary rounding follows. -# The tighter margin distinguishes the fractional award from cent rounding. -- name: Case 3, three eligible units with different sizes and bases each receive one third. +# Heat is included in each unit's unsubsidized rent, so no unit reports a +# heating bill and expense shares cannot be measured. Manual 3002-1 A.5 gives +# each of the three eligible units one third, regardless of its size. Fairbanks +# oil 10 * three-bedroom house 1.3 = 13 points before the share. Units 1 and +# 2 (income 0): 13 / 3 = 4.33 -> 4 points = 700. Unit 3 (24,000, factor .6): +# 13 / 3 * .6 = 2.6 -> 3 points = 525. Bases: 13 -> 2,275 for units 1 and 2, +# 13 * .6 = 7.8 -> 8 points = 1,400 for unit 3. +- name: Case 3, three eligible heat-in-rent units with no reported bill each receive one third of their points. period: 2027 - absolute_error_margin: 0.0001 + absolute_error_margin: 0.01 input: people: - person1: {} - person2: {} - person3: {} - person4: {} - person5: {} - person6: {} + person1: + age: 40 + immigration_status: CITIZEN + pre_subsidy_rent: 6_000 + person2: + age: 40 + immigration_status: CITIZEN + pre_subsidy_rent: 6_000 + person3: + age: 40 + immigration_status: CITIZEN + person4: + age: 40 + immigration_status: CITIZEN + employment_income: 24_000 + pre_subsidy_rent: 6_000 spm_units: spm_unit1: members: [person1] - ak_hap_base_benefit: 1_925 - heating_expense: 300 + heating_type: FUEL_OIL + ak_hap_dwelling_type: THREE_PLUS_BEDROOM_HOUSE receives_housing_assistance: false - heat_expense_included_in_rent: false + heat_expense_included_in_rent: true spm_unit2: members: [person2, person3] - ak_hap_base_benefit: 1_050 - heating_expense: 900 + heating_type: FUEL_OIL + ak_hap_dwelling_type: THREE_PLUS_BEDROOM_HOUSE receives_housing_assistance: false - heat_expense_included_in_rent: false + heat_expense_included_in_rent: true spm_unit3: - members: [person4, person5, person6] - ak_hap_base_benefit: 525 - heating_expense: 1_800 + members: [person4] + heating_type: FUEL_OIL + ak_hap_dwelling_type: THREE_PLUS_BEDROOM_HOUSE receives_housing_assistance: false - heat_expense_included_in_rent: false + heat_expense_included_in_rent: true households: household1: - members: [person1, person2, person3, person4, person5, person6] + members: [person1, person2, person3, person4] state_code: AK - hud_utility_allowance: 0 + place_fips: '24230' output: - ak_hap: [641.666667, 350, 175] + heating_expense: [0, 0, 0] + ak_hap_household_size: [1, 2, 1] + ak_hap_income_factor: [1, 1, 0.6] + ak_hap_base_benefit: [2_275, 2_275, 1_400] + ak_hap: [700, 700, 525] -# A.5 eligible-household denominator and explicit 50% maximum for house sharers. -# One positive base among three residents still receives one-half, not all or -# one-third. Two positive bases among three residents each receive one-half. -# All-zero resident units have no eligible denominator and safely return zero. -- name: Case 4, only eligible units enter the denominator and a sharer never exceeds half. +# Heat is included in every unit's unsubsidized rent, so manual 3002-1 A.5 +# divides among eligible units only, at most one half each. Fairbanks oil 10, +# two-bedroom house 1. Income of 36,000 exceeds the one-person 150% ceiling of +# 29,916, so those units have factor 0 and no base. Household 1 has one +# eligible unit: min(1 / 1, .5) = .5, so 10 * .5 = 5 points = 875. Household +# 2 has two: .5 each, so 875 and 10 * .5 * .6 = 3 points = 525 for 24,000 +# income. Household 3 has none. +- name: Case 4, only eligible units enter the equal-share denominator and a share never exceeds half. period: 2027 absolute_error_margin: 0.01 input: people: - person1: {} - person2: {} - person3: {} - person4: {} - person5: {} - person6: {} - person7: {} - person8: {} + person1: + age: 40 + immigration_status: CITIZEN + pre_subsidy_rent: 6_000 + person2: + age: 40 + immigration_status: CITIZEN + employment_income: 36_000 + pre_subsidy_rent: 6_000 + person3: + age: 40 + immigration_status: CITIZEN + employment_income: 36_000 + pre_subsidy_rent: 6_000 + person4: + age: 40 + immigration_status: CITIZEN + pre_subsidy_rent: 6_000 + person5: + age: 40 + immigration_status: CITIZEN + employment_income: 24_000 + pre_subsidy_rent: 6_000 + person6: + age: 40 + immigration_status: CITIZEN + employment_income: 36_000 + pre_subsidy_rent: 6_000 + person7: + age: 40 + immigration_status: CITIZEN + employment_income: 36_000 + pre_subsidy_rent: 6_000 + person8: + age: 40 + immigration_status: CITIZEN + employment_income: 36_000 + pre_subsidy_rent: 6_000 spm_units: spm_unit1: members: [person1] - ak_hap_base_benefit: 1_750 + heating_type: FUEL_OIL receives_housing_assistance: false + heat_expense_included_in_rent: true spm_unit2: members: [person2] - ak_hap_base_benefit: 0 + heating_type: FUEL_OIL receives_housing_assistance: false + heat_expense_included_in_rent: true spm_unit3: members: [person3] - ak_hap_base_benefit: 0 + heating_type: FUEL_OIL receives_housing_assistance: false + heat_expense_included_in_rent: true spm_unit4: members: [person4] - ak_hap_base_benefit: 1_750 + heating_type: FUEL_OIL receives_housing_assistance: false + heat_expense_included_in_rent: true spm_unit5: members: [person5] - ak_hap_base_benefit: 1_050 + heating_type: FUEL_OIL receives_housing_assistance: false + heat_expense_included_in_rent: true spm_unit6: members: [person6] - ak_hap_base_benefit: 0 + heating_type: FUEL_OIL receives_housing_assistance: false + heat_expense_included_in_rent: true spm_unit7: members: [person7] - ak_hap_base_benefit: 0 + heating_type: FUEL_OIL receives_housing_assistance: false + heat_expense_included_in_rent: true spm_unit8: members: [person8] - ak_hap_base_benefit: 0 + heating_type: FUEL_OIL receives_housing_assistance: false + heat_expense_included_in_rent: true households: household1: members: [person1, person2, person3] state_code: AK - hud_utility_allowance: 0 + place_fips: '24230' household2: members: [person4, person5, person6] state_code: AK - hud_utility_allowance: 0 + place_fips: '24230' household3: members: [person7, person8] state_code: AK - hud_utility_allowance: 0 + place_fips: '24230' output: + ak_hap_income_factor: [1, 0, 0, 1, 0.6, 0, 0, 0] + ak_hap_base_benefit: [1_750, 0, 0, 1_750, 1_050, 0, 0, 0] ak_hap: [875, 0, 0, 875, 525, 0, 0, 0] -# Separate homes never share a denominator. A supplied positive base outside -# Alaska cannot bypass the final variable's state restriction. +# Fairbanks oil 10, two-bedroom house 1, income 0. Household 1's two units +# each pay 1,500 of its 3,000 in bills: 10 * .5 = 5 points = 875 each. +# Household 2's sole unit pays its whole bill: 10 points = 1,750. Bills in +# other dwellings do not enter a dwelling's total. The New Hampshire units +# receive nothing from the Alaska program. - name: Case 5, sharing remains within each physical household in a mixed state vector. period: 2027 absolute_error_margin: 0.01 input: people: - person1: {} - person2: {} - person3: {} - person4: {} - person5: {} - person6: {} + person1: + age: 40 + immigration_status: CITIZEN + person2: + age: 40 + immigration_status: CITIZEN + person3: + age: 40 + immigration_status: CITIZEN + person4: + age: 40 + immigration_status: CITIZEN + person5: + age: 40 + immigration_status: CITIZEN + person6: + age: 40 + immigration_status: CITIZEN spm_units: spm_unit1: members: [person1, person2] - ak_hap_base_benefit: 1_925 + heating_type: FUEL_OIL + fuel_oil_expense: 1_500 receives_housing_assistance: false spm_unit2: members: [person3] - ak_hap_base_benefit: 1_925 + heating_type: FUEL_OIL + fuel_oil_expense: 1_500 receives_housing_assistance: false spm_unit3: members: [person4] - ak_hap_base_benefit: 1_925 + heating_type: FUEL_OIL + fuel_oil_expense: 1_500 receives_housing_assistance: false spm_unit4: members: [person5] - ak_hap_base_benefit: 1_925 + heating_type: FUEL_OIL + fuel_oil_expense: 1_500 receives_housing_assistance: false spm_unit5: members: [person6] - ak_hap_base_benefit: 1_925 + heating_type: FUEL_OIL + fuel_oil_expense: 1_500 receives_housing_assistance: false households: household1: members: [person1, person2, person3] state_code: AK - hud_utility_allowance: 0 + place_fips: '24230' household2: members: [person4] state_code: AK - hud_utility_allowance: 0 + place_fips: '24230' household3: members: [person5, person6] state_code: NH - hud_utility_allowance: 0 output: - ak_hap: [962.50, 962.50, 1_925, 0, 0] + ak_hap_base_benefit: [1_750, 1_750, 1_750, 0, 0] + ak_hap: [875, 875, 1_750, 0, 0] -# Grant step 8 requires subsidized housing, directly paid heat and a positive -# allowance. Test all Boolean combinations of those supplied facts, plus a -# second positive allowance magnitude. Fairbanks zero-income base is 1,750. -# Subsidized heat-in-rent cases remain zero through the existing base gate. -- name: Case 6, the allowance reduction requires all conditions and ignores its positive magnitude. +# Fairbanks oil 10, two-bedroom house 1, income 0, each unit the only one in +# its dwelling: base 10 * 175 = 1,750. A subsidized unit that pays its heat +# directly receives a HUD utility allowance, so 44.080(l) halves its points: +# 10 * .5 = 5 points = 875. Heat in unsubsidized rent keeps 1,750, and heat +# in subsidized rent is excluded. +- name: Case 6, the utility-allowance reduction applies to subsidized households that pay heat directly. period: 2027 absolute_error_margin: 0.01 input: @@ -285,41 +398,6 @@ ak_ssp: 0 ak_permanent_fund_dividend: 0 pre_subsidy_rent: 12_000 - person5: - age: 40 - immigration_status: CITIZEN - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - pre_subsidy_rent: 12_000 - person6: - age: 40 - immigration_status: CITIZEN - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - pre_subsidy_rent: 12_000 - person7: - age: 40 - immigration_status: CITIZEN - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - pre_subsidy_rent: 12_000 - person8: - age: 40 - immigration_status: CITIZEN - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - pre_subsidy_rent: 12_000 - person9: - age: 40 - immigration_status: CITIZEN - ssi: 0 - ak_ssp: 0 - ak_permanent_fund_dividend: 0 - pre_subsidy_rent: 12_000 spm_units: spm_unit1: members: [person1] @@ -333,120 +411,50 @@ members: [person2] heating_type: FUEL_OIL ak_hap_dwelling_type: TWO_BEDROOM_HOUSE - fuel_oil_expense: 300 ak_atap: 0 receives_housing_assistance: false - heat_expense_included_in_rent: false + heat_expense_included_in_rent: true spm_unit3: members: [person3] heating_type: FUEL_OIL ak_hap_dwelling_type: TWO_BEDROOM_HOUSE fuel_oil_expense: 300 ak_atap: 0 - receives_housing_assistance: false - heat_expense_included_in_rent: true - spm_unit4: - members: [person4] - heating_type: FUEL_OIL - ak_hap_dwelling_type: TWO_BEDROOM_HOUSE - fuel_oil_expense: 300 - ak_atap: 0 - receives_housing_assistance: false - heat_expense_included_in_rent: true - spm_unit5: - members: [person5] - heating_type: FUEL_OIL - ak_hap_dwelling_type: TWO_BEDROOM_HOUSE - fuel_oil_expense: 300 - ak_atap: 0 receives_housing_assistance: true heat_expense_included_in_rent: false - spm_unit6: - members: [person6] - heating_type: FUEL_OIL - ak_hap_dwelling_type: TWO_BEDROOM_HOUSE - fuel_oil_expense: 300 - ak_atap: 0 - receives_housing_assistance: true - heat_expense_included_in_rent: false - spm_unit7: - members: [person7] - heating_type: FUEL_OIL - ak_hap_dwelling_type: TWO_BEDROOM_HOUSE - fuel_oil_expense: 300 - ak_atap: 0 - receives_housing_assistance: true - heat_expense_included_in_rent: true - spm_unit8: - members: [person8] + spm_unit4: + members: [person4] heating_type: FUEL_OIL ak_hap_dwelling_type: TWO_BEDROOM_HOUSE fuel_oil_expense: 300 ak_atap: 0 receives_housing_assistance: true heat_expense_included_in_rent: true - spm_unit9: - members: [person9] - heating_type: FUEL_OIL - ak_hap_dwelling_type: TWO_BEDROOM_HOUSE - fuel_oil_expense: 300 - ak_atap: 0 - receives_housing_assistance: true - heat_expense_included_in_rent: false households: household1: members: [person1] state_code: AK place_fips: '24230' - hud_utility_allowance: 0 household2: members: [person2] state_code: AK place_fips: '24230' - hud_utility_allowance: 1 household3: members: [person3] state_code: AK place_fips: '24230' - hud_utility_allowance: 0 household4: members: [person4] state_code: AK place_fips: '24230' - hud_utility_allowance: 1 - household5: - members: [person5] - state_code: AK - place_fips: '24230' - hud_utility_allowance: 0 - household6: - members: [person6] - state_code: AK - place_fips: '24230' - hud_utility_allowance: 1 - household7: - members: [person7] - state_code: AK - place_fips: '24230' - hud_utility_allowance: 0 - household8: - members: [person8] - state_code: AK - place_fips: '24230' - hud_utility_allowance: 1 - household9: - members: [person9] - state_code: AK - place_fips: '24230' - hud_utility_allowance: 12_000 output: - ak_hap_base_benefit: [1_750, 1_750, 1_750, 1_750, 1_750, 1_750, 0, 0, 1_750] - ak_hap: [1_750, 1_750, 1_750, 1_750, 1_750, 875, 0, 0, 875] + ak_hap_base_benefit: [1_750, 1_750, 1_750, 0] + ak_hap: [1_750, 1_750, 875, 0] -# Juneau oil 5 * dwelling 1 * income factor 0.6 = 3 points, at least 2; -# 3 * 175 = $525. Step 8 then reduces dollars to 262.50. Reducing points -# first would wrongly deny this household for having only 1.5 points. -- name: Case 7, a three point Juneau household receives half the dollar award. +# Juneau oil 5 * dwelling 1 * income factor .6 = 3 points; the base is +# 3 * 175 = 525. This subsidized household pays its heat directly, so +# 44.080(l) halves the points to 1.5 before the (m) minimum, and 1.5 < 2. +- name: Case 7, the utility-allowance reduction leaves a three point Juneau household below the minimum. period: 2027 absolute_error_margin: 0.01 input: @@ -472,21 +480,20 @@ members: [person1] state_code: AK place_fips: '36400' - hud_utility_allowance: 1_200 output: ak_hap_household_size: 1 ak_hap_countable_income: 24_000 ak_hap_income_factor: 0.6 heating_expense: 300 ak_hap_base_benefit: 525 - ak_hap: 262.50 + ak_hap: 0 -# Fairbanks studio 10 * .15 = 1.5 points fails before rounding. The two -# elderly units each add 1, reach 2.5 points, and round up to 3 before -# conversion to $525. The ineligible unit does not enter their two-household -# denominator; sharing gives 262.50 each and the subsidized unit is halved -# again to 131.25. -- name: Case 8, minimum points and half up rounding precede sharing and allowance adjustments. +# Fairbanks oil 10 * studio .15 = 1.5 points before the share. Each unit pays +# 300 of the dwelling's 900, a one-third share: 1.5 / 3 = .5 points. The two +# elderly units add 1 unshared point (1.5), and the subsidized unit's +# allowance halves that to .75. All are below the 2.0 minimum. As sole +# households, the elderly units would have 2.5 -> 3 points = 525. +- name: Case 8, sharing reduces points before the minimum so studio units sharing a dwelling receive nothing. period: 2027 absolute_error_margin: 0.01 input: @@ -539,19 +546,19 @@ members: [person1, person2, person3] state_code: AK place_fips: '24230' - hud_utility_allowance: 1_200 output: ak_hap_household_size: [1, 1, 1] ak_hap_countable_income: [0, 0, 0] ak_hap_income_factor: [1, 1, 1] ak_hap_base_benefit: [0, 525, 525] - ak_hap: [0, 262.50, 131.25] + ak_hap: [0, 0, 0] -# Ambler oil 35 * large mobile home 1.4 = 49 points, capped at 35, giving -# $6,125. Both eligible resident units get 3,062.50; step 8 halves only the -# subsidized unit again to 1,531.25. Neither benefit is capped at its $300 -# heating bill. -- name: Case 9, the point cap applies before sharing and final dollar reduction. +# Ambler oil 35 * large mobile home 1.4 = 49 points; each unit pays half of +# the dwelling's bills: 49 * .5 = 24.5 -> 25 points = 4,375, under the 35-point +# cap. The subsidized unit's allowance halves 24.5 to 12.25 -> 12 points = +# 2,100. Capping before the share would give 17.5 -> 18 points. As sole +# households both bases reach the cap: 35 * 175 = 6,125. +- name: Case 9, points are shared before the thirty-five point cap. period: 2027 absolute_error_margin: 0.01 input: @@ -590,20 +597,19 @@ members: [person1, person2] state_code: AK place_fips: '01970' - hud_utility_allowance: 1_200 output: ak_hap_household_size: [1, 1] ak_hap_countable_income: [0, 0] ak_hap_income_factor: [1, 1] ak_hap_base_benefit: [6_125, 6_125] - ak_hap: [3_062.50, 1_531.25] + ak_hap: [4_375, 2_100] # Fairbanks oil 10 * two-bedroom house 1. The retiree's $36,000 military # retirement pay is above the one-person 150% ceiling of 2,493 * 12 = 29,916, # so factor 0 and base 0; pension and veterans inputs do not count it again. -# Each zero-income neighbor has 10 * 1 * 175 = 1,750. Only the two eligible -# units enter the denominator, so each receives 1,750 / 2 = 875. -- name: Case 10, primary military retirement excludes its household from eligible heating shares. +# Each unit pays 3,000 of the dwelling's 9,000, so each zero-income neighbor +# gets a one-third share: 10 / 3 = 3.33 -> 3 points = 525. +- name: Case 10, a household made ineligible by military retirement still pays its share of the dwelling's heating bills. period: 2027 absolute_error_margin: 0.01 input: @@ -650,7 +656,7 @@ ak_hap_countable_income: [36_000, 0, 0] ak_hap_income_factor: [0, 1, 1] ak_hap_base_benefit: [0, 1_750, 1_750] - ak_hap: [0, 875, 875] + ak_hap: [0, 525, 525] # Two Fairbanks units of a parent and a 10-year-old child, each with a $3,000 # oil bill. The unit that does not take up ATAP counts no income: factor 1, @@ -770,9 +776,10 @@ # Four zero-income Fairbanks public housing units: 10 * 175 = 1,750 when # eligible. Heat included in subsidized rent is excluded, with or without a # separate housing assistance flag, so the first two receive 0. The two units -# paying a $3,000 oil bill directly with a $1,200 utility allowance keep the -# 1,750 base, and step 8 halves the dollars to 875. -- name: Case 13, explicit public housing controls included heat and the reported utility allowance. +# paying a $3,000 oil bill directly receive a HUD utility allowance for +# tenant-paid utilities, so 44.080(l) halves their points: 10 * .5 = 5 +# points = 875; their sole-household bases stay 1,750. +- name: Case 13, public housing excludes included heat and halves the points of tenants who pay heat directly. period: 2027 absolute_error_margin: 0.01 input: @@ -839,13 +846,11 @@ state_code: AK place_fips: '24230' is_in_public_housing: true - hud_utility_allowance: 1_200 household4: members: [person4] state_code: AK place_fips: '24230' is_in_public_housing: true - hud_utility_allowance: 1_200 output: is_in_public_housing: [true, true, true, true] receives_housing_assistance: [false, true, false, true] @@ -888,7 +893,6 @@ members: [person1] state_code: AK place_fips: '24230' - hud_utility_allowance: 0 output: military_retirement_income: 18_000 ak_hap_countable_income: 18_000 @@ -896,3 +900,78 @@ heating_expense: 3_000 ak_hap_base_benefit: 1_400 ak_hap: 1_400 + +# Fairbanks oil 10 * two-bedroom house 1. Wages of 18,000 are 1,500 a month, +# above the one-person 75% ceiling of 1,246 and within the 100% ceiling of +# 1,662, so factor .7: 7 points and a 7 * 175 = 1,225 base. This voucher +# household pays its oil bill directly and receives a utility allowance, so +# 44.080(l) halves the points to 3.5, which rounds half up to 4 points = 700. +- name: Case 15, a subsidized Fairbanks household at factor seven tenths rounds its halved points up. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + employment_income: 18_000 + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: [person1] + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + fuel_oil_expense: 1_500 + ak_atap: 0 + receives_housing_assistance: true + heat_expense_included_in_rent: false + households: + household1: + members: [person1] + state_code: AK + place_fips: '24230' + output: + ak_hap_countable_income: 18_000 + ak_hap_income_factor: 0.7 + heating_expense: 1_500 + ak_hap_base_benefit: 1_225 + ak_hap: 700 + +# Juneau oil 5 * two-bedroom house 1. Wages of 12,000 are 1,000 a month, +# above the one-person 50% ceiling of 831 and within the 75% ceiling of +# 1,246, so factor .8: 4 points and a 4 * 175 = 700 base. The subsidized +# household pays its oil bill directly, so 44.080(l) halves the points to +# exactly 2.0, which meets the (m) minimum: 2 * 175 = 350. +- name: Case 16, a subsidized household halved to exactly two points receives the minimum award. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + employment_income: 12_000 + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: [person1] + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + fuel_oil_expense: 1_500 + ak_atap: 0 + receives_housing_assistance: true + heat_expense_included_in_rent: false + households: + household1: + members: [person1] + state_code: AK + place_fips: '36400' + output: + ak_hap_countable_income: 12_000 + ak_hap_income_factor: 0.8 + ak_hap_base_benefit: 700 + ak_hap: 350 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_base_benefit.yaml b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_base_benefit.yaml index 347bf576afb..407d680d6eb 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_base_benefit.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_base_benefit.yaml @@ -1,13 +1,14 @@ -# Independently derived from the adopted FY2027 source package and controlling contract. -# Base component precedes disputed sharing and utility-allowance adjustments. +# FY2027 sole-household award (7 AAC 44.035(c)): no dwelling share and no +# utility-allowance reduction; ak_hap applies both at the points stage. # Sources (each URL listed once): # http://dpaweb.hss.state.ak.us/manuals/HAP/3004/3004-5_grant_computation.htm # http://dpaweb.hss.state.ak.us/manuals/HAP/addendum/addendum_e.htm # http://dpaweb.hss.state.ak.us/manuals/HAP/addendum/addendum_a.htm # http://dpaweb.hss.state.ak.us/manuals/HAP/3002/3002-1_households.htm # https://www.akleg.gov/basis/aac.asp?media=print&secStart=7.44.010&secEnd=7.44.9001 -# Geographic/name and nearest-gas approximations are documented in the research manifest. -# 415 replaces the stale published one-person 25% cell 407 under the approved reconciliation. +# Census places not named in Addendum A take the oil and gas points of the nearest listed +# community; these approximations are not a state-issued crosswalk. +# The one-person 25% ceiling is 415 under the 25% rule; Addendum E prints 407. # Fuel, dwelling and location are explicit; no new monetary inputs or sentinel defaults. # GRANT: 10 oil points * 1.4; minimum 2 before half-up whole-point rounding, then $175/point. @@ -341,7 +342,7 @@ ak_hap_base_benefit: 1_750 # Current COMMUNITY table / adopted source crosswalk: 8 points * $175; Loring uses current 4 rather than legacy 5. -- name: Case 12, Fairbanks gas follows the adopted mapping. +- name: Case 12, Fairbanks gas follows the place crosswalk. period: 2027 absolute_error_margin: 0.01 input: @@ -371,7 +372,7 @@ ak_hap_base_benefit: 1_400 # Current COMMUNITY table / adopted source crosswalk: 5 points * $175; Loring uses current 4 rather than legacy 5. -- name: Case 13, Anchorage gas follows the adopted mapping. +- name: Case 13, Anchorage gas follows the place crosswalk. period: 2027 absolute_error_margin: 0.01 input: @@ -401,7 +402,7 @@ ak_hap_base_benefit: 875 # Current COMMUNITY table / adopted source crosswalk: 6 points * $175; Loring uses current 4 rather than legacy 5. -- name: Case 14, Utqiagvik renamed from Barrow gas follows the adopted mapping. +- name: Case 14, Utqiagvik renamed from Barrow gas follows the place crosswalk. period: 2027 absolute_error_margin: 0.01 input: @@ -431,7 +432,7 @@ ak_hap_base_benefit: 1_050 # Current COMMUNITY table / adopted source crosswalk: 21 points * $175; Loring uses current 4 rather than legacy 5. -- name: Case 15, Utqiagvik renamed from Barrow oil follows the adopted mapping. +- name: Case 15, Utqiagvik renamed from Barrow oil follows the place crosswalk. period: 2027 absolute_error_margin: 0.01 input: @@ -461,7 +462,7 @@ ak_hap_base_benefit: 3_675 # Current COMMUNITY table / adopted source crosswalk: 5 points * $175; Loring uses current 4 rather than legacy 5. -- name: Case 16, Knik Fairview gas follows the adopted mapping. +- name: Case 16, Knik Fairview gas follows the place crosswalk. period: 2027 absolute_error_margin: 0.01 input: @@ -491,7 +492,7 @@ ak_hap_base_benefit: 875 # Current COMMUNITY table / adopted source crosswalk: 7 points * $175; Loring uses current 4 rather than legacy 5. -- name: Case 17, Knik Fairview oil follows the adopted mapping. +- name: Case 17, Knik Fairview oil follows the place crosswalk. period: 2027 absolute_error_margin: 0.01 input: @@ -521,7 +522,7 @@ ak_hap_base_benefit: 1_225 # Current COMMUNITY table / adopted source crosswalk: 8 points * $175; Loring uses current 4 rather than legacy 5. -- name: Case 18, North Pole current gas follows the adopted mapping. +- name: Case 18, North Pole current gas follows the place crosswalk. period: 2027 absolute_error_margin: 0.01 input: @@ -551,7 +552,7 @@ ak_hap_base_benefit: 1_400 # Current COMMUNITY table / adopted source crosswalk: 5 points * $175; Loring uses current 4 rather than legacy 5. -- name: Case 19, Juneau uniform consolidated oil follows the adopted mapping. +- name: Case 19, Juneau uniform consolidated oil follows the place crosswalk. period: 2027 absolute_error_margin: 0.01 input: @@ -581,7 +582,7 @@ ak_hap_base_benefit: 875 # Current COMMUNITY table / adopted source crosswalk: 6 points * $175; Loring uses current 4 rather than legacy 5. -- name: Case 20, Sitka uniform consolidated oil follows the adopted mapping. +- name: Case 20, Sitka uniform consolidated oil follows the place crosswalk. period: 2027 absolute_error_margin: 0.01 input: @@ -611,7 +612,7 @@ ak_hap_base_benefit: 1_050 # Current COMMUNITY table / adopted source crosswalk: 5 points * $175; Loring uses current 4 rather than legacy 5. -- name: Case 21, Wrangell uniform consolidated oil follows the adopted mapping. +- name: Case 21, Wrangell uniform consolidated oil follows the place crosswalk. period: 2027 absolute_error_margin: 0.01 input: @@ -641,7 +642,7 @@ ak_hap_base_benefit: 875 # Current COMMUNITY table / adopted source crosswalk: 4 points * $175; Loring uses current 4 rather than legacy 5. -- name: Case 22, Loring current manual oil follows the adopted mapping. +- name: Case 22, Loring current manual oil follows the place crosswalk. period: 2027 absolute_error_margin: 0.01 input: @@ -926,7 +927,7 @@ output: ak_hap_base_benefit: 0 -# Approved disability approximation, GRANT Step 4: 1.5 + 1 = 2.5 -> 3. +# Disability approximation, GRANT Step 4: 1.5 + 1 = 2.5 -> 3. - name: Case 31, disabled qualified adult adds the vulnerability point. period: 2027 absolute_error_margin: 0.01 @@ -1441,7 +1442,7 @@ ak_hap_base_benefit: 0 # One qualified adult; annual payroll 4980, no general earned disregard. Apply source band to Fairbanks 10 oil points. -- name: Case 46, integrated wages at reconciled 25 percent use the inclusive income boundary. +- name: Case 46, integrated wages at the 25 percent limit use the inclusive income boundary. period: 2027 absolute_error_margin: 0.01 input: @@ -1729,8 +1730,8 @@ output: ak_hap_base_benefit: 0 -# Juneau 5 * .55 * .7 + 1 = 2.925 -> 3 * 175; positive allowance affects a later unresolved final adjustment only. -- name: Case 54, base amount does not apply disputed utility allowance reduction. +# Juneau 5 * .55 * .7 + 1 = 2.925 -> 3 * 175. The base omits the 7 AAC 44.080(l) reduction for this subsidized household; ak_hap applies it. +- name: Case 54, base amount does not apply the utility allowance reduction. period: 2027 absolute_error_margin: 0.01 input: @@ -1757,7 +1758,6 @@ - person1 state_code: AK place_fips: '36400' - hud_utility_allowance: 1_200 output: ak_hap_base_benefit: 525 @@ -2002,8 +2002,8 @@ output: ak_hap_base_benefit: 0 -# Numeric 0 represents unavailable supported oil geography, not statutory ineligibility. -- name: Case 63, unmatched place yields an unavailable modeled amount. +# '99999' is not an Alaska Census place, so neither points table has a value; numeric 0 is not statutory ineligibility. +- name: Case 63, a place code outside the Census gazetteer yields an unavailable modeled amount. period: 2027 absolute_error_margin: 0.01 input: @@ -2062,8 +2062,8 @@ output: ak_hap_base_benefit: 0 -# Numeric 0 represents unavailable supported oil geography, not statutory ineligibility. -- name: Case 65, ambiguous Anchorage oil place yields an unavailable modeled amount. +# Addendum A lists Anchorage at 8 oil points, and place 03000 covers the whole municipality (Chugiak, listed at 7, lies inside it): 8 * 1 = 8 points * $175 = $1,400. +- name: Case 65, Anchorage municipality fuel oil uses the Anchorage oil points. period: 2027 absolute_error_margin: 0.01 input: @@ -2090,9 +2090,9 @@ state_code: AK place_fips: '03000' output: - ak_hap_base_benefit: 0 + ak_hap_base_benefit: 1_400 -# User-approved purchased-fuel default: Fairbanks oil 10 * .8 * $175 = $1400. +# Purchased-fuel assumption under 7 AAC 44.080(d): Fairbanks oil 10 * .8 = 8 points * $175 = $1,400. - name: Case 66, wood uses the purchased-fuel approximation with existing heating type. period: 2027 absolute_error_margin: 0.01 @@ -2122,7 +2122,7 @@ output: ak_hap_base_benefit: 1_400 -# User-approved purchased-fuel default: Fairbanks oil 10 * .8 * $175 = $1400. +# Purchased-fuel assumption under 7 AAC 44.080(d): Fairbanks oil 10 * .8 = 8 points * $175 = $1,400. - name: Case 67, coal uses the purchased-fuel approximation with existing heating type. period: 2027 absolute_error_margin: 0.01 @@ -2152,8 +2152,8 @@ output: ak_hap_base_benefit: 1_400 -# Numeric 0 is missing modeled fuel coverage, not a legal determination that all such households are ineligible. -- name: Case 68, other without a supported subtype yields an unavailable modeled amount. +# 7 AAC 44.080(f) and grant step 1 put steam, hot water and vehicle gasoline on oil points; OTHER stands for them. Fairbanks oil 10 = 10 points * $175 = $1,750, with the bill in other_heating_fuel_expense. +- name: Case 68, other heating such as steam or hot water uses oil points. period: 2027 absolute_error_margin: 0.01 input: @@ -2180,10 +2180,10 @@ state_code: AK place_fips: '24230' output: - ak_hap_base_benefit: 0 + ak_hap_base_benefit: 1_750 -# Numeric 0 is missing modeled fuel coverage, not a legal determination that all such households are ineligible. -- name: Case 69, solar without a supported subtype yields an unavailable modeled amount. +# A SOLAR household's bill is grid electricity (pre_subsidy_electricity_expense), and 7 AAC 44.080(f) puts electricity on oil points: Fairbanks oil 10 = 10 points * $175 = $1,750. +- name: Case 69, solar heat uses oil points like grid electricity. period: 2027 absolute_error_margin: 0.01 input: @@ -2210,7 +2210,7 @@ state_code: AK place_fips: '24230' output: - ak_hap_base_benefit: 0 + ak_hap_base_benefit: 1_750 # Numeric 0 is missing modeled fuel coverage, not a legal determination that all such households are ineligible. - name: Case 70, unspecified without a supported subtype yields an unavailable modeled amount. @@ -2644,8 +2644,8 @@ output: ak_hap_base_benefit: [0, 0, 1_400] -# Anchorage oil mapping remains ambiguous and an unmatched place is unavailable; selecting wood or coal cannot use gas points instead. -- name: "Case 79, purchased fuel cannot resolve unavailable oil community points." +# Anchorage wood: oil 8 * .8 = 6.4 -> 6 points * $175 = $1,050. Place '99999' has no oil points, and selecting coal cannot use gas points instead. +- name: "Case 79, purchased fuel scales the Anchorage oil points and cannot resolve an unavailable place." period: 2027 absolute_error_margin: 0.01 input: @@ -2688,7 +2688,7 @@ state_code: "AK" place_fips: "99999" output: - ak_hap_base_benefit: [0, 0] + ak_hap_base_benefit: [1_050, 0] # Purchased approximation is fixed for WOOD, independent of reported bill: zero wood bill plus 300 annual rent meets the existing heat-in-rent expense gate; base 8 * 175 = 1,400. - name: "Case 80, unsubsidized heat in rent supplies the expense gate without inferring fuel procurement." @@ -2719,3 +2719,153 @@ place_fips: "24230" output: ak_hap_base_benefit: 1_400 + +# Anchorage oil 8 (Addendum A) applies to electric heat under 7 AAC 44.080(f). Social Security of 18,000 is 1,500 a month, above the one-person 75% ceiling of 1,246 and within the 100% ceiling of 1,662: factor .7. One-bedroom 8 * .55 * .7 = 3.08, plus 1 for age 70 = 4.08 -> 4 points * $175 = $700. +- name: Case 81, an elderly Anchorage household with electric heat receives the Anchorage oil points. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + immigration_status: CITIZEN + social_security: 18_000 + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: [person1] + heating_type: ELECTRICITY + ak_hap_dwelling_type: ONE_BEDROOM_OR_ONE_ROOM_HOUSE + pre_subsidy_electricity_expense: 1_200 + ak_atap: 0 + receives_housing_assistance: false + households: + household1: + members: [person1] + state_code: AK + place_fips: '03000' + output: + ak_hap_countable_income: 18_000 + ak_hap_income_factor: 0.7 + ak_hap_base_benefit: 700 + +# 7 AAC 44.042(16) exempts cash gifts that do not exceed $20 a month: 240 / 12 = 20. Wages of 14,800 are 1,233.33 a month, within the one-person 75% ceiling of 1,246: factor .8. Fairbanks oil 10 * .8 = 8 points * $175 = $1,400. Counting the gift would give 15,040 (1,253.33 a month) and factor .7. +- name: Case 82, a twenty dollar monthly gift does not move a household into a lower income factor. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + employment_income: 14_800 + financial_assistance: 240 + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: [person1] + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + fuel_oil_expense: 1_500 + ak_atap: 0 + receives_housing_assistance: false + households: + household1: + members: [person1] + state_code: AK + place_fips: '24230' + output: + ak_hap_countable_income: 14_800 + ak_hap_income_factor: 0.8 + ak_hap_base_benefit: 1_400 + +# Manual 3003-1 A.1 and 3003-5 B.1.a count military basic pay as earned income. 40,000 exceeds the one-person 150% ceiling of 2,493 * 12 = 29,916: factor 0, so no award. Without the pay, Fairbanks oil 10 would give $1,750. +- name: Case 83, military basic pay counts as earned income. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + military_basic_pay: 40_000 + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: [person1] + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + fuel_oil_expense: 1_500 + ak_atap: 0 + receives_housing_assistance: false + households: + household1: + members: [person1] + state_code: AK + place_fips: '24230' + output: + ak_hap_countable_income: 40_000 + ak_hap_income_factor: 0 + ak_hap_base_benefit: 0 + +# Meadow Lakes CDP (place 47735) is not named in Addendum A; its nearest listed community, Wasilla, has 7 oil points. 7 * 1 * 1 = 7 points * $175 = $1,225. +- name: Case 84, an unlisted Census place takes its nearest listed community's oil points. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: [person1] + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + fuel_oil_expense: 1_000 + ak_atap: 0 + receives_housing_assistance: false + households: + household1: + members: [person1] + state_code: AK + place_fips: '47735' + output: + ak_hap_base_benefit: 1_225 + +# Mertarvik CDP (place 48590) is not named in Addendum A. It takes the 25 oil points of its nearest listed community, Newtok, and also its 0/AVCP marker, which routes all residents to the tribal program, so the state award is zero. +- name: Case 85, an unlisted Census place inherits its nearest community's all-resident tribal routing. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: [person1] + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + fuel_oil_expense: 1_000 + ak_atap: 0 + receives_housing_assistance: false + households: + household1: + members: [person1] + state_code: AK + place_fips: '48590' + output: + ak_hap_base_benefit: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_countable_income.yaml index 211f860bc71..f1f531ec9bc 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_countable_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_countable_income.yaml @@ -1,4 +1,4 @@ -# Adopted FY2027 HAP manual; supported income components only. +# FY2027 HAP manual; supported income components only. # These tests do not assert final eligibility, heating points or an award. # Sources: # http://dpaweb.hss.state.ak.us/manuals/HAP/3003/3003-1_countable_income.htm @@ -33,7 +33,7 @@ output: ak_hap_countable_income: 12_000 -# MS 3003-4 A.7 defines gross less allowable costs; contract accepts already-net input, so no second standard expense deduction. +# MS 3003-4 A.7 defines gross less allowable costs; the supplied input is already net, so no second standard expense deduction applies. - name: "Case 2, supplied net self-employment is not reduced by another fifty percent." period: 2027 absolute_error_margin: 0.01 @@ -116,7 +116,7 @@ output: ak_hap_countable_income: 3_800 -# MS 3003-1 B.6.f and contract nonnegative rental streams: 10,000 + 0 + 600. +# MS 3003-1 B.6.f; each rental stream is floored at zero: 10,000 + 0 + 600. - name: "Case 5, negative rental income does not offset positive farm rental income." period: 2027 absolute_error_margin: 0.01 @@ -144,7 +144,7 @@ output: ak_hap_countable_income: 10_600 -# Contract floors each reported rental source separately; no extra expense deduction from supplied net rent. +# Each reported rental source is floored separately; no extra expense deduction from supplied net rent. - name: "Case 6, negative farm rental income does not reduce positive rental income." period: 2027 absolute_error_margin: 0.01 @@ -376,7 +376,7 @@ output: ak_hap_countable_income: 36_000 -# MS 3003-6 E and contract dependent-child approximation do not exclude a minor household head's earnings. +# MS 3003-6 E and the dependent-child approximation do not exclude a minor household head's earnings. - name: "Case 13, an independent minor student has countable earnings." period: 2027 absolute_error_margin: 0.01 @@ -441,7 +441,7 @@ output: ak_hap_countable_income: 28_200 -# MS 3003-1 B.2.c counts gross SSA including Medicare withholding. Contract adds no general medical, childcare or support deduction. +# MS 3003-1 B.2.c counts gross SSA including Medicare withholding. No general medical, childcare or support deduction applies. - name: "Case 15, gross Social Security is not reduced by reported medical or support expenses." period: 2027 absolute_error_margin: 0.01 @@ -473,8 +473,8 @@ output: ak_hap_countable_income: 18_000 -# MS 3003-1 B.2 and B.6.c list these ordinary unearned receipts; inputs represent distinct payments. -- name: "Case 16, retirement and regular disability or survivor receipts count." +# MS 3003-1 B.2 and B.6.c list these ordinary unearned receipts, and 3000-2 names Railroad Retirement Act annuities; inputs represent distinct payments: 2,400 + 1,200 + 600 + 600 + 600. +- name: "Case 16, retirement, railroad and regular disability or survivor receipts count." period: 2027 absolute_error_margin: 0.01 input: @@ -489,6 +489,7 @@ retirement_distributions: 1_200 disability_benefits: 600 survivor_benefits: 600 + railroad_benefits: 600 spm_units: spm_unit1: members: ["person1"] @@ -500,7 +501,7 @@ members: ["person1"] state_code: "AK" output: - ak_hap_countable_income: 4_800 + ak_hap_countable_income: 5_400 # MS 3003-1 B.2 and B.6.a,b,j,o: ordinary nonexempt cash receipts. General assistance represents cash paid to the household, not a vendor payment. - name: "Case 17, ordinary cash assistance and compensation receipts count." @@ -532,8 +533,8 @@ output: ak_hap_countable_income: 3_000 -# MS 3003-1 B.6.h; ordinary receipts have no NH-style $50 disregard. Generic dividends cannot identify exempt ANCSA payments. -- name: "Case 18, ordinary interest dividends and estate payments count in full." +# MS 3003-1 B.6.h and B.6.n (bingo and lottery winnings); ordinary receipts have no NH-style $50 disregard. Generic dividends cannot identify exempt ANCSA payments: 120 + 240 + 120 + 600. +- name: "Case 18, ordinary interest, dividends, estate payments and gambling winnings count in full." period: 2027 absolute_error_margin: 0.01 input: @@ -547,6 +548,7 @@ interest_income: 120 ordinary_dividend_income: 240 estate_income: 120 + gambling_winnings: 600 spm_units: spm_unit1: members: ["person1"] @@ -558,7 +560,7 @@ members: ["person1"] state_code: "AK" output: - ak_hap_countable_income: 480 + ak_hap_countable_income: 1_080 # MS 3003-1 B.6.h. Canonical ordinary dividends aggregate the two components; do not count the aggregate and components again. - name: "Case 19, canonical dividend components are counted once." @@ -614,7 +616,7 @@ output: ak_hap_countable_income: 3_000 -# MS 3003-1 B.3 and B.6.e; contract treats support as actually retained and does not impose an unsupported blanket $50 pass-through cap. 600 + 1,200 + 2,400 ATAP. +# MS 3003-1 B.3 and B.6.e; reported support is treated as retained, with no $50 pass-through cap. 600 + 1,200 + 2,400 ATAP. - name: "Case 21, retained child support and alimony are countable." period: 2027 absolute_error_margin: 0.01 @@ -713,7 +715,7 @@ output: ak_hap_countable_income: 8_400 -# MS 3003-2 A.24: 239.88 / 12 = 19.99 each month under the authorized constant-receipt proxy. +# MS 3003-2 A.24: 239.88 / 12 = 19.99 each month under the constant monthly receipt approximation. - name: "Case 24, regular cash gifts strictly below twenty dollars monthly are excluded." period: 2027 absolute_error_margin: 0.01 @@ -739,8 +741,8 @@ output: ak_hap_countable_income: 0 -# MS 3003-2 A.24 excludes only amounts under $20; contract retains the whole gift at 240 / 12 = 20. -- name: "Case 25, regular cash gifts at twenty dollars monthly count in full." +# 7 AAC 44.042(16) exempts gifts that do not exceed $20 a month, and MS 3003-1 B.6.r counts only gifts over $20: 240 / 12 = 20 is excluded. +- name: "Case 25, regular cash gifts of exactly twenty dollars monthly are excluded." period: 2027 absolute_error_margin: 0.01 input: @@ -763,7 +765,7 @@ members: ["person1"] state_code: "AK" output: - ak_hap_countable_income: 240 + ak_hap_countable_income: 0 # MS 3003-1 B.6.r and 3003-2 A.24: 240.12 / 12 = 20.01; this is an exclusion threshold, not a $20 deduction. - name: "Case 26, regular cash gifts above twenty dollars monthly count in full." @@ -824,7 +826,7 @@ output: ak_hap_countable_income: 0 -# MS 3003-2 A.1,6,9,30 and the shared contract exclude the household member's PFD, Pell, SNAP and vendor housing benefit. +# MS 3003-2 A.1,6,9,30 exclude the household member's PFD, Pell, SNAP and vendor housing benefit. - name: "Case 28, household PFD and vendor or education benefits are excluded." period: 2027 absolute_error_margin: 0.01 @@ -853,7 +855,7 @@ output: ak_hap_countable_income: 10_000 -# MS 3003-2 A.9 counts actual cash utility reimbursement; contract does not infer that a HUD allowance was paid in cash. +# MS 3003-2 A.9 counts actual cash utility reimbursement; a HUD allowance alone does not show a cash payment. - name: "Case 29, a utility allowance is not automatically treated as a cash reimbursement." period: 2027 absolute_error_margin: 0.01 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_household_size.yaml b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_household_size.yaml index 37daee2e572..837e8a292c7 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_household_size.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_household_size.yaml @@ -1,4 +1,4 @@ -# Adopted FY2027 HAP manual; supported income components only. +# FY2027 HAP manual; supported income components only. # These tests do not assert final eligibility, heating points or an award. # Sources: # http://dpaweb.hss.state.ak.us/manuals/HAP/3002/3002-1_households.htm @@ -251,7 +251,7 @@ ak_hap_household_size: 0 ak_hap_countable_income: 12_000 -# Shared contract masks both components to Alaska; MS 3002-1 B requires Alaska residence. +# Both components are limited to Alaska; MS 3002-1 B requires Alaska residence. - name: "Case 4, all supported HAP components are zero outside Alaska." period: 2027 absolute_error_margin: 0.01 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_income_factor.yaml b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_income_factor.yaml index 63eb88405ee..6d2fc691e5e 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_income_factor.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_income_factor.yaml @@ -1,13 +1,11 @@ -# Independently derived from the adopted FY2027 source package and controlling contract. -# Base component precedes disputed sharing and utility-allowance adjustments. +# FY2027 income factors from the lagged 2026 Alaska poverty guideline (Addendum E). # Sources (each URL listed once): # http://dpaweb.hss.state.ak.us/manuals/HAP/3004/3004-5_grant_computation.htm # http://dpaweb.hss.state.ak.us/manuals/HAP/addendum/addendum_e.htm # http://dpaweb.hss.state.ak.us/manuals/HAP/addendum/addendum_a.htm # http://dpaweb.hss.state.ak.us/manuals/HAP/3002/3002-1_households.htm # https://www.akleg.gov/basis/aac.asp?media=print&secStart=7.44.010&secEnd=7.44.9001 -# Geographic/name and nearest-gas approximations are documented in the research manifest. -# 415 replaces the stale published one-person 25% cell 407 under the approved reconciliation. +# The one-person 25% ceiling is 415 under the 25% rule; Addendum E prints 407. # Fuel, dwelling and location are explicit; no new monetary inputs or sentinel defaults. # GRANT Step 3: income at or below 25% receives factor 1. @@ -74,7 +72,7 @@ output: ak_hap_income_factor: 1 -# Controlling contract: positive qualified size is required. +# A household with no qualified members has no income band. - name: Case 3, no qualified members yields zero income factor. period: 2027 absolute_error_margin: 0.0001 @@ -106,7 +104,7 @@ output: ak_hap_income_factor: 0 -# GRID discrepancy: 407/month is below adopted derived 415 ceiling. +# Addendum E prints 407/month; the 25% rule gives a 415 ceiling, so 407 is in the lowest band. - name: Case 4, printed stale 407 amount stays in the lowest band. period: 2027 absolute_error_margin: 0.0001 @@ -139,7 +137,7 @@ ak_hap_income_factor: 1 # floor(1662 * .25) = 415, not the stale printed 407. -- name: Case 5, 408 remains below the reconciled 25 percent ceiling. +- name: Case 5, 408 remains below the 25 percent ceiling. period: 2027 absolute_error_margin: 0.0001 input: @@ -170,7 +168,7 @@ output: ak_hap_income_factor: 1 -# GRID + contract: monthly ceiling 415 * 12 = 4980; inclusive band top. +# Addendum E grid: monthly ceiling 415 * 12 = 4980; inclusive band top. - name: Case 6, exact one-person band 1 ceiling is inclusive. period: 2027 absolute_error_margin: 0.0001 @@ -234,7 +232,7 @@ output: ak_hap_income_factor: 0.9 -# GRID + contract: monthly ceiling 831 * 12 = 9972; inclusive band top. +# Addendum E grid: monthly ceiling 831 * 12 = 9972; inclusive band top. - name: Case 8, exact one-person band 2 ceiling is inclusive. period: 2027 absolute_error_margin: 0.0001 @@ -298,7 +296,7 @@ output: ak_hap_income_factor: 0.8 -# GRID + contract: monthly ceiling 1246 * 12 = 14952; inclusive band top. +# Addendum E grid: monthly ceiling 1246 * 12 = 14952; inclusive band top. - name: Case 10, exact one-person band 3 ceiling is inclusive. period: 2027 absolute_error_margin: 0.0001 @@ -362,7 +360,7 @@ output: ak_hap_income_factor: 0.7 -# GRID + contract: monthly ceiling 1662 * 12 = 19944; inclusive band top. +# Addendum E grid: monthly ceiling 1662 * 12 = 19944; inclusive band top. - name: Case 12, exact one-person band 4 ceiling is inclusive. period: 2027 absolute_error_margin: 0.0001 @@ -426,7 +424,7 @@ output: ak_hap_income_factor: 0.6 -# GRID + contract: monthly ceiling 2077 * 12 = 24924; inclusive band top. +# Addendum E grid: monthly ceiling 2077 * 12 = 24924; inclusive band top. - name: Case 14, exact one-person band 5 ceiling is inclusive. period: 2027 absolute_error_margin: 0.0001 @@ -490,7 +488,7 @@ output: ak_hap_income_factor: 0.5 -# GRID + contract: monthly ceiling 2493 * 12 = 29916; inclusive band top. +# Addendum E grid: monthly ceiling 2493 * 12 = 29916; inclusive band top. - name: Case 16, exact one-person band 6 ceiling is inclusive. period: 2027 absolute_error_margin: 0.0001 diff --git a/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap.py b/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap.py index e8efb762f2b..f7c8b6f6edd 100644 --- a/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap.py +++ b/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap.py @@ -1,4 +1,7 @@ from policyengine_us.model_api import * +from policyengine_us.variables.gov.states.ak.dpa.hap.ak_hap_base_benefit import ( + ak_hap_award, +) class ak_hap(Variable): @@ -11,24 +14,34 @@ class ak_hap(Variable): "http://dpaweb.hss.state.ak.us/manuals/HAP/3002/3002-1_households.htm", "http://dpaweb.hss.state.ak.us/manuals/HAP/3004/3004-5_grant_computation.htm", "https://www.akleg.gov/basis/aac.asp?media=print&secStart=7.44.010&secEnd=7.44.9001", + "https://www.law.cornell.edu/cfr/text/24/965.502", + "https://www.law.cornell.edu/cfr/text/24/982.517", ) defined_for = StateCode.AK def formula(spm_unit, period, parameters): p = parameters(period).gov.states.ak.dpa.hap.benefit - base_benefit = spm_unit("ak_hap_base_benefit", period) # SPM units approximate separate economic households. This does not # distinguish the manual's owner/occupant and room-renter exceptions. # Project one first-member marker per SPM unit, regardless of its size. first_member = spm_unit.members_position == 0 household_count = spm_unit.household.sum(first_member) + sole_household_eligible = spm_unit("ak_hap_base_benefit", period) > 0 eligible_household_count = spm_unit.household.sum( - first_member & spm_unit.project(base_benefit > 0) + first_member & spm_unit.project(sole_household_eligible) ) - # Approved convention: household manual A.3-5 applies equal shares to - # dollar awards, capped at 50% for any sharer. Conflicting earlier - # points/actual-cost sharing text is documented in the parameter. - share = where( + heating_expense = spm_unit("heating_expense", period).astype(np.float64) + dwelling_heating_expense = spm_unit.household.sum( + first_member * spm_unit.project(heating_expense) + ) + # 7 AAC 44.080(h) reduces a sharing household's points to its + # proportionate share of the dwelling's heating expenses. When no + # household reports a heating expense (heat in rent), manual 3002-1 + # A.5 fills the gap: equal shares among the eligible households, at + # most the maximum share each. A heat-in-rent household that shares a + # dwelling with a household reporting a heating bill gets a zero share, + # because the heating portion of its rent is not observed. + equal_share = where( household_count > 1, min_( 1 / max_(eligible_household_count, 1), @@ -36,22 +49,10 @@ def formula(spm_unit, period, parameters): ), 1, ) - # The supplied household allowance is a proxy, not an Alaska schedule; - # its zero default cannot establish absence. Housing step-down - # exceptions are unobserved, as are the base formula's tribal, - # residency and unresolved geography limitations. - subsidized = spm_unit( - "receives_housing_assistance", period - ) | spm_unit.household("is_in_public_housing", period) - utility_adjustment = ( - subsidized - & ~spm_unit("heat_expense_included_in_rent", period) - & (spm_unit.household("hud_utility_allowance", period) > 0) - ) - # Manual step 8 reduces dollars after the base minimum/rounding/cap; - # 7 AAC 44.080(l)-(n) instead reduces points before the minimum. - return ( - base_benefit - * share - * where(utility_adjustment, 1 - p.utility_allowance_reduction, 1) + share = np.divide( + heating_expense, + dwelling_heating_expense, + out=equal_share, + where=dwelling_heating_expense > 0, ) + return ak_hap_award(spm_unit, period, parameters, share, True) diff --git a/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_base_benefit.py b/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_base_benefit.py index ddfb58c99b4..023d8a51b69 100644 --- a/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_base_benefit.py +++ b/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_base_benefit.py @@ -1,6 +1,102 @@ from policyengine_us.model_api import * +def ak_hap_award(spm_unit, period, parameters, share, apply_utility_allowance): + # 7 AAC 44.080: community points (a)-(f) times the dwelling factor (g), + # reduced to the dwelling share (h), times the income factor (i), plus + # the vulnerable point (k), halved for a utility allowance (l), then the + # 2.0-point minimum (m), half-up rounding (n) and the 35-point cap (o). + p = parameters(period).gov.states.ak.dpa.hap.benefit + place = spm_unit.household("place_fips", period) + fuel = spm_unit("heating_type", period) + fuels = fuel.possible_values + oil_table = p.community_points.oil + gas_table = p.community_points.natural_gas + oil_place = where(np.isin(place, list(oil_table)), place, "UNAVAILABLE") + gas_place = where(np.isin(place, list(gas_table)), place, "UNAVAILABLE") + # 7 AAC 44.080(f) and grant step 1 put electricity, propane, steam, hot + # water and vehicle gasoline on oil points. OTHER stands for the steam, + # hot-water and vehicle-gasoline cases, which heating_type cannot name, + # and a SOLAR household's bill is grid electricity. Kerosene is Grade 1 + # heating oil in the AHFC-funded technical guide. + oil_fuel = ( + (fuel == fuels.FUEL_OIL) + | (fuel == fuels.KEROSENE) + | (fuel == fuels.PROPANE) + | (fuel == fuels.ELECTRICITY) + | (fuel == fuels.SOLAR) + | (fuel == fuels.OTHER) + ) + # WOOD and COAL take the purchased-fuel factor of 7 AAC 44.080(d); + # heating_type cannot identify self-harvested fuel or pellets, whose + # factors differ under (c) and (e). + wood_or_coal = (fuel == fuels.WOOD) | (fuel == fuels.COAL) + # Both tables cover every Census place; a missing or unknown place code + # has no points. + community_points = select( + [oil_fuel, fuel == fuels.NATURAL_GAS, wood_or_coal], + [ + oil_table[oil_place], + gas_table[gas_place], + oil_table[oil_place] * p.purchased_wood_coal_multiplier, + ], + default=0, + ) + dwelling = spm_unit("ak_hap_dwelling_type", period) + # Restore the table's decimal tenths after float32 storage so exact + # half points retain the half-up rounding below. + factor = np.round(spm_unit("ak_hap_income_factor", period).astype(np.float64), 1) + person = spm_unit.members + age = person("age", period) + # Existing disability status approximates the manual's documented + # disability categories. Excluded members cannot add priority points. + vulnerable = spm_unit.any( + person("is_citizen_or_legal_immigrant", period) + & ( + (age >= p.elderly_age) + | (age < p.child_age_limit) + | person("is_disabled", period) + ) + ) + heat_in_rent = spm_unit("heat_expense_included_in_rent", period) + subsidized = spm_unit("receives_housing_assistance", period) | spm_unit.household( + "is_in_public_housing", period + ) + # Subsidized households paying heat directly receive a HUD utility + # allowance for tenant-paid utilities (24 CFR 965.502(a) and + # 982.517(a)(1)), so 44.080(l) applies without a reported allowance. + # Step-down programs that end the allowance after a year are unobserved. + utility_allowance = apply_utility_allowance & subsidized & ~heat_in_rent + points = community_points * p.dwelling_factor[dwelling] * share * factor + points = points + vulnerable * p.vulnerability_points + points = points * where(utility_allowance, 1 - p.utility_allowance_reduction, 1) + # NOTE: Drop floating-point noise from fractional shares so exact + # half points and the 2.0 minimum compare exactly. + points = np.round(points, 9) + # Full annual rent satisfies the expense test for nonsubsidized + # heat-in-rent households. Pre-subsidy rent avoids benefit feedback. + expense = where( + heat_in_rent, + add(spm_unit, period, ["pre_subsidy_rent"]), + spm_unit("heating_expense", period), + ) + # The table identifies all-resident tribal routing. Native-only tribal + # eligibility and contrary interagency arrangements are unobserved; + # never infer tribal enrollment from race. Finer residency, temporary + # shelter duration and vendor-credit rules are also unobserved. + state_served = ~np.isin(place, p.tribal_service_places) + eligible = ( + (factor > 0) + & (community_points > 0) + & (expense > p.minimum_expense) + & ~(heat_in_rent & subsidized) + & state_served + & (points >= p.minimum_points) + ) + rounded_points = min_(np.floor(points + 0.5), p.maximum_points) + return where(eligible, rounded_points * p.point_value, 0) + + class ak_hap_base_benefit(Variable): value_type = float entity = SPMUnit @@ -18,90 +114,6 @@ class ak_hap_base_benefit(Variable): defined_for = StateCode.AK def formula(spm_unit, period, parameters): - p = parameters(period).gov.states.ak.dpa.hap.benefit - place = spm_unit.household("place_fips", period) - fuel = spm_unit("heating_type", period) - fuels = fuel.possible_values - oil_table = p.community_points.oil - gas_table = p.community_points.natural_gas - oil_place = where( - np.isin(place, list(oil_table._children)), place, "UNAVAILABLE" - ) - gas_place = where( - np.isin(place, list(gas_table._children)), place, "UNAVAILABLE" - ) - oil_fuel = ( - (fuel == fuels.FUEL_OIL) - | (fuel == fuels.KEROSENE) - | (fuel == fuels.PROPANE) - | (fuel == fuels.ELECTRICITY) - ) - wood_or_coal = (fuel == fuels.WOOD) | (fuel == fuels.COAL) - # Propane uses oil points under 7 AAC 44.080(f). Kerosene is Grade 1 - # heating oil in the AHFC-funded technical guide. Unclassified OTHER - # fuels and unmatched oil geography yield unavailable modeled amounts - # (zero fallback), not statutory denials. Anchorage - # oil is ambiguous. The gas table uses a documented nearest-community - # approximation where a direct published place match is unavailable. - # Purchased wood/coal is the approved modeling default. Existing - # heating_type cannot identify self-harvest or pellets, whose factors - # differ; neither subtype is inferred from the reported expense. - community_points = select( - [oil_fuel, fuel == fuels.NATURAL_GAS, wood_or_coal], - [ - oil_table[oil_place], - gas_table[gas_place], - oil_table[oil_place] * p.purchased_wood_coal_multiplier, - ], - default=0, - ) - dwelling = spm_unit("ak_hap_dwelling_type", period) - # Restore the table's decimal tenths after float32 storage so exact - # half points retain the manual's half-up rounding below. - factor = np.round( - spm_unit("ak_hap_income_factor", period).astype(np.float64), 1 - ) - person = spm_unit.members - age = person("age", period) - # Existing disability status approximates the manual's documented - # disability categories. Excluded members cannot add priority points. - vulnerable = spm_unit.any( - person("is_citizen_or_legal_immigrant", period) - & ( - (age >= p.elderly_age) - | (age < p.child_age_limit) - | person("is_disabled", period) - ) - ) - points = community_points * p.dwelling_factor[dwelling] * factor - points = points + vulnerable * p.vulnerability_points - heat_in_rent = spm_unit("heat_expense_included_in_rent", period) - subsidized = spm_unit( - "receives_housing_assistance", period - ) | spm_unit.household("is_in_public_housing", period) - # Full annual rent satisfies the expense test for nonsubsidized - # heat-in-rent households. Pre-subsidy rent avoids benefit feedback. - expense = where( - heat_in_rent, - add(spm_unit, period, ["pre_subsidy_rent"]), - spm_unit("heating_expense", period), - ) - # The table identifies all-resident tribal routing. Native-only tribal - # eligibility and contrary interagency arrangements are unobserved; - # never infer tribal enrollment from race. Finer residency, temporary - # shelter duration and vendor-credit rules are also unobserved. - state_served = ~np.isin(place, p.tribal_service_places) - eligible = ( - (factor > 0) - & (community_points > 0) - & (expense > p.minimum_expense) - & ~(heat_in_rent & subsidized) - & state_served - & (points >= p.minimum_points) - ) - # Apply the unrounded minimum before half-up whole-point rounding. - # This is the sole-household base amount, without an expense cap. - # ak_hap applies sharing and utility-allowance reductions to dollars - # under the approved manual-based modeling convention. - rounded_points = min_(np.floor(points + 0.5), p.maximum_points) - return where(eligible, rounded_points * p.point_value, 0) + # The award as if the household were the sole household in the + # dwelling (7 AAC 44.035(c)), without the utility-allowance reduction. + return ak_hap_award(spm_unit, period, parameters, 1, False) diff --git a/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_countable_income.py b/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_countable_income.py index ed5a210f36b..14d153a3cc6 100644 --- a/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_countable_income.py +++ b/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_countable_income.py @@ -11,7 +11,9 @@ class ak_hap_countable_income(Variable): "http://dpaweb.hss.state.ak.us/manuals/HAP/3003/3003-1_countable_income.htm", "http://dpaweb.hss.state.ak.us/manuals/HAP/3003/3003-2_noncountable_(exempt)_income.htm", "http://dpaweb.hss.state.ak.us/manuals/HAP/3003/3003-4_income_from_self-employment.htm", + "http://dpaweb.hss.state.ak.us/manuals/HAP/3003/3003-5_military_pay.htm", "http://dpaweb.hss.state.ak.us/manuals/HAP/3003/3003-6_guidelines_for_computing_income.htm", + "https://www.akleg.gov/basis/aac.asp?media=print&secStart=7.44.010&secEnd=7.44.9001", ) defined_for = StateCode.AK @@ -32,15 +34,15 @@ def formula(spm_unit, period, parameters): & person("is_tax_unit_dependent", period) & school ) - # Supplied net business income approximates gross receipts less - # allowable current costs. Do not deduct the 50% expense standard again. - # Each source is floored at zero, so a business loss does not offset - # wages or other income. Prior-period losses, disallowed tax expenses - # and multiple businesses within a source cannot be separated. - # Partnership/S-corp metadata is broader than policy net income; no - # expense reconstruction is imputed. - earned = max_(person("employment_income", period), 0) - for source in p.business_sources: + # Supplied net business income stands in for gross receipts less + # costs. Manual 3003-4 B deducts 50% of gross unless actual costs are + # higher, so net inputs overstate countable income when actual costs + # are under half of gross. Each source is floored at zero, so a + # business loss does not offset wages or other income. Prior-period + # losses, disallowed tax expenses and multiple businesses within a + # source cannot be separated. + earned = 0 + for source in p.earned_sources: earned = earned + max_(person(source, period), 0) countable_earned = spm_unit.sum(where(exempt_child, 0, earned)) # These are cash receipts, so a tax loss in an unearned source does not @@ -55,21 +57,21 @@ def formula(spm_unit, period, parameters): ) gifts = person("financial_assistance", period) # Existing outside cash support approximates gifts received at a - # constant monthly rate. The manual excludes strictly under $20 per - # person per month; annual data cannot identify irregular receipt dates. + # constant monthly rate. 7 AAC 44.042(16) exempts gifts that do not + # exceed $20 per person per month, and manual 3003-1 B.6.r counts + # gifts over $20; annual data cannot identify irregular receipt dates. countable_gifts = spm_unit.sum( - where(gifts / MONTHS_IN_YEAR < p.gift_exemption_threshold, 0, gifts) + where(gifts / MONTHS_IN_YEAR <= p.gift_exemption_threshold, 0, gifts) ) # Reported support represents retained receipts; assignment/payment # routes are unavailable, so no ATAP pass-through cap is imputed. # Gross SSA includes Medicare withholding. No general medical, care, # support-paid or earned-income deduction is authorized by these rules. # Count the takeup-sensitive ATAP receipt once per SPM unit. - total = ( + return ( countable_earned + unearned + rental + countable_gifts + spm_unit("tanf", period) ) - return max_(total, 0) diff --git a/source_conflicts/candidates.yaml b/source_conflicts/candidates.yaml index 713b72070e1..955b0a8757f 100644 --- a/source_conflicts/candidates.yaml +++ b/source_conflicts/candidates.yaml @@ -11,39 +11,210 @@ # unreviewed. version: 1 candidates: +- id: us-ak:hap-general-relief-assistance + program: liheap + years: + from: 2027 + to: 2027 + type: federal-fiscal + question: Does Alaska count general assistance paid directly to a household as heating assistance income, although + 7 AAC 44.042(18) exempts General Relief Assistance payments? + sources: + - kind: regulation + citation: 7 AAC 44.042(18) + url: https://www.akleg.gov/basis/aac.asp?media=print&secStart=7.44.010&secEnd=7.44.9001 + - kind: plan + citation: FY2026 Alaska LIHEAP State Plan 1.9 + url: https://liheapch.acf.gov/docs/2026/state-plans/AK_Plan_2026.pdf#page=7 + - kind: manual + citation: Alaska HAP Manual 3003-1 B.6.o and 3003-2 A.19 + url: null + readings: + statute: No statute is supplied; 7 AAC 44.042(18) excludes payments received under 7 AAC 38.030 (General Relief + Assistance) from gross monthly income. + other: Plan 1.9 counts "General Assistance and Borough of Indian Affairs (BIA) General Assistance benefits if paid + directly to the household"; manual 3003-1 B.6.o counts BIA General Assistance payments made to the household, + and 3003-2 A.19 exempts only General Relief Assistance payments made to a vendor. + pe_us: + follows: conflicting-source + code: + - policyengine_us/parameters/gov/states/ak/dpa/hap/income/unearned_sources.yaml + prs: + - https://github.com/PolicyEngine/policyengine-us/pull/10341 + state: open + note: The general_assistance input cannot tell State General Relief Assistance from BIA General Assistance, and + the code counts it in full. The manual is served only over http, at + http://dpaweb.hss.state.ak.us/manuals/HAP/3003/3003-1_countable_income.htm. +- id: us-ak:hap-income-limit-rounding + program: liheap + years: + from: 2027 + to: 2027 + type: federal-fiscal + question: Are Alaska's heating assistance income limits exact percentages of the monthly Alaska poverty guideline, + or Addendum E's amounts, which round the monthly guideline and then each percentage down to whole dollars? + sources: + - kind: regulation + citation: 7 AAC 44.040(a)(4) and 44.080(i) + url: https://www.akleg.gov/basis/aac.asp?media=print&secStart=7.44.010&secEnd=7.44.9001 + - kind: manual + citation: Alaska HAP Manual Addendum E, FFY 2027 AK Federal Poverty Income Guidelines + url: null + readings: + statute: No statute is supplied; 7 AAC 44.040(a)(4) and 44.080(i) compare gross monthly income with exact + percentages of the Alaska poverty level. + other: Addendum E floors the monthly guideline and then each percentage ("All dollars rounded down to guarantee + they are below income guidelines"), which puts 23 of its 108 limits for the six LIHEAP income factors $1 below + the exact percentage. + example: For four people, 150% of the FY2027 monthly guideline of $3,437.50 is $5,156.25, but Addendum E and the + PR use $5,155, so a household with $5,156 of monthly income is ineligible in the PR. + pe_us: + follows: conflicting-source + code: + - policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_income_factor.py + prs: + - https://github.com/PolicyEngine/policyengine-us/pull/10341 + state: open + note: The manual is served only over http, at http://dpaweb.hss.state.ak.us/manuals/HAP/addendum/addendum_e.htm. +- id: us-ak:hap-loring-oil-points + program: liheap + years: + from: 2027 + to: 2027 + type: federal-fiscal + question: Does Loring receive 4 oil heating cost points, as in the FY2027 Addendum A, or 5, as in Appendix A to + 7 AAC 44? + sources: + - kind: regulation + citation: 7 AAC 44.080(a) and Appendix A to 7 AAC 44, item (170) Loring + url: https://www.akleg.gov/basis/aac.asp?media=print&secStart=7.44.010&secEnd=7.44.9001 + - kind: manual + citation: Alaska HAP Manual Addendum A, FFY2027 Community Listing, 99901 Loring + url: null + readings: + statute: No statute is supplied; 7 AAC 44.080(a) assigns the community heating cost points listed in Appendix + A, which gives Loring 5 oil points. + other: Addendum A gives Loring 4 oil points ("99901 Loring/04/00/"). + example: A Loring adult aged 40 with no income, a two-bedroom house and an oil bill receives 4 points, $700, in the + PR; Appendix A's 5 points would pay $875. + pe_us: + follows: conflicting-source + code: + - policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/community_points/oil.yaml + prs: + - https://github.com/PolicyEngine/policyengine-us/pull/10341 + state: open + note: Tetlin also differs (Addendum A 12, Appendix A 16), but its residents are routed to their tribal program, so + that difference does not change results. The manual is served only over http, at + http://dpaweb.hss.state.ak.us/manuals/HAP/addendum/addendum_a.htm. +- id: us-ak:hap-one-person-lowest-income-limit + program: liheap + years: + from: 2027 + to: 2027 + type: federal-fiscal + question: Is the FY2027 one-person income ceiling for Alaska's 100% heating point factor $415, from 25% of the + Alaska poverty guideline, or the $407 printed in Addendum E? + sources: + - kind: regulation + citation: 7 AAC 44.080(i)(1) + url: https://www.akleg.gov/basis/aac.asp?media=print&secStart=7.44.010&secEnd=7.44.9001 + - kind: manual + citation: Alaska HAP Manual Addendum E, FFY 2027 AK Federal Poverty Income Guidelines, one person, 0% - 25% + url: null + readings: + statute: No statute is supplied; 7 AAC 44.080(i)(1) assigns 100% of points when gross monthly income is no more + than 25% of the Alaska poverty level, which for one person is 25% of $1,662.50 ($19,950 / 12), or $415.63. + other: Addendum E prints $407, which is 25% of the prior year's floored monthly guideline ($19,550 / 12, floored + to $1,629); its other 161 cells use the 2026 guideline. + example: A one-person household with $410 of monthly income receives the 1.0 income factor in the PR and would + receive 0.9 under Addendum E's $407. + pe_us: + follows: statute + code: + - policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_income_factor.py + prs: + - https://github.com/PolicyEngine/policyengine-us/pull/10341 + state: unreviewed + note: The code uses $415, the 25% rule with the same whole-dollar floors Addendum E applies to every other cell + (see us-ak:hap-income-limit-rounding). The manual is served only over http, at + http://dpaweb.hss.state.ak.us/manuals/HAP/addendum/addendum_e.htm. - id: us-ak:hap-shared-household-allocation program: liheap years: from: 2027 to: 2027 type: federal-fiscal - question: Does Alaska split a shared dwelling's heating award equally among its eligible households or by each - household's actual share of the heating cost? + question: Does Alaska reduce a sharing household's heating assistance to its share of the dwelling's heating cost at + the heating-point stage, or divide each dollar award equally among the dwelling's eligible households? sources: - kind: regulation - citation: 7 AAC 44.035(c) and 44.080(h) + citation: 7 AAC 44.080(h) and 44.035(c) url: https://www.akleg.gov/basis/aac.asp?media=print&secStart=7.44.010&secEnd=7.44.9001 - kind: manual citation: Alaska HAP Manual 3002-1 A.3 and A.5, Multiple Households Residing in the Same Dwelling and Housing Percent Share url: null readings: - statute: No statute is supplied; 7 AAC 44.035(c) pays each household the percentage of its sole-household award - equal to the percentage of the dwelling's heating cost it actually pays, and 44.080(h) reduces its points to - that proportionate share. - other: The manual divides each award by the number of eligible households in the dwelling, never pays a sharer - more than 50% and disregards what each household contributes to heat or rent. + statute: No statute is supplied; 7 AAC 44.080(h) reduces each sharing household's heating cost points under + (a)-(g) to its proportionate share of the home heating expenses, before the income factor (i), the vulnerable + point (k), the 2.0-point minimum (m) and the rounding (n). + other: The manual divides each household's dollar award by the number of eligible households in the dwelling, + never pays a sharer more than 50%, disregards what each household contributes to heat or rent, and adds the + vulnerable point before the share. example: Two eligible Fairbanks households paying 25% and 75% of the heating bills, with sole-household awards of - $1,925 and $1,050, receive $962.50 and $525 in the PR; 7 AAC 44.035(c) would pay $481.25 and $787.50. + $1,925 and $1,050, receive $700 (3.5 points, rounded to 4) and $875 (4.5 points, rounded to 5) under 7 AAC + 44.080(h), $962.50 and $525 under the manual, and $481.25 and $787.50 under 7 AAC 44.035(c). pe_us: - follows: conflicting-source - code: [] + follows: statute + code: + - policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap.py + - policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_base_benefit.py + - policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/maximum_shared_household_share.yaml prs: - https://github.com/PolicyEngine/policyengine-us/pull/10341 state: unreviewed - note: 'Same id as the entry proposed in draft rulespec-us PR 1846; delete this candidate when that entry registers. - The manual is served only over http, at http://dpaweb.hss.state.ak.us/manuals/HAP/3002/3002-1_households.htm. - Code not yet on main: ak_hap, gov.states.ak.dpa.hap.benefit.maximum_shared_household_share.' + note: The code follows 7 AAC 44.080(h). 7 AAC 44.035(c) is a second regulatory reading, which pays each household + the percentage of its sole-household dollar award equal to its share of the dwelling's heating cost. When no + household in the dwelling reports a heating expense, as with heat included in rent, the code fills the gap with + the manual's equal split among eligible households, at most 50% each. Draft rulespec-us PR 1846 proposed this id + with the manual reading. The manual is served only over http, at + http://dpaweb.hss.state.ak.us/manuals/HAP/3002/3002-1_households.htm. +- id: us-ak:hap-student-earnings-exemption + program: liheap + years: + from: 2027 + to: 2027 + type: federal-fiscal + question: Are a student's wages exempt from Alaska heating assistance income when the student is under 18, attends + school full time and is not the head of household, or when the student is under 18, under parental control and + enrolled at least half time in elementary or secondary school? + sources: + - kind: regulation + citation: 7 AAC 44.042(5) + url: https://www.akleg.gov/basis/aac.asp?media=print&secStart=7.44.010&secEnd=7.44.9001 + - kind: manual + citation: Alaska HAP Manual 3003-2 A.15, Earnings of Elementary and Secondary Students Under Age 18 + url: null + readings: + statute: No statute is supplied; 7 AAC 44.042(5) exempts "wages received by a full-time student under 18 years + of age who is not the head of household". + other: The manual exempts the earned income of a student under 18 who lives with, or is under the parental + control of, an adult household member and is enrolled at least half time in elementary or secondary school, + including during school breaks. + example: A 16-year-old dependent enrolled half time in high school has wages exempt in the PR; under 7 AAC + 44.042(5) they count, because the student does not attend full time. + pe_us: + follows: conflicting-source + code: + - policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_countable_income.py + - policyengine_us/parameters/gov/states/ak/dpa/hap/income/child_earnings_age_limit.yaml + prs: + - https://github.com/PolicyEngine/policyengine-us/pull/10341 + state: open + note: The model's school inputs do not record full-time or half-time enrollment; the code approximates the + manual's test with tax dependency and K-12 or secondary school attendance. The manual is served only over http, + at http://dpaweb.hss.state.ak.us/manuals/HAP/3003/3003-2_noncountable_(exempt)_income.htm. - id: us-ak:hap-utility-allowance-order program: liheap years: @@ -60,23 +231,27 @@ candidates: citation: Alaska HAP Manual 3004-5, Grant Computation, Step 8 url: null readings: - statute: No statute is supplied; the regulation halves the heating cost points before the 2.0-point minimum and - the rounding to whole points. + statute: No statute is supplied; 7 AAC 44.080(l) halves the heating cost points determined under (a)-(k), and + (m) and (n) then apply the 2.0-point minimum and the rounding to whole points. other: The manual applies the 2.0-point minimum, rounding, the 35-point cap and the benefit rate first, then - halves the dollar award. - example: A one-person Juneau household with 3.0 points, direct oil bills and a utility allowance receives $262.50 - ($525 halved) in the PR; under 7 AAC 44.080(l)-(m) its points halve to 1.5, below the 2.0 minimum, so it - receives $0. + halves the dollar award in step 8. + example: A one-person Juneau household with 3.0 points, direct oil bills and a utility allowance has its points + halved to 1.5 under 7 AAC 44.080(l)-(m), below the 2.0 minimum, so it receives $0; the manual pays $262.50 ($525 + halved). pe_us: - follows: conflicting-source - code: [] + follows: statute + code: + - policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap.py + - policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_base_benefit.py + - policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/utility_allowance_reduction.yaml prs: - https://github.com/PolicyEngine/policyengine-us/pull/10341 state: unreviewed - note: 'Draft rulespec-us PR 1846 covers only the shared-household allocation; register this order separately or - extend that entry. The manual is served only over http, at - http://dpaweb.hss.state.ak.us/manuals/HAP/3004/3004-5_grant_computation.htm. Code not yet on main: ak_hap, - gov.states.ak.dpa.hap.benefit.utility_allowance_reduction.' + note: The code follows 7 AAC 44.080(l)-(n). It infers the allowance for subsidized households that pay heat + directly, because HUD sets a utility allowance for tenant-paid utilities (24 CFR 965.502(a) and 982.517(a)(1)). + The manual's step 8 example 1 halves a $700 award to $350, where the regulation's order gives 1.95 points and no + award. The manual is served only over http, at + http://dpaweb.hss.state.ak.us/manuals/HAP/3004/3004-5_grant_computation.htm. - id: us-ak:snap-abawd-implementation-date program: snap years: From 39532312d185493306504def4bfe0df178bf86c1 Mon Sep 17 00:00:00 2001 From: Ziming Date: Wed, 28 Oct 2026 10:42:03 -0400 Subject: [PATCH 14/16] Address second review of Alaska HAP Follow 7 AAC 44 where the manual differs: Appendix A oil points for Loring and Tetlin, exact poverty-guideline percentages for the income limits, General Relief Assistance exempt, and only wages exempt for full-time students under 18 who do not head the household. Give a heat-in-rent household sharing a dwelling with bill payers the equal share, exclude residents of military-base places, assign four places by Addendum A ZIP code, and restate test comments as source readings. Co-Authored-By: Claude Opus 5.5 --- .../dpa/hap/benefit/community_points/oil.yaml | 35 ++-- .../maximum_shared_household_share.yaml | 13 +- .../dpa/hap/benefit/military_base_places.yaml | 22 ++ .../hap/benefit/tribal_service_places.yaml | 9 +- .../hap/income/child_earnings_age_limit.yaml | 6 +- .../ak/dpa/hap/income/unearned_sources.yaml | 11 +- .../ak/dpa/hap/income_factor/factors.yaml | 2 + .../ak/dpa/hap/income_factor/fpg_rates.yaml | 2 + .../gov/states/ak/dpa/hap/ak_hap.yaml | 88 ++++++-- .../ak/dpa/hap/ak_hap_base_benefit.yaml | 188 ++++++++++++++---- .../ak/dpa/hap/ak_hap_countable_income.yaml | 155 ++++++++++++--- .../ak/dpa/hap/ak_hap_income_factor.yaml | 110 ++++++---- .../variables/gov/states/ak/dpa/hap/ak_hap.py | 32 ++- .../states/ak/dpa/hap/ak_hap_base_benefit.py | 4 + .../ak/dpa/hap/ak_hap_countable_income.py | 23 ++- .../states/ak/dpa/hap/ak_hap_income_factor.py | 16 +- source_conflicts/candidates.yaml | 75 ++++--- 17 files changed, 588 insertions(+), 203 deletions(-) create mode 100644 policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/military_base_places.yaml diff --git a/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/community_points/oil.yaml b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/community_points/oil.yaml index 704c671c9e1..615d6dd93f6 100644 --- a/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/community_points/oil.yaml +++ b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/community_points/oil.yaml @@ -1,13 +1,16 @@ description: Alaska assigns these oil heating points by Census place under the Heating Assistance Program. -# Derived place crosswalk: 279 direct Addendum A matches and 76 nearest-community -# approximations. Direct matches include spelling variants such as Adak -# (Station), Chenega Bay, Kalskag (lower/upper), Eilson AFB, Harding Lake and -# Saint for St., and give the Anchorage municipality the Anchorage value of 8 -# (Chugiak, listed at 7, lies inside it). Every other place takes the points of -# the nearest listed oil community by great-circle distance between Census -# internal points. This is not a state-issued crosswalk. FY2027 Addendum A lists -# Loring at 4 and Tetlin at 12; the 7 AAC 44.080(a) Appendix A lists 5 and 16. -# This table uses the FY2027 Addendum A values. +# Derived place crosswalk: 279 direct Addendum A matches, 4 ZIP-code +# assignments and 72 nearest-community approximations. Direct matches include +# spelling variants such as Adak (Station), Chenega Bay, Kalskag (lower/upper), +# Eilson AFB, Harding Lake and Saint for St., and give the Anchorage +# municipality the Anchorage value of 8 (Chugiak, listed at 7, lies inside it). +# Four places take the community Addendum A lists for their ZIP code: Chena +# Ridge and Goldstream (ZIP 99709, College, 10) and Covenant Life and Mosquito +# Lake (ZIP 99827, Haines, 6). Every other place takes the points of the +# nearest listed oil community by great-circle distance between Census internal +# points. This is not a state-issued crosswalk. Values follow the FY2027 +# Addendum A, except Loring (5) and Tetlin (16), which follow Appendix A to +# 7 AAC 44 under 7 AAC 44.080(a); Addendum A lists them at 4 and 12. "00065": # Adak city 2026-10-01: 6 "00650": # Akhiok city @@ -93,7 +96,7 @@ description: Alaska assigns these oil heating points by Census place under the H "12680": # Chefornak city 2026-10-01: 20 "12920": # Chena Ridge CDP - 2026-10-01: 11 + 2026-10-01: 10 "12970": # Chenega CDP 2026-10-01: 8 "13230": # Chevak city @@ -141,7 +144,7 @@ description: Alaska assigns these oil heating points by Census place under the H "17410": # Cordova city 2026-10-01: 7 "17670": # Covenant Life CDP - 2026-10-01: 8 + 2026-10-01: 6 "17740": # Craig city 2026-10-01: 5 "17850": # Crooked Creek CDP @@ -241,7 +244,7 @@ description: Alaska assigns these oil heating points by Census place under the H "28740": # Glennallen CDP 2026-10-01: 11 "29130": # Goldstream CDP - 2026-10-01: 11 + 2026-10-01: 10 "29180": # Golovin city 2026-10-01: 26 "29290": # Goodnews Bay city @@ -379,7 +382,7 @@ description: Alaska assigns these oil heating points by Census place under the H "44580": # Livengood CDP 2026-10-01: 14 "45020": # Loring CDP - 2026-10-01: 4 + 2026-10-01: 5 "45295": # Lowell Point CDP 2026-10-01: 6 "45460": # Lower Kalskag city @@ -417,7 +420,7 @@ description: Alaska assigns these oil heating points by Census place under the H "50190": # Moose Pass CDP 2026-10-01: 6 "50800": # Mosquito Lake CDP - 2026-10-01: 8 + 2026-10-01: 6 "51180": # Mountain Village city 2026-10-01: 25 "51455": # Mud Bay CDP @@ -650,7 +653,7 @@ description: Alaska assigns these oil heating points by Census place under the H "76260": # Tenakee Springs city 2026-10-01: 7 "76590": # Tetlin CDP - 2026-10-01: 12 + 2026-10-01: 16 "77140": # Thorne Bay city 2026-10-01: 5 "77690": # Togiak city @@ -727,6 +730,8 @@ metadata: period: year label: Alaska HAP oil community heating points reference: + - title: 7 AAC 44.080(a) and Appendix A to 7 AAC 44 + href: https://www.akleg.gov/basis/aac.asp?media=print&secStart=7.44.010&secEnd=7.44.9001 - title: Alaska HAP Manual Addendum A, FFY2027 Community Listing href: http://dpaweb.hss.state.ak.us/manuals/HAP/addendum/addendum_a.htm - title: Census 2025 Alaska Places Gazetteer diff --git a/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/maximum_shared_household_share.yaml b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/maximum_shared_household_share.yaml index 1db864cf3f6..8ddbd36f9fd 100644 --- a/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/maximum_shared_household_share.yaml +++ b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/maximum_shared_household_share.yaml @@ -1,9 +1,12 @@ description: Alaska limits a household sharing its dwelling to this share of its heating points under the Heating Assistance Program. # 7 AAC 44.080(h) reduces a sharing household's points to its proportionate -# share of the dwelling's heating expenses. When no household in the dwelling -# reports a heating expense, as with heat included in rent, that share cannot -# be measured, so manual 3002-1 A.5 fills the gap: an equal share for each -# eligible household, at most this share. +# share of the dwelling's home heating expenses, which include heat paid +# through rent (7 AAC 44.900(11)). The heat portion of rent cannot be +# measured, so manual 3002-1 A.5 fills the gap: each eligible household paying +# heat through rent gets an equal share among the dwelling's eligible +# households, at most this share, and households reporting heating bills split +# the remainder in proportion to their bills. When no household reports a +# bill, each household gets the equal share. values: 2026-10-01: 0.5 @@ -14,5 +17,5 @@ metadata: reference: - title: Alaska HAP Manual 3002-1 A.5, Housing Percent Share href: http://dpaweb.hss.state.ak.us/manuals/HAP/3002/3002-1_households.htm - - title: 7 AAC 44.080(h) + - title: 7 AAC 44.080(h) and 44.900(11) href: https://www.akleg.gov/basis/aac.asp?media=print&secStart=7.44.010&secEnd=7.44.9001 diff --git a/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/military_base_places.yaml b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/military_base_places.yaml new file mode 100644 index 00000000000..472cb8b50cb --- /dev/null +++ b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/military_base_places.yaml @@ -0,0 +1,22 @@ +description: Alaska excludes residents of these military base Census places under the Heating Assistance Program. +# Census delineates Eielson AFB CDP (21370) and Fort Greely CDP (26100) from +# the installations themselves, so their residents live on base. Addendum A +# marks both installations 0/USA. Kodiak Station CDP (41210) is the housing +# area of Coast Guard Base Kodiak, and Addendum A says Coast Guard members +# living on base in provided housing do not qualify. Elmendorf AFB and Fort Richardson, also +# 0/USA, lie inside the Anchorage municipality with no separate Census place, +# so their residents cannot be identified. +values: + 2026-10-01: ["21370", "26100", "41210"] + +metadata: + unit: list + period: year + label: Alaska HAP military base places + reference: + - title: 7 AAC 44.040(b)(3)(B) + href: https://www.akleg.gov/basis/aac.asp?media=print&secStart=7.44.010&secEnd=7.44.9001 + - title: Alaska HAP Manual Addendum A, FFY2027 Community Listing and symbol key + href: http://dpaweb.hss.state.ak.us/manuals/HAP/addendum/addendum_a.htm + - title: Census 2025 Alaska Places Gazetteer + href: https://www2.census.gov/geo/docs/maps-data/data/gazetteer/2025_Gazetteer/2025_gaz_place_02.txt diff --git a/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/tribal_service_places.yaml b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/tribal_service_places.yaml index d563059dcc0..2240cbefcdd 100644 --- a/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/tribal_service_places.yaml +++ b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/tribal_service_places.yaml @@ -1,10 +1,11 @@ description: Alaska excludes all residents of these tribe-served Census places under the Heating Assistance Program. # Places whose every Addendum A row is marked 0 (the tribe serves all -# residents), except 0/USA military bases, matched by Census place name. -# Approximated places inherit their nearest community's all-resident tribal -# routing, the same proxy used for their oil points. +# residents), matched by Census place name. The 0/USA military bases are in +# military_base_places instead. Approximated places inherit the all-resident +# tribal routing of the community whose oil points they take: the community +# listed for their ZIP code, or else the nearest listed community. values: - 2026-10-01: ["00760", "00870", "01200", "01305", "01390", "01420", "01860", "03440", "03550", "03880", "03990", "04430", "05750", "06520", "06630", "07620", "11690", "11800", "12680", "13230", "13450", "13550", "13670", "13780", "14330", "14880", "15430", "16630", "17670", "17740", "18950", "19720", "19750", "20020", "20380", "20600", "21040", "21150", "21810", "22910", "23790", "26760", "26835", "27530", "27700", "29290", "30060", "32310", "32550", "33030", "33360", "33470", "33910", "34350", "34460", "34790", "35120", "35890", "36770", "37430", "37650", "37975", "39630", "39740", "40400", "40510", "41280", "41500", "41610", "41720", "42050", "42380", "42490", "42820", "43810", "44030", "45460", "45700", "46010", "46780", "46890", "47000", "47990", "48590", "48870", "49530", "50800", "51180", "52060", "52390", "52720", "53050", "53270", "53710", "53820", "53930", "54150", "55030", "56220", "56350", "56600", "56680", "58330", "60640", "60750", "60860", "61080", "62125", "62285", "63390", "64600", "64820", "64930", "65590", "65700", "66140", "67570", "67680", "68670", "71090", "72190", "73290", "74610", "75050", "75160", "76590", "77690", "78240", "78790", "79120", "79230", "79780", "80100", "81320", "82420", "84200", "85610", "86490"] + 2026-10-01: ["00760", "00870", "01200", "01305", "01390", "01420", "01860", "03440", "03550", "03880", "03990", "04430", "05750", "06520", "06630", "07620", "11690", "11800", "12680", "13230", "13450", "13550", "13670", "13780", "14330", "14880", "15430", "16630", "17740", "18950", "19720", "19750", "20020", "20380", "20600", "21040", "21150", "21810", "22910", "23790", "26760", "26835", "27530", "27700", "29290", "30060", "32310", "32550", "33030", "33360", "33470", "33910", "34350", "34460", "34790", "35120", "35890", "36770", "37430", "37650", "37975", "39630", "39740", "40400", "40510", "41280", "41500", "41610", "41720", "42050", "42380", "42490", "42820", "43810", "44030", "45460", "45700", "46010", "46780", "46890", "47000", "47990", "48590", "48870", "49530", "51180", "52060", "52390", "52720", "53050", "53270", "53710", "53820", "53930", "54150", "55030", "56220", "56350", "56600", "56680", "58330", "60640", "60750", "60860", "61080", "62125", "62285", "63390", "64600", "64820", "64930", "65590", "65700", "66140", "67570", "67680", "68670", "71090", "72190", "73290", "74610", "75050", "75160", "76590", "77690", "78240", "78790", "79120", "79230", "79780", "80100", "81320", "82420", "84200", "85610", "86490"] metadata: unit: list diff --git a/policyengine_us/parameters/gov/states/ak/dpa/hap/income/child_earnings_age_limit.yaml b/policyengine_us/parameters/gov/states/ak/dpa/hap/income/child_earnings_age_limit.yaml index 73fb81677ef..f9d5768d906 100644 --- a/policyengine_us/parameters/gov/states/ak/dpa/hap/income/child_earnings_age_limit.yaml +++ b/policyengine_us/parameters/gov/states/ak/dpa/hap/income/child_earnings_age_limit.yaml @@ -1,11 +1,13 @@ -description: Alaska excludes earnings of qualifying dependent students below this age under the Heating Assistance Program. +description: Alaska excludes wages of full-time students below this age under the Heating Assistance Program. values: 2026-10-01: 18 metadata: unit: year period: year - label: Alaska HAP child earnings exclusion age limit + label: Alaska HAP student earnings exclusion age limit reference: + - title: 7 AAC 44.042(5) + href: https://www.akleg.gov/basis/aac.asp?media=print&secStart=7.44.010&secEnd=7.44.9001 - title: Alaska HAP Manual 3003-2 A(15), Earnings of Elementary and Secondary Students Under Age 18 href: http://dpaweb.hss.state.ak.us/manuals/HAP/3003/3003-2_noncountable_(exempt)_income.htm diff --git a/policyengine_us/parameters/gov/states/ak/dpa/hap/income/unearned_sources.yaml b/policyengine_us/parameters/gov/states/ak/dpa/hap/income/unearned_sources.yaml index 42b3320e48a..fa4e6c44ed0 100644 --- a/policyengine_us/parameters/gov/states/ak/dpa/hap/income/unearned_sources.yaml +++ b/policyengine_us/parameters/gov/states/ak/dpa/hap/income/unearned_sources.yaml @@ -13,7 +13,6 @@ values: - disability_benefits - total_unemployment_compensation - workers_compensation - - general_assistance - strike_benefits - alimony_income - child_support_received @@ -24,9 +23,11 @@ values: - gambling_winnings # ATAP is added once separately. ak_ssp is Alaska Adult Public Assistance, -# distinct from exempt Senior Benefits. General assistance approximates other -# cash public assistance, not exempt vendor-paid relief. PFD, Senior Benefits, SNAP, -# in-kind/vendor benefits, tax refunds and balances are excluded. +# distinct from exempt Senior Benefits. general_assistance stands for State +# General Relief Assistance (7 AAC 38.030), which 7 AAC 44.042(18) exempts, so +# it is not listed. BIA General Assistance paid to the household counts under +# plan 1.9 and manual 3003-1 B.6.o but has no separate input. PFD, Senior +# Benefits, SNAP, in-kind/vendor benefits, tax refunds and balances are excluded. # Broad VA/compensation inputs lack exempt-subtype detail. Generic dividends # cannot identify fully exempt ANCSA payments. Estate income excludes separately # reported interest/dividends/capital gains, avoiding component duplication. @@ -40,6 +41,8 @@ metadata: period: year label: Alaska HAP ordinary unearned income sources reference: + - title: 7 AAC 44.042 + href: https://www.akleg.gov/basis/aac.asp?media=print&secStart=7.44.010&secEnd=7.44.9001 - title: Alaska HAP Manual 3003-1 B, Countable Unearned Income href: http://dpaweb.hss.state.ak.us/manuals/HAP/3003/3003-1_countable_income.htm - title: Alaska HAP Manual 3003-2 A, Non-countable Income diff --git a/policyengine_us/parameters/gov/states/ak/dpa/hap/income_factor/factors.yaml b/policyengine_us/parameters/gov/states/ak/dpa/hap/income_factor/factors.yaml index 12fb8323e54..2250ea38f01 100644 --- a/policyengine_us/parameters/gov/states/ak/dpa/hap/income_factor/factors.yaml +++ b/policyengine_us/parameters/gov/states/ak/dpa/hap/income_factor/factors.yaml @@ -7,5 +7,7 @@ metadata: period: year label: Alaska HAP income band point factors reference: + - title: 7 AAC 44.080(i) + href: https://www.akleg.gov/basis/aac.asp?media=print&secStart=7.44.010&secEnd=7.44.9001 - title: Alaska HAP Manual 3004-5, Grant Computation href: http://dpaweb.hss.state.ak.us/manuals/HAP/3004/3004-5_grant_computation.htm diff --git a/policyengine_us/parameters/gov/states/ak/dpa/hap/income_factor/fpg_rates.yaml b/policyengine_us/parameters/gov/states/ak/dpa/hap/income_factor/fpg_rates.yaml index d92c3f4d9f3..a612ed59839 100644 --- a/policyengine_us/parameters/gov/states/ak/dpa/hap/income_factor/fpg_rates.yaml +++ b/policyengine_us/parameters/gov/states/ak/dpa/hap/income_factor/fpg_rates.yaml @@ -7,5 +7,7 @@ metadata: period: year label: Alaska HAP income band upper FPG rates reference: + - title: 7 AAC 44.040(a)(4) and 44.080(i) + href: https://www.akleg.gov/basis/aac.asp?media=print&secStart=7.44.010&secEnd=7.44.9001 - title: Alaska HAP Manual 3004-5, Grant Computation href: http://dpaweb.hss.state.ak.us/manuals/HAP/3004/3004-5_grant_computation.htm diff --git a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap.yaml b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap.yaml index 81f91d0b578..17dd1a6cd0c 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap.yaml @@ -4,7 +4,10 @@ # allowance (l), then the 2.0-point minimum (m), half-up rounding (n) and the # 35-point cap (o). When no household in the dwelling reports a heating # expense, as with heat in rent, manual 3002-1 A.5 gives each eligible -# household an equal share of at most one half. Subsidized households that +# household an equal share of at most one half. When some households report +# bills, each eligible heat-in-rent household takes that equal share and the +# bill payers split the rest in proportion to their bills (7 AAC 44.900(11) +# counts heat paid through rent). Subsidized households that # pay heat directly receive a HUD utility allowance for tenant-paid utilities. # SPM units approximate separate economic households within one dwelling. # Sources, each URL listed once: @@ -184,7 +187,7 @@ # Heat is included in every unit's unsubsidized rent, so manual 3002-1 A.5 # divides among eligible units only, at most one half each. Fairbanks oil 10, # two-bedroom house 1. Income of 36,000 exceeds the one-person 150% ceiling of -# 29,916, so those units have factor 0 and no base. Household 1 has one +# 29,925, so those units have factor 0 and no base. Household 1 has one # eligible unit: min(1 / 1, .5) = .5, so 10 * .5 = 5 points = 875. Household # 2 has two: .5 each, so 875 and 10 * .5 * .6 = 3 points = 525 for 24,000 # income. Household 3 has none. @@ -605,7 +608,7 @@ ak_hap: [4_375, 2_100] # Fairbanks oil 10 * two-bedroom house 1. The retiree's $36,000 military -# retirement pay is above the one-person 150% ceiling of 2,493 * 12 = 29,916, +# retirement pay is above the one-person 150% ceiling of 19,950 * 1.5 = 29,925, # so factor 0 and base 0; pension and veterans inputs do not count it again. # Each unit pays 3,000 of the dwelling's 9,000, so each zero-income neighbor # gets a one-third share: 10 / 3 = 3.33 -> 3 points = 525. @@ -661,9 +664,8 @@ # Two Fairbanks units of a parent and a 10-year-old child, each with a $3,000 # oil bill. The unit that does not take up ATAP counts no income: factor 1, # 10 * 175 = 1,750. The other counts its modeled 9,852 ATAP receipt. The -# two-person guideline floor(27,050 / 12) = 2,254 a month gives a 25% ceiling -# of floor(563.5) * 12 = 6,756 and a 50% ceiling of 1,127 * 12 = 13,524, so -# factor 0.9: 10 * 0.9 = 9 points * 175 = 1,575. +# two-person guideline of 27,050 gives a 25% ceiling of 6,762.50 and a 50% +# ceiling of 13,525, so factor 0.9: 10 * 0.9 = 9 points * 175 = 1,575. - name: Case 11, only received ATAP reduces the regular heating award. period: 2027 absolute_error_margin: 0.01 @@ -712,8 +714,8 @@ ak_hap_income_factor: [1, 0.9] ak_hap: [1_750, 1_575] -# Juneau oil 5 * two-bedroom house 1. One-person annual ceilings: 50% 9,972, -# 75% 14,952, 100% 19,944, 125% 24,924 and 150% 29,916. Income 12,000 gives +# Juneau oil 5 * two-bedroom house 1. One-person annual ceilings: 50% 9,975, +# 75% 14,962.50, 100% 19,950, 125% 24,937.50 and 150% 29,925. Income 12,000 gives # factor 0.8: 5 * 0.8 = 4 points -> 700. Income 18,000 gives 0.7: 3.5 points # round half up to 4 -> 700. Income 25,000 gives 0.5: 2.5 points, at least 2, # round half up to 3 -> 525. @@ -862,9 +864,9 @@ # Manual 3003-1 B.6.c counts annuities, pensions and retirement benefits, and # Manual 3003-2 does not exempt a military survivor annuity. An $18,000 # Survivor Benefit Plan annuity is $1,500 a month. One-person bands use -# floor(19,950 / 12) = 1,662 a month: the 75% ceiling is floor(1,662 * 0.75) -# = 1,246 (14,952 a year) and the 100% ceiling is 1,662 (19,944 a year), so -# factor 0.7. Fairbanks oil 10 * two-bedroom house 1 * 0.7 = 7 points, plus +# 19,950 / 12 = 1,662.50 a month: the 75% ceiling is 1,662.50 * 0.75 = +# 1,246.875 (14,962.50 a year) and the 100% ceiling is 1,662.50 (19,950 a +# year), so factor 0.7. Fairbanks oil 10 * two-bedroom house 1 * 0.7 = 7 points, plus # 1 point for age 62 = 8 points; 8 * 175 = 1,400. Leaving the annuity out # would give factor 1 and (10 + 1) * 175 = 1,925. - name: Case 14, a military survivor annuity counts as unearned income. @@ -902,8 +904,8 @@ ak_hap: 1_400 # Fairbanks oil 10 * two-bedroom house 1. Wages of 18,000 are 1,500 a month, -# above the one-person 75% ceiling of 1,246 and within the 100% ceiling of -# 1,662, so factor .7: 7 points and a 7 * 175 = 1,225 base. This voucher +# above the one-person 75% ceiling of 1,246.875 and within the 100% ceiling of +# 1,662.50, so factor .7: 7 points and a 7 * 175 = 1,225 base. This voucher # household pays its oil bill directly and receives a utility allowance, so # 44.080(l) halves the points to 3.5, which rounds half up to 4 points = 700. - name: Case 15, a subsidized Fairbanks household at factor seven tenths rounds its halved points up. @@ -940,8 +942,8 @@ ak_hap: 700 # Juneau oil 5 * two-bedroom house 1. Wages of 12,000 are 1,000 a month, -# above the one-person 50% ceiling of 831 and within the 75% ceiling of -# 1,246, so factor .8: 4 points and a 4 * 175 = 700 base. The subsidized +# above the one-person 50% ceiling of 831.25 and within the 75% ceiling of +# 1,246.875, so factor .8: 4 points and a 4 * 175 = 700 base. The subsidized # household pays its oil bill directly, so 44.080(l) halves the points to # exactly 2.0, which meets the (m) minimum: 2 * 175 = 350. - name: Case 16, a subsidized household halved to exactly two points receives the minimum award. @@ -975,3 +977,59 @@ ak_hap_income_factor: 0.8 ak_hap_base_benefit: 700 ak_hap: 350 + +# One Fairbanks dwelling (oil 10), both units in a two-bedroom house with no +# income (factor 1). Unit 1 (age 40) pays a 1,200 oil bill; unit 2 (age 65) has +# heat in its unsubsidized 6,000 rent, which passes the 200 expense test. Sole- +# household bases: 10 * 175 = 1,750 and (10 + 1) * 175 = 1,925. Both units are +# eligible, so the equal share is min(1 / 2, .5) = .5. 7 AAC 44.900(11) counts +# heat paid through rent, so the heat-in-rent unit takes that .5 and the bill +# payer gets 1,200 * (1 - .5 * 1) / 1,200 = .5. Unit 1: 10 * .5 = 5 points = +# 875. Unit 2: 10 * .5 + 1 for age 65 = 6 points = 1,050. +- name: Case 17, a heat-in-rent unit sharing a dwelling with a bill payer receives the equal share. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person2: + age: 65 + immigration_status: CITIZEN + pre_subsidy_rent: 6_000 + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: [person1] + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + fuel_oil_expense: 1_200 + ak_atap: 0 + receives_housing_assistance: false + heat_expense_included_in_rent: false + spm_unit2: + members: [person2] + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + fuel_oil_expense: 0 + ak_atap: 0 + receives_housing_assistance: false + heat_expense_included_in_rent: true + households: + household1: + members: [person1, person2] + state_code: AK + place_fips: '24230' + output: + ak_hap_household_size: [1, 1] + ak_hap_countable_income: [0, 0] + ak_hap_income_factor: [1, 1] + heating_expense: [1_200, 0] + ak_hap_base_benefit: [1_750, 1_925] + ak_hap: [875, 1_050] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_base_benefit.yaml b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_base_benefit.yaml index 407d680d6eb..92b7b4d0e3c 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_base_benefit.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_base_benefit.yaml @@ -6,9 +6,12 @@ # http://dpaweb.hss.state.ak.us/manuals/HAP/addendum/addendum_a.htm # http://dpaweb.hss.state.ak.us/manuals/HAP/3002/3002-1_households.htm # https://www.akleg.gov/basis/aac.asp?media=print&secStart=7.44.010&secEnd=7.44.9001 -# Census places not named in Addendum A take the oil and gas points of the nearest listed -# community; these approximations are not a state-issued crosswalk. -# The one-person 25% ceiling is 415 under the 25% rule; Addendum E prints 407. +# Census places not named in Addendum A take the oil and gas points of the community +# Addendum A lists for their ZIP code (four places) or else of the nearest listed +# community; these approximations are not a state-issued crosswalk. Oil points follow +# Addendum A except Loring and Tetlin, which follow Appendix A to 7 AAC 44. +# Income ceilings are exact percentages of the guideline: the one-person 25% ceiling +# is 415.625 a month (4,987.50 a year); Addendum E prints 407. # Fuel, dwelling and location are explicit; no new monetary inputs or sentinel defaults. # GRANT: 10 oil points * 1.4; minimum 2 before half-up whole-point rounding, then $175/point. @@ -341,7 +344,7 @@ output: ak_hap_base_benefit: 1_750 -# Current COMMUNITY table / adopted source crosswalk: 8 points * $175; Loring uses current 4 rather than legacy 5. +# FY2027 Addendum A community listing: 8 points * $175 = $1,400. - name: Case 12, Fairbanks gas follows the place crosswalk. period: 2027 absolute_error_margin: 0.01 @@ -371,7 +374,7 @@ output: ak_hap_base_benefit: 1_400 -# Current COMMUNITY table / adopted source crosswalk: 5 points * $175; Loring uses current 4 rather than legacy 5. +# FY2027 Addendum A community listing: 5 points * $175 = $875. - name: Case 13, Anchorage gas follows the place crosswalk. period: 2027 absolute_error_margin: 0.01 @@ -401,7 +404,7 @@ output: ak_hap_base_benefit: 875 -# Current COMMUNITY table / adopted source crosswalk: 6 points * $175; Loring uses current 4 rather than legacy 5. +# FY2027 Addendum A community listing: 6 points * $175 = $1,050. - name: Case 14, Utqiagvik renamed from Barrow gas follows the place crosswalk. period: 2027 absolute_error_margin: 0.01 @@ -431,7 +434,7 @@ output: ak_hap_base_benefit: 1_050 -# Current COMMUNITY table / adopted source crosswalk: 21 points * $175; Loring uses current 4 rather than legacy 5. +# FY2027 Addendum A community listing: 21 points * $175 = $3,675. - name: Case 15, Utqiagvik renamed from Barrow oil follows the place crosswalk. period: 2027 absolute_error_margin: 0.01 @@ -461,7 +464,7 @@ output: ak_hap_base_benefit: 3_675 -# Current COMMUNITY table / adopted source crosswalk: 5 points * $175; Loring uses current 4 rather than legacy 5. +# FY2027 Addendum A community listing: 5 points * $175 = $875. - name: Case 16, Knik Fairview gas follows the place crosswalk. period: 2027 absolute_error_margin: 0.01 @@ -491,7 +494,7 @@ output: ak_hap_base_benefit: 875 -# Current COMMUNITY table / adopted source crosswalk: 7 points * $175; Loring uses current 4 rather than legacy 5. +# FY2027 Addendum A community listing: 7 points * $175 = $1,225. - name: Case 17, Knik Fairview oil follows the place crosswalk. period: 2027 absolute_error_margin: 0.01 @@ -521,7 +524,7 @@ output: ak_hap_base_benefit: 1_225 -# Current COMMUNITY table / adopted source crosswalk: 8 points * $175; Loring uses current 4 rather than legacy 5. +# FY2027 Addendum A community listing: 8 points * $175 = $1,400. - name: Case 18, North Pole current gas follows the place crosswalk. period: 2027 absolute_error_margin: 0.01 @@ -551,7 +554,7 @@ output: ak_hap_base_benefit: 1_400 -# Current COMMUNITY table / adopted source crosswalk: 5 points * $175; Loring uses current 4 rather than legacy 5. +# FY2027 Addendum A community listing: 5 points * $175 = $875. - name: Case 19, Juneau uniform consolidated oil follows the place crosswalk. period: 2027 absolute_error_margin: 0.01 @@ -581,7 +584,7 @@ output: ak_hap_base_benefit: 875 -# Current COMMUNITY table / adopted source crosswalk: 6 points * $175; Loring uses current 4 rather than legacy 5. +# FY2027 Addendum A community listing: 6 points * $175 = $1,050. - name: Case 20, Sitka uniform consolidated oil follows the place crosswalk. period: 2027 absolute_error_margin: 0.01 @@ -611,7 +614,7 @@ output: ak_hap_base_benefit: 1_050 -# Current COMMUNITY table / adopted source crosswalk: 5 points * $175; Loring uses current 4 rather than legacy 5. +# FY2027 Addendum A community listing: 5 points * $175 = $875. - name: Case 21, Wrangell uniform consolidated oil follows the place crosswalk. period: 2027 absolute_error_margin: 0.01 @@ -641,8 +644,8 @@ output: ak_hap_base_benefit: 875 -# Current COMMUNITY table / adopted source crosswalk: 4 points * $175; Loring uses current 4 rather than legacy 5. -- name: Case 22, Loring current manual oil follows the place crosswalk. +# 7 AAC 44.080(a) sets community points by Appendix A to 7 AAC 44, which lists Loring at 5 oil points; FY2027 Addendum A lists 4. 5 points * $175 = $875. +- name: Case 22, Loring oil uses the Appendix A points of 7 AAC 44. period: 2027 absolute_error_margin: 0.01 input: @@ -669,10 +672,10 @@ state_code: AK place_fips: '45020' output: - ak_hap_base_benefit: 700 + ak_hap_base_benefit: 875 -# Research crosswalk: Ester -> Fairbanks, 8 gas points * $175; not a direct published Ester gas entry. -- name: Case 23, Ester gas uses the adopted nearest-community approximation. +# Addendum A lists no gas points for Ester; the nearest listed gas community, Fairbanks, has 8: 8 points * $175 = $1,400. +- name: Case 23, Ester gas takes the points of the nearest listed gas community. period: 2027 absolute_error_margin: 0.01 input: @@ -1317,7 +1320,7 @@ output: ak_hap_base_benefit: 0 -# One qualified adult; annual payroll 24924, no general earned disregard. Apply source band to Fairbanks 10 oil points. +# One qualified adult; annual payroll 24,937.50 = 19,950 * 1.25, the exact 125% ceiling, no general earned disregard. Factor .6: Fairbanks 10 oil points * .6 = 6 points * $175 = $1,050. - name: Case 42, integrated wages at exact 125 percent use the inclusive income boundary. period: 2027 absolute_error_margin: 0.01 @@ -1329,7 +1332,7 @@ ssi: 0 ak_ssp: 0 ak_permanent_fund_dividend: 0 - employment_income: 24_924 + employment_income: 24_937.5 spm_units: spm_unit1: members: @@ -1348,7 +1351,7 @@ output: ak_hap_base_benefit: 1_050 -# One qualified adult; annual payroll 24924.12, no general earned disregard. Apply source band to Fairbanks 10 oil points. +# One qualified adult; annual payroll 24,937.62, a cent a month above the 125% ceiling of 24,937.50. Factor .5: 10 * .5 = 5 points * $175 = $875. - name: Case 43, integrated wages at above 125 percent use the inclusive income boundary. period: 2027 absolute_error_margin: 0.01 @@ -1360,7 +1363,7 @@ ssi: 0 ak_ssp: 0 ak_permanent_fund_dividend: 0 - employment_income: 24924.12 + employment_income: 24_937.62 spm_units: spm_unit1: members: @@ -1379,7 +1382,7 @@ output: ak_hap_base_benefit: 875 -# One qualified adult; annual payroll 29916, no general earned disregard. Apply source band to Fairbanks 10 oil points. +# One qualified adult; annual payroll 29,925 = 19,950 * 1.5, the exact 150% ceiling, no general earned disregard. Factor .5: 10 * .5 = 5 points * $175 = $875. - name: Case 44, integrated wages at exact 150 percent use the inclusive income boundary. period: 2027 absolute_error_margin: 0.01 @@ -1391,7 +1394,7 @@ ssi: 0 ak_ssp: 0 ak_permanent_fund_dividend: 0 - employment_income: 29_916 + employment_income: 29_925 spm_units: spm_unit1: members: @@ -1410,7 +1413,7 @@ output: ak_hap_base_benefit: 875 -# One qualified adult; annual payroll 29916.12, no general earned disregard. Apply source band to Fairbanks 10 oil points. +# One qualified adult; annual payroll 29,925.12, a cent a month above the 150% ceiling of 29,925. Factor 0, so no award. - name: Case 45, integrated wages at above 150 percent use the inclusive income boundary. period: 2027 absolute_error_margin: 0.01 @@ -1422,7 +1425,7 @@ ssi: 0 ak_ssp: 0 ak_permanent_fund_dividend: 0 - employment_income: 29916.12 + employment_income: 29_925.12 spm_units: spm_unit1: members: @@ -1441,7 +1444,7 @@ output: ak_hap_base_benefit: 0 -# One qualified adult; annual payroll 4980, no general earned disregard. Apply source band to Fairbanks 10 oil points. +# One qualified adult; annual payroll 4,987.50 = 19,950 * .25, the exact 25% ceiling, no general earned disregard. Factor 1: 10 points * $175 = $1,750. - name: Case 46, integrated wages at the 25 percent limit use the inclusive income boundary. period: 2027 absolute_error_margin: 0.01 @@ -1453,7 +1456,7 @@ ssi: 0 ak_ssp: 0 ak_permanent_fund_dividend: 0 - employment_income: 4_980 + employment_income: 4_987.5 spm_units: spm_unit1: members: @@ -1472,7 +1475,7 @@ output: ak_hap_base_benefit: 1_750 -# One qualified adult; annual payroll 4980.12, no general earned disregard. Apply source band to Fairbanks 10 oil points. +# One qualified adult; annual payroll 4,987.62, a cent a month above the 25% ceiling of 4,987.50. Factor .9: 10 * .9 = 9 points * $175 = $1,575. - name: Case 47, integrated wages at above 25 percent use the inclusive income boundary. period: 2027 absolute_error_margin: 0.01 @@ -1484,7 +1487,7 @@ ssi: 0 ak_ssp: 0 ak_permanent_fund_dividend: 0 - employment_income: 4980.12 + employment_income: 4_987.62 spm_units: spm_unit1: members: @@ -1536,7 +1539,7 @@ ak_hap_countable_income: 0 ak_hap_income_factor: 1 -# Five qualified members, monthly 2,900 <= 75% ceiling 3,021; 27 * .8 + 1 = 22.6 -> 23 * $175. +# Five qualified members, monthly 2,900 <= 75% ceiling 3,021.875 (48,350 * .75 / 12); 27 * .8 + 1 = 22.6 -> 23 * $175. - name: Case 49, Savoonga updated five-person band supersedes stale worked label. period: 2027 absolute_error_margin: 0.0001 @@ -1851,8 +1854,8 @@ output: ak_hap_base_benefit: 1_925 -# Fort Greely 0/USA is explicitly excluded from tribal list; on-base residence is unobserved. Oil 11 * 175 under the ordinary location approximation. -- name: Case 58, USA marker is not an all-resident tribal provider. +# 7 AAC 44.040(b)(3)(B) excludes a household residing on a military base, and Addendum A marks Fort Greely 0/USA. Census draws Fort Greely CDP from the installation, so its residents receive nothing. Without the exclusion, oil 11 * 175 = 1,925. +- name: Case 58, Fort Greely CDP residents live on a military base and receive nothing. period: 2027 absolute_error_margin: 0.01 input: @@ -1879,9 +1882,9 @@ state_code: AK place_fips: '26100' output: - ak_hap_base_benefit: 1_925 + ak_hap_base_benefit: 0 -# Tetlin current 12 oil differs from legacy 16, but 0/TCC routing controls this state component. +# Appendix A to 7 AAC 44 lists Tetlin at 16 oil points and FY2027 Addendum A at 12; Addendum A's 0/TCC marker routes all residents to the tribal program, so the state award is zero at either value. - name: Case 59, Tetlin is routed to all-resident tribal program. period: 2027 absolute_error_margin: 0.01 @@ -2720,7 +2723,7 @@ output: ak_hap_base_benefit: 1_400 -# Anchorage oil 8 (Addendum A) applies to electric heat under 7 AAC 44.080(f). Social Security of 18,000 is 1,500 a month, above the one-person 75% ceiling of 1,246 and within the 100% ceiling of 1,662: factor .7. One-bedroom 8 * .55 * .7 = 3.08, plus 1 for age 70 = 4.08 -> 4 points * $175 = $700. +# Anchorage oil 8 (Addendum A) applies to electric heat under 7 AAC 44.080(f). Social Security of 18,000 is 1,500 a month, above the one-person 75% ceiling of 1,246.875 and within the 100% ceiling of 1,662.50: factor .7. One-bedroom 8 * .55 * .7 = 3.08, plus 1 for age 70 = 4.08 -> 4 points * $175 = $700. - name: Case 81, an elderly Anchorage household with electric heat receives the Anchorage oil points. period: 2027 absolute_error_margin: 0.01 @@ -2751,7 +2754,7 @@ ak_hap_income_factor: 0.7 ak_hap_base_benefit: 700 -# 7 AAC 44.042(16) exempts cash gifts that do not exceed $20 a month: 240 / 12 = 20. Wages of 14,800 are 1,233.33 a month, within the one-person 75% ceiling of 1,246: factor .8. Fairbanks oil 10 * .8 = 8 points * $175 = $1,400. Counting the gift would give 15,040 (1,253.33 a month) and factor .7. +# 7 AAC 44.042(16) exempts cash gifts that do not exceed $20 a month: 240 / 12 = 20. Wages of 14,800 are 1,233.33 a month, within the one-person 75% ceiling of 1,246.875: factor .8. Fairbanks oil 10 * .8 = 8 points * $175 = $1,400. Counting the gift would give 15,040 (1,253.33 a month) and factor .7. - name: Case 82, a twenty dollar monthly gift does not move a household into a lower income factor. period: 2027 absolute_error_margin: 0.01 @@ -2783,7 +2786,7 @@ ak_hap_income_factor: 0.8 ak_hap_base_benefit: 1_400 -# Manual 3003-1 A.1 and 3003-5 B.1.a count military basic pay as earned income. 40,000 exceeds the one-person 150% ceiling of 2,493 * 12 = 29,916: factor 0, so no award. Without the pay, Fairbanks oil 10 would give $1,750. +# Manual 3003-1 A.1 and 3003-5 B.1.a count military basic pay as earned income. 40,000 exceeds the one-person 150% ceiling of 19,950 * 1.5 = 29,925: factor 0, so no award. Without the pay, Fairbanks oil 10 would give $1,750. - name: Case 83, military basic pay counts as earned income. period: 2027 absolute_error_margin: 0.01 @@ -2869,3 +2872,112 @@ place_fips: '48590' output: ak_hap_base_benefit: 0 + +# 7 AAC 44.040(b)(3)(B) excludes a household residing on a military base. +# Addendum A marks Eielson AFB 0/USA, and Census draws Eielson AFB CDP from the +# installation. Kodiak Station CDP is the housing area of Coast Guard Base +# Kodiak, whose members living on base in provided housing do not qualify +# (Addendum A). Each member's 24,000 of basic pay is in the 100-125% band +# (19,950 < 24,000 <= 24,937.50): factor .6. Without the exclusion, Eielson +# oil 11 * 1 * .6 = 6.6 -> 7 points * $175 = $1,225, and Kodiak Station oil +# 6 * 1 * .6 = 3.6 -> 4 points * $175 = $700; on base each award is 0. +- name: Case 86, Eielson AFB CDP and Kodiak Station CDP residents live on a military base and receive nothing. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + military_basic_pay: 24_000 + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person2: + age: 30 + immigration_status: CITIZEN + military_basic_pay: 24_000 + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: [person1] + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + fuel_oil_expense: 1_500 + ak_atap: 0 + receives_housing_assistance: false + spm_unit2: + members: [person2] + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + fuel_oil_expense: 1_500 + ak_atap: 0 + receives_housing_assistance: false + households: + household1: + members: [person1] + state_code: AK + place_fips: '21370' + household2: + members: [person2] + state_code: AK + place_fips: '41210' + output: + ak_hap_countable_income: [24_000, 24_000] + ak_hap_income_factor: [0.6, 0.6] + ak_hap_base_benefit: [0, 0] + +# Addendum A lists ZIP 99709 as College (10 oil points) and ZIP 99827 as +# Haines (6 oil points, tribal service for Natives only). Most addresses in +# Chena Ridge CDP use ZIP 99709, and Covenant Life CDP uses ZIP 99827, so +# they take those communities' points; Covenant Life is not an all-resident +# tribal place. With no income the factor is 1.0 (0 <= 25% of the guideline): +# Covenant Life 6 * 1 * 1.0 = 6 points * $175 = $1,050; Chena Ridge +# 10 * 1 * 1.0 = 10 points * $175 = $1,750. +- name: Case 87, Covenant Life CDP and Chena Ridge CDP take the oil points of the community listed for their ZIP code. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person2: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: [person1] + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + fuel_oil_expense: 1_500 + ak_atap: 0 + receives_housing_assistance: false + spm_unit2: + members: [person2] + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + fuel_oil_expense: 1_500 + ak_atap: 0 + receives_housing_assistance: false + households: + household1: + members: [person1] + state_code: AK + place_fips: '17670' + household2: + members: [person2] + state_code: AK + place_fips: '12920' + output: + ak_hap_countable_income: [0, 0] + ak_hap_income_factor: [1, 1] + ak_hap_base_benefit: [1_050, 1_750] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_countable_income.yaml index f1f531ec9bc..65b97e305ce 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_countable_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_countable_income.yaml @@ -5,6 +5,7 @@ # http://dpaweb.hss.state.ak.us/manuals/HAP/3003/3003-2_noncountable_(exempt)_income.htm # http://dpaweb.hss.state.ak.us/manuals/HAP/3003/3003-4_income_from_self-employment.htm # http://dpaweb.hss.state.ak.us/manuals/HAP/3003/3003-6_guidelines_for_computing_income.htm +# https://www.akleg.gov/basis/aac.asp?media=print&secStart=7.44.010&secEnd=7.44.9001 # Annual receipts approximate the application-month rules; computed benefits are supplied. # MS 3003-1 A.1 counts gross wages before deductions or garnishments. @@ -231,8 +232,8 @@ output: ak_hap_countable_income: 24_000 -# MS 3003-2 A.15; existing dependency and school facts approximate parental control and at-least-half-time enrollment. -- name: "Case 9, dependent elementary student earnings are excluded." +# 7 AAC 44.042(5) exempts wages of a full-time student under 18 who is not the head of household; is_full_time_student treats K-12 attendance as full time, and the 40-year-old parent is the tax-unit head: 24,000 + 0 = 24,000. +- name: "Case 9, wages of a full-time elementary student who is not the head are excluded." period: 2027 absolute_error_margin: 0.01 input: @@ -252,7 +253,6 @@ ak_permanent_fund_dividend: 0 is_tax_unit_dependent: true is_in_k12_school: true - is_in_secondary_school: false employment_income: 1_200 spm_units: spm_unit1: @@ -267,8 +267,8 @@ output: ak_hap_countable_income: 24_000 -# MS 3003-2 A.15 excludes earned income under age 18; reported secondary-school attendance satisfies the available-input approximation. -- name: "Case 10, dependent secondary student wages and net business income are excluded." +# 7 AAC 44.042(5) covers any full-time student under 18, not only elementary or secondary students, and exempts only "wages". A 17-year-old full-time college student who is not the head has the 12,000 of wages excluded, but the 2,000 of net business income counts: 24,000 + 0 + 2,000 = 26,000. +- name: "Case 10, a full-time college student under 18 who is not the head has wages excluded and net business income counted." period: 2027 absolute_error_margin: 0.01 input: @@ -287,8 +287,8 @@ ak_ssp: 0 ak_permanent_fund_dividend: 0 is_tax_unit_dependent: true + is_full_time_college_student: true is_in_k12_school: false - is_in_secondary_school: true employment_income: 12_000 self_employment_income: 2_000 spm_units: @@ -302,10 +302,10 @@ members: ["person1", "person2"] state_code: "AK" output: - ak_hap_countable_income: 24_000 + ak_hap_countable_income: 26_000 -# MS 3003-2 A.15 exclusion requires age under 18. -- name: "Case 11, school attendance does not exclude earnings at age eighteen." +# 7 AAC 44.042(5) requires age under 18. This 18-year-old is a full-time high school student and not the head, so only age fails: 24,000 + 12,000 = 36,000. +- name: "Case 11, full-time school attendance does not exclude wages at age eighteen." period: 2027 absolute_error_margin: 0.01 input: @@ -324,8 +324,7 @@ ak_ssp: 0 ak_permanent_fund_dividend: 0 is_tax_unit_dependent: true - is_in_k12_school: false - is_in_secondary_school: true + is_in_k12_school: true employment_income: 12_000 spm_units: spm_unit1: @@ -340,8 +339,8 @@ output: ak_hap_countable_income: 36_000 -# MS 3003-2 A.15 requires qualifying school attendance. -- name: "Case 12, earnings of a dependent minor outside school count." +# 7 AAC 44.042(5) requires full-time student status. A 17-year-old who attends neither school nor college is not a full-time student: 24,000 + 12,000 = 36,000. +- name: "Case 12, wages of a minor who is not a full-time student count." period: 2027 absolute_error_margin: 0.01 input: @@ -361,7 +360,6 @@ ak_permanent_fund_dividend: 0 is_tax_unit_dependent: true is_in_k12_school: false - is_in_secondary_school: false employment_income: 12_000 spm_units: spm_unit1: @@ -376,8 +374,8 @@ output: ak_hap_countable_income: 36_000 -# MS 3003-6 E and the dependent-child approximation do not exclude a minor household head's earnings. -- name: "Case 13, an independent minor student has countable earnings." +# 7 AAC 44.042(5) does not exempt a head of household. This 17-year-old high school student lives alone and heads a tax unit (supplied role; age ordering infers no head when no member is an adult), so the wages of 12,000 count. +- name: "Case 13, wages of a minor student who heads a tax unit count." period: 2027 absolute_error_margin: 0.01 input: @@ -388,9 +386,8 @@ ssi: 0 ak_ssp: 0 ak_permanent_fund_dividend: 0 - is_tax_unit_dependent: false + tax_unit_role_input: "HEAD" is_in_k12_school: true - is_in_secondary_school: true employment_income: 12_000 spm_units: spm_unit1: @@ -405,7 +402,7 @@ output: ak_hap_countable_income: 12_000 -# MS 3003-1 B.2 and 3003-6 E: 24,000 + 2,400 + 600 + 1,200; school exclusion applies only to earnings. +# MS 3003-1 B.2 and 3003-6 E: 24,000 + 2,400 + 600 + 1,200; the 7 AAC 44.042(5) student exemption covers wages only. - name: "Case 14, unearned income of a dependent child remains countable." period: 2027 absolute_error_margin: 0.01 @@ -425,7 +422,7 @@ ak_ssp: 0 ak_permanent_fund_dividend: 0 is_tax_unit_dependent: true - is_in_secondary_school: true + is_in_k12_school: true social_security: 600 pension_income: 1_200 spm_units: @@ -503,8 +500,8 @@ output: ak_hap_countable_income: 5_400 -# MS 3003-1 B.2 and B.6.a,b,j,o: ordinary nonexempt cash receipts. General assistance represents cash paid to the household, not a vendor payment. -- name: "Case 17, ordinary cash assistance and compensation receipts count." +# MS 3003-1 B.2 and B.6.a,b,j: ordinary nonexempt cash receipts: 600 + 600 + 600 + 600 = 2,400. +- name: "Case 17, ordinary compensation, veterans and strike receipts count." period: 2027 absolute_error_margin: 0.01 input: @@ -519,7 +516,6 @@ workers_compensation: 600 veterans_benefits: 600 strike_benefits: 600 - general_assistance: 600 spm_units: spm_unit1: members: ["person1"] @@ -531,7 +527,7 @@ members: ["person1"] state_code: "AK" output: - ak_hap_countable_income: 3_000 + ak_hap_countable_income: 2_400 # MS 3003-1 B.6.h and B.6.n (bingo and lottery winnings); ordinary receipts have no NH-style $50 disregard. Generic dividends cannot identify exempt ANCSA payments: 120 + 240 + 120 + 600. - name: "Case 18, ordinary interest, dividends, estate payments and gambling winnings count in full." @@ -906,3 +902,114 @@ state_code: "AK" output: ak_hap_countable_income: 0 + +# 7 AAC 44.042(5): a 16-year-old in high school is a full-time student (K-12 +# attendance is full time, by default from age), and the 40-year-old parent +# is the inferred tax-unit head, so the student's 6,000 of wages are exempt: +# 24,000 + 0 = 24,000. +- name: "Case 31, wages of a 16-year-old full-time student who is not a tax-unit head are excluded." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + employment_income: 24_000 + person2: + age: 16 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + employment_income: 6_000 + spm_units: + spm_unit1: + members: ["person1", "person2"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + households: + household1: + members: ["person1", "person2"] + state_code: "AK" + output: + is_full_time_student: [false, true] + is_tax_unit_head: [true, false] + ak_hap_countable_income: 24_000 + +# The same 16-year-old full-time student heads a separate tax unit (supplied +# roles), so 7 AAC 44.042(5) does not exempt the wages: 24,000 + 6,000 = +# 30,000. Only the head role differs from Case 31. +- name: "Case 32, wages of the same 16-year-old full-time student count when the student heads a tax unit." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + tax_unit_role_input: "HEAD" + employment_income: 24_000 + person2: + age: 16 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + tax_unit_role_input: "HEAD" + employment_income: 6_000 + tax_units: + tax_unit1: + members: ["person1"] + tax_unit2: + members: ["person2"] + spm_units: + spm_unit1: + members: ["person1", "person2"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + households: + household1: + members: ["person1", "person2"] + state_code: "AK" + output: + is_full_time_student: [false, true] + is_tax_unit_head: [true, true] + ak_hap_countable_income: 30_000 + +# 7 AAC 44.042(18) exempts State General Relief Assistance (7 AAC 38.030), +# which general_assistance stands for, so the 1,200 is not counted: wages +# 10,000 + 0 = 10,000. +- name: "Case 33, general relief assistance is not countable income." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + employment_income: 10_000 + general_assistance: 1_200 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "NATURAL_GAS" + gas_expense: 1_000 + ak_atap: 0 + households: + household1: + members: ["person1"] + state_code: "AK" + output: + ak_hap_countable_income: 10_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_income_factor.yaml b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_income_factor.yaml index 6d2fc691e5e..eb08f68707f 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_income_factor.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_income_factor.yaml @@ -5,7 +5,9 @@ # http://dpaweb.hss.state.ak.us/manuals/HAP/addendum/addendum_a.htm # http://dpaweb.hss.state.ak.us/manuals/HAP/3002/3002-1_households.htm # https://www.akleg.gov/basis/aac.asp?media=print&secStart=7.44.010&secEnd=7.44.9001 -# The one-person 25% ceiling is 415 under the 25% rule; Addendum E prints 407. +# Ceilings are exact percentages of the guideline (7 AAC 44.040(a)(4) and +# 44.080(i)): one person 19,950 / 12 = 1,662.50 a month, so the 25% ceiling is +# 415.625 a month (4,987.50 a year); Addendum E prints 407. # Fuel, dwelling and location are explicit; no new monetary inputs or sentinel defaults. # GRANT Step 3: income at or below 25% receives factor 1. @@ -104,7 +106,7 @@ output: ak_hap_income_factor: 0 -# Addendum E prints 407/month; the 25% rule gives a 415 ceiling, so 407 is in the lowest band. +# Addendum E prints 407/month; the exact 25% ceiling is 415.625, so 407 is in the lowest band. - name: Case 4, printed stale 407 amount stays in the lowest band. period: 2027 absolute_error_margin: 0.0001 @@ -136,7 +138,7 @@ output: ak_hap_income_factor: 1 -# floor(1662 * .25) = 415, not the stale printed 407. +# 1,662.50 * .25 = 415.625, not the printed 407; 408 a month is below it. - name: Case 5, 408 remains below the 25 percent ceiling. period: 2027 absolute_error_margin: 0.0001 @@ -168,7 +170,7 @@ output: ak_hap_income_factor: 1 -# Addendum E grid: monthly ceiling 415 * 12 = 4980; inclusive band top. +# Exact 25% ceiling: 19,950 * .25 = 4,987.50 a year (415.625 a month); inclusive band top. - name: Case 6, exact one-person band 1 ceiling is inclusive. period: 2027 absolute_error_margin: 0.0001 @@ -189,7 +191,7 @@ ak_atap: 0 receives_housing_assistance: false fuel_oil_expense: 1_000 - ak_hap_countable_income: 4_980 + ak_hap_countable_income: 4_987.5 ak_hap_household_size: 1 households: household1: @@ -200,7 +202,7 @@ output: ak_hap_income_factor: 1 -# Annual income 4980 + .12 gives monthly 415.01; next factor 0.9. +# Annual income 4,987.50 + .12 gives monthly 415.635, a cent above 415.625; next factor 0.9. - name: Case 7, one cent monthly above band 1 enters the next band. period: 2027 absolute_error_margin: 0.0001 @@ -221,7 +223,7 @@ ak_atap: 0 receives_housing_assistance: false fuel_oil_expense: 1_000 - ak_hap_countable_income: 4980.12 + ak_hap_countable_income: 4_987.62 ak_hap_household_size: 1 households: household1: @@ -232,7 +234,7 @@ output: ak_hap_income_factor: 0.9 -# Addendum E grid: monthly ceiling 831 * 12 = 9972; inclusive band top. +# Exact 50% ceiling: 19,950 * .5 = 9,975 a year (831.25 a month); inclusive band top. - name: Case 8, exact one-person band 2 ceiling is inclusive. period: 2027 absolute_error_margin: 0.0001 @@ -253,7 +255,7 @@ ak_atap: 0 receives_housing_assistance: false fuel_oil_expense: 1_000 - ak_hap_countable_income: 9_972 + ak_hap_countable_income: 9_975 ak_hap_household_size: 1 households: household1: @@ -264,7 +266,7 @@ output: ak_hap_income_factor: 0.9 -# Annual income 9972 + .12 gives monthly 831.01; next factor 0.8. +# Annual income 9,975 + .12 gives monthly 831.26, a cent above 831.25; next factor 0.8. - name: Case 9, one cent monthly above band 2 enters the next band. period: 2027 absolute_error_margin: 0.0001 @@ -285,7 +287,7 @@ ak_atap: 0 receives_housing_assistance: false fuel_oil_expense: 1_000 - ak_hap_countable_income: 9972.12 + ak_hap_countable_income: 9_975.12 ak_hap_household_size: 1 households: household1: @@ -296,7 +298,7 @@ output: ak_hap_income_factor: 0.8 -# Addendum E grid: monthly ceiling 1246 * 12 = 14952; inclusive band top. +# Exact 75% ceiling: 19,950 * .75 = 14,962.50 a year (1,246.875 a month); inclusive band top. - name: Case 10, exact one-person band 3 ceiling is inclusive. period: 2027 absolute_error_margin: 0.0001 @@ -317,7 +319,7 @@ ak_atap: 0 receives_housing_assistance: false fuel_oil_expense: 1_000 - ak_hap_countable_income: 14_952 + ak_hap_countable_income: 14_962.5 ak_hap_household_size: 1 households: household1: @@ -328,7 +330,7 @@ output: ak_hap_income_factor: 0.8 -# Annual income 14952 + .12 gives monthly 1246.01; next factor 0.7. +# Annual income 14,962.50 + .12 gives monthly 1,246.885, a cent above 1,246.875; next factor 0.7. - name: Case 11, one cent monthly above band 3 enters the next band. period: 2027 absolute_error_margin: 0.0001 @@ -349,7 +351,7 @@ ak_atap: 0 receives_housing_assistance: false fuel_oil_expense: 1_000 - ak_hap_countable_income: 14952.12 + ak_hap_countable_income: 14_962.62 ak_hap_household_size: 1 households: household1: @@ -360,7 +362,7 @@ output: ak_hap_income_factor: 0.7 -# Addendum E grid: monthly ceiling 1662 * 12 = 19944; inclusive band top. +# Exact 100% ceiling: 19,950 a year (1,662.50 a month); inclusive band top. - name: Case 12, exact one-person band 4 ceiling is inclusive. period: 2027 absolute_error_margin: 0.0001 @@ -381,7 +383,7 @@ ak_atap: 0 receives_housing_assistance: false fuel_oil_expense: 1_000 - ak_hap_countable_income: 19_944 + ak_hap_countable_income: 19_950 ak_hap_household_size: 1 households: household1: @@ -392,7 +394,7 @@ output: ak_hap_income_factor: 0.7 -# Annual income 19944 + .12 gives monthly 1662.01; next factor 0.6. +# Annual income 19,950 + .12 gives monthly 1,662.51, a cent above 1,662.50; next factor 0.6. - name: Case 13, one cent monthly above band 4 enters the next band. period: 2027 absolute_error_margin: 0.0001 @@ -413,7 +415,7 @@ ak_atap: 0 receives_housing_assistance: false fuel_oil_expense: 1_000 - ak_hap_countable_income: 19944.12 + ak_hap_countable_income: 19_950.12 ak_hap_household_size: 1 households: household1: @@ -424,7 +426,7 @@ output: ak_hap_income_factor: 0.6 -# Addendum E grid: monthly ceiling 2077 * 12 = 24924; inclusive band top. +# Exact 125% ceiling: 19,950 * 1.25 = 24,937.50 a year (2,078.125 a month); inclusive band top. - name: Case 14, exact one-person band 5 ceiling is inclusive. period: 2027 absolute_error_margin: 0.0001 @@ -445,7 +447,7 @@ ak_atap: 0 receives_housing_assistance: false fuel_oil_expense: 1_000 - ak_hap_countable_income: 24_924 + ak_hap_countable_income: 24_937.5 ak_hap_household_size: 1 households: household1: @@ -456,7 +458,7 @@ output: ak_hap_income_factor: 0.6 -# Annual income 24924 + .12 gives monthly 2077.01; next factor 0.5. +# Annual income 24,937.50 + .12 gives monthly 2,078.135, a cent above 2,078.125; next factor 0.5. - name: Case 15, one cent monthly above band 5 enters the next band. period: 2027 absolute_error_margin: 0.0001 @@ -477,7 +479,7 @@ ak_atap: 0 receives_housing_assistance: false fuel_oil_expense: 1_000 - ak_hap_countable_income: 24924.12 + ak_hap_countable_income: 24_937.62 ak_hap_household_size: 1 households: household1: @@ -488,7 +490,7 @@ output: ak_hap_income_factor: 0.5 -# Addendum E grid: monthly ceiling 2493 * 12 = 29916; inclusive band top. +# Exact 150% ceiling: 19,950 * 1.5 = 29,925 a year (2,493.75 a month); inclusive band top. - name: Case 16, exact one-person band 6 ceiling is inclusive. period: 2027 absolute_error_margin: 0.0001 @@ -509,7 +511,7 @@ ak_atap: 0 receives_housing_assistance: false fuel_oil_expense: 1_000 - ak_hap_countable_income: 29_916 + ak_hap_countable_income: 29_925 ak_hap_household_size: 1 households: household1: @@ -520,7 +522,7 @@ output: ak_hap_income_factor: 0.5 -# Annual income 29916 + .12 gives monthly 2493.01; next factor 0. +# Annual income 29,925 + .12 gives monthly 2,493.76, a cent above 2,493.75; next factor 0. - name: Case 17, one cent monthly above band 6 enters the next band. period: 2027 absolute_error_margin: 0.0001 @@ -541,7 +543,7 @@ ak_atap: 0 receives_housing_assistance: false fuel_oil_expense: 1_000 - ak_hap_countable_income: 29916.12 + ak_hap_countable_income: 29_925.12 ak_hap_household_size: 1 households: household1: @@ -552,8 +554,8 @@ output: ak_hap_income_factor: 0 -# floor(floor(27050/12) * .25) * 12 = 563 * 12 = 6756. -- name: Case 18, two-person first ceiling uses both monthly floors. +# Two-person guideline 19,950 + 7,100 = 27,050; 27,050 * .25 = 6,762.50 a year (563.54 a month). +- name: Case 18, two-person first ceiling is the exact 25 percent amount. period: 2027 absolute_error_margin: 0.0001 input: @@ -573,7 +575,7 @@ ak_atap: 0 receives_housing_assistance: false fuel_oil_expense: 1_000 - ak_hap_countable_income: 6_756 + ak_hap_countable_income: 6_762.5 ak_hap_household_size: 2 households: household1: @@ -584,7 +586,7 @@ output: ak_hap_income_factor: 1 -# 563.01 monthly exceeds the two-person 25% ceiling 563. +# 6,762.62 a year (563.55 a month) exceeds the two-person 25% ceiling of 6,762.50. - name: Case 19, above two-person first ceiling receives ninety percent. period: 2027 absolute_error_margin: 0.0001 @@ -605,7 +607,7 @@ ak_atap: 0 receives_housing_assistance: false fuel_oil_expense: 1_000 - ak_hap_countable_income: 6756.12 + ak_hap_countable_income: 6_762.62 ak_hap_household_size: 2 households: household1: @@ -616,7 +618,7 @@ output: ak_hap_income_factor: 0.9 -# GRID size 18: 125% ceiling 14650 monthly; 14650 * 12 = 175800. +# Size 18: guideline 19,950 + 17 * 7,100 = 140,650; 125% ceiling 175,812.50 a year (14,651.04 a month). - name: Case 20, eighteen-person middle-high band uses published additional members. period: 2027 absolute_error_margin: 0.0001 @@ -637,7 +639,7 @@ ak_atap: 0 receives_housing_assistance: false fuel_oil_expense: 1_000 - ak_hap_countable_income: 175_800 + ak_hap_countable_income: 175_812.5 ak_hap_household_size: 18 households: household1: @@ -648,7 +650,7 @@ output: ak_hap_income_factor: 0.6 -# GRID size 18: 14650.01 monthly is in the 125–150% band. +# Size 18: 175,812.62 a year is a cent a month above the 125% ceiling, in the 125-150% band. - name: Case 21, above eighteen-person 125 percent enters fifty percent band. period: 2027 absolute_error_margin: 0.0001 @@ -669,7 +671,7 @@ ak_atap: 0 receives_housing_assistance: false fuel_oil_expense: 1_000 - ak_hap_countable_income: 175800.12 + ak_hap_countable_income: 175_812.62 ak_hap_household_size: 18 households: household1: @@ -711,3 +713,39 @@ place_fips: '24230' output: ak_hap_income_factor: 0 + +# 7 AAC 44.040(a)(4) and 44.080(i) use exact percentages. Four-person guideline +# 19,950 + 3 * 7,100 = 41,250 (3,437.50 a month). The 125% ceiling is 51,562.50 +# and the 150% ceiling is 61,875 a year (5,156.25 a month). Income of 5,156 a +# month (61,872 a year) is within 150%: factor 0.5. A ceiling floored to whole +# monthly dollars, 5,155 (61,860 a year), would give factor 0. +- name: Case 23, four people at 5,156 a month are within the exact 150 percent ceiling. + period: 2027 + absolute_error_margin: 0.0001 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: + - person1 + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + ak_atap: 0 + receives_housing_assistance: false + fuel_oil_expense: 1_000 + ak_hap_countable_income: 61_872 + ak_hap_household_size: 4 + households: + household1: + members: + - person1 + state_code: AK + place_fips: '24230' + output: + ak_hap_income_factor: 0.5 diff --git a/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap.py b/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap.py index f7c8b6f6edd..43e3142f078 100644 --- a/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap.py +++ b/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap.py @@ -35,12 +35,14 @@ def formula(spm_unit, period, parameters): first_member * spm_unit.project(heating_expense) ) # 7 AAC 44.080(h) reduces a sharing household's points to its - # proportionate share of the dwelling's heating expenses. When no - # household reports a heating expense (heat in rent), manual 3002-1 - # A.5 fills the gap: equal shares among the eligible households, at - # most the maximum share each. A heat-in-rent household that shares a - # dwelling with a household reporting a heating bill gets a zero share, - # because the heating portion of its rent is not observed. + # proportionate share of the dwelling's home heating expenses, which + # 7 AAC 44.900(11) defines to include heat paid indirectly through + # rent. The heat portion of rent is not observed, so the equal split + # of manual 3002-1 A.5 fills that gap: each eligible heat-in-rent + # household gets an equal share among the dwelling's eligible + # households, at most the maximum share. Households reporting heating + # bills split the remaining share in proportion to their bills. When + # no household reports a bill, every household gets the equal share. equal_share = where( household_count > 1, min_( @@ -49,10 +51,22 @@ def formula(spm_unit, period, parameters): ), 1, ) - share = np.divide( - heating_expense, + heat_in_rent = spm_unit("heat_expense_included_in_rent", period) & ( + heating_expense == 0 + ) + eligible_heat_in_rent_count = spm_unit.household.sum( + first_member & spm_unit.project(sole_household_eligible & heat_in_rent) + ) + bill_payer_share = 1 - equal_share * eligible_heat_in_rent_count + expense_share = np.divide( + heating_expense * bill_payer_share, dwelling_heating_expense, - out=equal_share, + out=np.zeros_like(heating_expense), where=dwelling_heating_expense > 0, ) + share = where( + (dwelling_heating_expense > 0) & ~heat_in_rent, + expense_share, + equal_share, + ) return ak_hap_award(spm_unit, period, parameters, share, True) diff --git a/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_base_benefit.py b/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_base_benefit.py index 023d8a51b69..1f58a0aeebb 100644 --- a/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_base_benefit.py +++ b/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_base_benefit.py @@ -85,12 +85,16 @@ def ak_hap_award(spm_unit, period, parameters, share, apply_utility_allowance): # never infer tribal enrollment from race. Finer residency, temporary # shelter duration and vendor-credit rules are also unobserved. state_served = ~np.isin(place, p.tribal_service_places) + # 7 AAC 44.040(b)(3)(B) excludes households residing on a military base. + # Census draws the listed places from the installations themselves. + on_base = np.isin(place, p.military_base_places) eligible = ( (factor > 0) & (community_points > 0) & (expense > p.minimum_expense) & ~(heat_in_rent & subsidized) & state_served + & ~on_base & (points >= p.minimum_points) ) rounded_points = min_(np.floor(points + 0.5), p.maximum_points) diff --git a/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_countable_income.py b/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_countable_income.py index 14d153a3cc6..7c2be8743ca 100644 --- a/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_countable_income.py +++ b/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_countable_income.py @@ -23,16 +23,16 @@ def formula(spm_unit, period, parameters): # Annual inputs approximate prior-month receipts and the alternative # seasonal/business annualization rules. Include income of all members, # regardless of whether immigration status permits counting their size. - school = person("is_in_k12_school", period) | person( - "is_in_secondary_school", period - ) - # Dependency and schooling approximate parental control and at least - # half-time elementary/high-school/GED attendance; those details are - # not separately observed. This exclusion applies only to earnings. - exempt_child = ( + # 7 AAC 44.042(5) exempts wages of a full-time student under 18 who is + # not the head of household. The tax-unit head stands in for the head + # of household. is_full_time_student treats any K-12 attendance as + # full time, since part-time enrollment is not observed. Only wages + # (employment income and military basic pay) are exempt; the + # student's business income still counts. + exempt_student = ( (person("age", period) < p.child_earnings_age_limit) - & person("is_tax_unit_dependent", period) - & school + & person("is_full_time_student", period) + & ~person("is_tax_unit_head", period) ) # Supplied net business income stands in for gross receipts less # costs. Manual 3003-4 B deducts 50% of gross unless actual costs are @@ -44,7 +44,10 @@ def formula(spm_unit, period, parameters): earned = 0 for source in p.earned_sources: earned = earned + max_(person(source, period), 0) - countable_earned = spm_unit.sum(where(exempt_child, 0, earned)) + wages = max_(person("employment_income", period), 0) + max_( + person("military_basic_pay", period), 0 + ) + countable_earned = spm_unit.sum(earned - where(exempt_student, wages, 0)) # These are cash receipts, so a tax loss in an unearned source does not # offset other income. Net rental sources are separately nonnegative. unearned_person = 0 diff --git a/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_income_factor.py b/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_income_factor.py index 44f76be0fd5..9c2a2cb5b0b 100644 --- a/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_income_factor.py +++ b/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_income_factor.py @@ -8,6 +8,7 @@ class ak_hap_income_factor(Variable): definition_period = YEAR label = "Alaska HAP income factor" reference = ( + "https://www.akleg.gov/basis/aac.asp?media=print&secStart=7.44.010&secEnd=7.44.9001", "http://dpaweb.hss.state.ak.us/manuals/HAP/3004/3004-5_grant_computation.htm", "http://dpaweb.hss.state.ak.us/manuals/HAP/addendum/addendum_e.htm", ) @@ -19,16 +20,11 @@ def formula(spm_unit, period, parameters): income = spm_unit("ak_hap_countable_income", period) state_group = spm_unit.household("state_group_str", period) guideline = fpg(size, state_group, period, parameters, year_lag=p.fpg_year_lag) - monthly_fpg = np.floor(guideline / MONTHS_IN_YEAR) - # Reconcile the published grid by flooring the monthly FPG before each - # percentage. This gives 415, not the printed 407, at the FY2027 size-1 - # 25% ceiling. 407 matches the prior-year base; using 415 follows the - # explicit 25% rule, not an agency-issued correction. Historical years - # are unverified backfilled estimates. - limits = [ - np.floor(monthly_fpg * rate) * MONTHS_IN_YEAR - for rate in p.income_factor.fpg_rates - ] + # 7 AAC 44.040(a)(4) and 44.080(i) compare gross monthly income with + # exact percentages of the monthly Alaska poverty guideline; annual + # amounts compare the same way. Historical years are unverified + # backfilled estimates. + limits = [guideline * rate for rate in p.income_factor.fpg_rates] factor = select( [income <= limit for limit in limits], p.income_factor.factors, default=0 ) diff --git a/source_conflicts/candidates.yaml b/source_conflicts/candidates.yaml index 58e2e17b3f5..e1170ac54b8 100644 --- a/source_conflicts/candidates.yaml +++ b/source_conflicts/candidates.yaml @@ -35,15 +35,18 @@ candidates: other: Plan 1.9 counts "General Assistance and Borough of Indian Affairs (BIA) General Assistance benefits if paid directly to the household"; manual 3003-1 B.6.o counts BIA General Assistance payments made to the household, and 3003-2 A.19 exempts only General Relief Assistance payments made to a vendor. + example: A household with $1,200 a year of State General Relief Assistance paid to it has none of it counted under + 7 AAC 44.042(18); plan 1.9 counts General Assistance paid directly to the household. pe_us: - follows: conflicting-source + follows: statute code: - policyengine_us/parameters/gov/states/ak/dpa/hap/income/unearned_sources.yaml prs: - https://github.com/PolicyEngine/policyengine-us/pull/10341 - state: open - note: The general_assistance input cannot tell State General Relief Assistance from BIA General Assistance, and - the code counts it in full. The manual is served only over http, at + state: unreviewed + note: The code reads the general_assistance input as State General Relief Assistance and leaves it out of countable + income under 7 AAC 44.042(18). BIA General Assistance paid to the household, which plan 1.9 and manual 3003-1 B.6.o + count, has no separate input, so it is not counted. The manual is served only over http, at http://dpaweb.hss.state.ak.us/manuals/HAP/3003/3003-1_countable_income.htm. - id: us-ak:hap-income-limit-rounding program: liheap @@ -66,16 +69,18 @@ candidates: other: Addendum E floors the monthly guideline and then each percentage ("All dollars rounded down to guarantee they are below income guidelines"), which puts 23 of its 108 limits for the six LIHEAP income factors $1 below the exact percentage. - example: For four people, 150% of the FY2027 monthly guideline of $3,437.50 is $5,156.25, but Addendum E and the - PR use $5,155, so a household with $5,156 of monthly income is ineligible in the PR. + example: For four people, 150% of the FY2027 monthly guideline of $3,437.50 is $5,156.25, so a household with $5,156 + of monthly income is eligible under 7 AAC 44.040(a)(4) and ineligible under Addendum E's $5,155. pe_us: - follows: conflicting-source + follows: statute code: - policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_income_factor.py prs: - https://github.com/PolicyEngine/policyengine-us/pull/10341 - state: open - note: The manual is served only over http, at http://dpaweb.hss.state.ak.us/manuals/HAP/addendum/addendum_e.htm. + state: unreviewed + note: The code compares income with the exact percentages of the guideline, with no whole-dollar floors. Each of the + 108 limits is $0.04 to $1.79 a month above its floored amount. The manual is served only over http, at + http://dpaweb.hss.state.ak.us/manuals/HAP/addendum/addendum_e.htm. - id: us-ak:hap-loring-oil-points program: liheap years: @@ -95,17 +100,18 @@ candidates: statute: No statute is supplied; 7 AAC 44.080(a) assigns the community heating cost points listed in Appendix A, which gives Loring 5 oil points. other: Addendum A gives Loring 4 oil points ("99901 Loring/04/00/"). - example: A Loring adult aged 40 with no income, a two-bedroom house and an oil bill receives 4 points, $700, in the - PR; Appendix A's 5 points would pay $875. + example: A Loring adult aged 40 with no income, a two-bedroom house and an oil bill receives 5 points, $875, under + Appendix A and 4 points, $700, under Addendum A. pe_us: - follows: conflicting-source + follows: statute code: - policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/community_points/oil.yaml prs: - https://github.com/PolicyEngine/policyengine-us/pull/10341 - state: open - note: Tetlin also differs (Addendum A 12, Appendix A 16), but its residents are routed to their tribal program, so - that difference does not change results. The manual is served only over http, at + state: unreviewed + note: The code gives Loring Appendix A's 5 oil points. Tetlin also differs (Addendum A 12, Appendix A 16), and the + code uses Appendix A's 16; its residents are routed to their tribal program, so that value does not change + results. The manual is served only over http, at http://dpaweb.hss.state.ak.us/manuals/HAP/addendum/addendum_a.htm. - id: us-ak:hap-one-person-lowest-income-limit program: liheap @@ -113,7 +119,7 @@ candidates: from: 2027 to: 2027 type: federal-fiscal - question: Is the FY2027 one-person income ceiling for Alaska's 100% heating point factor $415, from 25% of the + question: Is the FY2027 one-person income ceiling for Alaska's 100% heating point factor $415.625, 25% of the Alaska poverty guideline, or the $407 printed in Addendum E? sources: - kind: regulation @@ -124,11 +130,11 @@ candidates: url: null readings: statute: No statute is supplied; 7 AAC 44.080(i)(1) assigns 100% of points when gross monthly income is no more - than 25% of the Alaska poverty level, which for one person is 25% of $1,662.50 ($19,950 / 12), or $415.63. + than 25% of the Alaska poverty level, which for one person is 25% of $1,662.50 ($19,950 / 12), or $415.625. other: Addendum E prints $407, which is 25% of the prior year's floored monthly guideline ($19,550 / 12, floored to $1,629); its other 161 cells use the 2026 guideline. - example: A one-person household with $410 of monthly income receives the 1.0 income factor in the PR and would - receive 0.9 under Addendum E's $407. + example: A one-person household with $410 of monthly income receives the 1.0 income factor under the $415.625 limit + and 0.9 under Addendum E's $407. pe_us: follows: statute code: @@ -136,8 +142,8 @@ candidates: prs: - https://github.com/PolicyEngine/policyengine-us/pull/10341 state: unreviewed - note: The code uses $415, the 25% rule with the same whole-dollar floors Addendum E applies to every other cell - (see us-ak:hap-income-limit-rounding). The manual is served only over http, at + note: The code uses the exact 25% limit, $415.625 a month ($4,987.50 a year), with no whole-dollar floor (see + us-ak:hap-income-limit-rounding). The manual is served only over http, at http://dpaweb.hss.state.ak.us/manuals/HAP/addendum/addendum_e.htm. - id: us-ak:hap-shared-household-allocation program: liheap @@ -175,10 +181,14 @@ candidates: - https://github.com/PolicyEngine/policyengine-us/pull/10341 state: unreviewed note: The code follows 7 AAC 44.080(h). 7 AAC 44.035(c) is a second regulatory reading, which pays each household - the percentage of its sole-household dollar award equal to its share of the dwelling's heating cost. When no - household in the dwelling reports a heating expense, as with heat included in rent, the code fills the gap with - the manual's equal split among eligible households, at most 50% each. Draft rulespec-us PR 1846 proposed this id - with the manual reading. The manual is served only over http, at + the percentage of its sole-household dollar award equal to its share of the dwelling's heating cost. 7 AAC + 44.900(11) counts heat paid indirectly through rent as a home heating cost, but the heat portion of rent is not + observed, so the code fills that gap with the manual's equal split. Each eligible heat-in-rent household gets an + equal share among the dwelling's eligible households, at most 50%, and households reporting heating bills split the + remaining share in proportion to their bills; when no household reports a bill, every household gets the equal + share. In a Fairbanks two-bedroom house where an adult household pays a $1,200 oil bill and an elderly household + has heat in its $6,000 rent, each gets half, so they receive $875 (5 points) and $1,050 (6 points). Draft + rulespec-us PR 1846 proposed this id with the manual reading. The manual is served only over http, at http://dpaweb.hss.state.ak.us/manuals/HAP/3002/3002-1_households.htm. - id: us-ak:hap-student-earnings-exemption program: liheap @@ -202,18 +212,21 @@ candidates: other: The manual exempts the earned income of a student under 18 who lives with, or is under the parental control of, an adult household member and is enrolled at least half time in elementary or secondary school, including during school breaks. - example: A 16-year-old dependent enrolled half time in high school has wages exempt in the PR; under 7 AAC - 44.042(5) they count, because the student does not attend full time. + example: A 17-year-old full-time college student who is not the head of household has wages exempt under 7 AAC + 44.042(5) and counted under the manual, which covers only elementary and secondary students. pe_us: - follows: conflicting-source + follows: statute code: - policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_countable_income.py - policyengine_us/parameters/gov/states/ak/dpa/hap/income/child_earnings_age_limit.yaml prs: - https://github.com/PolicyEngine/policyengine-us/pull/10341 - state: open - note: The model's school inputs do not record full-time or half-time enrollment; the code approximates the - manual's test with tax dependency and K-12 or secondary school attendance. The manual is served only over http, + state: unreviewed + note: The code exempts the wages (employment income and military basic pay) of a member under 18 who is a + full-time student (is_full_time_student) and not the tax-unit head, the closest existing input to the head of + household; the student's business income still counts. Half-time enrollment cannot be + observed, and is_full_time_student treats any K-12 attendance as full time, so a half-time high school student's + wages are exempt in the code. The manual is served only over http, at http://dpaweb.hss.state.ak.us/manuals/HAP/3003/3003-2_noncountable_(exempt)_income.htm. - id: us-ak:hap-utility-allowance-order program: liheap From 99d3073399a3f528d7774cdbbcbe1870cc31d3dd Mon Sep 17 00:00:00 2001 From: Ziming Date: Wed, 28 Oct 2026 15:18:22 -0400 Subject: [PATCH 15/16] Address third review of Alaska HAP Pin the bill guard in the shared-dwelling rule and military basic pay in the student wage exemption with tests, move the exempt wage sources to a parameter list, treat a minor in a unit without an adult as its head, exclude Eareckson Station residents as living on a military base, and correct the ZIP-code and leftover test wording. Co-Authored-By: Claude Opus 5.5 --- .../dpa/hap/benefit/community_points/oil.yaml | 11 ++-- .../dpa/hap/benefit/military_base_places.yaml | 6 +- .../hap/benefit/tribal_service_places.yaml | 3 +- .../dpa/hap/income/student_wage_sources.yaml | 17 ++++++ .../gov/states/ak/dpa/hap/ak_hap.yaml | 55 +++++++++++++++++++ .../ak/dpa/hap/ak_hap_base_benefit.yaml | 51 ++++++++++++----- .../ak/dpa/hap/ak_hap_countable_income.yaml | 8 +-- .../ak/dpa/hap/ak_hap_income_factor.yaml | 2 +- .../ak/dpa/hap/ak_hap_countable_income.py | 24 ++++---- source_conflicts/candidates.yaml | 7 ++- 10 files changed, 143 insertions(+), 41 deletions(-) create mode 100644 policyengine_us/parameters/gov/states/ak/dpa/hap/income/student_wage_sources.yaml diff --git a/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/community_points/oil.yaml b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/community_points/oil.yaml index 615d6dd93f6..85774458cfb 100644 --- a/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/community_points/oil.yaml +++ b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/community_points/oil.yaml @@ -4,11 +4,12 @@ description: Alaska assigns these oil heating points by Census place under the H # spelling variants such as Adak (Station), Chenega Bay, Kalskag (lower/upper), # Eilson AFB, Harding Lake and Saint for St., and give the Anchorage # municipality the Anchorage value of 8 (Chugiak, listed at 7, lies inside it). -# Four places take the community Addendum A lists for their ZIP code: Chena -# Ridge and Goldstream (ZIP 99709, College, 10) and Covenant Life and Mosquito -# Lake (ZIP 99827, Haines, 6). Every other place takes the points of the -# nearest listed oil community by great-circle distance between Census internal -# points. This is not a state-issued crosswalk. Values follow the FY2027 +# Four places take the points of the main community Addendum A lists for their +# ZIP code: Chena Ridge and Goldstream (ZIP 99709, College, 10) and Covenant +# Life and Mosquito Lake (ZIP 99827, Haines, 6; Addendum A also lists +# Excursion Inlet and Klukwan under 99827). Every other place takes the points +# of the nearest listed oil community by great-circle distance between Census +# internal points. This is not a state-issued crosswalk. Values follow the FY2027 # Addendum A, except Loring (5) and Tetlin (16), which follow Appendix A to # 7 AAC 44 under 7 AAC 44.080(a); Addendum A lists them at 4 and 12. "00065": # Adak city diff --git a/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/military_base_places.yaml b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/military_base_places.yaml index 472cb8b50cb..ba898ba341b 100644 --- a/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/military_base_places.yaml +++ b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/military_base_places.yaml @@ -3,11 +3,13 @@ description: Alaska excludes residents of these military base Census places unde # the installations themselves, so their residents live on base. Addendum A # marks both installations 0/USA. Kodiak Station CDP (41210) is the housing # area of Coast Guard Base Kodiak, and Addendum A says Coast Guard members -# living on base in provided housing do not qualify. Elmendorf AFB and Fort Richardson, also +# living on base in provided housing do not qualify. Eareckson Station CDP +# (20716) is drawn on Shemya Island around Eareckson Air Station, an Air Force +# installation; Addendum A lists no community there. Elmendorf AFB and Fort Richardson, also # 0/USA, lie inside the Anchorage municipality with no separate Census place, # so their residents cannot be identified. values: - 2026-10-01: ["21370", "26100", "41210"] + 2026-10-01: ["20716", "21370", "26100", "41210"] metadata: unit: list diff --git a/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/tribal_service_places.yaml b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/tribal_service_places.yaml index 2240cbefcdd..ddb32659b2e 100644 --- a/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/tribal_service_places.yaml +++ b/policyengine_us/parameters/gov/states/ak/dpa/hap/benefit/tribal_service_places.yaml @@ -3,7 +3,8 @@ description: Alaska excludes all residents of these tribe-served Census places u # residents), matched by Census place name. The 0/USA military bases are in # military_base_places instead. Approximated places inherit the all-resident # tribal routing of the community whose oil points they take: the community -# listed for their ZIP code, or else the nearest listed community. +# that is the main listing for their ZIP code, or else the nearest listed +# community. values: 2026-10-01: ["00760", "00870", "01200", "01305", "01390", "01420", "01860", "03440", "03550", "03880", "03990", "04430", "05750", "06520", "06630", "07620", "11690", "11800", "12680", "13230", "13450", "13550", "13670", "13780", "14330", "14880", "15430", "16630", "17740", "18950", "19720", "19750", "20020", "20380", "20600", "21040", "21150", "21810", "22910", "23790", "26760", "26835", "27530", "27700", "29290", "30060", "32310", "32550", "33030", "33360", "33470", "33910", "34350", "34460", "34790", "35120", "35890", "36770", "37430", "37650", "37975", "39630", "39740", "40400", "40510", "41280", "41500", "41610", "41720", "42050", "42380", "42490", "42820", "43810", "44030", "45460", "45700", "46010", "46780", "46890", "47000", "47990", "48590", "48870", "49530", "51180", "52060", "52390", "52720", "53050", "53270", "53710", "53820", "53930", "54150", "55030", "56220", "56350", "56600", "56680", "58330", "60640", "60750", "60860", "61080", "62125", "62285", "63390", "64600", "64820", "64930", "65590", "65700", "66140", "67570", "67680", "68670", "71090", "72190", "73290", "74610", "75050", "75160", "76590", "77690", "78240", "78790", "79120", "79230", "79780", "80100", "81320", "82420", "84200", "85610", "86490"] diff --git a/policyengine_us/parameters/gov/states/ak/dpa/hap/income/student_wage_sources.yaml b/policyengine_us/parameters/gov/states/ak/dpa/hap/income/student_wage_sources.yaml new file mode 100644 index 00000000000..ad5c10f559f --- /dev/null +++ b/policyengine_us/parameters/gov/states/ak/dpa/hap/income/student_wage_sources.yaml @@ -0,0 +1,17 @@ +description: Alaska exempts these wage sources of a full-time student under 18 who is not the head of household under the Heating Assistance Program. +# 7 AAC 44.042(5) exempts "wages received by a full-time student under 18 +# years of age who is not the head of household". Military basic pay includes +# National Guard and reserve drill pay. A student's business income is not +# wages and still counts. +values: + 2026-10-01: + - employment_income + - military_basic_pay + +metadata: + unit: list + period: year + label: Alaska HAP student exempt wage sources + reference: + - title: 7 AAC 44.042(5) + href: https://www.akleg.gov/basis/aac.asp?media=print&secStart=7.44.010&secEnd=7.44.9001 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap.yaml b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap.yaml index 17dd1a6cd0c..447c23feab3 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap.yaml @@ -1033,3 +1033,58 @@ heating_expense: [1_200, 0] ak_hap_base_benefit: [1_750, 1_925] ak_hap: [875, 1_050] + +# One Fairbanks dwelling (oil 10), both units aged 40 in a two-bedroom house +# with no income (factor 1). Unit 1 has heat in its unsubsidized 6,000 rent and +# also reports a 600 oil bill; unit 2 pays a 1,200 oil bill. A unit reporting a +# bill is a bill payer even with heat in rent, so no unit takes the equal share +# and the shares follow the bills: 600 / 1,800 and 1,200 / 1,800. Unit 1: +# 10 * 1/3 = 3.33 -> 3 points = 525. Unit 2: 10 * 2/3 = 6.67 -> 7 points = +# 1,225. Treating unit 1 as heat in rent would give it .5 (875) and unit 2 +# 1,200 * .5 / 1,800 = 1/3 (525). +- name: Case 18, a heat-in-rent unit that reports a heating bill shares by its bill. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + pre_subsidy_rent: 6_000 + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + person2: + age: 40 + immigration_status: CITIZEN + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 + spm_units: + spm_unit1: + members: [person1] + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + fuel_oil_expense: 600 + ak_atap: 0 + receives_housing_assistance: false + heat_expense_included_in_rent: true + spm_unit2: + members: [person2] + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + fuel_oil_expense: 1_200 + ak_atap: 0 + receives_housing_assistance: false + heat_expense_included_in_rent: false + households: + household1: + members: [person1, person2] + state_code: AK + place_fips: '24230' + output: + ak_hap_countable_income: [0, 0] + ak_hap_income_factor: [1, 1] + heating_expense: [600, 1_200] + ak_hap_base_benefit: [1_750, 1_750] + ak_hap: [525, 1_225] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_base_benefit.yaml b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_base_benefit.yaml index 92b7b4d0e3c..a3ad33fb417 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_base_benefit.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_base_benefit.yaml @@ -6,8 +6,8 @@ # http://dpaweb.hss.state.ak.us/manuals/HAP/addendum/addendum_a.htm # http://dpaweb.hss.state.ak.us/manuals/HAP/3002/3002-1_households.htm # https://www.akleg.gov/basis/aac.asp?media=print&secStart=7.44.010&secEnd=7.44.9001 -# Census places not named in Addendum A take the oil and gas points of the community -# Addendum A lists for their ZIP code (four places) or else of the nearest listed +# Census places not named in Addendum A take the oil and gas points of the main +# community Addendum A lists for their ZIP code (four places) or else of the nearest listed # community; these approximations are not a state-issued crosswalk. Oil points follow # Addendum A except Loring and Tetlin, which follow Appendix A to 7 AAC 44. # Income ceilings are exact percentages of the guideline: the one-person 25% ceiling @@ -1540,7 +1540,7 @@ ak_hap_income_factor: 1 # Five qualified members, monthly 2,900 <= 75% ceiling 3,021.875 (48,350 * .75 / 12); 27 * .8 + 1 = 22.6 -> 23 * $175. -- name: Case 49, Savoonga updated five-person band supersedes stale worked label. +- name: Case 49, a Savoonga five-person household is in the 75% band. period: 2027 absolute_error_margin: 0.0001 input: @@ -1764,7 +1764,7 @@ output: ak_hap_base_benefit: 525 -# Current COMMUNITY 0/AVCP means all residents are routed; no race-based inference. +# Addendum A marks Akiachak 0/AVCP: the tribe serves all residents, so no race-based inference is needed. - name: Case 55, all-resident tribal routing excludes Akiachak state component. period: 2027 absolute_error_margin: 0.01 @@ -2877,11 +2877,13 @@ # Addendum A marks Eielson AFB 0/USA, and Census draws Eielson AFB CDP from the # installation. Kodiak Station CDP is the housing area of Coast Guard Base # Kodiak, whose members living on base in provided housing do not qualify -# (Addendum A). Each member's 24,000 of basic pay is in the 100-125% band -# (19,950 < 24,000 <= 24,937.50): factor .6. Without the exclusion, Eielson -# oil 11 * 1 * .6 = 6.6 -> 7 points * $175 = $1,225, and Kodiak Station oil -# 6 * 1 * .6 = 3.6 -> 4 points * $175 = $700; on base each award is 0. -- name: Case 86, Eielson AFB CDP and Kodiak Station CDP residents live on a military base and receive nothing. +# (Addendum A). Eareckson Station CDP is drawn on Shemya Island around +# Eareckson Air Station. Each member's 24,000 of basic pay is in the 100-125% +# band (19,950 < 24,000 <= 24,937.50): factor .6. Without the exclusion, +# Eielson oil 11 * 1 * .6 = 6.6 -> 7 points * $175 = $1,225, and Kodiak +# Station and Eareckson Station oil 6 * 1 * .6 = 3.6 -> 4 points * $175 = $700; +# on base each award is 0. +- name: Case 86, Eielson AFB, Kodiak Station and Eareckson Station CDP residents live on a military base and receive nothing. period: 2027 absolute_error_margin: 0.01 input: @@ -2900,6 +2902,13 @@ ssi: 0 ak_ssp: 0 ak_permanent_fund_dividend: 0 + person3: + age: 30 + immigration_status: CITIZEN + military_basic_pay: 24_000 + ssi: 0 + ak_ssp: 0 + ak_permanent_fund_dividend: 0 spm_units: spm_unit1: members: [person1] @@ -2915,6 +2924,13 @@ fuel_oil_expense: 1_500 ak_atap: 0 receives_housing_assistance: false + spm_unit3: + members: [person3] + heating_type: FUEL_OIL + ak_hap_dwelling_type: TWO_BEDROOM_HOUSE + fuel_oil_expense: 1_500 + ak_atap: 0 + receives_housing_assistance: false households: household1: members: [person1] @@ -2924,19 +2940,24 @@ members: [person2] state_code: AK place_fips: '41210' + household3: + members: [person3] + state_code: AK + place_fips: '20716' output: - ak_hap_countable_income: [24_000, 24_000] - ak_hap_income_factor: [0.6, 0.6] - ak_hap_base_benefit: [0, 0] + ak_hap_countable_income: [24_000, 24_000, 24_000] + ak_hap_income_factor: [0.6, 0.6, 0.6] + ak_hap_base_benefit: [0, 0, 0] -# Addendum A lists ZIP 99709 as College (10 oil points) and ZIP 99827 as -# Haines (6 oil points, tribal service for Natives only). Most addresses in +# Addendum A lists College (10 oil points) as the main community for ZIP 99709 +# and Haines (6 oil points, tribal service for Natives only) as the main +# community for ZIP 99827, which also lists Excursion Inlet and Klukwan. Most addresses in # Chena Ridge CDP use ZIP 99709, and Covenant Life CDP uses ZIP 99827, so # they take those communities' points; Covenant Life is not an all-resident # tribal place. With no income the factor is 1.0 (0 <= 25% of the guideline): # Covenant Life 6 * 1 * 1.0 = 6 points * $175 = $1,050; Chena Ridge # 10 * 1 * 1.0 = 10 points * $175 = $1,750. -- name: Case 87, Covenant Life CDP and Chena Ridge CDP take the oil points of the community listed for their ZIP code. +- name: Case 87, Covenant Life CDP and Chena Ridge CDP take the oil points of the main community listed for their ZIP code. period: 2027 absolute_error_margin: 0.01 input: diff --git a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_countable_income.yaml index 65b97e305ce..bac4d60d3c5 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_countable_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_countable_income.yaml @@ -267,7 +267,7 @@ output: ak_hap_countable_income: 24_000 -# 7 AAC 44.042(5) covers any full-time student under 18, not only elementary or secondary students, and exempts only "wages". A 17-year-old full-time college student who is not the head has the 12,000 of wages excluded, but the 2,000 of net business income counts: 24,000 + 0 + 2,000 = 26,000. +# 7 AAC 44.042(5) covers any full-time student under 18, not only elementary or secondary students, and exempts only "wages". A 17-year-old full-time college student who is not the head has 12,000 of wages and 1,200 of National Guard drill pay (military basic pay) excluded, but the 2,000 of net business income counts: 24,000 + 0 + 0 + 2,000 = 26,000. - name: "Case 10, a full-time college student under 18 who is not the head has wages excluded and net business income counted." period: 2027 absolute_error_margin: 0.01 @@ -290,6 +290,7 @@ is_full_time_college_student: true is_in_k12_school: false employment_income: 12_000 + military_basic_pay: 1_200 self_employment_income: 2_000 spm_units: spm_unit1: @@ -374,8 +375,8 @@ output: ak_hap_countable_income: 36_000 -# 7 AAC 44.042(5) does not exempt a head of household. This 17-year-old high school student lives alone and heads a tax unit (supplied role; age ordering infers no head when no member is an adult), so the wages of 12,000 count. -- name: "Case 13, wages of a minor student who heads a tax unit count." +# 7 AAC 44.042(5) does not exempt a head of household. This 17-year-old high school student lives alone with no role supplied. A tax unit infers a head only among adults, so the student is not a tax-unit head, but with no adult in the SPM unit the student is treated as its head, so the wages of 12,000 count. +- name: "Case 13, wages of a minor student living without an adult count." period: 2027 absolute_error_margin: 0.01 input: @@ -386,7 +387,6 @@ ssi: 0 ak_ssp: 0 ak_permanent_fund_dividend: 0 - tax_unit_role_input: "HEAD" is_in_k12_school: true employment_income: 12_000 spm_units: diff --git a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_income_factor.yaml b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_income_factor.yaml index eb08f68707f..1814f466635 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_income_factor.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ak/dpa/hap/ak_hap_income_factor.yaml @@ -107,7 +107,7 @@ ak_hap_income_factor: 0 # Addendum E prints 407/month; the exact 25% ceiling is 415.625, so 407 is in the lowest band. -- name: Case 4, printed stale 407 amount stays in the lowest band. +- name: Case 4, Addendum E's printed 407 a month stays in the lowest band. period: 2027 absolute_error_margin: 0.0001 input: diff --git a/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_countable_income.py b/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_countable_income.py index 7c2be8743ca..07b5da8f6cb 100644 --- a/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_countable_income.py +++ b/policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_countable_income.py @@ -25,14 +25,18 @@ def formula(spm_unit, period, parameters): # regardless of whether immigration status permits counting their size. # 7 AAC 44.042(5) exempts wages of a full-time student under 18 who is # not the head of household. The tax-unit head stands in for the head - # of household. is_full_time_student treats any K-12 attendance as - # full time, since part-time enrollment is not observed. Only wages - # (employment income and military basic pay) are exempt; the - # student's business income still counts. + # of household. A tax unit infers a head only among adults, so a minor + # in an SPM unit with no adult member is treated as its head. + # is_full_time_student treats any K-12 attendance as full time, since + # part-time enrollment is not observed. Only the listed wage sources + # are exempt; the student's business income still counts. + age = person("age", period) + adult_present = spm_unit.any(age >= p.child_earnings_age_limit) exempt_student = ( - (person("age", period) < p.child_earnings_age_limit) + (age < p.child_earnings_age_limit) & person("is_full_time_student", period) & ~person("is_tax_unit_head", period) + & spm_unit.project(adult_present) ) # Supplied net business income stands in for gross receipts less # costs. Manual 3003-4 B deducts 50% of gross unless actual costs are @@ -43,11 +47,11 @@ def formula(spm_unit, period, parameters): # source cannot be separated. earned = 0 for source in p.earned_sources: - earned = earned + max_(person(source, period), 0) - wages = max_(person("employment_income", period), 0) + max_( - person("military_basic_pay", period), 0 - ) - countable_earned = spm_unit.sum(earned - where(exempt_student, wages, 0)) + amount = max_(person(source, period), 0) + if source in p.student_wage_sources: + amount = where(exempt_student, 0, amount) + earned = earned + amount + countable_earned = spm_unit.sum(earned) # These are cash receipts, so a tax loss in an unearned source does not # offset other income. Net rental sources are separately nonnegative. unearned_person = 0 diff --git a/source_conflicts/candidates.yaml b/source_conflicts/candidates.yaml index 997451d0c93..0982b15d09c 100644 --- a/source_conflicts/candidates.yaml +++ b/source_conflicts/candidates.yaml @@ -219,14 +219,15 @@ candidates: code: - policyengine_us/variables/gov/states/ak/dpa/hap/ak_hap_countable_income.py - policyengine_us/parameters/gov/states/ak/dpa/hap/income/child_earnings_age_limit.yaml + - policyengine_us/parameters/gov/states/ak/dpa/hap/income/student_wage_sources.yaml prs: - https://github.com/PolicyEngine/policyengine-us/pull/10341 state: unreviewed note: The code exempts the wages (employment income and military basic pay) of a member under 18 who is a full-time student (is_full_time_student) and not the tax-unit head, the closest existing input to the head of - household; the student's business income still counts. Half-time enrollment cannot be - observed, and is_full_time_student treats any K-12 attendance as full time, so a half-time high school student's - wages are exempt in the code. The manual is served only over http, + household, in an SPM unit with an adult member; a minor in a unit without an adult is treated as its head. The + student's business income still counts. Half-time enrollment cannot be observed, and is_full_time_student treats + any K-12 attendance as full time, so a half-time high school student's wages are exempt in the code. The manual is served only over http, at http://dpaweb.hss.state.ak.us/manuals/HAP/3003/3003-2_noncountable_(exempt)_income.htm. - id: us-ak:hap-utility-allowance-order program: liheap From e3a66e7bcc910dd926b7c90b7d9c4f2250ee5850 Mon Sep 17 00:00:00 2001 From: Ziming Date: Wed, 28 Oct 2026 15:18:30 -0400 Subject: [PATCH 16/16] List Alaska on the LIHEAP coverage line Co-Authored-By: Claude Opus 5.5 --- policyengine_us/programs.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/policyengine_us/programs.yaml b/policyengine_us/programs.yaml index 92cd7e17356..807b5760412 100644 --- a/policyengine_us/programs.yaml +++ b/policyengine_us/programs.yaml @@ -987,7 +987,7 @@ programs: category: Benefits agency: HHS status: partial - coverage: AR, AL, AZ, DC, GA, Riverside County, MA, FL, IL, IA, IN, KS, KY, MD, MS, NC, ND, NE, NH, NJ, NY, OH, OK, OR, SD, RI, TX, UT, VA, WA, WY + coverage: AK, AR, AL, AZ, DC, GA, Riverside County, MA, FL, IL, IA, IN, KS, KY, MD, MS, NC, ND, NE, NH, NJ, NY, OH, OK, OR, SD, RI, TX, UT, VA, WA, WY state_implementations: - state: AL status: partial