Skip to content

Add Arkansas LIHEAP summer regular cooling assistance - #10744

Merged
hua7450 merged 20 commits into
mainfrom
ar-liheap-cooling
Nov 15, 2026
Merged

hua7450 merged 20 commits into
mainfrom
ar-liheap-cooling

Conversation

@hua7450

@hua7450 hua7450 commented Nov 9, 2026 •

Copy link
Copy Markdown
Collaborator

Adds Arkansas's summer regular LIHEAP benefit, paid from the existing Electricity matrix.

Fixes #10743

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

What and why

The adopted FFY 2025 Policy and Procedures Manual says the Regular program "is available during both winter and summer application periods" and "Only electric benefits are available during the Summer Program" (section 2.1, p. 29). It lists the "Electricity Matrix: used for both Winter and Summer Regular Assistance" (section 6.1, p. 78) and allows "one Crisis and one Regular benefit ... for each household for each season" (section 3.3, p. 46). No FY2026 manual was found. The FY2026 plan's cooling section uses the heating income limits (item 3.1) and gives a $60 to $344 range (item 3.6), exactly the range of the FY2026 Electric matrix. The FY2025 plan's item 3.6 gives $50 to $287; the posted FFY 2025 electric matrix, headed "20% OVER BASE", pays $60 to $344. Summer follows the matrix, as the winter benefit does; candidate us-ar:liheap-fy2025-benefit-matrix now lists ar_liheap_cooling and cites item 3.6.

  • ar_liheap_cooling_eligible: heating's household size and income limit, plus either has_cooling_expense with a positive electricity bill, or utilities included in unsubsidized rent. Plan item 3.3 (p. 12): "Unsubsidized households with utilities included in their rent may be eligible for LIHEAP assistance if they meet other criteria".
  • ar_liheap_cooling: the Electricity matrix cell for the household's monthly income band and size group, from the same parameters as the winter grant. The amount is fixed, not capped at the bill.
  • Three shared payment parameters now describe the "regular benefit" in place of the "regular heating benefit"; their values are unchanged.
  • The summer benefit does not depend on heating_type: every value, including NONE and UNSPECIFIED, can be paid.
  • Income limit stops at the federal maximum. ar_liheap_income_limit, which heating and cooling share, rounds each monthly chart limit to the nearest dollar. That put several annual limits a few dollars above the greater of HHS's 60% state median income amount and 150% of the poverty guideline, the most 42 U.S.C. 8624(b)(2)(B) allows. Each limit now stops there:
    • FY2026: $36,834 for two people (chart $36,840), $45,501 for three ($45,504), $73,126 for seven ($73,128), $3 lower at each even size from 8 to 20, and lower at every size from 21 up ($188,475 against $188,484 at 21; $196,725 against $196,740 at 22).
    • FY2025: $27,011 for one person (chart $27,012), $35,323 for two ($35,328), $51,946 for four ($51,948), and $6 lower at each odd size from 7 to 19. These are HHS's FY2025 amounts (LIHEAP IM 2024-02 Attachment 4).
    • Heating eligibility changes for households within those few dollars of the limit.
  • has_cooling_expense is required from bill payers. This is a PolicyEngine convention with no Arkansas source: Arkansas's energy burden is a utility bill the household receives (manual section 4.8.1). Unsubsidized renters whose utilities are included in rent need no cooling cost; they are identified by the existing tenant_pays_utilities input (false) with positive rent; no input is added.

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. 12 cases in 2 files: matrix cells by band and size, the income limit, no cooling cost, no electricity bill, unsubsidized and subsidized renters with utilities in rent, each condition of the rent route, a subsidized household with its own electric bill, UNSPECIFIED and NONE heating paid, and the national liheap total.
  • Existing heating cases that asserted a chart limit above the federal maximum now assert the capped limit (ar_liheap_income_limit.yaml, ar_liheap.yaml, integration.yaml). One existing case changes eligibility: ar_liheap_eligible.yaml Case 6 (FY2025, seven people, $71,016) is now ineligible because the capped limit is $71,010; its inputs are kept.
  • Source-conflict register: candidate us-ar:liheap-income-limit-above-federal-ceiling (ruled) records the cap; the code follows the statute. Candidate us-ar:liheap-fy2025-benefit-matrix (unreviewed) now covers the summer reader.
  • make format (ruff)
  • Changelog fragment in changelog.d/

Not modeled

  • The FY2027 plan raises the range 10% to $66-$378, but no FY2027 matrix is posted, so FY2026 values carry forward unverified.

axiom: TheAxiomFoundation/rulespec-us#2183 queued

🤖 Generated with Claude Code

hua7450 and others added 14 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>
… rent

Plan item 3.3 makes these renters eligible. Rewords the energy account
comments, adds an in-rent renter case, 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 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>
@hua7450
hua7450 requested a review from DTrim99 November 12, 2026 19:13
@DTrim99

DTrim99 commented Nov 12, 2026

Copy link
Copy Markdown
Collaborator

PR Review: Add Arkansas LIHEAP summer regular cooling assistance

Reviewed at head 086717cdcc (16 files, +456/-26). Nothing was run locally; every claim below rests on reading the code at the head, hand traces against the printed tables, and the CI logs, and says which.

Summary

The cooling payment itself is right. Arkansas pays one Regular benefit in winter and one in summer, the summer benefit is electric only, and it comes from the same Electricity matrix as electric heat. The two new variables read the right cells for FY2025 and FY2026, the national total can sum both seasons, and the new test files pass in CI.

