Skip to content

Add Oklahoma LIHEAP regular summer cooling assistance - #10748

Merged
hua7450 merged 18 commits into
mainfrom
ok-liheap-cooling
Nov 15, 2026
Merged

hua7450 merged 18 commits into
mainfrom
ok-liheap-cooling

Conversation

@hua7450

@hua7450 hua7450 commented Nov 9, 2026 •

Copy link
Copy Markdown
Collaborator

Adds Oklahoma's Summer Cooling Program payment: $500 or $385 for one person, $650 or $425 for two or more, by net monthly income.

Fixes #10747

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

What and why

OAC 340:20-1-20(d) points to Appendix C-7-A for the amounts, "based on the household's net income and household size". Appendix C-7-A page 2 prints the Summer Cooling Program table: $500 (one person) and $650 (two or more) at net monthly income of $0 to $700, and $385 and $425 at $701 and up. OAC 340:20-1-20(d)(1) gives the same amount to renters with utilities in rent. The OKDHS release of July 14, 2026 says "Only one payment per year, per household is allowed for the summer cooling program". It prints the same FY2026 monthly income limits heating uses (130% of the 2025 guidelines), so cooling shares heating's guideline year. The July 15, 2025 release prints the FY2025 limits ($1,632 for one person). One household can receive both components in a year: OAC 340:20-1-10(c)(4) allows "one authorization per household for each application-based assistance period", 340:20-1-20(b) requires a household pre-authorized for winter heating to "complete an application for summer cooling and be approved", and the OKDHS LIHEAP page says "Only one payment per household is allowed per program component."

  • New ok_liheap_income_eligible holds the income test, moved unchanged from ok_liheap_eligible.
  • ok_liheap_cooling_eligible: household size, the income test and has_cooling_expense.
  • ok_liheap_cooling: the Appendix C-7-A page 2 amount for the household's net monthly income (the heating code's ok_liheap_net_income, rounded half up) and size. New parameters under cooling/. Net income of exactly $700 gets the higher amount: C-7-A prints "$0 - $700", while the plan says "under $700".
  • The cooling payment does not read heating_type. The amount depends only on household size and net income (OAC 340:20-1-10(i)(2)), so every value can be paid, including NONE (no heating) and UNSPECIFIED.
  • has_cooling_expense is required, the input the all-state cooling work uses for a cooling cost.
  • Renters, roomers and boarders with utilities in the rent get the same amount (OAC 340:20-1-20(d)(1)). For them, has_cooling_expense true stands for the verified surcharge or utility portion of the rent (340:20-1-20(d)(2); plan item 3.3), as heating's positive surcharge bill does.

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. 19 cases in 3 files, covering 2025, 2026 and 2027: each table cell, the $700 and $701 edges, half-up rounding at $700.42 and $700.50, the income limit, the moved income test, no cooling cost, an unspecified heating fuel (paid), no eligible member when income passes the test, a heat-in-rent roomer household of four, heating and cooling in one year, and the national liheap total.
  • Source-conflict register: candidate us-ok:liheap-cooling-income-boundary (ruled 2026-11-13 by the project lead; ruling record) records the $700 boundary: Appendix C-7-A, which OAC 340:20-1-20(d) names, over the plan's "under $700".
  • make format (ruff)
  • Changelog fragment in changelog.d/

Not modeled

  • The program pays first come, first served, and OKDHS keeps each program open only until funds are expended. The FY2026 summer window opened on July 14, 2026 and closed on July 17. The model pays every eligible household.
  • The cooling equipment reimbursement (up to $150), which replaces the bill payment (OAC 340:20-1-20(f): "When the household chooses this option, it is not eligible to receive help paying its energy bill").
  • Pre-authorization, receipt of the same component from a tribe, and roomer relatedness, which have no existing inputs.
  • The optional priority for households with a member aged 60 or older, with a disability or under five when funds run short (OAC 340:20-1-10(j)). It affects who is served, not eligibility or the amount.

axiom: TheAxiomFoundation/rulespec-us#2186 queued

🤖 Generated with Claude Code

hua7450 and others added 12 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 Register reference at its first cited page, describes the
guideline lag by benefit year, checks the national liheap total, and
records the cooling income boundary in the source-conflict candidates.

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>
…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 Oklahoma LIHEAP regular summer cooling assistance

Reviewed at head 85d9e9b766 (16 files, +540/-11). No tests were run locally for this review: results below rest on reading the head, hand traces, the sources, and the CI run at this head.

Summary

The policy is right. Oklahoma runs a regular summer cooling component separate from winter heating, pays one household both in a year, and the four amounts, the two size groups, the $700/$701 edge, the 130% gross test and the fiscal-year mapping all match OAC 340:20-1-10, 340:20-1-11, 340:20-1-20, Appendix C-7-A page 2, the FY2025-FY2027 plans and the July 2025 and July 2026 OKDHS releases. The income-test refactor leaves every heating result unchanged. I found no wrong result.

Three things need fixing before merge, none of them a change to the formula: two new terms have no test that would fail without them, the new source-conflict candidate is marked ruled with no ruling on record, and an existing Oklahoma candidate still names the file the income test was moved out of.

0 critical, 3 should, 6 suggestions.

Critical

None.

Should address

1. Two new terms have no test that would fail without them.

