Repository navigation
Add Rhode Island LIHEAP regular heating assistance - #9972
Conversation
- Start regular heating payments in FY2026 with a dated in_effect switch: no FY2025 benefit matrix is published, so 2025 and earlier pay $0. - Use the eligibility primary-bill test for subsidized row F. - Count military retirement pay, retirement distributions and gambling winnings; floor each unearned source at zero. - Count TANF through the take-up-gated tanf variable instead of ri_works. - Deduct the Medicare Part B premium per manual III.H (p21); rename the deduction list to deduction_sources. - Put RI on the LIHEAP coverage line and shorten its note. - Add 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 #9972 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 4 7 +3
Lines 76 147 +71
Branches 2 3 +1
=========================================
+ Hits 76 147 +71
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:
|
Follow the FY2026/FY2027 application instructions over the 2020 manual's household-head exception, drop the unused is_household_head test inputs, and note the plan-versus-manual conflict for workers' compensation and TDI/TCI. 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>
Heat-in-rent households receive the FY2026 matrix rows G-I: a $400 direct grant, or an $80 secondary-electric grant ($50 when subsidized) when a separate electric bill is reported, with the $350 utility enhancement on the secondary-electric grant. Subsidized heat-in-rent tenants without a utility burden are ineligible. The research-date payment gate is removed, so earlier years backfill the FY2026 schedule as unverified estimates. Utility provider and grant receipt stay an assumption; no new input. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Calls liheap_smi_limit from PR 10019 instead of repeating the HHS floor-then-floor calculation. Limits are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PR Review: Add Rhode Island LIHEAP regular heating assistancePR #9972: Add Rhode Island LIHEAP regular heating assistance (author: hua7450, head Scope: Rhode Island's LIHEAP regular (primary) heating grant, run by DHS through seven Community Action Agencies, for FY2026. The PR covers:
Crisis, cooling, weatherization and the $20.01 SNAP nominal payment are out of scope. The PR changes 31 files: 15 parameters, 7 variables, 7 test files (55 cases), Overall: the FY2026 policy values are right.
There are no critical findings. The five should-address items:
All 55 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. The values each proposed fix would produce are hand computations and are labelled as such. The untested-logic claims in S2 and S3 were confirmed by 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
|
| File:line | Current | Suggested |
|---|---|---|
P/income/sources/earned.yaml:1 |
"counts these earned income sources" | "Rhode Island uses these sources as earned income under the Low Income Home Energy Assistance Program." |
P/income/sources/unearned.yaml:1 |
"counts these unearned income sources" | "Rhode Island uses these sources as unearned income under the ..." |
P/income/minimum_income_age.yaml:1 |
"counts individual income beginning at this age" | "Rhode Island excludes the income of members below this age under the ..." |
P/income/rental_income_rate.yaml:1 |
"counts this share of rental receipts" | "Rhode Island uses this share of rental income as countable income under the ..." |
P/income/deduction_sources.yaml:1 |
"deducts these reported expenses from income" | "Rhode Island uses these expenses as income deductions under the ..." |
P/payment/utility_enhancement.yaml:1 |
"adds this enhancement to the primary federal Low Income Home Energy Assistance Program grant credited to a qualifying gas or electric distribution-company account" (verb, and a clause after the program name) | "Rhode Island provides this enhancement with a primary heating grant credited to a gas or electric distribution-company account under the Low Income Home Energy Assistance Program." |
The other nine fit: smi_rate (limits), interest_exclusion and student_age_limit (excludes), the three amount files and heat_in_rent (provides), fpg_rates (sets) and fpg_year_lag (uses). Consistency: #9967 S4 and #9745 S6.
S5. One anchor opens the wrong page, Appendix H is linked without its page and from two hosts, and multi-page titles lack page lists
| File:line | Problem | Fix |
|---|---|---|
P/income/rental_income_rate.yaml:13 (and the comment at line 2) |
M #page=17 opens the documentation list. The rule is at the foot of p. 16, "Fifty percent (50%) of rental income shall be included in the total income for eligibility determination.", and on p. 20, "50 percent of Gross Rental Income". The comment says "pages 17 and 20". Appendix M p1 does corroborate the 50% |
#page=16, a title ending #page 16,20, and correct the comment |
P/income/interest_exclusion.yaml:13, P/income/sources/earned.yaml:23, P/income/sources/unearned.yaml:53, V/income/ri_liheap_income.py:18 |
Appendix H (media/9671) has no anchor, so it opens p1 (identity and residence documents). The interest rule and the income list are on p2 |
Add #page=2 |
V/income/ri_liheap_income.py:18,20; P/income/student_age_limit.yaml:15 |
The same May 2025 instructions are cited from DHS (media/9671, footed "Appendix H") and from westbaycap.org (footed "Appendix C", although the parameter title says Appendix H); the variable lists both |
One entry, on the DHS host, #page=2 |
P/income/sources/earned.yaml:18-21, P/income/sources/unearned.yaml:48-51 |
"Sections III.E-G" opens p14, but the cited sources and exclusions run to p20; "Sections 1.8 and 1.9" opens p5, but 1.9 runs to p7 | Titles ending #page 14-20 and #page 5-7 |
Consistency: #9745 S7 rated wrong anchors SHOULD. The author's #1537 interpretation 20 already records the p17 error.
Suggestions
G1. Backfilled years pay FY2026 amounts that the earlier sources contradict
- Every single-dated parameter carries back to every earlier period. Earlier years differ:
- FY2025 grants ranged "$64 to $1,148" (the DHS press release of Sept 30, 2024; DIV 1-5 p2).
- The FY2023 and FY2024 matrices are published and differ in every row A-F cell and in rows H and I ($125 / $75).
- The enhancement was $515 for 2024 and $450 for 2023 (PUC Order 24925, p. 2: "raised the LIHEAP Enhancement Grant to $515.00 for 2024, where in 2023 it was $450.00").
- Period 2025 pays $861 to
T/ri_liheap.yamlCase 5's household; FY2025's top grant was $1,148. The limits do carry back correctly: FY2024 ($35,674 for one person) and FY2025 ($39,101) reproduce. - The branch gated the payment with
payment/in_effect.yaml(false before 2025-10-01) untilaa4ccc33b9removed it. Merged NJ gates witheligibility/in_effect.yaml. - The PR documents the backfill and labels the 2025 cases unverified, so this is a suggestion (checklist item 3). Either restore the gate, or encode the published FY2023-FY2024 matrices and enhancements. In both cases, drop or reword the 2025 award assertions (
T/ri_liheap.yamlCases 5 and 11,T/payment/ri_liheap_base_payment.yamlCase 9), which pin values the FY2025 sources contradict.
G2. Give row F its own amounts
V/payment/ri_liheap_base_payment.py:42maps row F to bandlen(p.fpg_rates) + 1, so it reuses row E's cells. That is right for FY2026, where row F equals row E ($657 / $159 / $268).- In FY2023 and FY2024, row F ("Sec. 8 w/ Primary Heating Bill", $696 / $205 / $310) was below row E ($981 / $355 / $533 and $932 / $256 / $426). A future matrix like those could not be encoded without a code change, and the comment's "lowest payment" holds only by coincidence.
- Add a row-F amount per fuel (for example a sixth breakdown key), so the index no longer depends on the length of the band-rate list.
G3. Cite DHS's current summaries for three income rules
- Part B deduction (correct as is). The draft FY2027 summary (file p. 3) reads "Social Security Administration (SSA) benefits (Including Medicare deduction)*" with "*meaning the Medicare amount deducted is not counted". So plan 1.9 and M III.H agree. Cite it in
P/income/deduction_sources.yamland drop the "conflict" row from the PR body. - Lottery winnings. Plan 1.9 leaves "winnings from lotteries" unchecked. The FY2026 summary, the draft FY2027 summary and both editions of Appendix H omit them; only M p17 lists "Cash Prizes and Lottery Winnings". The choice is documented, but the weight of current DHS documents points the other way. Consider dropping
gambling_winnings, or say in the comment that the current summaries omit it. - Self-employment. The FY2026 summary (p1) still lists "Self-employment income (60%)", so M's 40% deduction is current. The deferral to net business income is reasonable; cite the summary in
P/income/sources/earned.yaml.
G4. Sources and naming
- M's cover reads "PUBLISHED: JUNE 11, 2019". The PR body and titles call it the 2020 manual.
- The appendix footers ("RI LIHEAP Policy Manual Appendix H, May 2025"; July 2026) and the footer of the FFY2026 notice to applicants ("RI LIHEAP Policy Manual July 2025") show that later editions exist. None was found online. Say so in the PR body, as Add OR income subtraction of taxable social security benefits #1537 interpretation 18 does.
V/eligibility/ri_liheap_income_limit.py:16cites a CDN copy of the FY2027 sheet. DHS hosts it athttps://dhs.ri.gov/media/12266/download?language=en.- The PR describes the FY2027 instructions but links only the May 2025 edition. The July 2026 edition is
media/12306.
G5. FY2027 enhancement
DHS's Oct 2, 2026 filing (Docket 26-34-GE) says "Accounts receiving a 2027 Primary benefit will receive one additional credit", with the amount still to be set. The $350 carry-forward is documented as unverified, which is fine. Record the filing in P/payment/utility_enhancement.yaml and the registry notes, and update the value when DHS answers the docket's data requests. Rhode Island pays no IIJA supplement; the enhancement is ratepayer-funded under § 39-1-27.12, so checklist item 12 does not apply.
G6. PR body and issue housekeeping
- Add a conflict-table row: plan 2.3, p. 8 answers "No" for "Renters Living in subsidized housing?", while M p6 makes "Subsidized renters with no utility burden" ineligible (Add OR income subtraction of taxable social security benefits #1537 interpretation 6; as Add Alabama LIHEAP regular heating assistance #9967 G6).
- "Coal, other, solar and unspecified fuels have no matrix column" should read "no matrix amount": the Other column exists and is blank in rows A-F. Appendix B has no coal or solar box, so those fuels would be marked "Other".
- The
make formatbox is unchecked, although CI lint passed. - rulespec-us#1537 still calls the PR "open as a draft".
G7. Test hygiene
- About twenty comment lines lost the spaces around their numbers. Examples:
T/income/ri_liheap_income.yaml:3("approximation:12000+2400+600+1200+1200=17400; no additional40% deduction"), line 394 ("arepositive"), line 456 ("underp20");T/eligibility/ri_liheap_income_limit.yaml:3("annual60%SMI") and line 31 ("all14");T/payment/ri_liheap_base_payment.yaml:6, 23, 58, 86("bills10", "bandB deliverables805", "ExplicitNONE", "Oil861 remains861");T/ri_liheap.yaml:228("October2025 DIV1-1", "direct400").
- Comments such as
T/income/ri_liheap_income.yaml:3and:34call conventions "approved", which refers to internal decisions. - The income, limit, band and household-size tests set
heating_typeand fuel bills that those variables never read. - Five files open with "no final award is asserted", but
T/income/ri_liheap_income.yamlCase 15 and the base-payment file assert payment amounts. - SOLAR and OTHER households with a bill are eligible but get $0 (the matrix's Other column is blank in rows A-F). That is consistent with the matrix; as in Add New Jersey LIHEAP regular heating assistance #9745 G1 and Add Alabama LIHEAP regular heating assistance #9967 G2, either make the flag match or note it.
Verified correct
- Matrix (FY2026):
- Rows A-E: Deliverables 861 / 805 / 752 / 704 / 657, Natural Gas 232 / 211 / 192 / 175 / 159, Electric 393 / 357 / 324 / 295 / 268.
- Row F 657 / 159 / 268, at any income. Rows G $400, H $80, I $50.
- Oil, kerosene, propane and wood pay from Deliverables (Appendix B: "Oil Kerosene Propane Wood/Pellets").
- The plan 2.6 range of $50-$861 matches, with the state-funded enhancement outside it.
- Enhancement: $350 per primary grant (DIV 1-1 p1; Order 25579 p3). It is added to gas and electric grants and to heat-in-rent grants paid to an electric account, never to Deliverables or the direct $400. That follows § 39-1-27.12(e) and PUC 1-5 ("credited to a customer's account by the utility once the federal grant to that household has been received").
- Limits:
- All 14 FY2026 limits (42,252 ... 126,756) and all 14 FY2027 limits (43,410 ... 130,230) reproduce from SMI $135,424 and $139,136: floor(0.6 x SMI) = 81,254 and 83,481, times the 45 CFR 96.85 shares, floored.
- The limit is inclusive ("equal to or less than"; Case 3's 42,252 / 42,252.01 pair).
- Bands:
- Tops are the 2025 guideline x 0.75 / 1 / 1.25 / 1.5, rounded half up and upper-inclusive: 11,738 / 15,650 / 19,563 / 23,475 for one person. 41 of the 42 printed 75%, 125% and 150% tops for sizes 1-14 reproduce.
- Following the labeled 125% rate for size 2 (26,438, not the printed 31,725) is a documented, reasonable reading of a typo.
- The FPG lag gives the 2025 guideline for period 2026.
- Timing: heating assistance runs 10/01/2025-04/15/2026 (plan 1.1, p4), and period 2026 reads January 1, 2026.
- Income (plan 1.8 gross; M III.E-H):
- Members 18 and over count; full-time students 18-23 are excluded, head or not, following the current Appendix H over M p20.
- Each source is floored at zero. Rental and farm rent count at 50%. Interest is counted above $500 once per household, and dividends in full.
- TANF is read through the take-up-gated
tanf. A child's SSI is excluded. SNAP is excluded. - Child support and alimony paid are deducted, and child care only when unsubsidized.
medicare_part_b_premiumis deducted, and it is already net of Medicare Savings Program coverage.
- Household: size counts citizens and 8 U.S.C. 1641 qualified statuses (DACA excluded), matching M p12-13. Nonqualified members' income counts (M p12).
- Eligibility:
- Rhode Island residence. No categorical eligibility (plan 1.4 No) and no asset test (plan 2.3 No).
- A heating obligation, or heat in unsubsidized rent, qualifies. Subsidized heat in rent needs an electric bill (M p6). NONE is ineligible.
- Code patterns:
- No hard-coded values.
defined_for = StateCode.RIon six variables, andri_liheapis gated byri_liheap_eligible. - Vectorized formulas. All 15 parameters are read. The shared
fpg()andliheap_smi_limit()helpers are reused.
- No hard-coded values.
- Tests:
- 55 of 55 pass locally at head (policyengine-core 3.32.29) and on the merged tree. Periods are plain.
- Hand-checked:
T/ri_liheap.yamlCases 1-4 and 9-10; income Cases 8, 10, 11, 12 and 15; all 15 base-payment cells; all 28 limits; the 9 one-person and 5 two-person band edges; the 2025 band tops (11,295 / 18,825).
- Changelog:
changelog.d/ri-liheap.added.mdis top level and typedadded.
Checklist results (LIHEAP wave 2a)
- State plan and manual first: pass, with S2. I read the accepted FY2026 plan (rendered checkboxes), the FY2026 matrix, the FY2027 income sheet, M, the May 2025 and July 2026 appendices, DHS's FY2026 and draft FY2027 summaries, the FY2023-FY2025 sources and the PUC enhancement record, and verified every encoded cell, limit and band. The one blank cell (row G Electric) is paid without a stated reason (S2).
- Income definition: pass at head. Gross income with M's deductions; Social Security net of Part B, matching DHS's own gloss; losses floored per source; annual income. After rebase the list must read
total_unemployment_compensation(S1). Lottery and self-employment notes are in G3. - Backdating: limits reproduce FY2024-FY2025. Payments and the enhancement do not, which the PR documents (G1). FY2027 limits are used; no FY2027 matrix is published.
- Household and arrangement rules: pass on subsidized and public housing, heat in rent (rows G-I), renters, no categorical eligibility and crisis-only priority. Row G Electric is S2; the SNAP nominal payment is documented as out of scope.
- Tests: 55 cases, more than 8 hand-checked. Limits for sizes 1-14 in both years, band edges, the limit edge and plain periods are covered. Gaps are in S2-S3.
- Parameter descriptions: six fall outside the template (S4).
- References: one wrong anchor, missing Appendix H anchors, a duplicate host and missing page lists (S5).
- Wiring: pass. The
programs.yamlentry and coverage line are well formed. No aggregate wiring, which matches OR, NY, NJ and MD on main.defined_forgating is on every variable. No take-up beyond TANF's. - Axiom: valid
queuedline. rulespec-us#1537 is open, labelledpe-parity, dispatch-ready and current toc8b6cafa25; it needs updates for S1-S2 (see below). - Branch and CI: all checks are green at head. 11 ahead and 82 behind main. No textual conflicts, but main's UI guard fails on the merged tree (S1).
- Integrate modeled state unemployment insurance into income flows #9558: S1. No modeled RI UI exists, so the effect today is the guard failure only.
- IIJA and FY2027: no IIJA supplement. The $350 is ratepayer-funded, continues into FY2027 with the amount pending (G5), and the FY2027 limits are encoded.
- Mutation check: S3, plus the row G Electric cell in S2.
CI status
28 of 28 checks pass at c8b6cafa25 (gh pr checks 9972, run of 2026-10-12). The three "skipping" entries belong to a superseded run on the same SHA.
Branch status
- 11 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 c8b6cafa25exits 0 with no textual conflicts.programs.yamlmerges tocoverage: DC, Riverside County, MA, IL, IN, KS, KY, MD, MS, NC, NE, NJ, NY, OR, RI, TX.- Semantic conflict: main's Integrate modeled state unemployment insurance into income flows #9558 guard fails on the merged tree (S1). The PR's 55 cases pass there.
- The other main commits since the merge base that touch premiums or Medicare (Document disjoint health premium inputs and correct consumer treatment #10046, Uprate premium inputs by premium series, not CMS out-of-pocket spending #10085, Charge the Part D income-related premium only to Part D enrollees #10115) leave
medicare_part_b_premiumand every listed source variable in place. - 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#1537 queued: valid format, and the issue meets the bar.
- rulespec-us#1537 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 module paths with corpus status, verbatim manual, plan, matrix and instruction text, required outputs for all 7 variables, and companion tests derived from the matrix, manual, instructions, guidelines and PUC record ("None is taken from policyengine-us output").
- It describes
c8b6cafa25correctly. It already records the row G Electric gap (interpretation 3), the p17 anchor (interpretation 20), the 2019 manual edition (interpretation 18) and the backfill (interpretation 12). - Updates needed when the fixes land:
- the input list and a UI case (S1);
- the row G Electric decision (S2);
- the new branch cases (S3);
- the draft FY2027 summary's Medicare gloss for interpretation 11 (G3);
- the stale "open as a draft".
Next steps
- S1: rebase onto main, switch
P/income/sources/unearned.yaml:12tototal_unemployment_compensation, and add a UI case. - S2: decide the row G Electric cell ($0 or a documented $400) and add the two electric heat-in-rent cases.
- S3: add the minor-interest, all-sources and size-0 cases.
- S4-S5: align the six descriptions and fix the anchors and duplicate Appendix H entries.
- Optionally address G1-G7, then refresh the PR body and rulespec-us#1537 and re-request review.
0 critical and 5 should-address findings, plus 7 suggestions.
Verdict: REQUEST_CHANGES
DTrim99
left a comment
There was a problem hiding this comment.
Requesting changes for 5 should items; details in the full report above. The FY2026 values check out: all 15 primary benefit cells, rows F–I, the $350 enhancement and all 28 FY2026/FY2027 income limits. The Part B treatment is correct, all 55 tests pass, and CI is green. (1) Merge blocker from main's #9558: unearned.yaml:12 lists the raw unemployment_compensation, so the guard fails on the merged tree. (2) Matrix row G prints no Electric amount, but the PR pays $400 to unsubsidized electric-heat households with heat in rent and no electric bill. This is undocumented and untested. (3) Logic that passes every test even when broken on purpose: the interest exclusion for minors and students, 8 of the 18 unearned sources, and the size check in eligibility. (4) Six parameter descriptions are off the house template. (5) Reference anchors: rental_income_rate cites page 17 (the rule is on pages 16 and 20); the Appendix H links lack #page=2 and come from two hosts.
- S1: The unearned list reads the raw unemployment_compensation, so main's #9558 guard fails - S2: Row G prints no Electric amount, but the PR pays $400 for electric heat in unsubsidized rent with no electric - S3: Three pieces of logic have no test that fails when they break: excluded members' interest, 8 unearned sources - S4: Six parameter descriptions fall outside the house template - S5: Wrong rental anchor, Appendix H without page 2 and on two hosts, multi-page titles without page lists 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 09fddd6. The branch also merges upstream/main (PRs 9558 and 10046). Rhode Island deducts no health insurance premium other than Medicare Part B, so 10046 changes nothing here. The 60% SMI limit stays above the federal 110% poverty floor (42 U.S.C. 8624(b)(2)(B)) for sizes 1–20 in FY2025–FY2027; the smallest margin is $1,833, at size 20 in FY2025. So this PR does not add the shared
|
PavelMakarchuk
left a comment
There was a problem hiding this comment.
Approving. All round-1 should-address items (S1-S5) are resolved, the row G Electric fix matches the FY2026 matrix, and CI is green. S6-S8 are non-blocking: the 110% floor first binds at 23 people, the row G Electric value is correct but belongs in a parameter, and the UNSPECIFIED heat-in-rent path needs a test. Please pick them up here or in a quick follow-up; for S6, reuse gov/hhs/liheap/fpg_floor.yaml once #9968 or #9969 merges.
Program Review
IDs: C = critical, S = should address, G = suggestion. S1-S5 and G1-G7 keep the prior review's numbers; S6-S8 and G8-G17 are new.
Source Documents
- PDF: FY2026 Grant Amounts and Income Eligibility (matrix) (1 page)
- PDF: FY2026 Rhode Island LIHEAP State Plan (49 pages; checkbox states exist only in the renders)
- PDF: DHS LIHEAP Manual, published June 11, 2019 (Docket 4290) (28 pages; "M" below)
- PDF: Appendix H, May 2025 (2 pages) and DHS Summary of the FFY2026 State Plan (10 pages), read from Wayback captures
- PDF: PUC Order 25579 (4 pages), DHS answer to DIV 1-1 in Docket 25-38-GE (2 pages), and the Docket 26-34-GE FFY2027 filing (2 pages)
- Law: 42 U.S.C. 8624(b)(2)(B)
- Unverifiable here (not wrong): dhs.ri.gov returns a Cloudflare 403 to automated clients, and no reachable archive exists for the July 2026 Appendix H (
media/12306), the draft FFY2027 summary (media/11711) and the FFY2027 income sheet (media/12266). The prior review quoted all three; the FY2027 limits match a third-party copy of the sheet. - Year: FY2026 verified; FY2027 limits encoded; FY2027 payments and earlier years are carry-forward or backfill estimates. Tests use 2025-2027.
- Scope: Incremental — changes since the prior review, plus unresolved prior findings
- Reviewed head SHA: 09fddd6
- Mode: incremental from c8b6caf
Paths: P/ = policyengine_us/parameters/gov/states/ri/dhs/liheap/, V/ = policyengine_us/variables/gov/states/ri/dhs/liheap/, T/ = policyengine_us/tests/policy/baseline/gov/states/ri/dhs/liheap/.
Branch Status
13 commits ahead of main and 38 behind; merges cleanly. Staleness did not affect any finding. Informational only.
Critical (Must Fix)
None.
Should Address
S6. The federal 110%-of-poverty floor is not encoded
- Defect:
V/eligibility/ri_liheap_eligible.py:42tests onlyincome <= limit;V/eligibility/ri_liheap_income_limit.py:24has no floor. - Evidence: 42 U.S.C. 8624(b)(2)(B) bars excluding a household with income "less than 110 percent of the poverty level"; the plan assurances, #page=45 restate it.
- Impact: the 60% SMI limit falls below the floor from size 21 in 2025 and size 23 in 2026-2027 (size 19 in the 2024 backfill). Period 2026, 23 people, $150,000: limit $148,694 < floor 1.1 × $136,650 = $150,315, so the model pays $0; with the floor, band 3 gas pays $542. The author's margins are correct, but the model does not cap household size at 20.
- Severity: SHOULD, not CRITICAL as #9969 C1, because the first binding size in FY2026-FY2027 is 23 (FL: 15), which no realistic household reaches. The legal gap is the same.
- Fix: in
ri_liheap_eligible, use(income <= limit) | (income < p_hhs.fpg_floor * guideline)withfpg()and the RI year lag (generalize theP/payment/fpg_year_lag.yamldescription or add an eligibility lag). Reusegov/hhs/liheap/fpg_floor.yaml(1.1) from #9968/#9969 after one merges, or add the identical file. Round the product to cents (#9969 S4). Add the 23-person case and a $150,314.99 / $150,315.01 pair.
S7. The blank row G Electric cell is in the formula, not a parameter
- Defect:
V/payment/ri_liheap_base_payment.py:78sets the row G grant to 0 forfuels.ELECTRICITY;P/payment/heat_in_rent.yaml:6-7showsdirect: 400for every fuel. Every other matrix cell is a parameter. - Impact: the parameter tree and API show $400 for all fuels, and a later matrix with a row G Electric amount needs a code change.
- Severity: SHOULD: the literal is 0, which the repo rule allows, and
T/ri_liheap.yamlCase 12 pins the result. - Fix: split
directintodeliverables/natural_gas/electricity(0) /other, selected with the existing fuel mapping anddefault=hir.direct.other. A list parameter of excluded fuels is a lighter option.
S8. Heat in rent with an UNSPECIFIED fuel gets the $400 row G grant, with no test and an unclear comment
- Defect: an unsubsidized heat-in-rent household with no electric bill and
heating_typeUNSPECIFIED (the default), SOLAR or COAL is eligible and gets $400 (V/payment/ri_liheap_base_payment.py:78, 82). No test covers this; a mutation that pays row G only for the printed columns passes all 60 cases. - Comment:
:61-64sits in the rows A-Fselect, so "UNSPECIFIED receives none" is scoped to rows A-F and is not wrong. But it does not say that heat in rent then pays row G, so a reader can take it as the whole outcome. - Evidence: the matrix prints row G under Deliverables, Natural Gas and Other, and leaves Electric blank. The
HeatingTypedocstring uses UNSPECIFIED for heat in rent with an unknown fuel, which can be electric. SOLAR and COAL read as "Other" (Appendix B has no box for them). - Severity: SHOULD under the untested-branch rule (as #9967 S5): it is the default heat-in-rent path, and it sets the award.
- Fix: decide the UNSPECIFIED outcome (with S7, the
defaultbranch carries it), and extend the comment to say what row G pays. Add aT/ri_liheap.yamlcase: unsubsidized, heat in rent,pre_subsidy_electricity_expense: 0,heating_type: [UNSPECIFIED, SOLAR, COAL], expectingri_liheap_eligible: [true, true, true]andri_liheap: [400, 400, 400]under the current code.
Suggestions
- G8. Lottery winnings: the author took round 1's documentation option, which is acceptable. The reviewer still leans toward removing
gambling_winnings(P/income/sources/unearned.yaml:42): the 600-dpi check confirms that plan 1.9 leaves "winnings from lotteries" (p6) and "Other" (p7) unchecked, and only M p17 counts them. If removed, income Case 22 expects 20,000 and Case 26 expects 17,200. - G9. Self-employment: round 1 accepted net business income. The comment at
V/income/ri_liheap_income.py:38("approximate the gross-receipts rule") is inaccurate. With the M III.H, p20 40% allowance, the error is receipts × (0.4 − expense ratio), so net is exact only at a 40% expense ratio. Correct the comment (andP/income/sources/earned.yaml:2-5), citingks_liheap_countable_earned_income.py:11. Optionally add a 0.4 deduction parameter for the self-employment sources. 0.6 × net is not a correct fix; it removes expenses twice. - G10. Pin the
subsidized |term atV/payment/ri_liheap_base_payment.py:78with a base-payment unit (subsidized, heat in rent, no bill, gas) expecting 0. - G11. Pin the documented eligible-but-$0 result for COAL, SOLAR and OTHER (
V/eligibility/ri_liheap_eligible.py:36-38). - G12. Coverage: no
integration.yaml; the end-to-end limit edge is tested for size 1 only; the negative-interest floor and deductions of excluded members are untested. - G13. Add the FY2026 summary (
media/9371#page=1) to theunearned.yamlreferences, and name mortgage or sales-contract payments, contract income and AmeriCorp allowances as not represented. - G14. Titles:
earned.yaml:26"Countable Income" is not a summary heading; markutility_enhancement.yaml:20"(2027 credit amount not yet set)"; use one Appendix H title style. - G15. "So the sources agree" (
P/income/deduction_sources.yaml:9-14) rests on the draft FFY2027 gloss; replace the draft link when DHS posts the final summary. - G16.
T/income/ri_liheap_income.yaml:738: strike pay and VA benefits come from plan 1.9 (p6), not the manual;:706-712cites DLT figures without a link. - G17. Nits:
addsforri_liheap_household_sizeandri_liheap; the changelog name differs from the branch; optionally archive the DHS links.
Investigated and cleared: workers' compensation (REJECTED: plan 1.9 does not name it; M p16 governs, and Appendix H counts TDI); the size-2 125% band cell (REJECTED: $31,725 repeats the 150% cell, and 55 of 56 cells follow the rate; likely a matrix typo); the $350 enhancement (MATCH: DIV 1-1 p1, Order 25579 p3); the FY2027 limits (MATCH: all 14 reproduce from 60% of $139,136).
Prior Findings
| ID | Finding | Status |
|---|---|---|
| S1 | Raw unemployment_compensation |
RESOLVED (guard 4/4; Case 25) |
| S2 | Row G Electric paid $400 | RESOLVED ($0, Case 12); encoding in S7 |
| S3 | Untested mask, sources, size gate | RESOLVED (each mutation fails) |
| S4 | Six off-template descriptions | RESOLVED |
| S5 | Anchors, hosts, page lists | RESOLVED |
| G1 | Backfill contradicts FY2023-25 | STILL OPEN, declined by author |
| G2 | Row F own amounts | STILL OPEN, declined by author |
| G3 | Cite DHS summaries (Part B, lottery, self-employment) | RESOLVED per the round-1 documentation option (author kept the entry with a documented note); see G8, G9 |
| G4 | Manual edition, DHS hosts | RESOLVED |
| G5 | FFY2027 enhancement filing | RESOLVED |
| G6 | PR body housekeeping | RESOLVED (rulespec-us#1537 per author) |
| G7 | Test hygiene | RESOLVED |
PDF Audit Summary
| Category | Count |
|---|---|
| Changed values confirmed on rendered pages | 34 |
| Source differences confirmed (code path + 600-dpi), documented in the PR | 2 (G8, G9) |
| Investigated and cleared | 2 |
| External documents matched | 2 |
| Missing from repo (documented or no input) | 6 |
| Repo behavior without source support | 6 (one is S8) |
| Page anchors: correct / wrong / unverifiable | 45 / 0 / 7 |
| Pages rendered | 107 (98 at 300 dpi, 9 at 600 dpi) |
Validation Summary
| Check | Result |
|---|---|
| CI | 29/29 pass |
| Local tests | 60/60 RI cases pass |
| Mutation checks | Prior S2/S3 mutations fail; S8 and G10 mutations survive |
| Regulatory accuracy | FY2026 values correct; S6; documented choices in G8, G9 |
| References | 0 missing, 0 wrong; 7 unverifiable |
| Code patterns | S7 |
| New test values | 5 cases reproduce by hand |
Review Severity: COMMENT
Next Steps
To auto-fix issues: run the fix-pr workflow for this PR.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Thanks for the review. Fixes pushed in 2376cb4.
Thanks also for checking workers' compensation, the size-two 125% cell, the $350 enhancement and the FY2027 limits; those stay as they are. |
PR Review (round 2): Add Rhode Island LIHEAP regular heating assistancePR #9972 (author: hua7450). This round reviews head
Neither merge had a hand-resolved conflict. The PR's Path prefixes, as in round 1:
Line numbers refer to SummaryZiming fixed all five round-1 should items:
Of the seven suggestions, five are fixed (G3–G7). G1 (backfilled history) and G2 (separate row-F amounts) are declined with reasons I accept, as in #9967–#9970. His second commit also fixes Pavel's three should items:
Pavel's G8–G17 are all done or answered; G8 (lottery winnings) is kept with documentation, which I accept. There are no new critical or should findings. Three new suggestions:
Batch checks:
I checked every new expectation by hand: 18 new cases, plus the cases whose unread inputs were removed. No existing expected value changed. CI is 29/29 green at the head. The branch is 15 commits ahead of Prior findings status
Pavel's review (between rounds). He approved with three non-blocking should items. All are fixed, and every suggestion is answered:
New findingsCritical (must fix)None. Should addressNone. Suggestions1. After #10182, count military SBP survivor annuities through
2. After #10168, count Rhode Island's State Supplementary Payment (
3. Pin the floor's cent rounding.
Verified
Checklist results (LIHEAP wave 2a)
Axiom line assessmentValid:
CI status29 pass, 0 pending, 0 failed (run 39324242551 on head
Branch status
Verdict: APPROVE |
# Conflicts: # policyengine_us/programs.yaml
Adds Rhode Island's LIHEAP regular heating assistance. The model counts citizens and qualified noncitizens for household size and the income of adult members, tests income against 60% of state median income, and places the household in one of five bands by the prior year's poverty guideline. It pays the FY2026 primary heating grant for the household's fuel, plus the $350 utility enhancement on natural gas and electric grants, and the FY2026 heat-in-rent grants. In FY2026, a one-person household with $10,000 of wages and its own heating bill receives $861 for fuel oil, $582 for natural gas ($232 plus $350) and $743 for electricity ($393 plus $350). If heat is included in its unsubsidized rent, it receives $400, or $430 ($80 plus $350) when it pays a separate electric bill. With electric heat included in that rent and no electric bill, it receives $0, because matrix row G leaves the Electric cell blank. Earlier years and FY2027 reuse the FY2026 payment schedule as unverified estimates. Income below 110% of the prior-year poverty guideline also passes the income test under the federal floor, which first exceeds the 60% SMI limit at 23 qualified members in FY2026 and FY2027.
Fixes #9963
Regulatory authority
The model follows the DHS manual published June 11, 2019 and filed with the Public Utilities Commission in Docket 4290. Later editions exist: the Appendix H footers read "RI LIHEAP Policy Manual Appendix H May 2025" and "RI LIHEAP Policy Manual Appendix H July 2026", and the footer of the FFY2026 notice to applicants reads "RI LIHEAP Policy Manual July 2025". A search found none of these editions online.
Eligibility
defined_for = StateCode.RIis_citizen_or_legal_immigrant, with no SNAP-specific waiting periods or bars. A household with no qualified member is ineligible. The income of nonqualified adults counts.liheap_smi_limithelper (#10019): floors 60% of the four-person state median income, applies the federal size share and floors again. This order reproduces all 14 published limits in FY2026 and FY2027; the sources do not state the order. One person: $42,252 in FY2026 and $43,410 in FY2027. The limit is inclusive.gov.hhs.liheap.fpg_floor(1.1), a file byte-identical to the copy in #10279. The guideline uses the bands' one-year lag (gov.states.ri.dhs.liheap.fpg_year_lag): the 2025 guideline in FY2026 and the 2026 guideline in FY2027. The 60% SMI limit falls below the floor from size 23 in FY2026 and FY2027 (23 people: limit $148,694 and floor $150,315 in FY2026; $152,770 and $155,012 in FY2027), from size 21 in the 2025 backfill and from size 19 in the 2024 backfill.ri_liheap_income_limitkeeps the published limit.has_heating_expense) or a positive heating bill qualifies. Heat included in unsubsidized rent qualifies. A household with housing assistance or in public housing whose rent includes heat needs a positive electric bill (pre_subsidy_electricity_expense), whatever heating obligation it reports.heating_typeNONE is ineligible.Countable income
total_unemployment_compensation: the reported amount, or modeled state unemployment insurance when none is reported), strike benefits, Social Security (gross), SSI, pensions, military retirement pay, retirement account distributions, survivor benefits, railroad retirement, alimony, child support received, workers' compensation, disability benefits (standing in for Temporary Disability and Temporary Caregivers Insurance), cash support (financial_assistance), ordinary dividends, veterans benefits, estate income and gambling winnings. Floors each source at zero, so a loss in one source offsets nothing.tanfaggregate, which includesri_works, once per household.Benefit
heat_in_rent.direct): Deliverables, Natural Gas and Other print $400, and the blank Electric cell is $0, so electric heat included in unsubsidized rent with no electric bill is eligible but receives $0. Coal and solar read the Other cell ($400) because Appendix B has no coal or solar box. As a modeling assumption, an unspecified fuel (heating_typeUNSPECIFIED, the input for heat in rent with an unknown fuel) also reads the Other cell; when the building heats with electricity, the matrix pays $0 and the model overpays $400. A household with a separate electric bill receives $80 on that electric account (row H), or $50 in subsidized housing (row I), plus the $350 enhancement: $430 or $400. A subsidized heat-in-rent household with no electric bill is ineligible.has_heating_expenseis set; it then receives $0 becauseheating_typeis a required input (Default heating_type to electricity and remove the UNSPECIFIED-gated state heating adapters #9754).Years covered
A calendar-year period reads the parameters in force on January 1. Formulas are undated and
verified_yearsis"2026". Earlier years backfill the FY2026 grants and enhancement as unverified estimates. The FY2025 plan (section 2.6, page 9) gives a $64 minimum and $1,148 maximum benefit, compared with FY2026's $50 and $861, so 2025 and earlier results do not reproduce those years' awards.A search for the FY2025 grant matrix and enhancement found neither. It covered the ACF clearinghouse (the FY2025 matrix links return 404 on both clearinghouse domains), Wayback captures of the clearinghouse benefit page and of DHS's FY2025 guidelines and LIHEAP pages (income limits only), the FY2025 state plan, and Docket 23-33-EL: the DHS filing of October 8, 2024, the Division memo of November 13, 2024 and PUC Order 25281, which set the charge but not the grant. Earlier years differ as well: the FY2024 matrix differs from FY2026 in every cell, and PUC Order 24925 sets the enhancement at $515 for 2024 and $450 for 2023. RI Energy's April 2025 reconciliation shows FY2025 credits in multiples of $360, but no document states that amount, so the model does not encode it.
No adopted FY2027 matrix was found. DHS's October 2, 2026 filing in Docket 26-34-GE (page 2) says "Accounts receiving a 2027 Primary benefit will receive one additional credit from the LIHEAP Enhancement Fund" and leaves the amount to DHS, so the model carries the $350 forward as an unverified estimate.
Not modeled and source conflicts
veterans_benefits, which counts in full.ssiis the federal benefit.has_heating_expenseis set, and it receives $0 becauseheating_typeis a required input (#9754).Where the FY2026 plan and the manual differ, the model follows the manual:
gambling_winnings.disability_benefitsandworkers_compensation.Plan section 1.9 (page 6) counts Social Security "Including MediCare deduction". Only DHS's draft FFY2027 plan summary (page 3) glosses this, as "meaning the Medicare amount deducted is not counted"; read that way, the plan agrees with manual section III.H (page 21).
deduction_sources.yamlcites the draft until DHS posts a final FFY2027 summary; a search found none online. The model counts Social Security gross and deductsmedicare_part_b_premium.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
74 YAML cases in 8 files cover:
total_unemployment_compensation($10,010), every listed unearned source at once ($17,300), the Part B deduction, support and unsubsidized child care deductions, the zero floor, business, estate and rental losses, a negative interest entry that cannot offset another member's interest ($12,200), and child support and alimony paid by an excluded student and a nonqualified member deducted ($46,920);Every eligibility and payment case specifies
heating_type; the income, limit, band and household-size cases omit it because those variables do not read it. CI validates the cases.make formatchangelog.d/axiom: TheAxiomFoundation/rulespec-us#1537 queued
🤖 Generated with Claude Code