The income-limit cap is also right in its arithmetic. Every figure in the body matches HHS's published Arkansas amounts for FY2025 and FY2026 and 150% of the guideline, and the change follows the pattern already on main for West Virginia and Oregon.

What blocks approval:

  • One real CI failure caused by this PR. An existing heating test that the PR did not update still expects the old FY2025 seven-person limit. The body's statement that no case changes eligibility is therefore wrong.
  • An unrecorded FY2025 source conflict. The FY2025 plan gives a cooling range of $50 to $287; the PR pays $60 to $344 from the posted matrix.
  • A cooling-cost requirement with no Arkansas source, presented in comments as the state's energy-burden rule.
  • Three terms of the rent route that no test pins.

Counts: 1 critical, 3 should, 5 suggestions.

Critical (must fix)

1. CI fails on an existing heating test the cap changes: ar_liheap_eligible.yaml Case 6.

  • Where: policyengine_us/tests/policy/baseline/gov/states/ar/ee/aeo/liheap/eligibility/ar_liheap_eligible.yaml, lines 94-107. The PR does not touch this file. It tests ar_liheap_eligible, which reads ar_liheap_income_limit, which the PR changes (ar_liheap_income_limit.py lines 42-51).
  • CI result (job "Baseline (states-shard-3)", run 43287773382): Test 'Case 6, FY2025 size seven households use the poverty guideline limit.': ar_liheap_eligible@2025: [1. 0. 0.] differs from [1. 1. 0.]. 1 failed, 983 passed. It is the only failing test in the job.
  • The household: period 2025, Arkansas, seven people, electric heat with a $2,400 bill, countable income $71,016 (monthly countable income $5,918, the amount the FFY 2025 chart prints for seven).
    • Test expects: eligible.
    • Head gives: not eligible. By hand: the chart limit is 5,918 x 12 = $71,016. The cap is the greater of HHS's 60% amount for seven ($70,127) and 150% of the 2024 guideline (47,340 x 1.5 = $71,010), so the limit is $71,010 and 71,016 > 71,010.
  • Cause: this PR. Main's own runs of the same job pass (push runs 43291115019, 43287593110 and 43284121969), and the test file is identical on main. It is not infrastructure.
  • The body is wrong on this point. It says "No case changes eligibility or payment." This case does, and it is exactly the kind of household the body says changes ("within those few dollars of the limit").
  • Fix:
    • Update Case 6 to the capped limit. For example, incomes [70_800, 71_004, 71_016] expecting [true, true, false]: monthly income $5,917 is the highest that stays within $71,010, and $5,918 is now above it. Rewrite the comment on lines 94-97, which still says $71,016 is eligible.
    • Correct the test-plan line in the body, and the matching sentence in the queued Axiom issue ("no changed case changes eligibility or payment").

Should address

1. FY2025 cooling amounts rest on a source conflict the PR neither records nor mentions.

  • Where: ar_liheap_cooling.py line 33 reads payment.matrix.electricity for period 2025; programs.yaml line 1071 claims verified_years: "2025-2026".
  • The conflict:
    • FY2025 plan, item 3.6 (page 12): "Minimum Benefit $50 Maximum Benefit $287".
    • FFY 2025 electric matrix, headed "HOUSEHOLD SIZE BENEFIT PAYMENT (20% OVER BASE)": $60 to $344.
  • Household: period 2025, five people, no income, a cooling cost and an electric bill. The PR pays $344 (row 0-69, column 5 & UP). The FY2025 plan's stated maximum is $287.
  • Why the matrix is a defensible choice: the Wayback Machine holds captures of the FY2025 electric matrix from 2024-12-06, 2025-06-15 and 2025-07-25 with the same content digest, so the 20%-over-base table was the one posted through the summer 2025 season. The body's cross-check ("exactly the range of the FY2026 Electric matrix") holds for FY2026 only.
  • What is missing: main already has the candidate us-ar:liheap-fy2025-benefit-matrix (source_conflicts/candidates.yaml line 657, state unreviewed, follows: unknown) for the same choice on the heating side. It lists the electricity parameter and ar_liheap_matrix_amount.py, not the new reader, and it does not cite plan item 3.6. The queued Axiom issue describes this conflict (its interpretation 8), but the PR body and the register do not.
  • Fix: extend that candidate: add ar_liheap_cooling.py to pe_us.code, add this PR to prs, and add the FY2025 plan item 3.6 as a source with the $50 to $287 reading. Add one sentence to the body.

2. has_cooling_expense is required from bill payers with no Arkansas source, and the comments present it as the state's rule.

  • Where: ar_liheap_cooling_eligible.py lines 24-28; the test comment and case name in ar_liheap_cooling_eligible.yaml Case 2 ("a cooling cost and an electric bill are both required").
  • What Arkansas requires: an energy burden. FFY 2025 manual, section 4.8.1 (page 63): "A household that has the responsibility to pay its home energy bill by receiving a utility bill has an energy burden." Section 2.1 (page 29): "Only electric benefits are available during the Summer Program." No Arkansas source I found names a cooling cost or air conditioning. The queued Axiom issue says the same.
  • What the code comment says: "The summer benefit pays the electric bill, so the energy burden is a cooling cost on an electric bill the household pays itself." That is an inference, not the manual's definition.
  • Household: period 2026, one adult, wages $22,880 (monthly countable income $1,525), gas heat, a $1,800 electric bill, has_cooling_expense left at its default of false. The PR pays $0. Under the manual the household has an energy burden and the summer electric benefit is $77 (row 1510-1569, column 1&2). This is the PR's own Case 2, second unit.
  • Why it matters more here than in the earlier cooling PRs: has_cooling_expense has no formula and defaults to false, so the summer benefit is $0 for every bill-paying household that does not set it. The rent route in the same formula asks for no cooling cost at all.
  • Fix, either of:
    • Keep the term, and say in the code comment, the Case 2 comment and the registry note that it is a PolicyEngine convention with no Arkansas source (the wording the Axiom issue already uses).
    • Drop the term for bill payers, so a positive pre_subsidy_electricity_expense alone shows the direct energy burden.

