From 446aa9d103a1b40d84f906c15a8f2ded6290e0cd Mon Sep 17 00:00:00 2001 From: Ziming Date: Sat, 3 Oct 2026 19:52:53 -0400 Subject: [PATCH 1/7] Add West Virginia LIEAP household and income limit components --- changelog.d/wv-liheap-wave2c.added.md | 1 + .../gov/states/wv/dhhr/lieap/README.md | 35 + .../wv/dhhr/lieap/eligibility/fpg_rate.yaml | 10 + .../dhhr/lieap/eligibility/fpg_year_lag.yaml | 10 + .../eligibility/smi_max_household_size.yaml | 10 + .../wv/dhhr/lieap/eligibility/smi_rate.yaml | 10 + policyengine_us/programs.yaml | 7 + .../dhhr/lieap/wv_lieap_household_size.yaml | 127 ++++ .../wv/dhhr/lieap/wv_lieap_income_limit.yaml | 641 ++++++++++++++++++ .../wv/dhhr/lieap/wv_lieap_household_size.py | 17 + .../wv/dhhr/lieap/wv_lieap_income_limit.py | 33 + 11 files changed, 901 insertions(+) create mode 100644 changelog.d/wv-liheap-wave2c.added.md create mode 100644 policyengine_us/parameters/gov/states/wv/dhhr/lieap/README.md create mode 100644 policyengine_us/parameters/gov/states/wv/dhhr/lieap/eligibility/fpg_rate.yaml create mode 100644 policyengine_us/parameters/gov/states/wv/dhhr/lieap/eligibility/fpg_year_lag.yaml create mode 100644 policyengine_us/parameters/gov/states/wv/dhhr/lieap/eligibility/smi_max_household_size.yaml create mode 100644 policyengine_us/parameters/gov/states/wv/dhhr/lieap/eligibility/smi_rate.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_household_size.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_income_limit.yaml create mode 100644 policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_household_size.py create mode 100644 policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_income_limit.py diff --git a/changelog.d/wv-liheap-wave2c.added.md b/changelog.d/wv-liheap-wave2c.added.md new file mode 100644 index 00000000000..76b0ca80b93 --- /dev/null +++ b/changelog.d/wv-liheap-wave2c.added.md @@ -0,0 +1 @@ +Add West Virginia LIEAP qualified household-size and income-limit components; countable income and final heating awards remain incomplete pending source conflicts. diff --git a/policyengine_us/parameters/gov/states/wv/dhhr/lieap/README.md b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/README.md new file mode 100644 index 00000000000..9ebdc88761b --- /dev/null +++ b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/README.md @@ -0,0 +1,35 @@ +# West Virginia regular heating components + +The qualified household-size and income-limit components use the FY2026 state +plan and operational manuals, including the adopted October 2026 update for +FY2027. The assistance group includes co-residents sharing +heating costs. Qualified members count in its size; nonqualified members' income +is not excluded. SPM membership approximates the physical sharing group. Prior +assistance in another group can exclude a member, but receipt history is absent +from existing inputs and is not inferred. + +The plan specifies 60% of requested-year SMI through size seven, then 150% of +prior-calendar-year FPG from size eight. Nearest-dollar monthly rounding matches +all ten published agency amounts. Applying the guideline before rounding also +matches the manual's size-eleven limit of $8,831; repeatedly adding the web page's +rounded $688 increment gives a conflicting $8,832. The adopted percentage and +manual calculation take precedence over that rounded web shorthand. This is a +numerically validated rounding convention, not an express rounding instruction. +The same calculation matches the current manual's FY2027 monthly limits for +sizes one through eleven. The payment grid's apparent size-twelve maximum of +$10,160 conflicts with the guideline-derived $9,805; payment cells do not replace +the stated income eligibility rule. + +Countable income, final eligibility and benefit remain incomplete. The manual's +all-income rule conflicts with some unchecked state-plan categories, including +TANF, general assistance and minor earnings; the acquired sources do not settle +that conflict. Both exclude Social Security and SSI. The FY2026 payment chart +has overlapping first/second income bands and anomalous larger-family cells. +The October 2026 operational manual repeats an overlap in FY2027. The source +library preserves both literal grids and their edition details; the model does +not silently correct them or encode unmodeled eligible benefits as zero. + +Only the household-size and income-limit components are verified for FY2026 and +FY2027. Earlier backfilled results are unverified historical estimates; the whole +program is not verified for either year. The full regular-heating goal remains open. Crisis, cooling, +weatherization, equipment and the separate utility discount are out of scope. diff --git a/policyengine_us/parameters/gov/states/wv/dhhr/lieap/eligibility/fpg_rate.yaml b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/eligibility/fpg_rate.yaml new file mode 100644 index 00000000000..a5e730aac8e --- /dev/null +++ b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/eligibility/fpg_rate.yaml @@ -0,0 +1,10 @@ +description: West Virginia limits income to this share of federal poverty guidelines for larger households under the Low Income Energy Assistance Program. +values: + 2025-10-01: 1.5 +metadata: + unit: /1 + period: year + label: West Virginia LIEAP fpg rate + reference: + - title: West Virginia accepted FY2026 LIHEAP State Plan, heating eligibility + href: https://liheapch.acf.gov/docs/2026/state-plans/WV_Plan_2026.pdf#page=9,11 diff --git a/policyengine_us/parameters/gov/states/wv/dhhr/lieap/eligibility/fpg_year_lag.yaml b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/eligibility/fpg_year_lag.yaml new file mode 100644 index 00000000000..a3dcc2b5d8c --- /dev/null +++ b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/eligibility/fpg_year_lag.yaml @@ -0,0 +1,10 @@ +description: West Virginia uses poverty guidelines from this many calendar years before the benefit year under the Low Income Energy Assistance Program. +values: + 2025-10-01: 1 +metadata: + unit: int + period: year + label: West Virginia LIEAP fpg year lag + reference: + - title: West Virginia accepted FY2026 LIHEAP State Plan, heating eligibility + href: https://liheapch.acf.gov/docs/2026/state-plans/WV_Plan_2026.pdf#page=9,11 diff --git a/policyengine_us/parameters/gov/states/wv/dhhr/lieap/eligibility/smi_max_household_size.yaml b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/eligibility/smi_max_household_size.yaml new file mode 100644 index 00000000000..c0d8a1b56e4 --- /dev/null +++ b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/eligibility/smi_max_household_size.yaml @@ -0,0 +1,10 @@ +description: West Virginia uses state median income through this household size under the Low Income Energy Assistance Program. +values: + 2025-10-01: 7 +metadata: + unit: int + period: year + label: West Virginia LIEAP smi max household size + reference: + - title: West Virginia accepted FY2026 LIHEAP State Plan, heating eligibility + href: https://liheapch.acf.gov/docs/2026/state-plans/WV_Plan_2026.pdf#page=9,11 diff --git a/policyengine_us/parameters/gov/states/wv/dhhr/lieap/eligibility/smi_rate.yaml b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/eligibility/smi_rate.yaml new file mode 100644 index 00000000000..8f1bed4dfa6 --- /dev/null +++ b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/eligibility/smi_rate.yaml @@ -0,0 +1,10 @@ +description: West Virginia limits income to this share of state median income for smaller households under the Low Income Energy Assistance Program. +values: + 2025-10-01: 0.6 +metadata: + unit: /1 + period: year + label: West Virginia LIEAP smi rate + reference: + - title: West Virginia accepted FY2026 LIHEAP State Plan, heating eligibility + href: https://liheapch.acf.gov/docs/2026/state-plans/WV_Plan_2026.pdf#page=9,11 diff --git a/policyengine_us/programs.yaml b/policyengine_us/programs.yaml index 756dc2c4988..b0c88c46813 100644 --- a/policyengine_us/programs.yaml +++ b/policyengine_us/programs.yaml @@ -846,6 +846,13 @@ 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: WV + status: in_progress + name: West Virginia LIEAP components + full_name: West Virginia Low Income Energy Assistance Program components + parameter_prefix: gov.states.wv.dhhr.lieap + verified_years: "2026-2027" + notes: "Household-size and income-limit components only. No final countable income, eligibility or regular benefit: published payment intervals overlap and income-category guidance conflicts. Annual inputs and SPM units approximate application circumstances. Earlier backfills are unverified historical estimates. Crisis, cooling, weatherization and equipment remain outside scope." # --- SSA programs --- - id: ssi diff --git a/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_household_size.yaml b/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_household_size.yaml new file mode 100644 index 00000000000..9bf96064ee2 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_household_size.yaml @@ -0,0 +1,127 @@ +# Household composition: earlier official IMM21.3.1.B, physical1728; +# current IMM21.3.1.B and citizenship, physical1729,1734. +# https://bfa.wv.gov/media/39948/download?inline=#page=1728 +# https://bfa.wv.gov/media/40005/download?inline=#page=1729,1734 +# The SPM unit approximates the assistance group sharing heat costs. +# These component tests make no claim about income or final benefit eligibility. + +- name: Case 1, one qualified adult is counted. + period: 2026 + input: + people: + person1: {age: 40, is_citizen_or_legal_immigrant: true} + spm_units: + spm_unit1: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_200 + households: + household1: + members: [person1] + state_code: WV + output: + wv_lieap_household_size: 1 + +- name: Case 2, qualified adults and children count while nonqualified members do not. + period: 2026 + input: + people: + person1: {age: 40, is_citizen_or_legal_immigrant: true} + person2: {age: 38, is_citizen_or_legal_immigrant: false} + person3: {age: 15, is_citizen_or_legal_immigrant: true} + person4: {age: 8, is_citizen_or_legal_immigrant: true} + person5: {age: 65, is_citizen_or_legal_immigrant: false} + spm_units: + spm_unit1: + members: [person1, person2, person3, person4, person5] + heating_type: NATURAL_GAS + gas_expense: 1_200 + households: + household1: + members: [person1, person2, person3, person4, person5] + state_code: WV + output: + wv_lieap_household_size: 3 + +- name: Case 3, an entirely nonqualified household has no qualified members. + period: 2026 + input: + people: + person1: {age: 40, is_citizen_or_legal_immigrant: false} + person2: {age: 38, is_citizen_or_legal_immigrant: false} + spm_units: + spm_unit1: + members: [person1, person2] + heating_type: NATURAL_GAS + gas_expense: 1_200 + households: + household1: + members: [person1, person2] + state_code: WV + output: + wv_lieap_household_size: 0 + +- name: Case 4, qualified children count even when the adults are nonqualified. + period: 2026 + input: + people: + person1: {age: 40, is_citizen_or_legal_immigrant: false} + person2: {age: 38, is_citizen_or_legal_immigrant: false} + person3: {age: 15, is_citizen_or_legal_immigrant: true} + person4: {age: 8, is_citizen_or_legal_immigrant: true} + spm_units: + spm_unit1: + members: [person1, person2, person3, person4] + heating_type: NATURAL_GAS + gas_expense: 1_200 + households: + household1: + members: [person1, person2, person3, person4] + state_code: WV + output: + wv_lieap_household_size: 2 + +- name: Case 5, mixed states and qualification counts remain independent. + period: 2026 + input: + people: + person1: {age: 40, is_citizen_or_legal_immigrant: true} + person2: {age: 38, is_citizen_or_legal_immigrant: false} + person3: {age: 40, is_citizen_or_legal_immigrant: true} + person4: {age: 38, is_citizen_or_legal_immigrant: true} + person5: {age: 40, is_citizen_or_legal_immigrant: true} + person6: {age: 38, is_citizen_or_legal_immigrant: true} + person7: {age: 8, is_citizen_or_legal_immigrant: true} + person8: {age: 50, is_citizen_or_legal_immigrant: false} + spm_units: + spm_unit1: + members: [person1, person2] + heating_type: NATURAL_GAS + gas_expense: 1_200 + spm_unit2: + members: [person3, person4] + heating_type: NATURAL_GAS + gas_expense: 1_200 + spm_unit3: + members: [person5, person6, person7] + heating_type: NATURAL_GAS + gas_expense: 1_200 + spm_unit4: + members: [person8] + heating_type: NATURAL_GAS + gas_expense: 1_200 + households: + household1: + members: [person1, person2] + state_code: WV + household2: + members: [person3, person4] + state_code: OH + household3: + members: [person5, person6, person7] + state_code: WV + household4: + members: [person8] + state_code: WV + output: + wv_lieap_household_size: [1, 0, 3, 0] diff --git a/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_income_limit.yaml b/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_income_limit.yaml new file mode 100644 index 00000000000..82ba665e75f --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_income_limit.yaml @@ -0,0 +1,641 @@ +# Sources: FY2026 agency table gives sizes1–10; earlier IMM gives size11. +# https://bfa.wv.gov/utility-assistancelieap +# https://bfa.wv.gov/media/39948/download?inline=#page=1772,1773 +# FY2027 adopted operational IMM gives separately verified sizes1–11. +# https://bfa.wv.gov/media/40005/download?inline=#page=1775,1776 +# The60%SMI-through7 /150%FPG-from8 split is explicit in the accepted FY2026 plan. +# https://liheapch.acf.gov/docs/2026/state-plans/WV_Plan_2026.pdf#page=11 +# Expected limits are published monthly amounts multiplied by12, independently +# checked with Decimal arithmetic; no model formula was used to generate them. +# FY2026 size11 is8831/month, not the agency shorthand8144+688=8832. +# Payment-grid overlaps and larger-family defects are outside this component. + +- name: Case 1, FY2026 published limit for 1 qualified members. + period: 2026 + absolute_error_margin: 0.01 + # 60% requested-year SMI; published $2,454/month x12 =$29,448/year. + input: + people: + person1: {age: 70, is_citizen_or_legal_immigrant: true} + spm_units: + spm_unit1: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_200 + households: + household1: + members: [person1] + state_code: WV + output: + wv_lieap_income_limit: 29_448 + +- name: Case 2, FY2026 published limit for 2 qualified members. + period: 2026 + absolute_error_margin: 0.01 + # 60% requested-year SMI; published $3,209/month x12 =$38,508/year. + input: + people: + person1: {age: 70, is_citizen_or_legal_immigrant: true} + person2: {age: 68, is_citizen_or_legal_immigrant: true} + spm_units: + spm_unit1: + members: [person1, person2] + heating_type: NATURAL_GAS + gas_expense: 1_200 + households: + household1: + members: [person1, person2] + state_code: WV + output: + wv_lieap_income_limit: 38_508 + +- name: Case 3, FY2026 published limit for 3 qualified members. + period: 2026 + absolute_error_margin: 0.01 + # 60% requested-year SMI; published $3,965/month x12 =$47,580/year. + input: + people: + person1: {age: 70, is_citizen_or_legal_immigrant: true} + person2: {age: 68, is_citizen_or_legal_immigrant: true} + person3: {age: 45, is_citizen_or_legal_immigrant: true} + spm_units: + spm_unit1: + members: [person1, person2, person3] + heating_type: NATURAL_GAS + gas_expense: 1_200 + households: + household1: + members: [person1, person2, person3] + state_code: WV + output: + wv_lieap_income_limit: 47_580 + +- name: Case 4, FY2026 published limit for 4 qualified members. + period: 2026 + absolute_error_margin: 0.01 + # 60% requested-year SMI; published $4,720/month x12 =$56,640/year. + input: + people: + person1: {age: 70, is_citizen_or_legal_immigrant: true} + person2: {age: 68, is_citizen_or_legal_immigrant: true} + person3: {age: 45, is_citizen_or_legal_immigrant: true} + person4: {age: 44, is_citizen_or_legal_immigrant: true} + spm_units: + spm_unit1: + members: [person1, person2, person3, person4] + heating_type: NATURAL_GAS + gas_expense: 1_200 + households: + household1: + members: [person1, person2, person3, person4] + state_code: WV + output: + wv_lieap_income_limit: 56_640 + +- name: Case 5, FY2026 published limit for 5 qualified members. + period: 2026 + absolute_error_margin: 0.01 + # 60% requested-year SMI; published $5,475/month x12 =$65,700/year. + input: + people: + person1: {age: 70, is_citizen_or_legal_immigrant: true} + person2: {age: 68, is_citizen_or_legal_immigrant: true} + person3: {age: 45, is_citizen_or_legal_immigrant: true} + person4: {age: 44, is_citizen_or_legal_immigrant: true} + person5: {age: 22, is_citizen_or_legal_immigrant: true} + spm_units: + spm_unit1: + members: [person1, person2, person3, person4, person5] + heating_type: NATURAL_GAS + gas_expense: 1_200 + households: + household1: + members: [person1, person2, person3, person4, person5] + state_code: WV + output: + wv_lieap_income_limit: 65_700 + +- name: Case 6, FY2026 published limit for 6 qualified members. + period: 2026 + absolute_error_margin: 0.01 + # 60% requested-year SMI; published $6,230/month x12 =$74,760/year. + input: + people: + person1: {age: 70, is_citizen_or_legal_immigrant: true} + person2: {age: 68, is_citizen_or_legal_immigrant: true} + person3: {age: 45, is_citizen_or_legal_immigrant: true} + person4: {age: 44, is_citizen_or_legal_immigrant: true} + person5: {age: 22, is_citizen_or_legal_immigrant: true} + person6: {age: 17, is_citizen_or_legal_immigrant: true} + spm_units: + spm_unit1: + members: [person1, person2, person3, person4, person5, person6] + heating_type: NATURAL_GAS + gas_expense: 1_200 + households: + household1: + members: [person1, person2, person3, person4, person5, person6] + state_code: WV + output: + wv_lieap_income_limit: 74_760 + +- name: Case 7, FY2026 published limit for 7 qualified members. + period: 2026 + absolute_error_margin: 0.01 + # 60% requested-year SMI; published $6,372/month x12 =$76,464/year. + input: + people: + person1: {age: 70, is_citizen_or_legal_immigrant: true} + person2: {age: 68, is_citizen_or_legal_immigrant: true} + person3: {age: 45, is_citizen_or_legal_immigrant: true} + person4: {age: 44, is_citizen_or_legal_immigrant: true} + person5: {age: 22, is_citizen_or_legal_immigrant: true} + person6: {age: 17, is_citizen_or_legal_immigrant: true} + person7: {age: 15, is_citizen_or_legal_immigrant: true} + spm_units: + spm_unit1: + members: [person1, person2, person3, person4, person5, person6, person7] + heating_type: NATURAL_GAS + gas_expense: 1_200 + households: + household1: + members: [person1, person2, person3, person4, person5, person6, person7] + state_code: WV + output: + wv_lieap_income_limit: 76_464 + +- name: Case 8, FY2026 published limit for 8 qualified members. + period: 2026 + absolute_error_margin: 0.01 + # 150% prior-year FPG; published $6,769/month x12 =$81,228/year. + input: + people: + person1: {age: 70, is_citizen_or_legal_immigrant: true} + person2: {age: 68, is_citizen_or_legal_immigrant: true} + person3: {age: 45, is_citizen_or_legal_immigrant: true} + person4: {age: 44, is_citizen_or_legal_immigrant: true} + person5: {age: 22, is_citizen_or_legal_immigrant: true} + person6: {age: 17, is_citizen_or_legal_immigrant: true} + person7: {age: 15, is_citizen_or_legal_immigrant: true} + person8: {age: 12, is_citizen_or_legal_immigrant: true} + spm_units: + spm_unit1: + members: [person1, person2, person3, person4, person5, person6, person7, person8] + heating_type: NATURAL_GAS + gas_expense: 1_200 + households: + household1: + members: [person1, person2, person3, person4, person5, person6, person7, person8] + state_code: WV + output: + wv_lieap_income_limit: 81_228 + +- name: Case 9, FY2026 published limit for 9 qualified members. + period: 2026 + absolute_error_margin: 0.01 + # 150% prior-year FPG; published $7,456/month x12 =$89,472/year. + input: + people: + person1: {age: 70, is_citizen_or_legal_immigrant: true} + person2: {age: 68, is_citizen_or_legal_immigrant: true} + person3: {age: 45, is_citizen_or_legal_immigrant: true} + person4: {age: 44, is_citizen_or_legal_immigrant: true} + person5: {age: 22, is_citizen_or_legal_immigrant: true} + person6: {age: 17, is_citizen_or_legal_immigrant: true} + person7: {age: 15, is_citizen_or_legal_immigrant: true} + person8: {age: 12, is_citizen_or_legal_immigrant: true} + person9: {age: 9, is_citizen_or_legal_immigrant: true} + spm_units: + spm_unit1: + members: [person1, person2, person3, person4, person5, person6, person7, person8, person9] + heating_type: NATURAL_GAS + gas_expense: 1_200 + households: + household1: + members: [person1, person2, person3, person4, person5, person6, person7, person8, person9] + state_code: WV + output: + wv_lieap_income_limit: 89_472 + +- name: Case 10, FY2026 published limit for 10 qualified members. + period: 2026 + absolute_error_margin: 0.01 + # 150% prior-year FPG; published $8,144/month x12 =$97,728/year. + input: + people: + person1: {age: 70, is_citizen_or_legal_immigrant: true} + person2: {age: 68, is_citizen_or_legal_immigrant: true} + person3: {age: 45, is_citizen_or_legal_immigrant: true} + person4: {age: 44, is_citizen_or_legal_immigrant: true} + person5: {age: 22, is_citizen_or_legal_immigrant: true} + person6: {age: 17, is_citizen_or_legal_immigrant: true} + person7: {age: 15, is_citizen_or_legal_immigrant: true} + person8: {age: 12, is_citizen_or_legal_immigrant: true} + person9: {age: 9, is_citizen_or_legal_immigrant: true} + person10: {age: 7, is_citizen_or_legal_immigrant: true} + spm_units: + spm_unit1: + members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10] + heating_type: NATURAL_GAS + gas_expense: 1_200 + households: + household1: + members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10] + state_code: WV + output: + wv_lieap_income_limit: 97_728 + +- name: Case 11, FY2026 published limit for 11 qualified members. + period: 2026 + absolute_error_margin: 0.01 + # 150% prior-year FPG; published $8,831/month x12 =$105,972/year. + input: + people: + person1: {age: 70, is_citizen_or_legal_immigrant: true} + person2: {age: 68, is_citizen_or_legal_immigrant: true} + person3: {age: 45, is_citizen_or_legal_immigrant: true} + person4: {age: 44, is_citizen_or_legal_immigrant: true} + person5: {age: 22, is_citizen_or_legal_immigrant: true} + person6: {age: 17, is_citizen_or_legal_immigrant: true} + person7: {age: 15, is_citizen_or_legal_immigrant: true} + person8: {age: 12, is_citizen_or_legal_immigrant: true} + person9: {age: 9, is_citizen_or_legal_immigrant: true} + person10: {age: 7, is_citizen_or_legal_immigrant: true} + person11: {age: 3, is_citizen_or_legal_immigrant: true} + spm_units: + spm_unit1: + members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10, person11] + heating_type: NATURAL_GAS + gas_expense: 1_200 + households: + household1: + members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10, person11] + state_code: WV + output: + wv_lieap_income_limit: 105_972 + +- name: Case 12, FY2027 published limit for 1 qualified members. + period: 2027 + absolute_error_margin: 0.01 + # 60% requested-year SMI; published $2,550/month x12 =$30,600/year. + input: + people: + person1: {age: 70, is_citizen_or_legal_immigrant: true} + spm_units: + spm_unit1: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_200 + households: + household1: + members: [person1] + state_code: WV + output: + wv_lieap_income_limit: 30_600 + +- name: Case 13, FY2027 published limit for 2 qualified members. + period: 2027 + absolute_error_margin: 0.01 + # 60% requested-year SMI; published $3,335/month x12 =$40,020/year. + input: + people: + person1: {age: 70, is_citizen_or_legal_immigrant: true} + person2: {age: 68, is_citizen_or_legal_immigrant: true} + spm_units: + spm_unit1: + members: [person1, person2] + heating_type: NATURAL_GAS + gas_expense: 1_200 + households: + household1: + members: [person1, person2] + state_code: WV + output: + wv_lieap_income_limit: 40_020 + +- name: Case 14, FY2027 published limit for 3 qualified members. + period: 2027 + absolute_error_margin: 0.01 + # 60% requested-year SMI; published $4,120/month x12 =$49,440/year. + input: + people: + person1: {age: 70, is_citizen_or_legal_immigrant: true} + person2: {age: 68, is_citizen_or_legal_immigrant: true} + person3: {age: 45, is_citizen_or_legal_immigrant: true} + spm_units: + spm_unit1: + members: [person1, person2, person3] + heating_type: NATURAL_GAS + gas_expense: 1_200 + households: + household1: + members: [person1, person2, person3] + state_code: WV + output: + wv_lieap_income_limit: 49_440 + +- name: Case 15, FY2027 published limit for 4 qualified members. + period: 2027 + absolute_error_margin: 0.01 + # 60% requested-year SMI; published $4,904/month x12 =$58,848/year. + input: + people: + person1: {age: 70, is_citizen_or_legal_immigrant: true} + person2: {age: 68, is_citizen_or_legal_immigrant: true} + person3: {age: 45, is_citizen_or_legal_immigrant: true} + person4: {age: 44, is_citizen_or_legal_immigrant: true} + spm_units: + spm_unit1: + members: [person1, person2, person3, person4] + heating_type: NATURAL_GAS + gas_expense: 1_200 + households: + household1: + members: [person1, person2, person3, person4] + state_code: WV + output: + wv_lieap_income_limit: 58_848 + +- name: Case 16, FY2027 published limit for 5 qualified members. + period: 2027 + absolute_error_margin: 0.01 + # 60% requested-year SMI; published $5,689/month x12 =$68,268/year. + input: + people: + person1: {age: 70, is_citizen_or_legal_immigrant: true} + person2: {age: 68, is_citizen_or_legal_immigrant: true} + person3: {age: 45, is_citizen_or_legal_immigrant: true} + person4: {age: 44, is_citizen_or_legal_immigrant: true} + person5: {age: 22, is_citizen_or_legal_immigrant: true} + spm_units: + spm_unit1: + members: [person1, person2, person3, person4, person5] + heating_type: NATURAL_GAS + gas_expense: 1_200 + households: + household1: + members: [person1, person2, person3, person4, person5] + state_code: WV + output: + wv_lieap_income_limit: 68_268 + +- name: Case 17, FY2027 published limit for 6 qualified members. + period: 2027 + absolute_error_margin: 0.01 + # 60% requested-year SMI; published $6,474/month x12 =$77,688/year. + input: + people: + person1: {age: 70, is_citizen_or_legal_immigrant: true} + person2: {age: 68, is_citizen_or_legal_immigrant: true} + person3: {age: 45, is_citizen_or_legal_immigrant: true} + person4: {age: 44, is_citizen_or_legal_immigrant: true} + person5: {age: 22, is_citizen_or_legal_immigrant: true} + person6: {age: 17, is_citizen_or_legal_immigrant: true} + spm_units: + spm_unit1: + members: [person1, person2, person3, person4, person5, person6] + heating_type: NATURAL_GAS + gas_expense: 1_200 + households: + household1: + members: [person1, person2, person3, person4, person5, person6] + state_code: WV + output: + wv_lieap_income_limit: 77_688 + +- name: Case 18, FY2027 published limit for 7 qualified members. + period: 2027 + absolute_error_margin: 0.01 + # 60% requested-year SMI; published $6,621/month x12 =$79,452/year. + input: + people: + person1: {age: 70, is_citizen_or_legal_immigrant: true} + person2: {age: 68, is_citizen_or_legal_immigrant: true} + person3: {age: 45, is_citizen_or_legal_immigrant: true} + person4: {age: 44, is_citizen_or_legal_immigrant: true} + person5: {age: 22, is_citizen_or_legal_immigrant: true} + person6: {age: 17, is_citizen_or_legal_immigrant: true} + person7: {age: 15, is_citizen_or_legal_immigrant: true} + spm_units: + spm_unit1: + members: [person1, person2, person3, person4, person5, person6, person7] + heating_type: NATURAL_GAS + gas_expense: 1_200 + households: + household1: + members: [person1, person2, person3, person4, person5, person6, person7] + state_code: WV + output: + wv_lieap_income_limit: 79_452 + +- name: Case 19, FY2027 published limit for 8 qualified members. + period: 2027 + absolute_error_margin: 0.01 + # 150% prior-year FPG; published $6,965/month x12 =$83,580/year. + input: + people: + person1: {age: 70, is_citizen_or_legal_immigrant: true} + person2: {age: 68, is_citizen_or_legal_immigrant: true} + person3: {age: 45, is_citizen_or_legal_immigrant: true} + person4: {age: 44, is_citizen_or_legal_immigrant: true} + person5: {age: 22, is_citizen_or_legal_immigrant: true} + person6: {age: 17, is_citizen_or_legal_immigrant: true} + person7: {age: 15, is_citizen_or_legal_immigrant: true} + person8: {age: 12, is_citizen_or_legal_immigrant: true} + spm_units: + spm_unit1: + members: [person1, person2, person3, person4, person5, person6, person7, person8] + heating_type: NATURAL_GAS + gas_expense: 1_200 + households: + household1: + members: [person1, person2, person3, person4, person5, person6, person7, person8] + state_code: WV + output: + wv_lieap_income_limit: 83_580 + +- name: Case 20, FY2027 published limit for 9 qualified members. + period: 2027 + absolute_error_margin: 0.01 + # 150% prior-year FPG; published $7,675/month x12 =$92,100/year. + input: + people: + person1: {age: 70, is_citizen_or_legal_immigrant: true} + person2: {age: 68, is_citizen_or_legal_immigrant: true} + person3: {age: 45, is_citizen_or_legal_immigrant: true} + person4: {age: 44, is_citizen_or_legal_immigrant: true} + person5: {age: 22, is_citizen_or_legal_immigrant: true} + person6: {age: 17, is_citizen_or_legal_immigrant: true} + person7: {age: 15, is_citizen_or_legal_immigrant: true} + person8: {age: 12, is_citizen_or_legal_immigrant: true} + person9: {age: 9, is_citizen_or_legal_immigrant: true} + spm_units: + spm_unit1: + members: [person1, person2, person3, person4, person5, person6, person7, person8, person9] + heating_type: NATURAL_GAS + gas_expense: 1_200 + households: + household1: + members: [person1, person2, person3, person4, person5, person6, person7, person8, person9] + state_code: WV + output: + wv_lieap_income_limit: 92_100 + +- name: Case 21, FY2027 published limit for 10 qualified members. + period: 2027 + absolute_error_margin: 0.01 + # 150% prior-year FPG; published $8,385/month x12 =$100,620/year. + input: + people: + person1: {age: 70, is_citizen_or_legal_immigrant: true} + person2: {age: 68, is_citizen_or_legal_immigrant: true} + person3: {age: 45, is_citizen_or_legal_immigrant: true} + person4: {age: 44, is_citizen_or_legal_immigrant: true} + person5: {age: 22, is_citizen_or_legal_immigrant: true} + person6: {age: 17, is_citizen_or_legal_immigrant: true} + person7: {age: 15, is_citizen_or_legal_immigrant: true} + person8: {age: 12, is_citizen_or_legal_immigrant: true} + person9: {age: 9, is_citizen_or_legal_immigrant: true} + person10: {age: 7, is_citizen_or_legal_immigrant: true} + spm_units: + spm_unit1: + members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10] + heating_type: NATURAL_GAS + gas_expense: 1_200 + households: + household1: + members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10] + state_code: WV + output: + wv_lieap_income_limit: 100_620 + +- name: Case 22, FY2027 published limit for 11 qualified members. + period: 2027 + absolute_error_margin: 0.01 + # 150% prior-year FPG; published $9,095/month x12 =$109,140/year. + input: + people: + person1: {age: 70, is_citizen_or_legal_immigrant: true} + person2: {age: 68, is_citizen_or_legal_immigrant: true} + person3: {age: 45, is_citizen_or_legal_immigrant: true} + person4: {age: 44, is_citizen_or_legal_immigrant: true} + person5: {age: 22, is_citizen_or_legal_immigrant: true} + person6: {age: 17, is_citizen_or_legal_immigrant: true} + person7: {age: 15, is_citizen_or_legal_immigrant: true} + person8: {age: 12, is_citizen_or_legal_immigrant: true} + person9: {age: 9, is_citizen_or_legal_immigrant: true} + person10: {age: 7, is_citizen_or_legal_immigrant: true} + person11: {age: 3, is_citizen_or_legal_immigrant: true} + spm_units: + spm_unit1: + members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10, person11] + heating_type: NATURAL_GAS + gas_expense: 1_200 + households: + household1: + members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10, person11] + state_code: WV + output: + wv_lieap_income_limit: 109_140 + +- name: Case 23, eight residents with seven qualified members stay on the SMI branch. + period: 2026 + absolute_error_margin: 0.01 + # Qualified size7: FY2026 monthly6372 x12 =76464. + input: + people: + person1: {age: 70, is_citizen_or_legal_immigrant: true} + person2: {age: 68, is_citizen_or_legal_immigrant: true} + person3: {age: 45, is_citizen_or_legal_immigrant: true} + person4: {age: 44, is_citizen_or_legal_immigrant: true} + person5: {age: 22, is_citizen_or_legal_immigrant: true} + person6: {age: 17, is_citizen_or_legal_immigrant: true} + person7: {age: 15, is_citizen_or_legal_immigrant: true} + person8: {age: 12, is_citizen_or_legal_immigrant: false} + spm_units: + spm_unit1: + members: [person1, person2, person3, person4, person5, person6, person7, person8] + heating_type: NATURAL_GAS + gas_expense: 1_200 + households: + household1: + members: [person1, person2, person3, person4, person5, person6, person7, person8] + state_code: WV + output: + wv_lieap_income_limit: 76_464 + +- name: Case 24, nine residents with eight qualified members use the FPG branch. + period: 2026 + absolute_error_margin: 0.01 + # Qualified size8: FY2026 monthly6769 x12 =81228. + input: + people: + person1: {age: 70, is_citizen_or_legal_immigrant: true} + person2: {age: 68, is_citizen_or_legal_immigrant: true} + person3: {age: 45, is_citizen_or_legal_immigrant: true} + person4: {age: 44, is_citizen_or_legal_immigrant: true} + person5: {age: 22, is_citizen_or_legal_immigrant: true} + person6: {age: 17, is_citizen_or_legal_immigrant: true} + person7: {age: 15, is_citizen_or_legal_immigrant: true} + person8: {age: 12, is_citizen_or_legal_immigrant: true} + person9: {age: 9, is_citizen_or_legal_immigrant: false} + spm_units: + spm_unit1: + members: [person1, person2, person3, person4, person5, person6, person7, person8, person9] + heating_type: NATURAL_GAS + gas_expense: 1_200 + households: + household1: + members: [person1, person2, person3, person4, person5, person6, person7, person8, person9] + state_code: WV + output: + wv_lieap_income_limit: 81_228 + +- name: Case 25, mixed WV and neighboring-state households retain independent limits. + period: 2026 + absolute_error_margin: 0.01 + # WV sizes1/8 use2454/6769 monthly; WV variable is zero in Ohio. + input: + people: + person1: {age: 40, is_citizen_or_legal_immigrant: true} + person2: {age: 70, is_citizen_or_legal_immigrant: true} + person3: {age: 68, is_citizen_or_legal_immigrant: true} + person4: {age: 45, is_citizen_or_legal_immigrant: true} + person5: {age: 44, is_citizen_or_legal_immigrant: true} + person6: {age: 22, is_citizen_or_legal_immigrant: true} + person7: {age: 17, is_citizen_or_legal_immigrant: true} + person8: {age: 15, is_citizen_or_legal_immigrant: true} + person9: {age: 12, is_citizen_or_legal_immigrant: true} + person10: {age: 70, is_citizen_or_legal_immigrant: true} + person11: {age: 68, is_citizen_or_legal_immigrant: true} + person12: {age: 45, is_citizen_or_legal_immigrant: true} + person13: {age: 44, is_citizen_or_legal_immigrant: true} + person14: {age: 22, is_citizen_or_legal_immigrant: true} + person15: {age: 17, is_citizen_or_legal_immigrant: true} + person16: {age: 15, is_citizen_or_legal_immigrant: true} + person17: {age: 12, is_citizen_or_legal_immigrant: true} + spm_units: + spm_unit1: + members: [person1] + heating_type: NATURAL_GAS + gas_expense: 1_200 + spm_unit2: + members: [person2, person3, person4, person5, person6, person7, person8, person9] + heating_type: NATURAL_GAS + gas_expense: 1_200 + spm_unit3: + members: [person10, person11, person12, person13, person14, person15, person16, person17] + heating_type: NATURAL_GAS + gas_expense: 1_200 + households: + household1: + members: [person1] + state_code: WV + household2: + members: [person2, person3, person4, person5, person6, person7, person8, person9] + state_code: OH + household3: + members: [person10, person11, person12, person13, person14, person15, person16, person17] + state_code: WV + output: + wv_lieap_income_limit: [29448, 0, 81228] diff --git a/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_household_size.py b/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_household_size.py new file mode 100644 index 00000000000..c4b6ba8d128 --- /dev/null +++ b/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_household_size.py @@ -0,0 +1,17 @@ +from policyengine_us.model_api import * + + +class wv_lieap_household_size(Variable): + value_type = int + entity = SPMUnit + label = "West Virginia LIEAP qualified household size" + definition_period = YEAR + defined_for = StateCode.WV + reference = ( + "https://bfa.wv.gov/media/39948/download?inline=#page=1728,1732", + "https://bfa.wv.gov/media/40005/download?inline=#page=1729,1734", + ) + # SPMUnit approximates the co-resident energy-sharing assistance group. + # Prior-season benefit recipients are excluded by policy, but that receipt + # history is unavailable. Nonqualified members' income remains countable. + adds = ["is_citizen_or_legal_immigrant"] diff --git a/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_income_limit.py b/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_income_limit.py new file mode 100644 index 00000000000..1a248957cb6 --- /dev/null +++ b/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_income_limit.py @@ -0,0 +1,33 @@ +from policyengine_us.model_api import * +from policyengine_us.variables.gov.hhs.hhs_smi import smi +from policyengine_us.variables.gov.hhs.tax_unit_fpg import fpg + + +class wv_lieap_income_limit(Variable): + value_type = float + entity = SPMUnit + label = "West Virginia LIEAP annual income limit" + unit = USD + definition_period = YEAR + defined_for = StateCode.WV + reference = ( + "https://liheapch.acf.gov/docs/2026/state-plans/WV_Plan_2026.pdf#page=9,11", + "https://bfa.wv.gov/utility-assistancelieap", + "https://bfa.wv.gov/media/40005/download?inline=#page=1734,1775,1776", + ) + + def formula(spm_unit, period, parameters): + size = spm_unit("wv_lieap_household_size", period) + state = spm_unit.household("state_code_str", period) + group = spm_unit.household("state_group_str", period) + p = parameters(period).gov.states.wv.dhhr.lieap.eligibility + annual_smi = p.smi_rate * smi(size, state, period, parameters) + annual_fpg = p.fpg_rate * fpg( + max_(size, 1), group, period, parameters, year_lag=p.fpg_year_lag + ) + annual = where(size <= p.smi_max_household_size, annual_smi, annual_fpg) + # Nearest-dollar monthly rounding matches all ten published agency rows. + # Apply the actual guideline to additional members, rather than repeatedly + # adding a rounded increment; the latter diverges from the manual at 11. + monthly = np.floor(annual / MONTHS_IN_YEAR + 0.5) + return where(size > 0, monthly * MONTHS_IN_YEAR, 0) From b02a38bb4a28d8a2ddb295f446fba81ac5e2d526 Mon Sep 17 00:00:00 2001 From: Ziming Date: Sat, 3 Oct 2026 21:35:39 -0400 Subject: [PATCH 2/7] Add West Virginia LIEAP countable income from operational manual --- changelog.d/wv-liheap-wave2c.added.md | 2 +- .../gov/states/wv/dhhr/lieap/README.md | 37 +- .../lieap/income/nonnegative_sources.yaml | 20 + .../states/wv/dhhr/lieap/income/sources.yaml | 34 + policyengine_us/programs.yaml | 2 +- .../dhhr/lieap/wv_lieap_countable_income.yaml | 586 ++++++++++++++++++ .../dhhr/lieap/wv_lieap_countable_income.py | 28 + 7 files changed, 701 insertions(+), 8 deletions(-) create mode 100644 policyengine_us/parameters/gov/states/wv/dhhr/lieap/income/nonnegative_sources.yaml create mode 100644 policyengine_us/parameters/gov/states/wv/dhhr/lieap/income/sources.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_countable_income.yaml create mode 100644 policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_countable_income.py diff --git a/changelog.d/wv-liheap-wave2c.added.md b/changelog.d/wv-liheap-wave2c.added.md index 76b0ca80b93..cad1cf817bb 100644 --- a/changelog.d/wv-liheap-wave2c.added.md +++ b/changelog.d/wv-liheap-wave2c.added.md @@ -1 +1 @@ -Add West Virginia LIEAP qualified household-size and income-limit components; countable income and final heating awards remain incomplete pending source conflicts. +Add West Virginia LIEAP qualified household size, income limits and countable income based on the operational manual; final eligibility and heating awards remain incomplete pending source conflicts. diff --git a/policyengine_us/parameters/gov/states/wv/dhhr/lieap/README.md b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/README.md index 9ebdc88761b..2e48ae3cba8 100644 --- a/policyengine_us/parameters/gov/states/wv/dhhr/lieap/README.md +++ b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/README.md @@ -1,6 +1,6 @@ # West Virginia regular heating components -The qualified household-size and income-limit components use the FY2026 state +The qualified household-size, countable-income and income-limit components use the FY2026 state plan and operational manuals, including the adopted October 2026 update for FY2027. The assistance group includes co-residents sharing heating costs. Qualified members count in its size; nonqualified members' income @@ -20,16 +20,41 @@ sizes one through eleven. The payment grid's apparent size-twelve maximum of $10,160 conflicts with the guideline-derived $9,805; payment cells do not replace the stated income eligibility rule. -Countable income, final eligibility and benefit remain incomplete. The manual's -all-income rule conflicts with some unchecked state-plan categories, including -TANF, general assistance and minor earnings; the acquired sources do not settle -that conflict. Both exclude Social Security and SSI. The FY2026 payment chart +Countable income follows the detailed operational manual, which current Board +of Review decisions apply, over unchecked summary-plan categories. This is an +explicit source-priority interpretation: minor earnings, TANF, general +assistance and recurring gifts count. RSDI and SSI do not. The manual distinguishes +excluded nonrecurring lump sums from recurring payments prorated over the period +they cover. Annual income fields approximate recurring application-month income. +Existing net business inputs receive no second 20% deduction, and business or +estate losses do not offset other sources under this modeling approximation. This does +not reproduce the source's gross-receipts calculation. + +Pension, retirement-account and non-Social-Security survivor aggregates enter +once. Narrower military or pension-survivor tax-detail inputs are not added again +because they can describe the same receipts. Recurring receipts should be +represented in the corresponding broad income fields. Monthly WV WORKS is +annualized once. Separate royalties and foster-care receipts are not identified +by existing inputs. Generic VA benefits cannot separate excluded Aid and +Attendance, and employment cannot separate excluded work-study, CNCS or CSEP +wages. A work-study participation flag cannot determine which wages to subtract. +Aggregate child support, retirement, insurance, estate and gift inputs cannot +identify every recurring payment, arrearage or earmarked reimbursement. These +are input limitations, not blanket legal inclusions or exclusions. Standalone +capital gains, life-insurance death proceeds and gambling/lottery winnings are +treated as nonrecurring; an actual recurring installment needs a separately +identified receipt that existing inputs do not provide. Rental inputs are +assumed nonnegative, and Medicare deductions remain deferred. + +Final eligibility and benefits remain incomplete. The ordinary-ceiling and +categorical plan wording is not fully reconciled; no income-eligibility bypass +is inferred from the plan's checkboxes. The FY2026 payment chart has overlapping first/second income bands and anomalous larger-family cells. The October 2026 operational manual repeats an overlap in FY2027. The source library preserves both literal grids and their edition details; the model does not silently correct them or encode unmodeled eligible benefits as zero. -Only the household-size and income-limit components are verified for FY2026 and +Only the household-size, countable-income and income-limit components are verified for FY2026 and FY2027. Earlier backfilled results are unverified historical estimates; the whole program is not verified for either year. The full regular-heating goal remains open. Crisis, cooling, weatherization, equipment and the separate utility discount are out of scope. diff --git a/policyengine_us/parameters/gov/states/wv/dhhr/lieap/income/nonnegative_sources.yaml b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/income/nonnegative_sources.yaml new file mode 100644 index 00000000000..40d4b718cfc --- /dev/null +++ b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/income/nonnegative_sources.yaml @@ -0,0 +1,20 @@ +description: West Virginia counts positive amounts of these represented net income sources under the Low Income Energy Assistance Program. +values: + 2025-10-01: + - self_employment_income + - sstb_self_employment_income + - farm_operations_income + - partnership_s_corp_income + - estate_income +# The source deducts 20% from gross receipts. Existing inputs are already net; +# using them without another deduction is an explicit modeling approximation. +# Estate and business losses do not offset other income. +metadata: + unit: list + period: year + label: West Virginia LIEAP net income sources without loss offsets + reference: + - title: West Virginia Income Maintenance Manual, Chapter 21.3.1.A + href: https://bfa.wv.gov/media/39948/download?inline=#page=1725,1726 + - title: West Virginia Income Maintenance Manual, October 2026 edition, Chapter 21.3.1.A + href: https://bfa.wv.gov/media/40005/download?inline=#page=1726,1727 diff --git a/policyengine_us/parameters/gov/states/wv/dhhr/lieap/income/sources.yaml b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/income/sources.yaml new file mode 100644 index 00000000000..5358ef59878 --- /dev/null +++ b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/income/sources.yaml @@ -0,0 +1,34 @@ +description: West Virginia counts these represented recurring income sources, in addition to net business and estate income, under the Low Income Energy Assistance Program. +values: + 2025-10-01: + - employment_income + - unemployment_compensation + - strike_benefits + - pension_income + - retirement_distributions + - survivor_benefits + - general_assistance + - wv_works + - rental_income + - farm_rent_income + - alimony_income + - child_support_received + - interest_income + - ordinary_dividend_income + - veterans_benefits + - workers_compensation + - disability_benefits + - financial_assistance +# All members' income counts, regardless of age or immigration qualification. +# RSDI, SSI and nonrecurring lump sums are excluded. Aggregate annual receipts +# are treated as recurring; VA Aid and Attendance cannot be separated from +# veterans_benefits. These input limitations are documented in the README. +metadata: + unit: list + period: year + label: West Virginia LIEAP recurring income sources + reference: + - title: West Virginia Income Maintenance Manual, Chapter 21.3.1.A + href: https://bfa.wv.gov/media/39948/download?inline=#page=1725,1726,1727,1728 + - title: West Virginia Income Maintenance Manual, October 2026 edition, Chapter 21.3.1.A + href: https://bfa.wv.gov/media/40005/download?inline=#page=1726,1727,1728,1729 diff --git a/policyengine_us/programs.yaml b/policyengine_us/programs.yaml index b0c88c46813..cf7386d9973 100644 --- a/policyengine_us/programs.yaml +++ b/policyengine_us/programs.yaml @@ -852,7 +852,7 @@ programs: full_name: West Virginia Low Income Energy Assistance Program components parameter_prefix: gov.states.wv.dhhr.lieap verified_years: "2026-2027" - notes: "Household-size and income-limit components only. No final countable income, eligibility or regular benefit: published payment intervals overlap and income-category guidance conflicts. Annual inputs and SPM units approximate application circumstances. Earlier backfills are unverified historical estimates. Crisis, cooling, weatherization and equipment remain outside scope." + notes: "Household-size, countable-income and income-limit components. Countable income follows the detailed operational manual over unchecked plan categories, including minor earnings, TANF and general assistance while excluding RSDI and SSI. Annual flows approximate recurring application-month income; aggregate inputs cannot separate all excluded receipts. No final eligibility or regular benefit: payment intervals overlap and categorical semantics remain unresolved. Earlier backfills are unverified historical estimates. Crisis, cooling, weatherization and equipment remain outside scope." # --- SSA programs --- - id: ssi diff --git a/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_countable_income.yaml new file mode 100644 index 00000000000..0bb7d402621 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_countable_income.yaml @@ -0,0 +1,586 @@ +# Independent source-derived tests for annualized countable income only. +# Earlier operative IMM, section 21.3.1.A.1-4/B/D (physical pages 1725-1728, 1732). +# https://bfa.wv.gov/media/39948/download?inline=#page=1725,1726,1727,1728,1732 +# Current October 1, 2026 IMM, section 21.3.1.A.1-3/A.5/B (physical pages 1726-1729, 1734). +# https://bfa.wv.gov/media/40005/download?inline=#page=1726,1727,1728,1729,1734 +# Annual flow inputs approximate steady application-month receipt; they do not +# reconstruct application dates, pay-frequency conversions or partial months. +# The detailed manual governs over unchecked summary-plan income categories. +# Capital/death/prize facts in Case 7 are explicitly nonrecurring. + +- name: Case 1, minors and nonqualified members retain their recurring earnings. + # The operative manual has no blanket minor-earnings exclusion. + # Every unit counts 12_000 + 6_000, including nonqualified parent earnings. + # The seventeenth/eighteenth birthday does not change this income rule. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + is_citizen_or_legal_immigrant: true + ssi: 0 + employment_income: 12000 + person2: + age: 17 + is_citizen_or_legal_immigrant: true + ssi: 0 + employment_income: 6000 + person3: + age: 40 + is_citizen_or_legal_immigrant: true + ssi: 0 + employment_income: 12000 + person4: + age: 18 + is_citizen_or_legal_immigrant: true + ssi: 0 + employment_income: 6000 + person5: + age: 40 + is_citizen_or_legal_immigrant: false + ssi: 0 + employment_income: 12000 + person6: + age: 10 + is_citizen_or_legal_immigrant: true + ssi: 0 + employment_income: 6000 + spm_units: + spm_unit1: + members: + - person1 + - person2 + heating_type: NATURAL_GAS + gas_expense: 1200 + pre_subsidy_electricity_expense: 0 + wv_works: 0 + snap: 0 + spm_unit2: + members: + - person3 + - person4 + heating_type: NATURAL_GAS + gas_expense: 1200 + pre_subsidy_electricity_expense: 0 + wv_works: 0 + snap: 0 + spm_unit3: + members: + - person5 + - person6 + heating_type: NATURAL_GAS + gas_expense: 1200 + pre_subsidy_electricity_expense: 0 + wv_works: 0 + snap: 0 + households: + household1: + members: + - person1 + - person2 + state_code: WV + household2: + members: + - person3 + - person4 + state_code: WV + household3: + members: + - person5 + - person6 + state_code: WV + output: + wv_lieap_countable_income: + - 18000 + - 18000 + - 18000 + +- name: Case 2, recurring represented income sources include assistance and ordinary VA. + # 2_400 + 300 + 600 + 700 + 400 + 900 + (200 + 100) + # + (250 + 50) + 800 + 1_000 + 900 + 1_100 + 1_200 + 1_300 = 12_200. + # VA here is ordinary recurring benefits, not excluded Aid and Attendance. + # Estate income and child support here are recurring, not inheritance or arrears. + # Outside-household cash assistance and GA count under the all-source rule. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + is_citizen_or_legal_immigrant: true + ssi: 0 + unemployment_compensation: 2400 + strike_benefits: 300 + rental_income: 600 + farm_rent_income: 700 + alimony_income: 400 + child_support_received: 900 + taxable_interest_income: 200 + tax_exempt_interest_income: 100 + qualified_dividend_income: 250 + non_qualified_dividend_income: 50 + veterans_benefits: 800 + workers_compensation: 1000 + disability_benefits: 900 + estate_income: 1100 + financial_assistance: 1200 + general_assistance: 1300 + spm_units: + spm_unit1: + members: + - person1 + heating_type: NATURAL_GAS + gas_expense: 1200 + pre_subsidy_electricity_expense: 0 + wv_works: 0 + snap: 0 + households: + household1: + members: + - person1 + state_code: WV + output: + wv_lieap_countable_income: + - 12200 + +- name: Case 3, pensions account distributions and non-SSA survivor benefits count once. + # Recurring pensions: 1_000 + 2_000 + 300 + 400 = 3_700. + # Recurring account withdrawals: 5_000 + 600 + 700 + 80 + 90 + 10 + 110 + 20 + 30 = 6_640. + # Non-SSA survivors 500 gives 3_700 + 6_640 + 500 = 10_840. + # All three RSDI categories are excluded; no narrower pension classifications + # are supplied alongside their potentially overlapping pension aggregates. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + is_citizen_or_legal_immigrant: true + ssi: 0 + taxable_public_pension_income: 1000 + taxable_private_pension_income: 2000 + tax_exempt_public_pension_income: 300 + tax_exempt_private_pension_income: 400 + taxable_ira_distributions: 5000 + tax_exempt_ira_distributions: 600 + taxable_401k_distributions: 700 + tax_exempt_401k_distributions: 80 + taxable_sep_distributions: 90 + tax_exempt_sep_distributions: 10 + taxable_403b_distributions: 110 + tax_exempt_403b_distributions: 20 + keogh_distributions: 30 + survivor_benefits: 500 + social_security_retirement: 18000 + social_security_disability: 12000 + social_security_survivors: 3600 + spm_units: + spm_unit1: + members: + - person1 + heating_type: NATURAL_GAS + gas_expense: 1200 + pre_subsidy_electricity_expense: 0 + wv_works: 0 + snap: 0 + households: + household1: + members: + - person1 + state_code: WV + output: + wv_lieap_countable_income: + - 10840 + +- name: Case 4, monthly WV WORKS aggregates once and general assistance remains countable. + # First unit: GA 600 + 900 plus WV WORKS 100 + 200 = 1_800. + # Second unit: GA 50 plus WV WORKS 25 * 12 = 350. + # WV WORKS is an SPMUnit monthly benefit, not a per-person or annual-times-12 amount. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + is_citizen_or_legal_immigrant: true + ssi: 0 + general_assistance: 600 + person2: + age: 8 + is_citizen_or_legal_immigrant: true + ssi: 0 + general_assistance: 900 + person3: + age: 40 + is_citizen_or_legal_immigrant: true + ssi: 0 + general_assistance: 50 + spm_units: + spm_unit1: + members: + - person1 + - person2 + heating_type: NATURAL_GAS + gas_expense: 1200 + pre_subsidy_electricity_expense: 0 + wv_works: + 2026-01: 100 + 2026-02: 200 + 2026-03: 0 + 2026-04: 0 + 2026-05: 0 + 2026-06: 0 + 2026-07: 0 + 2026-08: 0 + 2026-09: 0 + 2026-10: 0 + 2026-11: 0 + 2026-12: 0 + snap: 0 + spm_unit2: + members: + - person3 + heating_type: NATURAL_GAS + gas_expense: 1200 + pre_subsidy_electricity_expense: 0 + wv_works: + 2026-01: 25 + 2026-02: 25 + 2026-03: 25 + 2026-04: 25 + 2026-05: 25 + 2026-06: 25 + 2026-07: 25 + 2026-08: 25 + 2026-09: 25 + 2026-10: 25 + 2026-11: 25 + 2026-12: 25 + snap: 0 + households: + household1: + members: + - person1 + - person2 + state_code: WV + household2: + members: + - person3 + state_code: WV + output: + wv_lieap_countable_income: + - 1800 + - 350 + +- name: Case 5, existing net businesses are not discounted again and losses do not offset earnings. + # Authorized net-business approximation: do not apply the manual gross-receipts 20% deduction twice. + # First unit sums 1_000 + 2_000 + 3_000 + 4_000 = 10_000. + # Second counts wages 10_000 + positive business 2_000 + 3_000 = 15_000. + # Negative business streams contribute zero; the all-loss unit has zero income. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + is_citizen_or_legal_immigrant: true + ssi: 0 + self_employment_income: 1000 + sstb_self_employment_income: 2000 + farm_operations_income: 3000 + partnership_s_corp_income: 4000 + person2: + age: 40 + is_citizen_or_legal_immigrant: true + ssi: 0 + employment_income: 10000 + self_employment_income: -9000 + sstb_self_employment_income: 2000 + farm_operations_income: -7000 + partnership_s_corp_income: 3000 + person3: + age: 40 + is_citizen_or_legal_immigrant: true + ssi: 0 + self_employment_income: -1000 + sstb_self_employment_income: -2000 + farm_operations_income: -3000 + partnership_s_corp_income: -4000 + spm_units: + spm_unit1: + members: + - person1 + heating_type: NATURAL_GAS + gas_expense: 1200 + pre_subsidy_electricity_expense: 0 + wv_works: 0 + snap: 0 + spm_unit2: + members: + - person2 + heating_type: NATURAL_GAS + gas_expense: 1200 + pre_subsidy_electricity_expense: 0 + wv_works: 0 + snap: 0 + spm_unit3: + members: + - person3 + heating_type: NATURAL_GAS + gas_expense: 1200 + pre_subsidy_electricity_expense: 0 + wv_works: 0 + snap: 0 + households: + household1: + members: + - person1 + state_code: WV + household2: + members: + - person2 + state_code: WV + household3: + members: + - person3 + state_code: WV + output: + wv_lieap_countable_income: + - 10000 + - 15000 + - 0 + +- name: Case 6, student funding RSDI SSI and SNAP do not enlarge recurring wages. + # Only the 10_000 ordinary wages count; these are not work-study wages. + # Scholarships/grants 5_000, Pell 3_000, SSDI 2_400, annual SSI 1_200 and SNAP 6_000 are excluded. + # No separate work-study dollar input exists; this does not assert exclusion of mixed-job wages. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 20 + is_citizen_or_legal_immigrant: true + ssi: 1200 + employment_income: 10000 + educational_assistance: 5000 + pell_grant: 3000 + social_security_disability: 2400 + spm_units: + spm_unit1: + members: + - person1 + heating_type: NATURAL_GAS + gas_expense: 1200 + pre_subsidy_electricity_expense: 0 + wv_works: 0 + snap: 6000 + households: + household1: + members: + - person1 + state_code: WV + output: + wv_lieap_countable_income: + - 10000 + +- name: Case 7, specifically nonrecurring proceeds are excluded under the documented input convention. + # Fixture facts: one asset sale, one gambling prize and one life-insurance death payment. + # The manual excludes nonrecurring lump sums, not all possible recurring installments. + # Existing annual fields cannot distinguish those installments; this scenario + # does not claim a legal blanket exclusion or test unobserved recurrence. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + is_citizen_or_legal_immigrant: true + ssi: 0 + long_term_capital_gains: 10000 + gambling_winnings: 2000 + life_insurance_benefits: 50000 + spm_units: + spm_unit1: + members: + - person1 + heating_type: NATURAL_GAS + gas_expense: 1200 + pre_subsidy_electricity_expense: 0 + wv_works: 0 + snap: 0 + households: + household1: + members: + - person1 + state_code: WV + output: + wv_lieap_countable_income: + - 0 + +- name: Case 8, income remains unprorated in mixed states and all-nonqualified households. + # WV counts both 6_000 incomes and separately the all-nonqualified unit 15_000. + # Income is not conditioned on qualified household size; this is not eligibility. + # The Virginia unit has zero under the WV-only public variable. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + is_citizen_or_legal_immigrant: true + ssi: 0 + employment_income: 6000 + person2: + age: 12 + is_citizen_or_legal_immigrant: false + ssi: 0 + employment_income: 6000 + person3: + age: 40 + is_citizen_or_legal_immigrant: true + ssi: 0 + employment_income: 25000 + person4: + age: 40 + is_citizen_or_legal_immigrant: false + ssi: 0 + employment_income: 15000 + spm_units: + spm_unit1: + members: + - person1 + - person2 + heating_type: NATURAL_GAS + gas_expense: 1200 + pre_subsidy_electricity_expense: 0 + wv_works: 0 + snap: 0 + spm_unit2: + members: + - person3 + heating_type: NATURAL_GAS + gas_expense: 1200 + pre_subsidy_electricity_expense: 0 + wv_works: 0 + snap: 0 + spm_unit3: + members: + - person4 + heating_type: NATURAL_GAS + gas_expense: 1200 + pre_subsidy_electricity_expense: 0 + wv_works: 0 + snap: 0 + households: + household1: + members: + - person1 + - person2 + state_code: WV + household2: + members: + - person3 + state_code: VA + household3: + members: + - person4 + state_code: WV + output: + wv_lieap_countable_income: + - 12000 + - 0 + - 15000 + +- name: Case 9, the current FY2027 manual preserves recurring and excluded income treatment. + # Current manual A.1-3 retain the income rules; exclusions are now A.5. + # 2_000 + 1_000 + 300 + 400 + 500 + ordinary VA 600 + WV WORKS 1_200 = 6_000. + # RSDI 18_000, SSI 1_200 and educational assistance 800 remain excluded. + # The new Zero Income A.4 is about responsibility and adds no income to this fixture. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + is_citizen_or_legal_immigrant: true + ssi: 0 + employment_income: 2000 + general_assistance: 300 + taxable_private_pension_income: 400 + taxable_ira_distributions: 500 + veterans_benefits: 600 + social_security_retirement: 18000 + person2: + age: 17 + is_citizen_or_legal_immigrant: false + ssi: 1200 + employment_income: 1000 + educational_assistance: 800 + spm_units: + spm_unit1: + members: + - person1 + - person2 + heating_type: NATURAL_GAS + gas_expense: 1200 + pre_subsidy_electricity_expense: 0 + wv_works: + 2027-01: 100 + 2027-02: 100 + 2027-03: 100 + 2027-04: 100 + 2027-05: 100 + 2027-06: 100 + 2027-07: 100 + 2027-08: 100 + 2027-09: 100 + 2027-10: 100 + 2027-11: 100 + 2027-12: 100 + snap: 0 + households: + household1: + members: + - person1 + - person2 + state_code: WV + output: + wv_lieap_countable_income: + - 6000 + +- name: Case 10, estate losses do not offset wages or another member estate income. + period: 2026 + absolute_error_margin: 0.01 + # No-deduction rule applied to an input explicitly defined as net income or loss. + # Person 1 wages 12_000 plus zero from their -10_000 estate loss, + # plus Person 2 recurring estate income 1_000 = 13_000. + # Flooring after summing member estates would wrongly erase the positive 1_000. + input: + people: + person1: + age: 40 + is_citizen_or_legal_immigrant: true + employment_income: 12_000 + estate_income: -10_000 + ssi: 0 + person2: + age: 35 + is_citizen_or_legal_immigrant: true + estate_income: 1_000 + ssi: 0 + spm_units: + spm_unit1: + members: [person1, person2] + heating_type: NATURAL_GAS + gas_expense: 1_200 + pre_subsidy_electricity_expense: 0 + wv_works: 0 + snap: 0 + households: + household1: + members: [person1, person2] + state_code: WV + output: + wv_lieap_countable_income: 13_000 diff --git a/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_countable_income.py b/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_countable_income.py new file mode 100644 index 00000000000..bd695b46df3 --- /dev/null +++ b/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_countable_income.py @@ -0,0 +1,28 @@ +from policyengine_us.model_api import * + + +class wv_lieap_countable_income(Variable): + value_type = float + entity = SPMUnit + label = "West Virginia LIEAP annual countable income" + unit = USD + definition_period = YEAR + defined_for = StateCode.WV + reference = ( + "https://bfa.wv.gov/media/39948/download?inline=#page=1725,1726,1727,1728", + "https://bfa.wv.gov/media/40005/download?inline=#page=1726,1727,1728,1729", + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.wv.dhhr.lieap.income + person = spm_unit.members + # Existing net business inputs receive no second expense deduction; + # business and estate losses do not offset other income. + net_income = sum( + max_(person(source, period), 0) for source in p.nonnegative_sources + ) + # The operative manual counts minor and nonqualified members' income, + # TANF and general assistance. RSDI and SSI are expressly excluded. + # Annual flows approximate recurring application-month receipts. Generic + # VA cannot identify excluded Aid and Attendance; see README limitations. + return max_(spm_unit.sum(net_income) + add(spm_unit, period, p.sources), 0) From 4e25df092b7dd12decacf0b09ebf80381e8815dc Mon Sep 17 00:00:00 2001 From: Ziming Date: Tue, 20 Oct 2026 21:34:50 -0400 Subject: [PATCH 3/7] Model WV regular heating payments using approved table bounds --- changelog.d/wv-liheap-wave2c.added.md | 2 +- .../gov/states/wv/dhhr/lieap/README.md | 84 ++++- .../wv/dhhr/lieap/payment/amount_step.yaml | 16 + .../wv/dhhr/lieap/payment/base_amount.yaml | 16 + .../dhhr/lieap/payment/fuel_multiplier.yaml | 23 ++ .../wv/dhhr/lieap/payment/income_band.yaml | 222 +++++++++++++ .../lieap/payment/max_household_size.yaml | 16 + policyengine_us/programs.yaml | 9 +- .../gov/states/wv/dhhr/lieap/wv_lieap.yaml | 313 ++++++++++++++++++ .../dhhr/lieap/wv_lieap_income_eligible.yaml | 104 ++++++ .../gov/states/wv/dhhr/lieap/wv_lieap.py | 55 +++ .../wv/dhhr/lieap/wv_lieap_income_eligible.py | 17 + 12 files changed, 854 insertions(+), 23 deletions(-) create mode 100644 policyengine_us/parameters/gov/states/wv/dhhr/lieap/payment/amount_step.yaml create mode 100644 policyengine_us/parameters/gov/states/wv/dhhr/lieap/payment/base_amount.yaml create mode 100644 policyengine_us/parameters/gov/states/wv/dhhr/lieap/payment/fuel_multiplier.yaml create mode 100644 policyengine_us/parameters/gov/states/wv/dhhr/lieap/payment/income_band.yaml create mode 100644 policyengine_us/parameters/gov/states/wv/dhhr/lieap/payment/max_household_size.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_income_eligible.yaml create mode 100644 policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap.py create mode 100644 policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_income_eligible.py diff --git a/changelog.d/wv-liheap-wave2c.added.md b/changelog.d/wv-liheap-wave2c.added.md index 545ccabc0fb..5071594a9a7 100644 --- a/changelog.d/wv-liheap-wave2c.added.md +++ b/changelog.d/wv-liheap-wave2c.added.md @@ -1 +1 @@ -Add West Virginia LIEAP household size, income limits and countable income with military retirement, nonnegative source receipts and shared unemployment and TANF receipt handling; final eligibility and heating awards remain incomplete pending source conflicts. +Add West Virginia modeled regular heating LIEAP payments for one through twenty qualified members, with source-specific income handling, the operational income ceiling, approved continuous published upper bands and half-up cent rounding. Reuse existing heating-responsibility facts; larger households, unsupported fuels and administrative housing details remain partial coverage. diff --git a/policyengine_us/parameters/gov/states/wv/dhhr/lieap/README.md b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/README.md index 51e4008ff43..dd42c7163d8 100644 --- a/policyengine_us/parameters/gov/states/wv/dhhr/lieap/README.md +++ b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/README.md @@ -1,8 +1,8 @@ -# West Virginia regular heating components +# West Virginia modeled regular heating assistance -The qualified household-size, countable-income and income-limit components use the FY2026 state -plan and operational manuals, including the adopted October 2026 update for -FY2027. The assistance group includes co-residents sharing +The household-size, countable-income, income-limit, income-eligibility and modeled +regular-payment components use the FY2026 state plan and operational manuals, +including the adopted October 2026 update for FY2027. The assistance group includes co-residents sharing heating costs. Qualified members count in its size; nonqualified members' income is not excluded. SPM membership approximates the physical sharing group. Prior assistance in another group can exclude a member, but receipt history is absent @@ -10,7 +10,7 @@ from existing inputs and is not inferred. The plan specifies 60% of requested-year SMI through size seven, then 150% of prior-calendar-year FPG from size eight. Nearest-dollar monthly rounding matches -all ten published agency amounts. Applying the guideline before rounding also +all ten preserved FY2026 agency amounts. Applying the guideline before rounding also matches the manual's size-eleven limit of $8,831; repeatedly adding the web page's rounded $688 increment gives a conflicting $8,832. The adopted percentage and manual calculation take precedence over that rounded web shorthand. This is a @@ -19,6 +19,10 @@ The same calculation matches the current manual's FY2027 monthly limits for sizes one through eleven. The payment grid's apparent size-twelve maximum of $10,160 conflicts with the guideline-derived $9,805; payment cells do not replace the stated income eligibility rule. +Fresh FY2027 public materials print $6,695 for eight people, while the +operational manual and 150% FPG calculation give $6,965. The model retains the +manual/guideline amount; this discrepancy does not authorize smoothing any +other printed payment-band bound. Countable income follows the detailed operational manual, which current Board of Review decisions apply, over unchecked summary-plan categories. This is an @@ -38,7 +42,10 @@ Unemployment uses the shared reported-or-modeled receipt amount. TANF uses the shared take-up-gated receipt, annualizing monthly WV WORKS once at the household level. Separate royalties and foster-care receipts are not identified by existing inputs. Generic VA benefits cannot separate excluded Aid and -Attendance, and employment cannot separate excluded work-study, CNCS or CSEP +Attendance. The December 18, 2025 announcement broadly describes VA benefits +as excluded, in tension with the manual's specific Aid and Attendance +exclusion. Existing manual-priority treatment is retained; this source conflict +is not declared resolved. Employment cannot separate excluded work-study, CNCS or CSEP wages. A work-study participation flag cannot determine which wages to subtract. Aggregate child support, retirement, insurance, estate and gift inputs cannot identify every recurring payment, arrearage or earmarked reimbursement. These @@ -50,16 +57,57 @@ gross-income rule does not authorize a general Medicare premium deduction; RSDI is already excluded in full, so its Medicare withholding is not subtracted from other countable receipts. -Final eligibility and benefits remain incomplete. The ordinary-ceiling and -categorical plan wording is not fully reconciled; no income-eligibility bypass -is inferred from the plan's checkboxes. The FY2026 payment chart -has overlapping first/second income bands and anomalous larger-family cells. -The October 2026 operational manual repeats an overlap in FY2027. The source -library preserves both literal grids and their edition details; the model does -not silently correct them or encode unmodeled eligible benefits as zero. +The income-eligibility component requires a positive qualified household size +and countable income at or below the existing limit. The operational manual's +section 21.3.1.A explicitly denies groups above the income ceiling. Mail-out +reviews still require verification, and the manual's mixed SSI/employment +example requires verification of the employment income. The summary plan's +categorical checkboxes remain a source tension, but they do not establish an +unconstrained SNAP, TANF or SSI income-ceiling bypass. This follows the detailed +operational manual's income rule rather than inferring an exemption from +application streamlining. -Only the household-size, countable-income and income-limit components are verified for FY2026 and -FY2027. Earlier backfilled results are unverified historical estimates; the whole -program is not verified for either year and its partial registry entry therefore -omits `verified_years`. The full regular-heating goal remains open. Crisis, cooling, -weatherization, equipment and the separate utility discount are out of scope. +The regular-payment output supports one through twenty qualified members. On +October 20, 2026, the user approved using the published upper income bounds as +continuous closed-top intervals, without rounding observed monthly income. This +resolves the overlapping first/second lower endpoints and fractional-dollar +gaps. Every other printed upper bound is retained, including irregular values; +the table is not smoothed. The existing income ceiling is still independently +applied. The source library preserves both literal grids and edition details, +including the earlier chart's stale FY2025 heading despite its FY2026 limits. + +All 840 occupied cells across the two published grids exactly equal +`base_amount + amount_step * (size - 1 - band_index)`. +This is lossless compression of the published amounts, not permission to +extrapolate. The ordinary income limit confines eligible sizes one through +twenty to occupied cells. Fuel multipliers are applied once to the base amount. +Integer-dollar bases and three-decimal multipliers give exact dollar mills; +rounding those to cents half up reproduces the printed $70.79 and $147.02. +No unsupported actual-bill cap or proportional reduction for partial +responsibility is imposed. The combined regular/crisis ceiling and equipment +maximum are outside this regular payment calculation. + +Heating responsibility reuses `has_heating_expense`. Its default requires a +matching positive primary-fuel bill and excludes heat bundled in rent. A +subsidized tenant paying direct heating costs can qualify. The existing flag +can be supplied for a known obligation that its default cannot infer, including +documented heating charges in rent or auxiliary electric costs with self-cut +wood. The heat-in-rent or subsidy flag alone cannot establish that obligation. +No blanket exclusion of subsidized renters is introduced. A default zero for +bundled rent without the responsibility fact is not a definitive legal denial. + +Some facts remain unobserved: designated rent charges, anticipated surcharges, +traditional versus movable dwellings, portable-heater or alternate-fuel +approval, and prior-season duplicate assistance. The FY2027 manual explicitly +retains responsibility for a zero/minimal-income client whose own heating bill +is paid by an outsider; earlier wording differs. The model does not identify +every billholder or third-party arrangement and does not backdate that +exception. These are documented existing-input approximations, not new inputs +or a complete administrative housing predicate. + +Payment coverage above twenty members and for UNSPECIFIED, SOLAR or OTHER fuel +remains unmodeled. Output zero for those cases means no modeled award, not legal +ineligibility. NONE affirmatively reports no heating. The registry remains +partial and omits `verified_years`; no fully verified program year is claimed. +Earlier backfilled results are unverified historical estimates. Crisis, cooling, +weatherization, equipment and the separate utility discount remain out of scope. diff --git a/policyengine_us/parameters/gov/states/wv/dhhr/lieap/payment/amount_step.yaml b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/payment/amount_step.yaml new file mode 100644 index 00000000000..32449be6cb8 --- /dev/null +++ b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/payment/amount_step.yaml @@ -0,0 +1,16 @@ +# Across the two finite published grids, all 840 occupied cells equal +# base_amount + amount_step * (household_size - 1 - zero_based_band). +# This is exact transcription compression, not a legal extrapolation rule. +# The finite table does not define payments for blank cells or sizes above 20. +description: West Virginia varies adjacent published base payments by this amount under the Low Income Energy Assistance Program. +values: + 2025-10-01: 5 +metadata: + unit: currency-USD + period: year + label: West Virginia LIEAP published base payment step + reference: + - title: "West Virginia Income Maintenance Manual, Appendix A #page 1772-1773" + href: https://bfa.wv.gov/media/39948/download?inline=#page=1772 + - title: "West Virginia Income Maintenance Manual, October 2026 edition, Appendix A #page 1775-1776" + href: https://bfa.wv.gov/media/40005/download?inline=#page=1775 diff --git a/policyengine_us/parameters/gov/states/wv/dhhr/lieap/payment/base_amount.yaml b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/payment/base_amount.yaml new file mode 100644 index 00000000000..a951e1a49cc --- /dev/null +++ b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/payment/base_amount.yaml @@ -0,0 +1,16 @@ +# Across the two finite published grids, all 840 occupied cells equal +# base_amount + amount_step * (household_size - 1 - zero_based_band). +# This is exact transcription compression, not a legal extrapolation rule. +# The finite table does not define payments for blank cells or sizes above 20. +description: West Virginia sets this first-row one-person base payment under the Low Income Energy Assistance Program. +values: + 2025-10-01: 160 +metadata: + unit: currency-USD + period: year + label: West Virginia LIEAP first published base amount + reference: + - title: "West Virginia Income Maintenance Manual, Appendix A #page 1772-1773" + href: https://bfa.wv.gov/media/39948/download?inline=#page=1772 + - title: "West Virginia Income Maintenance Manual, October 2026 edition, Appendix A #page 1775-1776" + href: https://bfa.wv.gov/media/40005/download?inline=#page=1775 diff --git a/policyengine_us/parameters/gov/states/wv/dhhr/lieap/payment/fuel_multiplier.yaml b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/payment/fuel_multiplier.yaml new file mode 100644 index 00000000000..f3591fa1a06 --- /dev/null +++ b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/payment/fuel_multiplier.yaml @@ -0,0 +1,23 @@ +# bulk_fuel covers the source's LPG, coal, wood, fuel oil and kerosene rows. +# These are total payment multipliers, as confirmed by the printed products; +# do not add the base amount again. No multiplier is inferred for other fuels. +description: West Virginia multiplies regular base payments by these heating-source factors under the Low Income Energy Assistance Program. +electricity: + values: + 2025-10-01: 1.75 +natural_gas: + values: + 2025-10-01: 1.198 +bulk_fuel: + values: + 2025-10-01: 1.089 +metadata: + propagate_metadata_to_children: true + unit: /1 + period: year + label: West Virginia LIEAP heating-source payment multiplier + reference: + - title: "West Virginia Income Maintenance Manual, section 21.4.11.B #page 1754-1755" + href: https://bfa.wv.gov/media/39948/download?inline=#page=1754 + - title: "West Virginia Income Maintenance Manual, October 2026 edition, section 21.4.11.B #page 1757-1758" + href: https://bfa.wv.gov/media/40005/download?inline=#page=1757 diff --git a/policyengine_us/parameters/gov/states/wv/dhhr/lieap/payment/income_band.yaml b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/payment/income_band.yaml new file mode 100644 index 00000000000..fc64e5659eb --- /dev/null +++ b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/payment/income_band.yaml @@ -0,0 +1,222 @@ +# Use the first matching inclusive published upper bound with calc(right=True). +# The user approved ordered upper bounds and continuous monthly income on +# October 20, 2026, resolving overlapping From values and gaps between dollars. +# Retain every printed upper bound, including irregular larger-family intervals. +# Band 40 is the sentinel above the final published row, not another payment. +description: West Virginia determines this zero-based payment row from monthly countable income under the Low Income Energy Assistance Program. +brackets: + - threshold: + 2025-10-01: -.inf + amount: + 2025-10-01: 0 + - threshold: + 2025-10-01: 2_077 + 2026-10-01: 2_157 + amount: + 2025-10-01: 1 + - threshold: + 2025-10-01: 2_454 + 2026-10-01: 2_550 + amount: + 2025-10-01: 2 + - threshold: + 2025-10-01: 2_832 + 2026-10-01: 2_942 + amount: + 2025-10-01: 3 + - threshold: + 2025-10-01: 3_209 + 2026-10-01: 3_335 + amount: + 2025-10-01: 4 + - threshold: + 2025-10-01: 3_587 + 2026-10-01: 3_427 + amount: + 2025-10-01: 5 + - threshold: + 2025-10-01: 3_965 + 2026-10-01: 4_120 + amount: + 2025-10-01: 6 + - threshold: + 2025-10-01: 4_343 + 2026-10-01: 4_512 + amount: + 2025-10-01: 7 + - threshold: + 2025-10-01: 4_720 + 2026-10-01: 4_904 + amount: + 2025-10-01: 8 + - threshold: + 2025-10-01: 5_099 + 2026-10-01: 5_296 + amount: + 2025-10-01: 9 + - threshold: + 2025-10-01: 5_475 + 2026-10-01: 5_689 + amount: + 2025-10-01: 10 + - threshold: + 2025-10-01: 5_853 + 2026-10-01: 6_081 + amount: + 2025-10-01: 11 + - threshold: + 2025-10-01: 6_230 + 2026-10-01: 6_474 + amount: + 2025-10-01: 12 + - threshold: + 2025-10-01: 6_301 + 2026-10-01: 6_548 + amount: + 2025-10-01: 13 + - threshold: + 2025-10-01: 6_372 + 2026-10-01: 6_621 + amount: + 2025-10-01: 14 + - threshold: + 2025-10-01: 6_572 + 2026-10-01: 6_793 + amount: + 2025-10-01: 15 + - threshold: + 2025-10-01: 6_769 + 2026-10-01: 6_965 + amount: + 2025-10-01: 16 + - threshold: + 2025-10-01: 7_113 + 2026-10-01: 7_320 + amount: + 2025-10-01: 17 + - threshold: + 2025-10-01: 7_456 + 2026-10-01: 7_675 + amount: + 2025-10-01: 18 + - threshold: + 2025-10-01: 7_800 + 2026-10-01: 8_030 + amount: + 2025-10-01: 19 + - threshold: + 2025-10-01: 8_144 + 2026-10-01: 8_385 + amount: + 2025-10-01: 20 + - threshold: + 2025-10-01: 8_477 + 2026-10-01: 8_740 + amount: + 2025-10-01: 21 + - threshold: + 2025-10-01: 8_831 + 2026-10-01: 9_095 + amount: + 2025-10-01: 22 + - threshold: + 2025-10-01: 9_175 + 2026-10-01: 9_805 + amount: + 2025-10-01: 23 + - threshold: + 2025-10-01: 9_519 + 2026-10-01: 10_160 + amount: + 2025-10-01: 24 + - threshold: + 2025-10-01: 9_863 + 2026-10-01: 10_515 + amount: + 2025-10-01: 25 + - threshold: + 2025-10-01: 10_206 + 2026-10-01: 10_870 + amount: + 2025-10-01: 26 + - threshold: + 2025-10-01: 10_550 + 2026-10-01: 11_225 + amount: + 2025-10-01: 27 + - threshold: + 2025-10-01: 10_894 + 2026-10-01: 11_580 + amount: + 2025-10-01: 28 + - threshold: + 2025-10-01: 11_238 + 2026-10-01: 11_935 + amount: + 2025-10-01: 29 + - threshold: + 2025-10-01: 11_581 + 2026-10-01: 12_290 + amount: + 2025-10-01: 30 + - threshold: + 2025-10-01: 11_925 + 2026-10-01: 12_645 + amount: + 2025-10-01: 31 + - threshold: + 2025-10-01: 12_269 + 2026-10-01: 13_000 + amount: + 2025-10-01: 32 + - threshold: + 2025-10-01: 12_956 + 2026-10-01: 13_355 + amount: + 2025-10-01: 33 + - threshold: + 2025-10-01: 13_300 + 2026-10-01: 13_710 + amount: + 2025-10-01: 34 + - threshold: + 2025-10-01: 13_644 + 2026-10-01: 14_065 + amount: + 2025-10-01: 35 + - threshold: + 2025-10-01: 13_988 + 2026-10-01: 14_420 + amount: + 2025-10-01: 36 + - threshold: + 2025-10-01: 14_331 + 2026-10-01: 14_775 + amount: + 2025-10-01: 37 + - threshold: + 2025-10-01: 14_675 + 2026-10-01: 15_130 + amount: + 2025-10-01: 38 + - threshold: + 2025-10-01: 15_019 + 2026-10-01: 15_485 + amount: + 2025-10-01: 39 + - threshold: + 2025-10-01: 15_363 + 2026-10-01: 15_840 + amount: + 2025-10-01: 40 +metadata: + type: single_amount + threshold_unit: currency-USD + amount_unit: /1 + period: month + label: West Virginia LIEAP monthly income band index + reference: + - title: "West Virginia Income Maintenance Manual, Appendix A #page 1772-1773" + href: https://bfa.wv.gov/media/39948/download?inline=#page=1772 + - title: "West Virginia Income Maintenance Manual, October 2026 edition, Appendix A #page 1775-1776" + href: https://bfa.wv.gov/media/40005/download?inline=#page=1775 diff --git a/policyengine_us/parameters/gov/states/wv/dhhr/lieap/payment/max_household_size.yaml b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/payment/max_household_size.yaml new file mode 100644 index 00000000000..8e1d5d3dde6 --- /dev/null +++ b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/payment/max_household_size.yaml @@ -0,0 +1,16 @@ +# Across the two finite published grids, all 840 occupied cells equal +# base_amount + amount_step * (household_size - 1 - zero_based_band). +# This is exact transcription compression, not a legal extrapolation rule. +# The finite table does not define payments for blank cells or sizes above 20. +description: West Virginia publishes regular payment amounts through this household size under the Low Income Energy Assistance Program. +values: + 2025-10-01: 20 +metadata: + unit: person + period: year + label: West Virginia LIEAP maximum published payment household size + reference: + - title: "West Virginia Income Maintenance Manual, Appendix A #page 1772-1773" + href: https://bfa.wv.gov/media/39948/download?inline=#page=1772 + - title: "West Virginia Income Maintenance Manual, October 2026 edition, Appendix A #page 1775-1776" + href: https://bfa.wv.gov/media/40005/download?inline=#page=1775 diff --git a/policyengine_us/programs.yaml b/policyengine_us/programs.yaml index f322553f6ee..d3ad09e0199 100644 --- a/policyengine_us/programs.yaml +++ b/policyengine_us/programs.yaml @@ -961,11 +961,12 @@ programs: parameter_prefix: gov.states.tx.tdhca.ceap notes: Models the 150% FPG income limit, the alternative 60% SMI limit from the FY2024 state plan (applied through 2024), 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: WV - status: in_progress - name: West Virginia LIEAP components - full_name: West Virginia Low Income Energy Assistance Program components + status: partial + name: West Virginia LIEAP modeled regular heating + full_name: West Virginia Low Income Energy Assistance Program modeled regular heating + variable: wv_lieap parameter_prefix: gov.states.wv.dhhr.lieap - notes: "Household-size, countable-income and income-limit components. Countable income follows the detailed operational manual over unchecked plan categories, including minor earnings, TANF and general assistance while excluding RSDI and SSI. Annual flows approximate recurring application-month income; aggregate inputs cannot separate all excluded receipts. No final eligibility or regular benefit: payment intervals overlap and categorical semantics remain unresolved. Earlier backfills are unverified historical estimates. Crisis, cooling, weatherization and equipment remain outside scope." + notes: "Modeled FY2026-FY2027 regular heating payments for one through twenty qualified members. The operational manual's inclusive income ceiling applies without an unconditional SNAP, TANF or SSI bypass; RSDI and SSI income remain excluded. Published upper payment-band bounds are used continuously without observed-income rounding under the user-approved convention; other printed bounds remain literal. Exact grid compression and fuel multipliers reproduce occupied table amounts with half-up cent rounding. Shared heating-cost facts represent responsibility, including explicit known-obligation overrides; no blanket subsidy exclusion or actual-bill cap. Designated rent charges, dwelling/alternate-fuel approval, billholder and prior-assistance facts remain partly unobserved. Above twenty members and unsupported fuels return an unmodeled zero, not a definitive legal denial. Annual flows approximate application-month income and aggregate inputs cannot separate all excluded receipts. No fully verified year; earlier backfills are unverified historical estimates. Crisis, cooling, weatherization, equipment and the separate utility discount remain outside scope." # --- SSA programs --- - id: ssi diff --git a/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap.yaml b/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap.yaml new file mode 100644 index 00000000000..0198231882f --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap.yaml @@ -0,0 +1,313 @@ +# Published regular LIEAP tables and multiplication examples, not crisis caps. +# FY2026: PDF pages 1754-1755,1772-1773 +# https://bfa.wv.gov/media/39948/download?inline=#page=1754 +# FY2027: PDF pages 1757-1758,1775-1776 +# https://bfa.wv.gov/media/40005/download?inline=#page=1757 +# User-approved convention: continuous published upper bounds, no income rounding. + +- name: Case 1, zero income receives each supported fuel amount without a bill cap. + period: 2026 + absolute_error_margin: 0.01 + # One qualified person has base $160: electricity * 1.75 = $280; + # gas * 1.198 = $191.68; the other five published fuels * 1.089 = $174.24. + # Unsupported fuels have no modeled award, not a legal eligibility denial. + input: + state_code: [WV, WV, WV, WV, WV, WV, WV, WV, WV, WV, WV] + is_citizen_or_legal_immigrant: [true, true, true, true, true, true, + true, true, true, true, true] + heating_type: [ELECTRICITY, NATURAL_GAS, PROPANE, FUEL_OIL, KEROSENE, + WOOD, COAL, UNSPECIFIED, NONE, SOLAR, OTHER] + pre_subsidy_electricity_expense: [1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0] + gas_expense: [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0] + bottled_gas_expense: [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0] + fuel_oil_expense: [0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0] + wood_expense: [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0] + coal_expense: [0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0] + other_heating_fuel_expense: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1] + output: + wv_lieap: [280, 191.68, 174.24, 174.24, 174.24, 174.24, 174.24, + 0, 0, 0, 0] + +- name: Case 2, FY2026 upper bounds apply continuously with an inclusive ceiling. + period: 2026 + absolute_error_margin: 0.01 + # Monthly wages: 2077, 2077.25, 2077.50, 2078, 2454 and 2454.01. + # Only exact 2077 uses base160; the next four use155. Last row is over limit. + input: + state_code: [WV, WV, WV, WV, WV, WV] + is_citizen_or_legal_immigrant: [true, true, true, true, true, true] + employment_income: [24_924, 24_927, 24_930, 24_936, 29_448, 29_448.12] + heating_type: [ELECTRICITY, ELECTRICITY, ELECTRICITY, + ELECTRICITY, ELECTRICITY, ELECTRICITY] + pre_subsidy_electricity_expense: [1_200, 1_200, 1_200, 1_200, 1_200, 1_200] + output: + wv_lieap: [280, 271.25, 271.25, 271.25, 271.25, 0] + +- name: Case 3, FY2027 uses its own upper bounds and inclusive income ceiling. + period: 2027 + absolute_error_margin: 0.01 + # Monthly wages: 2157, 2157.25, 2157.50, 2158, 2550 and 2550.01. + input: + state_code: [WV, WV, WV, WV, WV, WV] + is_citizen_or_legal_immigrant: [true, true, true, true, true, true] + employment_income: [25_884, 25_887, 25_890, 25_896, 30_600, 30_600.12] + heating_type: [ELECTRICITY, ELECTRICITY, ELECTRICITY, + ELECTRICITY, ELECTRICITY, ELECTRICITY] + pre_subsidy_electricity_expense: [1_200, 1_200, 1_200, 1_200, 1_200, 1_200] + output: + wv_lieap: [280, 271.25, 271.25, 271.25, 271.25, 0] + +- name: Case 4, the literal FY2027 third-person upper bound is not smoothed. + period: 2027 + absolute_error_margin: 0.01 + # Monthly3400 is within the printed3427 upper bound: base150 *1.089=163.35. + # Monthly3430 is in the next row: base145 *1.089=157.905, rounded157.91. + input: + people: + person1: {age: 40, is_citizen_or_legal_immigrant: true, employment_income: 40_800} + person2: {age: 40, is_citizen_or_legal_immigrant: true} + person3: {age: 40, is_citizen_or_legal_immigrant: true} + person4: {age: 40, is_citizen_or_legal_immigrant: true, employment_income: 41_160} + person5: {age: 40, is_citizen_or_legal_immigrant: true} + person6: {age: 40, is_citizen_or_legal_immigrant: true} + spm_units: + spm_unit1: + members: [person1, person2, person3] + heating_type: PROPANE + bottled_gas_expense: 1_200 + spm_unit2: + members: [person4, person5, person6] + heating_type: PROPANE + bottled_gas_expense: 1_200 + households: + household1: + members: [person1, person2, person3] + state_code: WV + household2: + members: [person4, person5, person6] + state_code: WV + output: + wv_lieap: [163.35, 157.91] + +- name: Case 5, the literal FY2026 larger-family upper bound is not smoothed. + period: 2026 + absolute_error_margin: 0.01 + # Monthly8477 uses band20/base110; monthly8480 uses band21/base105. + # Both are below the eleven-person8831 monthly ceiling. + input: + people: + person1: {age: 40, is_citizen_or_legal_immigrant: true, employment_income: 101_724} + person2: {age: 40, is_citizen_or_legal_immigrant: true} + person3: {age: 40, is_citizen_or_legal_immigrant: true} + person4: {age: 40, is_citizen_or_legal_immigrant: true} + person5: {age: 40, is_citizen_or_legal_immigrant: true} + person6: {age: 40, is_citizen_or_legal_immigrant: true} + person7: {age: 40, is_citizen_or_legal_immigrant: true} + person8: {age: 40, is_citizen_or_legal_immigrant: true} + person9: {age: 40, is_citizen_or_legal_immigrant: true} + person10: {age: 40, is_citizen_or_legal_immigrant: true} + person11: {age: 40, is_citizen_or_legal_immigrant: true} + person12: {age: 40, is_citizen_or_legal_immigrant: true, employment_income: 101_760} + person13: {age: 40, is_citizen_or_legal_immigrant: true} + person14: {age: 40, is_citizen_or_legal_immigrant: true} + person15: {age: 40, is_citizen_or_legal_immigrant: true} + person16: {age: 40, is_citizen_or_legal_immigrant: true} + person17: {age: 40, is_citizen_or_legal_immigrant: true} + person18: {age: 40, is_citizen_or_legal_immigrant: true} + person19: {age: 40, is_citizen_or_legal_immigrant: true} + person20: {age: 40, is_citizen_or_legal_immigrant: true} + person21: {age: 40, is_citizen_or_legal_immigrant: true} + person22: {age: 40, is_citizen_or_legal_immigrant: true} + spm_units: + spm_unit1: + members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10, person11] + heating_type: ELECTRICITY + pre_subsidy_electricity_expense: 1_200 + spm_unit2: + members: [person12, person13, person14, person15, person16, person17, person18, person19, person20, person21, person22] + heating_type: ELECTRICITY + pre_subsidy_electricity_expense: 1_200 + households: + household1: + members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10, person11] + state_code: WV + household2: + members: [person12, person13, person14, person15, person16, person17, person18, person19, person20, person21, person22] + state_code: WV + output: + wv_lieap: [192.5, 183.75] + +- name: Case 6, a reachable bulk-fuel half cent rounds up for five people. + period: 2026 + absolute_error_margin: 0.001 + # Monthly5300 is below the five-person5475 ceiling and uses base135. + # The printed135 *1.089 =147.015 rounds to147.02, not147.01. + input: + people: + person1: {age: 40, is_citizen_or_legal_immigrant: true, employment_income: 63_600} + person2: {age: 40, is_citizen_or_legal_immigrant: true} + person3: {age: 40, is_citizen_or_legal_immigrant: true} + person4: {age: 40, is_citizen_or_legal_immigrant: true} + person5: {age: 40, is_citizen_or_legal_immigrant: true} + spm_units: + spm_unit1: + members: [person1, person2, person3, person4, person5] + heating_type: PROPANE + bottled_gas_expense: 1_200 + households: + household1: + members: [person1, person2, person3, person4, person5] + state_code: WV + output: + wv_lieap: 147.02 + +- name: Case 7, twenty people reach base65 while twenty-one remains unmodeled. + period: 2026 + absolute_error_margin: 0.001 + # Twenty people at the15019 monthly ceiling use band38/base65. + # 65 *1.089 =70.785 rounds to70.79. Twenty-one with zero income is + # within the ordinary income limit but outside modeled payment-table coverage; + # zero for that row is not a legal ineligibility determination. + input: + people: + person1: {age: 40, is_citizen_or_legal_immigrant: true, employment_income: 180_228} + person2: {age: 40, is_citizen_or_legal_immigrant: true} + person3: {age: 40, is_citizen_or_legal_immigrant: true} + person4: {age: 40, is_citizen_or_legal_immigrant: true} + person5: {age: 40, is_citizen_or_legal_immigrant: true} + person6: {age: 40, is_citizen_or_legal_immigrant: true} + person7: {age: 40, is_citizen_or_legal_immigrant: true} + person8: {age: 40, is_citizen_or_legal_immigrant: true} + person9: {age: 40, is_citizen_or_legal_immigrant: true} + person10: {age: 40, is_citizen_or_legal_immigrant: true} + person11: {age: 40, is_citizen_or_legal_immigrant: true} + person12: {age: 40, is_citizen_or_legal_immigrant: true} + person13: {age: 40, is_citizen_or_legal_immigrant: true} + person14: {age: 40, is_citizen_or_legal_immigrant: true} + person15: {age: 40, is_citizen_or_legal_immigrant: true} + person16: {age: 40, is_citizen_or_legal_immigrant: true} + person17: {age: 40, is_citizen_or_legal_immigrant: true} + person18: {age: 40, is_citizen_or_legal_immigrant: true} + person19: {age: 40, is_citizen_or_legal_immigrant: true} + person20: {age: 40, is_citizen_or_legal_immigrant: true} + person21: {age: 40, is_citizen_or_legal_immigrant: true} + person22: {age: 40, is_citizen_or_legal_immigrant: true} + person23: {age: 40, is_citizen_or_legal_immigrant: true} + person24: {age: 40, is_citizen_or_legal_immigrant: true} + person25: {age: 40, is_citizen_or_legal_immigrant: true} + person26: {age: 40, is_citizen_or_legal_immigrant: true} + person27: {age: 40, is_citizen_or_legal_immigrant: true} + person28: {age: 40, is_citizen_or_legal_immigrant: true} + person29: {age: 40, is_citizen_or_legal_immigrant: true} + person30: {age: 40, is_citizen_or_legal_immigrant: true} + person31: {age: 40, is_citizen_or_legal_immigrant: true} + person32: {age: 40, is_citizen_or_legal_immigrant: true} + person33: {age: 40, is_citizen_or_legal_immigrant: true} + person34: {age: 40, is_citizen_or_legal_immigrant: true} + person35: {age: 40, is_citizen_or_legal_immigrant: true} + person36: {age: 40, is_citizen_or_legal_immigrant: true} + person37: {age: 40, is_citizen_or_legal_immigrant: true} + person38: {age: 40, is_citizen_or_legal_immigrant: true} + person39: {age: 40, is_citizen_or_legal_immigrant: true} + person40: {age: 40, is_citizen_or_legal_immigrant: true} + person41: {age: 40, is_citizen_or_legal_immigrant: true} + spm_units: + spm_unit1: + members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10, person11, person12, person13, person14, person15, person16, person17, person18, person19, person20] + heating_type: PROPANE + bottled_gas_expense: 1_200 + spm_unit2: + members: [person21, person22, person23, person24, person25, person26, person27, person28, person29, person30, person31, person32, person33, person34, person35, person36, person37, person38, person39, person40, person41] + heating_type: PROPANE + bottled_gas_expense: 1_200 + households: + household1: + members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10, person11, person12, person13, person14, person15, person16, person17, person18, person19, person20] + state_code: WV + household2: + members: [person21, person22, person23, person24, person25, person26, person27, person28, person29, person30, person31, person32, person33, person34, person35, person36, person37, person38, person39, person40, person41] + state_code: WV + output: + wv_lieap: [70.79, 0] + +- name: Case 8, represented heating responsibility allows direct and stated costs. + period: 2027 + absolute_error_margin: 0.01 + # Rows1-2 pay direct heat, including a subsidized tenant; no bill cap applies. + # Row4 bundled rent has no responsibility override and remains unmodeled. + # Known-obligation overrides are isolated in Case9 so no input on this + # variable suppresses its derived default for the other units in this case. + input: + people: + person1: {age: 40, is_citizen_or_legal_immigrant: true} + person2: {age: 40, is_citizen_or_legal_immigrant: true} + person3: {age: 40, is_citizen_or_legal_immigrant: true} + person4: {age: 40, is_citizen_or_legal_immigrant: true} + person5: {age: 40, is_citizen_or_legal_immigrant: true} + person6: {age: 40, is_citizen_or_legal_immigrant: false} + spm_units: + spm_unit1: + members: [person1] + heating_type: ELECTRICITY + pre_subsidy_electricity_expense: 1 + spm_unit2: + members: [person2] + heating_type: ELECTRICITY + pre_subsidy_electricity_expense: 1_200 + receives_housing_assistance: true + spm_unit3: + members: [person3] + heating_type: ELECTRICITY + spm_unit4: + members: [person4] + heating_type: ELECTRICITY + pre_subsidy_electricity_expense: 1_200 + receives_housing_assistance: true + heat_expense_included_in_rent: true + spm_unit5: + members: [person5] + heating_type: ELECTRICITY + pre_subsidy_electricity_expense: 1_200 + spm_unit6: + members: [person6] + heating_type: ELECTRICITY + pre_subsidy_electricity_expense: 1_200 + households: + household1: {members: [person1], state_code: WV} + household2: {members: [person2], state_code: WV} + household3: {members: [person3], state_code: WV} + household4: {members: [person4], state_code: WV} + household5: {members: [person5], state_code: OH} + household6: {members: [person6], state_code: WV} + output: + wv_lieap: [280, 280, 0, 0, 0, 0] + +- name: Case 9, known responsibility for auxiliary and stated rent costs is supplied. + period: 2027 + absolute_error_margin: 0.01 + # The FY2027 manual expressly recognizes auxiliary electricity for self-cut + # wood. A separately documented heating charge in rent also qualifies. + # These existing responsibility facts are supplied only in this case; normal + # bill-based defaults remain independently exercised in Case8. + input: + people: + person1: {age: 40, is_citizen_or_legal_immigrant: true} + person2: {age: 40, is_citizen_or_legal_immigrant: true} + spm_units: + spm_unit1: + members: [person1] + heating_type: WOOD + wood_expense: 0 + pre_subsidy_electricity_expense: 200 + has_heating_expense: true + spm_unit2: + members: [person2] + heating_type: ELECTRICITY + pre_subsidy_electricity_expense: 200 + heat_expense_included_in_rent: true + has_heating_expense: true + households: + household1: {members: [person1], state_code: WV} + household2: {members: [person2], state_code: WV} + output: + wv_lieap: [174.24, 280] diff --git a/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_income_eligible.yaml new file mode 100644 index 00000000000..2e020fdc171 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_income_eligible.yaml @@ -0,0 +1,104 @@ +# Current Income Maintenance Manual, section 21.3.1.A, physical page 1726. +# https://bfa.wv.gov/media/40005/download?inline=#page=1726 + +- name: Case 1, the FY2026 ceiling is inclusive with qualified and state guards. + period: 2026 + # One qualified person has a $2,454 monthly ceiling, or $29,448 annually. + # The second row earns $2,454.01 per month. No qualified member must fail + # even when both countable income and the household limit are zero. + input: + state_code: [WV, WV, WV, OH] + age: [40, 40, 40, 40] + is_citizen_or_legal_immigrant: [true, true, false, true] + employment_income: [29_448, 29_448.12, 0, 0] + output: + wv_lieap_income_eligible: [true, false, false, false] + +- name: Case 2, the FY2027 ceiling remains inclusive without changing the formula. + period: 2027 + # The requested-year one-person limit is $2,550 monthly, or $30,600 annually. + input: + state_code: [WV, WV] + age: [40, 40] + is_citizen_or_legal_immigrant: [true, true] + employment_income: [30_600, 30_600.12] + output: + wv_lieap_income_eligible: [true, false] + +- name: Case 3, reported SNAP TANF or SSI receipt does not bypass the ceiling. + period: 2026 + # Every two-person group has $40,000 wages, above its $3,209 * 12 = $38,508 + # ceiling. Reported receipt facts do not override the manual's income test. + input: + people: + person1: + age: 40 + is_citizen_or_legal_immigrant: true + employment_income: 40_000 + person2: + age: 8 + is_citizen_or_legal_immigrant: true + person3: + age: 40 + is_citizen_or_legal_immigrant: true + employment_income: 40_000 + person4: + age: 8 + is_citizen_or_legal_immigrant: true + person5: + age: 40 + is_citizen_or_legal_immigrant: true + employment_income: 40_000 + person6: + age: 8 + is_citizen_or_legal_immigrant: true + receives_ssi: + 2026-01: true + spm_units: + spm_unit1: + members: [person1, person2] + receives_snap: + 2026-01: true + spm_unit2: + members: [person3, person4] + receives_tanf: + 2026-01: true + spm_unit3: + members: [person5, person6] + households: + household1: {members: [person1, person2], state_code: WV} + household2: {members: [person3, person4], state_code: WV} + household3: {members: [person5, person6], state_code: WV} + output: + wv_lieap_income_eligible: [false, false, false] + +- name: Case 4, nonqualified members income counts without increasing the limit. + period: 2026 + # Both groups have $36,000 wages. With one qualified person, the limit is + # $29,448; with two qualified people, the limit is $38,508. + input: + people: + person1: + age: 40 + is_citizen_or_legal_immigrant: true + employment_income: 18_000 + person2: + age: 40 + is_citizen_or_legal_immigrant: false + employment_income: 18_000 + person3: + age: 40 + is_citizen_or_legal_immigrant: true + employment_income: 18_000 + person4: + age: 40 + is_citizen_or_legal_immigrant: true + employment_income: 18_000 + spm_units: + spm_unit1: {members: [person1, person2]} + spm_unit2: {members: [person3, person4]} + households: + household1: {members: [person1, person2], state_code: WV} + household2: {members: [person3, person4], state_code: WV} + output: + wv_lieap_income_eligible: [false, true] diff --git a/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap.py b/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap.py new file mode 100644 index 00000000000..79cccd1d667 --- /dev/null +++ b/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap.py @@ -0,0 +1,55 @@ +from policyengine_us.model_api import * + + +class wv_lieap(Variable): + value_type = float + entity = SPMUnit + label = "West Virginia modeled regular heating LIEAP payment" + unit = USD + definition_period = YEAR + defined_for = "wv_lieap_income_eligible" + reference = ( + # PDF pages 1729-1731,1753-1755,1772-1773 + "https://bfa.wv.gov/media/39948/download?inline=#page=1729", + # PDF pages 1730-1734,1757-1758,1775-1776 + "https://bfa.wv.gov/media/40005/download?inline=#page=1730", + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.wv.dhhr.lieap.payment + size = spm_unit("wv_lieap_household_size", period) + income = spm_unit("wv_lieap_countable_income", period) / MONTHS_IN_YEAR + # Approved convention: use the printed upper bounds continuously, + # including cents, rather than the overlapping integer lower bounds. + band = p.income_band.calc(income, right=True) + # Exact compression of every occupied published cell, not extrapolation. + # Income eligibility confines sizes 1-20 to occupied table cells. + base = p.base_amount + p.amount_step * (size - 1 - band) + heating = spm_unit("heating_type", period) + types = heating.possible_values + multiplier = select( + [ + heating == types.ELECTRICITY, + heating == types.NATURAL_GAS, + (heating == types.FUEL_OIL) + | (heating == types.KEROSENE) + | (heating == types.PROPANE) + | (heating == types.WOOD) + | (heating == types.COAL), + ], + [ + p.fuel_multiplier.electricity, + p.fuel_multiplier.natural_gas, + p.fuel_multiplier.bulk_fuel, + ], + default=0, + ) + # Integer bases and three-decimal multipliers give exact dollar mills. + # Convert those to cents half up, matching the printed $70.79/$147.02. + mills = np.rint(base * multiplier * 1_000) + amount = np.floor((mills + 5) / 10) / 100 + pays_for_heat = spm_unit("has_heating_expense", period) + # Above 20 members is unmodeled coverage, not legal ineligibility. + # Existing heating-cost facts approximate the documented obligation; + # designated rent charges and some dwelling facts remain unobserved. + return where((size <= p.max_household_size) & pays_for_heat, amount, 0) diff --git a/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_income_eligible.py b/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_income_eligible.py new file mode 100644 index 00000000000..ae9dce8fef8 --- /dev/null +++ b/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_income_eligible.py @@ -0,0 +1,17 @@ +from policyengine_us.model_api import * + + +class wv_lieap_income_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "West Virginia LIEAP income eligible" + definition_period = YEAR + defined_for = StateCode.WV + # PDF pages 1726,1745,1752 + reference = "https://bfa.wv.gov/media/40005/download?inline=#page=1726" + + def formula(spm_unit, period, parameters): + size = spm_unit("wv_lieap_household_size", period) + income = spm_unit("wv_lieap_countable_income", period) + limit = spm_unit("wv_lieap_income_limit", period) + return (size > 0) & (income <= limit) From 9f2805c964655ad15228fdcf9df6c80fa815fa5f Mon Sep 17 00:00:00 2001 From: Ziming Date: Mon, 2 Nov 2026 11:57:08 -0500 Subject: [PATCH 4/7] Apply Wave 2C sweep and review fixes Co-Authored-By: Claude Opus 5.5 --- changelog.d/wv-liheap-wave2c.added.md | 2 +- .../gov/states/wv/dhhr/lieap/README.md | 113 --- .../dhhr/lieap/eligibility/fpg_year_lag.yaml | 8 +- .../eligibility/smi_max_household_size.yaml | 2 +- .../lieap/income/nonnegative_sources.yaml | 20 - .../states/wv/dhhr/lieap/income/sources.yaml | 19 +- .../wv/dhhr/lieap/payment/income_band.yaml | 4 +- policyengine_us/programs.yaml | 9 +- .../gov/states/wv/dhhr/lieap/wv_lieap.yaml | 51 +- .../dhhr/lieap/wv_lieap_countable_income.yaml | 166 ++-- .../dhhr/lieap/wv_lieap_household_size.yaml | 6 +- .../dhhr/lieap/wv_lieap_income_eligible.yaml | 6 +- .../wv/dhhr/lieap/wv_lieap_income_limit.yaml | 764 ++++++------------ .../gov/states/wv/dhhr/lieap/wv_lieap.py | 4 +- .../dhhr/lieap/wv_lieap_countable_income.py | 13 +- .../wv/dhhr/lieap/wv_lieap_household_size.py | 8 +- .../wv/dhhr/lieap/wv_lieap_income_eligible.py | 8 +- .../wv/dhhr/lieap/wv_lieap_income_limit.py | 13 +- 18 files changed, 385 insertions(+), 831 deletions(-) delete mode 100644 policyengine_us/parameters/gov/states/wv/dhhr/lieap/README.md delete mode 100644 policyengine_us/parameters/gov/states/wv/dhhr/lieap/income/nonnegative_sources.yaml diff --git a/changelog.d/wv-liheap-wave2c.added.md b/changelog.d/wv-liheap-wave2c.added.md index 5071594a9a7..308711ddf73 100644 --- a/changelog.d/wv-liheap-wave2c.added.md +++ b/changelog.d/wv-liheap-wave2c.added.md @@ -1 +1 @@ -Add West Virginia modeled regular heating LIEAP payments for one through twenty qualified members, with source-specific income handling, the operational income ceiling, approved continuous published upper bands and half-up cent rounding. Reuse existing heating-responsibility facts; larger households, unsupported fuels and administrative housing details remain partial coverage. +Add West Virginia LIEAP regular heating payments for FY2026 and FY2027 for one through twenty qualified members, with the manual's income rules, income ceiling and payment chart. diff --git a/policyengine_us/parameters/gov/states/wv/dhhr/lieap/README.md b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/README.md deleted file mode 100644 index dd42c7163d8..00000000000 --- a/policyengine_us/parameters/gov/states/wv/dhhr/lieap/README.md +++ /dev/null @@ -1,113 +0,0 @@ -# West Virginia modeled regular heating assistance - -The household-size, countable-income, income-limit, income-eligibility and modeled -regular-payment components use the FY2026 state plan and operational manuals, -including the adopted October 2026 update for FY2027. The assistance group includes co-residents sharing -heating costs. Qualified members count in its size; nonqualified members' income -is not excluded. SPM membership approximates the physical sharing group. Prior -assistance in another group can exclude a member, but receipt history is absent -from existing inputs and is not inferred. - -The plan specifies 60% of requested-year SMI through size seven, then 150% of -prior-calendar-year FPG from size eight. Nearest-dollar monthly rounding matches -all ten preserved FY2026 agency amounts. Applying the guideline before rounding also -matches the manual's size-eleven limit of $8,831; repeatedly adding the web page's -rounded $688 increment gives a conflicting $8,832. The adopted percentage and -manual calculation take precedence over that rounded web shorthand. This is a -numerically validated rounding convention, not an express rounding instruction. -The same calculation matches the current manual's FY2027 monthly limits for -sizes one through eleven. The payment grid's apparent size-twelve maximum of -$10,160 conflicts with the guideline-derived $9,805; payment cells do not replace -the stated income eligibility rule. -Fresh FY2027 public materials print $6,695 for eight people, while the -operational manual and 150% FPG calculation give $6,965. The model retains the -manual/guideline amount; this discrepancy does not authorize smoothing any -other printed payment-band bound. - -Countable income follows the detailed operational manual, which current Board -of Review decisions apply, over unchecked summary-plan categories. This is an -explicit source-priority interpretation: minor earnings, TANF, general -assistance and recurring gifts count. RSDI and SSI do not. The manual distinguishes -excluded nonrecurring lump sums from recurring payments prorated over the period -they cover. Annual income fields approximate recurring application-month income. -Existing net business inputs receive no second 20% deduction, and business or -estate losses do not offset other sources under this modeling approximation. This does -not reproduce the source's gross-receipts calculation. - -Pension, military retirement pay, retirement-account and non-Social-Security -survivor receipts each enter once through their separate existing inputs. -Each person's represented recurring source is floored at zero before aggregation; -rental losses cannot cancel pensions, wages or another member's receipts. -Unemployment uses the shared reported-or-modeled receipt amount. TANF uses the -shared take-up-gated receipt, annualizing monthly WV WORKS once at the household -level. Separate royalties and foster-care receipts are not identified -by existing inputs. Generic VA benefits cannot separate excluded Aid and -Attendance. The December 18, 2025 announcement broadly describes VA benefits -as excluded, in tension with the manual's specific Aid and Attendance -exclusion. Existing manual-priority treatment is retained; this source conflict -is not declared resolved. Employment cannot separate excluded work-study, CNCS or CSEP -wages. A work-study participation flag cannot determine which wages to subtract. -Aggregate child support, retirement, insurance, estate and gift inputs cannot -identify every recurring payment, arrearage or earmarked reimbursement. These -are input limitations, not blanket legal inclusions or exclusions. Standalone -capital gains, life-insurance death proceeds and gambling/lottery winnings are -treated as nonrecurring; an actual recurring installment needs a separately -identified receipt that existing inputs do not provide. The operative manual's -gross-income rule does not authorize a general Medicare premium deduction; -RSDI is already excluded in full, so its Medicare withholding is not subtracted -from other countable receipts. - -The income-eligibility component requires a positive qualified household size -and countable income at or below the existing limit. The operational manual's -section 21.3.1.A explicitly denies groups above the income ceiling. Mail-out -reviews still require verification, and the manual's mixed SSI/employment -example requires verification of the employment income. The summary plan's -categorical checkboxes remain a source tension, but they do not establish an -unconstrained SNAP, TANF or SSI income-ceiling bypass. This follows the detailed -operational manual's income rule rather than inferring an exemption from -application streamlining. - -The regular-payment output supports one through twenty qualified members. On -October 20, 2026, the user approved using the published upper income bounds as -continuous closed-top intervals, without rounding observed monthly income. This -resolves the overlapping first/second lower endpoints and fractional-dollar -gaps. Every other printed upper bound is retained, including irregular values; -the table is not smoothed. The existing income ceiling is still independently -applied. The source library preserves both literal grids and edition details, -including the earlier chart's stale FY2025 heading despite its FY2026 limits. - -All 840 occupied cells across the two published grids exactly equal -`base_amount + amount_step * (size - 1 - band_index)`. -This is lossless compression of the published amounts, not permission to -extrapolate. The ordinary income limit confines eligible sizes one through -twenty to occupied cells. Fuel multipliers are applied once to the base amount. -Integer-dollar bases and three-decimal multipliers give exact dollar mills; -rounding those to cents half up reproduces the printed $70.79 and $147.02. -No unsupported actual-bill cap or proportional reduction for partial -responsibility is imposed. The combined regular/crisis ceiling and equipment -maximum are outside this regular payment calculation. - -Heating responsibility reuses `has_heating_expense`. Its default requires a -matching positive primary-fuel bill and excludes heat bundled in rent. A -subsidized tenant paying direct heating costs can qualify. The existing flag -can be supplied for a known obligation that its default cannot infer, including -documented heating charges in rent or auxiliary electric costs with self-cut -wood. The heat-in-rent or subsidy flag alone cannot establish that obligation. -No blanket exclusion of subsidized renters is introduced. A default zero for -bundled rent without the responsibility fact is not a definitive legal denial. - -Some facts remain unobserved: designated rent charges, anticipated surcharges, -traditional versus movable dwellings, portable-heater or alternate-fuel -approval, and prior-season duplicate assistance. The FY2027 manual explicitly -retains responsibility for a zero/minimal-income client whose own heating bill -is paid by an outsider; earlier wording differs. The model does not identify -every billholder or third-party arrangement and does not backdate that -exception. These are documented existing-input approximations, not new inputs -or a complete administrative housing predicate. - -Payment coverage above twenty members and for UNSPECIFIED, SOLAR or OTHER fuel -remains unmodeled. Output zero for those cases means no modeled award, not legal -ineligibility. NONE affirmatively reports no heating. The registry remains -partial and omits `verified_years`; no fully verified program year is claimed. -Earlier backfilled results are unverified historical estimates. Crisis, cooling, -weatherization, equipment and the separate utility discount remain out of scope. diff --git a/policyengine_us/parameters/gov/states/wv/dhhr/lieap/eligibility/fpg_year_lag.yaml b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/eligibility/fpg_year_lag.yaml index 77e482d5924..f5e99a72fcb 100644 --- a/policyengine_us/parameters/gov/states/wv/dhhr/lieap/eligibility/fpg_year_lag.yaml +++ b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/eligibility/fpg_year_lag.yaml @@ -1,3 +1,5 @@ +# The plan names HHS Poverty Guidelines without a year. The printed limits fix the +# lag: 150% x $54,150 / 12 = $6,768.75, printed as $6,769 for eight in FY2026. description: West Virginia uses poverty guidelines from this many calendar years before the benefit year under the Low Income Energy Assistance Program. values: 2025-10-01: 1 @@ -6,5 +8,7 @@ metadata: period: year label: West Virginia LIEAP fpg year lag reference: - - title: "West Virginia accepted FY2026 LIHEAP State Plan, heating eligibility #page 9,11" - href: https://liheapch.acf.gov/docs/2026/state-plans/WV_Plan_2026.pdf#page=9 + - title: West Virginia Income Maintenance Manual, Chapter 4 Appendix A + href: https://bfa.wv.gov/media/39948/download?inline=#page=406 + - title: West Virginia Income Maintenance Manual, October 2026 edition, Chapter 4 Appendix A + href: https://bfa.wv.gov/media/40005/download?inline=#page=405 diff --git a/policyengine_us/parameters/gov/states/wv/dhhr/lieap/eligibility/smi_max_household_size.yaml b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/eligibility/smi_max_household_size.yaml index b260ba88c98..a388b8a8ed1 100644 --- a/policyengine_us/parameters/gov/states/wv/dhhr/lieap/eligibility/smi_max_household_size.yaml +++ b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/eligibility/smi_max_household_size.yaml @@ -2,7 +2,7 @@ description: West Virginia uses state median income through this household size values: 2025-10-01: 7 metadata: - unit: int + unit: person period: year label: West Virginia LIEAP smi max household size reference: diff --git a/policyengine_us/parameters/gov/states/wv/dhhr/lieap/income/nonnegative_sources.yaml b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/income/nonnegative_sources.yaml deleted file mode 100644 index fd63a39a38e..00000000000 --- a/policyengine_us/parameters/gov/states/wv/dhhr/lieap/income/nonnegative_sources.yaml +++ /dev/null @@ -1,20 +0,0 @@ -description: West Virginia counts positive amounts of these represented net income sources under the Low Income Energy Assistance Program. -values: - 2025-10-01: - - self_employment_income - - sstb_self_employment_income - - farm_operations_income - - partnership_s_corp_income - - estate_income -# The source deducts 20% from gross receipts. Existing inputs are already net; -# using them without another deduction is an explicit modeling approximation. -# Estate and business losses do not offset other income. -metadata: - unit: list - period: year - label: West Virginia LIEAP net income sources without loss offsets - reference: - - title: "West Virginia Income Maintenance Manual, Chapter 21.3.1.A #page 1725-1726" - href: https://bfa.wv.gov/media/39948/download?inline=#page=1725 - - title: "West Virginia Income Maintenance Manual, October 2026 edition, Chapter 21.3.1.A #page 1726-1727" - href: https://bfa.wv.gov/media/40005/download?inline=#page=1726 diff --git a/policyengine_us/parameters/gov/states/wv/dhhr/lieap/income/sources.yaml b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/income/sources.yaml index a58e1293836..64af59661e2 100644 --- a/policyengine_us/parameters/gov/states/wv/dhhr/lieap/income/sources.yaml +++ b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/income/sources.yaml @@ -1,11 +1,20 @@ -description: West Virginia counts these represented recurring income sources, in addition to net business and estate income, under the Low Income Energy Assistance Program. +description: West Virginia counts these represented recurring income sources under the Low Income Energy Assistance Program. values: 2025-10-01: - employment_income + # The source deducts 20% from gross receipts. Existing inputs are already net; + # using them without another deduction is an explicit modeling approximation. + - self_employment_income + - sstb_self_employment_income + - farm_operations_income + - partnership_s_corp_income + - estate_income - total_unemployment_compensation - strike_benefits - pension_income - - military_retirement_pay + - military_retirement_income + # Railroad retirement is paid by the Railroad Retirement Board, not SSA. + - railroad_benefits - retirement_distributions - survivor_benefits - general_assistance @@ -19,11 +28,15 @@ values: - workers_compensation - disability_benefits - financial_assistance + # The only input able to carry contract, mineral-rights, jury-duty or settlement + # receipts, which the manual's all-source rule counts. + - miscellaneous_income # All members' income counts, regardless of age or immigration qualification. # Take-up-gated TANF is counted separately once at the household level. +# Military retirement includes Survivor Benefit Plan annuities. # RSDI, SSI and nonrecurring lump sums are excluded. Aggregate annual receipts # are treated as recurring; VA Aid and Attendance cannot be separated from -# veterans_benefits. These input limitations are documented in the README. +# veterans_benefits. metadata: unit: list period: year diff --git a/policyengine_us/parameters/gov/states/wv/dhhr/lieap/payment/income_band.yaml b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/payment/income_band.yaml index fc64e5659eb..6428a8cd728 100644 --- a/policyengine_us/parameters/gov/states/wv/dhhr/lieap/payment/income_band.yaml +++ b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/payment/income_band.yaml @@ -1,6 +1,6 @@ # Use the first matching inclusive published upper bound with calc(right=True). -# The user approved ordered upper bounds and continuous monthly income on -# October 20, 2026, resolving overlapping From values and gaps between dollars. +# Ordered upper bounds and continuous monthly income resolve the printed From +# values that overlap and the gaps between whole-dollar rows. # Retain every printed upper bound, including irregular larger-family intervals. # Band 40 is the sentinel above the final published row, not another payment. description: West Virginia determines this zero-based payment row from monthly countable income under the Low Income Energy Assistance Program. diff --git a/policyengine_us/programs.yaml b/policyengine_us/programs.yaml index d3ad09e0199..7e4ad2a037b 100644 --- a/policyengine_us/programs.yaml +++ b/policyengine_us/programs.yaml @@ -808,7 +808,7 @@ programs: category: Benefits agency: HHS status: partial - coverage: AL, DC, Riverside County, MA, FL, IL, IN, KS, KY, MD, MS, NC, NE, NJ, NY, OH, OK, OR, SD, RI, TX + coverage: AL, DC, Riverside County, MA, FL, IL, IN, KS, KY, MD, MS, NC, NE, NJ, NY, OH, OK, OR, SD, RI, TX, WV state_implementations: - state: AL status: partial @@ -962,11 +962,12 @@ programs: notes: Models the 150% FPG income limit, the alternative 60% SMI limit from the FY2024 state plan (applied through 2024), 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: WV status: partial - name: West Virginia LIEAP modeled regular heating - full_name: West Virginia Low Income Energy Assistance Program modeled regular heating + name: West Virginia LIEAP + full_name: West Virginia Low Income Energy Assistance Program variable: wv_lieap parameter_prefix: gov.states.wv.dhhr.lieap - notes: "Modeled FY2026-FY2027 regular heating payments for one through twenty qualified members. The operational manual's inclusive income ceiling applies without an unconditional SNAP, TANF or SSI bypass; RSDI and SSI income remain excluded. Published upper payment-band bounds are used continuously without observed-income rounding under the user-approved convention; other printed bounds remain literal. Exact grid compression and fuel multipliers reproduce occupied table amounts with half-up cent rounding. Shared heating-cost facts represent responsibility, including explicit known-obligation overrides; no blanket subsidy exclusion or actual-bill cap. Designated rent charges, dwelling/alternate-fuel approval, billholder and prior-assistance facts remain partly unobserved. Above twenty members and unsupported fuels return an unmodeled zero, not a definitive legal denial. Annual flows approximate application-month income and aggregate inputs cannot separate all excluded receipts. No fully verified year; earlier backfills are unverified historical estimates. Crisis, cooling, weatherization, equipment and the separate utility discount remain outside scope." + verified_years: "2026-2027" + notes: FY2026-FY2027 regular heating payments for households of one to twenty qualified members. Crisis, cooling, weatherization, equipment and the utility discount are out of scope. # --- SSA programs --- - id: ssi diff --git a/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap.yaml b/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap.yaml index 0198231882f..a5fb8e57f04 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap.yaml @@ -3,7 +3,7 @@ # https://bfa.wv.gov/media/39948/download?inline=#page=1754 # FY2027: PDF pages 1757-1758,1775-1776 # https://bfa.wv.gov/media/40005/download?inline=#page=1757 -# User-approved convention: continuous published upper bounds, no income rounding. +# Continuous published upper bounds apply, with no income rounding. - name: Case 1, zero income receives each supported fuel amount without a bill cap. period: 2026 @@ -32,7 +32,7 @@ period: 2026 absolute_error_margin: 0.01 # Monthly wages: 2077, 2077.25, 2077.50, 2078, 2454 and 2454.01. - # Only exact 2077 uses base160; the next four use155. Last row is over limit. + # Only exact 2077 uses base 160; the next four use 155. Last row is over limit. input: state_code: [WV, WV, WV, WV, WV, WV] is_citizen_or_legal_immigrant: [true, true, true, true, true, true] @@ -60,8 +60,8 @@ - name: Case 4, the literal FY2027 third-person upper bound is not smoothed. period: 2027 absolute_error_margin: 0.01 - # Monthly3400 is within the printed3427 upper bound: base150 *1.089=163.35. - # Monthly3430 is in the next row: base145 *1.089=157.905, rounded157.91. + # Monthly 3400 is within the printed 3427 upper bound: base 150 x 1.089 = 163.35. + # Monthly 3430 is in the next row: base 145 x 1.089 = 157.905, rounded 157.91. input: people: person1: {age: 40, is_citizen_or_legal_immigrant: true, employment_income: 40_800} @@ -92,8 +92,8 @@ - name: Case 5, the literal FY2026 larger-family upper bound is not smoothed. period: 2026 absolute_error_margin: 0.01 - # Monthly8477 uses band20/base110; monthly8480 uses band21/base105. - # Both are below the eleven-person8831 monthly ceiling. + # Monthly 8477 uses band 20 and base 110; monthly 8480 uses band 21 and base 105. + # Both are below the eleven-person 8831 monthly ceiling. input: people: person1: {age: 40, is_citizen_or_legal_immigrant: true, employment_income: 101_724} @@ -140,8 +140,8 @@ - name: Case 6, a reachable bulk-fuel half cent rounds up for five people. period: 2026 absolute_error_margin: 0.001 - # Monthly5300 is below the five-person5475 ceiling and uses base135. - # The printed135 *1.089 =147.015 rounds to147.02, not147.01. + # Monthly 5300 is below the five-person 5475 ceiling and uses base 135. + # The printed 135 x 1.089 = 147.015 rounds to 147.02, not 147.01. input: people: person1: {age: 40, is_citizen_or_legal_immigrant: true, employment_income: 63_600} @@ -161,11 +161,11 @@ output: wv_lieap: 147.02 -- name: Case 7, twenty people reach base65 while twenty-one remains unmodeled. +- name: Case 7, twenty people reach base 65 while twenty-one remains unmodeled. period: 2026 absolute_error_margin: 0.001 - # Twenty people at the15019 monthly ceiling use band38/base65. - # 65 *1.089 =70.785 rounds to70.79. Twenty-one with zero income is + # Twenty people at the 15019 monthly ceiling use band 38 and base 65. + # 65 x 1.089 = 70.785 rounds to 70.79. Twenty-one with zero income is # within the ordinary income limit but outside modeled payment-table coverage; # zero for that row is not a legal ineligibility determination. input: @@ -233,9 +233,9 @@ - name: Case 8, represented heating responsibility allows direct and stated costs. period: 2027 absolute_error_margin: 0.01 - # Rows1-2 pay direct heat, including a subsidized tenant; no bill cap applies. - # Row4 bundled rent has no responsibility override and remains unmodeled. - # Known-obligation overrides are isolated in Case9 so no input on this + # Rows 1-2 pay direct heat, including a subsidized tenant; no bill cap applies. + # Row 4 bundled rent has no responsibility override and remains unmodeled. + # Known-obligation overrides are isolated in Case 9 so no input on this # variable suppresses its derived default for the other units in this case. input: people: @@ -288,7 +288,7 @@ # The FY2027 manual expressly recognizes auxiliary electricity for self-cut # wood. A separately documented heating charge in rent also qualifies. # These existing responsibility facts are supplied only in this case; normal - # bill-based defaults remain independently exercised in Case8. + # bill-based defaults remain independently exercised in Case 8. input: people: person1: {age: 40, is_citizen_or_legal_immigrant: true} @@ -311,3 +311,24 @@ household2: {members: [person2], state_code: WV} output: wv_lieap: [174.24, 280] + +- name: Case 10, a nonqualified member's income counts without enlarging the payment size. + period: 2026 + absolute_error_margin: 0.01 + # Size 1 and monthly income 2000 use the first row, base 160, so 160 x 1.75 = 280. + # Size 2 would use base 165 and pay 288.75. + input: + people: + person1: {age: 40, is_citizen_or_legal_immigrant: true} + person2: {age: 40, is_citizen_or_legal_immigrant: false, employment_income: 24_000} + spm_units: + spm_unit1: + members: [person1, person2] + heating_type: ELECTRICITY + pre_subsidy_electricity_expense: 1_200 + households: + household1: {members: [person1, person2], state_code: WV} + output: + wv_lieap_household_size: 1 + wv_lieap_income_limit: 29_448 + wv_lieap: 280 diff --git a/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_countable_income.yaml index 9cc49b89938..ce8063b66ac 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_countable_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_countable_income.yaml @@ -51,29 +51,17 @@ members: - person1 - person2 - heating_type: NATURAL_GAS - gas_expense: 1200 - pre_subsidy_electricity_expense: 0 wv_works: 0 - snap: 0 spm_unit2: members: - person3 - person4 - heating_type: NATURAL_GAS - gas_expense: 1200 - pre_subsidy_electricity_expense: 0 wv_works: 0 - snap: 0 spm_unit3: members: - person5 - person6 - heating_type: NATURAL_GAS - gas_expense: 1200 - pre_subsidy_electricity_expense: 0 wv_works: 0 - snap: 0 households: household1: members: @@ -130,11 +118,7 @@ spm_unit1: members: - person1 - heating_type: NATURAL_GAS - gas_expense: 1200 - pre_subsidy_electricity_expense: 0 wv_works: 0 - snap: 0 households: household1: members: @@ -179,11 +163,7 @@ spm_unit1: members: - person1 - heating_type: NATURAL_GAS - gas_expense: 1200 - pre_subsidy_electricity_expense: 0 wv_works: 0 - snap: 0 households: household1: members: @@ -221,9 +201,6 @@ members: - person1 - person2 - heating_type: NATURAL_GAS - gas_expense: 1200 - pre_subsidy_electricity_expense: 0 wv_works: 2026-01: 100 2026-02: 200 @@ -237,13 +214,9 @@ 2026-10: 0 2026-11: 0 2026-12: 0 - snap: 0 spm_unit2: members: - person3 - heating_type: NATURAL_GAS - gas_expense: 1200 - pre_subsidy_electricity_expense: 0 wv_works: 2026-01: 25 2026-02: 25 @@ -257,7 +230,6 @@ 2026-10: 25 2026-11: 25 2026-12: 25 - snap: 0 households: household1: members: @@ -274,7 +246,7 @@ - 350 - name: Case 5, existing net businesses are not discounted again and losses do not offset earnings. - # Authorized net-business approximation: do not apply the manual gross-receipts 20% deduction twice. + # Net-business approximation: do not apply the manual gross-receipts 20% deduction twice. # First unit sums 1_000 + 2_000 + 3_000 + 4_000 = 10_000. # Second counts wages 10_000 + positive business 2_000 + 3_000 = 15_000. # Negative business streams contribute zero; the all-loss unit has zero income. @@ -311,27 +283,15 @@ spm_unit1: members: - person1 - heating_type: NATURAL_GAS - gas_expense: 1200 - pre_subsidy_electricity_expense: 0 wv_works: 0 - snap: 0 spm_unit2: members: - person2 - heating_type: NATURAL_GAS - gas_expense: 1200 - pre_subsidy_electricity_expense: 0 wv_works: 0 - snap: 0 spm_unit3: members: - person3 - heating_type: NATURAL_GAS - gas_expense: 1200 - pre_subsidy_electricity_expense: 0 wv_works: 0 - snap: 0 households: household1: members: @@ -371,9 +331,6 @@ spm_unit1: members: - person1 - heating_type: NATURAL_GAS - gas_expense: 1200 - pre_subsidy_electricity_expense: 0 wv_works: 0 snap: 6000 households: @@ -405,11 +362,7 @@ spm_unit1: members: - person1 - heating_type: NATURAL_GAS - gas_expense: 1200 - pre_subsidy_electricity_expense: 0 wv_works: 0 - snap: 0 households: household1: members: @@ -452,27 +405,15 @@ members: - person1 - person2 - heating_type: NATURAL_GAS - gas_expense: 1200 - pre_subsidy_electricity_expense: 0 wv_works: 0 - snap: 0 spm_unit2: members: - person3 - heating_type: NATURAL_GAS - gas_expense: 1200 - pre_subsidy_electricity_expense: 0 wv_works: 0 - snap: 0 spm_unit3: members: - person4 - heating_type: NATURAL_GAS - gas_expense: 1200 - pre_subsidy_electricity_expense: 0 wv_works: 0 - snap: 0 households: household1: members: @@ -523,9 +464,6 @@ members: - person1 - person2 - heating_type: NATURAL_GAS - gas_expense: 1200 - pre_subsidy_electricity_expense: 0 wv_works: 2027-01: 100 2027-02: 100 @@ -539,7 +477,6 @@ 2027-10: 100 2027-11: 100 2027-12: 100 - snap: 0 households: household1: members: @@ -573,11 +510,7 @@ spm_units: spm_unit1: members: [person1, person2] - heating_type: NATURAL_GAS - gas_expense: 1_200 - pre_subsidy_electricity_expense: 0 wv_works: 0 - snap: 0 households: household1: members: [person1, person2] @@ -588,7 +521,7 @@ # Military pay is separate from pension_income. Rental losses cannot erase pensions or a different member's positive rent. # Expected [60_000, 30_000, 12_000 + 1_000] are supported countable-income outputs only. - name: Case 11, military retirement and positive receipts survive rental losses. - period: 2_026 + period: 2026 absolute_error_margin: 0.01 input: people: @@ -622,27 +555,15 @@ spm_unit1: members: - person1_1 - heating_type: NATURAL_GAS - gas_expense: 1_200 - pre_subsidy_electricity_expense: 0 - snap: 0 wv_works: 0 spm_unit2: members: - person2_1 - heating_type: NATURAL_GAS - gas_expense: 1_200 - pre_subsidy_electricity_expense: 0 - snap: 0 wv_works: 0 spm_unit3: members: - person3_1 - person3_2 - heating_type: NATURAL_GAS - gas_expense: 1_200 - pre_subsidy_electricity_expense: 0 - snap: 0 wv_works: 0 tax_units: tax_unit1: @@ -678,7 +599,7 @@ # Reported zero falls back to modeled UI; nonzero reported values override it. # Negative reported UI is zero for LIEAP, retaining the 12_000 wages. - name: Case 12, shared unemployment receipts retain overrides and floor negative amounts. - period: 2_026 + period: 2026 absolute_error_margin: 0.01 input: people: @@ -710,26 +631,14 @@ spm_unit1: members: - person1_1 - heating_type: NATURAL_GAS - gas_expense: 1_200 - pre_subsidy_electricity_expense: 0 - snap: 0 wv_works: 0 spm_unit2: members: - person2_1 - heating_type: NATURAL_GAS - gas_expense: 1_200 - pre_subsidy_electricity_expense: 0 - snap: 0 wv_works: 0 spm_unit3: members: - person3_1 - heating_type: NATURAL_GAS - gas_expense: 1_200 - pre_subsidy_electricity_expense: 0 - snap: 0 wv_works: 0 tax_units: tax_unit1: @@ -767,7 +676,7 @@ # Component receipt control: the supplied annual WV WORKS 6_000 represents 500/month. # Generic TANF annualizes once and suppresses the benefit for the nonparticipant. - name: Case 13, monthly TANF receipt counts once only for participants. - period: 2_026 + period: 2026 absolute_error_margin: 0.01 input: people: @@ -798,20 +707,12 @@ members: - person1_1 - person1_2 - heating_type: NATURAL_GAS - gas_expense: 1_200 - pre_subsidy_electricity_expense: 0 - snap: 0 wv_works: 6_000 takes_up_tanf_if_eligible: true spm_unit2: members: - person2_1 - person2_2 - heating_type: NATURAL_GAS - gas_expense: 1_200 - pre_subsidy_electricity_expense: 0 - snap: 0 wv_works: 6_000 takes_up_tanf_if_eligible: false tax_units: @@ -844,10 +745,9 @@ # No WV WORKS or TANF entitlement override. A zero-income parent and child have a # modeled size-two payment standard of 480/month, hence 5_760 annually. -# The eligible nonparticipant receives zero. This tests income receipt handling, -# with no assertion about an unimplemented final LIEAP eligibility or award. +# The eligible nonparticipant receives zero. This tests income receipt handling. - name: Case 14, actual modeled WV WORKS flows into income only when received. - period: 2_027 + period: 2027 absolute_error_margin: 0.01 input: people: @@ -882,18 +782,12 @@ members: - person1_1 - person1_2 - heating_type: NATURAL_GAS - gas_expense: 1_200 - pre_subsidy_electricity_expense: 0 snap: 0 takes_up_tanf_if_eligible: true spm_unit2: members: - person2_1 - person2_2 - heating_type: NATURAL_GAS - gas_expense: 1_200 - pre_subsidy_electricity_expense: 0 snap: 0 takes_up_tanf_if_eligible: false tax_units: @@ -923,3 +817,51 @@ wv_lieap_countable_income: - 5_760 - 0 + +# Manual 21.3.1.A.3 counts all sources; 21.3.1.A.5 excludes only SSA's RSDI and +# SSI, so Railroad Retirement Board payments of 20,000 count and RSDI of 6,000 +# does not. +- name: Case 15, railroad retirement counts although RSDI does not. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 66 + is_citizen_or_legal_immigrant: true + ssi: 0 + social_security_retirement: 6_000 + railroad_benefits: 20_000 + spm_units: + spm_unit: + members: [person1] + wv_works: 0 + households: + household: + members: [person1] + state_code: WV + output: + wv_lieap_countable_income: 20_000 + +# Manual 21.3.1.A.3 counts all sources and prorates recurring receipts such as a +# yearly mineral-rights check, so 3,000 of recurring miscellaneous income counts. +- name: Case 16, recurring miscellaneous receipts count under the all-source rule. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 60 + is_citizen_or_legal_immigrant: true + ssi: 0 + miscellaneous_income: 3_000 + spm_units: + spm_unit: + members: [person1] + wv_works: 0 + households: + household: + members: [person1] + state_code: WV + output: + wv_lieap_countable_income: 3_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_household_size.yaml b/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_household_size.yaml index 2c7a47d648c..43d404f222f 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_household_size.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_household_size.yaml @@ -1,8 +1,8 @@ -# Household composition: earlier official IMM21.3.1.B, physical1728; -# current IMM21.3.1.B and citizenship, physical1729,1734. +# Household composition: earlier official IMM 21.3.1.B, physical page 1728; +# current IMM 21.3.1.B and citizenship, physical pages 1729 and 1734. # https://bfa.wv.gov/media/39948/download?inline=#page=1728 # https://bfa.wv.gov/media/40005/download?inline=#page=1729 -# The SPM unit approximates the assistance group sharing heat costs. +# The SPM unit stands in for the manual's one-household assistance group. # These component tests make no claim about income or final benefit eligibility. - name: Case 1, one qualified adult is counted. diff --git a/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_income_eligible.yaml index 2e020fdc171..1410204e217 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_income_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_income_eligible.yaml @@ -34,21 +34,21 @@ person1: age: 40 is_citizen_or_legal_immigrant: true - employment_income: 40_000 + employment_income_before_lsr: 40_000 person2: age: 8 is_citizen_or_legal_immigrant: true person3: age: 40 is_citizen_or_legal_immigrant: true - employment_income: 40_000 + employment_income_before_lsr: 40_000 person4: age: 8 is_citizen_or_legal_immigrant: true person5: age: 40 is_citizen_or_legal_immigrant: true - employment_income: 40_000 + employment_income_before_lsr: 40_000 person6: age: 8 is_citizen_or_legal_immigrant: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_income_limit.yaml b/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_income_limit.yaml index 29ef12e5ed5..4063b5a10a6 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_income_limit.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_income_limit.yaml @@ -1,547 +1,259 @@ -# Sources: FY2026 agency table gives sizes1–10; earlier IMM gives size11. +# Sources: FY2026 agency table gives sizes 1-10; earlier IMM gives size 11. # https://bfa.wv.gov/utility-assistancelieap # https://bfa.wv.gov/media/39948/download?inline=#page=1772 -# FY2027 adopted operational IMM gives separately verified sizes1–11. +# FY2027 adopted operational IMM gives separately verified sizes 1-11. # https://bfa.wv.gov/media/40005/download?inline=#page=1775 -# The60%SMI-through7 /150%FPG-from8 split is explicit in the accepted FY2026 plan. +# The 60% SMI through 7 and 150% FPG from 8 split is explicit in the accepted FY2026 plan. # https://liheapch.acf.gov/docs/2026/state-plans/WV_Plan_2026.pdf#page=11 -# Expected limits are published monthly amounts multiplied by12, independently +# Expected limits are published monthly amounts multiplied by 12, independently # checked with Decimal arithmetic; no model formula was used to generate them. -# FY2026 size11 is8831/month, not the agency shorthand8144+688=8832. +# FY2026 size 11 is 8831/month, not the agency shorthand 8144 + 688 = 8832. # Payment-grid overlaps and larger-family defects are outside this component. -- name: Case 1, FY2026 published limit for 1 qualified members. +- name: Case 1, FY2026 published limits for 1 through 11 qualified members. period: 2026 absolute_error_margin: 0.01 - # 60% requested-year SMI; published $2,454/month x12 =$29,448/year. + # Size 1: 60% of requested-year SMI; published $2,454/month x 12 = $29,448/year. + # Size 2: 60% of requested-year SMI; published $3,209/month x 12 = $38,508/year. + # Size 3: 60% of requested-year SMI; published $3,965/month x 12 = $47,580/year. + # Size 4: 60% of requested-year SMI; published $4,720/month x 12 = $56,640/year. + # Size 5: 60% of requested-year SMI; published $5,475/month x 12 = $65,700/year. + # Size 6: 60% of requested-year SMI; published $6,230/month x 12 = $74,760/year. + # Size 7: 60% of requested-year SMI; published $6,372/month x 12 = $76,464/year. + # Size 8: 150% of prior-year FPG; published $6,769/month x 12 = $81,228/year. + # Size 9: 150% of prior-year FPG; published $7,456/month x 12 = $89,472/year. + # Size 10: 150% of prior-year FPG; published $8,144/month x 12 = $97,728/year. + # Size 11: 150% of prior-year FPG; published $8,831/month x 12 = $105,972/year. input: people: person1: {age: 70, is_citizen_or_legal_immigrant: true} + person2: {age: 70, is_citizen_or_legal_immigrant: true} + person3: {age: 68, is_citizen_or_legal_immigrant: true} + person4: {age: 70, is_citizen_or_legal_immigrant: true} + person5: {age: 68, is_citizen_or_legal_immigrant: true} + person6: {age: 45, is_citizen_or_legal_immigrant: true} + person7: {age: 70, is_citizen_or_legal_immigrant: true} + person8: {age: 68, is_citizen_or_legal_immigrant: true} + person9: {age: 45, is_citizen_or_legal_immigrant: true} + person10: {age: 44, is_citizen_or_legal_immigrant: true} + person11: {age: 70, is_citizen_or_legal_immigrant: true} + person12: {age: 68, is_citizen_or_legal_immigrant: true} + person13: {age: 45, is_citizen_or_legal_immigrant: true} + person14: {age: 44, is_citizen_or_legal_immigrant: true} + person15: {age: 22, is_citizen_or_legal_immigrant: true} + person16: {age: 70, is_citizen_or_legal_immigrant: true} + person17: {age: 68, is_citizen_or_legal_immigrant: true} + person18: {age: 45, is_citizen_or_legal_immigrant: true} + person19: {age: 44, is_citizen_or_legal_immigrant: true} + person20: {age: 22, is_citizen_or_legal_immigrant: true} + person21: {age: 17, is_citizen_or_legal_immigrant: true} + person22: {age: 70, is_citizen_or_legal_immigrant: true} + person23: {age: 68, is_citizen_or_legal_immigrant: true} + person24: {age: 45, is_citizen_or_legal_immigrant: true} + person25: {age: 44, is_citizen_or_legal_immigrant: true} + person26: {age: 22, is_citizen_or_legal_immigrant: true} + person27: {age: 17, is_citizen_or_legal_immigrant: true} + person28: {age: 15, is_citizen_or_legal_immigrant: true} + person29: {age: 70, is_citizen_or_legal_immigrant: true} + person30: {age: 68, is_citizen_or_legal_immigrant: true} + person31: {age: 45, is_citizen_or_legal_immigrant: true} + person32: {age: 44, is_citizen_or_legal_immigrant: true} + person33: {age: 22, is_citizen_or_legal_immigrant: true} + person34: {age: 17, is_citizen_or_legal_immigrant: true} + person35: {age: 15, is_citizen_or_legal_immigrant: true} + person36: {age: 12, is_citizen_or_legal_immigrant: true} + person37: {age: 70, is_citizen_or_legal_immigrant: true} + person38: {age: 68, is_citizen_or_legal_immigrant: true} + person39: {age: 45, is_citizen_or_legal_immigrant: true} + person40: {age: 44, is_citizen_or_legal_immigrant: true} + person41: {age: 22, is_citizen_or_legal_immigrant: true} + person42: {age: 17, is_citizen_or_legal_immigrant: true} + person43: {age: 15, is_citizen_or_legal_immigrant: true} + person44: {age: 12, is_citizen_or_legal_immigrant: true} + person45: {age: 9, is_citizen_or_legal_immigrant: true} + person46: {age: 70, is_citizen_or_legal_immigrant: true} + person47: {age: 68, is_citizen_or_legal_immigrant: true} + person48: {age: 45, is_citizen_or_legal_immigrant: true} + person49: {age: 44, is_citizen_or_legal_immigrant: true} + person50: {age: 22, is_citizen_or_legal_immigrant: true} + person51: {age: 17, is_citizen_or_legal_immigrant: true} + person52: {age: 15, is_citizen_or_legal_immigrant: true} + person53: {age: 12, is_citizen_or_legal_immigrant: true} + person54: {age: 9, is_citizen_or_legal_immigrant: true} + person55: {age: 7, is_citizen_or_legal_immigrant: true} + person56: {age: 70, is_citizen_or_legal_immigrant: true} + person57: {age: 68, is_citizen_or_legal_immigrant: true} + person58: {age: 45, is_citizen_or_legal_immigrant: true} + person59: {age: 44, is_citizen_or_legal_immigrant: true} + person60: {age: 22, is_citizen_or_legal_immigrant: true} + person61: {age: 17, is_citizen_or_legal_immigrant: true} + person62: {age: 15, is_citizen_or_legal_immigrant: true} + person63: {age: 12, is_citizen_or_legal_immigrant: true} + person64: {age: 9, is_citizen_or_legal_immigrant: true} + person65: {age: 7, is_citizen_or_legal_immigrant: true} + person66: {age: 3, is_citizen_or_legal_immigrant: true} spm_units: - spm_unit1: - members: [person1] - heating_type: NATURAL_GAS - gas_expense: 1_200 - households: - household1: - members: [person1] - state_code: WV - output: - wv_lieap_income_limit: 29_448 - -- name: Case 2, FY2026 published limit for 2 qualified members. - period: 2026 - absolute_error_margin: 0.01 - # 60% requested-year SMI; published $3,209/month x12 =$38,508/year. - input: - people: - person1: {age: 70, is_citizen_or_legal_immigrant: true} - person2: {age: 68, is_citizen_or_legal_immigrant: true} - spm_units: - spm_unit1: - members: [person1, person2] - heating_type: NATURAL_GAS - gas_expense: 1_200 - households: - household1: - members: [person1, person2] - state_code: WV - output: - wv_lieap_income_limit: 38_508 - -- name: Case 3, FY2026 published limit for 3 qualified members. - period: 2026 - absolute_error_margin: 0.01 - # 60% requested-year SMI; published $3,965/month x12 =$47,580/year. - input: - people: - person1: {age: 70, is_citizen_or_legal_immigrant: true} - person2: {age: 68, is_citizen_or_legal_immigrant: true} - person3: {age: 45, is_citizen_or_legal_immigrant: true} - spm_units: - spm_unit1: - members: [person1, person2, person3] - heating_type: NATURAL_GAS - gas_expense: 1_200 - households: - household1: - members: [person1, person2, person3] - state_code: WV - output: - wv_lieap_income_limit: 47_580 - -- name: Case 4, FY2026 published limit for 4 qualified members. - period: 2026 - absolute_error_margin: 0.01 - # 60% requested-year SMI; published $4,720/month x12 =$56,640/year. - input: - people: - person1: {age: 70, is_citizen_or_legal_immigrant: true} - person2: {age: 68, is_citizen_or_legal_immigrant: true} - person3: {age: 45, is_citizen_or_legal_immigrant: true} - person4: {age: 44, is_citizen_or_legal_immigrant: true} - spm_units: - spm_unit1: - members: [person1, person2, person3, person4] - heating_type: NATURAL_GAS - gas_expense: 1_200 - households: - household1: - members: [person1, person2, person3, person4] - state_code: WV - output: - wv_lieap_income_limit: 56_640 - -- name: Case 5, FY2026 published limit for 5 qualified members. - period: 2026 - absolute_error_margin: 0.01 - # 60% requested-year SMI; published $5,475/month x12 =$65,700/year. - input: - people: - person1: {age: 70, is_citizen_or_legal_immigrant: true} - person2: {age: 68, is_citizen_or_legal_immigrant: true} - person3: {age: 45, is_citizen_or_legal_immigrant: true} - person4: {age: 44, is_citizen_or_legal_immigrant: true} - person5: {age: 22, is_citizen_or_legal_immigrant: true} - spm_units: - spm_unit1: - members: [person1, person2, person3, person4, person5] - heating_type: NATURAL_GAS - gas_expense: 1_200 - households: - household1: - members: [person1, person2, person3, person4, person5] - state_code: WV - output: - wv_lieap_income_limit: 65_700 - -- name: Case 6, FY2026 published limit for 6 qualified members. - period: 2026 - absolute_error_margin: 0.01 - # 60% requested-year SMI; published $6,230/month x12 =$74,760/year. - input: - people: - person1: {age: 70, is_citizen_or_legal_immigrant: true} - person2: {age: 68, is_citizen_or_legal_immigrant: true} - person3: {age: 45, is_citizen_or_legal_immigrant: true} - person4: {age: 44, is_citizen_or_legal_immigrant: true} - person5: {age: 22, is_citizen_or_legal_immigrant: true} - person6: {age: 17, is_citizen_or_legal_immigrant: true} - spm_units: - spm_unit1: - members: [person1, person2, person3, person4, person5, person6] - heating_type: NATURAL_GAS - gas_expense: 1_200 - households: - household1: - members: [person1, person2, person3, person4, person5, person6] - state_code: WV - output: - wv_lieap_income_limit: 74_760 - -- name: Case 7, FY2026 published limit for 7 qualified members. - period: 2026 - absolute_error_margin: 0.01 - # 60% requested-year SMI; published $6,372/month x12 =$76,464/year. - input: - people: - person1: {age: 70, is_citizen_or_legal_immigrant: true} - person2: {age: 68, is_citizen_or_legal_immigrant: true} - person3: {age: 45, is_citizen_or_legal_immigrant: true} - person4: {age: 44, is_citizen_or_legal_immigrant: true} - person5: {age: 22, is_citizen_or_legal_immigrant: true} - person6: {age: 17, is_citizen_or_legal_immigrant: true} - person7: {age: 15, is_citizen_or_legal_immigrant: true} - spm_units: - spm_unit1: - members: [person1, person2, person3, person4, person5, person6, person7] - heating_type: NATURAL_GAS - gas_expense: 1_200 - households: - household1: - members: [person1, person2, person3, person4, person5, person6, person7] - state_code: WV - output: - wv_lieap_income_limit: 76_464 - -- name: Case 8, FY2026 published limit for 8 qualified members. - period: 2026 - absolute_error_margin: 0.01 - # 150% prior-year FPG; published $6,769/month x12 =$81,228/year. - input: - people: - person1: {age: 70, is_citizen_or_legal_immigrant: true} - person2: {age: 68, is_citizen_or_legal_immigrant: true} - person3: {age: 45, is_citizen_or_legal_immigrant: true} - person4: {age: 44, is_citizen_or_legal_immigrant: true} - person5: {age: 22, is_citizen_or_legal_immigrant: true} - person6: {age: 17, is_citizen_or_legal_immigrant: true} - person7: {age: 15, is_citizen_or_legal_immigrant: true} - person8: {age: 12, is_citizen_or_legal_immigrant: true} - spm_units: - spm_unit1: - members: [person1, person2, person3, person4, person5, person6, person7, person8] - heating_type: NATURAL_GAS - gas_expense: 1_200 - households: - household1: - members: [person1, person2, person3, person4, person5, person6, person7, person8] - state_code: WV - output: - wv_lieap_income_limit: 81_228 - -- name: Case 9, FY2026 published limit for 9 qualified members. - period: 2026 - absolute_error_margin: 0.01 - # 150% prior-year FPG; published $7,456/month x12 =$89,472/year. - input: - people: - person1: {age: 70, is_citizen_or_legal_immigrant: true} - person2: {age: 68, is_citizen_or_legal_immigrant: true} - person3: {age: 45, is_citizen_or_legal_immigrant: true} - person4: {age: 44, is_citizen_or_legal_immigrant: true} - person5: {age: 22, is_citizen_or_legal_immigrant: true} - person6: {age: 17, is_citizen_or_legal_immigrant: true} - person7: {age: 15, is_citizen_or_legal_immigrant: true} - person8: {age: 12, is_citizen_or_legal_immigrant: true} - person9: {age: 9, is_citizen_or_legal_immigrant: true} - spm_units: - spm_unit1: - members: [person1, person2, person3, person4, person5, person6, person7, person8, person9] - heating_type: NATURAL_GAS - gas_expense: 1_200 - households: - household1: - members: [person1, person2, person3, person4, person5, person6, person7, person8, person9] - state_code: WV - output: - wv_lieap_income_limit: 89_472 - -- name: Case 10, FY2026 published limit for 10 qualified members. - period: 2026 - absolute_error_margin: 0.01 - # 150% prior-year FPG; published $8,144/month x12 =$97,728/year. - input: - people: - person1: {age: 70, is_citizen_or_legal_immigrant: true} - person2: {age: 68, is_citizen_or_legal_immigrant: true} - person3: {age: 45, is_citizen_or_legal_immigrant: true} - person4: {age: 44, is_citizen_or_legal_immigrant: true} - person5: {age: 22, is_citizen_or_legal_immigrant: true} - person6: {age: 17, is_citizen_or_legal_immigrant: true} - person7: {age: 15, is_citizen_or_legal_immigrant: true} - person8: {age: 12, is_citizen_or_legal_immigrant: true} - person9: {age: 9, is_citizen_or_legal_immigrant: true} - person10: {age: 7, is_citizen_or_legal_immigrant: true} - spm_units: - spm_unit1: - members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10] - heating_type: NATURAL_GAS - gas_expense: 1_200 - households: - household1: - members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10] - state_code: WV - output: - wv_lieap_income_limit: 97_728 - -- name: Case 11, FY2026 published limit for 11 qualified members. - period: 2026 - absolute_error_margin: 0.01 - # 150% prior-year FPG; published $8,831/month x12 =$105,972/year. - input: - people: - person1: {age: 70, is_citizen_or_legal_immigrant: true} - person2: {age: 68, is_citizen_or_legal_immigrant: true} - person3: {age: 45, is_citizen_or_legal_immigrant: true} - person4: {age: 44, is_citizen_or_legal_immigrant: true} - person5: {age: 22, is_citizen_or_legal_immigrant: true} - person6: {age: 17, is_citizen_or_legal_immigrant: true} - person7: {age: 15, is_citizen_or_legal_immigrant: true} - person8: {age: 12, is_citizen_or_legal_immigrant: true} - person9: {age: 9, is_citizen_or_legal_immigrant: true} - person10: {age: 7, is_citizen_or_legal_immigrant: true} - person11: {age: 3, is_citizen_or_legal_immigrant: true} - spm_units: - spm_unit1: - members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10, person11] - heating_type: NATURAL_GAS - gas_expense: 1_200 - households: - household1: - members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10, person11] - state_code: WV - output: - wv_lieap_income_limit: 105_972 - -- name: Case 12, FY2027 published limit for 1 qualified members. - period: 2027 - absolute_error_margin: 0.01 - # 60% requested-year SMI; published $2,550/month x12 =$30,600/year. - input: - people: - person1: {age: 70, is_citizen_or_legal_immigrant: true} - spm_units: - spm_unit1: - members: [person1] - heating_type: NATURAL_GAS - gas_expense: 1_200 - households: - household1: - members: [person1] - state_code: WV - output: - wv_lieap_income_limit: 30_600 - -- name: Case 13, FY2027 published limit for 2 qualified members. - period: 2027 - absolute_error_margin: 0.01 - # 60% requested-year SMI; published $3,335/month x12 =$40,020/year. - input: - people: - person1: {age: 70, is_citizen_or_legal_immigrant: true} - person2: {age: 68, is_citizen_or_legal_immigrant: true} - spm_units: - spm_unit1: - members: [person1, person2] - heating_type: NATURAL_GAS - gas_expense: 1_200 - households: - household1: - members: [person1, person2] - state_code: WV - output: - wv_lieap_income_limit: 40_020 - -- name: Case 14, FY2027 published limit for 3 qualified members. - period: 2027 - absolute_error_margin: 0.01 - # 60% requested-year SMI; published $4,120/month x12 =$49,440/year. - input: - people: - person1: {age: 70, is_citizen_or_legal_immigrant: true} - person2: {age: 68, is_citizen_or_legal_immigrant: true} - person3: {age: 45, is_citizen_or_legal_immigrant: true} - spm_units: - spm_unit1: - members: [person1, person2, person3] - heating_type: NATURAL_GAS - gas_expense: 1_200 - households: - household1: - members: [person1, person2, person3] - state_code: WV - output: - wv_lieap_income_limit: 49_440 - -- name: Case 15, FY2027 published limit for 4 qualified members. - period: 2027 - absolute_error_margin: 0.01 - # 60% requested-year SMI; published $4,904/month x12 =$58,848/year. - input: - people: - person1: {age: 70, is_citizen_or_legal_immigrant: true} - person2: {age: 68, is_citizen_or_legal_immigrant: true} - person3: {age: 45, is_citizen_or_legal_immigrant: true} - person4: {age: 44, is_citizen_or_legal_immigrant: true} - spm_units: - spm_unit1: - members: [person1, person2, person3, person4] - heating_type: NATURAL_GAS - gas_expense: 1_200 - households: - household1: - members: [person1, person2, person3, person4] - state_code: WV - output: - wv_lieap_income_limit: 58_848 - -- name: Case 16, FY2027 published limit for 5 qualified members. - period: 2027 - absolute_error_margin: 0.01 - # 60% requested-year SMI; published $5,689/month x12 =$68,268/year. - input: - people: - person1: {age: 70, is_citizen_or_legal_immigrant: true} - person2: {age: 68, is_citizen_or_legal_immigrant: true} - person3: {age: 45, is_citizen_or_legal_immigrant: true} - person4: {age: 44, is_citizen_or_legal_immigrant: true} - person5: {age: 22, is_citizen_or_legal_immigrant: true} - spm_units: - spm_unit1: - members: [person1, person2, person3, person4, person5] - heating_type: NATURAL_GAS - gas_expense: 1_200 - households: - household1: - members: [person1, person2, person3, person4, person5] - state_code: WV - output: - wv_lieap_income_limit: 68_268 - -- name: Case 17, FY2027 published limit for 6 qualified members. - period: 2027 - absolute_error_margin: 0.01 - # 60% requested-year SMI; published $6,474/month x12 =$77,688/year. - input: - people: - person1: {age: 70, is_citizen_or_legal_immigrant: true} - person2: {age: 68, is_citizen_or_legal_immigrant: true} - person3: {age: 45, is_citizen_or_legal_immigrant: true} - person4: {age: 44, is_citizen_or_legal_immigrant: true} - person5: {age: 22, is_citizen_or_legal_immigrant: true} - person6: {age: 17, is_citizen_or_legal_immigrant: true} - spm_units: - spm_unit1: - members: [person1, person2, person3, person4, person5, person6] - heating_type: NATURAL_GAS - gas_expense: 1_200 - households: - household1: - members: [person1, person2, person3, person4, person5, person6] - state_code: WV - output: - wv_lieap_income_limit: 77_688 - -- name: Case 18, FY2027 published limit for 7 qualified members. - period: 2027 - absolute_error_margin: 0.01 - # 60% requested-year SMI; published $6,621/month x12 =$79,452/year. - input: - people: - person1: {age: 70, is_citizen_or_legal_immigrant: true} - person2: {age: 68, is_citizen_or_legal_immigrant: true} - person3: {age: 45, is_citizen_or_legal_immigrant: true} - person4: {age: 44, is_citizen_or_legal_immigrant: true} - person5: {age: 22, is_citizen_or_legal_immigrant: true} - person6: {age: 17, is_citizen_or_legal_immigrant: true} - person7: {age: 15, is_citizen_or_legal_immigrant: true} - spm_units: - spm_unit1: - members: [person1, person2, person3, person4, person5, person6, person7] - heating_type: NATURAL_GAS - gas_expense: 1_200 - households: - household1: - members: [person1, person2, person3, person4, person5, person6, person7] - state_code: WV - output: - wv_lieap_income_limit: 79_452 - -- name: Case 19, FY2027 published limit for 8 qualified members. - period: 2027 - absolute_error_margin: 0.01 - # 150% prior-year FPG; published $6,965/month x12 =$83,580/year. - input: - people: - person1: {age: 70, is_citizen_or_legal_immigrant: true} - person2: {age: 68, is_citizen_or_legal_immigrant: true} - person3: {age: 45, is_citizen_or_legal_immigrant: true} - person4: {age: 44, is_citizen_or_legal_immigrant: true} - person5: {age: 22, is_citizen_or_legal_immigrant: true} - person6: {age: 17, is_citizen_or_legal_immigrant: true} - person7: {age: 15, is_citizen_or_legal_immigrant: true} - person8: {age: 12, is_citizen_or_legal_immigrant: true} - spm_units: - spm_unit1: - members: [person1, person2, person3, person4, person5, person6, person7, person8] - heating_type: NATURAL_GAS - gas_expense: 1_200 - households: - household1: - members: [person1, person2, person3, person4, person5, person6, person7, person8] - state_code: WV - output: - wv_lieap_income_limit: 83_580 - -- name: Case 20, FY2027 published limit for 9 qualified members. - period: 2027 - absolute_error_margin: 0.01 - # 150% prior-year FPG; published $7,675/month x12 =$92,100/year. - input: - people: - person1: {age: 70, is_citizen_or_legal_immigrant: true} - person2: {age: 68, is_citizen_or_legal_immigrant: true} - person3: {age: 45, is_citizen_or_legal_immigrant: true} - person4: {age: 44, is_citizen_or_legal_immigrant: true} - person5: {age: 22, is_citizen_or_legal_immigrant: true} - person6: {age: 17, is_citizen_or_legal_immigrant: true} - person7: {age: 15, is_citizen_or_legal_immigrant: true} - person8: {age: 12, is_citizen_or_legal_immigrant: true} - person9: {age: 9, is_citizen_or_legal_immigrant: true} - spm_units: - spm_unit1: - members: [person1, person2, person3, person4, person5, person6, person7, person8, person9] - heating_type: NATURAL_GAS - gas_expense: 1_200 - households: - household1: - members: [person1, person2, person3, person4, person5, person6, person7, person8, person9] - state_code: WV - output: - wv_lieap_income_limit: 92_100 - -- name: Case 21, FY2027 published limit for 10 qualified members. - period: 2027 - absolute_error_margin: 0.01 - # 150% prior-year FPG; published $8,385/month x12 =$100,620/year. - input: - people: - person1: {age: 70, is_citizen_or_legal_immigrant: true} - person2: {age: 68, is_citizen_or_legal_immigrant: true} - person3: {age: 45, is_citizen_or_legal_immigrant: true} - person4: {age: 44, is_citizen_or_legal_immigrant: true} - person5: {age: 22, is_citizen_or_legal_immigrant: true} - person6: {age: 17, is_citizen_or_legal_immigrant: true} - person7: {age: 15, is_citizen_or_legal_immigrant: true} - person8: {age: 12, is_citizen_or_legal_immigrant: true} - person9: {age: 9, is_citizen_or_legal_immigrant: true} - person10: {age: 7, is_citizen_or_legal_immigrant: true} - spm_units: - spm_unit1: - members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10] - heating_type: NATURAL_GAS - gas_expense: 1_200 + spm_unit1: {members: [person1]} + spm_unit2: {members: [person2, person3]} + spm_unit3: {members: [person4, person5, person6]} + spm_unit4: {members: [person7, person8, person9, person10]} + spm_unit5: {members: [person11, person12, person13, person14, person15]} + spm_unit6: {members: [person16, person17, person18, person19, person20, person21]} + spm_unit7: {members: [person22, person23, person24, person25, person26, person27, person28]} + spm_unit8: {members: [person29, person30, person31, person32, person33, person34, person35, person36]} + spm_unit9: {members: [person37, person38, person39, person40, person41, person42, person43, person44, person45]} + spm_unit10: {members: [person46, person47, person48, person49, person50, person51, person52, person53, person54, person55]} + spm_unit11: {members: [person56, person57, person58, person59, person60, person61, person62, person63, person64, person65, person66]} households: - household1: - members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10] - state_code: WV + household1: {members: [person1], state_code: WV} + household2: {members: [person2, person3], state_code: WV} + household3: {members: [person4, person5, person6], state_code: WV} + household4: {members: [person7, person8, person9, person10], state_code: WV} + household5: {members: [person11, person12, person13, person14, person15], state_code: WV} + household6: {members: [person16, person17, person18, person19, person20, person21], state_code: WV} + household7: {members: [person22, person23, person24, person25, person26, person27, person28], state_code: WV} + household8: {members: [person29, person30, person31, person32, person33, person34, person35, person36], state_code: WV} + household9: {members: [person37, person38, person39, person40, person41, person42, person43, person44, person45], state_code: WV} + household10: {members: [person46, person47, person48, person49, person50, person51, person52, person53, person54, person55], state_code: WV} + household11: {members: [person56, person57, person58, person59, person60, person61, person62, person63, person64, person65, person66], state_code: WV} output: - wv_lieap_income_limit: 100_620 + wv_lieap_income_limit: + - 29_448 + - 38_508 + - 47_580 + - 56_640 + - 65_700 + - 74_760 + - 76_464 + - 81_228 + - 89_472 + - 97_728 + - 105_972 -- name: Case 22, FY2027 published limit for 11 qualified members. +- name: Case 2, FY2027 published limits for 1 through 11 qualified members. period: 2027 absolute_error_margin: 0.01 - # 150% prior-year FPG; published $9,095/month x12 =$109,140/year. + # Size 1: 60% of requested-year SMI; published $2,550/month x 12 = $30,600/year. + # Size 2: 60% of requested-year SMI; published $3,335/month x 12 = $40,020/year. + # Size 3: 60% of requested-year SMI; published $4,120/month x 12 = $49,440/year. + # Size 4: 60% of requested-year SMI; published $4,904/month x 12 = $58,848/year. + # Size 5: 60% of requested-year SMI; published $5,689/month x 12 = $68,268/year. + # Size 6: 60% of requested-year SMI; published $6,474/month x 12 = $77,688/year. + # Size 7: 60% of requested-year SMI; published $6,621/month x 12 = $79,452/year. + # Size 8: 150% of prior-year FPG; published $6,965/month x 12 = $83,580/year. + # Size 9: 150% of prior-year FPG; published $7,675/month x 12 = $92,100/year. + # Size 10: 150% of prior-year FPG; published $8,385/month x 12 = $100,620/year. + # Size 11: 150% of prior-year FPG; published $9,095/month x 12 = $109,140/year. input: people: person1: {age: 70, is_citizen_or_legal_immigrant: true} - person2: {age: 68, is_citizen_or_legal_immigrant: true} - person3: {age: 45, is_citizen_or_legal_immigrant: true} - person4: {age: 44, is_citizen_or_legal_immigrant: true} - person5: {age: 22, is_citizen_or_legal_immigrant: true} - person6: {age: 17, is_citizen_or_legal_immigrant: true} - person7: {age: 15, is_citizen_or_legal_immigrant: true} - person8: {age: 12, is_citizen_or_legal_immigrant: true} - person9: {age: 9, is_citizen_or_legal_immigrant: true} - person10: {age: 7, is_citizen_or_legal_immigrant: true} - person11: {age: 3, is_citizen_or_legal_immigrant: true} + person2: {age: 70, is_citizen_or_legal_immigrant: true} + person3: {age: 68, is_citizen_or_legal_immigrant: true} + person4: {age: 70, is_citizen_or_legal_immigrant: true} + person5: {age: 68, is_citizen_or_legal_immigrant: true} + person6: {age: 45, is_citizen_or_legal_immigrant: true} + person7: {age: 70, is_citizen_or_legal_immigrant: true} + person8: {age: 68, is_citizen_or_legal_immigrant: true} + person9: {age: 45, is_citizen_or_legal_immigrant: true} + person10: {age: 44, is_citizen_or_legal_immigrant: true} + person11: {age: 70, is_citizen_or_legal_immigrant: true} + person12: {age: 68, is_citizen_or_legal_immigrant: true} + person13: {age: 45, is_citizen_or_legal_immigrant: true} + person14: {age: 44, is_citizen_or_legal_immigrant: true} + person15: {age: 22, is_citizen_or_legal_immigrant: true} + person16: {age: 70, is_citizen_or_legal_immigrant: true} + person17: {age: 68, is_citizen_or_legal_immigrant: true} + person18: {age: 45, is_citizen_or_legal_immigrant: true} + person19: {age: 44, is_citizen_or_legal_immigrant: true} + person20: {age: 22, is_citizen_or_legal_immigrant: true} + person21: {age: 17, is_citizen_or_legal_immigrant: true} + person22: {age: 70, is_citizen_or_legal_immigrant: true} + person23: {age: 68, is_citizen_or_legal_immigrant: true} + person24: {age: 45, is_citizen_or_legal_immigrant: true} + person25: {age: 44, is_citizen_or_legal_immigrant: true} + person26: {age: 22, is_citizen_or_legal_immigrant: true} + person27: {age: 17, is_citizen_or_legal_immigrant: true} + person28: {age: 15, is_citizen_or_legal_immigrant: true} + person29: {age: 70, is_citizen_or_legal_immigrant: true} + person30: {age: 68, is_citizen_or_legal_immigrant: true} + person31: {age: 45, is_citizen_or_legal_immigrant: true} + person32: {age: 44, is_citizen_or_legal_immigrant: true} + person33: {age: 22, is_citizen_or_legal_immigrant: true} + person34: {age: 17, is_citizen_or_legal_immigrant: true} + person35: {age: 15, is_citizen_or_legal_immigrant: true} + person36: {age: 12, is_citizen_or_legal_immigrant: true} + person37: {age: 70, is_citizen_or_legal_immigrant: true} + person38: {age: 68, is_citizen_or_legal_immigrant: true} + person39: {age: 45, is_citizen_or_legal_immigrant: true} + person40: {age: 44, is_citizen_or_legal_immigrant: true} + person41: {age: 22, is_citizen_or_legal_immigrant: true} + person42: {age: 17, is_citizen_or_legal_immigrant: true} + person43: {age: 15, is_citizen_or_legal_immigrant: true} + person44: {age: 12, is_citizen_or_legal_immigrant: true} + person45: {age: 9, is_citizen_or_legal_immigrant: true} + person46: {age: 70, is_citizen_or_legal_immigrant: true} + person47: {age: 68, is_citizen_or_legal_immigrant: true} + person48: {age: 45, is_citizen_or_legal_immigrant: true} + person49: {age: 44, is_citizen_or_legal_immigrant: true} + person50: {age: 22, is_citizen_or_legal_immigrant: true} + person51: {age: 17, is_citizen_or_legal_immigrant: true} + person52: {age: 15, is_citizen_or_legal_immigrant: true} + person53: {age: 12, is_citizen_or_legal_immigrant: true} + person54: {age: 9, is_citizen_or_legal_immigrant: true} + person55: {age: 7, is_citizen_or_legal_immigrant: true} + person56: {age: 70, is_citizen_or_legal_immigrant: true} + person57: {age: 68, is_citizen_or_legal_immigrant: true} + person58: {age: 45, is_citizen_or_legal_immigrant: true} + person59: {age: 44, is_citizen_or_legal_immigrant: true} + person60: {age: 22, is_citizen_or_legal_immigrant: true} + person61: {age: 17, is_citizen_or_legal_immigrant: true} + person62: {age: 15, is_citizen_or_legal_immigrant: true} + person63: {age: 12, is_citizen_or_legal_immigrant: true} + person64: {age: 9, is_citizen_or_legal_immigrant: true} + person65: {age: 7, is_citizen_or_legal_immigrant: true} + person66: {age: 3, is_citizen_or_legal_immigrant: true} spm_units: - spm_unit1: - members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10, person11] - heating_type: NATURAL_GAS - gas_expense: 1_200 + spm_unit1: {members: [person1]} + spm_unit2: {members: [person2, person3]} + spm_unit3: {members: [person4, person5, person6]} + spm_unit4: {members: [person7, person8, person9, person10]} + spm_unit5: {members: [person11, person12, person13, person14, person15]} + spm_unit6: {members: [person16, person17, person18, person19, person20, person21]} + spm_unit7: {members: [person22, person23, person24, person25, person26, person27, person28]} + spm_unit8: {members: [person29, person30, person31, person32, person33, person34, person35, person36]} + spm_unit9: {members: [person37, person38, person39, person40, person41, person42, person43, person44, person45]} + spm_unit10: {members: [person46, person47, person48, person49, person50, person51, person52, person53, person54, person55]} + spm_unit11: {members: [person56, person57, person58, person59, person60, person61, person62, person63, person64, person65, person66]} households: - household1: - members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10, person11] - state_code: WV + household1: {members: [person1], state_code: WV} + household2: {members: [person2, person3], state_code: WV} + household3: {members: [person4, person5, person6], state_code: WV} + household4: {members: [person7, person8, person9, person10], state_code: WV} + household5: {members: [person11, person12, person13, person14, person15], state_code: WV} + household6: {members: [person16, person17, person18, person19, person20, person21], state_code: WV} + household7: {members: [person22, person23, person24, person25, person26, person27, person28], state_code: WV} + household8: {members: [person29, person30, person31, person32, person33, person34, person35, person36], state_code: WV} + household9: {members: [person37, person38, person39, person40, person41, person42, person43, person44, person45], state_code: WV} + household10: {members: [person46, person47, person48, person49, person50, person51, person52, person53, person54, person55], state_code: WV} + household11: {members: [person56, person57, person58, person59, person60, person61, person62, person63, person64, person65, person66], state_code: WV} output: - wv_lieap_income_limit: 109_140 + wv_lieap_income_limit: + - 30_600 + - 40_020 + - 49_440 + - 58_848 + - 68_268 + - 77_688 + - 79_452 + - 83_580 + - 92_100 + - 100_620 + - 109_140 -- name: Case 23, eight residents with seven qualified members stay on the SMI branch. +- name: Case 3, eight residents with seven qualified members stay on the SMI branch. period: 2026 absolute_error_margin: 0.01 - # Qualified size7: FY2026 monthly6372 x12 =76464. + # Qualified size 7: FY2026 monthly 6372 x 12 = 76464. input: people: person1: {age: 70, is_citizen_or_legal_immigrant: true} @@ -555,8 +267,6 @@ spm_units: spm_unit1: members: [person1, person2, person3, person4, person5, person6, person7, person8] - heating_type: NATURAL_GAS - gas_expense: 1_200 households: household1: members: [person1, person2, person3, person4, person5, person6, person7, person8] @@ -564,10 +274,10 @@ output: wv_lieap_income_limit: 76_464 -- name: Case 24, nine residents with eight qualified members use the FPG branch. +- name: Case 4, nine residents with eight qualified members use the FPG branch. period: 2026 absolute_error_margin: 0.01 - # Qualified size8: FY2026 monthly6769 x12 =81228. + # Qualified size 8: FY2026 monthly 6769 x 12 = 81228. input: people: person1: {age: 70, is_citizen_or_legal_immigrant: true} @@ -582,8 +292,6 @@ spm_units: spm_unit1: members: [person1, person2, person3, person4, person5, person6, person7, person8, person9] - heating_type: NATURAL_GAS - gas_expense: 1_200 households: household1: members: [person1, person2, person3, person4, person5, person6, person7, person8, person9] @@ -591,10 +299,10 @@ output: wv_lieap_income_limit: 81_228 -- name: Case 25, mixed WV and neighboring-state households retain independent limits. +- name: Case 5, mixed WV and neighboring-state households retain independent limits. period: 2026 absolute_error_margin: 0.01 - # WV sizes1/8 use2454/6769 monthly; WV variable is zero in Ohio. + # WV sizes 1 and 8 use 2454 and 6769 monthly; the WV variable is zero in Ohio. input: people: person1: {age: 40, is_citizen_or_legal_immigrant: true} @@ -617,16 +325,10 @@ spm_units: spm_unit1: members: [person1] - heating_type: NATURAL_GAS - gas_expense: 1_200 spm_unit2: members: [person2, person3, person4, person5, person6, person7, person8, person9] - heating_type: NATURAL_GAS - gas_expense: 1_200 spm_unit3: members: [person10, person11, person12, person13, person14, person15, person16, person17] - heating_type: NATURAL_GAS - gas_expense: 1_200 households: household1: members: [person1] diff --git a/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap.py b/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap.py index 79cccd1d667..bebfa294dfe 100644 --- a/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap.py +++ b/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap.py @@ -19,8 +19,8 @@ def formula(spm_unit, period, parameters): p = parameters(period).gov.states.wv.dhhr.lieap.payment size = spm_unit("wv_lieap_household_size", period) income = spm_unit("wv_lieap_countable_income", period) / MONTHS_IN_YEAR - # Approved convention: use the printed upper bounds continuously, - # including cents, rather than the overlapping integer lower bounds. + # Use the printed upper bounds continuously, including cents: the printed + # integer lower bounds overlap and leave cent gaps. band = p.income_band.calc(income, right=True) # Exact compression of every occupied published cell, not extrapolation. # Income eligibility confines sizes 1-20 to occupied table cells. diff --git a/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_countable_income.py b/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_countable_income.py index 9ab658a7022..1e3b9756975 100644 --- a/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_countable_income.py +++ b/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_countable_income.py @@ -18,15 +18,12 @@ class wv_lieap_countable_income(Variable): def formula(spm_unit, period, parameters): p = parameters(period).gov.states.wv.dhhr.lieap.income person = spm_unit.members - # Existing net business inputs receive no second expense deduction; - # business and estate losses do not offset other income. - net_income = sum( - max_(add(person, period, [source]), 0) for source in p.nonnegative_sources - ) # Floor each member/source before aggregation so losses cannot erase # another receipt. The operative manual counts minor and nonqualified members' income, # TANF and general assistance. RSDI and SSI are expressly excluded. # Annual flows approximate recurring application-month receipts. Generic - # VA cannot identify excluded Aid and Attendance; see README limitations. - receipts = sum(max_(add(person, period, [source]), 0) for source in p.sources) - return spm_unit.sum(net_income + receipts) + max_(spm_unit("tanf", period), 0) + # VA cannot identify excluded Aid and Attendance. + income = 0 + for source in p.sources: + income = income + max_(add(person, period, [source]), 0) + return spm_unit.sum(income) + spm_unit("tanf", period) diff --git a/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_household_size.py b/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_household_size.py index 7d7d05f3197..755307edd58 100644 --- a/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_household_size.py +++ b/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_household_size.py @@ -13,7 +13,9 @@ class wv_lieap_household_size(Variable): # PDF pages 1729,1734 "https://bfa.wv.gov/media/40005/download?inline=#page=1729", ) - # SPMUnit approximates the co-resident energy-sharing assistance group. - # Prior-season benefit recipients are excluded by policy, but that receipt - # history is unavailable. Nonqualified members' income remains countable. + # The manual treats everyone living in the home as one assistance group, whether + # or not they share heating costs. The SPM unit stands in for that group, so a + # household with more than one SPM unit is split. Anyone already paid as part of + # another group leaves the size and income, but that receipt history is + # unavailable. Nonqualified members' income remains countable. adds = ["is_citizen_or_legal_immigrant"] diff --git a/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_income_eligible.py b/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_income_eligible.py index ae9dce8fef8..7cc70af7b46 100644 --- a/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_income_eligible.py +++ b/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_income_eligible.py @@ -7,8 +7,12 @@ class wv_lieap_income_eligible(Variable): label = "West Virginia LIEAP income eligible" definition_period = YEAR defined_for = StateCode.WV - # PDF pages 1726,1745,1752 - reference = "https://bfa.wv.gov/media/40005/download?inline=#page=1726" + reference = ( + # PDF pages 1725,1749 + "https://bfa.wv.gov/media/39948/download?inline=#page=1725", + # PDF pages 1726,1752 + "https://bfa.wv.gov/media/40005/download?inline=#page=1726", + ) def formula(spm_unit, period, parameters): size = spm_unit("wv_lieap_household_size", period) diff --git a/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_income_limit.py b/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_income_limit.py index d6076c1244e..6c27983534b 100644 --- a/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_income_limit.py +++ b/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_income_limit.py @@ -1,5 +1,5 @@ from policyengine_us.model_api import * -from policyengine_us.variables.gov.hhs.hhs_smi import smi +from policyengine_us.variables.gov.hhs.hhs_smi import liheap_smi_limit from policyengine_us.variables.gov.hhs.tax_unit_fpg import fpg @@ -13,9 +13,10 @@ class wv_lieap_income_limit(Variable): reference = ( # PDF pages 9,11 "https://liheapch.acf.gov/docs/2026/state-plans/WV_Plan_2026.pdf#page=9", - "https://bfa.wv.gov/utility-assistancelieap", - # PDF pages 1734,1775-1776 - "https://bfa.wv.gov/media/40005/download?inline=#page=1734", + # FY2026 chart, PDF pages 406,1777 + "https://bfa.wv.gov/media/39948/download?inline=#page=406", + # FY2027 chart, PDF pages 405,1779 + "https://bfa.wv.gov/media/40005/download?inline=#page=405", ) def formula(spm_unit, period, parameters): @@ -23,9 +24,9 @@ def formula(spm_unit, period, parameters): state = spm_unit.household("state_code_str", period) group = spm_unit.household("state_group_str", period) p = parameters(period).gov.states.wv.dhhr.lieap.eligibility - annual_smi = p.smi_rate * smi(size, state, period, parameters) + annual_smi = liheap_smi_limit(size, state, p.smi_rate, period, parameters) annual_fpg = p.fpg_rate * fpg( - max_(size, 1), group, period, parameters, year_lag=p.fpg_year_lag + size, group, period, parameters, year_lag=p.fpg_year_lag ) annual = where(size <= p.smi_max_household_size, annual_smi, annual_fpg) # Nearest-dollar monthly rounding matches all ten published agency rows. From 80c117294a83bfa4290c67dca51079d57a3e232a Mon Sep 17 00:00:00 2001 From: Ziming Date: Tue, 3 Nov 2026 16:44:57 -0500 Subject: [PATCH 5/7] Apply review fixes to West Virginia LIEAP - Stop a monthly limit that rounds up at the federal ceiling in 42 U.S.C. 8624(b)(2)(B). - Count military_basic_pay and pin the zero-size limit. - Cite the FY2027 plan on the limit rates. - Record four source choices in the source-conflict candidates. Co-Authored-By: Claude Opus 5.5 --- .../wv/dhhr/lieap/eligibility/fpg_rate.yaml | 2 + .../eligibility/smi_max_household_size.yaml | 2 + .../wv/dhhr/lieap/eligibility/smi_rate.yaml | 2 + .../states/wv/dhhr/lieap/income/sources.yaml | 3 + .../gov/states/wv/dhhr/lieap/wv_lieap.yaml | 89 +++++++++- .../dhhr/lieap/wv_lieap_countable_income.yaml | 7 +- .../dhhr/lieap/wv_lieap_income_eligible.yaml | 1 + .../wv/dhhr/lieap/wv_lieap_income_limit.yaml | 69 ++++---- .../gov/states/wv/dhhr/lieap/wv_lieap.py | 3 +- .../wv/dhhr/lieap/wv_lieap_income_limit.py | 17 +- source_conflicts/candidates.yaml | 156 ++++++++++++++++++ 11 files changed, 310 insertions(+), 41 deletions(-) diff --git a/policyengine_us/parameters/gov/states/wv/dhhr/lieap/eligibility/fpg_rate.yaml b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/eligibility/fpg_rate.yaml index f9b3e9ab236..e47285fff41 100644 --- a/policyengine_us/parameters/gov/states/wv/dhhr/lieap/eligibility/fpg_rate.yaml +++ b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/eligibility/fpg_rate.yaml @@ -8,3 +8,5 @@ metadata: reference: - title: "West Virginia accepted FY2026 LIHEAP State Plan, heating eligibility #page 9,11" href: https://liheapch.acf.gov/docs/2026/state-plans/WV_Plan_2026.pdf#page=9 + - title: "West Virginia submitted FY2027 LIHEAP State Plan, heating eligibility #page 9,12" + href: https://bfa.wv.gov/media/39990/download?inline=#page=9 diff --git a/policyengine_us/parameters/gov/states/wv/dhhr/lieap/eligibility/smi_max_household_size.yaml b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/eligibility/smi_max_household_size.yaml index a388b8a8ed1..bc75adc52fa 100644 --- a/policyengine_us/parameters/gov/states/wv/dhhr/lieap/eligibility/smi_max_household_size.yaml +++ b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/eligibility/smi_max_household_size.yaml @@ -8,3 +8,5 @@ metadata: reference: - title: "West Virginia accepted FY2026 LIHEAP State Plan, heating eligibility #page 9,11" href: https://liheapch.acf.gov/docs/2026/state-plans/WV_Plan_2026.pdf#page=9 + - title: "West Virginia submitted FY2027 LIHEAP State Plan, heating eligibility #page 9,12" + href: https://bfa.wv.gov/media/39990/download?inline=#page=9 diff --git a/policyengine_us/parameters/gov/states/wv/dhhr/lieap/eligibility/smi_rate.yaml b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/eligibility/smi_rate.yaml index 5197ec747d0..08ea2faf425 100644 --- a/policyengine_us/parameters/gov/states/wv/dhhr/lieap/eligibility/smi_rate.yaml +++ b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/eligibility/smi_rate.yaml @@ -8,3 +8,5 @@ metadata: reference: - title: "West Virginia accepted FY2026 LIHEAP State Plan, heating eligibility #page 9,11" href: https://liheapch.acf.gov/docs/2026/state-plans/WV_Plan_2026.pdf#page=9 + - title: "West Virginia submitted FY2027 LIHEAP State Plan, heating eligibility #page 9,12" + href: https://bfa.wv.gov/media/39990/download?inline=#page=9 diff --git a/policyengine_us/parameters/gov/states/wv/dhhr/lieap/income/sources.yaml b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/income/sources.yaml index 64af59661e2..f990c4e3787 100644 --- a/policyengine_us/parameters/gov/states/wv/dhhr/lieap/income/sources.yaml +++ b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/income/sources.yaml @@ -2,6 +2,9 @@ description: West Virginia counts these represented recurring income sources und values: 2025-10-01: - employment_income + # Active-duty basic pay, entered apart from employment_income; enter it in one + # of the two. + - military_basic_pay # The source deducts 20% from gross receipts. Existing inputs are already net; # using them without another deduction is an explicit modeling approximation. - self_employment_income diff --git a/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap.yaml b/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap.yaml index a5fb8e57f04..61208e97045 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap.yaml @@ -164,13 +164,14 @@ - name: Case 7, twenty people reach base 65 while twenty-one remains unmodeled. period: 2026 absolute_error_margin: 0.001 - # Twenty people at the 15019 monthly ceiling use band 38 and base 65. + # Twenty people at the 180_225 federal ceiling (15_018.75 monthly, below the + # chart's 15_019) use band 38 and base 65. # 65 x 1.089 = 70.785 rounds to 70.79. Twenty-one with zero income is # within the ordinary income limit but outside modeled payment-table coverage; # zero for that row is not a legal ineligibility determination. input: people: - person1: {age: 40, is_citizen_or_legal_immigrant: true, employment_income: 180_228} + person1: {age: 40, is_citizen_or_legal_immigrant: true, employment_income: 180_225} person2: {age: 40, is_citizen_or_legal_immigrant: true} person3: {age: 40, is_citizen_or_legal_immigrant: true} person4: {age: 40, is_citizen_or_legal_immigrant: true} @@ -332,3 +333,87 @@ wv_lieap_household_size: 1 wv_lieap_income_limit: 29_448 wv_lieap: 280 + +- name: Case 11, FY2026 income above the federal ceiling pays nothing within a rounded chart limit. + period: 2026 + absolute_error_margin: 0.01 + # Three people: HHS's 60% SMI amount 47_575 is below the chart's 3_965 x 12 = 47_580. + # 47_575 is 3_964.58 monthly, row 5, base 145, x 1.75 = 253.75; 47_578 is over the ceiling. + # Eight people: 150% of the 2025 guideline 81_225 is below the chart's 6_769 x 12 = 81_228. + # 81_225 is 6_768.75 monthly, row 15, base 120, x 1.75 = 210; 81_227 is over the ceiling. + input: + people: + person1: {age: 40, is_citizen_or_legal_immigrant: true, employment_income: 47_575} + person2: {age: 40, is_citizen_or_legal_immigrant: true} + person3: {age: 40, is_citizen_or_legal_immigrant: true} + person4: {age: 40, is_citizen_or_legal_immigrant: true, employment_income: 47_578} + person5: {age: 40, is_citizen_or_legal_immigrant: true} + person6: {age: 40, is_citizen_or_legal_immigrant: true} + person7: {age: 40, is_citizen_or_legal_immigrant: true, employment_income: 81_225} + person8: {age: 40, is_citizen_or_legal_immigrant: true} + person9: {age: 40, is_citizen_or_legal_immigrant: true} + person10: {age: 40, is_citizen_or_legal_immigrant: true} + person11: {age: 40, is_citizen_or_legal_immigrant: true} + person12: {age: 40, is_citizen_or_legal_immigrant: true} + person13: {age: 40, is_citizen_or_legal_immigrant: true} + person14: {age: 40, is_citizen_or_legal_immigrant: true} + person15: {age: 40, is_citizen_or_legal_immigrant: true, employment_income: 81_227} + person16: {age: 40, is_citizen_or_legal_immigrant: true} + person17: {age: 40, is_citizen_or_legal_immigrant: true} + person18: {age: 40, is_citizen_or_legal_immigrant: true} + person19: {age: 40, is_citizen_or_legal_immigrant: true} + person20: {age: 40, is_citizen_or_legal_immigrant: true} + person21: {age: 40, is_citizen_or_legal_immigrant: true} + person22: {age: 40, is_citizen_or_legal_immigrant: true} + spm_units: + spm_unit1: + members: [person1, person2, person3] + heating_type: ELECTRICITY + pre_subsidy_electricity_expense: 1_200 + spm_unit2: + members: [person4, person5, person6] + heating_type: ELECTRICITY + pre_subsidy_electricity_expense: 1_200 + spm_unit3: + members: [person7, person8, person9, person10, person11, person12, person13, person14] + heating_type: ELECTRICITY + pre_subsidy_electricity_expense: 1_200 + spm_unit4: + members: [person15, person16, person17, person18, person19, person20, person21, person22] + heating_type: ELECTRICITY + pre_subsidy_electricity_expense: 1_200 + households: + household1: {members: [person1, person2, person3], state_code: WV} + household2: {members: [person4, person5, person6], state_code: WV} + household3: {members: [person7, person8, person9, person10, person11, person12, person13, person14], state_code: WV} + household4: {members: [person15, person16, person17, person18, person19, person20, person21, person22], state_code: WV} + output: + wv_lieap: [253.75, 0, 210, 0] + +- name: Case 12, FY2027 income above the federal ceiling pays nothing within a rounded chart limit. + period: 2027 + absolute_error_margin: 0.01 + # HHS's 60% SMI amount for three, 49_435, is below the chart's 4_120 x 12 = 49_440. + # 49_435 is 4_119.58 monthly, row 5, base 145, x 1.75 = 253.75; 49_438 is over the ceiling. + input: + people: + person1: {age: 40, is_citizen_or_legal_immigrant: true, employment_income: 49_435} + person2: {age: 40, is_citizen_or_legal_immigrant: true} + person3: {age: 40, is_citizen_or_legal_immigrant: true} + person4: {age: 40, is_citizen_or_legal_immigrant: true, employment_income: 49_438} + person5: {age: 40, is_citizen_or_legal_immigrant: true} + person6: {age: 40, is_citizen_or_legal_immigrant: true} + spm_units: + spm_unit1: + members: [person1, person2, person3] + heating_type: ELECTRICITY + pre_subsidy_electricity_expense: 1_200 + spm_unit2: + members: [person4, person5, person6] + heating_type: ELECTRICITY + pre_subsidy_electricity_expense: 1_200 + households: + household1: {members: [person1, person2, person3], state_code: WV} + household2: {members: [person4, person5, person6], state_code: WV} + output: + wv_lieap: [253.75, 0] diff --git a/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_countable_income.yaml index ce8063b66ac..67d46cedeaf 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_countable_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_countable_income.yaml @@ -85,8 +85,8 @@ - 18000 - name: Case 2, recurring represented income sources include assistance and ordinary VA. - # 2_400 + 300 + 600 + 700 + 400 + 900 + (200 + 100) - # + (250 + 50) + 800 + 1_000 + 900 + 1_100 + 1_200 + 1_300 = 12_200. + # 500 + 2_400 + 300 + 600 + 700 + 400 + 900 + (200 + 100) + # + (250 + 50) + 800 + 1_000 + 900 + 1_100 + 1_200 + 1_300 = 12_700. # VA here is ordinary recurring benefits, not excluded Aid and Attendance. # Estate income and child support here are recurring, not inheritance or arrears. # Outside-household cash assistance and GA count under the all-source rule. @@ -98,6 +98,7 @@ age: 40 is_citizen_or_legal_immigrant: true ssi: 0 + military_basic_pay: 500 unemployment_compensation: 2400 strike_benefits: 300 rental_income: 600 @@ -126,7 +127,7 @@ state_code: WV output: wv_lieap_countable_income: - - 12200 + - 12700 - name: Case 3, pensions account distributions and non-SSA survivor benefits count once. # Recurring pensions: 1_000 + 2_000 + 300 + 400 = 3_700. diff --git a/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_income_eligible.yaml index 1410204e217..ef82a1f986f 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_income_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_income_eligible.yaml @@ -12,6 +12,7 @@ is_citizen_or_legal_immigrant: [true, true, false, true] employment_income: [29_448, 29_448.12, 0, 0] output: + wv_lieap_income_limit: [29_448, 29_448, 0, 0] wv_lieap_income_eligible: [true, false, false, false] - name: Case 2, the FY2027 ceiling remains inclusive without changing the formula. diff --git a/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_income_limit.yaml b/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_income_limit.yaml index 4063b5a10a6..8748722619e 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_income_limit.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_income_limit.yaml @@ -1,28 +1,33 @@ -# Sources: FY2026 agency table gives sizes 1-10; earlier IMM gives size 11. +# Sources: the FY2026 chart prints sizes 1-10 and adds $688 for each further person. # https://bfa.wv.gov/utility-assistancelieap # https://bfa.wv.gov/media/39948/download?inline=#page=1772 # FY2027 adopted operational IMM gives separately verified sizes 1-11. # https://bfa.wv.gov/media/40005/download?inline=#page=1775 # The 60% SMI through 7 and 150% FPG from 8 split is explicit in the accepted FY2026 plan. # https://liheapch.acf.gov/docs/2026/state-plans/WV_Plan_2026.pdf#page=11 -# Expected limits are published monthly amounts multiplied by 12, independently -# checked with Decimal arithmetic; no model formula was used to generate them. -# FY2026 size 11 is 8831/month, not the agency shorthand 8144 + 688 = 8832. +# Expected limits are the published monthly amounts x 12, stopped at the ceiling of +# 42 U.S.C. 8624(b)(2)(B): HHS's 60% SMI amounts through 7, 150% of the guideline from 8. +# https://www.law.cornell.edu/uscode/text/42/8624#b_2_B +# https://acf.gov/sites/default/files/documents/ocs/COMM_LIHEAP_IM2025-02_SMIStateTable_Att4.pdf#page=3 +# https://acf.gov/sites/default/files/documents/ocs/COMM_LIHEAP_Att4SMITable_States_FY2027.pdf#page=3 +# Both were checked independently by hand; no model formula was used. +# FY2026 size 11 is 8831/month: the chart's 8144 + 688 = 8832 is above 150% of the +# guideline, 8831.25. # Payment-grid overlaps and larger-family defects are outside this component. -- name: Case 1, FY2026 published limits for 1 through 11 qualified members. +- name: Case 1, FY2026 limits for 1 through 11 qualified members stop at the federal ceiling. period: 2026 absolute_error_margin: 0.01 # Size 1: 60% of requested-year SMI; published $2,454/month x 12 = $29,448/year. # Size 2: 60% of requested-year SMI; published $3,209/month x 12 = $38,508/year. - # Size 3: 60% of requested-year SMI; published $3,965/month x 12 = $47,580/year. - # Size 4: 60% of requested-year SMI; published $4,720/month x 12 = $56,640/year. - # Size 5: 60% of requested-year SMI; published $5,475/month x 12 = $65,700/year. + # Size 3: published $3,965/month x 12 = $47,580/year, above HHS's $47,575. + # Size 4: published $4,720/month x 12 = $56,640/year, above HHS's $56,637. + # Size 5: published $5,475/month x 12 = $65,700/year, above HHS's $65,698. # Size 6: 60% of requested-year SMI; published $6,230/month x 12 = $74,760/year. - # Size 7: 60% of requested-year SMI; published $6,372/month x 12 = $76,464/year. - # Size 8: 150% of prior-year FPG; published $6,769/month x 12 = $81,228/year. + # Size 7: published $6,372/month x 12 = $76,464/year, above HHS's $76,459. + # Size 8: published $6,769/month x 12 = $81,228/year, above 1.5 x $54,150 = $81,225. # Size 9: 150% of prior-year FPG; published $7,456/month x 12 = $89,472/year. - # Size 10: 150% of prior-year FPG; published $8,144/month x 12 = $97,728/year. + # Size 10: published $8,144/month x 12 = $97,728/year, above 1.5 x $65,150 = $97,725. # Size 11: 150% of prior-year FPG; published $8,831/month x 12 = $105,972/year. input: people: @@ -120,26 +125,26 @@ wv_lieap_income_limit: - 29_448 - 38_508 - - 47_580 - - 56_640 - - 65_700 + - 47_575 + - 56_637 + - 65_698 - 74_760 - - 76_464 - - 81_228 + - 76_459 + - 81_225 - 89_472 - - 97_728 + - 97_725 - 105_972 -- name: Case 2, FY2027 published limits for 1 through 11 qualified members. +- name: Case 2, FY2027 limits for 1 through 11 qualified members stop at the federal ceiling. period: 2027 absolute_error_margin: 0.01 # Size 1: 60% of requested-year SMI; published $2,550/month x 12 = $30,600/year. - # Size 2: 60% of requested-year SMI; published $3,335/month x 12 = $40,020/year. - # Size 3: 60% of requested-year SMI; published $4,120/month x 12 = $49,440/year. + # Size 2: published $3,335/month x 12 = $40,020/year, above HHS's $40,019. + # Size 3: published $4,120/month x 12 = $49,440/year, above HHS's $49,435. # Size 4: 60% of requested-year SMI; published $4,904/month x 12 = $58,848/year. # Size 5: 60% of requested-year SMI; published $5,689/month x 12 = $68,268/year. - # Size 6: 60% of requested-year SMI; published $6,474/month x 12 = $77,688/year. - # Size 7: 60% of requested-year SMI; published $6,621/month x 12 = $79,452/year. + # Size 6: published $6,474/month x 12 = $77,688/year, above HHS's $77,684. + # Size 7: published $6,621/month x 12 = $79,452/year, above HHS's $79,450. # Size 8: 150% of prior-year FPG; published $6,965/month x 12 = $83,580/year. # Size 9: 150% of prior-year FPG; published $7,675/month x 12 = $92,100/year. # Size 10: 150% of prior-year FPG; published $8,385/month x 12 = $100,620/year. @@ -239,12 +244,12 @@ output: wv_lieap_income_limit: - 30_600 - - 40_020 - - 49_440 + - 40_019 + - 49_435 - 58_848 - 68_268 - - 77_688 - - 79_452 + - 77_684 + - 79_450 - 83_580 - 92_100 - 100_620 @@ -253,7 +258,7 @@ - name: Case 3, eight residents with seven qualified members stay on the SMI branch. period: 2026 absolute_error_margin: 0.01 - # Qualified size 7: FY2026 monthly 6372 x 12 = 76464. + # Qualified size 7: HHS's FY2026 amount 76459, below the chart's 6372 x 12 = 76464. input: people: person1: {age: 70, is_citizen_or_legal_immigrant: true} @@ -272,12 +277,12 @@ members: [person1, person2, person3, person4, person5, person6, person7, person8] state_code: WV output: - wv_lieap_income_limit: 76_464 + wv_lieap_income_limit: 76_459 - name: Case 4, nine residents with eight qualified members use the FPG branch. period: 2026 absolute_error_margin: 0.01 - # Qualified size 8: FY2026 monthly 6769 x 12 = 81228. + # Qualified size 8: 1.5 x 54150 = 81225, below the chart's 6769 x 12 = 81228. input: people: person1: {age: 70, is_citizen_or_legal_immigrant: true} @@ -297,12 +302,12 @@ members: [person1, person2, person3, person4, person5, person6, person7, person8, person9] state_code: WV output: - wv_lieap_income_limit: 81_228 + wv_lieap_income_limit: 81_225 - name: Case 5, mixed WV and neighboring-state households retain independent limits. period: 2026 absolute_error_margin: 0.01 - # WV sizes 1 and 8 use 2454 and 6769 monthly; the WV variable is zero in Ohio. + # WV size 1 uses 2454 monthly and size 8 stops at 81225; the WV variable is zero in Ohio. input: people: person1: {age: 40, is_citizen_or_legal_immigrant: true} @@ -340,4 +345,4 @@ members: [person10, person11, person12, person13, person14, person15, person16, person17] state_code: WV output: - wv_lieap_income_limit: [29448, 0, 81228] + wv_lieap_income_limit: [29448, 0, 81225] diff --git a/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap.py b/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap.py index bebfa294dfe..4f16dec589f 100644 --- a/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap.py +++ b/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap.py @@ -23,7 +23,8 @@ def formula(spm_unit, period, parameters): # integer lower bounds overlap and leave cent gaps. band = p.income_band.calc(income, right=True) # Exact compression of every occupied published cell, not extrapolation. - # Income eligibility confines sizes 1-20 to occupied table cells. + # In both verified years, income eligibility confines sizes 1-20 to occupied + # table cells. base = p.base_amount + p.amount_step * (size - 1 - band) heating = spm_unit("heating_type", period) types = heating.possible_values diff --git a/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_income_limit.py b/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_income_limit.py index 6c27983534b..3c2427ef254 100644 --- a/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_income_limit.py +++ b/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_income_limit.py @@ -11,8 +11,15 @@ class wv_lieap_income_limit(Variable): definition_period = YEAR defined_for = StateCode.WV reference = ( + "https://www.law.cornell.edu/uscode/text/42/8624#b_2_B", + # FY2026 federal amounts, PDF pages 3,6 + "https://acf.gov/sites/default/files/documents/ocs/COMM_LIHEAP_IM2025-02_SMIStateTable_Att4.pdf#page=3", + # FY2027 federal amounts, PDF pages 3,6 + "https://acf.gov/sites/default/files/documents/ocs/COMM_LIHEAP_Att4SMITable_States_FY2027.pdf#page=3", # PDF pages 9,11 "https://liheapch.acf.gov/docs/2026/state-plans/WV_Plan_2026.pdf#page=9", + # PDF pages 9,12 + "https://bfa.wv.gov/media/39990/download?inline=#page=9", # FY2026 chart, PDF pages 406,1777 "https://bfa.wv.gov/media/39948/download?inline=#page=406", # FY2027 chart, PDF pages 405,1779 @@ -30,7 +37,11 @@ def formula(spm_unit, period, parameters): ) annual = where(size <= p.smi_max_household_size, annual_smi, annual_fpg) # Nearest-dollar monthly rounding matches all ten published agency rows. - # Apply the actual guideline to additional members, rather than repeatedly - # adding a rounded increment; the latter diverges from the manual at 11. + # Apply the actual guideline to additional members: the chart's rounded + # add-on for each member above ten overshoots 150% of the guideline. monthly = np.floor(annual / MONTHS_IN_YEAR + 0.5) - return where(size > 0, monthly * MONTHS_IN_YEAR, 0) + # 42 U.S.C. 8624(b)(2)(B) pays no household above the greater of 60% of SMI + # and 150% of the guideline, which is annual at every size. A published + # monthly amount that rounds up therefore stops there. + limit = min_(monthly * MONTHS_IN_YEAR, annual) + return where(size > 0, limit, 0) diff --git a/source_conflicts/candidates.yaml b/source_conflicts/candidates.yaml index 1cea80fc061..05adf1ec5ed 100644 --- a/source_conflicts/candidates.yaml +++ b/source_conflicts/candidates.yaml @@ -9735,6 +9735,162 @@ candidates: threshold and federal-method conditions by year. Code not yet on main: gov/states/wv/tax/income/subtractions/wv_claim_of_right_subtraction.yaml, policyengine_us/variables/gov/states/wv/tax/income/subtractions/wv_subtractions.py, wv_claim_of_right_subtraction, gov.states.wv.tax.income.subtractions.claim_of_right.threshold.' +- id: us-wv:liheap-income-limit-above-federal-ceiling + program: liheap + years: + from: 2026 + to: 2027 + type: federal-fiscal + question: Can West Virginia's whole-dollar monthly LIEAP limits pay a household whose income exceeds both 150% of the + poverty guideline and HHS's 60% state median income amount? + sources: + - kind: statute + citation: 42 U.S.C. 8624(b)(2)(B) + url: https://www.law.cornell.edu/uscode/text/42/8624#b_2_B + - kind: guidance + citation: HHS LIHEAP IM 2025-02 Attachment 4, Mandatory Use in LIHEAP for FY26, West Virginia, pages 3 and 6 + url: https://acf.gov/sites/default/files/documents/ocs/COMM_LIHEAP_IM2025-02_SMIStateTable_Att4.pdf#page=3 + - kind: guidance + citation: HHS LIHEAP FY2027 Attachment 4, Mandatory Use in LIHEAP for FY27, West Virginia, pages 3 and 6 + url: https://acf.gov/sites/default/files/documents/ocs/COMM_LIHEAP_Att4SMITable_States_FY2027.pdf#page=3 + - kind: manual + citation: West Virginia Income Maintenance Manual, Chapter 4 Appendix A, PDF page 406 (FY2026 chart) + url: https://bfa.wv.gov/media/39948/download?inline=#page=406 + - kind: manual + citation: West Virginia Income Maintenance Manual, update 881, Chapter 4 Appendix A, PDF page 405 (FY2027 chart) + url: https://bfa.wv.gov/media/40005/download?inline=#page=405 + readings: + statute: Payments go only to households whose income does not exceed the greater of 150% of the poverty guideline + and 60% of the state median income that HHS publishes and adjusts for household size. + other: The charts round each monthly limit to the nearest dollar, and the FY2026 chart adds a rounded $688 for each + member above ten, which puts the limits above the federal maximum at several sizes. + example: In FY2026, three people with $47,578 of countable income and electric heat are within the printed $47,580 + limit ($3,965 a month), which would pay $253.75, but exceed the $47,575 federal maximum and receive $0 in the PR. + pe_us: + follows: statute + code: + - policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_income_limit.py + prs: + - https://github.com/PolicyEngine/policyengine-us/pull/10618 + state: ruled + note: 'Ruled under the 2026-10-19 statute-first rule. The PR stops each limit at the federal maximum. Printed and capped + annual limits: FY2026 size 3, $47,580 and $47,575; 4, $56,640 and $56,637; 5, $65,700 and $65,698; 7, $76,464 and + $76,459; even sizes from 8, $3 lower ($81,228 and $81,225 at 8). FY2027 size 2, $40,020 and $40,019; 3, $49,440 and + $49,435; 6, $77,688 and $77,684; 7, $79,452 and $79,450. Other sizes keep the printed amount, which rounds down or + equals the maximum. Verify each later fiscal-year chart.' + +- id: us-wv:liheap-plan-categorical-eligibility + program: liheap + years: + from: 2026 + to: 2026 + type: federal-fiscal + question: Do West Virginia households receiving TANF, SSI or SNAP bypass the LIEAP income test, as FY2026 plan item 1.4 + answers, or does the manual's income test apply to every assistance group? + sources: + - kind: manual + citation: West Virginia Income Maintenance Manual, 21.3.1.A and 21.4.9.A, PDF pages 1725 and 1749 + url: https://bfa.wv.gov/media/39948/download?inline=#page=1725 + - kind: plan + citation: West Virginia FY2026 LIHEAP State Plan, item 1.4, page 5 + url: https://liheapch.acf.gov/docs/2026/state-plans/WV_Plan_2026.pdf#page=5 + - kind: plan + citation: West Virginia submitted FY2027 LIHEAP State Plan, item 1.4, page 5 + url: https://bfa.wv.gov/media/39990/download?inline=#page=5 + readings: + statute: No statute is supplied; the manual denies a group above the ceiling, and its 21.4.9.A example verifies a + working member's income when another member receives SSI. + other: FY2026 plan item 1.4 answers Yes for TANF, SSI and SNAP in heating. The FY2027 plan answers No for all of them. + example: In FY2026, a two-person SNAP household with $40,000 of wages is above the $38,508 limit and ineligible under + the manual, and categorically eligible under plan item 1.4. + pe_us: + follows: gap-fill + code: + - policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_income_eligible.py + prs: + - https://github.com/PolicyEngine/policyengine-us/pull/10618 + state: ruled + note: 'Ruled 2026-10-06: follow the manual over the plan.' + +- id: us-wv:liheap-plan-income-and-benefit-items + program: liheap + years: + from: 2026 + to: 2027 + type: federal-fiscal + question: Do income sources and benefit factors follow West Virginia's manual or the check boxes in plan items 1.9 and + 2.5? + sources: + - kind: manual + citation: West Virginia Income Maintenance Manual, 21.3.1.A and 21.4.11.B, PDF pages 1725-1728 and 1754-1755 + url: https://bfa.wv.gov/media/39948/download?inline=#page=1725 + - kind: manual + citation: West Virginia Income Maintenance Manual, update 881, 21.3.1.A and 21.4.11.B, PDF pages 1726-1729 and + 1757-1758 + url: https://bfa.wv.gov/media/40005/download?inline=#page=1726 + - kind: plan + citation: West Virginia FY2026 LIHEAP State Plan, items 1.9 and 2.5, pages 6-7 and 11 + url: https://liheapch.acf.gov/docs/2026/state-plans/WV_Plan_2026.pdf#page=6 + - kind: plan + citation: West Virginia submitted FY2027 LIHEAP State Plan, items 1.9 and 2.5, pages 6-7 and 12 + url: https://bfa.wv.gov/media/39990/download?inline=#page=6 + readings: + statute: No statute is supplied; the manual considers all sources of income, excludes nonrecurring lump sums and sets + the payment by income, group size and energy type. + other: Plan item 1.9 leaves general assistance, TANF, cash gifts and (in FY2026 only) a child's earnings unchecked and + checks one-time lump sums. Plan item 2.5 also checks individual bill, energy burden and energy need. + example: In FY2026, a parent's $12,000 of wages and a 17-year-old's $6,000 of wages count $18,000 under the manual and + $12,000 under the plan. + pe_us: + follows: gap-fill + code: + - policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_countable_income.py + - policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap.py + - policyengine_us/parameters/gov/states/wv/dhhr/lieap/income/sources.yaml + prs: + - https://github.com/PolicyEngine/policyengine-us/pull/10618 + state: ruled + note: 'Ruled 2026-10-06: follow the manual over the plan. Veterans benefits have their own item, + us-wv:liheap-veterans-benefits.' + +- id: us-wv:liheap-veterans-benefits + program: liheap + years: + from: 2026 + to: 2027 + type: federal-fiscal + question: Does West Virginia LIEAP exclude all veterans benefits, as the agency's December 2025 announcement and the + plan's unchecked box read, or only VA Aid and Attendance payments, as both manual editions read? + sources: + - kind: manual + citation: West Virginia Income Maintenance Manual, 21.3.1.A.5, PDF page 1728 + url: https://bfa.wv.gov/media/39948/download?inline=#page=1728 + - kind: manual + citation: West Virginia Income Maintenance Manual, update 881, 21.3.1.A.5, PDF page 1729 + url: https://bfa.wv.gov/media/40005/download?inline=#page=1729 + - kind: agency-practice + citation: West Virginia Department of Human Services announcement, December 18, 2025 + url: https://dohs.wv.gov/article/west-virginia-department-human-services-announces-automatic-lieap-application-mailing-low + - kind: plan + citation: West Virginia FY2026 LIHEAP State Plan, item 1.9, page 7 + url: https://liheapch.acf.gov/docs/2026/state-plans/WV_Plan_2026.pdf#page=7 + readings: + statute: No statute is supplied; both manual editions list only "Veterans Affairs (VA) Aid and Attendance payments" + among the exclusions. + other: The announcement's income table says "Social Security & Veterans Benefits Excluded", and plan item 1.9 leaves + "Veterans Administration (VA) benefits" unchecked. + example: In FY2026, one person with electric heat, $20,000 of wages and $12,000 of VA compensation counts $32,000 and + receives $0 under the manual, and counts $20,000 and receives $280 under the announcement. + pe_us: + follows: gap-fill + code: + - policyengine_us/parameters/gov/states/wv/dhhr/lieap/income/sources.yaml + prs: + - https://github.com/PolicyEngine/policyengine-us/pull/10618 + state: unreviewed + note: PE-US follows the manual, whose two editions are both later than the announcement, and counts veterans_benefits in + full because the input cannot separate Aid and Attendance. + - id: us-wv:medicaid-ssi-related-non-cash-income-at-standard program: medicaid years: From 2ce7b1846870f542730104a0c321348ae231c72b Mon Sep 17 00:00:00 2001 From: Ziming Date: Thu, 5 Nov 2026 13:08:12 -0500 Subject: [PATCH 6/7] Move West Virginia LIEAP manual citations to archived copies The Bureau for Family Assistance removed both Income Maintenance Manual files. Update 881 keeps its page numbers in the Wayback capture. The only capture of the earlier edition has later page numbers, so its anchors move with it. Co-Authored-By: Claude Opus 5.5 --- .../dhhr/lieap/eligibility/fpg_year_lag.yaml | 4 +-- .../states/wv/dhhr/lieap/income/sources.yaml | 6 ++--- .../wv/dhhr/lieap/payment/amount_step.yaml | 6 ++--- .../wv/dhhr/lieap/payment/base_amount.yaml | 6 ++--- .../dhhr/lieap/payment/fuel_multiplier.yaml | 6 ++--- .../wv/dhhr/lieap/payment/income_band.yaml | 6 ++--- .../lieap/payment/max_household_size.yaml | 6 ++--- .../gov/states/wv/dhhr/lieap/wv_lieap.yaml | 6 ++--- .../dhhr/lieap/wv_lieap_countable_income.yaml | 6 ++--- .../dhhr/lieap/wv_lieap_household_size.yaml | 6 ++--- .../dhhr/lieap/wv_lieap_income_eligible.yaml | 2 +- .../wv/dhhr/lieap/wv_lieap_income_limit.yaml | 4 +-- .../gov/states/wv/dhhr/lieap/wv_lieap.py | 6 ++--- .../dhhr/lieap/wv_lieap_countable_income.py | 6 ++--- .../wv/dhhr/lieap/wv_lieap_household_size.py | 6 ++--- .../wv/dhhr/lieap/wv_lieap_income_eligible.py | 6 ++--- .../wv/dhhr/lieap/wv_lieap_income_limit.py | 6 ++--- source_conflicts/candidates.yaml | 26 ++++++++++--------- 18 files changed, 61 insertions(+), 59 deletions(-) diff --git a/policyengine_us/parameters/gov/states/wv/dhhr/lieap/eligibility/fpg_year_lag.yaml b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/eligibility/fpg_year_lag.yaml index f5e99a72fcb..5876324e288 100644 --- a/policyengine_us/parameters/gov/states/wv/dhhr/lieap/eligibility/fpg_year_lag.yaml +++ b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/eligibility/fpg_year_lag.yaml @@ -9,6 +9,6 @@ metadata: label: West Virginia LIEAP fpg year lag reference: - title: West Virginia Income Maintenance Manual, Chapter 4 Appendix A - href: https://bfa.wv.gov/media/39948/download?inline=#page=406 + href: https://web.archive.org/web/20260302130424/https://bfa.wv.gov/media/39948/download?inline#page=407 - title: West Virginia Income Maintenance Manual, October 2026 edition, Chapter 4 Appendix A - href: https://bfa.wv.gov/media/40005/download?inline=#page=405 + href: https://web.archive.org/web/20261023203756/https://bfa.wv.gov/media/40005/download?inline#page=405 diff --git a/policyengine_us/parameters/gov/states/wv/dhhr/lieap/income/sources.yaml b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/income/sources.yaml index f990c4e3787..b532aefbabe 100644 --- a/policyengine_us/parameters/gov/states/wv/dhhr/lieap/income/sources.yaml +++ b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/income/sources.yaml @@ -45,7 +45,7 @@ metadata: period: year label: West Virginia LIEAP recurring income sources reference: - - title: "West Virginia Income Maintenance Manual, Chapter 21.3.1.A #page 1725-1728" - href: https://bfa.wv.gov/media/39948/download?inline=#page=1725 + - title: "West Virginia Income Maintenance Manual, Chapter 21.3.1.A #page 1732-1735" + href: https://web.archive.org/web/20260302130424/https://bfa.wv.gov/media/39948/download?inline#page=1732 - title: "West Virginia Income Maintenance Manual, October 2026 edition, Chapter 21.3.1.A #page 1726-1729" - href: https://bfa.wv.gov/media/40005/download?inline=#page=1726 + href: https://web.archive.org/web/20261023203756/https://bfa.wv.gov/media/40005/download?inline#page=1726 diff --git a/policyengine_us/parameters/gov/states/wv/dhhr/lieap/payment/amount_step.yaml b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/payment/amount_step.yaml index 32449be6cb8..959d114e9d0 100644 --- a/policyengine_us/parameters/gov/states/wv/dhhr/lieap/payment/amount_step.yaml +++ b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/payment/amount_step.yaml @@ -10,7 +10,7 @@ metadata: period: year label: West Virginia LIEAP published base payment step reference: - - title: "West Virginia Income Maintenance Manual, Appendix A #page 1772-1773" - href: https://bfa.wv.gov/media/39948/download?inline=#page=1772 + - title: "West Virginia Income Maintenance Manual, Appendix A #page 1780-1781" + href: https://web.archive.org/web/20260302130424/https://bfa.wv.gov/media/39948/download?inline#page=1780 - title: "West Virginia Income Maintenance Manual, October 2026 edition, Appendix A #page 1775-1776" - href: https://bfa.wv.gov/media/40005/download?inline=#page=1775 + href: https://web.archive.org/web/20261023203756/https://bfa.wv.gov/media/40005/download?inline#page=1775 diff --git a/policyengine_us/parameters/gov/states/wv/dhhr/lieap/payment/base_amount.yaml b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/payment/base_amount.yaml index a951e1a49cc..4673b54a9ae 100644 --- a/policyengine_us/parameters/gov/states/wv/dhhr/lieap/payment/base_amount.yaml +++ b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/payment/base_amount.yaml @@ -10,7 +10,7 @@ metadata: period: year label: West Virginia LIEAP first published base amount reference: - - title: "West Virginia Income Maintenance Manual, Appendix A #page 1772-1773" - href: https://bfa.wv.gov/media/39948/download?inline=#page=1772 + - title: "West Virginia Income Maintenance Manual, Appendix A #page 1780-1781" + href: https://web.archive.org/web/20260302130424/https://bfa.wv.gov/media/39948/download?inline#page=1780 - title: "West Virginia Income Maintenance Manual, October 2026 edition, Appendix A #page 1775-1776" - href: https://bfa.wv.gov/media/40005/download?inline=#page=1775 + href: https://web.archive.org/web/20261023203756/https://bfa.wv.gov/media/40005/download?inline#page=1775 diff --git a/policyengine_us/parameters/gov/states/wv/dhhr/lieap/payment/fuel_multiplier.yaml b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/payment/fuel_multiplier.yaml index f3591fa1a06..d11806f2b47 100644 --- a/policyengine_us/parameters/gov/states/wv/dhhr/lieap/payment/fuel_multiplier.yaml +++ b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/payment/fuel_multiplier.yaml @@ -17,7 +17,7 @@ metadata: period: year label: West Virginia LIEAP heating-source payment multiplier reference: - - title: "West Virginia Income Maintenance Manual, section 21.4.11.B #page 1754-1755" - href: https://bfa.wv.gov/media/39948/download?inline=#page=1754 + - title: "West Virginia Income Maintenance Manual, section 21.4.11.B #page 1761-1762" + href: https://web.archive.org/web/20260302130424/https://bfa.wv.gov/media/39948/download?inline#page=1761 - title: "West Virginia Income Maintenance Manual, October 2026 edition, section 21.4.11.B #page 1757-1758" - href: https://bfa.wv.gov/media/40005/download?inline=#page=1757 + href: https://web.archive.org/web/20261023203756/https://bfa.wv.gov/media/40005/download?inline#page=1757 diff --git a/policyengine_us/parameters/gov/states/wv/dhhr/lieap/payment/income_band.yaml b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/payment/income_band.yaml index 6428a8cd728..b699113a6a8 100644 --- a/policyengine_us/parameters/gov/states/wv/dhhr/lieap/payment/income_band.yaml +++ b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/payment/income_band.yaml @@ -216,7 +216,7 @@ metadata: period: month label: West Virginia LIEAP monthly income band index reference: - - title: "West Virginia Income Maintenance Manual, Appendix A #page 1772-1773" - href: https://bfa.wv.gov/media/39948/download?inline=#page=1772 + - title: "West Virginia Income Maintenance Manual, Appendix A #page 1780-1781" + href: https://web.archive.org/web/20260302130424/https://bfa.wv.gov/media/39948/download?inline#page=1780 - title: "West Virginia Income Maintenance Manual, October 2026 edition, Appendix A #page 1775-1776" - href: https://bfa.wv.gov/media/40005/download?inline=#page=1775 + href: https://web.archive.org/web/20261023203756/https://bfa.wv.gov/media/40005/download?inline#page=1775 diff --git a/policyengine_us/parameters/gov/states/wv/dhhr/lieap/payment/max_household_size.yaml b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/payment/max_household_size.yaml index 8e1d5d3dde6..c1e8713d588 100644 --- a/policyengine_us/parameters/gov/states/wv/dhhr/lieap/payment/max_household_size.yaml +++ b/policyengine_us/parameters/gov/states/wv/dhhr/lieap/payment/max_household_size.yaml @@ -10,7 +10,7 @@ metadata: period: year label: West Virginia LIEAP maximum published payment household size reference: - - title: "West Virginia Income Maintenance Manual, Appendix A #page 1772-1773" - href: https://bfa.wv.gov/media/39948/download?inline=#page=1772 + - title: "West Virginia Income Maintenance Manual, Appendix A #page 1780-1781" + href: https://web.archive.org/web/20260302130424/https://bfa.wv.gov/media/39948/download?inline#page=1780 - title: "West Virginia Income Maintenance Manual, October 2026 edition, Appendix A #page 1775-1776" - href: https://bfa.wv.gov/media/40005/download?inline=#page=1775 + href: https://web.archive.org/web/20261023203756/https://bfa.wv.gov/media/40005/download?inline#page=1775 diff --git a/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap.yaml b/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap.yaml index 61208e97045..740af4ce0d1 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap.yaml @@ -1,8 +1,8 @@ # Published regular LIEAP tables and multiplication examples, not crisis caps. -# FY2026: PDF pages 1754-1755,1772-1773 -# https://bfa.wv.gov/media/39948/download?inline=#page=1754 +# FY2026: PDF pages 1761-1762,1780-1781 +# https://web.archive.org/web/20260302130424/https://bfa.wv.gov/media/39948/download?inline#page=1761 # FY2027: PDF pages 1757-1758,1775-1776 -# https://bfa.wv.gov/media/40005/download?inline=#page=1757 +# https://web.archive.org/web/20261023203756/https://bfa.wv.gov/media/40005/download?inline#page=1757 # Continuous published upper bounds apply, with no income rounding. - name: Case 1, zero income receives each supported fuel amount without a bill cap. diff --git a/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_countable_income.yaml index 67d46cedeaf..d583103955f 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_countable_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_countable_income.yaml @@ -1,8 +1,8 @@ # Independent source-derived tests for annualized countable income only. -# Earlier operative IMM, section 21.3.1.A.1-4/B/D (physical pages 1725-1728, 1732). -# https://bfa.wv.gov/media/39948/download?inline=#page=1725 +# Earlier operative IMM, section 21.3.1.A.1-4/B/D (physical pages 1732-1735, 1739). +# https://web.archive.org/web/20260302130424/https://bfa.wv.gov/media/39948/download?inline#page=1732 # Current October 1, 2026 IMM, section 21.3.1.A.1-3/A.5/B (physical pages 1726-1729, 1734). -# https://bfa.wv.gov/media/40005/download?inline=#page=1726 +# https://web.archive.org/web/20261023203756/https://bfa.wv.gov/media/40005/download?inline#page=1726 # Annual flow inputs approximate steady application-month receipt; they do not # reconstruct application dates, pay-frequency conversions or partial months. # The detailed manual governs over unchecked summary-plan income categories. diff --git a/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_household_size.yaml b/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_household_size.yaml index 43d404f222f..61280925358 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_household_size.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_household_size.yaml @@ -1,7 +1,7 @@ -# Household composition: earlier official IMM 21.3.1.B, physical page 1728; +# Household composition: earlier official IMM 21.3.1.B, physical page 1735; # current IMM 21.3.1.B and citizenship, physical pages 1729 and 1734. -# https://bfa.wv.gov/media/39948/download?inline=#page=1728 -# https://bfa.wv.gov/media/40005/download?inline=#page=1729 +# https://web.archive.org/web/20260302130424/https://bfa.wv.gov/media/39948/download?inline#page=1735 +# https://web.archive.org/web/20261023203756/https://bfa.wv.gov/media/40005/download?inline#page=1729 # The SPM unit stands in for the manual's one-household assistance group. # These component tests make no claim about income or final benefit eligibility. diff --git a/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_income_eligible.yaml index ef82a1f986f..7af280a0a8f 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_income_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_income_eligible.yaml @@ -1,5 +1,5 @@ # Current Income Maintenance Manual, section 21.3.1.A, physical page 1726. -# https://bfa.wv.gov/media/40005/download?inline=#page=1726 +# https://web.archive.org/web/20261023203756/https://bfa.wv.gov/media/40005/download?inline#page=1726 - name: Case 1, the FY2026 ceiling is inclusive with qualified and state guards. period: 2026 diff --git a/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_income_limit.yaml b/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_income_limit.yaml index 8748722619e..10318e54403 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_income_limit.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/wv/dhhr/lieap/wv_lieap_income_limit.yaml @@ -1,8 +1,8 @@ # Sources: the FY2026 chart prints sizes 1-10 and adds $688 for each further person. # https://bfa.wv.gov/utility-assistancelieap -# https://bfa.wv.gov/media/39948/download?inline=#page=1772 +# https://web.archive.org/web/20260302130424/https://bfa.wv.gov/media/39948/download?inline#page=1780 # FY2027 adopted operational IMM gives separately verified sizes 1-11. -# https://bfa.wv.gov/media/40005/download?inline=#page=1775 +# https://web.archive.org/web/20261023203756/https://bfa.wv.gov/media/40005/download?inline#page=1775 # The 60% SMI through 7 and 150% FPG from 8 split is explicit in the accepted FY2026 plan. # https://liheapch.acf.gov/docs/2026/state-plans/WV_Plan_2026.pdf#page=11 # Expected limits are the published monthly amounts x 12, stopped at the ceiling of diff --git a/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap.py b/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap.py index 4f16dec589f..34d7aba7073 100644 --- a/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap.py +++ b/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap.py @@ -9,10 +9,10 @@ class wv_lieap(Variable): definition_period = YEAR defined_for = "wv_lieap_income_eligible" reference = ( - # PDF pages 1729-1731,1753-1755,1772-1773 - "https://bfa.wv.gov/media/39948/download?inline=#page=1729", + # PDF pages 1736-1738,1760-1762,1780-1781 + "https://web.archive.org/web/20260302130424/https://bfa.wv.gov/media/39948/download?inline#page=1736", # PDF pages 1730-1734,1757-1758,1775-1776 - "https://bfa.wv.gov/media/40005/download?inline=#page=1730", + "https://web.archive.org/web/20261023203756/https://bfa.wv.gov/media/40005/download?inline#page=1730", ) def formula(spm_unit, period, parameters): diff --git a/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_countable_income.py b/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_countable_income.py index 1e3b9756975..9863a956079 100644 --- a/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_countable_income.py +++ b/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_countable_income.py @@ -9,10 +9,10 @@ class wv_lieap_countable_income(Variable): definition_period = YEAR defined_for = StateCode.WV reference = ( - # PDF pages 1725-1728 - "https://bfa.wv.gov/media/39948/download?inline=#page=1725", + # PDF pages 1732-1735 + "https://web.archive.org/web/20260302130424/https://bfa.wv.gov/media/39948/download?inline#page=1732", # PDF pages 1726-1729 - "https://bfa.wv.gov/media/40005/download?inline=#page=1726", + "https://web.archive.org/web/20261023203756/https://bfa.wv.gov/media/40005/download?inline#page=1726", ) def formula(spm_unit, period, parameters): diff --git a/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_household_size.py b/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_household_size.py index 755307edd58..2379ae38796 100644 --- a/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_household_size.py +++ b/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_household_size.py @@ -8,10 +8,10 @@ class wv_lieap_household_size(Variable): definition_period = YEAR defined_for = StateCode.WV reference = ( - # PDF pages 1728,1732 - "https://bfa.wv.gov/media/39948/download?inline=#page=1728", + # PDF pages 1735,1739 + "https://web.archive.org/web/20260302130424/https://bfa.wv.gov/media/39948/download?inline#page=1735", # PDF pages 1729,1734 - "https://bfa.wv.gov/media/40005/download?inline=#page=1729", + "https://web.archive.org/web/20261023203756/https://bfa.wv.gov/media/40005/download?inline#page=1729", ) # The manual treats everyone living in the home as one assistance group, whether # or not they share heating costs. The SPM unit stands in for that group, so a diff --git a/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_income_eligible.py b/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_income_eligible.py index 7cc70af7b46..9c4dd83ead8 100644 --- a/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_income_eligible.py +++ b/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_income_eligible.py @@ -8,10 +8,10 @@ class wv_lieap_income_eligible(Variable): definition_period = YEAR defined_for = StateCode.WV reference = ( - # PDF pages 1725,1749 - "https://bfa.wv.gov/media/39948/download?inline=#page=1725", + # PDF pages 1732,1756 + "https://web.archive.org/web/20260302130424/https://bfa.wv.gov/media/39948/download?inline#page=1732", # PDF pages 1726,1752 - "https://bfa.wv.gov/media/40005/download?inline=#page=1726", + "https://web.archive.org/web/20261023203756/https://bfa.wv.gov/media/40005/download?inline#page=1726", ) def formula(spm_unit, period, parameters): diff --git a/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_income_limit.py b/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_income_limit.py index 3c2427ef254..c8d0e611003 100644 --- a/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_income_limit.py +++ b/policyengine_us/variables/gov/states/wv/dhhr/lieap/wv_lieap_income_limit.py @@ -20,10 +20,10 @@ class wv_lieap_income_limit(Variable): "https://liheapch.acf.gov/docs/2026/state-plans/WV_Plan_2026.pdf#page=9", # PDF pages 9,12 "https://bfa.wv.gov/media/39990/download?inline=#page=9", - # FY2026 chart, PDF pages 406,1777 - "https://bfa.wv.gov/media/39948/download?inline=#page=406", + # FY2026 chart, PDF pages 407,1785 + "https://web.archive.org/web/20260302130424/https://bfa.wv.gov/media/39948/download?inline#page=407", # FY2027 chart, PDF pages 405,1779 - "https://bfa.wv.gov/media/40005/download?inline=#page=405", + "https://web.archive.org/web/20261023203756/https://bfa.wv.gov/media/40005/download?inline#page=405", ) def formula(spm_unit, period, parameters): diff --git a/source_conflicts/candidates.yaml b/source_conflicts/candidates.yaml index 48043381dea..c230d2fe659 100644 --- a/source_conflicts/candidates.yaml +++ b/source_conflicts/candidates.yaml @@ -10765,11 +10765,11 @@ candidates: citation: HHS LIHEAP FY2027 Attachment 4, Mandatory Use in LIHEAP for FY27, West Virginia, pages 3 and 6 url: https://acf.gov/sites/default/files/documents/ocs/COMM_LIHEAP_Att4SMITable_States_FY2027.pdf#page=3 - kind: manual - citation: West Virginia Income Maintenance Manual, Chapter 4 Appendix A, PDF page 406 (FY2026 chart) - url: https://bfa.wv.gov/media/39948/download?inline=#page=406 + citation: West Virginia Income Maintenance Manual, Chapter 4 Appendix A, PDF page 407 (FY2026 chart) + url: https://web.archive.org/web/20260302130424/https://bfa.wv.gov/media/39948/download?inline#page=407 - kind: manual citation: West Virginia Income Maintenance Manual, update 881, Chapter 4 Appendix A, PDF page 405 (FY2027 chart) - url: https://bfa.wv.gov/media/40005/download?inline=#page=405 + url: https://web.archive.org/web/20261023203756/https://bfa.wv.gov/media/40005/download?inline#page=405 readings: statute: Payments go only to households whose income does not exceed the greater of 150% of the poverty guideline and 60% of the state median income that HHS publishes and adjusts for household size. @@ -10786,7 +10786,9 @@ candidates: state: ruled note: 'Ruled under the 2026-10-19 statute-first rule. The PR stops each limit at the federal maximum. Printed and capped annual limits: FY2026 size 3, $47,580 and $47,575; 4, $56,640 and $56,637; 5, $65,700 and $65,698; 7, $76,464 and - $76,459; even sizes from 8, $3 lower ($81,228 and $81,225 at 8). FY2027 size 2, $40,020 and $40,019; 3, $49,440 and + $76,459; sizes 8 and 10, $3 lower ($81,228 and $81,225 at 8). From size 11 the FY2026 chart adds $688 a person, + while the PR uses 150% of the guideline, rounded by month and capped: $105,972 against the printed $105,984 at 11 + and $180,225 against $180,288 at 20. FY2027 size 2, $40,020 and $40,019; 3, $49,440 and $49,435; 6, $77,688 and $77,684; 7, $79,452 and $79,450. Other sizes keep the printed amount, which rounds down or equals the maximum. Verify each later fiscal-year chart.' @@ -10800,8 +10802,8 @@ candidates: answers, or does the manual's income test apply to every assistance group? sources: - kind: manual - citation: West Virginia Income Maintenance Manual, 21.3.1.A and 21.4.9.A, PDF pages 1725 and 1749 - url: https://bfa.wv.gov/media/39948/download?inline=#page=1725 + citation: West Virginia Income Maintenance Manual, 21.3.1.A and 21.4.9.A, PDF pages 1732 and 1756 + url: https://web.archive.org/web/20260302130424/https://bfa.wv.gov/media/39948/download?inline#page=1732 - kind: plan citation: West Virginia FY2026 LIHEAP State Plan, item 1.4, page 5 url: https://liheapch.acf.gov/docs/2026/state-plans/WV_Plan_2026.pdf#page=5 @@ -10833,12 +10835,12 @@ candidates: 2.5? sources: - kind: manual - citation: West Virginia Income Maintenance Manual, 21.3.1.A and 21.4.11.B, PDF pages 1725-1728 and 1754-1755 - url: https://bfa.wv.gov/media/39948/download?inline=#page=1725 + citation: West Virginia Income Maintenance Manual, 21.3.1.A and 21.4.11.B, PDF pages 1732-1735 and 1761-1762 + url: https://web.archive.org/web/20260302130424/https://bfa.wv.gov/media/39948/download?inline#page=1732 - kind: manual citation: West Virginia Income Maintenance Manual, update 881, 21.3.1.A and 21.4.11.B, PDF pages 1726-1729 and 1757-1758 - url: https://bfa.wv.gov/media/40005/download?inline=#page=1726 + url: https://web.archive.org/web/20261023203756/https://bfa.wv.gov/media/40005/download?inline#page=1726 - kind: plan citation: West Virginia FY2026 LIHEAP State Plan, items 1.9 and 2.5, pages 6-7 and 11 url: https://liheapch.acf.gov/docs/2026/state-plans/WV_Plan_2026.pdf#page=6 @@ -10874,11 +10876,11 @@ candidates: plan's unchecked box read, or only VA Aid and Attendance payments, as both manual editions read? sources: - kind: manual - citation: West Virginia Income Maintenance Manual, 21.3.1.A.5, PDF page 1728 - url: https://bfa.wv.gov/media/39948/download?inline=#page=1728 + citation: West Virginia Income Maintenance Manual, 21.3.1.A.4, PDF pages 1734-1735 + url: https://web.archive.org/web/20260302130424/https://bfa.wv.gov/media/39948/download?inline#page=1734 - kind: manual citation: West Virginia Income Maintenance Manual, update 881, 21.3.1.A.5, PDF page 1729 - url: https://bfa.wv.gov/media/40005/download?inline=#page=1729 + url: https://web.archive.org/web/20261023203756/https://bfa.wv.gov/media/40005/download?inline#page=1729 - kind: agency-practice citation: West Virginia Department of Human Services announcement, December 18, 2025 url: https://dohs.wv.gov/article/west-virginia-department-human-services-announces-automatic-lieap-application-mailing-low From 8f5702ae6613d3eb59dc46afedda328c76ccd0b6 Mon Sep 17 00:00:00 2001 From: Ziming Date: Thu, 5 Nov 2026 13:20:42 -0500 Subject: [PATCH 7/7] Replace removed West Virginia manual links on main's other references The Bureau for Family Assistance also removed the manual files that WV WORKS, Medicaid, one register backlog entry and three dead-URL replacement values cite. Each now names a Wayback capture, and each page anchor was read in that capture. No formula, parameter value or test expectation changes. Co-Authored-By: Claude Opus 5.5 --- .../senior_or_disabled/covers_non_ssi_recipients.yaml | 2 +- .../income/limit/requires_income_below_limit.yaml | 2 +- .../income/limit/uses_ssi_federal_benefit_rate.yaml | 2 +- .../wv/dhhr/works/income/child_support_disregard.yaml | 2 +- .../wv/dhhr/works/income/earned_income_disregard/rate.yaml | 2 +- .../wv/dhhr/works/income/standard_of_need/amount.yaml | 4 ++-- .../gov/states/wv/dhhr/works/max_household_size.yaml | 2 +- .../gov/states/wv/dhhr/works/payment_standard/amount.yaml | 2 +- .../gov/states/wv/dhhr/works/resources/limit.yaml | 2 +- .../code_health/known_dead_reference_urls/midatlantic.toml | 6 +++--- .../wv/dhhr/works/eligibility/wv_works_income_eligible.py | 2 +- .../works/income/earned/wv_works_countable_earned_income.py | 2 +- .../income/unearned/wv_works_countable_unearned_income.py | 2 +- .../wv/dhhr/works/income/wv_works_countable_income.py | 2 +- .../variables/gov/states/wv/dhhr/works/wv_works.py | 2 +- source_conflicts/candidates.yaml | 4 ++-- 16 files changed, 20 insertions(+), 20 deletions(-) diff --git a/policyengine_us/parameters/gov/hhs/medicaid/eligibility/categories/senior_or_disabled/covers_non_ssi_recipients.yaml b/policyengine_us/parameters/gov/hhs/medicaid/eligibility/categories/senior_or_disabled/covers_non_ssi_recipients.yaml index c3b74216bf2..6594bdf9bc5 100644 --- a/policyengine_us/parameters/gov/hhs/medicaid/eligibility/categories/senior_or_disabled/covers_non_ssi_recipients.yaml +++ b/policyengine_us/parameters/gov/hhs/medicaid/eligibility/categories/senior_or_disabled/covers_non_ssi_recipients.yaml @@ -55,7 +55,7 @@ metadata: - title: Wyoming Medicaid Eligibility Online Manual M1005 - SSI and SSI Related href: https://ecom.wyo.gov/m1000-aged-blind-or-disabled-program/m1005-ssi-and-ssi-related - title: West Virginia Income Maintenance Manual 23.11.4 - SSI-Related/Non-Cash Assistance (October 5, 2026 edition) - href: https://bfa.wv.gov/media/40005/download?inline#page=1889 + href: https://web.archive.org/web/20261023203756/https://bfa.wv.gov/media/40005/download?inline#page=1889 AK: 2018-01-01: true diff --git a/policyengine_us/parameters/gov/hhs/medicaid/eligibility/categories/senior_or_disabled/income/limit/requires_income_below_limit.yaml b/policyengine_us/parameters/gov/hhs/medicaid/eligibility/categories/senior_or_disabled/income/limit/requires_income_below_limit.yaml index ca59754fbae..0b52c10f083 100644 --- a/policyengine_us/parameters/gov/hhs/medicaid/eligibility/categories/senior_or_disabled/income/limit/requires_income_below_limit.yaml +++ b/policyengine_us/parameters/gov/hhs/medicaid/eligibility/categories/senior_or_disabled/income/limit/requires_income_below_limit.yaml @@ -25,7 +25,7 @@ metadata: - title: "North Dakota Administrative Code 75-02-02.1-40(1)(a)(2) (the income level \"which establishes supplemental security income eligibility\") and 75-02-02.1-41.1 (recipient liability is net income \"remaining after\" the Medicaid income level) #page 89,93" href: https://www.ndlegis.gov/information/acdata/pdf/75-02-02.1.pdf#page=89 - title: West Virginia Income Maintenance Manual § 4.14.3 Step 5 - SSI-Related income eligibility ("equal to or less than the appropriate SSI Maximum Payment Level") - href: https://bfa.wv.gov/media/40005/download?inline#page=662 + href: https://web.archive.org/web/20261023203756/https://bfa.wv.gov/media/40005/download?inline#page=662 - title: West Virginia Income Maintenance Manual (archived) § 10.23.C Step 5 - SSI-Related income eligibility (rev. 5/13) href: https://www.wvdhhr.org/bcf/policy/imm/new_manual/immanual/manual_pdf_files/chapter_10/ch10_23.pdf#page=4 - title: 42 U.S. Code § 1382(a)(1)(A) and (2)(A) - SSI eligible individual (income "at a rate of not more than" the benefit rate) diff --git a/policyengine_us/parameters/gov/hhs/medicaid/eligibility/categories/senior_or_disabled/income/limit/uses_ssi_federal_benefit_rate.yaml b/policyengine_us/parameters/gov/hhs/medicaid/eligibility/categories/senior_or_disabled/income/limit/uses_ssi_federal_benefit_rate.yaml index ee4ac8b5f37..1c73997359a 100644 --- a/policyengine_us/parameters/gov/hhs/medicaid/eligibility/categories/senior_or_disabled/income/limit/uses_ssi_federal_benefit_rate.yaml +++ b/policyengine_us/parameters/gov/hhs/medicaid/eligibility/categories/senior_or_disabled/income/limit/uses_ssi_federal_benefit_rate.yaml @@ -41,7 +41,7 @@ metadata: - title: Washington Administrative Code 182-512-0100(2)(a) - SSI-related categorically needy medical eligibility href: https://app.leg.wa.gov/wac/default.aspx?cite=182-512-0100 - title: "West Virginia Income Maintenance Manual, Chapter 4 Appendix A (SSI Max), § 23.9 (SSI Related/Non-Cash Assistance, optional categorically needy) and § 23.11.4 SSI-Related/Non-Cash Assistance #page 405,1859,1889" - href: https://bfa.wv.gov/media/40005/download?inline#page=405 + href: https://web.archive.org/web/20261023203756/https://bfa.wv.gov/media/40005/download?inline#page=405 - title: West Virginia Income Maintenance Manual (archived), § 16.7.H SSI-Related/Non-Cash Assistance (rev. 10/13) href: https://www.wvdhhr.org/bcf/policy/imm/new_manual/immanual/manual_pdf_files/chapter_16/ch16_7.pdf#page=8 diff --git a/policyengine_us/parameters/gov/states/wv/dhhr/works/income/child_support_disregard.yaml b/policyengine_us/parameters/gov/states/wv/dhhr/works/income/child_support_disregard.yaml index 6efb1fbb176..ae93fee2413 100644 --- a/policyengine_us/parameters/gov/states/wv/dhhr/works/income/child_support_disregard.yaml +++ b/policyengine_us/parameters/gov/states/wv/dhhr/works/income/child_support_disregard.yaml @@ -8,7 +8,7 @@ metadata: label: West Virginia Works child support disregard reference: - title: WV Income Maintenance Manual Chapter 4 Section 4.5.2.B - href: https://bfa.wv.gov/media/40005/download?inline#page=590 + href: https://web.archive.org/web/20261023203756/https://bfa.wv.gov/media/40005/download?inline#page=590 brackets: - threshold: diff --git a/policyengine_us/parameters/gov/states/wv/dhhr/works/income/earned_income_disregard/rate.yaml b/policyengine_us/parameters/gov/states/wv/dhhr/works/income/earned_income_disregard/rate.yaml index dce67a5704e..786a351fd7e 100644 --- a/policyengine_us/parameters/gov/states/wv/dhhr/works/income/earned_income_disregard/rate.yaml +++ b/policyengine_us/parameters/gov/states/wv/dhhr/works/income/earned_income_disregard/rate.yaml @@ -9,4 +9,4 @@ metadata: label: West Virginia Works earned income disregard rate reference: - title: WV Income Maintenance Manual Chapter 4 Section 4.5.2.A.1 - href: https://bfa.wv.gov/media/40005/download?inline#page=590 + href: https://web.archive.org/web/20261023203756/https://bfa.wv.gov/media/40005/download?inline#page=590 diff --git a/policyengine_us/parameters/gov/states/wv/dhhr/works/income/standard_of_need/amount.yaml b/policyengine_us/parameters/gov/states/wv/dhhr/works/income/standard_of_need/amount.yaml index 8fc58296462..2bf21259a83 100644 --- a/policyengine_us/parameters/gov/states/wv/dhhr/works/income/standard_of_need/amount.yaml +++ b/policyengine_us/parameters/gov/states/wv/dhhr/works/income/standard_of_need/amount.yaml @@ -11,9 +11,9 @@ metadata: label: West Virginia Works standard of need amount reference: - title: WV Income Maintenance Manual Chapter 10, Appendix A - href: https://bfa.wv.gov/media/40005/download?inline#page=405 + href: https://web.archive.org/web/20261023203756/https://bfa.wv.gov/media/40005/download?inline#page=405 - title: WV Income Maintenance Manual Appendix A Income limit(2024) - href: https://bfa.wv.gov/media/40005/download?inline#page=405 + href: https://web.archive.org/web/20261023203756/https://bfa.wv.gov/media/40005/download?inline#page=405 1: 2017-01-01: 581 diff --git a/policyengine_us/parameters/gov/states/wv/dhhr/works/max_household_size.yaml b/policyengine_us/parameters/gov/states/wv/dhhr/works/max_household_size.yaml index 4db112544e2..5bbf0f59268 100644 --- a/policyengine_us/parameters/gov/states/wv/dhhr/works/max_household_size.yaml +++ b/policyengine_us/parameters/gov/states/wv/dhhr/works/max_household_size.yaml @@ -9,4 +9,4 @@ metadata: label: West Virginia Works maximum household size reference: - title: WV Income Maintenance Manual Appendix A Income Limits(2024) - href: https://bfa.wv.gov/media/40005/download?inline#page=405 + href: https://web.archive.org/web/20261023203756/https://bfa.wv.gov/media/40005/download?inline#page=405 diff --git a/policyengine_us/parameters/gov/states/wv/dhhr/works/payment_standard/amount.yaml b/policyengine_us/parameters/gov/states/wv/dhhr/works/payment_standard/amount.yaml index 2c361447081..e1d2b282aea 100644 --- a/policyengine_us/parameters/gov/states/wv/dhhr/works/payment_standard/amount.yaml +++ b/policyengine_us/parameters/gov/states/wv/dhhr/works/payment_standard/amount.yaml @@ -11,7 +11,7 @@ metadata: label: West Virginia Works payment standard amount reference: - title: WV Income Maintenance Manual Appendix A Income Limit (2024) - href: https://bfa.wv.gov/media/40005/download?inline#page=405 + href: https://web.archive.org/web/20261023203756/https://bfa.wv.gov/media/40005/download?inline#page=405 1: 2017-06-01: 262 diff --git a/policyengine_us/parameters/gov/states/wv/dhhr/works/resources/limit.yaml b/policyengine_us/parameters/gov/states/wv/dhhr/works/resources/limit.yaml index cd5522b2dcb..f09cbe93f89 100644 --- a/policyengine_us/parameters/gov/states/wv/dhhr/works/resources/limit.yaml +++ b/policyengine_us/parameters/gov/states/wv/dhhr/works/resources/limit.yaml @@ -9,4 +9,4 @@ metadata: label: West Virginia Works resource limit reference: - title: WV Income Maintenance Manual Chapter 11.3 - href: https://bfa.wv.gov/media/40005/download?inline#page=746 + href: https://web.archive.org/web/20261023203756/https://bfa.wv.gov/media/40005/download?inline#page=746 diff --git a/policyengine_us/tests/code_health/known_dead_reference_urls/midatlantic.toml b/policyengine_us/tests/code_health/known_dead_reference_urls/midatlantic.toml index 3e017c9c33f..8ab016b9cb7 100644 --- a/policyengine_us/tests/code_health/known_dead_reference_urls/midatlantic.toml +++ b/policyengine_us/tests/code_health/known_dead_reference_urls/midatlantic.toml @@ -6,7 +6,7 @@ [[dead]] prefix = "https://bfa.wv.gov/media/2766/download?inline" verified = "2026-10-01" -replacement = "https://bfa.wv.gov/media/40005/download?inline" +replacement = "https://web.archive.org/web/20261023203756/https://bfa.wv.gov/media/40005/download?inline" [[dead]] prefix = "https://data.virginia.gov/dataset/general-child-care-subsidy-program-maximum-reimbursement-rates" @@ -21,12 +21,12 @@ replacement = "https://web.archive.org/web/20161226193813/https://dhhr.wv.gov/bc [[dead]] prefix = "https://dhhr.wv.gov/bcf/Services/familyassistance/Documents/744/ch10_apa.pdf" verified = "2026-10-01" -replacement = "https://bfa.wv.gov/media/40005/download?inline" +replacement = "https://web.archive.org/web/20261023203756/https://bfa.wv.gov/media/40005/download?inline" [[dead]] prefix = "https://dhhr.wv.gov/bcf/Services/familyassistance/PolicyManual/Documents/Chapter%2011/ch11_3.pdf" verified = "2026-10-01" -replacement = "https://bfa.wv.gov/media/40005/download?inline" +replacement = "https://web.archive.org/web/20261023203756/https://bfa.wv.gov/media/40005/download?inline" [[dead]] prefix = "https://dhss.delaware.gov/dss/childcr/" diff --git a/policyengine_us/variables/gov/states/wv/dhhr/works/eligibility/wv_works_income_eligible.py b/policyengine_us/variables/gov/states/wv/dhhr/works/eligibility/wv_works_income_eligible.py index fa7f6129205..b36c79993d7 100644 --- a/policyengine_us/variables/gov/states/wv/dhhr/works/eligibility/wv_works_income_eligible.py +++ b/policyengine_us/variables/gov/states/wv/dhhr/works/eligibility/wv_works_income_eligible.py @@ -6,7 +6,7 @@ class wv_works_income_eligible(Variable): entity = SPMUnit label = "West Virginia WV Works income eligible" definition_period = MONTH - reference = "https://bfa.wv.gov/media/40005/download?inline#page=593" + reference = "https://web.archive.org/web/20261023203756/https://bfa.wv.gov/media/40005/download?inline#page=593" defined_for = StateCode.WV def formula(spm_unit, period, parameters): diff --git a/policyengine_us/variables/gov/states/wv/dhhr/works/income/earned/wv_works_countable_earned_income.py b/policyengine_us/variables/gov/states/wv/dhhr/works/income/earned/wv_works_countable_earned_income.py index 3276fb14015..3494a11287b 100644 --- a/policyengine_us/variables/gov/states/wv/dhhr/works/income/earned/wv_works_countable_earned_income.py +++ b/policyengine_us/variables/gov/states/wv/dhhr/works/income/earned/wv_works_countable_earned_income.py @@ -7,7 +7,7 @@ class wv_works_countable_earned_income(Variable): label = "West Virginia WV Works countable earned income" unit = USD definition_period = MONTH - reference = "https://bfa.wv.gov/media/39948/download?inline#page=590" + reference = "https://web.archive.org/web/20260302130424/https://bfa.wv.gov/media/39948/download?inline#page=590" defined_for = StateCode.WV def formula(spm_unit, period, parameters): diff --git a/policyengine_us/variables/gov/states/wv/dhhr/works/income/unearned/wv_works_countable_unearned_income.py b/policyengine_us/variables/gov/states/wv/dhhr/works/income/unearned/wv_works_countable_unearned_income.py index b2eb5c7d7a7..8951527e16f 100644 --- a/policyengine_us/variables/gov/states/wv/dhhr/works/income/unearned/wv_works_countable_unearned_income.py +++ b/policyengine_us/variables/gov/states/wv/dhhr/works/income/unearned/wv_works_countable_unearned_income.py @@ -7,7 +7,7 @@ class wv_works_countable_unearned_income(Variable): label = "West Virginia WV Works countable unearned income" unit = USD definition_period = MONTH - reference = "https://bfa.wv.gov/media/40005/download?inline#page=590" + reference = "https://web.archive.org/web/20261023203756/https://bfa.wv.gov/media/40005/download?inline#page=590" defined_for = StateCode.WV def formula(spm_unit, period, parameters): diff --git a/policyengine_us/variables/gov/states/wv/dhhr/works/income/wv_works_countable_income.py b/policyengine_us/variables/gov/states/wv/dhhr/works/income/wv_works_countable_income.py index 8fb386f4947..1a0b79792d6 100644 --- a/policyengine_us/variables/gov/states/wv/dhhr/works/income/wv_works_countable_income.py +++ b/policyengine_us/variables/gov/states/wv/dhhr/works/income/wv_works_countable_income.py @@ -7,7 +7,7 @@ class wv_works_countable_income(Variable): label = "West Virginia WV Works countable income" unit = USD definition_period = MONTH - reference = "https://bfa.wv.gov/media/40005/download?inline#page=593" + reference = "https://web.archive.org/web/20261023203756/https://bfa.wv.gov/media/40005/download?inline#page=593" defined_for = StateCode.WV # Step 7: Add together the total countable earned and unearned income diff --git a/policyengine_us/variables/gov/states/wv/dhhr/works/wv_works.py b/policyengine_us/variables/gov/states/wv/dhhr/works/wv_works.py index 6a7a6d92c34..5e6cda75ef5 100644 --- a/policyengine_us/variables/gov/states/wv/dhhr/works/wv_works.py +++ b/policyengine_us/variables/gov/states/wv/dhhr/works/wv_works.py @@ -7,7 +7,7 @@ class wv_works(Variable): label = "West Virginia WV Works benefit" unit = USD definition_period = MONTH - reference = "https://bfa.wv.gov/media/40005/download?inline#page=593" + reference = "https://web.archive.org/web/20261023203756/https://bfa.wv.gov/media/40005/download?inline#page=593" defined_for = "wv_works_eligible" def formula(spm_unit, period, parameters): diff --git a/source_conflicts/candidates.yaml b/source_conflicts/candidates.yaml index df55b203eaa..877eef77293 100644 --- a/source_conflicts/candidates.yaml +++ b/source_conflicts/candidates.yaml @@ -11350,10 +11350,10 @@ candidates: url: https://www.ecfr.gov/current/title-42/section-435.210 - kind: manual citation: West Virginia Income Maintenance Manual § 23.11.4 (consolidated PDF built 2026-10-05, PDF p.1889) - url: https://bfa.wv.gov/media/40005/download?inline#page=1889 + url: https://web.archive.org/web/20261023203756/https://bfa.wv.gov/media/40005/download?inline#page=1889 - kind: manual citation: West Virginia Income Maintenance Manual § 4.14.3 Step 5 (PDF p.662) - url: https://bfa.wv.gov/media/40005/download?inline#page=662 + url: https://web.archive.org/web/20261023203756/https://bfa.wv.gov/media/40005/download?inline#page=662 readings: statute: The optional group covers people who meet SSI's income requirement, which admits income at or below the benefit rate.