Skip to content

Add Nebraska LIHEAP regular cooling assistance - #10758

Open
hua7450 wants to merge 19 commits into
mainfrom
ne-liheap-cooling
Open

hua7450 wants to merge 19 commits into
mainfrom
ne-liheap-cooling

Conversation

@hua7450

@hua7450 hua7450 commented Nov 9, 2026 •

Copy link
Copy Markdown
Collaborator

Adds Nebraska's Cooling Assistance payment from the 2026 cooling table, by income tier and dwelling type, for households with a qualifying member.

Fixes #10757

Builds on the national LIHEAP total from #10730, merged on 2026-11-12: this PR adds ne_liheap_cooling to gov.hhs.liheap.regular_payments.

What and why

476 NAC 2-003 requires a qualifying member: someone 70 or older, a child under 6 in a household receiving ADC, someone with a medical condition heat aggravates, or someone who got a state air conditioner in the last four years. The 2026 cooling table pays single-family homes $700, $595, $525 or $478 and multifamily homes $385, $335, $300 or $273, by income tier (tops 70%, 100%, 130% and 150% of the guideline); "between two income levels, use the row with the higher amount". Income uses heating's test and 20% earned-income disregard (Guidance Document, pp. 2-3). The season runs June 1 through August 31 (476 NAC 1-004.04), and DHHS pays "one time per cooling season" (Energy Assistance page).

  • New ne_liheap_payment_fpg_ratio holds heating's income-ratio calculation, now shared. Every existing heating boundary lands in the same tier.
  • ne_liheap_cooling_eligible: heating's income test; has_cooling_expense, or utilities in the rent of an unsubsidized renter (tenant_pays_utilities false with positive rent, and neither receives_housing_assistance nor is_in_public_housing); and a member 70 or older, or a child under 6 in a unit with positive tanf. The qualifying member must pass the SNAP citizenship rule (476 NAC 2-002.02).
  • ne_liheap_cooling: the single-family or multifamily table, chosen by ne_liheap_dwelling_type. New parameters under cooling/.
  • 2027 is verified: the Guidance Document effective October 1, 2026 prints the same cooling table on the 2026 guidelines (p. 4), and the parameters now cite it. verified_years is "2026-2027". FY2027 plan item 3.5 (p. 12) makes the table subject to update closer to the cooling season based on funding.
  • Cooling adds no heating-fuel condition: the cooling table has no fuel column, so every heating_type, including NONE and UNSPECIFIED, can be paid (Nebraska heating likewise pays a multi-family home whatever its fuel).
  • Renters with utilities in the rent: plan item 3.3 (p. 11) repeats item 2.3's (p. 9) heating sentence, and 476 NAC 3-002.02 lets DHHS pay a household directly "if utilities are included in rent" for cooling as for heating. Cooling reads it as ne_liheap_eligible reads item 2.3, with the same subsidy test: an unsubsidized renter with utilities in the rent qualifies, and a household with housing assistance or in public housing needs its own cooling cost. The project lead set this on 2026-11-13, replacing the 2026-11-09 $0 treatment.

Test plan

Tests were not run locally. This PR now targets main, so CI runs them.

  • YAML tests with expected values worked from the sources above. 24 cases in 3 files (14, 6 and 4): each tier and dwelling type at the tier edges, each qualifying route, the citizenship rule on both routes, the shared ratio, no cooling cost, no heating and UNSPECIFIED fuel (both paid), renters with utilities in the rent (unsubsidized, subsidized, rent-free) and a renter who pays her own utilities, and the national liheap total.
  • Source-conflict register: not applicable; cooling reads plan item 3.3 as heating reads item 2.3, and no source contradicts that reading.
  • make format (ruff)
  • Changelog fragment in changelog.d/