3. Three terms of the rent route have no test that would fail without them (by my reading).

ar_liheap_cooling_eligible.py lines 31-37. Case 5 of ar_liheap_cooling_eligible.yaml is the only case with rent, and both of its units have tenant_pays_utilities: false, positive rent and is_in_public_housing unset.

Term If removed Case that would catch it
~tenant_pays_utilities Every unsubsidized renter qualifies without a cooling cost or bill None. Add: rent $11,868, tenant_pays_utilities true, no cooling cost, expect not eligible
rent > 0 An owner or rent-free household with the flag false qualifies None (the Axiom issue notes this too). Add: flag false, rent 0, expect not eligible
is_in_public_housing Public-housing tenants with utilities in rent are paid None. Add: flag false, rent > 0, is_in_public_housing true, expect not eligible

Every other new term is pinned; see "Verified correct".

Suggestions

  1. Stale comments in tests after the cap. These still give the chart figure as the limit:
    • ar_liheap.yaml lines 123 and 244 ("27012") and line 189 ("x12=71016").
    • ar_liheap_eligible.yaml line 65 ("> 36840 two-person limit").
    • integration.yaml lines 104 and 250 ("FY2026 chart, size 3: 3,792 x 12", "FY2025 chart, size 2: 2,944 x 12"), each directly above a capped expectation.
  2. References for the cap.
    • ar_liheap_income_limit.py line 16 cites HHS's FY2026 table at page 1. The seven-person amount ($73,126) is on page 4. The FY2025 table (IM 2024-02 Attachment 4, pages 1 and 4), which sets the FY2025 caps, is not in the variable's references at all.
    • The candidate's FY2026 citation (candidates.yaml line 733) says "Arkansas, page 1"; it should say pages 1 and 4, as its FY2025 citation does.
    • payment/matrix/electricity.yaml now says the matrix pays "every household in summer", but its references are the two matrices only. Add the manual's section 6.1 (page 78), the one text that says so.
  3. Body: sizes above 20. The FY2026 list stops at "each even size from 8 to 20". The cap also lowers every size from 21 up ($188,484 to $188,475 at 21, $196,740 to $196,725 at 22), as the candidate's note and the tests show.
  4. Optional tests.
    • A subsidized household with its own electric bill and a cooling cost (eligible, $77), which pins that ~subsidized applies only to the rent route.
    • A cooling case at a capped limit (FY2026, three people, incomes $45,492 and $45,504: $60 and $0).
    • A heating case at a capped state-median row, for example FY2026, two people, monthly income $3,069 and $3,070.
      The queued Axiom issue lists the first two as companion tests "not in the PR's YAML".
  5. Wording of the fuel gate. ar_liheap_cooling_eligible.py lines 38-45 exclude heating_type UNSPECIFIED. The comment labels it as the shared convention (issue 9754), and it matches Arkansas's heating formula, where UNSPECIFIED also pays $0. The summer benefit does not depend on the heating fuel, so the comment could say plainly that this is not an Arkansas rule.

Verified correct

Summer Regular benefit exists and is separate from heating (sources read directly).

  • FFY 2025 manual, section 2.1, page 29: "The Rate Reduction (Regular) Program offers a one-time payment per eligible household per application period and is available during both winter and summer application periods." and "Only electric benefits are available during the Summer Program." Both quotes are on the cited page.
  • Section 6.1, page 78: "Electricity Matrix: used for both Winter and Summer Regular Assistance." The other four matrices are "Winter Regular Assistance only."
  • FY2026 plan, item 1.1, page 4 (checked on the rendered page): cooling assistance is checked, dated 10/01/2025 to 09/30/2026; "Cooling Assistance begins the first Monday after the July 4 holiday ... rate reduction (Regular) households end the last business day of August." Item 1.2: heating 40%, cooling 15%, summer crisis 7.5%, winter crisis 7.5%.
  • FY2025 plan, item 1.1: cooling 07/07/2025 to 08/29/2025.
  • Whether the summer program ran: the LIHEAP Clearinghouse profile reports 24,954 cooling households in FY2024 and a FY2026 cooling benefit of $60 to $344. I found no households-served figures for FY2025 or FY2026. The plan's funding caveat ("AEO may increase or decrease the proposed benefit levels", "reserves the right to shorten or extend the program") is not modeled; the body does not list it under "Not modeled".

Both seasons in one year. Manual section 3.3, page 46: "An approved household's eligibility will continue for the entire program season (Winter or Summer). Unless otherwise specified, only one Crisis and one Regular benefit can be approved for each household for each season." One winter and one summer Regular benefit is what the rule allows, so listing both ar_liheap and ar_liheap_cooling in regular_payments does not double count. ar_liheap_cooling is not a component of any other listed variable.

Amount and fiscal years.

  • The electricity parameter matches both printed matrices cell for cell (39 rows, 3 columns, both years), read with table extraction.
  • Parameter dates are 2024-10-01 and 2025-10-01. A calendar-year period reads the 1 January value, so period 2025 reads FY2025 and period 2026 reads FY2026. Summer 2026 (July to August 2026) falls in FY2026, so it reads the right table. Period 2027 carries the FY2026 cells forward; the FY2027 plan (still "Submission in Review by CO") gives $66 to $378 and no FY2027 matrix is posted (the address returns 404). The body and registry note disclose this.
  • Cooling uses the heating income measure, bands and size groups. Plan item 3.1 (page 12, rendered) prints the same thresholds as item 2.1: 60% of state median income for sizes 1-7, 150% of the guideline from 8.
  • The grant is a fixed cell, not capped at the bill, which matches the heating grant.

