Skip to content

Add Oklahoma LIHEAP regular heating assistance - #9970

Open
hua7450 wants to merge 10 commits into
mainfrom
ok-liheap
Open

hua7450 wants to merge 10 commits into
mainfrom
ok-liheap

Conversation

@hua7450

@hua7450 hua7450 commented Oct 7, 2026 •

Copy link
Copy Markdown
Collaborator

Adds Oklahoma's LIHEAP regular winter heating assistance for FY2025 through FY2027. The model counts members who meet SNAP's citizenship and immigration rules for household size, adds income deemed from ineligible members after their own deductions and a need allowance, and tests monthly gross income against 130% of the prior year's poverty guidelines. It then subtracts the earned-income, medical, child support and child care copay deductions and reads the Appendix C-7-A winter matrix by net monthly income, household-size group, fuel and dwelling type. In FY2026, a 70-year-old who heats with natural gas and receives $1,000 a month of Social Security has $1,000 of gross income, within the $1,696 limit. After the $202.90 Medicare Part B premium and a $150 Medigap premium are deducted, net income is $647 a month, and the household receives $265. The limit test counts Social Security before the premium, so a retiree with $1,780 a month is ineligible even when the premium is withheld.

Fixes #9961

Regulatory authority

Eligibility

Requirement Source How modeled
Oklahoma residence — defined_for = StateCode.OK
Household size counts members who meet the citizenship and immigration rules OAC 340:20-1-10(d)(3) and (h)(3), pointing to the SNAP rule OAC 340:50-5-67(a); 7 CFR 273.4; P.L. 119-21 section 10108 Oklahoma lists no LIHEAP categories of its own, so the model reuses is_snap_immigration_status_eligible for January of each year: the SNAP status list then in force and its qualified-alien waiting rule. Before July 2025 the list includes refugees, asylees, people granted withholding of deportation, parolees and conditional entrants; from then it is citizens, lawful permanent residents and Cuban and Haitian entrants. So 2025 uses the earlier list and 2026 and 2027 the narrowed one. A household with no qualifying member is ineligible.
Income deemed from ineligible members OAC 340:20-1-11(a)(4); Appendix C-1 Schedules IX-A and IX-B Each tax unit's ineligible members contribute their countable income minus their own deductions and a monthly need allowance: TANF Schedule IX-A when the group includes an adult, otherwise the children-only Schedule IX-B ($193 for one child up to $1,333 for nine or more). The contribution enters gross income before the limit test.
Gross income limit FY2025 and FY2026 plans, section 2.1, page 9; Appendix C-7; December 2024 and January 2026 announcements 130% of the prior year's guideline. The monthly limit for sizes 1–8 and the amount for each member above eight are each rounded up to the dollar, which reproduces every printed C-7 amount in FY2025, FY2026 and FY2027. Monthly gross income is rounded half up to the dollar (OAC 340:20-1-11(a)), and the limit is inclusive.
Heating responsibility OAC 340:20-1-10(e) and (h)(1); OAC 340:20-1-19(d)(1)–(2); OAC 340:20-1-13(2)(B)–(C); FY2026 plan section 2.3, page 9 A household billed directly qualifies with a positive bill for its heating_type or a reported obligation (has_heating_expense). A renter or roomer whose rent includes heat must pay a verified surcharge, subsidized or not; a positive bill for its heating_type stands in for the surcharge, and the flag alone does not qualify. Housing-assistance inputs do not change the result. heating_type NONE is ineligible.
No categorical eligibility and no asset test FY2026 plan question 1.4, page 5, and resource statement, page 14 SSI or TANF receipt does not waive the income limit; resources are not tested.

Countable income

Item Source How modeled
Earned income OAC 340:20-1-11(a)–(b); OAC 340:50-7-22(9) Counts wages and net self-employment, SSTB, farm operations and partnership/S-corporation income, each floored at zero, with no further business-expense deduction. Excludes the earnings of a member under 18 who attends elementary or high school and is a tax dependent.
Unearned income OAC 340:20-1-11(a)–(b); OAC 340:50-7-29(c); FY2026 plan section 1.9, page 6 Counts unemployment (total_unemployment_compensation: the reported amount, otherwise modeled Oklahoma unemployment insurance), strike benefits, Social Security, SSI, pensions, retirement account distributions, military retirement pay, survivor benefits, railroad retirement (gross), workers' compensation, disability benefits, rental and farm rental income, alimony, child support received, interest, ordinary dividends, veterans benefits, cash support (financial_assistance) and estate income. Floors each source at zero, so a loss in one source offsets nothing.
Social Security OAC 340:20-1-11(a) and (c) Counts gross Social Security in the income test. The Medicare Part B premium is a medical deduction after the test (see the source conflicts below).
TANF FY2026 plan section 1.9, page 6 Counts the take-up-gated tanf aggregate, which includes ok_tanf, once per household.
Deductions for the payment band OAC 340:20-1-11(c); OAC 340:50-5-4; OAC 340:50-7-31(a)(3)(A); Appendix C-7 After the gross test, subtracts for each qualifying member $240 a month of earnings per employed member (capped at earnings), medical expenses of members 60 or older or disabled, and child support paid. Medical expenses are snap_allowable_medical_expenses, the modeled part of SNAP's list in OAC 340:50-7-31(a)(3)(A), without SNAP's $35 threshold: health premiums paid after tax or through payroll, the whole Part B premium of Medicare enrollees and other medical costs. A member under 60 qualifies through is_usda_disabled, the 7 CFR 271.2 benefit-receipt test that OAC 340:50-5-4 adopts. Subtracts the household's child care copay when it receives an Oklahoma child care subsidy. Ineligible members' deductions apply only within deeming.
Monthly rounding OAC 340:20-1-11(a) Rounds monthly gross and net income half up to the dollar before the limit test and the band lookup.

Benefit

Each cell lists household sizes 1–3 / 4–6 / 7 or more.

Schedule When used Net income $0–$400 $401–$700 $701 and up
Ordinary Natural gas, electricity, wood or coal, billed directly $365 / $402 / $430 $265 / $292 / $312 $235 / $259 / $277
Delivered Propane, fuel oil or kerosene, billed directly $425 / $468 / $500 $350 / $385 / $412 $280 / $308 / $330
Renter Heat included in rent, any fuel $150 / $165 / $180 $110 / $120 / $135 $100 / $110 / $125
Roomer Heat included in rent, ok_liheap_dwelling_type ROOMER $70 / $0 / $0 $50 / $0 / $0 $40 / $0 / $0
  • ok_liheap_dwelling_type (STANDARD by default, or ROOMER) is the only new input. It selects the roomer schedule for heat-in-rent households; C-7-A prints $0 for roomer households of four or more.
  • The heat-in-rent schedules cover "All Energy Sources", so the matrix prices any fuel other than NONE. The award still needs the surcharge bill for the household's heating_type, so an UNSPECIFIED fuel, which carries no bill, pays $0. Directly billed OTHER, SOLAR and UNSPECIFIED fuels have no column and pay $0.
  • Appendix C-7-A, dated 10/1/2021, sets the amounts in all three years; the FY2026 clearinghouse matrix prints the same cells.
  • The reported bill does not cap the award.

Years covered

Model year Program year Guideline One-person monthly limit Each member above eight
2025 FY2025, from October 1, 2024 2024 $1,632 $583
2026 FY2026, from October 1, 2025 2025 $1,696 $596
2027 FY2027, from October 1, 2026 2026 $1,729 $616

A calendar-year period reads the parameters in force on January 1. Formulas are undated and verified_years is "2025-2027". The income-limit parameters take effect October 1, 2024, the start of FY2025. The 10/1/2024, 10/1/2025 and 10/1/2026 editions of Appendix C-7 match the model's limits and print the $240 deduction; the 1/1/2025, 7/1/2025, 4/1/2026 and 7/1/2026 editions of Appendix C-1 print the same Schedule IX-B. A 2025 period applies OAC 340:20-1-11 as adopted effective September 15, 2025, which replaced a 38-item list of income exclusions (Register pages 578–580); the earlier list gives the same result for every modeled source. The text as amended effective September 15, 2026 (43 Ok Reg No. 23), in force for FY2027, keeps every modeled rule, drops the liquid-resource subsection 340:20-1-11(e) and sets out the surcharge verification in 340:20-1-13(2)(B)–(C). Years before 2025 are unverified backfilled estimates.

Not modeled and source conflicts