Not modeled

  • The heat-aggravated medical condition and the four-year air-conditioner routes have no input, so they pay $0. Disability is not used in their place: 476 NAC 2-003 has no disability route.
  • Later years carry the FY2027 table forward.
  • ADC receipt is known only for the whole unit, so a child under 6 in a unit that receives ADC qualifies even if that child is outside the grant.
  • has_cooling_expense is a PolicyEngine convention of the all-state cooling work. 476 NAC 2-003 names no air conditioner or separate cooling cost, and plan item 8.3 (p. 22) describes a cooling mass run for current cases, so a household with no reported cooling cost and no utilities in the rent can be paid by Nebraska but gets $0 here.

axiom: TheAxiomFoundation/rulespec-us#2189 queued

🤖 Generated with Claude Code

hua7450 and others added 13 commits November 8, 2026 22:01
Sum each state's regular LIHEAP payment in a new liheap variable, add an
Illinois regular heating payment without crisis assistance, add a Michigan
Home Heating Credit registry entry, and record each state's cooling
treatment in its registry note.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add regular_payments.yaml to the aggregate-list integrity test, which checks
that each member exists, is state-gated and is not dropped between year
blocks. Say that Rhode Island plans no regular cooling payment, since its
FY2027 plan still allows a leftover-funds cooling grant.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Points the eligibility reference at its first cited page, adds the DHHS
energy assistance page, describes the guideline lag by federal fiscal
year, and checks the national liheap total.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The national `liheap` total evaluates every state's formula over a
mixed-state population, which no household test does. Two patterns on main
raised errors there:

- 26 formula files passed options=[ADD] to an entity call. Core's
  Microsimulation.calculate_add rejects the keyword an entity call passes.
  The option is redundant: a plain read already sums a monthly variable over
  the year through the same Core function.
- The DC and Illinois payment formulas look up a matrix by an income level
  that is 0 for households outside the state. Add the floor Maryland and
  Kansas already use.

Also:
- Reword the North Dakota registry note: the state reserves an optional
  direct cooling payment, so its cooling component is not only equipment.
- Add a `liheap` case with Texas, DC and Illinois households in one
  simulation.
- Add a code-health check against options=[ADD] and options=[DIVIDE].
- Check that every state payment in the LIHEAP registry entry is in the
  list `liheap` sums.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
PolicyEngine/policyengine-core#647 fixes the cause in Core: it lets a
Microsimulation accept the keyword an entity call passes with
options=[ADD] or options=[DIVIDE]. Once that is released the option works
again, so a check that bans it here would be wrong. The 26 formula files
stay without the option, which was redundant and lets `liheap` run on
today's Core.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ogram prefix

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Base automatically changed from liheap-aggregate to main November 12, 2026 19:06
hua7450 and others added 2 commits November 12, 2026 14:08
PR 10730 was squash-merged into main as f67bb1e, so this merge uses its
final head 4625f4e, already merged here, as the merge base.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@DTrim99

DTrim99 commented Nov 12, 2026

Copy link
Copy Markdown
Collaborator

PR Review: Add Nebraska LIHEAP regular cooling assistance

Summary

This PR adds Nebraska's Cooling Assistance payment (ne_liheap_cooling) and its eligibility flag, moves heating's income-ratio calculation into a shared ne_liheap_payment_fpg_ratio, and adds the cooling payment to the national liheap list. The core of it is right:

  • The cooling table matches both Guidance Documents cell by cell.
  • Tiers, the 20% earned-income disregard, the six-person band cap, the one-year guideline lag and the program-year dating all match the sources.
  • The heating refactor returns exactly what main returns.
  • Nebraska pays heating and cooling to the same household in one program year, so listing both payments in regular_payments is not a double count.

Three things need changing before approval:

  1. The UNSPECIFIED-fuel gate blocks cooling for households that Nebraska's own heating formula pays, and the body says the opposite.
  2. Renters whose cooling is in the rent get $0. That reads the plan's renter sentence the opposite way from how the heating variable reads the identical sentence, and the choice isn't recorded.
  3. One citizenship term has no test that pins it.

CI is green (36 of 36). The branch merges cleanly with main and with each of the eight siblings.

