Repository navigation
Conversation
- 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 Report✅ All modified and coverable lines are covered by tests. 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
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
…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>
PR Review: Add Oklahoma LIHEAP regular heating assistancePR #9970: Add Oklahoma LIHEAP regular heating assistance (author: hua7450, head Scope: the regular payment of Oklahoma Human Services' (OKDHS) LIHEAP Winter Heating Program for federal fiscal years 2025-2027. The PR covers:
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), Overall: the matrix, the income limits, the deeming standards and the deduction amounts are right where the sources print them.
There are no critical findings. The six should-address items:
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:
Line numbers refer to head Source Documents
Critical (Must Fix)None. Should AddressS1. Merge blocker: after merging main, the unearned list reads the reported-only
|
| 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-37countsmax_(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-35deducts only the part of the premium that Social Security does not cover.- Pinned by
T/ok_liheap.yamlCase 7 (line 256) andT/income/ok_liheap_countable_income.yamlCases 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.yamlCase 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.
- Reproduced at head: the PR body's headline example (
- 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_securitygross: add it toP/income/sources/unearned.yamland drop the netting. Under (c)(1), deduct the wholemedicare_part_b_premiumfor members 60 or older or disabled: replaceunnetted_part_b_premiumwith the premium. - Then
T/ok_liheap.yamlCase 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_forgivenessvariable #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.
- Follow the OAC. Count
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 arehealth_insurance_premiums_without_medicare_part_b,other_medical_expensesandmedicare_part_b_premium;pre_tax_health_insurance_premiumsis 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.
- 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
- 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'shas_snap_elderly_disabled_memberuses. The code comment saysis_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_disabledunset.is_usda_disabledis true, but nothing is deducted: net income is $750 a month and the award $235. With the deduction (reproduced by settingis_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_premiumsto the medical expenses, preferably from a parameter list. - Use
is_usda_disabledfor "persons considered disabled". Keepingis_disabledalongside 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_forgivenessvariable #1535's "Personal deductions" output.
- Add
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 ..." |
- "for fully qualified households" is also misleading:
V/income/ok_liheap_deemed_income.pyapplies both lists to ineligible members. P/income/student_earned_income_age_limit.yaml:1uses a template verb but says "secondary-school students". The rule (340:50-7-22(9): "an elementary or high school student") and the code (is_in_k12_school) also cover elementary students.- The other eight fit:
earned_income(deducts);fpg_rate(limits);fpg_year_lag(uses);student_earned_income_age_limit(excludes); and the four matrix files (provides). - Consistency: Add Alabama LIHEAP regular heating assistance #9967 S4, Add Rhode Island LIHEAP regular heating assistance #9972 S4, Add Georgia LIHEAP regular heating assistance #9968 S3, Add Ohio HEAP regular heating assistance #9975 S5, Add Florida LIHEAP regular heating assistance #9969 S2, Add South Dakota LIEAP regular heating assistance #9974 S2 and Add New Jersey LIHEAP regular heating assistance #9745 S6.
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:10listsfarm_operations_income, but its only test value is the -$1,200 loss inT/income/ok_liheap_countable_earned_income.yamlCase 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:53failsT/eligibility/ok_liheap_eligible.yamlCase 4. Dropping the eligible-member mask on the net-income deductions fails six cases inT/ok_liheap.yamlandT/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: truewithok_liheap: 0.T/payment/ok_liheap_matrix_amount.yamlCase 7 asserts only the matrix amount. - UNSPECIFIED fuel with heat in rent and
has_heating_expense: trueis ineligible, with a matrix amount of $150 and an award of $0.
- SOLAR with an electric bill and OTHER with an other-fuel bill are
- 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 #9754note. - The heat-in-rent tables cover "All Energy Sources", and
heating_typedocuments UNSPECIFIED as "the right value when heat is included in rent and the fuel is unknown".has_heating_expensemeans "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.yamlCase 2 andT/ok_liheap.yamlCase 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_forgivenessvariable #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_forgivenessvariable #1535.
G3. Partnership and S-corporation income is counted as earned
P/income/sources/earned.yaml:11listspartnership_s_corp_incomeas 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:29calls 2025 an "Unverified2025 estimate" that "Does not verify historical fullprogram", while the registry claims 2025.is_full_time_studentis set inT/income/ok_liheap_countable_earned_income.yamlCases 3-7, but no Oklahoma variable reads it; the rule readsis_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_forgivenessvariable #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 formatbox 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 andV/eligibility/ok_liheap_income_limit.py:14. Prefer dated captures or the enrollment notices. V/income/ok_liheap_income_deductions.py:14-15relies 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-gatedtanf. - 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.OKis on all 13 variables, all 16 parameters are read, and the formulas are vectorized. The sharedfpg()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_liheapCase 6, matrix Case 6) pass.
- No hard-coded policy values.
-
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.yamlCases 1, 2, 4, 5, 9 and 11;- matrix Cases 1-3;
- deemed-income Cases 2, 3, 5 and 8;
- net-income Case 4.
- 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
-
Changelog:
changelog.d/ok-liheap.added.mdis top level and typedadded.
Checklist results (LIHEAP wave 2a)
- 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.
- 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). - Backdating: FY2025-FY2027 are represented and correct, apart from S2 and S3.
- The 2025 values come from parameters dated
2025-10-01and2025-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.
- The 2025 values come from parameters dated
- 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).
- 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).
- Parameter descriptions: eight are off-template and three misdescribe the parameter (S4). None has a trailing clause.
- References: two missing page lists, a missing
#page=1, and FY2025 values cited only from FY2026 (S5). Polish is in G6. - Wiring: pass.
- The
programs.yamlentry 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 feedshousehold_state_benefits). defined_forgating is on every variable, and the state-gating check passes on the merged tree. Take-up applies only throughtanf, as in the siblings.
- The
- Axiom: valid
queuedline. rulespec-us#1535 is open, labelledpe-parity, dispatch-ready and current to9b6b0dac45. It needs updates for S1-S3 and S6 (see below). - 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).
- 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). - 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).
- Mutation check: S6. Both control mutations fail as expected.
- 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.
- State-gated index defaults: pass.
ok_liheap_household_size(int) feeds bracket lookups (max_(size, 1)), the matrix keys are always 1-3, andok_liheap_dwelling_type(enum) is used only inwhere. 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
- 8 commits ahead of
mainand 82 behind. The merge base is1d699fec2d(Share one HHS SMI helper for LIHEAP income limits #10019); main is at8ae01aa3cb. git merge-tree --write-tree PolicyEngine/main 9b6b0dac45exits 0 with no textual conflicts.programs.yamlmerges tocoverage: DC, Riverside County, MA, IL, IN, KS, KY, MD, MS, NC, NE, NJ, NY, OK, OR, TX.- Semantic conflicts: main's Integrate modeled state unemployment insurance into income flows #9558 guard fails on the merged tree (S1), and Document disjoint health premium inputs and correct consumer treatment #10046 makes payroll premiums a disjoint input (S3).
- On the merged tree, the PR's 68 cases, the registry test and the state-gating and parameter code-health checks pass.
- The other main commits since the merge base that touch inputs the Oklahoma variables read are Uprate premium inputs by premium series, not CMS out-of-pocket spending #10085 (premium uprating) and Charge the Part D income-related premium only to Part D enrollees #10115 (Part D income-related premium). Neither changes them.
- The wave 2a siblings (Add Alabama LIHEAP regular heating assistance #9967-Add Ohio HEAP regular heating assistance #9975) touch the same LIHEAP coverage line, which is a branch note, not a finding.
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(plusenhancement), 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").
- proposed
- It describes head
9b6b0dac45correctly, 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_compensationin the countable-income output (S1);- the Social Security reading, companion tests C15-C16 and
ok_liheap.yamlCase 7 (S2); - payroll premiums and
is_usda_disabledin 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
- S1: rebase onto main, switch
P/income/sources/unearned.yaml:14tototal_unemployment_compensation, and add a modeled-ok_uicase. - 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.
- S3: deduct
pre_tax_health_insurance_premiums, useis_usda_disabledfor "persons considered disabled", and add a case for each. - S4-S6: align the eight descriptions, fix the references and the limit-parameter dates, and give
farm_operations_incomea positive test value. - 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
left a comment
There was a problem hiding this comment.
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.
- 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>
|
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
|
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
defined_for = StateCode.OKis_snap_immigration_status_eligiblefor 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.heating_typeor 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 itsheating_typestands in for the surcharge, and the flag alone does not qualify. Housing-assistance inputs do not change the result.heating_typeNONE is ineligible.Countable income
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.tanfaggregate, which includesok_tanf, once per household.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 throughis_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.Benefit
Each cell lists household sizes 1–3 / 4–6 / 7 or more.
ok_liheap_dwelling_typeROOMERok_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.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.Years covered
A calendar-year period reads the parameters in force on January 1. Formulas are undated and
verified_yearsis"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
partnership_s_corp_incomeas 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.is_disabledflag is not used because it shows no benefit receipt.immigration_statuscategory; not counted in household size.ssiis the federal benefit.Where the FY2026 plan and the OAC differ, the model follows the OAC; where the OAC is silent, it follows the plan:
Two readings are recorded in code notes but not followed:
Microsimulation: the microsimulation datasets carry no heating inputs, so population totals are about $0 until #9754 lands. Callers must send
heating_typewith the matching fuel bill.Test plan
72 YAML cases in 12 files cover:
Every case specifies
heating_type. The tests were not run locally; CI validates them.make formatchangelog.d/axiom: TheAxiomFoundation/rulespec-us#1535 queued
🤖 Generated with Claude Code