Hand-checked expectations (from the printed tables).

Case Arithmetic Expected Result
Cooling 1 (2026, 3 people) 22,880 x 0.8 = 18,304; /12 = 1,525.33, rounds to 1,525; row 1510-1569, 3&4 $114; limit 45,501 matches
Cooling 2 (2026, 5 people, no income) row 0-69, 5 & UP; limit 5,236 x 12 $344; 62,832 matches
Cooling 3 (2026) 828/12 = 69, row 0-69; 840/12 = 70, row 70-129; 1&2 $242, $233 matches
Cooling 4 (2025, 1 person, electric heat) FFY 2025 row 1,510-1,569, 1&2, both seasons $84 + $84 = 168 matches
Cooling 5 (2026, gas and no heat) FFY 2026 row 1510-1569, 1&2 $77, $77 matches
Eligible 1 (2026, 1 person) 2,347 x 12 = 28,164, inclusive; row 2130-2347 $60, then $0 matches
Eligible 5 (rent route) monthly income 1,525, row 1510-1569, 1&2; subsidized unit excluded $77, $0 matches
Limit, FY2026 size 2 chart 3,070 x 12 = 36,840; HHS 54,168 x 0.68 = 36,834.24, floored 36,834 matches
Limit, FY2026 size 7 chart 6,094 x 12 = 73,128; HHS 54,168 x 1.35 = 73,126.8, floored; 150% guideline 72,975 73,126 matches
Limit, FY2026 size 8 chart 6,769 x 12 = 81,228; 54,150 x 1.5 = 81,225; HHS 74,751 81,225 matches
Limit, FY2026 size 22 (15,019 + 2 x 688) x 12 = 196,740; 131,150 x 1.5 = 196,725 196,725 matches
Limit, FY2025 size 1 chart 2,251 x 12 = 27,012; HHS 51,946 x 0.52 = 27,011.92, floored 27,011 matches
Limit, FY2025 size 9 chart 7,263 x 12 = 87,156; 58,100 x 1.5 = 87,150 87,150 matches

The income-limit cap.

  • Statute, 42 U.S.C. 8624(b)(2)(B): "households with incomes which do not exceed the greater of— (i) an amount equal to 150 percent of the poverty level for such State; or (ii) an amount equal to 60 percent of the State median income".
  • HHS's Arkansas rows, read from the tables themselves:
    • FY2026 (IM 2025-02 Attachment 4), four-person median $90,280: $28,167, $36,834, $45,501, $54,168, $62,834, $71,501 (page 1); $73,126 for seven, $74,751 for eight (page 4).
    • FY2025 (IM 2024-02 Attachment 4), four-person median $86,577: $27,011, $35,323, $43,634, $51,946, $60,257, $68,568 (page 1); $70,127 for seven (page 4).
  • The shared helper (floor 60% of the four-person median, multiply by the size factor, floor again) reproduces every one of these figures. Sizes 1, 5 and 6 in FY2026 and 3, 5 and 6 in FY2025 keep the chart amount because it is at or below HHS's.
  • Every figure in the body is right: FY2026 sizes 2, 3 and 7 and $3 at each even size from 8 to 20; FY2025 sizes 1, 2 and 4 and $6 at each odd size from 7 to 19. I checked all 21 values of ar_liheap_income_limit.yaml Case 1 and all 8 of Case 3 by hand, against the two printed eligibility charts.
  • Changed expectations in ar_liheap.yaml (six cases) and integration.yaml (two cases) are each the capped amount for that size and year, and none of those households changes eligibility or payment. The one unchanged case that does change is Critical 1.
  • Because countable income is whole monthly dollars times 12, the cap lowers the effective monthly limit by $1 at the affected sizes (for example $3,069 instead of $3,070 for two people in FY2026). No household at or below the federal amount loses eligibility except one whose monthly income is exactly the half-dollar that rounds up.
  • Pattern on main: wv_lieap_income_limit and or_liheap_income_limit cap the same way, with the same guideline year lag, and their candidates (us-wv:liheap-income-limit-above-federal-ceiling, us-or:liheap-income-limit-above-federal-ceiling) are ruled "under the 2026-10-19 statute-first rule" in the same words. Idaho and North Dakota have the same cap with unreviewed candidates. Arkansas had no such entry and needed one; the PR adds it.
  • The new candidate has every field CONTRIBUTING.md asks for (id, program, years, question, five sources, readings, example, pe_us with follows, code and prs, state). The ruling it cites is the general statute-first rule recorded in CONTRIBUTING.md, the same basis as the West Virginia and Oregon entries. No existing Arkansas LIHEAP candidate is ruled, so there is no earlier ruling to be inconsistent with. No existing candidate or marker names a file this PR moved.