Critical (must fix)

None.

Should address

1. The UNSPECIFIED-fuel gate excludes households that Nebraska's heating formula pays, and "as in every state LIHEAP program" is not accurate for Nebraska

Where: policyengine_us/variables/gov/states/ne/dhhs/liheap/cooling/ne_liheap_cooling_eligible.py lines 42-46 and 50, and ne_liheap_cooling.yaml Case 5 (line 99).

The cooling payment does not depend on heating fuel:

Nebraska's own heating formula pays an unspecified fuel when the home is multi-family:

  • ne_liheap.py lines 34-37 put multifamily first in the select, ahead of every fuel test.
  • On main, integration.yaml Case 7 (line 176) pins ne_liheap: 300 for a multi-family heat-in-rent renter with heating_type: UNSPECIFIED.
  • The heating_type enum documentation says UNSPECIFIED "is also the right value when heat is included in rent and the fuel is unknown".

The body's sentence "heating_type UNSPECIFIED pays $0, as in every state LIHEAP program" is therefore contradicted by Nebraska's own heating variable and its test. The queued rulespec-us issue says this more accurately (item 7: "No Nebraska source states this rule").

Household:

  • Inputs: one person aged 72 with $1,200 a month of Social Security ($14,400). She lives in an apartment (ne_liheap_dwelling_type: MULTI_FAMILY) with heat in the rent (heat_expense_included_in_rent: true, heating_type: UNSPECIFIED). She pays her own electric bill for a window air conditioner (has_cooling_expense: true) and gets no housing assistance.
  • Tier: 14,400 / 15,650 = 0.920, which is tier 2.
  • Heating: ne_liheap = $300, the same as integration Case 7.
  • Cooling expected: multi-family tier 2, $335.
  • Cooling actual, by hand trace: fuel_reported is false at line 46, so ne_liheap_cooling_eligible is false and ne_liheap_cooling is $0.

Fix: drop fuel_reported, since the amount never depends on fuel. At a minimum, let it pass wherever heating would pay, for example fuel_reported | multifamily | heat_expense_included_in_rent. Then update Case 5's UNSPECIFIED expectation, add the household above as a case, and correct the body sentence. If the gate stays as a deliberate cross-state convention, call it a PolicyEngine convention and say that Nebraska heating pays multi-family homes with an unspecified fuel.

2. Renters with cooling in the rent get $0, the opposite of the heating variable's reading of the same plan sentence, and the choice isn't recorded

Where: ne_liheap_cooling_eligible.py lines 37-41 and 49, and the last "Not modeled" bullet in the body.

The two plan sentences are the same:

  • FY2026 plan item 3.3, p. 11, cooling: "For renters with utilities included in rent, the household must be responsible for a portion of the cooling utilities."
  • Item 2.3, p. 9, heating: "For renters with utilities included in the rent, the household must be responsible for a portion of the heating."

ne_liheap_eligible.py (lines 26-43 at the head) reads the heating sentence as satisfied by a market-rate renter with heat in the rent: "Market-rate renters with heating paid through rent are treated as responsible even when the separately reported expense is zero: 476 NAC 3-002.02 lets the Department pay a household directly 'if utilities are included in rent'." Its code is responsible = pays_heating_bill | (heat_in_rent & ~subsidized).

That reading carries over to cooling:

  • 476 NAC 3-002.02, p. 1 ("Only if utilities are included in rent ... may the Department pay a household directly") covers every payment type in 3-001, including "(B) Cooling".
  • FY2026 plan item 1.1, p. 5 lists, among the cases where a supplemental payment for households "that received heating assistance or ... cooling assistance" goes to the household: "An economically vulnerable household's utilities are included in rent."

The PR instead requires has_cooling_expense, which the variable defines as cooling costs "separately from its rent or mortgage". That excludes every renter whose cooling is in the rent, market-rate or subsidized.