Item Source Model treatment
Gross business receipts and the 50% business-expense deduction OAC 340:20-1-11(c)(4) Uses existing net business inputs with no further deduction.
Partnership and S corporation income OAC 340:20-1-11(a)(2); OAC 340:50-7-29(b)(2) and (c)(8) Counts partnership_s_corp_income as earned income, as the Kansas, Kentucky, Oregon and New York LIHEAP lists do. The input does not separate active partners' earnings from S corporation profit shares and passive partners' distributions, which Oklahoma SNAP counts as unearned; only the $240 earned-income deduction differs.
Exclusions that aggregate inputs cannot isolate: irregular small gifts, qualified educational and VA aid, restricted tribal trust receipts, redirected support and third-party payments OAC 340:20-1-11(b); OAC 340:50-7-22 Not separated from the counted sources.
Composition of the ineligible need group OAC 340:20-1-11(a)(4) Tax units approximate it; actual claiming, several possible claimants and separate returns can differ.
Payer of the child care copay OAC 340:20-1-11(c) Deducted once from net income. A copay that an ineligible member pays is not moved into deeming, which can overstate gross income.
Disability categories with no input OAC 340:50-5-4(a)(3)–(5) and (a)(10)–(11); 7 CFR 271.2 Supplemental and government disability retirement benefits, Railroad Retirement disability annuities, interim assistance and disability-based Medicaid have no inputs, so members under 60 who qualify only through them get no medical deduction. The general is_disabled flag is not used because it shows no benefit receipt.
Noncitizen nationals, Compact of Free Association residents, trafficking victims and battered noncitizens 7 CFR 273.4; 7 U.S.C. 2015(f) No immigration_status category; not counted in household size.
Written roomer agreements, shared meters, institutional living and tribal LIHEAP receipt OAC 340:20-1-10 Not identified by existing inputs.
Utility allowances on direct bills OAC 340:20-1-10 Reported heating costs are assumed to be the obligation remaining after any allowance.
OTHER, SOLAR and unspecified fuels billed directly Appendix C-7-A Pay $0 as a coverage gap (#9754 for unspecified fuel). Solar is not an approved main energy source under OAC 340:20-1-10(b)(1).
State supplementary payments — Not modeled; ssi is the federal benefit.
Crisis, cooling, weatherization and equipment assistance — Out of scope.

Where the FY2026 plan and the OAC differ, the model follows the OAC; where the OAC is silent, it follows the plan:

Topic FY2026 plan OAC and model
Child earnings Section 1.9 (page 6) does not count "Earned income of a child under the age of 18" OAC 340:20-1-11(b) applies the SNAP exclusions, and OAC 340:50-7-22(9) excludes only the earnings of an elementary or high school student 17 or younger under parental control. The model excludes earnings of school-attending tax dependents under 18 and counts other minors' earnings.
Resources Page 14: "Oklahoma does not use resources (assets) to determine eligibility for energy assistance" The September 2025 adoption (Register page 581) kept a liquid-resource limit "per OKDHS Appendix C-7", but C-7 prints no resource level and the current OAC drops the subsection. The model has no asset test.
Medicare premium Section 1.9 of the FY2025, FY2026 and FY2027 plans (page 6) checks "Excluding MediCare deduction" for SSA benefits OAC 340:20-1-11(a) counts "All gross earned and unearned income", and 340:20-1-11(c) requires the household to meet the gross income standard "before allowing applicable income deductions", which include "Medicare premiums" (OAC 340:50-7-31(a)(3)(A)(vi)). The FY2026 plan's narrative (page 7) agrees: "OKDHS uses gross income to determine LIHEAP eligibility." The model counts gross Social Security in the income test and deducts the premium afterwards.

Two readings are recorded in code notes but not followed:

Topic Reading not followed Model
Immigration status The eCFR text of 7 CFR 273.4(a)(6) still lists refugees and asylees, which would keep them eligible. OAC 340:20-1-10(d)(3) points to the SNAP rule 340:50-5-67, so the model follows SNAP's list as amended by P.L. 119-21.
Heat in rent OAC 340:20-1-10(c) counts "undesignated payments for energy in the form of rent", and (f)(3) names only subsidized heat-in-rent households as non-vulnerable, which could pay an unsubsidized renter with no surcharge. OAC 340:20-1-19(d)(1) pays renters, roomers and boarders "who pay a surcharge", 340:20-1-19(d)(2) and 340:20-1-13(2)(B)–(C) set how it is verified, and 340:20-1-10(h) denies households that do not verify responsibility. Plan section 2.3 (page 9) agrees, so the model requires the surcharge.

Microsimulation: the microsimulation datasets carry no heating inputs, so population totals are about $0 until #9754 lands. Callers must send heating_type with the matching fuel bill.

Test plan

72 YAML cases in 12 files cover:

  • all 36 C-7-A cells including the roomer zeros, size-group edges at 3, 4, 6 and 7, all seven priced fuels, heat in rent for standard renters and roomers with any fuel, and $0 for directly billed OTHER, SOLAR and UNSPECIFIED;
  • half-up rounding at the $401 and $701 band starts and at the gross limit ($1,696.25 a month is eligible; $1,696.50 is not);
  • FY2026 limits for sizes 1–8, FY2027 limits for sizes 1–10 and FY2025 limits for sizes 1, 8 and 9;
  • each represented immigration status under the narrowed 2027 SNAP list, the five-year waiting rule and its exceptions for permanent residents, and a refugee who is eligible in 2025 but not in 2027;
  • deeming for one ineligible adult, an adult couple with a dependent, two tax units, children-only groups up to the nine-or-more amount and a child turning 18, plus the 2025 Schedule IX-B and $240 deduction;
  • the student earnings conditions, positive net farm income, per-source loss floors in earned and unearned income, gross Social Security in the income test with the Part B premium deducted afterwards, modeled Oklahoma unemployment insurance ($432 a week for 15 weeks, or $6,480, which moves a one-person household from $365 to $265), retirement account distributions, military retirement pay, TANF with and without take-up, and SNAP and housing assistance excluded;
  • the $240 allowance per worker, an unused allowance, medical deductions per elderly or disabled member (payroll and after-tax health premiums, the whole Part B premium, and an SSDI recipient under 60 beside a member flagged disabled with no qualifying benefit), child support paid, the zero floor and the copay with and without a subsidy;
  • heating responsibility: the heat-in-rent surcharge for subsidized and unsubsidized renters and roomers, the responsibility flag counting only for direct payers, public housing and a direct obligation, plus no heat, no qualifying member and out of state;
  • final awards for a mixed-status household, a delivered-fuel household, renter, roomer and surcharge routes, deemed income entering the gross test before the worker's deduction, TANF and the copay each applied once, a retiree whose Part B premium does not restore eligibility, and military retirement pay above and below the limit.

Every case specifies heating_type. The tests were not run locally; CI validates them.

  • YAML tests whose expected values come from an external source (statute, official form or worksheet, official calculator)
  • make format
  • Changelog fragment in changelog.d/

axiom: TheAxiomFoundation/rulespec-us#1535 queued

🤖 Generated with Claude Code

hua7450 and others added 4 commits October 3, 2026 19:49
- Count Social Security net of the Medicare Part B premium, floored per
  person (FY2025-FY2027 plans section 1.9).
- Count military retirement pay; correct the pension comment.
- Count TANF through the take-up-gated tanf variable instead of ok_tanf.
- Round monthly income half up to the dollar before the gross test and
  the band lookup (OAC 340:20-1-11).
- Date the $240 earned-income deduction from 10/1/2024 and the child-only
  need standard from 1/1/2025, the earliest official editions.
- Follow SNAP's noncitizen rule, as OAC 340:20-1-10(d)(3) directs through
  340:50-5-67, by reusing is_snap_immigration_status_eligible (narrowed by
  P.L. 119-21 from July 2025).
- Require a utility surcharge for heat-in-rent renters and roomers (OAC
  340:20-1-19(d), plan item 2.3), proxied by a positive heating expense.
- Set verified_years to 2025-2027 and shorten the programs.yaml note.
- Add and update tests for each change.

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

# Conflicts:
#	policyengine_us/programs.yaml
@codecov

codecov Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (909176a) to head (f0e2f40).
⚠️ Report is 495 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##              main     #9970    +/-   ##
==========================================
  Coverage   100.00%   100.00%            
==========================================
  Files            4        13     +9     
  Lines           76       220   +144     
  Branches         2         2            
==========================================
+ Hits            76       220   +144     
Flag Coverage Δ
unittests 100.00% <100.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

hua7450 and others added 4 commits October 7, 2026 22:56
…miums

Count retirement_distributions; deduct other health premiums and any Part B premium above Social Security for members 60+ or disabled (OAC 340:20-1-11(c)(1)); household size uses adds.

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

# Conflicts:
#	policyengine_us/programs.yaml
One reference entry per source; single-page citations keep the page only in the href; multi-page titles end with a quoted #page list and the href opens the first cited page; variable references use '# PDF pages ...' comments above multi-page hrefs (CLAUDE.md, PolicyEngine/policyengine-us PR 10009). Reference lines only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@hua7450
hua7450 marked this pull request as ready for review October 12, 2026 05:54
@DTrim99

DTrim99 commented Oct 15, 2026

Copy link
Copy Markdown
Collaborator

PR Review: Add Oklahoma LIHEAP regular heating assistance

PR #9970: Add Oklahoma LIHEAP regular heating assistance (author: hua7450, head 9b6b0dac45)

Scope: the regular payment of Oklahoma Human Services' (OKDHS) LIHEAP Winter Heating Program for federal fiscal years 2025-2027. The PR covers:

  • household size, which counts members who meet SNAP's citizenship and alien rules (OAC 340:20-1-10(d), which points to the SNAP rule 340:50-5-67), with income deemed from ineligible members after their own deductions and an Appendix C-1 Schedule IX need allowance;
  • the gross income test: 130% of the prior year's poverty guideline, with the monthly base and the per-member amount each rounded up to the dollar, against monthly gross income rounded to the nearest dollar;
  • countable income: gross earned and unearned income less the SNAP exclusions, each source floored at zero, Social Security net of the Medicare Part B premium, and take-up-gated TANF;
  • the deductions taken after the gross test: $240 per employed member, medical expenses of members 60 or older or disabled, child support paid, and the child care copay;
  • the Appendix C-7-A winter matrix (four tables by three net-income bands by three household-size groups), and heating responsibility: a bill or reported obligation for direct payers, and a surcharge (a positive bill) for heat-in-rent renters and roomers, subsidized or not.

Cooling, crisis (ECAP), weatherization, equipment and pre-authorization are out of scope. The PR changes 43 files: 16 parameters, 13 variables, 12 test files (68 cases), programs.yaml and a changelog fragment. The matrix, band and size-group parameters are dated 2021-10-01 (the only C-7-A edition), the limit parameters 2025-10-01, the income lists and the student and medical ages 2025-09-15, the $240 deduction 2024-10-01 and the children-only need standard 2025-01-01. The adult need standard reuses the existing Oklahoma TANF Schedule IX-A parameter. The tests use periods 2025-2027, and the registry lists Oklahoma partial with verified_years: "2025-2027".

Overall: the matrix, the income limits, the deeming standards and the deduction amounts are right where the sources print them.

  • All 36 C-7-A cells match the edition OKDHS still serves (dated 10/1/2021, file dated June 17, 2026) and the FY2026 Clearinghouse matrix. Table headings, band starts, size groups and the roomer zeros are encoded as printed. Every plan from FY2023 to FY2027 gives the same $40 minimum and $500 maximum.
  • 26 of the 27 printed limit figures for FY2025-FY2027 were checked against OKDHS documents and all reproduce. The 27th, FY2025's $583 per member, follows the rule but rests only on the PR's archived copy. Schedule IX-A and IX-B and the $240 deduction match Appendices C-1 and C-7, and the limit is above 110% of poverty at every size in every year.
  • The income structure follows OAC 340:20-1-11: the gross test comes before the deductions, deeming follows steps (a)(4)(A)-(E), SNAP exclusions apply (student earnings, housing subsidies and SNAP itself), losses are floored per source, and amounts are rounded to the nearest dollar. The heat-in-rent surcharge follows 340:20-1-19(d) and 340:20-1-13(2)(B)-(C).
  • The tests are strong. Every branch has a test that would fail if it broke, apart from one income-source entry (S6), and both control mutations fail as expected.

There are no critical findings. The six should-address items:

  • S1: a merge blocker from main's Integrate modeled state unemployment insurance into income flows #9558. The unearned list reads the raw unemployment_compensation, so main's guard fails on the merged tree. Oklahoma's unemployment insurance (ok_ui) is modeled on main, so modeled UI drops out of LIHEAP income. Reproduced: one household gets $365 instead of $235, and another $235 instead of $0.
  • S2: Social Security counts net of the Part B premium in the gross income test. The OAC and OKDHS's staff guide count all gross income and allow the premium only as a medical deduction after the test. The PR follows plan item 1.9 and calls the OAC "silent", although its own rule is to follow the OAC where the two differ. The PR body's headline retiree gets $235 at head and $0 under the OAC.
  • S3: the medical deduction misses payroll (pretax) premiums, which main's Document disjoint health premium inputs and correct consumer treatment #10046 now keeps in a separate input. It also reads is_disabled instead of the 7 CFR 271.2 definition that the rule incorporates (is_usda_disabled). Reproduced: a band change, an eligibility flip through deeming, and an SSDI recipient paid $235 instead of $265.
  • S4: eight of the 16 parameter descriptions use verbs outside the house template, and three misdescribe what the parameter covers.
  • S5: two missing page lists and one missing #page=1. The four limit parameters are also dated 2025-10-01 and cite only FY2026-FY2027 sources, although the registry claims FY2025.
  • S6: farm_operations_income is never positive in any test; removing it from the earned list passes every case.

All 68 cases pass locally at the head and on the merged tree. The model outputs quoted below were reproduced by running the head code, or the merged tree for S1 and S3. Values that a proposed fix or another reading would produce are hand computations and are labelled as such. The S6 claim and the control mutations come from mutating the code and rerunning the PR's tests.

Path prefixes used below:

  • P/ = policyengine_us/parameters/gov/states/ok/dhs/liheap/
  • V/ = policyengine_us/variables/gov/states/ok/dhs/liheap/
  • T/ = policyengine_us/tests/policy/baseline/gov/states/ok/dhs/liheap/
  • R = Oklahoma Register Vol. 42 No. 20 (July 1, 2025; 1,508 pp; PDF page = printed page − 878)
  • Q = Quest, the OKDHS staff policy guide for LIHEAP workers

Line numbers refer to head 9b6b0dac45.

Source Documents

# Document Link Use
1 OAC Title 340, current official text (HTML; LIHEAP sections as amended effective 9-15-26 by 43 Ok Reg No. 23) Title 340 340:20-1-10 (program factors), -11 (income), -13(2) (surcharge verification), -14(2) (supplements), -19 (winter heating); 340:50-5-4 (elderly or disabled, 7 CFR 271.2), -5-67 (alien status), -7-22 (exclusions: "No other income is excluded"), -7-29 (inclusions), -7-31 (medical expenses)
2 R: OAR Docket #25-364, permanent adoption effective September 15, 2025 R, p. 576 Gist "adjust the LIHEAP income determination in light of federal feedback" (p573); 340:20-1-10 (p574-576); 340:20-1-11 (p576-581), with the struck 38-item exclusion list (p578-580) and (c) unchanged except "may" (p580-581). Read from rendered pages, because the text layer merges struck and inserted words
3 FY2026 Oklahoma LIHEAP State Plan (50 pp, Revision #1, "Submission Accepted by CO") p. 6 1.1 heating 12/16/2025-12/26/2025 (p4); 1.4 No, 1.8 Gross Income (p5); 1.9 with "Excluding MediCare deduction" and Cash gifts checked (p6); narrative "OKDHS uses gross income ..." (p7); 2.1 130%, 2.3 (p9); 2.6 $40 / $500 (p10); "Oklahoma does not use resources" (p14). The text layer lacks the checkbox states, so the rendered pages were read
4 FY2025 plan (51 pp, Revision #2, accepted) and the FY2027 plan OKDHS posted (50 pp, a draft edited from the FY2026 form) FY2025, p. 6, FY2027, p. 6 Heating 12/17/2024-02/28/2025 and 01/12/2027-01/20/2027 (p4); the same 1.9 boxes (p6, rendered); 2.1 130% (p9); 2.6 $40 / $500 (p10)
5 FY2023 and FY2024 plans FY2023, p. 8, FY2024, p. 8 Backdating check: 2.1 130% (p8); 2.6 $40 / $500 (p9)
6 Appendix C-7 (1 p each): 10/1/2026 edition; 10/1/2025 edition; 10/1/2024 edition 10/1/2026, 10/1/2025 capture, 10/1/2024 capture "Allowable monthly gross income must be equal to or less than the following income standards that are 130 percent of federal poverty level"; sizes 1-8, the per-member amount and the $240 deduction. The 10/1/2024 capture refused automated requests (HTTP 429), so FY2025 was checked against item 9
7 Appendix C-7-A (2 pp, footer "10/1/2021", file dated June 17, 2026) and the FY2026 Clearinghouse matrix C-7-A, p. 1, OK_BenefitMatrix_2026.docx The four winter tables; the same 36 cells in both
8 Appendix C-1, 7/1/2026 edition (8 pp) C-1, p. 4 Schedule IX-A need standards (p4), IX-B (p5)
9 OKDHS enrollment notices, December 17, 2024 and January 6, 2026 Dec. 17, 2024, Jan. 6, 2026 Winter heating opened on those dates; FY2025 limits $1,632 ... $5,712 (not cited in the PR) and FY2026 limits $1,696 ... $5,867
10 Q: "LIHEAP / ECAP: Eligibility – Income" and "Energy Assistance Income Exclusions" (both updated August 12, 2026), "Eligibility – Household Composition & Other Factors" (December 27, 2024) Income, Exclusions, Household Not cited in the PR. Staff procedure for the gross test, deductions, exclusions, open-case gross income, deeming and resources ("Effective October 1, 2024, the Energy Assistance program does not consider resources")
11 HHS LIHEAP Model Plan Reference Guide (FY25) Reference Guide Lists "SSA benefits (including or excluding Medicare deduction)" without defining the boxes (S2)
12 42 USC 8624(b)(2)(B) LII The 110%-of-poverty floor

Critical (Must Fix)

None.

Should Address

S1. Merge blocker: after merging main, the unearned list reads the reported-only unemployment_compensation, so main's guard fails and modeled Oklahoma UI drops out

  • Where: P/income/sources/unearned.yaml:14 (- unemployment_compensation).

  • What changed on main: Integrate modeled state unemployment insurance into income flows #9558 (merged 2026-10-13, the day after this PR's last push) added total_unemployment_compensation, which uses the reported amount when present and otherwise the modeled state unemployment insurance programs. It moved every income-source list under parameters/ to the total and added policyengine_us/tests/code_health/test_unemployment_compensation_readers.py, which fails on any raw list entry. Main's gov.states.household.modeled_state_unemployment_compensation lists ok_ui from 2022.

  • Reproduced on the git merge-tree result of main 8ae01aa3cb and this head: test_parameter_source_lists_do_not_read_raw_unemployment_compensation fails with one violation, parameters/gov/states/ok/dhs/liheap/income/sources/unearned.yaml:14. The file's other three tests pass, and the PR's 68 cases still pass on that tree.

  • Source: OAC 340:20-1-11(a) counts "All gross earned and unearned income the household receives", OAC 340:50-7-29(c)(3) makes "unemployment compensation payments" countable unearned income, and plan item 1.9, p. 6 checks "Unemployment insurance". None separates reported from modeled amounts.

  • Impact on the merged tree, period 2026 (reproduced): one adult with gas heat, ok_ui of $6,000 and no reported UI. The right-hand column was reproduced with the same $6,000 reported as unemployment_compensation, which gives the same total.

    Wages Merged tree as is With total_unemployment_compensation
    $6,000 countable $6,000, net $260 a month, band 1, $365 countable $12,000, net $760 a month, band 3, $235
    $18,000 countable $18,000 ($1,500 ≤ $1,696), $235 countable $24,000 ($2,000 > $1,696), $0
  • Why should, not critical: the head is correct against its base and CI is green. The conflict comes from a main commit merged after the last push, and git merge-tree shows a clean textual merge, but this has to change before merge (as Add Alabama LIHEAP regular heating assistance #9967 S1, Add Rhode Island LIHEAP regular heating assistance #9972 S1, Add Georgia LIHEAP regular heating assistance #9968 S1, Add Ohio HEAP regular heating assistance #9975 S1 and Add South Dakota LIEAP regular heating assistance #9974 S1). Unlike Ohio and South Dakota, Oklahoma UI is modeled, so values change, as in Alabama (Add Alabama LIHEAP regular heating assistance #9967 S1).

  • Fix: replace the entry with total_unemployment_compensation, add a modeled-ok_ui case like main's New Jersey regression case (nj_liheap_countable_income_person.yaml Case 7), and update rulespec-us#1535's countable-income output.

S2. Social Security counts net of the Part B premium in the gross income test, but the OAC counts gross income and allows the premium only as a deduction after the test

  • Where:
    • V/income/ok_liheap_countable_income.py:30-37 counts max_(social_security - medicare_part_b_premium, 0). Its comment says the OAC "is silent on premium withholding".
    • V/income/ok_liheap_income_deductions.py:30-35 deducts only the part of the premium that Social Security does not cover.
    • Pinned by T/ok_liheap.yaml Case 7 (line 256) and T/income/ok_liheap_countable_income.yaml Cases 2 (line 55) and 4 (line 126).
  • What the rule says (OAC Title 340):
    • 340:20-1-11(a): "All gross earned and unearned income the household receives, except for income exclusions per (b) of this Section, determines a household's financial eligibility".
    • (b) excludes only what SNAP (or TANF, SSP, ABD Medicaid or Child Care Subsidy) excludes. The SNAP list, 340:50-7-22, ends "No other income is excluded", and nothing in it excludes a Medicare premium.
    • (c): "The household must meet the gross income standard for its household size, per OKDHS Appendix C-7 before allowing applicable income deductions". The first deduction is "(1) verified non-reimbursed medical expenses paid by persons 60 years of age and older or persons considered disabled".
    • SNAP's medical-expense list, which the PR itself uses, includes "(vi) Medicare premiums" (340:50-7-31(a)(3)(A)). So the premium is an expense deducted after the test, not an exclusion from gross income.
    • (a)(1)(B): when every member is on SNAP, TANF, SSP, ABD Medicaid or Child Care Subsidy, "eligibility staff uses the gross income used to establish eligibility for the other program". SNAP's gross income counts Social Security before the premium.
  • What OKDHS tells its workers: Q, "Eligibility – Income" (updated August 12, 2026).
    • "Except for excluded income and the self-employed business expense, EA staff uses all other income the household receives to determine income eligibility."
    • "The household has to meet the gross income standard prior to receiving any income deductions."
    • "unreimbursed medical expenses for household members 60 years of age or older or with a disability" is listed among the deductions.
    • Q, "Energy Assistance Income Exclusions" has staff take "The gross unearned income" from an open benefit case.
  • The plan's own narrative agrees (p. 7): "OKDHS uses gross income to determine LIHEAP eligibility. Households must meet gross income eligibility standard first, and then countable net income is used to determine the benefit amount".
  • Against: plan item 1.9 checks "Excluding MediCare deduction" in the FY2025, FY2026 and FY2027 plans (p6, rendered). The batch reads that box as net, and HHS's Model Plan Reference Guide does not define it.
  • The PR body states its own rule: "Where the FY2026 plan and the OAC differ, the model follows the OAC; where the OAC is silent, it follows the plan". It applies that rule to child earnings, following 340:50-7-22(9) over the plan's unchecked "Earned income of a child under the age of 18" box. For Social Security it treats the OAC as silent, but (a), (b) and (c) together do address the premium: it counts in gross income and is deducted afterwards.
  • Impact:
    • Reproduced at head: the PR body's headline example (T/ok_liheap.yaml Case 7). In period 2026, a 70-year-old with $21,360 of Social Security and a $2,434.80 premium has countable income of $18,925.20, or $1,577 a month, within $1,696, and gets $235.
    • Under the OAC (hand-computed): gross income is $1,780 a month, above $1,696, so $0.
    • The reach is every Part B enrollee whose gross income falls between the limit and the limit plus the premium ($202.90 a month in 2026, about 12% of the one-person limit).
    • The payment band does not change for members 60 or older or disabled, because the PR already deducts any premium it does not net. Deeming does not change either, since (a)(4)(D) subtracts the same deduction. Only the eligible members' gross test changes.
  • Why should, not critical: the accepted plans check the box the PR follows, so its result has official support, and the PR documents the conflict (PR body; rulespec-us#1535 interpretation 1). Wave 1 rated a Social Security gross-versus-net error SHOULD even where the state's handbook and plan agreed (Add New Jersey LIHEAP regular heating assistance #9745 S1). Here the OAC, the staff guide and the plan narrative point to gross, and the PR mislabels the OAC as silent.
  • Fix:
    • Follow the OAC. Count social_security gross: add it to P/income/sources/unearned.yaml and drop the netting. Under (c)(1), deduct the whole medicare_part_b_premium for members 60 or older or disabled: replace unnetted_part_b_premium with the premium.
    • Then T/ok_liheap.yaml Case 7's first household gets $0, countable-income Case 2 counts $13,200 and Case 4 $15,600. Case 12 is unchanged at $265 (hand-computed).
    • Correct the PR body's headline example, its conflict table and Make a pa_income_tax_forgiveness variable #1535 interpretation 1.
    • If OKDHS confirms that its workers net the premium before the gross test, keep the netting instead, but replace "silent" with the actual conflict and cite the confirmation.

S3. The medical deduction misses payroll (pretax) premiums after main's #10046, and reads is_disabled instead of the definition the rule incorporates

  • Where: V/income/ok_liheap_income_deductions.py:26-28 (medical_eligible = age >= 60 | is_disabled) and :36-40. The premium inputs read are health_insurance_premiums_without_medicare_part_b, other_medical_expenses and medicare_part_b_premium; pre_tax_health_insurance_premiums is never read.
  • Source: OAC 340:20-1-11(c)(1) deducts "verified non-reimbursed medical expenses paid by persons 60 years of age and older or persons considered disabled, per OAC 340:50-5-4". The PR reads the expenses with SNAP's list, "(v) health, dental, and hospitalization policy premiums" (340:50-7-31(a)(3)(A)). Wages count gross (340:20-1-11(a)), so a premium withheld from pay is paid by the person.
  • Part 1, payroll premiums:
    • What changed on main: Document disjoint health premium inputs and correct consumer treatment #10046 (merged 2026-10-14) documents that "Pretax payroll payments belong only in pre_tax_health_insurance_premiums. The pretax and non-pretax sets are disjoint". Main's SNAP allowable medical expenses now include pre_tax_health_insurance_premiums (snap_allowable_medical_expenses.py:32).
    • Reproduced on the merged tree, period 2026, gas heat:
      • A 62-year-old with $12,000 of wages and a $1,200 payroll premium in the pretax input has deductions of $2,880, net income of $760 a month (band 3) and gets $235. With the same premium in the non-pretax input, deductions are $4,080, net income $660 (band 2), and the award $265.
      • Deeming: a citizen aged 40 with $4,500 of wages and an undocumented spouse aged 62 with $24,000 of wages and a $1,200 payroll premium. With the pretax input, the deemed amount is $16,344 and gross income $20,844 ($1,737 a month, above $1,696), so $0. With the non-pretax input, the deemed amount is $15,144 and gross income $19,644 ($1,637 a month), and the household gets $235.
  • Part 2, who counts as disabled:
    • 340:50-5-4 adopts 7 CFR 271.2. A member is disabled if he or she "(2) receives Supplemental Security Income ... or disability or blindness payments under Titles I, II, XIV, or XVI of the Social Security Act", or receives VA total-disability and the other listed benefits.
    • PolicyEngine implements that benefit-receipt test as is_usda_disabled, which SNAP's has_snap_elderly_disabled_member uses. The code comment says is_disabled "approximates the incorporated SNAP disability test".
    • Reproduced at head, period 2026: a 50-year-old with $9,000 of SSDI and $1,200 of medical costs, with is_disabled unset. is_usda_disabled is true, but nothing is deducted: net income is $750 a month and the award $235. With the deduction (reproduced by setting is_disabled), net income is $650 and the award $265.
  • Why should, not critical: the PR follows its base's conventions, and Document disjoint health premium inputs and correct consumer treatment #10046 merged after the last push. 2026 is claimed, though, and both gaps change awards.
  • Fix:
    • Add pre_tax_health_insurance_premiums to the medical expenses, preferably from a parameter list.
    • Use is_usda_disabled for "persons considered disabled". Keeping is_disabled alongside it would stand in for 340:50-5-4's permanent-disability categories, (a)(5) and (a)(9).
    • Add a payroll-premium case and an SSDI case, and update Make a pa_income_tax_forgiveness variable #1535's "Personal deductions" output.

S4. Eight parameter descriptions use verbs outside the house template, and three misdescribe the parameter

All 16 descriptions end with "under the Low Income Home Energy Assistance Program." with nothing after it. The template's verbs are limits, provides, sets, excludes, deducts and uses.

File:line Current Suggested
P/income/deductions/medical_age_threshold.yaml:1 "allows medical expense deductions beginning at this age or for a qualifying disabled member" "Oklahoma limits the medical expense deduction to members this age or older, or disabled, under the ..."
P/income/deeming/child_only_need_standard.yaml:1 "protects this monthly need amount for a represented children-only ineligible group before deeming its income" "Oklahoma deducts this monthly need standard from the income of a children-only group of ineligible members before deeming it under the ..."
P/income/limit/max_table_size.yaml:1 "publishes monthly income limits through this household size before adding a separate additional-person amount" "Oklahoma sets monthly income limits through this household size and adds a per-member amount above it under the ..."
P/income/limit/rounding_increment.yaml:1 "publishes monthly income limits in increments of this amount" "Oklahoma rounds monthly income limits up to this increment under the ..."
P/income/sources/earned.yaml:1 "counts these earned income sources for fully qualified households" "Oklahoma uses these sources as earned income under the ..."
P/income/sources/unearned.yaml:1 "counts these unearned income sources for fully qualified households" "Oklahoma uses these sources as unearned income under the ..."
P/payment/household_size_group.yaml:1 "assigns this payment group based on household size" "Oklahoma uses this household-size group for the regular heating payment under the ..."
P/payment/income_band.yaml:1 "assigns this payment band based on net monthly income" "Oklahoma uses this net monthly income band for the regular heating payment under the ..."

S5. References: two missing page lists, one missing #page=1, and FY2025 limit values dated and cited only from FY2026

File:line Problem Fix
P/income/sources/earned.yaml:18-19 and P/income/sources/unearned.yaml:46-47 "OAC 340:20-1-11(a)-(b)" opens R p576, but (a)(2)-(3) are on p577 and (b) on p578, and the title has no page list End the titles with "#page 576-578", as the variable's # PDF pages 576-578 comment already does
V/ok_liheap.py:14 C-7-A linked without a page; the winter tables are on p1 of 2 Add #page=1, as V/payment/ok_liheap_matrix_amount.py and the matrix parameters do
P/income/limit/fpg_rate.yaml:3, fpg_year_lag.yaml:5, max_table_size.yaml:3, rounding_increment.yaml:6 Dated 2025-10-01, citing only the FY2026 plan, the January 2026 notice and the 10/1/2026 C-7, although the registry claims FY2025 and FY2025 (like FY2023-FY2024) used 130%. The 2025 values come only from backward extrapolation Date them 2024-10-01 and cite FY2025 plan item 2.1, p. 9 and the 10/1/2024 C-7 or the December 17, 2024 notice

Consistency: #9972 S5, #9975 S6 and #9974 S3 rated wrong anchors and missing page lists SHOULD; the brief rates period or instant mistakes with limited reach SHOULD.

S6. One listed income source has no test that would fail if it were dropped

  • P/income/sources/earned.yaml:10 lists farm_operations_income, but its only test value is the -$1,200 loss in T/income/ok_liheap_countable_earned_income.yaml Case 1 (line 19), which floors to $0 whether or not the entry is there.
  • Removing the entry still passes the four files that compute earned income (32 cases). No other case sets farm income. Reproduced at head: a member with $12,000 of farm income counts $12,000 of earned income, so the entry matters.
  • Fix: give an existing case a positive farm_operations_income (for example $1,200 in countable-earned Case 1 alongside the loss case), or add one.
  • Two control mutations confirm the method. Dropping the NONE check from V/eligibility/ok_liheap_eligible.py:53 fails T/eligibility/ok_liheap_eligible.yaml Case 4. Dropping the eligible-member mask on the net-income deductions fails six cases in T/ok_liheap.yaml and T/income/ok_liheap_deemed_income.yaml.
  • By inspection, the rest is pinned:
    • every other listed source (all positive in at least one case), the per-source floors, the Social Security floor and the student exclusion's three conditions;
    • the deeming need switch, the tax-unit representative and TANF take-up;
    • each limit rounding and the size-0 mask;
    • the medical age and disability arms, the copay subsidy condition and the zero floor;
    • every responsibility route, the band and size-group edges, each fuel table, the roomer table, and the size-0 and NONE masks.
  • This is the only gap. Consistency: Add Georgia LIHEAP regular heating assistance #9968 S2 rated untested income sources SHOULD (checklist item 13).

Suggestions

G1. Fuels and routes that are eligible but paid $0, and an unknown-fuel heat-in-rent household that reports a surcharge

  • Reproduced at head (period 2026, no income):
    • SOLAR with an electric bill and OTHER with an other-fuel bill are ok_liheap_eligible: true with ok_liheap: 0. T/payment/ok_liheap_matrix_amount.yaml Case 7 asserts only the matrix amount.
    • UNSPECIFIED fuel with heat in rent and has_heating_expense: true is ineligible, with a matrix amount of $150 and an award of $0.
  • OAC 340:20-1-10(b)(1): "The main energy source may be electricity, natural gas, propane, kerosene, firewood, coal, butane, or heating oil." The PR body agrees that "Solar is not an approved main energy source". Either make SOLAR and OTHER direct payers ineligible so the flag matches the $0, or add a # See #9754 note.
  • The heat-in-rent tables cover "All Energy Sources", and heating_type documents UNSPECIFIED as "the right value when heat is included in rent and the fuel is unknown".
    • has_heating_expense means "Whether the household incurs home heating costs separately from its rent", which is what a verified surcharge shows (340:20-1-13(2)(B): "a rent receipt designating that the fuel cost is separate from the total shelter payment").
    • Accepting the flag for heat-in-rent households would let them be paid without a made-up fuel bill. The PR chose otherwise, and T/eligibility/ok_liheap_eligible.yaml Case 2 and T/ok_liheap.yaml Case 10 pin that choice, so this is optional.
  • Consistency: Add Alabama LIHEAP regular heating assistance #9967 G2, Add Georgia LIHEAP regular heating assistance #9968 G2, Add Ohio HEAP regular heating assistance #9975 G3.

G2. Backfilled years and the 2025 income rule

  • FY2025: OKDHS's December 17, 2024 notice prints all eight limits ($1,632, $2,215, $2,798, $3,380, $3,963, $4,546, $5,129, $5,712), matching the head. It can be fetched, unlike the Wayback captures, so cite it.
  • The rule in force on January 1, 2025 was the pre-September 2025 text: the struck 38-item exclusion list on R pp. 578-580.
    • For every modeled source it gives the same result as the SNAP list carried back. Its item (14) excludes "a minor dependent child's earnings when he or she is a full-time student".
    • Its deductions in (c) were the same: only "may" is struck on p580.
    • So the 2025 carry-back is harmless. Say so in Make a pa_income_tax_forgiveness variable #1535 interpretation 10.
  • Earlier years (unclaimed):
    • The FY2023 and FY2024 plans also set 130% (p8) and $40 / $500 (p9), so the carried-back limit rule and matrix fit.
    • Q says "Effective October 1, 2024, the Energy Assistance program does not consider resources". FY2024 and earlier therefore had the liquid-resource test in the old 340:20-1-11(e), which the backfill omits. Record this in the registry notes or Make a pa_income_tax_forgiveness variable #1535.

G3. Partnership and S-corporation income is counted as earned

  • P/income/sources/earned.yaml:11 lists partnership_s_corp_income as earned income, which gets the $240 deduction.
  • OAC 340:20-1-11(a)(2) defines earned income as income "for which he or she puts forth labor". Oklahoma SNAP treats S-corporation profit shares and the distributions of partners who are not self-employed as unearned (340:50-7-29(b)(2) and (c)(8)).
  • The comment says passive and active income cannot be told apart, which is fair. Moving the source to the unearned list would follow the SNAP classification for the common case, and only the $240 deduction is affected. Optional.

G4. Test and comment hygiene

  • Many comments lost the spaces around their numbers, for example:
    • T/ok_liheap.yaml:2 ("tested in2027", also in six other headers);
    • T/eligibility/ok_liheap_income_limit.yaml:3 ("Jan6,2026 officialannouncement monthly[1696,...], multipliedby12") and line 29 ("Unverified2025 estimate uses2024FPG15060 ...");
    • T/income/ok_liheap_countable_earned_income.yaml:3 ("Register pp576-578 and approved existing-net-input convention:12000+2400+600+0+1200=16200");
    • T/payment/ok_liheap_matrix_amount.yaml:3 ("matchingFY2026matrix literal36cells").
  • Several comments refer to internal decisions: "under contract v1.3" (seven file headers), "approved existing-net-input convention" and "the contracted schedule-classification approximation" (deeming Case 7). See Add Rhode Island LIHEAP regular heating assistance #9972 G7 and Add Ohio HEAP regular heating assistance #9975 G6.
  • T/eligibility/ok_liheap_income_limit.yaml:29 calls 2025 an "Unverified2025 estimate" that "Does not verify historical fullprogram", while the registry claims 2025.
  • is_full_time_student is set in T/income/ok_liheap_countable_earned_income.yaml Cases 3-7, but no Oklahoma variable reads it; the rule reads is_in_k12_school.
  • The isolated limit and matrix tests set heating inputs that those variables never read.

G5. PR body and issue housekeeping

  • "The tests were not run locally; CI validates them": all 68 pass locally at this head and on the merged tree (policyengine-core 3.32.29).
  • "replaced an itemized list of income types": the struck list was of income exclusions (R pp. 578-580).
  • The OAC was amended again effective 9-15-26 (43 Ok Reg No. 23), and Make a pa_income_tax_forgiveness variable #1535 says that filing "was not read".
    • The current text keeps every modeled rule, drops the liquid-resource subsection (340:20-1-11(e)), and puts surcharge verification for subsidized and unsubsidized heat-in-rent households in 340:20-1-13(2)(B)-(C).
    • Mention it for FY2027, and add 340:20-1-13(2) to the heat-in-rent row of the conflict table.
  • The make format box is unchecked, although CI lint passed.
  • rulespec-us#1535 still calls the PR "open as a draft" (it is not a draft) and says the tests were "not run locally".

G6. References polish

  • The undated C-7 and C-1 links will resolve to whatever edition OKDHS posts next. That affects P/income/deductions/earned_income.yaml:29-30 (titled "10/1/2026 edition"), the four limit parameters and V/eligibility/ok_liheap_income_limit.py:14. Prefer dated captures or the enrollment notices.
  • V/income/ok_liheap_income_deductions.py:14-15 relies on OAC 340:50-7-31(a)(3)(A)(v)-(vi) and 340:50-5-4, but links only Title 340 and C-7. Naming the sections in the reference comment would help. The LII copy of 340:50-7-22 could point to the official Title 340 file instead.

Verified correct

  • Matrix (C-7-A, p. 1; FY2026 Clearinghouse matrix):

    • All 36 cells.
    • Headings map natural gas, electricity, wood and coal to the first table, and LP gas, kerosene and heating oil to the second. The renter and roomer tables apply when "Heating Cost is Included in Rent" for "All Energy Sources".
    • Rows "$0 - $400", "$401 - $700" and "$701 - ineligible"; columns 1-3, 4-6 and 7+; roomer $0 for four or more.
    • Plan item 2.6 gives $40 / $500 in every plan from FY2023 to FY2027 (p9-10). There is no bill cap ("estimated benefit amounts"; one payment per year).
  • Limits:

    • 130% of the prior year's guideline (C-7: "equal to or less than ... 130 percent"; plan 2.1).
    • Rounding the monthly base and the per-member amount up separately reproduces every figure: FY2025 $1,632 ... $5,712 (December 17, 2024 notice); FY2026 $1,696 ... $5,867 and $596 (C-7 10/1/2025 and the January 6, 2026 notice); FY2027 $1,729 ... $6,037 and $616 (C-7 10/1/2026).
    • The exact-dollar cases (1.3 × 15,960 / 12 = 1,729.00; 1.3 × 31,200 / 12 = 3,380.00) do not round up.
    • Monthly gross income is rounded to the nearest dollar, and the limit is inclusive.
  • Federal floor (42 USC 8624(b)(2)(B)). FY2026 monthly limit against 110% of the higher (2026) guideline, by household size:

    Size 1 2 3 4 5 6 7 8 Each additional
    Limit $1,696 $2,292 $2,888 $3,483 $4,079 $4,675 $5,271 $5,867 $596
    110% $1,463.00 $1,983.67 $2,504.33 $3,025.00 $3,545.67 $4,066.33 $4,587.00 $5,107.67 $520.67
    • FY2025's limits clear 110% of the 2025 guideline ($1,434.58 to $4,963.75, plus $504.17 per member). FY2027's clear 110% of the 2026 guideline; the 2027 guideline would have to rise 18% to bind (1.3 / 1.1).
    • The per-member amount exceeds 110% of the guideline increment, so the margin grows with size.
  • Timing: winter enrollment opened December 17, 2024 (FY2025), January 6, 2026 (FY2026) and is planned for January 12-20, 2027 (FY2027 plan p4). Period N reads FY N on January 1, so each season falls in the year the PR maps.

  • Income (OAC 340:20-1-11; R pp. 576-581; Q):

    • Gross earned and unearned income, with the SNAP exclusions: student earnings under 340:50-7-22(9), exempt "unless not attending school or dependent" (Q); housing subsidies; SNAP.
    • Each listed source maps to an OAC category or a checked 1.9 box, including Cash gifts (financial_assistance), retirement distributions and military retirement pay. TANF counts once, through the take-up-gated tanf.
    • Losses are floored per source, and net business inputs stand in for the documented 50% self-employment rule ((c)(4)).
    • No Oklahoma state supplement is modeled on main or at head, as the PR says.
  • Deeming ((a)(4)(A)-(E)): the earned deduction, the other (c) deductions and Schedule IX are subtracted before the gross test. IX-A matches the TANF need-standard parameter ($398 ... $1,436), and IX-B matches C-1 7/1/2026 p5 ($193 ... $1,333). The PR subtracts the earned deduction once, a reasonable reading of (A) and (D).

  • Deductions after the gross test ((c)): $240 per employed member, capped at earnings (C-7, all three editions; Q "currently, $240"); child support paid; the copay only with a subsidy; medical expenses for members 60 or older (plus S3).

  • Household and eligibility:

    • Size excludes ineligible aliens ((h)(3)); a unit with no eligible member is ineligible.
    • SNAP alien eligibility under 340:50-5-67(a), with P.L. 119-21 from July 2025. January reads keep FY2025 on the earlier list.
    • No categorical eligibility (plan 1.4 No) and no asset test (plan p14; Q).
    • Heat-in-rent renters and roomers need a verified surcharge (340:20-1-19(d)(1)-(2); 340:20-1-13(2)(B)-(C); plan 2.3). Subsidized households with out-of-pocket costs get the same benefit (340:20-1-10(g)(3)). NONE is ineligible.
  • Code patterns:

    • No hard-coded policy values. defined_for = StateCode.OK is on all 13 variables, all 16 parameters are read, and the formulas are vectorized. The shared fpg() helper and the TANF need standard are reused.
    • Matrix keys come from bracket lookups that always return 1-3, so non-residents cannot hit a missing key. Tests that mix TX and OK rows (eligibility Case 4, ok_liheap Case 6, matrix Case 6) pass.
  • Tests:

    • 68 of 68 pass locally at head (policyengine-core 3.32.29) and on the merged tree. Periods are plain (2025-2027), and every case sets heating_type.
    • Hand-checked against C-7, C-7-A, C-1 and the OAC:
      • limit Cases 1-3 (all 21 values);
      • T/ok_liheap.yaml Cases 1, 2, 4, 5, 9 and 11;
      • matrix Cases 1-3;
      • deemed-income Cases 2, 3, 5 and 8;
      • net-income Case 4.
  • Changelog: changelog.d/ok-liheap.added.md is top level and typed added.

Checklist results (LIHEAP wave 2a)

  1. State plan and manual first: pass, with S2. I read the following and verified every encoded cell, limit, standard, deduction and branch:
    • the FY2023-FY2027 plans (rendered checkboxes for FY2025-FY2027), OAC chapter 340:20 and the incorporated 340:50 sections in the current text;
    • the 2025 adoption in R (rendered strikethrough), C-7 (10/1/2025 and 10/1/2026), C-7-A, C-1 Schedule IX, OKDHS's two enrollment notices and the Quest staff pages.
  2. Income definition: pass on sources, exclusions, loss floors, rounding and deeming. Social Security counts net of Part B in the gross test against the OAC and staff guidance (S2). The medical deduction misses payroll premiums and reads is_disabled (S3), and UI needs the total after rebase (S1).
  3. Backdating: FY2025-FY2027 are represented and correct, apart from S2 and S3.
    • The 2025 values come from parameters dated 2025-10-01 and 2025-09-15 (S5), and the pre-September 2025 rule gives the same results for modeled sources (G2).
    • Unclaimed earlier years: the FY2023-FY2024 plans confirm 130% and $40-$500, but the backfill omits the resource test that applied before October 1, 2024 (G2).
    • The published FY2027 C-7 is used.
  4. Household and arrangement rules: pass. Subsidized and public housing, heat in rent with the surcharge, renters and roomers, no categorical eligibility and the $40 / $500 range are all handled. Priority affects enrollment only, so no supplement is due. Two fuels are eligible but paid $0 (G1).
  5. Tests: 68 cases, more than 8 hand-checked.
    • Covered: FY2026 sizes 1-8, FY2027 sizes 1-10 and FY2025 sizes 1, 8 and 9; the limit edge at ±50 cents; the band edges; the 3/4/6/7 size edges; the age-60 and age-18 boundaries; plain periods.
    • Gap: one source (S6).
  6. Parameter descriptions: eight are off-template and three misdescribe the parameter (S4). None has a trailing clause.
  7. References: two missing page lists, a missing #page=1, and FY2025 values cited only from FY2026 (S5). Polish is in G6.
  8. Wiring: pass.
    • The programs.yaml entry and coverage line are well formed, and the registry test passes on the merged tree. There is no aggregate wiring, which matches OR, NY, NJ and MD on main (none feeds household_state_benefits).
    • defined_for gating is on every variable, and the state-gating check passes on the merged tree. Take-up applies only through tanf, as in the siblings.
  9. Axiom: valid queued line. rulespec-us#1535 is open, labelled pe-parity, dispatch-ready and current to 9b6b0dac45. It needs updates for S1-S3 and S6 (see below).
  10. Branch and CI: all checks are green at head. The branch is 8 ahead and 82 behind main. There are no textual conflicts, but main's UI guard fails on the merged tree (S1), and Document disjoint health premium inputs and correct consumer treatment #10046 changes the premium inputs (S3).
  11. Integrate modeled state unemployment insurance into income flows #9558: S1. Oklahoma UI (ok_ui) is modeled from 2022, so values change on the merged tree (reproduced).
  12. IIJA and FY2027: no IIJA supplement in any FY2023-FY2027 plan or in the OAC.
    • 340:20-1-14(2) allows discretionary "supplements" from unencumbered funds to SSP, TANF and SNAP recipients; they are not IIJA-specific and are reasonably out of scope.
    • FY2027: the 10/1/2026 C-7 is encoded, C-7-A is unchanged, the FY2027 plan keeps 130% and $40 / $500, and the 9-15-26 OAC amendment leaves the modeled rules unchanged (G5).
  13. Mutation check: S6. Both control mutations fail as expected.
  14. Health premiums after Document disjoint health premium inputs and correct consumer treatment #10046: S3. Reproduced on the merged tree: a band change and an eligibility flip through deeming.
  15. State-gated index defaults: pass. ok_liheap_household_size (int) feeds bracket lookups (max_(size, 1)), the matrix keys are always 1-3, and ok_liheap_dwelling_type (enum) is used only in where. The mixed TX and OK test rows run in one simulation without error.

CI status

28 of 28 checks pass at 9b6b0dac45 (gh pr checks 9970, run of 2026-10-12). The three "skipping" entries belong to a superseded run on the same SHA.

Branch status

Axiom line

axiom: TheAxiomFoundation/rulespec-us#1535 queued: valid format, and the issue meets the bar.

  • rulespec-us#1535 is open and labelled pe-parity (plus enhancement), with no comments, and was last updated 2026-10-12.
  • It is dispatch-ready under the Add AMT parameters for 2020-2023 #1467 standard. It has:
    • proposed us-ok/ module paths with corpus status;
    • verbatim OAC, Register, plan, C-7, C-7-A, C-1 and federal text;
    • required outputs for all 13 variables;
    • 16 companion tests hand-derived from the sources ("None is taken from policyengine-us output").
  • It describes head 9b6b0dac45 correctly, including the Medicare reading and the one not followed (interpretation 1), the heat-in-rent surcharge, the deeming details and the 2025 carry-back (interpretation 10).
  • Updates needed when the fixes land:
    • total_unemployment_compensation in the countable-income output (S1);
    • the Social Security reading, companion tests C15-C16 and ok_liheap.yaml Case 7 (S2);
    • payroll premiums and is_usda_disabled in the personal-deductions output (S3), and the farm case (S6);
    • the 9-15-26 amendment it says was not read, and the stale "open as a draft" and "not run locally".

Next steps

  1. S1: rebase onto main, switch P/income/sources/unearned.yaml:14 to total_unemployment_compensation, and add a modeled-ok_ui case.
  2. S2: count Social Security gross in the gross test and deduct the whole Part B premium under (c)(1). Or, if OKDHS confirms that its workers net the premium, keep the netting and correct the conflict table.
  3. S3: deduct pre_tax_health_insurance_premiums, use is_usda_disabled for "persons considered disabled", and add a case for each.
  4. S4-S6: align the eight descriptions, fix the references and the limit-parameter dates, and give farm_operations_income a positive test value.
  5. Optionally address G1-G6, then refresh the PR body and rulespec-us#1535 and re-request review.

0 critical and 6 should-address findings, plus 6 suggestions.

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 for 6 should items; details in the full report above. Verified: all 36 Appendix C-7-A cells, the $40–$500 range, 26 of the 27 printed FY2025–FY2027 limits, the deductions, the deeming steps, the heat-in-rent surcharge, and the 110% floor at every size. All 68 tests pass and CI is green. (1) Merge blocker from main's #9558: unearned.yaml:14 reads the raw unemployment_compensation, so modeled ok_ui drops out on the merged tree. (2) Social Security is counted net of Part B in the gross test. OAC 340:20-1-11(a)–(c), the OKDHS staff guide and the plan narrative count gross income and deduct the premium after the test. Plan box 1.9 supports the PR's reading, but the regulation governs, and the PR calls the OAC "silent". Headline retiree: $235 at head, $0 under the OAC. (3) The medical deduction misses pre_tax_health_insurance_premiums (separate on main since #10046), and it uses is_disabled instead of the 7 CFR 271.2 test (is_usda_disabled). (4) Eight parameter descriptions are off the house template or misdescribe their parameters. (5) References: missing page lists and anchors, and the limit parameters are dated 2025-10-01 although FY2025 is claimed. (6) farm_operations_income is never positive in any test.

hua7450 and others added 2 commits October 15, 2026 15:13
- S1: Merge blocker from #9558: the unearned list reads the raw unemployment_compensation, so modeled ok_ui drops ou
- S2: Social Security counts net of Part B in the gross test; the OAC counts gross income and deducts the premium af
- S3: The medical deduction misses pretax payroll premiums (#10046) and reads is_disabled instead of the 7 CFR 271.2
- S4: Eight parameter descriptions are off the house template, and the student parameter misdescribes its scope
- S5: References: two missing page lists, a missing #page=1, and FY2025 limits dated and cited only from FY2026
- S6: farm_operations_income has no test that would fail if it were dropped

Also applies the in-scope suggestions. Tests not run locally; CI validates.

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

hua7450 commented Oct 15, 2026

Copy link
Copy Markdown
Collaborator Author

Thanks for the review. Fixes pushed in f0e2f40.

The branch also merges upstream/main (PRs 9558 and 10046). Your floor check shows Oklahoma's limit above 110% of the poverty guideline at every size in FY2025-FY2027, so this PR does not add the shared gov.hhs.liheap.fpg_floor parameter (42 U.S.C. 8624(b)(2)(B)).

  • S1: unearned.yaml now lists total_unemployment_compensation, so modeled ok_ui counts when no amount is reported. New countable-income Case 5 covers this. Its wage inputs give a $432 weekly benefit (DOL's Oklahoma average is $432.08). Fifteen weeks come to $6,480 of ok_ui, or $540 a month, which falls in band 2 and pays $265 ($365 without UI).

  • S2: Done as you proposed. social_security is now a gross unearned source, the netting is gone, and members 60 or older or disabled deduct the whole Part B premium after the gross test. The unearned.yaml comment and the PR body's conflict table set OAC 340:20-1-11(a) and (c), 340:50-7-31(a)(3)(A)(vi) and the plan narrative (page 7) against the plan item 1.9 box. Updated cases:

    • ok_liheap.yaml Case 7 now pays $0 to both retirees.
    • Case 12 counts $12,000 and deducts $4,234.80, for $265.
    • Countable-income Cases 2 and 4 count $13,200 and $15,600, matching your hand values.
    • The PR body's headline example now uses Case 12.
  • S3: The medical deduction now reads is_usda_disabled and snap_allowable_medical_expenses. That SNAP aggregate already sums, per person, the non-pretax premiums (with Part B for Medicare enrollees), pre_tax_health_insurance_premiums and other_medical_expenses. This is the modeled part of the 340:50-7-31(a)(3)(A) list, so I reused it in place of a new parameter list and left out SNAP's $35 threshold; PA CCW sums the same three inputs.

    • I did not keep is_disabled alongside it. 340:50-5-4(a)(5) and (a)(9) also require a government disability retirement or VA survivor benefit, which the flag does not show. NY HEAP, NC LIEAP and SNAP use is_usda_disabled alone. The PR body lists the categories that have no inputs.
    • New deductions Case 3 covers payroll and after-tax premiums: $4,320 each at age 62 ($265), and only the $2,880 earned allowance at age 40 ($235).
    • New ok_liheap.yaml Case 13 gives an SSDI recipient at the 2026 average of $1,630 a month the $1,200 medical deduction ($235). A member flagged disabled with no qualifying benefit gets no medical deduction.
    • Deductions Case 1 now sets is_usda_disabled. Net-income Case 4 now reports its 39-year-old's $6,000 as social_security_disability, so the $1,200 medical deduction still applies and net income stays $23,520.
  • S4: All eight descriptions now use your suggested wording, and the student parameter says "elementary or high school students".

  • S5:

    • The earned and unearned titles end with #page 576-578, and the ok_liheap C-7-A link opens #page=1.
    • The four limit parameters are dated 2024-10-01 and all cite the December 17, 2024 notice. fpg_rate and fpg_year_lag also cite FY2025 plan item 2.1 (page 9), and max_table_size and rounding_increment the 10/1/2024 C-7 capture.
    • No values change.
  • S6: Countable-earned Case 8 adds $1,200 of net farm income to $12,000 of wages, for $13,200.

  • G1: Comment only, under the settled heating_type decision. Directly billed OTHER and SOLAR stay eligible with a $0 matrix amount as a documented coverage limit. With heat in rent, UNSPECIFIED carries no surcharge bill, so it pays $0; the default is tracked in Default heating_type to electricity and remove the UNSPECIFIED-gated state heating adapters #9754. ok_liheap_eligible.py now records both and cites 340:20-1-13(2)(B)-(C) for surcharge verification.

  • G2: Partly done. FY2025 now cites plan item 2.1 and the December 17, 2024 notice (S5). The PR body and the rulespec-us issue note that the pre-September 2025 exclusion list gives the same result for every modeled source. History is out of scope for this PR, so FY2023-FY2024 stay unclaimed, and the resource test that applied before October 1, 2024 is recorded only in the rulespec-us issue.

  • G3: Kept as earned income. The earned.yaml comment and a new not-modeled row give the reasons. The input mixes active partners' earnings with S corporation and passive shares. The KS, KY, OR and NY lists on main count it as earned, and only the $240 deduction differs.

  • G4: Done.

    • Comments are re-spaced and no longer use the internal "contract" wording.
    • The 2025 limit case now describes FY2025.
    • The unread is_full_time_student and bill inputs are removed from the earned-income, limit and matrix cases.
    • heating_type stays in every case under the LIHEAP test convention.
    • No expected value changed.
  • G5: Done in the PR body:

    • the struck list is now described as income exclusions (Register pages 578-580);
    • the September 15, 2026 amendment is noted for FY2027;
    • 340:20-1-13(2)(B)-(C) is added to the heat-in-rent rows;
    • make format is checked.

    The rulespec-us issue no longer calls the PR a draft. The body still says the tests were not run locally because we leave test runs to CI. Thanks for running all 68 at 9b6b0da.

  • G6: Partly done.

    • The LII links now point to the official Title 340 file.
    • earned_income.yaml adds the dated 10/1/2025 C-7 capture.
    • ok_liheap_income_limit adds the December 2024 notice.
    • The deduction variable names 340:50-5-4 and 340:50-7-31(a)(3)(A)(v)-(vi).
    • The 10/1/2026 C-7 keeps its live link, titled by edition. No dated capture of that edition was available because the Wayback index was offline on 2026-10-15.
  • LIHEAP wave 2a: encode Oklahoma LIHEAP regular heating assistance TheAxiomFoundation/rulespec-us#1535 is refreshed to this head.

@hua7450
hua7450 requested a review from DTrim99 October 15, 2026 21:08

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement Oklahoma LIHEAP regular heating assistance

2 participants