(a) Rounding before the band lookup, policyengine_us/variables/gov/states/ok/dhs/liheap/cooling/ok_liheap_cooling.py:26 (np.floor(net_income / MONTHS_IN_YEAR + 0.5)). Every case in cooling/ok_liheap_cooling.yaml has net monthly income that lands on the same band with or without rounding (0, 700.00, 701.00, 545.42, 1,016.67). By my reading, deleting the rounding leaves all nine cases unchanged. The rule: OAC 340:20-1-11(a), staff "converts income received more than once per month from the same source to a monthly amount and rounds it to the nearest dollar"; Appendix C-7-A page 2 prints whole-dollar bands "$0 - $700" and "$701 - ineligible" (https://oklahoma.gov/content/dam/ok/en/okdhs/documents/searchcenter/okdhsformresults/c-7-a.pdf#page=2).

  • Household: Oklahoma, 2026, one adult aged 40, wages $11,286, heating_type ELECTRICITY, has_cooling_expense true. Gross 11,286 / 12 = 940.5 -> 941 <= 1,696. Net 11,286 - 2,880 = 8,406 -> 700.50 a month -> 701 -> $385. Without the rounding, 700.50 is below the 701 threshold and pays $500.
  • Fix: add that household with ok_liheap_cooling: 385, paired with wages $11,285 (net 8,405 -> 700.42 -> 700 -> $500).

(b) (size > 0) in policyengine_us/variables/gov/states/ok/dhs/liheap/cooling/ok_liheap_cooling_eligible.py:35. cooling/ok_liheap_cooling_eligible.yaml Case 5 (line 58) is meant to pin it, but that household fails the income test first: the undocumented adult's wages are deemed (15,080 - 2,880 - 398 x 12 = 7,424, or 619 a month) against a limit of $0 for size 0. By my reading, Case 5 stays false with the size term removed. The rule: OAC 340:20-1-10(h)(3), "Households must include at least one U.S. citizen or eligible alien."

  • Household: Oklahoma, 2026, one adult aged 40, immigration_status UNDOCUMENTED, wages $7,000, heating_type ELECTRICITY, has_cooling_expense true. Deemed income is max(7,000 - 2,880 - 4,776, 0) = 0, so gross income 0 <= limit 0 and the income test passes. Expected: not eligible, $0. Without (size > 0): eligible, and ok_liheap_cooling pays $500 (band 1, size group 1).
  • Fix: add that household with ok_liheap_cooling_eligible: false and ok_liheap_cooling: 0.

2. The new candidate is marked ruled, with no ruling on record. source_conflicts/candidates.yaml:8955 (us-ok:liheap-cooling-income-boundary). The entry has no ruling: block and its note gives no date or decision-maker; the PR and issue #10747 have no comments. Other ruled items record it: us-ca:ssp-blind-couple-food-allowance carries ruling: with by, date and record, and us-de:liheap-plan-income-checklist opens its note with "Ruled 2026-11-02 ...". The other four Oklahoma LIHEAP items, which make the same kind of choice (regulation over plan), are unreviewed.

  • The reading itself is sound and I would keep it: OAC 340:20-1-20(d) names Appendix C-7-A, which prints "$0 - $700" and "$701 - ineligible"; plan item 3.5 ("The cooling program grants a larger benefit to households with net monthly incomes under $700", FY2026 page 12, FY2027 page 16, also FY2025 page 12) is a one-line summary. Case 2 pins $700 -> $500 and $701 -> $385.
  • Fix: either record the ruling (who, date, link) in the entry, or set state: unreviewed until there is one.
  • Smaller points in the same entry: follows: statute (line 8949) and readings.statute describe a regulation and its appendix; the sibling Oklahoma items open that field with "No statute supplied". The plan citation could add FY2025 page 12, since years.from is 2025.

3. An existing candidate still points at the file the income test left. source_conflicts/candidates.yaml:9018, item us-ok:liheap-medicare-premium-income-test, lists eligibility/ok_liheap_eligible.py under pe_us.code, and its note names that file, for "Social Security counts gross in the gross income test". This PR moves that test (monthly_income <= monthly_limit on ok_liheap_gross_income) to the new eligibility/ok_liheap_income_eligible.py:24-28; ok_liheap_eligible.py now only reads the result. The guard does not catch this, because the old file still exists.

  • Fix: add policyengine_us/variables/gov/states/ok/dhs/liheap/eligibility/ok_liheap_income_eligible.py to that item's pe_us.code and note (and drop ok_liheap_eligible.py from it if nothing deciding is left there).
  • Related: us-ok:liheap-resource-test (line 9059, FY2026) records that no resource test is applied although the rule in force until 9-15-26 kept "gross income and resource standards". The new cooling/ok_liheap_cooling_eligible.py takes the same reading for the July 2026 cooling round; add it to that item's pe_us.code.

Suggestions

  1. UNSPECIFIED heating type is a modeling convention, not an Oklahoma rule. ok_liheap_cooling_eligible.py:31-32. The cooling amount "is based on household size and net income" (OAC 340:20-1-10(i)(2)) and does not depend on the heating fuel. The body's claim holds for Oklahoma heating: ok_liheap pays an UNSPECIFIED fuel $0 in every case (no direct-payment column; the heat-in-rent path needs a positive primary fuel bill, which UNSPECIFIED cannot carry). Because UNSPECIFIED is the input's default, a household that sets only has_cooling_expense gets $0; say so in the registry note ("for households with cooling costs and a stated heating type") so API users are not surprised.
  2. Renters with utilities in the rent. OAC 340:20-1-20(d)(1) approves "the same benefit amount ... for renters, roomers, and boarders with utilities included in their rent", and plan item 3.3 (FY2026 page 11) adds that they "must verify that a specific portion of the rent is for utilities or be charged a surcharge during high usage months to be considered vulnerable". The code pays them only through has_cooling_expense true (comment at lines 23-25), while that input's documentation describes costs "separately from its rent or mortgage". This matches how heating treats heat-in-rent (a positive surcharge bill is required), but it is stated only in a code comment. Add a line to the body's "Not modeled" or the registry note, and a case with heat_expense_included_in_rent: true and has_cooling_expense: true that receives the full cooling amount (for example a roomer household of four, where heating's roomer table pays $0 and cooling pays $650 or $425).
  3. Pin and cite heating plus cooling in one year. The body quotes only the cooling sentence of the release. The basis for summing both is OAC 340:20-1-10(c)(4) ("There is one authorization per household for each application-based assistance period"), 340:20-1-20(b) (a household pre-authorized for winter heating "must complete an application for summer cooling and be approved"), and the OKDHS LIHEAP page ("Only one payment per household is allowed per program component ... You may qualify for all three programs"). Add a case where both are paid and liheap is their sum, for example Case 5 with has_cooling_expense: true: ok_liheap: 235, ok_liheap_cooling: 385, liheap: 620.
  4. References. cooling/amount.yaml cites the FY2026 and FY2027 plans; add the FY2025 plan page 12 (https://liheapch.acf.gov/docs/2025/state-plans/OK_Plan_2025.pdf#page=12), since 2025 is a verified year. The July 14, 2026 release is quoted in the body and test comments with no link; it is https://oklahoma.gov/okdhs/newsroom/2026/july/comm07132026.html (the July 15, 2025 release, with the FY2025 limits, is https://oklahoma.gov/okdhs/newsroom/2025/july/comm07172025.html).
  5. "Not modeled" in the body lists only first-come funding. The code comments and registry note also leave out the equipment reimbursement, which replaces the bill payment (OAC 340:20-1-20(f): "When the household chooses this option, it is not eligible to receive help paying its energy bill"), pre-authorization, tribal LIHEAP receipt, and the optional priority for members 60 or older, with a disability or under five when funds run short (OAC 340:20-1-10(j)). List them in the body too.
  6. Axiom issue wording. rulespec-us#2186 still says CI "has not yet run its tests at this head"; CI is now green at 85d9e9b766. Its interpretation 2 already notes that no branch case separates the rounding readings; the case in finding 1(a) would close that there too.

Verified correct

Regular cooling benefit in each claimed year. OAC 340:20-1-3(b) lists "summer cooling assistance during the summer cooling application period" as its own component. Plan item 1.1: cooling 07/15/2025-09/30/2025 (FY2025 page 4), 07/14/2026-09/30/2026 (FY2026 page 4), 07/13/2027-07/16/2027 (FY2027 page 4). FY2026 item 1.2 budgets 37% heating and 36% cooling (prior year 38.73% and 45.59%). OKDHS opened enrollment on July 15, 2025 and July 14, 2026 and closed the 2026 window on July 17, as the body says. Funding is first come, first served (OAC 340:20-1-20(c)); the body discloses that.

Heating and cooling in one year. Both are paid; see the quotes in suggestion 3. Only pre-authorization is limited to one component per fiscal year (OAC 340:20-1-12(1); FY2027 plan page 13). Listing ok_liheap and ok_liheap_cooling together does not double count.

Amounts. Appendix C-7-A page 2 (footer 10/1/2021, the only edition; the FY2026 benefits matrix repeats it): size 1, $0 - $700, $500; size 1, $701 - ineligible, $385; 2 or more, $0 - $700, $650; 2 or more, $701 - ineligible, $425. cooling/amount.yaml, income_band.yaml (thresholds 0 and 701) and household_size_group.yaml (thresholds 0 and 2) match, dated 2021-10-01. Plan item 3.6 prints maximum $650 in FY2025, FY2026 and FY2027; its $150 minimum is the equipment cap. No bill cap, no fuel or dwelling dimension, no vulnerable-member supplement in the rule. Net income is the right measure (OAC 340:20-1-11(c); FY2026 plan page 7: "countable net income is used to determine the benefit amount for winter heating and summer cooling"). ok_liheap_net_income is unchanged apart from its label.

Eligibility. Plan item 3.1 sets 130% of the HHS Poverty Guidelines for cooling in all three plans, the same as item 2.1; that is above the 110% federal floor and below the 150% / 60% SMI ceiling. The July 2026 release prints $1,696 / $2,292 / ... / $5,867, the FY2026 Appendix C-7 limits, and the July 2025 release prints $1,632 for one person, so calendar year Y reads fiscal year Y for both heating and cooling. Responsibility for the cooling cost is required (OAC 340:20-1-10(e), (h)(1)). The rule has no age, disability or medical condition for cooling; (j) is an optional priority only.

Refactor. ok_liheap_income_eligible is the three removed lines of ok_liheap_eligible verbatim, with the same entity, period and defined_for = StateCode.OK. ok_liheap_eligible returns what main returns for every household. Its only reader is ok_liheap. No existing test file changed. fpg_year_lag changed its description only; its one reader is ok_liheap_income_limit.

National total and registry. ok_liheap_cooling is a dollar amount, SPMUnit, YEAR, gated to Oklahoma through ok_liheap_cooling_eligible, and not a component of another list entry. The registry gains a second Oklahoma implementation with a distinct name, which the registry test allows; its parameter_prefix resolves. By my reading test_liheap_total_sums_every_registered_state_payment requires both Oklahoma variables in the list and test_members_are_state_gated follows the defined_for chain to OK. Deleting the list line would fail that test and Case 4 (liheap: 425). verified_years: "2025-2027" is backed by cases in each year.

Mixed-state and keyed lookups. ok_liheap_income_eligible and ok_liheap_cooling_eligible are defined_for = StateCode.OK; ok_liheap_cooling is defined_for = "ok_liheap_cooling_eligible". When the formula runs over non-residents or size-0 households, net income is 0 (band 1) and size is 0 (group 1, threshold 0), so p.amount[band][size_group] always finds a key.

Periods. All new variables are YEAR and read YEAR variables; no options=[ADD]; the monthly comparison divides annual amounts by 12 as heating does.

Mutation coverage that is in place. Four amount cells (Cases 1-4, 7, 8); the 700/701 edge (Case 2); size 1 against 2 (Cases 2, 3); income test (Case 6, eligible Cases 2-4, income-eligible Case 1 with half-up rounding and the inclusive limit); has_cooling_expense (Case 5); UNSPECIFIED (Case 9); NONE (Case 4, eligible Case 1); list entry (Case 4).

Hand checks (2026 unless noted; earned income deduction $240 x 12 = $2,880 per worker):

Case Arithmetic Expected File value
Cooling 1 loss floored at 0; net 0 -> $0 - $700, size 1 500 500
Cooling 2a 11,280 - 2,880 = 8,400; / 12 = 700 500 500
Cooling 2b 11,292 - 2,880 = 8,412; / 12 = 701 385 385
Cooling 3 gross 785 <= 2,292; 9,425 - 2,880 = 6,545; / 12 = 545.42 -> 545; size 2 650 650
Cooling 4 15,080 - 2,880 = 12,200; / 12 = 1,016.67 -> 1,017; size 2; heating 0 (NONE) 425; liheap 425 425; 425
Cooling 5 heating: $701 - ineligible, electricity, size 1-3; no cooling cost 235; 0 235; 0
Cooling 6 21,000 / 12 = 1,750 > 1,696 0 0
Cooling 7 (2025) 1.3 x 15,060 / 12 = 1,631.5 -> 1,632; gross 1,257; net 1,017; size 1 385 385
Cooling 8 (2027) 1.3 x 21,640 / 12 = 2,344.33 -> 2,345; gross 785; net 545; size 2 650 650
Cooling 9 UNSPECIFIED 0 0
Eligible 2 20,000 / 12 = 1,666.67 -> 1,667 <= 1,696; 20,400 / 12 = 1,700 > 1,696 true, false true, false
Eligible 3 (2025) 1,667 > 1,632 false false
Eligible 4 (2027) 1,700 <= 1,729 true true
Income eligible 1 1,696.00; 1,696.42 -> 1,696; 1,696.50 -> 1,697 against 1,696 true, true, false true, true, false

References. Each anchor opens on the cited text: C-7-A page 2; FY2026 plan pages 4, 9, 11, 12; FY2027 plan page 16; Oklahoma Register Vol. 42 No. 20 PDF pages 574-576 and 588-589. Parameter descriptions, labels, units and periods follow the house pattern; tests sit in variable-named files; the changelog fragment is changelog.d/ok-liheap-cooling.added.md.

Axiom line assessment

axiom: TheAxiomFoundation/rulespec-us#2186 queued is valid. The issue is OPEN, labelled pe-parity, names head 85d9e9b766, and is dispatch-ready: module paths, corpus status, verbatim source text, required outputs and twelve companion cases derived from the sources. It matches the head. If the tests in finding 1 are added, add them there too.

CI status

All 36 checks pass at 85d9e9b766 (gh pr checks, run 43287783463), none pending. The Quick Feedback job log shows the PR's own YAML files collected and passing at this head.

Branch status

12 commits behind main, mergeable. A test merge with current main (cc486336d7) is clean; main's changes since the merge base to programs.yaml and source_conflicts/candidates.yaml do not overlap this PR's lines, and the source-conflict guard file is unchanged on main since then. Test merges with the eight sibling heads (AR #10744, GA #10746, LA #10750, KY #10752, SC #10754, AL #10756, NE #10758, VA #10760) are all clean today, although each edits regular_payments.yaml, programs.yaml and candidates.yaml.

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 touches the formula. The policy is right: Oklahoma pays winter heating and summer cooling as separate components, one household can get both in a year, and the four amounts, the two size groups, the $700/$701 edge, the 130% gross test and the fiscal-year dating all match the rule, Appendix C-7-A and the plans. The income-test refactor leaves every heating result unchanged.

  1. Two new terms have no test that would fail without them, by my reading: the half-up rounding before the band lookup (a household with net monthly income of $700.50 gets $385 with it and $500 without), and size > 0 (the zero-size case already fails the income test). Two worked households are in the report above (Should Address 1).
  2. The new candidate us-ok:liheap-cooling-income-boundary is marked ruled with no ruling on record. The reading is sound; record who ruled and when, or set it to unreviewed.
  3. A stale path from the refactor. us-ok:liheap-medicare-premium-income-test still names ok_liheap_eligible.py for the gross income test, which now lives in ok_liheap_income_eligible.py.

Six optional suggestions follow. CI is green at 85d9e9b766.

@hua7450

hua7450 commented Nov 13, 2026

Copy link
Copy Markdown
Collaborator Author

Ruling by the project lead, 2026-11-13: us-ok:liheap-cooling-income-boundary

For Oklahoma's summer cooling benefit, follow OKDHS Appendix C-7-A (page 2), which OAC 340:20-1-20(d) names for the benefit amounts: net monthly income of "$0 - $700" receives the larger amount and "$701 - ineligible" the smaller one. Plan section 3.5's "under $700" is not followed at the $700 edge.

Reason: the regulation points to the appendix, and the heating table's "$401 - $700" band is read the same way.

Example: a one-person household with net monthly income of exactly $700 receives $500; test Case 2 pins $700 and $701.

hua7450 and others added 2 commits November 13, 2026 15:25
Addresses DTrim99's round-1 review; upstream main merged first.

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

hua7450 commented Nov 13, 2026

Copy link
Copy Markdown
Collaborator Author

Thanks, David. b3b87c9204 adds the two pinning cases, records the boundary ruling, fixes the stale candidate path and drops the cooling formula's heating-type condition; upstream main is merged in.

Should address

  • 1. Untested terms. (a) cooling/ok_liheap_cooling.yaml Case 10 is your pair: wages $11,285 give net 8,405, or 700.42 a month, and $500; wages $11,286 give 8,406, or 700.50 a month, rounded to 701, and $385. (b) cooling/ok_liheap_cooling_eligible.yaml Case 6 is your undocumented adult with wages $7,000: ok_liheap_income_eligible true, ok_liheap_cooling_eligible false, ok_liheap_cooling 0. Case 5 keeps its inputs and result; its comment now says it fails the income test first (deemed 7,424, or 619 a month).
  • 2. Ruling record. The ruling is in Add Oklahoma LIHEAP regular summer cooling assistance #10748 (comment). The note of us-ok:liheap-cooling-income-boundary now opens "Ruled 2026-11-13 by the project lead; the ruling record is" followed by that link, then gives the Appendix C-7-A reading. state: ruled stays. Smaller points: readings.statute now opens "No statute supplied;", and the plan citation adds the FY2025 plan, page 12. follows: statute stays; 18 other entries whose statute reading opens "No statute" use it too.
  • 3. Stale path. us-ok:liheap-medicare-premium-income-test now names eligibility/ok_liheap_income_eligible.py instead of ok_liheap_eligible.py, in pe_us.code and in the note; ok_liheap_eligible.py keeps no deciding line for it. Related: us-ok:liheap-resource-test now lists cooling/ok_liheap_cooling_eligible.py and this PR, and its note covers both winter heating and summer cooling.

Suggestions

  • 1. UNSPECIFIED. Handled in the code instead of the registry note: the project lead decided on 2026-11-13 that a separate cooling payment adds no heating-fuel condition of its own. cooling/ok_liheap_cooling_eligible.py no longer reads heating_type, and its comment cites OAC 340:20-1-10(b)(2) and (i)(2). ok_liheap_cooling.yaml Case 9 keeps its inputs and now expects $425, with a "Was 0, now 425" comment. Heating's ok_liheap_eligible is unchanged. The body's "as in every state LIHEAP program" line is gone.
  • 2. Renters with utilities in the rent. The body now says they get the same amount (OAC 340:20-1-20(d)(1)) and that has_cooling_expense true stands for the verified surcharge or utility portion of the rent (340:20-1-20(d)(2); plan item 3.3). It is not in the registry note: registry notes stay one or two sentences. ok_liheap_cooling.yaml Case 12 is a roomer household of four with heat in the rent and a $300 gas surcharge: ok_liheap 0, ok_liheap_cooling 425.
  • 3. Heating and cooling in one year. ok_liheap_cooling.yaml Case 11 is Case 5 with a cooling cost: ok_liheap 235, ok_liheap_cooling 385, liheap 620. The body quotes OAC 340:20-1-10(c)(4), 340:20-1-20(b) and the OKDHS LIHEAP page.
  • 4. References. cooling/amount.yaml cites the FY2025 plan, page 12. The body links the July 14, 2026 and July 15, 2025 releases.
  • 5. Not modeled. The body now also lists the equipment reimbursement (OAC 340:20-1-20(f)), pre-authorization, tribal receipt, roomer relatedness and the optional priority groups (OAC 340:20-1-10(j)).
  • 6. Axiom issue. LIHEAP cooling: encode Oklahoma LIHEAP regular summer cooling payment and eligibility (PE-US PR 10748) TheAxiomFoundation/rulespec-us#2186 is updated: the head and CI sentences, the scope and cooling eligibility output (heating type not read), the tests (19 cases), the FY2025 plan row, companion tests 11 ($425) and 12 (fails the income test first), new companion tests 13-16 for the new cases, interpretations 1 (ruling record), 2 (Case 10 separates the rounding readings), 3, 5 and 7, and the delivery checklist.

Tests were not run locally. CI is running at b3b87c9204.

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

DTrim99 commented Nov 15, 2026

Copy link
Copy Markdown
Collaborator

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

Reviewed at head b3b87c9204. Round 1 (2026-11-12) was at 85d9e9b766 and requested changes: 0 critical, 3 should, 6 suggestions. Since then there is one fix commit (bec5b3d6b3, 2026-11-13) and two merges of main (05b5a6fa27, b3b87c9204). No tests were run locally for this review. Each claim below says whether it rests on hand tracing, on reading the tests, or on the CI log at this head. The only commands run were git test merges and source downloads.

Summary

All three should-address findings are fixed, and each fix is pinned by a case that would fail without it (by my reading). CI ran those cases green at this head. The boundary ruling is on record as a dated PR comment. The candidate, the PR body and the Axiom issue all link that comment and describe the same choice. The stale code path is corrected. The author took all six suggestions. For the first one, the author went further and removed the cooling formula's heating-type condition instead of documenting it. That matches the project lead's 2026-11-13 decision that a separate cooling payment adds no heating-fuel condition. It also matches OAC 340:20-1-10(b)(2) and (i)(2) in both the 2025 adoption and the current text, and Case 9 pins it. The fix commit changes no heating result, and no household eligible at round 1 loses eligibility or changes amount. One wording point remains in the Axiom issue.

Open: 0 critical, 0 should, 1 suggestion.

Prior findings

Finding Status Evidence
Should 1(a): rounding before the band lookup had no pinning test Fixed New cooling/ok_liheap_cooling.yaml Case 10 is the household pair I proposed: wages $11,285 and $11,286 (one adult, 2026). By hand: net 8,405 / 12 = 700.42, rounded to 700, which pays $500; net 8,406 / 12 = 700.50, rounded half up to 701, which pays $385. The case also asserts ok_liheap_net_income [8,405, 8,406]. By my reading, without the rounding the second unit stays below 701 and gets $500, so the case would fail. The pair also rules out the other two rounding choices: floor gives 700.50 -> 700 ($500), and ceiling gives 700.42 -> 701 ($385). CI: the file's 12 cases pass at this head.
Should 1(b): (size > 0) had no pinning test Fixed New cooling/ok_liheap_cooling_eligible.yaml Case 6 is the undocumented adult with wages $7,000. By hand (reading ok_liheap_deemed_income): deemed income is max(7,000 - 2,880 - 398 x 12, 0) = 0, gross income is 0, and the size-0 limit is 0, so ok_liheap_income_eligible is true (asserted). Size is 0, so cooling eligibility is false and the payment is $0 (both asserted). By my reading, without the size term the unit is eligible and gets $500 (net 0 is band 1, size 0 is group 1), so the case would fail. Case 5 keeps its inputs and result. Its comment now gives the reason it fails: deemed income of 7,424, or 619 a month, is above the size-0 limit. CI: the file's 6 cases pass.
Should 2: candidate marked ruled with no ruling on record Fixed The ruling is a dated comment on this PR, quoted under Verified. It was posted from the author's account under the heading "Ruling by the project lead". That is the form main's register backlog already accepts: us-de:liheap-cooling-heating-bill links a comment of the same form on #10762, also posted from the author's account. The candidate note now opens "Ruled 2026-11-13 by the project lead; the ruling record is #10748 (comment)" and then gives the reading. The PR body's source-conflict line and interpretation 1 of rulespec-us#2186 link the same comment. All three say what the ruling says: $700 gets the larger amount and $701 the smaller one, and Case 2 pins both. Field check against CONTRIBUTING.md#source-conflicts: id, program: liheap, years 2025-2027 (federal fiscal), question, two sources (both links answer 200), readings (statute and other), pe_us (follows, two code paths that exist at the head, prs) and state: ruled. The quoted text is on the cited pages: C-7-A page 2 (round 1), FY2026 plan page 12 (round 1), and the newly cited FY2025 plan page 12. That page prints "The cooling program grants a larger benefit to households with net monthly incomes under $700." under item 3.5 (text extraction). readings.statute now opens "No statute supplied;". The guard's candidate checks pass in CI (Python shard 5). Smaller point declined: follows: statute stays. The reason holds. The guard allows only statute, conflicting-source, gap-fill, not-modelled and unknown. statute is the closest value for following a regulation, which CONTRIBUTING.md treats as law. I count 18 other candidates whose statute reading opens "No statute" and that use follows: statute.
Should 3: us-ok:liheap-medicare-premium-income-test named the file the income test left Fixed Its pe_us.code and its note now name eligibility/ok_liheap_income_eligible.py instead of ok_liheap_eligible.py. At the head, the gross test (monthly_income <= monthly_limit on ok_liheap_gross_income) is in that file, and ok_liheap_eligible.py only reads the result (read in full). For the related point, us-ok:liheap-resource-test now lists cooling/ok_liheap_cooling_eligible.py and this PR, and its note covers both winter heating and summer cooling. Both cooling and heating apply no resource test at the head.
Suggestion 1: UNSPECIFIED heating type is a convention, not an Oklahoma rule Taken, more broadly The heating_type term was removed instead of documented. See "Heating-type condition" under Verified.
Suggestion 2: renters with utilities in the rent Taken (body and test); registry note unchanged (optional) The body now says such renters get the same amount (OAC 340:20-1-20(d)(1)) and that has_cooling_expense true stands for the verified surcharge or utility portion of the rent (340:20-1-20(d)(2), plan item 3.3). Both quotes are in the current Title 340 text. New Case 12 is the roomer household of four. The author's reason for keeping the registry note short is fine.
Suggestion 3: pin and cite heating plus cooling in one year Taken New Case 11 (heating $235, cooling $385, liheap $620). The body quotes OAC 340:20-1-10(c)(4), 340:20-1-20(b) and the OKDHS LIHEAP page. Each quote matches its source word for word (current Title 340 text; the LIHEAP page: "Only one payment per household is allowed per program component.").
Suggestion 4: references Taken cooling/amount.yaml cites the FY2025 plan at page 12, which shows items 3.5 to 3.7 as titled. The body links the July 14, 2026 release ("Only one payment per year, per household is allowed for the summer cooling program.") and the July 15, 2025 release ($1,632). Both links answer 200.
Suggestion 5: "Not modeled" in the body Taken The body now lists the equipment reimbursement (with the 340:20-1-20(f) quote), pre-authorization, tribal receipt, roomer relatedness and the optional priority groups (340:20-1-10(j)).
Suggestion 6: Axiom issue wording Taken rulespec-us#2186 names the new head. Interpretation 2 now says Case 10 separates the rounding readings. Its new CI sentences are now out of date (new Suggestion 1).

New findings

Critical

None.

Should address

None.

Suggestions

  1. CI sentences in the Axiom issue are out of date. rulespec-us#2186 says under "Why queued" that "CI has not yet finished at this head". Its Tests line says the four new cases and Case 9's new expectation "have not yet passed at this head". All 36 checks have passed at b3b87c9204 (run 43501520294), including the three PR test files (see CI). Update both sentences the next time the issue is edited. Neither changes what the issue specifies.

Verified

Scope of the fix commit (files read in full at the head):

  • Code: cooling/ok_liheap_cooling_eligible.py loses the heating_type read and the fuel_known term, and its comment changes.
  • Tests: the two cooling test files gain cooling Cases 10-12 and eligible Case 6. Cooling Case 9 changes its expectation, and eligible Case 5 changes its comment.
  • cooling/amount.yaml gains one reference. source_conflicts/candidates.yaml changes the three entries above.
  • ok_liheap_cooling.py, the cooling parameters' values, the registry entries and every heating file are unchanged since round 1.
  • Both merges match git's automatic merge of their parents tree for tree (test merges run here), so nothing was resolved by hand.

Heating-type condition (reading and hand trace).

  • Code: ok_liheap_cooling_eligible now returns (size > 0) & income_eligible & responsible, and neither cooling variable reads heating_type.
  • The decision: the author's replies here and on Add Arkansas LIHEAP summer regular cooling assistance #10744 word it as "a separate cooling payment adds no heating-fuel condition". Oklahoma's cooling payment is its own component (OAC 340:20-1-3(b), round 1), and the head adds no fuel condition to it, so the code matches the decision.
  • The rule: the code also matches Oklahoma's rule in both editions that cover the claimed years after September 2025.
    • The 2025 adoption (Oklahoma Register Vol. 42 No. 20, PDF page 574) says at 340:20-1-10(b)(2): "The main energy source used to cool the home is approved during the summer cooling application period. In most instances, the main cooling source is electricity." At (i)(2), on PDF page 576, it says: "summer cooling is based upon household size and net income".
    • The current Title 340 text has the same (b)(2). Its (i)(2) reads "summer cooling is based on household size and net income". By contrast, (i)(1) bases winter heating on the "primary energy source".
  • Who changes: only Oklahoma households with heating_type UNSPECIFIED (the input's default), at least one eligible member, income within the limit, and a cooling cost. They go from $0 to the C-7-A amount. Every other heating type was already paid at round 1.
  • Heating is unchanged: ok_liheap_eligible still excludes NONE, and ok_liheap_matrix_amount still pays UNSPECIFIED $0. For such a household, liheap is the cooling amount alone. The body says every value "can be paid, including NONE (no heating) and UNSPECIFIED".
  • Pinned: Case 9 (UNSPECIFIED, otherwise Case 4) now expects $425, with a "Was 0, now 425" line. By my reading, restoring the term would make it $0 and the case would fail. NONE stays pinned by Case 4 and eligible Case 1.
  • No new lookups: the removal adds no parameter lookup, so non-residents and NONE households reach no new key.
  • Record: the fuel decision has no dated record on this PR. Its only text here is the reply's sentence. None is needed. Neither the code comment, the body nor rulespec-us#2186 (interpretation 5) cites it as a ruling. Each rests on 340:20-1-10(b)(2) and (i)(2), which carry the change alone.

Boundary ruling record (fetched). Comment 6863978810 was posted on 2026-11-13 at 20:24 UTC and has not been edited since. It reads:

Ruling by the project lead, 2026-11-13: us-ok:liheap-cooling-income-boundary

For Oklahoma's summer cooling benefit, follow OKDHS Appendix C-7-A (page 2), which OAC 340:20-1-20(d) names for the benefit amounts: net monthly income of "$0 - $700" receives the larger amount and "$701 - ineligible" the smaller one. Plan section 3.5's "under $700" is not followed at the $700 edge.

Reason: the regulation points to the appendix, and the heating table's "$401 - $700" band is read the same way.

Example: a one-person household with net monthly income of exactly $700 receives $500; test Case 2 pins $700 and $701.

The code follows it: the cooling income_band.yaml threshold is 701, and Case 2 pins $700 -> $500 and $701 -> $385. The heating band's thresholds are 0, 401 and 701, as the ruling's reason says.

No regressions (reading). The new eligibility condition is round 1's with one conjunct removed, and the amount formula is unchanged. Every household eligible at round 1 is still eligible, for the same amount. No heating variable or heating test changed.

New and changed expectations, by hand (2026; earned income deduction $240 x 12 = $2,880 per worker; FY2026 limits 130% of the 2025 guidelines: size 1 $1,696, size 2 $2,292, size 4 41,795 / 12 = 3,482.92, rounded up to $3,483):

Case Arithmetic Expected File value
Cooling 9 (changed) UNSPECIFIED, fuel not read; gross 1,256.67 -> 1,257 <= 2,292; net 12,200 / 12 = 1,016.67 -> 1,017, $701 row; size 2 or more 425 425
Cooling 10, unit 1 gross 940.42 -> 940 <= 1,696; net 8,405 / 12 = 700.42 -> 700, $0 - $700 row; size 1 8,405; 500 8,405; 500
Cooling 10, unit 2 gross 940.50 -> 941; net 8,406 / 12 = 700.50 -> 701, $701 row; size 1 8,406; 385 8,406; 385
Cooling 11 heating: $1,200 electric bill, net 1,017 (band 3), ordinary matrix, size group 1-3 = 235; cooling: size 1, $701 row = 385; liheap 235 + 385 235; 385; 620 235; 385; 620
Cooling 12 size 4; gross 1,257 <= 3,483; $300 gas surcharge > 0, so heating eligible; roomer matrix band 3, size group 4-6 = 0; cooling: net 1,017, size 2 or more = 425 true; 0; 425 true; 0; 425
Eligible 5 (comment only) 15,080 - 2,880 - 4,776 = 7,424; / 12 = 618.67 -> 619 > 0 false false
Eligible 6 deemed max(7,000 - 2,880 - 4,776, 0) = 0 <= limit 0; size 0 true; false; 0 true; false; 0

Source-conflict ratchet, #10287 (CI log and reading). The changed comment in ok_liheap_cooling_eligible.py uses none of the guard's conflict phrases. No Oklahoma file is in KNOWN_UNMARKED. test_conflict_sounding_comments_do_not_grow and the four candidate checks pass at this head. Since the head's last merge, main has added only one KNOWN_UNMARKED line, for an IRS parameter, so by my reading the merged tree passes too.

Body and registry (reading). The body matches the head:

  • 19 cases in 3 files (12 + 6 + 1);
  • the fuel sentence;
  • the renter sentence;
  • the ruling link;
  • the expanded "Not modeled".

The phrase "as in every state LIHEAP program" and the issue-9754 reference are gone from the body and the cooling files (searched at the head). The cooling registry note says "for households with cooling costs" and makes no fuel claim, which matches the code.

Axiom

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

  • The required outputs say heating_type is not read.
  • The Tests line counts 19 cases, matching the files.
  • Companion test 11 expects $425 for UNSPECIFIED, and test 12 says Case 5 fails the income test first.
  • New companion tests 13 to 16 mirror eligible Case 6 and cooling Cases 10 to 12, with source-derived arithmetic that matches the table above.
  • Interpretation 1 links the ruling, interpretation 2 cites Case 10, and interpretation 5 rests the fuel change on 340:20-1-10(b)(2) and (i)(2).

It is dispatch-ready: module paths, corpus status, verbatim text, required outputs and companion tests. Only its CI sentences are behind (Suggestion 1).

CI

All 36 checks pass at b3b87c9204, with none pending, failing or skipped (re-checked at the end of this review). The run is 43501520294 (pull_request event, started 2026-11-13 at 20:26 UTC, head SHA b3b87c9204).

  • The PR's own test files ran in the Quick Feedback job at this head: cooling/ok_liheap_cooling.yaml 12 passed, cooling/ok_liheap_cooling_eligible.yaml 6 passed, eligibility/ok_liheap_income_eligible.yaml 1 passed. That covers every new and changed case.
  • Existing Oklahoma heating tests ran in the Baseline states shards, which are green.
  • Source-conflict guard: it ran in Python shard 5 (2063 passed), including the ratchet and the candidate field, registration and public-text checks.

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). All three round-1 items are fixed:

  • Cooling Case 10 pins the half-up rounding, and eligible Case 6 pins the size > 0 guard.
  • The income-boundary candidate links the dated 2026-11-13 ruling.
  • Both candidates name the right files.

Every suggestion was taken, including removing the heating-type term, which OAC 340:20-1-10 supports and Case 9 pins. CI is green at b3b87c9204, and the branch merges cleanly with main and the open siblings. The one remaining suggestion: rulespec-us#2186 still says CI hasn't finished at this head.

@hua7450
hua7450 merged commit b99c2d4 into main Nov 15, 2026
36 checks passed
@hua7450
hua7450 deleted the ok-liheap-cooling branch November 15, 2026 01:17
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 Oklahoma LIHEAP regular summer cooling assistance

2 participants