The line 40 comment says "Cooling paid only through rent has no existing input". The facts the heating test uses for this case do exist: heat_expense_included_in_rent, receives_housing_assistance and is_in_public_housing, and tenant_pays_utilities for utilities generally.

The body says "Source-conflict register: not applicable". The rulespec-us issue calls this $0 "a settled modeling decision", but nothing in the PR records who settled it.

Household:

  • Inputs: the same 72-year-old in an apartment, with all utilities in the rent (heat_expense_included_in_rent: true, heating_type: ELECTRICITY, has_cooling_expense: false), market rate.
  • Heating: ne_liheap = $300, because heat is in the rent and she isn't subsidized (ne_liheap_eligible.py line 43).
  • Cooling actual: $0 (line 49).
  • Cooling expected under the heating variable's reading of the identical sentence: multi-family tier 2, $335.

Fix, either:

  • (a) mirror heating, for example has_cooling_expense | (utilities in rent & ~subsidized), and add a test; or
  • (b) keep the $0 but record the choice, as a source-conflict candidate or a ruling in this thread. Then reword the body so it doesn't say plan 3.3 requires $0, and say why cooling departs from heating's reading.

3. Mutation gap: the citizenship term on the young-child route has no test

Where: ne_liheap_cooling_eligible.py line 34 (included & (age < p.adc_child_age_limit)).

ne_liheap_cooling_eligible.yaml Case 5 pins included only on the age-70 route (line 36). By my reading, no case in the three files changes if included & is deleted from line 34.

476 NAC 2-002.02, p. 1 says: "A person who does not meet the citizenship and residency requirements must be excluded from a household for purposes of determining eligibility."

Household:

  • Inputs: a mother aged 28 receiving ADC (tanf: 5_920) with a citizen child aged 8 and an undocumented child aged 4 (immigration_status: UNDOCUMENTED).
  • Expected: ne_liheap_cooling_eligible false, because the only child under 6 is excluded.
  • Without the term: true.

Fix: add this case to ne_liheap_cooling_eligible.yaml.

Suggestions

  1. Cooling cost for every household. 476 NAC 2-003 has no equipment requirement. 476 NAC 2-005.02 (p. 4) says: "To qualify for assistance to purchase a window air conditioning unit, the household must be eligible for cooling assistance". So a household with no air conditioner can be cooling-eligible. Plan item 8.3, p. 22 also describes a "mass run" that determines cooling eligibility for households with a current application. The body labels has_cooling_expense as the shared all-state input, which is fine as a convention. Add a "Not modeled" line saying that a household with an electric account but no reported cooling cost is paid by Nebraska and gets $0 here.

  2. Funding contingency and the FY2027 table. Two plan passages make the FY2027 table less certain than "verified" suggests:

    • Plan item 1.1 (p. 4): "The availability of the cooling assistance program and the variables used to determine eligible households will depend on the LIHEAP funding received and available for the current federal fiscal year."
    • Item 3.5 in both plans: "The LIHEAP Cooling Season Payment Table (matrix) is subject to update (closer to the cooling season) based on funding availability."

    Say in the ne_liheap_cooling documentation that FY2027 rests on the 10/01/2026 print and may be revised before June 2027. The program is funded and operated: cooling gets 18% of funds in FY2026 and 27% in FY2027 (item 1.2, p. 5 of each plan), and 13,099 households received cooling in FY2023 (HHS FY2023 Nebraska profile).

  3. Moving URL. The FY2027 references point at DHHS's undated Guidance Docs/...Guidance Document.pdf, which DHHS replaces in place each year; a FY2026 print sat at the same address in July 2026. Add an archived copy, such as a Wayback snapshot, next to it so the 2027 citation keeps opening on the 2027 table.

  4. Dwelling-type default. ne_liheap_dwelling_type defaults to SINGLE_FAMILY. For cooling, that is $700/$595/$525/$478 instead of $385/$335/$300/$273, a gap of $205 to $315 by tier. The heating dwelling-type documentation says so, but the cooling documentation and the body don't. Add one line.

  5. Reference titles. earned_income_disregard.yaml line 9 and payment_size_limit.yaml now title the reference "...Heating and Cooling Payment Computation #page 2-3". That puts page text in the title, and the single href #page=2 opens only on the heating page. Split each into two references with plain titles: #page=2 for heating and #page=3 for cooling.

  6. Size-6+ footnote and a stale comment.

    • The comment moved into ne_liheap_payment_fpg_ratio.py (lines 22-26) records that the footnote states the size-6+ tiers in "gross countable income", while the instructions apply the disregard first. That choice now decides cooling too, since page 3 has the same footnote. Consider recording it as a candidate.
    • ne_liheap_fpg.py still says "The annual period represents the heating season ending in that year". It could say "federal fiscal year (heating and cooling)", matching the re-described fpg_year_lag.