Eligibility.

  • Rent route: plan item 3.3, page 12 (rendered; "Renters with utilities included in the rent?" is checked Yes): "Unsubsidized households with utilities included in their rent may be eligible for LIHEAP assistance if they meet other criteria." The quote is on the cited page. Manual Appendix B (page 147) pays such a household directly. Requiring positive rent follows the manual's definition of an indirect burden ("by paying the landlord through the rent", page 140).
  • Subsidized tenants with utilities in rent are excluded unless they show an extra energy cost (plan 3.3: "not eligible for LIHEAP assistance, unless the household can demonstrate an energy burden"). In the code they qualify only through a cooling cost with a positive electric bill, which stands in for the surcharge.
  • Heating uses a different input for its rent route (heat_expense_included_in_rent, with a positive heating expense for subsidized tenants). Cooling uses tenant_pays_utilities false with positive rent; Hawaii's, Nevada's and Georgia's LIHEAP formulas on main read the same input. tenant_pays_utilities defaults to true, so default inputs do not open the route.
  • Account name: the manual does not require the electric account in the applicant's name. Section 4.8.1 (page 63): "The name on the bill should match the applicant's name or the name of someone listed in the household ... If the name on the utility account is not in a household member's name, the applicant or the Subgrantee must document ... the relationship". A positive bill is a fair stand-in.
  • No categorical eligibility and no asset test for cooling (plan items 1.4 and 3.3).

Mutation coverage (by my reading). Size above zero: eligible Case 3. Income limit, inclusive: eligible Case 1. Cooling cost: eligible Case 2, unit 2. Electric bill: Case 2, unit 3. Rent route present: Case 5, unit 1. Subsidized exclusion (housing assistance): Case 5, unit 2. UNSPECIFIED: Case 4. NONE and other fuels paid: cooling Case 5. Band and size-group lookups: cooling Cases 1-3. FY2025 cells: cooling Case 4. The regular_payments line: cooling Case 4 (liheap: 168; without the line it is 84). Both arms of the cap and the chart arm: ar_liheap_income_limit.yaml Cases 1, 3 and 4.

National total and registry. The new list entry is a dollar amount on the SPM unit, yearly, gated to Arkansas through ar_liheap_cooling_eligible. The registry gets a second Arkansas entry with its own name, so labels stay unique. test_liheap_total_sums_every_registered_state_payment requires a float registry variable to be in the list, and it is; LIHEAP_PAYMENT_STAND_INS needs no change. All nine Rest shards and the guard-test job pass at this head.

Mixed-state and periods. No state-gated value is used as a parameter key. For a non-resident the formula sees countable income 0 and size 0, which give band 1 and size group 1, both present in the matrix. All new variables are yearly; the rent read uses add with no options; income is divided by 12 before the monthly band lookup.

Hygiene. Both new variables have label, reference, defined_for, and unit where it applies. Tests are in variable-named files. Two changelog fragments (added and fixed) are present.

Axiom line assessment

axiom: TheAxiomFoundation/rulespec-us#2183 queued is valid. The issue is OPEN, labelled pe-parity, names head 086717cdcc, and is dispatch-ready: module paths, corpus status, verbatim source text, required outputs, twelve companion tests derived from the sources, and fifteen interpretations, including the cap, the FY2025 range conflict and the has_cooling_expense convention. It will need two updates once this PR changes: the sentence "no changed case changes eligibility or payment" (Critical 1), and the new head.

CI status

Re-checked at the end: 26 pass, 1 fail, 1 skipped (Contrib tests). None pending.

  • Failing: "Baseline tests / Full Suite - Baseline (states-shard-3)". One test, ar_liheap_eligible.yaml Case 6, expected [true, true, false], actual [true, false, false]. Caused by this PR, in a file the PR did not change that tests another reader of the changed income limit. See Critical 1. Main's runs of the same job pass.
  • The PR's own files in that job: cooling/ar_liheap_cooling.yaml (5), cooling/ar_liheap_cooling_eligible.yaml (5), income/ar_liheap_income_limit.yaml (4), ar_liheap.yaml (20) and integration.yaml (5) all pass.
  • The guard tests, lint, changelog check, all nine Rest shards and the microsimulation job pass.

Branch status

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 changes. The cooling payment itself is right: Arkansas pays one Regular benefit in winter and one in summer, the summer benefit is electric only from the Electricity matrix, and the parameter matches both printed matrices cell for cell. The income-limit cap's arithmetic is also right against HHS's Arkansas figures for FY2025 and FY2026. What blocks:

  1. CI fails, and this PR causes it (Critical 1). The cap changes an existing heating case the PR did not update: ar_liheap_eligible.yaml Case 6 (FY2025, seven people, $71,016) expects eligible, and the capped limit is $71,010. Baseline (states-shard-3) reports [1. 0. 0.] differs from [1. 1. 0.]; main passes that job. The description's "No case changes eligibility or payment" needs correcting too.
  2. An unrecorded FY2025 source conflict. The FY2025 plan's item 3.6 gives a cooling range of $50 to $287, and the PR pays $60 to $344 from the posted matrix. Main already has us-ar:liheap-fy2025-benefit-matrix for the heating side; extend it to the new reader and cite item 3.6.
  3. has_cooling_expense is required from bill payers with no Arkansas source, and the comment presents it as the state's energy-burden rule. Label it a convention or drop it for bill payers.
  4. Three terms of the rent route are pinned by no test (~tenant_pays_utilities, rent > 0, is_in_public_housing), by my reading.

Fixes and worked households are in the report above.

@hua7450

hua7450 commented Nov 13, 2026

Copy link
Copy Markdown
Collaborator Author

Thanks, David. This push, head c984f475b7, applies the fixes below (in 81f96098e0) and merges upstream main into the branch.

Critical

  • 1. CI failure in ar_liheap_eligible.yaml Case 6. The case keeps its inputs ($70,800, $71,016, $71,028), since a changed expectation keeps its inputs, and now expects [true, false, false]. Its comment gives the cap, max(70,127, 47,340 x 1.5 = 71,010) = 71,010, and a "Was" line names 42 U.S.C. 8624(b)(2)(B). The body's "No case changes eligibility or payment" now names this case, and the matching sentence in the Axiom issue is corrected.