Verified correct

A separate regular cooling benefit exists in both claimed years.

  • 476 NAC 3-001 lists "(A) Heating; (B) Cooling" as separate payment types, and 476 NAC 2-003 sets the cooling test.
  • 476 NAC 1-004.04 sets the cooling season as "June 1 through August 31 of each federal fiscal year".
  • Plan item 1.1 gives 06/01/2026-08/31/2026 (FY2026, p. 4) and 06/01/2027-08/31/2027 (FY2027, p. 4).
  • The DHHS Energy Assistance page describes the cooling payment.

Heating and cooling in one year: both are paid, so there is no double count. Nothing limits cooling to households without heating help. The supporting text:

  • The DHHS page: "Payments are made one time per heating season" and, separately, "Payments are made one time per cooling season to utility providers".
  • 476 NAC 2-001.02: "An approved application provides household eligibility for the remainder of the program year." The program year (1-004.14, October 1 through September 30) contains both seasons.
  • Plan item 1.1: supplements "for LIHEAP-eligible households that received heating assistance or for LIHEAP-eligible households that received cooling assistance".
  • Plan item 8.3: a cooling mass run for households with a current case "including LIHEAP".
  • ne_liheap_cooling.yaml Case 3 pins both payments: $550 + $595 = $1,145.

Amounts and tiers.

  • Single-family $700/$595/$525/$478 and multi-family $385/$335/$300/$273 appear in both the 10/1/2025 document (p. 3) and the 10/01/2026 document (p. 4). Plan item 3.6 gives $273 to $700 in both years.
  • Tier tops are 70%, 100%, 130% and 150% of the 2025 guideline for FY2026 (one person at 100%: $15,650) and of the 2026 guideline for FY2027 ($15,960; two people $21,640 = 15,960 + 5,680).
  • The size-6+ footnotes match the six-person guideline: $30,205 = 0.7 × 43,150, $56,095 = 1.3 × 43,150, and for FY2027 $31,052 = 0.7 × 44,360.
  • "Use the row with the higher amount" means the next income row up. The footnote confirms it ("$30,205.01 through $43,150 is eligible for Tier 2"), so right=True is right.

Periods. The parameters are dated 2025-10-01 and are read on 1 January. So period 2026 is FY2026, whose cooling season is summer 2026, with the 2025 guidelines. Period 2027 uses the 2026 guidelines (gov.hhs.fpg 2026-01-01: 15,960 / 5,680). No options=[ADD]. The only MONTH read is immigration status for the first month, the same as household size.

Income test. Plan item 3.1 sets 150% of the HHS guidelines, the same as heating item 2.1 and 476 NAC 2-002.01. ne_liheap_income_eligible is reused, and it sits above the federal 110% floor.

Qualifying routes.

  • age >= 70 and age < 6 with tanf > 0. tanf sums ne_adc (tanf_if_takes_up lists "ne_adc # Nebraska Aid to Dependent Children"), so positive tanf is Nebraska ADC receipt.
  • Routes (C) and (D) have no inputs, and that is disclosed in the body, the code and programs.yaml.
  • Disability correctly does not qualify (eligibility Case 4).
  • The plan's wording "5 years and under and ADC-eligible" sits next to its own quote of the rule ("receives"); the PR follows 476 NAC 2-003(A).

Citizenship. Qualifying members must pass 476 NAC 2-002.02 through the same SNAP status variable used for household size (Case 5).

Fuel type. 476 NAC 3-003.01 lists fuel type among the payment factors, and FY2027 plan item 3.5 checks it, but neither cooling table varies by fuel. The PR follows the tables, and a home with no heating (NONE) is paid (Case 5).

Refactor.

  • ne_liheap_payment_fpg_ratio is line for line main's computation: gross minus 20% of earned income, floored at 0, divided by the guideline for clip(size, 1, 6) with the lag.
  • Its only readers are ne_liheap and ne_liheap_cooling, so ne_liheap returns main's values for every household.
  • No existing test file changed, and every heating case still passes in CI.
  • The re-described parameters are read only by Nebraska LIHEAP variables.
  • No source_conflicts record or # Source conflict marker names a Nebraska LIHEAP file. The PR does not touch candidates.yaml. The moved comment matches none of the ratchet's patterns.

National total and registry.

  • The new list line sits in the single 2023-01-01 block. It is a dollar amount on the SPM unit for the year, and it is gated through ne_liheap_cooling_eligible to StateCode.NE, which satisfies the state-gate chain check. It is not a component of ne_liheap.
  • The second Nebraska implementation in programs.yaml has a unique registry label. By my reading, test_liheap_total_sums_every_registered_state_payment finds ne_liheap_cooling in the list, and LIHEAP_PAYMENT_STAND_INS doesn't name it.
  • Case 3 fails if the list line is deleted.

Mixed-state lookups. There are no state-gated int or enum keys. The dwelling type is compared, not used as a key, and the brackets read a float ratio.

Mutation coverage, apart from Should 3. Each term has a case that fails without it:

Term Pinned by
income test cooling Case 6
has_cooling_expense cooling Case 7
fuel_reported cooling Case 5
age 70 edge eligibility Case 1
age 6 edge eligibility Case 2
ADC term eligibility Case 3
citizenship on the age-70 route eligibility Case 5
dwelling branch cooling Cases 2 and 4
each closed tier edge (right=True) cooling Cases 1 and 2
disregard cooling Case 9 and ratio Case 1
six-person cap ratio Case 2
floor at 0 ratio Case 3
FY2027 lag ratio Case 4 and cooling Case 8
list line cooling Case 3

Hygiene. Descriptions follow the template. Labels, units, periods and defined_for are present. References open on the values: the 10/1/2025 document #page=3, the 10/01/2026 document #page=4, 476 NAC 2 #page=2 and the plan #page=11/#page=12. The changelog fragment is in changelog.d/, and the test files are named after their variables.

Hand checks (2025 guideline $15,650 for one person and $21,150 for two; FY2027 $15,960):

  1. Cooling Case 1: 10,955 / 15,650 = 0.70, which is tier 1, $700. 10,955.01 is above 0.70, so $595.
  2. Cooling Case 1: 15,650 is 1.00, $595. 15,650.01 gives $525.
  3. Cooling Case 1: 20,345 is 1.30, $525. 20,345.01 gives $478. 23,475 is 1.50, $478. −100 floors to 0, $700.
  4. Cooling Case 2, multi-family: 10,955 gives $385, 10,955.01 gives $335, 15,650.01 gives $300, 20,345.01 gives $273.
  5. Cooling Case 3: 14,400 / 15,650 = 0.920, tier 2. Heating utility column $550 plus cooling $595 = $1,145.
  6. Cooling Case 4: 5,920 / 21,150 = 0.280, multi-family tier 1, $385.
  7. Cooling Case 6: 24,000 is above 1.5 × 15,650 = 23,475, so income ineligible and $0.
  8. Cooling Case 8 (2027): 14,400 / 15,960 = 0.902, tier 2, $595.
  9. Cooling Case 9: 28,800 − 0.2 × 15,600 = 25,680. 25,680 / 21,150 = 1.214, tier 3, $525. Without the disregard, 1.362 would give $478.
  10. Ratio Case 1: (17,000 − 3,400) / 15,650 = 0.86901.
  11. Ratio Case 2: 31,000 / (15,650 + 5 × 5,500) = 31,000 / 43,150 = 0.71842.
  12. Eligibility Cases 1 and 2: age 69 is false and 70 is true; a child aged 5 with ADC is true and aged 6 is false.