Should address

  • 1. FY2025 range conflict. us-ar:liheap-fy2025-benefit-matrix in source_conflicts/candidates.yaml now has a plan source for FY2025 plan item 3.6 (page 12) with the $50 to $287 reading, a summer example ($344 against $287), ar_liheap_cooling.py in pe_us.code and PR 10744 in prs. Its note covers winter and summer and records the three Wayback captures with one digest. The state stays unreviewed and follows: unknown. The body has one new sentence on it.
  • 2. has_cooling_expense. Kept the term. The comment in ar_liheap_cooling_eligible.py and the comment on ar_liheap_cooling_eligible.yaml Case 2 now say the positive electric bill comes from manual section 4.8.1, and the cooling cost is a PolicyEngine convention with no Arkansas source, not part of Arkansas's energy-burden rule. The variable's references add section 4.8.1 (pages 29, 63), and the body says the same. The registry note is unchanged: registry notes stay one or two sentences; the text is in the code comment and the description.
  • 3. Rent-route terms. New ar_liheap_cooling_eligible.yaml Case 6 takes Case 5's unsubsidized renter and removes one condition per unit: tenant_pays_utilities true (rent $11,868); rent 0; is_in_public_housing true (rent $6,864, 30% of income under 24 CFR 5.628). Each expects false and $0, and each would be paid without its term.

Suggestions

  • 1. Stale comments. Updated to the capped limits: ar_liheap.yaml Cases 6, 8 and 9; ar_liheap_eligible.yaml Case 5 (36,834); integration.yaml Cases 2 and 5.
  • 2. References. ar_liheap_income_limit.py marks the FY2026 HHS table as pages 1 and 4 and adds the FY2025 table (IM 2024-02 Attachment 4, pages 1 and 4). The candidate's FY2026 citation says pages 1 and 4. payment/matrix/electricity.yaml adds manual section 6.1 (page 78).
  • 3. Sizes above 20. The body's FY2026 list now covers every size from 21 up ($188,475 against $188,484 at 21; $196,725 against $196,740 at 22).
  • 4. Optional tests. The first is added as ar_liheap_cooling_eligible.yaml Case 7: a subsidized household with its own electric bill and a cooling cost, true and $77. The other two are not added, as each repeats a pinned class: cooling Case 1 already asserts the 45,501 limit and eligible Case 1 pins <=; ar_liheap_income_limit.yaml Cases 1 and 3 pin both cap arms, and ar_liheap_eligible.yaml Case 6 now sits on a capped limit.
  • 5. Fuel gate. Removed rather than reworded. The project lead decided on 2026-11-13 that a separate cooling payment adds no heating-fuel condition. ar_liheap_cooling_eligible.py drops the UNSPECIFIED term and its "every state LIHEAP program" comment; ar_liheap_cooling_eligible.yaml Case 4 now expects true and $77, with a "Was" line; ar_liheap_cooling.py says "every heating type". Heating is unchanged.

The body and TheAxiomFoundation/rulespec-us#2183 are updated: the head, test counts, interpretations 2 to 8 and 11, companion tests 6, 8 and 10, and a new companion test 13 for Case 6. Tests were not run locally.

CI is running at c984f475b7.

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

DTrim99 commented Nov 15, 2026

Copy link
Copy Markdown
Collaborator

PR Review (round 2): Add Arkansas LIHEAP summer regular cooling assistance

Re-reviewed at head c984f475b7. Since round 1 (head 086717cdcc) there is one fix commit, 81f96098e0 (2026-11-13), and two merges of main, 08fe73111d and c984f475b7. I ran no tests and no Python. The only things I ran were test merges and text extraction of the source PDFs. Each claim below says whether it rests on hand tracing, on reading the tests, on the source documents or on the CI logs at this head.

Summary

Every round-1 critical and should finding is fixed, and CI is green at this head, including the test that failed in round 1.

  • The FY2025 seven-person heating case now expects the capped limit. The body and the Axiom issue now say this one case changes eligibility.
  • The FY2025 plan's $50 to $287 cooling range is now recorded on the existing Arkansas matrix candidate, which lists this PR's reader. The body says so too.
  • The code comment, the test comment, the body and the Axiom issue now call the cooling-cost requirement a PolicyEngine convention with no Arkansas source.
  • A new case pins each of the three rent-route terms.

The fix also drops the UNSPECIFIED heating-fuel condition from summer eligibility, so households with no stated fuel can now get the summer benefit. Arkansas's sources support this. The summer benefit is electric only and comes from the Electricity matrix whatever the heating fuel. The body and a changed test disclose the change.

The author's reply credits this change to a project-lead decision of 2026-11-13. I found no record of that decision on this PR (see "Ruling cited in the reply"). The PR's code, tests, body and Axiom issue don't cite it, so it doesn't affect the verdict.

Counts: 0 critical, 0 should, 2 suggestions.

Prior findings