Axiom line assessment

axiom: TheAxiomFoundation/rulespec-us#2189 queued is valid. Issue #2189 is OPEN and labelled pe-parity, and it names this head (a3d04b54c5). It is dispatch-ready: proposed module paths, corpus citations with status, verbatim 476 NAC, Guidance and plan text, required outputs, and companion tests worked from the sources rather than from PolicyEngine output.

Two things to refresh:

  • It still says "CI has not yet run its tests at this head" and "They have not yet passed in CI at this head". All 18 cases have now passed.
  • If Should 1 or 2 changes behavior, update the ne_liheap_cooling_eligible required-outputs row, companion test 11 and items 7-8 to match.

CI status

All 36 checks pass at a3d04b54c5 (gh pr checks 10758), and none are pending. Quick Feedback ran the three new test files: 9 passed (ne_liheap_cooling.yaml), 5 passed (ne_liheap_cooling_eligible.yaml) and 4 passed (ne_liheap_payment_fpg_ratio.yaml), matching the body's 18 cases. The state shards, which hold the existing Nebraska heating tests, passed. The run's base includes main through c65b162782, after #10287 and #10730.

Branch status

The head is 12 commits behind main (cc486336d7). git merge-tree --write-tree against main reports no conflicts. Since the head's last merge, main has changed only one programs.yaml line (Hawaii) and source_conflicts/candidates.yaml; neither overlaps this PR.

Pairwise test merges with all eight siblings are clean: AR #10744, GA #10746, OK #10748, LA #10750, KY #10752, SC #10754, AL #10756 and VA #10760. This PR edits regular_payments.yaml and programs.yaml but not candidates.yaml, so it cannot conflict with the siblings there.

Verdict: REQUEST_CHANGES

@DTrim99 DTrim99 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requesting three changes; none is critical, and the core is right. The cooling table matches both Guidance Documents cell by cell, the tiers, the 20% disregard, the guideline lag and the program-year dating match the sources, the heating refactor returns exactly what main returns, and Nebraska pays heating and cooling to the same household in one program year, so the national total doesn't double count.

  1. The UNSPECIFIED gate. Nebraska's own heating formula pays a multifamily home whatever the fuel (integration.yaml Case 7 pays $300 with heating_type: UNSPECIFIED), and the cooling amount never depends on fuel. The description's "as in every state LIHEAP program" isn't accurate here. Drop the term, or let it pass wherever heating pays and label it a convention.
  2. Renters with cooling in the rent get $0. Plan item 3.3's cooling sentence is word for word the heating sentence in item 2.3, which ne_liheap_eligible reads as met by a market-rate renter with heat in the rent, and 476 NAC 3-002.02 covers cooling payments too. Mirror heating, or record the choice instead of "Source-conflict register: not applicable".
  3. The citizenship term on the young-child route has no test, by my reading. A case is sketched in the report.

Details and households are in the report above. CI is green at a3d04b54c5.

@hua7450

hua7450 commented Nov 13, 2026

Copy link
Copy Markdown
Collaborator Author

Thanks, David. This push (head a497a51822) applies the fixes in e07d4a9e60 and merges upstream main.

Should address

  1. UNSPECIFIED gate. Dropped. ne_liheap_cooling_eligible.py no longer reads heating_type; a comment notes the cooling table has no fuel column. ne_liheap_cooling.yaml Case 5 keeps its inputs and now expects [true, true] and [595, 595], with a "Was" comment. Your household is new Case 10: 72, apartment, heat in the rent, UNSPECIFIED, her own cooling bill, so heating $300 and cooling $335. The body's "as in every state LIHEAP program" sentence is gone; it now says cooling adds no heating-fuel condition and that Nebraska heating pays a multi-family home whatever its fuel. The same change is in all nine cooling PRs.

  2. Renters with cooling in the rent. Mirrored heating, your option (a). The test is now has_cooling_expense | (utilities_in_rent & ~subsidized): utilities in the rent means tenant_pays_utilities false with positive rent, and subsidized is heating's test (receives_housing_assistance | is_in_public_housing). I used tenant_pays_utilities because heat_expense_included_in_rent covers heat only; the AR, LA, KY and AL cooling PRs read the same input. The comment cites plan items 2.3 and 3.3 and 476 NAC 3-002.02. The variable now cites 476 NAC 3 (p. 1), and its plan entry covers pages 9 and 11-12. New cases in ne_liheap_cooling.yaml:

    • Case 11: your market-rate renter, paying the FY2026 Douglas County one-bedroom FMR ($1,148 a month), utilities in the rent, no cooling cost: heating $300, cooling $335.
    • Case 12: the same renter with housing assistance, then in public housing: $0 for both programs.
    • Case 13: rent-free, utilities paid by a relative: $0. This pins the rent > 0 term.
    • Case 14: pays her own utilities, no cooling cost: $0. This pins the tenant_pays_utilities term.

    The project lead adopted this reading on 2026-11-13, replacing the earlier $0 choice. The register line now says cooling reads item 3.3 as heating reads item 2.3, and the "Renters ... get $0" line under Not modeled is gone.

  3. Citizenship on the young-child route. Added your household as ne_liheap_cooling_eligible.yaml Case 6: a mother aged 28 on ADC ($5,920), a citizen child aged 8 and an undocumented child aged 4. It expects size 2, income eligible, and cooling eligible false; without included & it would be true.

Suggestions

  1. Cooling cost for every household. Applied. The formula comment calls has_cooling_expense a PolicyEngine convention of the all-state cooling work, since 476 NAC 2-003 names no air conditioner or separate cooling cost. The body's Not modeled section adds the line and cites plan item 8.3. It leaves out the electric account, because every household is assumed to hold an active energy account.
  2. Funding contingency. Applied. The ne_liheap_cooling documentation says FY2027 rests on the October 1, 2026 print, which FY2027 plan item 3.5 makes subject to update closer to the cooling season. The variable now cites that plan at #page=12, and the body's 2027 bullet says the same.
  3. Moving URL. Not added yet. The Wayback Machine's latest capture of the Guidance Docs address is from 2026-01-01, before the 10/01/2026 print was posted, so no archived copy of that print exists to cite.
  4. Dwelling-type default. Declined. Every state LIHEAP program uses the same single-family default and callers report the dwelling type, so there is no per-state note.
  5. Reference titles. Kept. The repo's reference rule is one entry per source, with the href on the first cited page and the page list in the quoted title (#page 2-3).
  6. Size-6+ footnote and stale comment. The footnote reading stays recorded in the ne_liheap_payment_fpg_ratio.py comment, with no candidate. The ne_liheap_fpg.py comment now says the period is the federal fiscal year ending that year, with its heating season and its June-August cooling season.

Axiom issue. TheAxiomFoundation/rulespec-us#2189 now points at this head. Updated: the review and CI sentences, the scope, the ne_liheap_cooling_eligible output row and inputs, test counts (24: 14, 6 and 4), companion test 11 (UNSPECIFIED now pays $595), test 10(b), new companion tests 13 to 18, and interpretations 6, 7, 8 and 13.

Tests were not run locally.

CI is running at a497a51822.

@hua7450
hua7450 requested a review from DTrim99 November 13, 2026 20:36

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement Nebraska LIHEAP regular cooling assistance

2 participants