Finding Status Evidence
Critical 1: CI fails on ar_liheap_eligible.yaml Case 6 after the cap Fixed The inputs are kept ($70,800, $71,016, $71,028). The expectation is now [true, false, false], with the cap arithmetic and a "Was" line. By hand: the limit is min(71,016, max(70,127, 47,340 x 1.5 = 71,010)) = 71,010. So $70,800 is eligible, and $71,016 and $71,028 are not. Without the cap the second unit would be eligible again, so the case pins the cap (by my reading). CI at this head: states-shard-3 runs the file and all 7 cases pass. The body's test plan and the Axiom issue (Tests line and interpretation 6) now name this as the one case that changes eligibility.
Should 1: FY2025 cooling range conflict not recorded Fixed us-ar:liheap-fy2025-benefit-matrix now has a plan source (FY2025 plan item 3.6, page 12) and a plan reading ($50 to $287 against $60 to $344). It adds a summer example ($344 against $287), ar_liheap_cooling.py under pe_us.code, this PR under prs, and the Wayback note. The state stays unreviewed with follows: unknown, so it claims no ruling. Sources checked: page 12 of the plan prints "Minimum Benefit $50 Maximum Benefit $287" under item 3.6 (text extraction). The Wayback index lists captures from 2024-12-06, 2025-06-15 and 2025-07-25 with one digest. plan is an allowed source kind, and the code path is a tracked file; the candidate checks pass in CI (Python shard 5). The body and Axiom interpretation 8 say the same thing.
Should 2: has_cooling_expense presented as Arkansas's rule Fixed The author took the first option. The formula comment, the comment on eligible Case 2, the body and Axiom interpretation 3 now say two things. The positive electric bill comes from manual section 4.8.1. The cooling cost is a PolicyEngine convention with no Arkansas source. The variable's references add section 4.8.1, which is on PDF page 63 as cited: "A household that has the responsibility to pay its home energy bill by receiving a utility bill has an energy burden." The registry note is unchanged; the reason given is that registry notes stay short. The note says the benefit is "paid once per summer on the electric bill". That states Arkansas's rule and doesn't present the cooling cost as part of it, so I accept the reason.
Should 3: three rent-route terms have no pinning test Fixed New eligible Case 6, traced by hand (by my reading). Without ~tenant_pays_utilities, unit 1 (flag true, rent $11,868) would be eligible. Without rent > 0, unit 2 (flag false, rent 0) would be eligible. Without the public-housing term, unit 3 (flag false, rent $6,864, is_in_public_housing true, receives_housing_assistance false) would be eligible. Each would then get $77; the case expects false and $0 for all three. None of the three has a cooling cost or an electric bill, so the bill route stays closed. The case passes in CI.
Suggestion 1: stale chart figures in test comments Taken The comments in ar_liheap.yaml Cases 6, 8 and 9, ar_liheap_eligible.yaml Case 5 and integration.yaml Cases 2 and 5 now give the capped figures (27,011; 71,010; 36,834; 45,501; 35,323). I checked each by hand against HHS's tables.
Suggestion 2: references for the cap and the summer matrix Taken ar_liheap_income_limit.py adds a # PDF pages 1, 4 comment above the FY2026 HHS table and adds the FY2025 table (IM 2024-02 Attachment 4; the link answers 200). The candidate's FY2026 citation now says pages 1 and 4. electricity.yaml cites manual section 6.1 at page 78, which shows "Electricity Matrix: used for both Winter and Summer Regular Assistance." The page comments follow CLAUDE.md's rule for multi-page variable references.
Suggestion 3: body omits sizes above 20 Taken The FY2026 list now covers sizes 21 and up ($188,475 against $188,484 at 21; $196,725 against $196,740 at 22).
Suggestion 4: optional tests Partly taken The subsidized household with its own electric bill is new eligible Case 7 (true, $77). The other two were not added, with reasons given. They were optional.
Suggestion 5: wording of the fuel gate Taken, more broadly The UNSPECIFIED term was removed rather than reworded. See "Verified".

New findings

Critical

None.

Should address

None.

Suggestions

  1. CI sentences in the Axiom issue are out of date. rulespec-us#2183 still says, on its Tests line, that the cases "have not yet passed in CI at this head", and under "Why queued", "CI has not yet passed its tests at this head". Both now pass at c984f475b7 (run 43501506832). Update them the next time the issue is edited.
  2. No record of the fuel-condition decision. The reply says: "The project lead decided on 2026-11-13 that a separate cooling payment adds no heating-fuel condition." This PR has no record of that decision. The PR doesn't need one, because the change rests on the manual. If the decision is cited as a ruling anywhere, link a dated record, as was done for the Georgia, Oklahoma and Virginia rulings on the sibling PRs.

Verified

What the fix commit changes (files read in full at the head).

  • Code: ar_liheap_cooling_eligible.py (the fuel term and its comment removed, new comments, one reference comment), ar_liheap_cooling.py (a comment), ar_liheap_income_limit.py (references only) and electricity.yaml (one reference).
  • No heating variable changes.
  • Both merges match git's automatic merge of their parents tree for tree, so nothing was resolved by hand.

Removing the fuel condition is right for Arkansas.

  • Code: ar_liheap_cooling_eligible now returns (size > 0) & (income <= income_limit) & responsible and reads no heating_type.
  • Sources (text extraction): FFY 2025 manual section 2.1, PDF page 29: "Only electric benefits are available during the Summer Program." Section 6.1, page 78: "Electricity Matrix: used for both Winter and Summer Regular Assistance." Neither ties the summer benefit to the heating fuel. Round 1 found the same.
  • Who it affects: households with heating_type UNSPECIFIED, the variable's default, that have a cooling cost and an electric bill or utilities in unsubsidized rent. They go from $0 to the matrix cell.
    • Eligible Case 4 now asserts this. By hand: wages 22,880 x 0.8 = 18,304; monthly income 1,525.33, rounded to 1,525; countable income 18,300, within 28,164; FY2026 row 1510-1569, column 1&2, $77.
    • Re-adding the term would make Case 4 fail (by my reading).
    • The winter ar_liheap still pays $0 for UNSPECIFIED, so for such a household the national total includes only the summer amount.
    • The body says "every value, including NONE and UNSPECIFIED, can be paid."
  • The removal adds no parameter lookup, so non-residents and NONE households reach no new key.

Ruling cited in the reply (record search).

  • This PR: the only comments are our round-1 review and the author's reply. There is no comment, review or review comment from the project lead. The decision's only text is the reply's sentence: "The project lead decided on 2026-11-13 that a separate cooling payment adds no heating-fuel condition."
  • Open siblings:
  • Ruled candidates: no candidate is ruled on this decision. The only ruled Arkansas entry this PR touches is us-ar:liheap-income-limit-above-federal-ceiling. It rests on the statute-first rule ("Ruled under the 2026-10-19 statute-first rule") with follows: statute, and the fix commit changed only its FY2026 citation pages.

New and changed expectations. All are traced by hand from the printed tables. The electric cells are the ones matched to the printed matrix cell for cell in round 1.

Case Arithmetic Expected Result
Eligible (heating) Case 6, FY2025, 7 people limit min(5,918 x 12 = 71,016, max(70,127, 71,010)) = 71,010 true, false, false matches
Cooling eligible Case 4, UNSPECIFIED countable 18,300 ≤ 28,164; row 1510-1569, 1&2 true, $77 matches
Cooling eligible Case 6 no cooling cost or bill; unit 1 utilities not in rent, unit 2 no rent, unit 3 public housing false x3, $0 x3 matches
Cooling eligible Case 7, subsidized with own bill bill route (cooling cost, $1,800 bill); the subsidy test applies only to the rent route; 18,300 ≤ 28,164; row 1510-1569, 1&2 true, $77 matches
ar_liheap.yaml Cases 6 and 9 (comments) 51,946 x 0.52 = 27,011.92, floored 27,011 unchanged matches
ar_liheap.yaml Case 8 (comment) 47,340 x 1.5 = 71,010 unchanged matches
integration.yaml Case 2 (comment) 54,168 x 0.84 = 45,501.12, floored 45,501 unchanged matches
integration.yaml Case 5 (comment) 51,946 x 0.68 = 35,323.28, floored 35,323 unchanged matches
Eligible (heating) Case 5 (comment) 44,172 > 36,834 unchanged matches
  • Case 6 gives the public-housing unit rent of 30% of monthly adjusted income: 22,880 x 0.3 / 12 = 572, x 12 = 6,864. The rent only needs to be positive for the test.
  • Case 7's comment paraphrases manual section 4.8.2, which is on PDF page 63: "If a household in SUBSIDIZED HOUSING receives a utility bill and is not reimbursed in any manner, then that household may be eligible for LIHEAP benefits if they meet other criteria."

Source-conflict ratchet.

  • The guard scans variables, parameters and reforms. I read the PR's added lines there against the guard's pattern, and none matches. No file the PR touches is in KNOWN_UNMARKED.
  • The guard passes in CI at this head.
  • Since the head's last merge, main has added one unrelated KNOWN_UNMARKED line, so the merged tree should pass too (by my reading).

Body. The body matches the head on each point:

  • 12 cases in 2 files;
  • the one case that changes eligibility;
  • both candidates;
  • the convention;
  • the UNSPECIFIED sentence;
  • sizes above 20.

Axiom

axiom: TheAxiomFoundation/rulespec-us#2183 queued is still valid. The issue is OPEN, labelled pe-parity, was updated at 20:35 UTC on 2026-11-13 and names head c984f475b7. It matches the fix:

  • The required-outputs row says "No heating-type condition".
  • Interpretation 3 calls the cooling cost a PolicyEngine convention.
  • Interpretation 6 names eligible Case 6 as the case that changes eligibility.
  • Interpretation 8 records the FY2025 range on the candidate.
  • Companion tests 8, 10 and 13 cover eligible Cases 7, 4 and 6, with values derived from the sources.

Only the two CI sentences are behind (Suggestion 1).

CI

Re-checked at the end: all 36 checks pass, with none pending, failing or skipped. Run 43501506832 is on c984f475b7.

  • The PR's own test files ran in states-shard-3, all passing: ar_liheap.yaml (20 cases), cooling/ar_liheap_cooling.yaml (5), cooling/ar_liheap_cooling_eligible.yaml (7), eligibility/ar_liheap_eligible.yaml (7), income/ar_liheap_income_limit.yaml (4) and integration.yaml (5). That test session reports 669 passed and no failures.
  • Guard and other jobs: the source-conflict guard (Python shard 5), the aggregate-list check (shard 4), lint, the changelog check and microsimulation all pass.

Branch

Verdict: APPROVE

@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.

Approving (round 2). The round-1 critical and all three should items are fixed:

  • Eligible Case 6 now expects [true, false, false] against the 71,010 limit and passes in CI.
  • The FY2025 matrix candidate has its plan source and example.
  • The cooling cost is labelled a PolicyEngine convention.
  • New Case 6 pins each rent-route term.

Dropping the UNSPECIFIED fuel term is supported by manual sections 2.1 and 6.1, and Case 4 pins it. CI is green at c984f475b7, and the branch merges cleanly with main and the open siblings. One of the two suggestions: the reply cites a 2026-11-13 project-lead decision on the fuel term, but this PR has no record of it. Nothing here depends on it, but if it's cited as a ruling, a dated record would help.

@hua7450
hua7450 merged commit 59ab85c into main Nov 15, 2026
36 checks passed
@hua7450
hua7450 deleted the ar-liheap-cooling branch November 15, 2026 01:10
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 Arkansas LIHEAP summer regular cooling assistance

2 participants