Skip to content

Add Arkansas LIHEAP regular heating assistance - #9973

Open
hua7450 wants to merge 13 commits into
mainfrom
ar-liheap
Open

hua7450 wants to merge 13 commits into
mainfrom
ar-liheap

Conversation

@hua7450

@hua7450 hua7450 commented Oct 7, 2026 •

Copy link
Copy Markdown
Collaborator

Adds a partial Arkansas LIHEAP regular heating model using FY2025 and FY2026 schedules. The model counts qualified members for household size and every member's countable income, applies the 20% earned-income disregard, tests monthly income against limits built from state median income and the poverty guidelines, and reads the five published fuel matrices by monthly income band and household-size group. In FY2026, a five-person household heating with fuel oil receives $570 with no income and $497 with $286 a month of TEA cash assistance.

Fixes #9964

The state application, in both the FY2025 form and the current form, requests work income only from members "18 and older & not a full-time student" and does not define a full-time student. The formula applies the adopted FFY 2025 manual's definition. It excludes the earnings of every member under 18, of a full-time college student up to age 23 (read as inclusive) who is a dependent of a household member, and of an 18-year-old high-school student; unearned income still counts. Independent full-time college students, and dependent ones aged 24 or older, report work income like other adults. Final-award tests cover members aged 17 and 18 and independent full-time students aged 22, 23 and 24.

Policy verification remains partial. The interest allowance's assessment unit remains unconfirmed. The model does not apply the manual's full-time-work and emancipation exceptions to the 18-year-old high-school rule or its half-time attendance condition on a child's earnings. The FY2025 form (AEO 9495 R 01/FY2025) carries the same work-income sentence as the current form (LIHEAP 9495 R 11/2025).

Regulatory authority

Manual page numbers in this PR refer to the adopted 190-page FFY 2025 manual (cover: "Effective October 1, 2024 – September 30, 2025"; PDF metadata: created November 18, 2024). It supersedes the 167-page August 2024 draft. Every encoded rule reads the same in both versions. The draft's section 4.7.3 also exempts adult full-time students from the Zero Income Form; the adopted section 4.7.3 (page 59) omits that sentence. No FY2026 manual was found, so FY2026 applies the FFY 2025 manual's income rules.

Eligibility

Requirement Source How modeled
Arkansas residence — defined_for = StateCode.AR
Household size counts citizens and qualified noncitizens Manual sections 4.4–4.4.1, page 52; applicant rights statement, item 9 Counts members with is_citizen_or_legal_immigrant, with no SNAP-specific waiting periods or bars. A household with no qualified member is ineligible. Every member's countable income counts in full.
Monthly income limit FY2025 plan section 2.1, page 8; FY2026 plan section 2.1, page 9; FY2025 and FY2026 income charts FY2025: 60% of state median income for sizes 1–6 and 150% of the 2024 guideline for sizes 7–20. FY2026: 60% of state median income for sizes 1–7 and 150% of the 2025 guideline for sizes 8–20. Each chart adds a printed amount per member above 20: $672 a month in FY2025, $688 in FY2026. Half-up monthly rounding reproduces all 40 printed rows; the rounding is a reconciled pattern, not an express rule. One person: $2,251 a month in FY2025, $2,347 in FY2026. The limit is inclusive. In periods 2025 to 2027, every limit is at least 32% above 110% of the poverty guideline at every household size, so the federal floor in 42 U.S.C. 8624(b)(2)(B) never binds and the model applies no separate floor.
Heating responsibility FY2026 plan sections 2.1–2.3, pages 9–10 A direct heating obligation qualifies through has_heating_expense, which defaults to a positive primary-fuel bill with heat not in rent; an explicit false (for example, a bill fully reimbursed through an allowance, plan item 2.3, page 10) is respected. Heat included in unsubsidized rent qualifies with no separate bill. A household with housing assistance or in public housing whose rent includes heat needs a positive reported excess charge. heating_type NONE is ineligible.
No categorical eligibility and no asset test FY2026 plan question 1.4, page 5 SSI receipt does not waive the income limit; assets are not tested.

Countable income

Item Source How modeled
Earned income FY2026 plan section 1.8, page 5; manual Appendix F, pages 158, 159, 165, 166 Counts wages, net business income (self-employment, SSTB, farm operations, partnership/S-corporation) and rental and farm rent income, which the manual treats as self-employment (page 165). Floors each source at zero (section 4.7.4, page 63), then subtracts the 20% earned-income disregard. The business inputs are already net of expenses, which stands in for the manual's 10% operating-cost allowance (page 166); no further business or work-expense deduction applies.
Minor and student earnings Application Section III, page 2, both forms; manual section 4.7, page 56; section 17.0 Full-time Student definition, page 141; Appendix F, pages 158–159 Excludes the earnings of every member under 18; of a full-time college student (is_full_time_college_student) up to age 23, inclusive, who is a dependent of a household member (is_tax_unit_dependent); and of an 18-year-old high-school student (is_in_k12_school). Other students' earnings count after the 20% disregard; unearned income counts for all members. In FY2026, three independent full-time college students aged 22, 23 and 24, each living alone with $48,000 of wages, have countable income of $38,400, above the $28,164 one-person limit, and receive $0. A dependent student's $6,000 of wages is excluded through age 23 and counted at 24.
Unearned income FY2026 plan section 1.9, pages 6–7; manual Appendices E–F, pages 155–168 Counts, for every member: unemployment compensation (total_unemployment_compensation: the reported amount, or modeled state unemployment insurance when none is reported; Arkansas UI is not modeled), strike benefits, SSI, pensions, military retirement pay, survivor benefits, alimony, child support, qualified and non-qualified dividends, veterans benefits, cash gifts from outside the household (financial_assistance), workers' compensation, gambling winnings and capital gains. Floors each source at zero, so a loss in one source offsets nothing. The manual counts only regular cash gifts (three or more consecutive months, page 157); financial_assistance cannot separate them, so every reported gift counts.
Social Security and Railroad Retirement FY2026 plan section 1.9, page 6 ("Excluding MediCare deduction"); manual section 4.7.2, page 59 Adds each person's Social Security and railroad benefits, subtracts medicare_part_b_premium and floors the result at zero.
Interest Manual Appendix F, page 162 ("amount over $200.00") Counts each person's interest above $200 a month ($2,400 a year).
TEA cash assistance Current application, Section III, page 2; manual Appendix E, page 155 Counts the take-up-gated tanf aggregate, which includes ar_tea. The current application explicitly requests TEA despite the plan's unchecked TANF box.
Monthly rounding Manual procedure 4.7.1 (Determining Income), page 58 Rounds monthly countable income half up to the whole dollar before the limit and band tests.

Benefit

Fuel schedule Fuels mapped to it $0–$69 monthly income: sizes 1–2 / 3–4 / 5+
Electric Electricity $242 / $288 / $344
Natural gas Natural gas $308 / $366 / $437
Propane Propane $397 / $472 / $563
Fuel oil Fuel oil, kerosene $402 / $478 / $570
Other Wood, coal, other $289 / $344 / $410
  • Each schedule declines across 39 monthly income bands for three household-size groups (1–2, 3–4, 5 and up), with the fuel mapping from the application's fuel groups (page 3). Amounts in the first band are the same in both years.
  • The top five band lower bounds changed: $2,250, $2,945, $4,330, $5,022 and $5,140 in FY2025; $2,348, $3,071, $3,793, $4,515 and $5,237 in FY2026. 63 cells differ between the years (electric 11, natural gas 25, propane 12, fuel oil 11, other 4).
  • FY2025 cells follow AEO's FY2025 matrices, headed "HOUSEHOLD SIZE BENEFIT PAYMENT (20% OVER BASE)". The FY2025 electric file (PDF metadata October 7, 2024; no date is printed) is byte-identical to a December 6, 2024 Wayback capture, so AEO posted it before the January 6, 2025 opening. FY2025 plan item 2.6 (page 9) estimates a $50 minimum and a $475 maximum. The Clearinghouse "2025" Arkansas matrix repeats the FY2024 base amounts (electric $202 / $240 / $287 at $0–$69). Multiplying those base amounts by 1.2 and rounding gives the FY2025 cells in the 35 rows whose lower bounds run from $0 to $2,250, for every fuel; the top income rows differ.
  • Where a matrix prints $0.00 for a band and size group, the model pays $0.
  • Eligible households with solar or unspecified fuel receive $0. The application (page 3) has no solar box, and a solar home could answer "all electric" (electric matrix) or write in OTHER (other-fuels matrix), so the source fixes no single schedule. heating_type is a required input; Default heating_type to electricity and remove the UNSPECIFIED-gated state heating adapters #9754 tracks the unspecified default.
  • The reported bill does not cap the grant.

Years covered

Model year Program year Income limit basis One-person limit
2025 FY2025, from October 1, 2024 SMI for sizes 1–6; 2024 guideline for 7–20 $27,012
2026 FY2026, from October 1, 2025 SMI for sizes 1–7; 2025 guideline for 8–20 $28,164

A calendar-year period reads the parameters in force on January 1. Formulas are undated, and the registry entry lists no verified_years. Matrix and limit checks do not establish complete verified policy years. Other years are unverified backfilled estimates:

  • Periods before 2025 read the FY2025 "20% OVER BASE" matrices. In 2024, a one-person household heating with gas and no income receives $308, where the FY2024 Clearinghouse matrix pays $257.
  • Period 2027 carries the FY2026 matrices forward with the FY2027 state median income, for a one-person limit of $29,520 ($2,460 a month). The proposed FY2027 plan estimates a $70 minimum and a $665 maximum benefit (item 2.6), and AEO's responses to comments give $66 and $627. AEO has posted no FY2027 chart or matrix, so FY2027 is not encoded.

Not modeled and source conflicts

Item Source Model treatment
Adoption assistance, cryptocurrency, crowd-fund contributions, executor fees, foster care payments, HUD utility payments (the application's Housing Utility Assistance Payment), inheritance, jury duty pay, royalties and Trade Adjustment Assistance Manual Appendix E, page 155; Appendix F, pages 156–162, 166, 168 Counted by the manual, but no sufficiently specific input exists; not counted.
Irregular cash gifts Manual Appendix F, page 157 The manual counts only regular gifts (three or more consecutive months); financial_assistance cannot separate them, so every reported gift counts.
Loans FY2026 plan section 1.9 checks loans that must be repaid; manual Appendix F, page 163, excludes all loans Not counted; the manual is followed.
High-school student exceptions Manual section 4.7, page 56 An 18-year-old high-school student's earnings are excluded even when the student works full time or is an emancipated head of household; neither exception has an input.
Student status and dependency Manual section 4.7, page 56; section 17.0, page 141 is_in_k12_school defaults to true only for ages 5–17, so the 18-year-old high-school exclusion applies when a caller sets it. is_tax_unit_dependent stands for "a dependent of a member of the household"; a student the household lists as a dependent whom no member claims for tax purposes has earnings counted.
Medical deductions other than the Part B premium, and the manual's Medicaid condition on that deduction Manual section 4.7.2, page 59 Not modeled. medicare_part_b_premium is zero when a person is not enrolled and excludes the share a Medicare Savings Program pays.
Business gross receipts and expenses Manual Appendix E, page 155; Appendix F, page 166 Uses existing net business and rental inputs; their expense netting stands in for the manual's 10% operating-cost allowance on gross receipts.
Manual version Adopted FFY 2025 manual (190 pages); the 167-page August 2024 draft is superseded Page citations follow the adopted manual. No FY2026 manual was found, so FY2026 applies the FFY 2025 manual's income rules.
Interest allowance assessment unit Manual Appendix F, page 162 The $200 monthly allowance is applied per recipient under the manual's definition of interest as "the sum of money paid to one for the use of their money"; the manual names no assessment unit, and a household allowance would count more income for multiple recipients.
Income in the month before application — Annual inputs approximate it.
Utility allowances on direct bills FY2026 plan sections 2.1–2.3 A direct bill counts through has_heating_expense (default: a positive primary-fuel bill with heat not in rent); a caller sets it false when an allowance fully reimburses the bill. Verification of allowances is not modeled.
Qualified noncitizens absent from immigration_status (for example, COFA or battered-noncitizen cases) Manual section 4.4.1, page 52 Require an override of is_citizen_or_legal_immigrant.
Solar and unspecified fuel Application page 3 fuel groups Pay $0 as a coverage gap (#9754 for unspecified fuel).
Crisis, cooling, weatherization and equipment assistance — Out of scope.

Application Section III, read with the manual's full-time-student definition, governs minor and student earnings. The plans, application forms and manual differ on these items:

Topic FY2026 plan or application Source treatment and model
Workers' compensation Section 1.9 leaves "Insurance payments made directly to the insured" unchecked Appendix E (page 155), Appendix F (page 168) and application page 2 count it; the model counts workers_compensation.
TEA Section 1.9 leaves TANF unchecked The current LIHEAP 9495 R 11/2025 application explicitly requests TEA, corroborating manual Appendix E (page 155); the model counts take-up-gated tanf.
Gambling winnings Section 1.9 (page 7) counts lottery winnings as the only one-time lump sum Manual page 163 excludes nonrecurring lump sums. Appendix F (page 160) counts all gaming and gambling winnings; the model follows the Appendix F row and counts gambling_winnings.
Capital gains Section 1.9 (page 7) counts no one-time lump sum other than lottery winnings Manual page 163 excludes nonrecurring lump sums, including the sale of personal property. Appendix F (page 157) counts capital gains and excludes losses; the model follows the Appendix F row and counts capital_gains floored at zero.
Interest Section 1.9 counts "Interest, dividends, or royalties" with no threshold Appendix F (page 162) counts the "amount over $200.00". The model reads the $200 as monthly, because unearned income is the month's receipts (page 57; Appendix E, pages 154–155), and as each person's, a chosen reading: a household-wide $200 would count more (two spouses with $2,400 each and a $12,000 pension: 14,400 instead of 12,000).
Rental income Section 1.8 takes 20% off work income only; section 1.9 lists rental income separately Appendix F (page 165): "Ownership of rental property will be considered a self-employment enterprise." The model moves rental_income and farm_rent_income (landlord rent) to the earned sources, which take the 20% disregard.
Minors' earnings The accepted plans leave minors' earnings unchecked; both application forms (AEO 9495 R 01/FY2025 and LIHEAP 9495 R 11/2025) request work income only from members 18 and older The model excludes every minor's earnings, regardless of school attendance. It follows the application forms over the manual's narrower rule (Appendix F, page 158), which excludes a child's earnings only during at least half-time school attendance.
Full-time students Both application forms request work income only from members "18 and older & not a full-time student" and do not define the term; the plans have no student item The model uses the manual's definition (section 17.0, page 141; Appendix F, page 159): a full-time college student up to age 23, read as inclusive, who is a dependent of a household member. It adds section 4.7's 18-year-old high-school students (page 56); the full-time-work and emancipation exceptions are not modeled. The page 141 definition also says "High school students over age eighteen (18) may provide proof of enrollment or report card"; the model follows section 4.7 and counts the earnings of a high-school student aged 19 or older. The draft's section 4.7.3 sentence exempting adult full-time students from the Zero Income Form (draft page 43) is absent from the adopted section 4.7.3 (page 59).

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

83 YAML cases in 7 files cover:

  • every FY2026 matrix row and size column at each band's lower bound for all five fuels, the FY2025 top bands for each fuel, and every one of the 63 FY2025 cells that change at 2025-10-01;
  • all FY2026 income limits for sizes 1–22 and FY2025 limits for sizes 1–9, 20 and 21, including the printed $672 and $688 additional-member amounts, with $688 added twice at size 22;
  • inclusive limits and half-up rounding at the limit and at a band edge;
  • heat in rent with and without a subsidy, a direct obligation with no bill, an explicit has_heating_expense false with a $1,200 gas bill (ineligible, $0), no heat and no qualified member (household size 0 and a $0 income limit);
  • the 20% disregard, rental and farm rent as self-employment, interest above $200 a month per person, minors in and out of school, an 18-year-old in and out of high school and a 19-year-old in high school, dependent full-time college students aged 22 to 24, a dependent part-time student aged 20, independent full-time students aged 22 to 24, Social Security and railroad retirement net of the Part B premium, a premium larger than the benefit, military retirement, workers' compensation, gambling winnings, capital gains, unemployment compensation (reported, read through total_unemployment_compensation), strike pay, qualified and non-qualified dividends, veterans' benefits and regular cash gifts, TEA with and without take-up, and loss floors in earned and unearned sources;
  • kerosene, wood and coal mapping, and $0 for solar, unspecified fuel and an empty household;
  • final grants in both years, including an FY2025 seven-person household between the SMI and poverty-guideline limits, a five-person family whose TEA moves it into a lower band, a landlord made eligible by the disregard and a pensioner whose interest above $200 a month lowers the grant;
  • five end-to-end households in integration.yaml, each checking the heating expense, heating-cost flag, household size, countable income, limit, eligibility, matrix amount and grant: an SSI and Social Security retiree with electric heat ($127), a minimum-wage single parent with gas heat ($124), a family of four with a dependent college student heating with propane ($114), a renter whose unsubsidized rent includes gas heat ($146), and an FY2025 retired couple heating with wood ($68).

Every case that tests eligibility or a grant specifies heating_type; income-only cases do not need it. A mixed-state case pays only the Arkansas household. Expected values are hand computations from the sources; CI runs the cases. Registry YAML parsing, git diff --check and make format passed. Tests that encode the documented assumptions do not resolve the remaining source gaps.

  • 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#1538 queued

🤖 Generated with Claude Code

hua7450 and others added 4 commits October 3, 2026 19:49
- Encode the FY2025 matrices, income bands and eligibility chart (size 7 on
  150% FPG, $672 extra-person amount) alongside FY2026.
- Count Social Security and railroad retirement net of the Medicare Part B
  premium; count military retirement pay.
- Follow the draft manual where it conflicts with the plan: count workers'
  compensation, TEA (through take-up-gated tanf), gambling winnings and
  capital gains, each with the conflict noted.
- Also follow the draft manual on: interest counted only above $200 a month
  (p137); rental and farm rent as self-employment with the 20% deduction
  (p141); a minor's earnings excluded only while in school (p133); the
  student exclusion only for dependent college students up to 23 (p134).
- Round monthly countable income to the nearest dollar; floor each income
  source at zero.
- Shorten the registry note and fix reference locators.
- Add period-2025, income-source, rounding and fuel cases; tidy tests.

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 (f2a1172).
⚠️ Report is 541 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff            @@
##              main     #9973   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files            4         6    +2     
  Lines           76       119   +43     
  Branches         2         2           
=========================================
+ Hits            76       119   +43     
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 5 commits October 7, 2026 22:56
…nings

Draft manual 4.7 (page 41) excludes the earnings of members aged 18 enrolled in high school; identified with is_in_k12_school. The full-time-work and emancipation exceptions are not modeled.

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 Arkansas LIHEAP regular heating assistance

PR #9973: Add Arkansas LIHEAP regular heating assistance (author: hua7450, head 7e42062309)

Scope: the winter Regular (rate-reduction) Assistance benefit of Arkansas LIHEAP for federal fiscal years 2025 and 2026. The Arkansas Energy Office (AEO) in the Department of Energy and Environment runs the program through community-based organizations; DHS does not. The PR covers:

  • household size, which counts citizens and qualified noncitizens (is_citizen_or_legal_immigrant) while every member's income counts;
  • monthly countable income (MCI):
    • 80% of the gross work income (wages, net business income, rental and farm rent) of members 18 or older who are not full-time students;
    • plus the unearned income of all members from 14 listed sources, each floored at zero;
    • interest above $200 a month per member, Social Security and railroad retirement net of the Part B premium, and take-up-gated TEA;
    • the total rounded half up to the dollar;
  • the income limit from the eligibility charts:
    • 60% of state median income for sizes 1-6 (FY2025) or 1-7 (FY2026), and 150% of the prior year's poverty guideline above that, rounded half up;
    • the printed $672 or $688 per member above size 20;
  • five fuel matrices (electric; natural gas; propane; fuel oil with kerosene; other with wood and coal), each with 39 MCI rows by three size columns (1-2, 3-4, 5 and up) for each year;
  • heating responsibility: a direct bill or reported obligation, heat in unsubsidized rent, or heat in subsidized rent with a positive excess charge. There is no categorical eligibility and no asset test.

Crisis, summer (cooling) Regular Assistance on the electric matrix, weatherization, Assurance 16, split benefits and FY2027 are out of scope. The PR changes 33 files: 19 parameters, 6 variables, 6 test files (70 cases), programs.yaml and a changelog fragment. Parameters start at 2024-10-01. The matrices (63 cells), the top five band bounds, smi_max_size and additional_member_amount change at 2025-10-01. The tests use periods 2025 and 2026, and the registry lists Arkansas partial with no verified_years.

Overall: the FY2025 and FY2026 tables and limits are right where the sources print them, and the income rules follow the accepted plans and the operating application.

  • All 1,170 matrix cells (5 fuels × 39 rows × 3 columns × 2 years) and all 78 row lower bounds match the AEO PDFs. I compared them row by row, using the coordinates of the PDF text layer.
    • The FY2026 set is identical to the Clearinghouse copy.
    • The FY2025 electric file is byte-identical to a Wayback capture of December 6, 2024, so it was posted before the January 6, 2025 opening.
  • All 40 printed limits (sizes 1-20, both years) reproduce, and the printed per-member amounts are stored.
    • They come from the repo's medians ($86,577 and $90,280) and the 2024 and 2025 guidelines with half-up monthly rounding.
    • Every limit is at least 32% above 110% of poverty, so the federal floor never binds.
  • The income definition follows plan item 1.8 ("For work income, we collect data for gross income and subtract 20%. For non-work income, we use gross amount") and the checked 1.9 boxes, including "Excluding MediCare deduction".
    • The minor and full-time-student rule follows application Section III. The FY2025 form (R 01/FY2025) uses the same words (G2).
    • The PR resolves several conflicts toward the draft manual or the application: TEA, workers' compensation, gambling, capital gains, interest and rental. Each is documented.
  • The tests are strong. The hand checks reproduce, the band edges and the limit edge are tested to the cent, and three control mutations fail as expected. Five unearned sources and two small pieces of logic are not pinned (S3).

There are no critical findings. The four 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. Arkansas UI is not modeled on main, so no value changes today.
  • S2: six parameter descriptions use verbs outside the house template.
  • S3: five listed unearned sources are never positive in a test. Two small pieces of logic also have no test that would fail without them: the bill term in the direct-responsibility branch and the size-0 mask on the income limit.
  • S4: three plan references lack page lists, and the manual reference's page list omits four of the pages the list relies on.

All 70 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. Values that a proposed fix or another reading would produce are hand computations and are labelled as such. The S3 claims 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/ar/ee/aeo/liheap/
  • V/ = policyengine_us/variables/gov/states/ar/ee/aeo/liheap/
  • T/ = policyengine_us/tests/policy/baseline/gov/states/ar/ee/aeo/liheap/
  • M = the FY2025 Arkansas LIHEAP Policy and Procedures Manual. It is watermarked DRAFT, runs to 167 pages and has the cover line "Effective October 1, 2024 – September 30, 2025". PDF page = printed page.

Line numbers refer to head 7e42062309.

Source Documents

# Document Link Use
1 FY2026 Arkansas LIHEAP Detailed Model Plan (55 pp, Revision #1, "Submission Accepted by CO"). The SF-424 names "Arkansas Energy Office (AEO)" in the "Arkansas Department of Energy and Environment" p. 9 1.1: heating "is offered the first Monday after the New Year holiday", and Regular households "end the last business day of March" (p4). 1.4 No and 1.8 (p5). 1.9 with "Excluding MediCare deduction" (p6), foster care and the "Other" lottery note (p7). 2.1: 60% of SMI for sizes 1-7 and 150% of the HHS guidelines for 8-15; 2.2-2.3 (p9). Energy burden (p10). 2.6: $60 / $570 (p11). Checkbox states were read from rendered pages
2 FY2025 plan (51 pp, "Submission Accepted by CO") p. 8 Heating 01/06/2025-03/31/2025 (p4). 1.4 No, 1.8 and the start of 1.9 (p5); the rest of 1.9 (p6); the lottery note (p7). 2.1: SMI for sizes 1-6 and the guidelines for 7-15; 2.3 (p8). 2.6: $50 / $475 (p9)
3 Proposed FY2027 plan (55 pp, status "Saved") and AEO's responses to comments (8 pp, comments received through Aug. 12, 2026) plan, p. 11, responses, p. 5 The same 1.8, 1.9 and 2.1 (p5-6, p9). 2.6: $70 / $665 (p11). The responses say "The 10% increase to heating assistance benefits sets the heating minimum at $66 and the maximum at $627" (p5)
4 FFY 2026 and FFY 2025 eligibility charts (1 p each) FY2026, FY2025 Maximum MCI for sizes 1-20; "ADD $688" and "ADD $672 FOR EACH ADDITIONAL HOUSEHOLD MEMBER"
5 FFY 2026 and FFY 2025 benefit matrices (5 fuels × 2 pp each) and the Clearinghouse FY2026 copy (10 pp) FY2026 electric, p. 1, FY2025 electric, p. 1, Clearinghouse FY2026 All cells. The four non-electric fuels are headed "(WINTER ONLY)", and the FY2025 electric header reads "(20% OVER BASE)". The FY2025 electric file's SHA-1 equals the Dec. 6, 2024 Wayback capture
6 Clearinghouse "2025" and "2024" Arkansas matrices ("REGULAR ASSISTANCE") 2025, 2024 Not cited in the PR. Both carry the same base amounts (electric $202 / $240 / $287 at $0-69), and 1.2 times them gives the FY2025 AEO cells (G1)
7 Application AEO-9495, R 11/2025 (current) and R 01/FY2025 R 11/2025, p. 2; R 01/FY2025, p. 2 (a subgrantee's copy; also the Jan. 4, 2025 Wayback capture) Both versions have the Section III line "WORK INCOME: List anyone in your household (18 and older & not a full-time student) who has work income" and a non-work list that includes TEA and workers' compensation. Fuel groups (p3)
8 M p. 41 4.4 household size (p36-37). 4.7: the income period and the 18-year-old high-school rule (p41). 80% of gross "before any pre-tax deductions" and MCI rounding (p42). 4.7.2 Part B (p43). 4.7.4 loss floor (p47). 4.8 energy burden (p47-48). "no longer considers eligibility using other means-tested programs" (p49). 6.1 matrices (p62). Appendices E-F (p129-144)
9 HHS state median income and poverty guidelines repo gov.hhs.smi.amount (AR: $86,577 for FY2025, $90,280 for FY2026, $94,627 for FY2027) and gov.hhs.fpg Limit derivations. The 2025 and 2026 guidelines are used for the floor check
10 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

  • Where: P/income/sources/unearned.yaml:11 (- unemployment_compensation).
  • What changed on main: Integrate modeled state unemployment insurance into income flows #9558, merged on 2026-10-13, the day after this PR's last push.
    • It 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.
    • It added policyengine_us/tests/code_health/test_unemployment_compensation_readers.py, which fails on any raw list entry.
  • 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/ar/ee/aeo/liheap/income/sources/unearned.yaml:11.
    • The file's other three tests pass, and the PR's 70 cases still pass on that tree.
  • Source: none of these separates reported from modeled amounts.
    • Plan item 1.9 checks "Unemployment insurance" (FY2026, p. 6; FY2025, p5).
    • M Appendix F counts "Unemployment" as "YES" (p. 144).
    • The application lists "Unemployment Benefits" as non-work income.
  • Impact: main models UI only for AL, NJ, NY, OK, PA and UT (gov.states.household.modeled_state_unemployment_compensation).
    • For Arkansas households the total equals the reported amount, so no value changes today. Reproduced at head: a reported $6,000 counts in full, giving MCI $500 and $216 with gas heat.
    • The guard still blocks the merge, and the raw entry would silently drop Arkansas UI once it is modeled.
  • 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. The same finding was 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, Add South Dakota LIEAP regular heating assistance #9974 S1 and Add Oklahoma LIHEAP regular heating assistance #9970 S1. As in Ohio (Add Ohio HEAP regular heating assistance #9975), no values change.
  • Fix:
    • Replace the entry with total_unemployment_compensation.
    • Add a case with positive UI; none exists today (S3).
    • Update rulespec-us#1538: its countable-income output and its inputs list both name unemployment_compensation.

S2. Six parameter descriptions use verbs outside the house template

All 19 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/limit/max_table_size.yaml:1 "publishes income limits up to this household size before adding a separate amount per additional member" "Arkansas sets 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" "Arkansas uses this increment to round monthly income limits under the ..."
P/income/sources/earned.yaml:1 "counts these earned income sources" "Arkansas uses these sources as earned income under the ..."
P/income/sources/unearned.yaml:1 "counts these unearned income sources" "Arkansas uses these sources as unearned income under the ..."
P/payment/household_size_group.yaml:1 "assigns this payment group by household size" "Arkansas uses this household-size group for the regular heating payment under the ..."
P/payment/income_band.yaml:1 "assigns this payment band by monthly countable income" "Arkansas uses this monthly countable income band for the regular heating payment under the ..."

S3. Five listed income sources and two small pieces of logic have no test that would fail if they broke

Each mutation below, applied to the head on its own, still passes all 70 cases.

  1. Five unearned sources are never positive in any test.
    • The sources: unemployment_compensation (P/income/sources/unearned.yaml:11), strike_benefits (:12), ordinary_dividend_income (:23), veterans_benefits (:24) and financial_assistance (:26).
    • Removing any one of them passes every case (reproduced for each).
    • Each maps to a checked 1.9 box: unemployment insurance, strike pay, "Interest, dividends, or royalties", VA benefits and cash gifts.
    • Fix: add a column for each to countable-income Case 11 (T/income/ar_liheap_countable_income.yaml:312), which already checks four sources in a vector, or add them to an existing household.
  2. The bill term in the direct-responsibility branch (V/eligibility/ar_liheap_eligible.py:33, (expense > 0) | has_expense).
    • has_heating_expense already defaults to "bill above zero and heat not in rent". So the term matters only when a caller sets has_heating_expense to false while reporting a bill.
    • Reproduced: one adult with $12,000 of wages, gas heat, a $1,200 gas bill and has_heating_expense: false is eligible for $182 at head. Without the term the household is ineligible and gets $0.
    • The input's documentation tells callers to set it directly when the bill is not the heating cost. That argues for respecting an explicit false and dropping the term. Otherwise, pin the current result with that case (as Add Florida LIHEAP regular heating assistance #9969 S3.2 asked for Florida).
  3. The size-0 mask on the income limit (V/income/ar_liheap_income_limit.py:39, where(size > 0, ..., 0)).
    • Without it, a unit with no qualified member gets the one-person limit, because smi_size_factor clips size 0 to the 52% share.
    • Reproduced: one undocumented adult has a limit of $0 at head and $28,164 under the mutation.
    • Eligibility still gates on size > 0, which T/eligibility/ar_liheap_eligible.yaml Case 4 pins, so only the limit variable changes.
    • Fix: add ar_liheap_income_limit: 0 to T/ar_liheap_household_size.yaml Case 2, as Add Georgia LIHEAP regular heating assistance #9968 S2.3 and Add Florida LIHEAP regular heating assistance #9969 S3.1 asked.

Three control mutations confirm the method:

  • Dropping size > 0 from eligibility fails T/eligibility/ar_liheap_eligible.yaml.
  • Dropping the NONE check fails the same file.
  • Dropping the surcharge term for subsidized heat in rent fails that file and T/ar_liheap.yaml.

By inspection, the rest is pinned:

  • the seven earned sources: countable-income Case 5 breaks if any of its five business and wage sources is dropped, and rental and farm rent are positive in Cases 7, 16 and 18;
  • the other nine unearned sources, the per-source loss floors, the interest disregard, and the Part B netting with its floor;
  • TEA with and without take-up, the minor and full-time-student exclusions at ages 17 and 18, and MCI rounding at the limit and at a band edge;
  • the SMI/FPG switch in both years, each limit rounding and the per-member amount above size 20;
  • every band edge tested, each fuel table and the kerosene, wood, coal and other mapping, the size-group edges, and the matrix size-0 mask;
  • heat in rent with both subsidy routes, the obligation flag without a bill, the NONE check and the Arkansas gate.

Consistency: #9967 S3, #9972 S3, #9968 S2, #9975 S4, #9969 S3 and #9970 S6 rated untested logic and sources SHOULD (checklist item 13).

S4. References: three plan citations lack page lists, and the manual's page list omits four cited pages

File:line Problem Fix
P/income/sources/unearned.yaml:45-46 FY2025 plan item 1.9 opens on p5, which shows only "Unemployment insurance". Strike pay, Social Security, SSI, pensions, cash gifts, alimony, child support, "Interest, dividends, or royalties" and VA benefits are on p6, and the lottery note is on p7 Keep #page=5 and end the title with "#page 5-7"
P/income/sources/unearned.yaml:43-44 FY2026 item 1.9 opens on p6, but the lottery-only note that the gambling_winnings comment cites (:31-32) is on p7 End the title with "#page 6-7"
P/income/sources/earned.yaml:27-28 FY2025 item 1.9 opens on p5 (wages, self-employment), but "Rental income" is on p6 End the title with "#page 5-6"
P/income/sources/unearned.yaml:47-48 The manual title ends #page 130,132,135,141,144, but the list also relies on Appendix F rows for alimony (p131), dividends (p133), pensions (p140), and strike pay and SSI (p143) End it with "#page 130-133,135,140-141,143-144"

The other plan, chart, manual and matrix anchors show their values (see Verified correct). Consistency: #9972 S5, #9975 S6, #9974 S3 and #9970 S5 rated missing page lists SHOULD.

Suggestions

G1. FY2025 benefit levels: say why the "20% OVER BASE" matrices win over plan item 2.6 and the Clearinghouse file

  • FY2025 plan item 2.6 estimates a $50 minimum and a $475 maximum (p. 9). The AEO FY2025 matrices print $60 to $570, and the electric header reads "HOUSEHOLD SIZE BENEFIT PAYMENT (20% OVER BASE)".
  • The Clearinghouse's AR_BenefitMatrix_2025.pdf is titled "2025 ELECTRICITY FUEL BENEFIT MATRIX REGULAR ASSISTANCE". It nonetheless carries the base amounts, identical to its 2024 file:
    • first-row (income $0-69) base amounts: electric $202 / $240 / $287, natural gas $257 / $305 / $364, propane $331 / $393 / $469 and other $241 / $287 / $342;
    • 1.2 times these, rounded, gives every first-row AEO FY2025 cell: $242 / $288 / $344; $308 / $366 / $437; $397 / $472 / $563; $289 / $344 / $410;
    • fuel oil's $570 is 1.2 times the plan's $475.
  • The AEO matrices were on the AEO site before the season. Their file dates are October 7, 2024, and the FY2025 electric file is byte-identical to the December 6, 2024 Wayback capture; the same digest appears in captures from June and July 2025. So the PR's FY2025 cells are the ones in force from January 6, 2025.
  • rulespec-us#1538 records the plan conflict (interpretation 10), but the PR body and the matrix comments do not. Add a sentence and the capture link, and note that the Clearinghouse "2025" file repeats the FY2024 matrix.

G2. Minors and full-time students: the FY2025 form supports the backfill, and the reach is worth stating

  • The PR calls applying the current application's rule to FY2025 "a backfilled assumption without a confirmed change date". But the FY2025 form, AEO 9495 R 01/FY2025, has the same Section III sentence (source 7). Cite it in the comment at V/income/ar_liheap_countable_income.py:29-33, in the PR body and in Resolve US discrepancies against TAXSIM35 for 2021 #1538 interpretation 3(c).
  • M 4.7.3 also exempts full-time students from the Zero Income Form (p. 43: "Each adult (aged 18 or older) who declares zero or inadequate income and who is not a full-time student"). That fits the form's broad reading better than Appendix F's rule for dependent students up to age 23 (p134).
  • Reach: the rule excludes all earnings of a full-time student of any age. Reproduced at head (2026, gas heat):
    • a 35-year-old full-time graduate student living alone with $40,000 of wages has countable income of $0 and gets $308;
    • the same person, not in school, has MCI of $2,667, above the $2,347 limit, and gets $0.
  • That follows the form literally. If AEO confirms the draft manual's narrower rule instead, revert to it. Either way, mention the reach in the registry notes.

G3. Solar and unknown-fuel households are eligible but paid $0

G4. Unclaimed years: FY2027 and the pre-FY2025 backfill

  • FY2027. The proposed plan gives $70 / $665 (item 2.6, p11), while AEO's responses give $66 / $627 (p5). No FY2027 chart or matrix is posted.
    • Period 2027 carries the FY2026 matrices with the FY2027 median ($94,627) and the 2026 guideline.
    • Reproduced: one person has a limit of $29,520 ($2,460 a month) and gets $308 with no income and gas heat.
    • The PR documents this.
  • Before FY2025. Periods up to 2024 read FY2025's 20%-higher matrices.
    • FY2024's plan gives $50 / $475 (item 2.6, p. 9), and the Clearinghouse FY2024 matrix has the base amounts and different top rows.
    • Reproduced: in 2024, a one-person gas household with no income gets $308; the FY2024 matrix pays $257.
    • The years are unclaimed and documented as unverified. Record this in the registry notes (checklist item 3).
  • No plan from FY2025 to FY2027 calls the increase an IIJA supplement (checklist item 12).
    • FY2026 keeps the same first-row amounts without the "over base" label.
    • The FY2027 proposal raises them a further 10%.

G5. Two documented conflicts to state more precisely

  • Capital gains and gambling.
    • The PR body says "Section 1.9 has no capital gains item". But both plans add "The only one-time lump sum payment counted towards income is lottery winnings" (FY2026 and FY2025, p7).
    • M p138 also excludes "nonrecurring lump-sum payments, including but not limited to the sale of personal property".
    • Those point against counting a one-time capital gain or a non-lottery gambling win, while M p132 and p135 count them.
    • The choice is documented; describe the lump-sum conflict accurately in the PR body and Resolve US discrepancies against TAXSIM35 for 2021 #1538 interpretation 2.
  • Interest. "amount over $200.00" (M p137) gives no period and no unit. The monthly per-member reading is the most generous one. Reproduced at head:
    • two spouses with $2,400 of interest each and a $12,000 pension count $12,000 and get $161;
    • if one spouse held all $4,800, they count $14,400 and get $139.
    • The PR already documents this; no change is needed.
  • TEA is reasonable as encoded.
    • Plan 1.9 leaves TANF unchecked in both years.
    • Both application versions list "TEA" as non-work income, and M p130 says "Do not count sources such as SSA, SSI, and TEA more than once monthly per individual".
    • Reproduced: a family of three with $204 a month of TEA gets $324 rather than $366.

G6. Code, test and PR hygiene

  • P/income/student_exclusion/child_age_limit.yaml: since 92153a43cb the parameter excludes every minor's earnings, whether or not the minor is in school. Full-time students are excluded in the formula, without a parameter. The folder name student_exclusion no longer describes it; consider, for example, income/earned/minimum_age.
  • MCI rounding uses a literal (np.floor(annual_income / MONTHS_IN_YEAR + 0.5), V/income/ar_liheap_countable_income.py:86), while the limit uses rounding_increment. Optional: read a parameter.
  • Reference titles:
    • The fpg_year_lag titles describe the charts as "using the 2025 federal poverty guidelines", which the charts do not print. "Reproduced by" would be accurate.
    • The matrix and size-group titles call the electric file a "Winter Benefits Matrix", but its heading is "FFY 2026 BENEFITS MATRIX" and M p62 uses it for both seasons.
  • Many test comments lost the spaces around their numbers, for example:
    • T/ar_liheap.yaml:1 ("monthly370-429 gives227 ... zero income gives308");
    • T/payment/ar_liheap_matrix_amount.yaml:3 ("matrix:39lower bounds×3size columns=117literal cell checks");
    • T/income/ar_liheap_income_limit.yaml:3 ("Official2026income chart sizes1–20 plus explicit688monthly");
    • T/income/ar_liheap_countable_income.yaml:94 ("Exactly18 ... after20%disregard").
  • Several comments refer to internal material (see Add Rhode Island LIHEAP regular heating assistance #9972 G7, Add Ohio HEAP regular heating assistance #9975 G6 and Add Oklahoma LIHEAP regular heating assistance #9970 G4):
    • "Contract specifies nonnegative earned sources" (T/income/ar_liheap_countable_income.yaml:154);
    • "Draft status is disclosed in the research report" (T/ar_liheap_household_size.yaml:1);
    • "qualified composition source hierarchy in the research report" (T/eligibility/ar_liheap_eligible.yaml:1).
  • PR body and issue:
    • "the PR remains draft": the PR is not a draft.
    • rulespec-us#1538 also says "open as a draft" and that the tests were "Not run in this session". All 70 pass locally at this head.

Verified correct

  • Matrices (source 5):

    • All 1,170 cells and 78 row bounds, including the $20 row "1990-2009" and the $120 rows "1750-1869" and "1870-1989".
    • The FY2025 top rows "2,250-2,944" to "5,140-Max" and the FY2026 top rows "2348-3070" to "5237-Max".
    • The columns "1&2", "3&4" and "5 & UP".
    • The 63 changed cells match the PR body's count (electric 11, natural gas 25, propane 12, fuel oil 11, other 4).
    • Fuel groups follow the application (p3): "FUEL OIL/ KEROSENE", and wood and other on "OTHER (WOOD, PELLETS, ETC.)".
    • Plan item 2.6's $60 / $570 matches the FY2026 extremes.
    • There is no bill cap. M 2.1 says "The benefit is designed to assist households with their energy burden, not to cover total costs" (p15), and 6.1 uses MCI, household size and fuel type (p62).
  • Limits (source 4):

    • FY2026: 0.6 × $90,280 × the 45 CFR 96.85(b) factor ÷ 12, rounded half up, for sizes 1-7 ($2,347 ... $6,094). Above that, 1.5 × the 2025 guideline ÷ 12 ($6,769 ... $15,019), plus the printed $688.
    • FY2025: the $86,577 median for sizes 1-6 ($2,251 ... $5,714), the 2024 guideline from size 7 ($5,918 ... $14,660), and the printed $672. Half-up rounding at the exact half-dollars ($5,917.50, $7,262.50, $8,607.50 and others) matches every printed row.
    • The limit is inclusive (M 3.2: "at or below", p31) and is compared with rounded MCI.
  • Federal floor (42 USC 8624(b)(2)(B)). FY2026 monthly limit against 110% of the higher (2026) guideline:

    Size 1 2 3 4 5 6 7 8 20 Each additional
    Limit $2,347 $3,070 $3,792 $4,514 $5,236 $5,958 $6,094 $6,769 $15,019 $688
    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 $11,355.67 $520.67
    • FY2025's limits clear 110% of the 2025 guideline at every size: $1,434.58 for one person, $4,459.58 for seven and $11,013.75 for twenty, plus $504.17 per member.
    • The narrowest margin is 32%, so the floor cannot bind.
  • Timing:

    • FY2025 regular heating ran from 01/06/2025 to 03/31/2025 (plan p4).
    • FY2026 Regular Assistance runs from the first Monday after New Year's to the last business day of March. Priority intake may start up to 30 days earlier; AEO's responses say December 8, 2025.
    • Period N reads FY N on January 1.
  • Income:

    • Plan 1.8 and the checked 1.9 boxes.
    • Social Security and railroad retirement net of Part B: 1.9 "Excluding MediCare deduction"; M 4.7.2 ("must not count medical deductions as income ... This includes the Medicare Part B Buy-in premium", p43); and M Appendix F ("Medicare insurance premiums" No, p138).
    • Per-source loss floors (M 4.7.4: "Negative self-employment income will not be subtracted from other household income but will be counted as zero", p47; capital losses No, p132).
    • Rental property as a self-employment enterprise (p141).
    • 80% of gross wages "before any pre-tax deductions" (p42).
    • Minors' earnings excluded: 1.9 leaves "Earned income of a child under the age of 18" unchecked, and the application agrees.
    • Undocumented members' income counted (M 4.4, p36; p136).
    • MCI rounding to the nearest dollar (p42).
    • TEA counted once through the take-up-gated tanf.
  • Household and eligibility:

    • Size counts citizens and qualified noncitizens (M 4.4-4.4.1). The enum covers the 8 USC 1641(b) statuses except COFA and battered noncitizens, which the PR documents. A unit with no qualified member is ineligible.
    • No categorical eligibility (plan 1.4 No; M p49) and no asset test (plan 2.3).
    • Energy burden (plan 2.3, p9; M 4.8.3, p48): a direct bill or obligation qualifies; unsubsidized heat in rent qualifies with a lease; subsidized heat in rent needs "a utility surcharge or other extra cost". NONE is ineligible.
  • Code patterns:

    • No hard-coded policy values (apart from the rounding literal in G6). defined_for = StateCode.AR is on five variables, and ar_liheap is gated by ar_liheap_eligible. All 19 parameters are read, the formulas are vectorized, and the shared smi() and fpg() helpers are reused.
    • The matrix keys come from bracket lookups that always return 1-39 and 1-3.
  • Tests:

    • 70 of 70 pass locally at head (policyengine-core 3.32.29) and on the merged tree. Periods are plain (2025, 2026).
    • Hand-checked against the charts, matrices, plans, manual and application:
      • T/ar_liheap.yaml Cases 1, 3, 6-12 and 14-19;
      • limit Cases 1-3 (all 32 values);
      • countable-income Cases 5, 7, 9, 14, 24 and 25;
      • eligibility Case 5;
      • matrix Cases 6 and 10.
  • Changelog: changelog.d/ar-liheap.added.md is top level and typed added.

Checklist results (LIHEAP wave 2a)

  1. State plan and manual first: pass. I read the following and verified every encoded cell, limit and branch:
    • the accepted FY2025 and FY2026 plans (rendered checkboxes), the proposed FY2027 plan and AEO's comment responses;
    • both charts, all ten matrices, the Clearinghouse FY2024-FY2026 matrices, both application versions and M.
    • Arkansas LIHEAP is run by AEO, not DHS, so gov.states.ar.ee.aeo is the right path. No adopted FY2025 or FY2026 manual was found; the PR discloses its reliance on the draft.
  2. Income definition: pass.
    • Gross work income less 20%, and gross non-work income (plan 1.8). Social Security net of Part B, per the plan box and M 4.7.2. Loss floors per source, and annual inputs standing in for the prior month.
    • The minor and student rule follows both application versions (G2). The lump-sum wording is in G5. UI needs the total after rebase (S1).
  3. Backdating: FY2025 and FY2026 are represented and correct.
    • FY2025 uses the "20% OVER BASE" matrices posted before the season (G1).
    • Earlier years and 2027 are unclaimed, documented estimates (G4). No FY2027 chart or matrix is published.
  4. Household and arrangement rules: pass. Subsidized and public housing, heat in rent with and without a surcharge, a direct obligation without a bill, no categorical eligibility, the $60-$570 range and NONE are handled and tested. Priority affects intake timing only. Solar and unknown fuel get $0 (G3).
  5. Tests: 70 cases, more than 8 hand-checked.
    • Covered: FY2026 limits for sizes 1-21 and FY2025 limits for sizes 1-9, 20 and 21; the limit edge (to the cent and at the half dollar); band edges; the size-group edges; ages 17 and 18; plain periods.
    • Gaps: S3.
  6. Parameter descriptions: six are off-template (S2). None has a trailing clause.
  7. References: three missing page lists and one incomplete page list (S4). Polish is in G6.
  8. Wiring: pass.
    • The programs.yaml entry and the coverage line are well formed, and the registry test passes on the merged tree (655 passed).
    • There is no aggregate wiring, which matches OR, NY, NJ and MD on main.
    • defined_for gating is on every variable, and the state-gating checks pass on the merged tree.
    • Take-up applies only through tanf, as in the siblings.
  9. Axiom: valid queued line. rulespec-us#1538 is open, labelled pe-parity, dispatch-ready and current to 7e42062309. It needs updates for S1 and S3 and the G1, G2 and G5 notes (see below).
  10. Branch and CI: all checks are green at head. The branch is 9 ahead and 82 behind main. There are no textual conflicts, but main's UI guard fails on the merged tree (S1).
  11. Integrate modeled state unemployment insurance into income flows #9558: S1. Arkansas UI is not modeled, so the guard fails but no value changes.
  12. IIJA and FY2027: no plan from FY2025 to FY2027 mentions an IIJA supplement.
    • The FY2025 20% increase persists in FY2026, and FY2027 proposes a further 10%, so it is not a temporary supplement.
    • FY2027 is proposed only ($70 / $665, or $66 / $627 in AEO's responses) and has no matrix. It is unencoded and documented (G4).
  13. Mutation check: S3. Three control mutations fail as expected.
  14. Health premiums after Document disjoint health premium inputs and correct consumer treatment #10046: not applicable.
    • Arkansas counts 80% of gross wages "before any pre-tax deductions" (M p42) and deducts no health premiums from them.
    • The only medical item is the Part B netting from Social Security and railroad retirement, which reads medicare_part_b_premium.
  15. State-gated index defaults: pass.
    • ar_liheap_household_size (int, default 0) feeds only bracket lookups (max_(size, 1)), smi() and clip(size, 1, 20), and the matrix keys are always 1-39 and 1-3.
    • T/ar_liheap.yaml Case 5 runs AR and GA households in one simulation without error.

CI status

28 of 28 checks pass at 7e42062309 (gh pr checks 9973, 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#1538 queued: valid format, and the issue meets the bar.

  • rulespec-us#1538 is open and labelled pe-parity (plus enhancement), with no comments. It was last updated 2026-10-12.
  • It is dispatch-ready under the Add AMT parameters for 2020-2023 #1467 standard. It has:
    • proposed us-ar/ module paths with corpus status;
    • verbatim plan, chart, matrix, manual, application, guideline and median-income text;
    • required outputs for all six variables;
    • 14 companion tests derived from the sources ("None is taken from policyengine-us output").
  • It describes head 7e42062309 correctly, including:
    • the FY2025 plan-matrix conflict (interpretation 10);
    • the student rule (3(c)), the interest reading (3(a)) and the Part B netting (6).
  • Updates needed when the fixes land:
    • total_unemployment_compensation in the countable-income output and the inputs list (S1);
    • the new cases (S3);
    • the FY2025 form (G2), the Clearinghouse "2025" note (G1) and the lump-sum wording (G5);
    • the stale "open as a draft" and "Not run in this session".

Next steps

  1. S1: rebase onto main, switch P/income/sources/unearned.yaml:11 to total_unemployment_compensation, and add a case with reported UI.
  2. S2: align the six descriptions.
  3. S3: give the five unearned sources positive test values, pin or drop the bill term in the direct-responsibility branch, and assert the size-0 limit.
  4. S4: add the page lists.
  5. Optionally address G1-G6, then refresh the PR body and rulespec-us#1538 and re-request review.

0 critical and 4 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 4 should items; details in the full report above. Verified: all 1,170 matrix cells and 78 row bounds (5 fuels, FY2025 and FY2026) and all 40 income-limit chart values. The 110% floor never binds. Income treatment follows plan 1.8/1.9 and the application, all 70 tests pass, and CI is green. (1) Merge blocker from main's #9558: unearned.yaml:11 reads the raw unemployment_compensation, so the guard fails on the merged tree. (2) Six parameter descriptions are off the house template. (3) Logic that passes every test even when broken on purpose: five income sources are never set to a nonzero value (unemployment, strike benefits, ordinary dividends, veterans' benefits, financial assistance), along with the bill term in direct responsibility and the size-0 income-limit mask. (4) Incomplete page anchors and lists on the plan 1.9, earned-income and manual references.

hua7450 and others added 2 commits October 15, 2026 15:13
- S1: Merge blocker: the unearned list reads raw unemployment_compensation (main PR 9558 guard)
- S2: Six parameter descriptions are off the house template (plus optional interest wording)
- S3: Untested logic: five unearned sources, the bill term in direct responsibility, and the size-0 limit mask
- S4: References: three plan citations lack page lists, and the manual list omits cited pages

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 1206c14.

This head also merges upstream/main (PRs 9558 and 10046). Arkansas deducts no payroll health premiums (its only premium netting is Part B against Social Security and railroad retirement), so 10046 changes nothing here. As you found, every Arkansas limit clears 110% of poverty (42 U.S.C. 8624(b)(2)(B)) by at least 32% in 2025-2027, so this PR does not add the shared gov.hhs.liheap.fpg_floor parameter; the PR body now states the margin.

  • S1: income/sources/unearned.yaml now lists total_unemployment_compensation, so main's guard passes. No value changes, because Arkansas UI is not modeled. Countable-income Case 26 pins a reported $5,412 (the $451 maximum weekly benefit for 12 weeks, DOL July 2025 table) at $5,412.
  • S2: the six descriptions now use the template verbs: "sets" for max_table_size, and "uses" for rounding_increment, both source lists, household_size_group and income_band, worded as in the merged NJ and MD files where they have the same parameter. interest_disregard takes your optional wording ("this monthly amount of each member's interest").
  • S3: (1) Countable-income Case 26 gives each of the five sources its own household: UI $5,412, strike pay $3,000 (6 weeks at $500), dividends $1,200 (through qualified_dividend_income), 2026 VA compensation at 30% for a veteran alone ($552.47 a month, so MCI $552 and $6,624) and regular cash gifts $1,800. (2) I took your first option: the direct branch now reads has_heating_expense alone, so an explicit false is respected. Eligibility Case 7 pins one adult with $11,440 of wages and a $1,200 gas bill at eligible and $190 with the flag true, and ineligible and $0 with it false; no existing case relied on the bill term. (3) Household-size Case 2 asserts ar_liheap_income_limit: 0. The PR now has 72 cases.
  • S4: applied as proposed, plus page 138 in the manual title because the revised gambling and capital-gains comments cite it: unearned FY2026 #page 6-7 and FY2025 #page 5-7, earned FY2025 #page 5-6, and manual #page 130-133,135,138,140-141,143-144.
  • G1: a comment above the matrix select and a new PR-body bullet explain the FY2025 cells: AEO's "(20% OVER BASE)" matrices, dated October 7, 2024 and posted before the season (the December 6, 2024 capture), take precedence over plan item 2.6's $50-$475 estimate, and the Clearinghouse "2025" file repeats the FY2024 base. Multiplying that base by 1.2 and rounding reproduces only the 35 shared rows from $0 through $2,250 for every fuel; the top rows differ, so the text limits the claim to those rows.
  • G2: the FY2025 form (R 01/FY2025, January 4, 2025 capture) is now cited in the countable-income comment and references, the earned-age parameter, the PR body and the issue, and the reach (your $40,000 graduate student: $308 in school, $0 out of school) is in the PR body. The comment also cites manual 4.7.3 (p. 43) on the Zero Income Form, but that sentence is only in the 167-page draft: the 190-page FFY 2025 manual on the Clearinghouse (AR_Manual_2025.pdf, created November 18, 2024) omits it from 4.7.3 (p. 59) and keeps the dependent-student rule up to age 23 (pp. 141 and 159), and the PR body now says so. By repo convention registry notes stay one or two short sentences, so the reach is not in programs.yaml.
  • G3: declined. A fuel the source does not map to one priced column stays eligible with $0 as a documented limitation. The application has no solar box, and a solar home could answer all-electric (electric matrix) or write in OTHER (other-fuels matrix), so the source does not fix a column. The same decision keeps these households eligible, so the $0 stays a payment result rather than an ineligibility, and Default heating_type to electricity and remove the UNSPECIFIED-gated state heating adapters #9754 tracks the unspecified default.
  • G4: history is out of scope for this PR; earlier periods and 2027 stay unverified backfilled estimates. The registry note now says other years are unverified, and the PR body records the 2024 contrast ($308 against the FY2024 matrix's $257) and the FY2027 proposal ($70-$665, or $66-$627 in AEO's responses). No FY2025-FY2027 plan mentions an IIJA supplement, so no end date applies.
  • G5: the gambling and capital-gains comments, the PR body's conflict rows and the issue now cite the plans' lottery-only lump-sum sentence (p. 7) and the manual's nonrecurring lump-sum exclusion (p. 138). The model still follows the Appendix F rows (pp. 132 and 135). As you noted, interest and TEA need no change.
  • G6: income/student_exclusion/child_age_limit is now income/earned_minimum_age (still 18). The fpg_year_lag titles say "reproduced by", and the FY2026 electric, size-group and income-band titles drop "Winter"; the four WINTER ONLY files keep it. I also fixed the glued numbers in the test comments and the Case 19 name. The three comments that cited internal material now cite the manual and plan, and the PR body and the issue no longer call the PR a draft. The MCI rounding literal stays: the manual sets MCI at the nearest whole dollar (p. 42), so np.floor(x + 0.5) is the repo's half-up idiom and there is no policy lever to parameterize. The limit has a parameter only because its rounding is an inferred pattern.
  • LIHEAP wave 2a: encode Arkansas LIHEAP regular heating assistance TheAxiomFoundation/rulespec-us#1538 is refreshed to this head.

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

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

Program Review

IDs: C = critical, S = should address, G = suggestion. S1-S4 and G1-G6 keep the prior review's numbers; C1, S5-S6 and G7-G13 are new.

Source Documents

Paths: P/ = policyengine_us/parameters/gov/states/ar/ee/aeo/liheap/, V/ = policyengine_us/variables/gov/states/ar/ee/aeo/liheap/, T/ = policyengine_us/tests/policy/baseline/gov/states/ar/ee/aeo/liheap/. Pages are file pages of the adopted manual unless marked "draft".

Branch Status

  • 11 commits ahead of main and 38 behind. The branch merges cleanly with main, with no conflicts; the head already includes #9558 and #10046.
  • Informational only: the staleness did not affect any finding.

Critical (Must Fix)

C1. The full-time-student earnings exclusion is broader than the adopted manual

  • Defect: V/income/ar_liheap_countable_income.py:40-42 excludes the earnings of every full-time student (is_full_time_student: any college or K-12 student) at any age, with no dependency or credit-hour test. The comment at :31-39 cites "Manual section 4.7.3 (page 43)" as support and calls the narrower rules "the draft manual's". Test comments repeat "without age or dependency restrictions" (T/ar_liheap.yaml:578-582; T/income/ar_liheap_countable_income.yaml Cases 2 and 21-23).
  • Evidence:
    • Glossary: "Full-time Student – a full-time student, up to age 23, who is a dependent of a member of the household", with 12 or more credit hours (p. 141).
    • Appendix F excludes college earnings only for students "up to age 23, who are listed as dependents of a household member" (p. 159), and a child's earnings under 18 (p. 158).
    • 4.7 excludes an 18-year-old high-school student's earnings "unless working full time or the individual is emancipated" (p. 56).
    • The adopted 4.7.3 drops the "who is not a full-time student" sentence (p. 59); only the draft has it (draft p. 43). The PR body concedes this; the code comment does not.
    • The application's "(18 and older & not a full-time student)" (p. 2, both versions) does not define the term, and the plans have no student row. The manual's definition is the natural reading. No source supports "any age, no dependency". No FY2026 manual exists, and no FY2026 source is broader.
  • Impact: T/ar_liheap.yaml Case 19 (2026): three independent full-time students aged 22-24 with $48,000 of wages each get countable income $0 and $308. Under the manual, $48,000 × 0.8 = $38,400 exceeds the $28,164 limit, so each gets $0, as the case's non-student control row shows. Overpayment: $308 per student unit, in 2025 and 2026.
  • Prior G2: the round-1 fix added the FY2025 form citation (correct) and the draft 4.7.3 sentence (not in the adopted manual).
  • Preferred fix:
    • Add P/income/full_time_student_age_limit.yaml = 23, cited to p. 141 and p. 159; state that "up to age 23" is read as inclusive.
    • Exclude earnings for is_full_time_college_student & is_tax_unit_dependent & (age <= limit), and for 18-year-old high-school students (is_in_k12_school); note that the full-time-work and emancipation exceptions are not modeled. Keep earned_minimum_age (18).
    • Tests: countable-income Case 2 becomes $15,600; Case 23 (dependent, 24) becomes $24,000; T/ar_liheap.yaml Case 19 becomes [38_400, 38_400, 38_400, 38_400], all ineligible, ar_liheap: [0, 0, 0, 0] (rename it). Cases 21, 22 and 24 do not change.
    • Rewrite the comment to cite p. 56, 141, 158 and 159.
  • Minimum fix (keeps the form-literal values): delete the 4.7.3 sentence, cite p. 141 and p. 159 as contrary authority, correct the five test comments, and state the divergence and its reach in the programs.yaml note.

Should Address

S5. References and the registry note cite the superseded draft manual

  • Defect: every manual citation points to the August 2024 draft. The adopted manual ("Effective October 1, 2024 – September 30, 2025") was created on 2024-11-18, before the season opened.
  • Where: V/income/ar_liheap_countable_income.py:18-20, V/ar_liheap_household_size.py:13-19, P/income/sources/unearned.yaml:6,51-52, P/income/sources/earned.yaml:31-32, P/income/interest_disregard.yaml:17-18, test comments (T/ar_liheap_household_size.yaml:1,44; T/income/ar_liheap_countable_income.yaml:154), and policyengine_us/programs.yaml:819 ("draft-manual income rules ... are unverified").
  • Evidence: a word-level diff of Appendix F, 4.4-4.4.1 and 4.7.3-4.9 found every encoded rule unchanged except the 4.7.3 student sentence (C1). No values change.
  • Fix: retarget to https://liheapch.acf.gov/docs/2025/manuals/AR_Manual_2025.pdf (draft → adopted pages: 36-37 → 52-53; 41 → 56; 42 → 57-58; 43 → 59; 47 → 63; 116 → 141; 129-130 → 154-155; Appendix F 131-144 → 156-168). Add the wage, farming and self-employment rows (158, 159, 166) to the earned.yaml manual title. Update the registry note.
  • Severity: the reference validator said suggestion and the regulatory reviewer said should; SHOULD, because the adopted version of the cited draft exists.

S6. unearned.yaml comments misstate the gift and loan rules and omit counted sources

  • Cash gifts (confirmed mismatch): P/income/sources/unearned.yaml:25-26 counts all financial_assistance. The manual counts "Cash gifts - Regular" (three or more consecutive months) and excludes "Cash Gifts - Irregular" (p. 157). The plans' "Cash gifts" box has no qualifier, and line 6 says the manual is followed. Example (2026, one person, gas): a one-time $1,200 gift gives $295 instead of $308, and near the limit it can remove eligibility.
    • Not critical: no input separates regular from irregular gifts, so the remedy is documentation. Suggested: "Manual Appendix F (page 157) counts only regular cash gifts (three or more consecutive months); financial_assistance cannot separate them, so all reported gifts are counted." Precedent: gov/states/me/dhhs/tanf/income/sources/unearned.yaml:11-12.
  • Loans: lines 7-8 say "Counted loans ... are not represented", but the manual says "All loans are excluded as income" (p. 163); only plan 1.9 checks loans. The output is right; the comment contradicts line 6.
  • Counted sources with no note: HUD utility payments (p. 161), adoption assistance (p. 156), cryptocurrency (p. 157), crowd-fund accounts (p. 158), executor fees (p. 159), inheritance (p. 162), Trade Adjustment Assistance (p. 168), and the application's "Housing Utility Assistance Payment". Add them to the "not represented" note.
  • Severity: the auditors said minor to should; SHOULD, because the comments misstate what the governing manual counts.

Suggestions

  • G7. V/payment/ar_liheap_matrix_amount.py:46-50: link the FY2025 plan p. 9, the Wayback capture and the Clearinghouse 2025 matrix; "October 7, 2024" is PDF metadata, not printed; say "the 35 rows whose lower bounds run from $0 to $2,250".
  • G8. Wayback hrefs (P/income/earned_minimum_age.yaml:17, V/income/ar_liheap_countable_income.py:24): use the id_ form so #page=2 opens; name "AEO 9495 R 11/2025" at earned_minimum_age.yaml:14 and align "Section" casing.
  • G9. Citations: Pension row "surviving dependents" (draft p. 140) for unearned.yaml:19; "FY2026 plan item 2.3 (page 10)" at V/eligibility/ar_liheap_eligible.py:33; Appendix E (draft p. 130) for the Case 26 VA input; a URL for the CSCDC statement (T/ar_liheap_household_size.yaml:1).
  • G10. V/income/ar_liheap_countable_income.py:43-44: the input is net of expenses, which stands in for the manual's 10% cost allowance (p. 166); "approximates gross receipts" is misleading.
  • G11. Add a comment near V/income/ar_liheap_income_limit.py:36-39 citing 42 USC 8624(b)(2)(B) and the minimum margin (at least 27% through 2030), since GA and FL add gov.hhs.liheap.fpg_floor.
  • G12. Tests: split Case 26 dividends between qualified and non-qualified; add a size-22 limit element ($16,395 a month in FY2026); pin the 26 untested FY2025 matrix cells that change at 2025-10-01. A hand-traced mutation survives each gap.
  • G13. Style: consider an integration.yaml; use person1-style names in T/ar_liheap.yaml Cases 17-18 and 38_400 at line 573; direct_responsibility = has_expense (V/eligibility/ar_liheap_eligible.py:34) is a single-use alias.

Prior Findings

ID Finding Status
S1 Raw unemployment_compensation in unearned list RESOLVED; Case 26 pins reported UI
S2 Off-template descriptions RESOLVED
S3 Untested sources, bill term, size-0 limit RESOLVED (Case 26; eligibility Case 7; household-size Case 2)
S4 Missing page lists RESOLVED
G1 Explain FY2025 "20% OVER BASE" matrices RESOLVED (precision in G7)
G2 Cite FY2025 form; state student reach STILL OPEN: superseded by C1
G3 Solar and unspecified fuel paid $0 STILL OPEN: declined by author; documented (#9754), acceptable
G4 FY2027 and pre-FY2025 backfill RESOLVED (documentation)
G5 Lump-sum conflict wording RESOLVED
G6 Hygiene RESOLVED; rounding literal declined by author, accepted

PDF Audit Summary

Category Count
Documents audited 5 (467 pages at 300 DPI), plus 8 external spot-checks
Values and rows matched 64
Mismatches queued 12
Confirmed (code path and 600-DPI check) 2 (C1; S6 cash gifts)
Investigated and cleared 10
References checked 31: 30 correct, 0 wrong, 1 unverifiable (HTTP 403)

Investigated and cleared:

  • FY2025 matrix extremes vs plan 2.6: AEO's "(20% OVER BASE)" matrices govern ($50 and $475 × 1.2).
  • Social Security net of Part B: the plans' "Excluding MediCare deduction" and 4.7.2 (p. 59) govern.
  • TEA counted: Appendix E (p. 155) and both forms count it.
  • $200 monthly per-member interest disregard: the manual row (p. 162) refines the plan.
  • Rental income with the 20% disregard: rental property is self-employment (p. 165).
  • Gambling and capital gains in full: Appendix F rows followed; inputs cannot separate one-time receipts.
  • Workers' compensation counted: manual (p. 168) and form count it.
  • No extra 10% self-employment discount: the input is already net of expenses.
  • "Counted loans" comment: output matches the manual; wording in S6.
  • 4.7.3 Zero Income Form comment: merged into C1.

Validation Summary

Check Result
Regulatory accuracy 1 critical (C1); incremental fixes correct, no regressions
References New anchors correct; draft manual still cited (S5)
Code patterns No hard-coded values; descriptions on template
Test coverage 72 cases; every variable tested; prior S3 gaps pinned (G12)
CI 29/29 pass at 1206c14c3f
Main merge #9558 guard passes; #10046 not applicable
Federal 110% floor Never binds
Changelog Present, top level, added

Review Severity: REQUEST_CHANGES

One confirmed value mismatch (C1) changes eligibility and benefits.

Next Steps

To auto-fix issues: run the fix-pr workflow for this PR.

@hua7450

hua7450 commented Oct 19, 2026

Copy link
Copy Markdown
Collaborator Author

Thanks for the review. Fixes pushed in 23a055f.

  • C1: The model now reads the forms' undefined "full-time student" with the adopted manual's definition. New income/full_time_student_age_limit (23, "up to age 23" read as inclusive; pp. 141 and 159) and income/high_school_student_age_limit (18; p. 56) limit the earnings exclusion to members under 18 (earned_minimum_age, unchanged), dependent full-time college students (is_full_time_college_student & is_tax_unit_dependent & age <= 23) and 18-year-old high-school students (is_in_k12_school). The full-time-work and emancipation exceptions are documented as not modeled, and the comment now cites pp. 56, 141, 158 and 159 and no longer has the draft 4.7.3 sentence. Countable-income Case 2 is now $15,600 and Case 23 is $24,000; ar_liheap Case 19 is renamed, with countable income [38_400, 38_400, 38_400, 38_400], all ineligible and ar_liheap: [0, 0, 0, 0]. New Cases 27 (a 19-year-old high-school student, $23,796) and 28 (a dependent part-time student aged 20, $24,000) cover earnings that count. The p. 141 definition also says "High school students over age eighteen (18) may provide proof of enrollment or report card"; I followed section 4.7's 18-year-old rule and recorded the conflict in high_school_student_age_limit.yaml.
  • S5: Every manual citation in variables, parameters and test comments now points to AR_Manual_2025.pdf. I used your mapping, refined where a passage sits on one page: 4.4-4.4.1 on p. 52, the month-before unearned rule on p. 57, MCI rounding on p. 58 and the 4.7.4 loss rule on p. 63. The earned.yaml manual title lists pp. 158-159 and 165-166 (wages, farming, rental property and self-employment). The registry note says the income rules follow the FFY 2025 manual because no FY2026 manual was found. No values change.
  • S6: The unearned.yaml notes now say that financial_assistance counts every reported gift because the input cannot separate regular from irregular gifts (p. 157), and that the manual excludes all loans (p. 163), so none is counted. They also list, with pages, the counted receipts that have no input: adoption assistance, cryptocurrency, crowd-fund accounts, executor fees, foster care, HUD utility payments (including the application's Housing Utility Assistance Payment), inheritance, jury duty pay, royalties and Trade Adjustment Assistance. The PR body's not-modeled table matches, and values are unchanged.
  • G7: The matrix reference tuple adds FY2025 plan p. 9, the December 6, 2024 Wayback capture (id_ form) and the Clearinghouse 2025 matrix. The comment calls October 7, 2024 the PDF metadata date and refers to the 35 rows whose lower bounds run from $0 to $2,250.
  • G8: Both Wayback hrefs use the id_ form, so #page=2 opens. The current form is named by its printed footer, "LIHEAP 9495 R 11/2025" (only the FY2025 form prints "AEO 9495"), and the titles use "Section".
  • G9: Added the Pension row's "surviving dependents" citation (p. 165) above survivor_benefits, "FY2026 plan item 2.3, page 10" in ar_liheap_eligible.py, Appendix E (p. 155) for the Case 26 VA input, and the CSCDC URL in the household-size test header.
  • G10: The formula and earned.yaml comments now say the business inputs are already net of expenses, which stands in for the manual's 10% operating-cost allowance (p. 166).
  • G11: ar_liheap_income_limit.py now cites 42 U.S.C. 8624(b)(2)(B) and says that in 2025-2027 every limit stays at least 32% above 110% of the guideline at every household size, so no separate floor applies. I kept the hand-checked 2025-2027 margin in place of a 2030 figure. Later years rest on projected SMI and guidelines, and the fixed per-member amount above size 20 narrows the margin as households grow.
  • G12: Countable-income Case 26 splits the dividends into $600 qualified and $600 non-qualified. Income-limit Case 4 pins FY2026 size 22 at 15,019 + 2 × 688 = $16,395 a month ($196,740 a year). Matrix Cases 16-18 pin the 26 untested FY2025 cells that change at 2025-10-01 (electric 9, natural gas 14, propane 3), so all 63 changed cells are now tested.
  • G13: Added integration.yaml with five households, each checking heating expense, the heating-cost flag, size, countable income, limit, eligibility, matrix amount and grant: an SSI and Social Security retiree with electric heat ($127), a minimum-wage single parent with gas ($124), a family of four with a dependent college student on propane ($114), an unsubsidized renter whose rent includes gas heat ($146) and an FY2025 retired couple heating with wood ($68). ar_liheap Cases 17-18 now use person1, person2 and spm_unit, Case 18 writes 38_400, and has_expense is inlined. The PR now has 83 cases in 7 files.
  • G2: Resolved through C1. The FY2025 form citation stays (now an id_ link), the draft-only 4.7.3 sentence is gone, and the PR body describes which students are excluded under the manual definition.
  • G3: No change, as you accepted: solar and unspecified fuel stay eligible at $0 as a documented limitation, and Default heating_type to electricity and remove the UNSPECIFIED-gated state heating adapters #9754 tracks the unspecified default.
  • LIHEAP wave 2a: encode Arkansas LIHEAP regular heating assistance TheAxiomFoundation/rulespec-us#1538 is refreshed to match.

Thanks also for checking the ten cleared items. The loan and Zero Income Form comments you folded into S6 and C1 are fixed there.

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

Program Review

IDs: C = critical, S = should address, G = suggestion. C1, S5-S6 and G2-G13 keep the prior review's numbers (S1-S4, G1 and G4-G6 were resolved in round 2); S7 and G14-G19 are new.

Source Documents

Paths: P/ = policyengine_us/parameters/gov/states/ar/ee/aeo/liheap/, V/ = policyengine_us/variables/gov/states/ar/ee/aeo/liheap/, T/ = policyengine_us/tests/policy/baseline/gov/states/ar/ee/aeo/liheap/. Pages are file pages of the adopted manual unless marked otherwise.

Branch Status

  • 13 commits ahead of main and 17 behind. The branch merges cleanly with main. The head includes #10279 (federal 110% floor for DC, MA, MS, NJ and OR); AR does not read gov.hhs.liheap.fpg_floor.
  • Informational only: the staleness did not affect any finding.

Prior findings

ID Status Evidence
C1 RESOLVED V/income/ar_liheap_countable_income.py:44-56 now excludes only dependent full-time college students aged 23 or younger and 18-year-old high-school students (p. 56, p. 141, p. 159). Tests match the preferred fix, and new Cases 27-28 cover the age-19 and part-time cases. S7 covers a remaining input gap.
S5 RESOLVED No draft-manual URL remains. Every new anchor (52, 56-59, 62-64, 141, 154-168) holds the cited rule. policyengine_us/programs.yaml:819 is updated.
S6 RESOLVED P/income/sources/unearned.yaml:6-15,33-35: regular gifts only (p. 157), all loans excluded (p. 163), and every unrepresented counted source listed with its page.
G2 RESOLVED via C1 The draft-only 4.7.3 sentence is gone; the FY2025 form citation is now an id_ link.
G3 STILL OPEN (accepted) Declined by the author and accepted in round 2; documented, tracked in #9754.
G7 RESOLVED V/payment/ar_liheap_matrix_amount.py:32-39,54-60: plan p. 9, the Wayback capture and the Clearinghouse matrix are linked; the date and the "35 rows" wording are correct.
G8 RESOLVED id_ hrefs at P/income/earned_minimum_age.yaml:21 and V/income/ar_liheap_countable_income.py:25; the R 11/2025 footer is confirmed.
G9 RESOLVED Pension p. 165, plan 2.3 p. 10, Appendix E p. 155 and the CSCDC URL are all present and correct.
G10 RESOLVED The net-of-expenses wording matches the 10% allowance on p. 166.
G11 RESOLVED The statute is cited. The "at least 32%" claim is true for 2025-2027 (code-path check: minimum 1.3259 in 2027). One parenthetical is imprecise for 2026 (G18).
G12 RESOLVED The dividend split, the size-22 limit ($196,740) and all 26 FY2025 matrix cells are pinned and match the AEO files.
G13 RESOLVED T/integration.yaml (5 cases), person1 names, 38_400 and the inlined alias.
S1-S4, G1, G4-G6 RESOLVED (round 2) No regression.

Critical (Must Fix)

None. C1 is resolved, and no value mismatch was confirmed this round.

Should Address

S7. The 18-year-old high-school exclusion ignores is_in_secondary_school

  • Defect: V/income/ar_liheap_countable_income.py:49-51 reads only is_in_k12_school. That variable is imputed for ages 5-17 (policyengine_us/variables/household/demographic/person/is_in_k12_school.py:10-17), so it is false at 18 unless a user overrides it. earned_minimum_age already excludes everyone under 18, so this term matters only at age 18, and only with the override. The repo's input for an 18-year-old still in high school is is_in_secondary_school (no formula), and the AR formula does not read it.
  • Rule: section 4.7 excludes the earnings of members "aged 18 and enrolled in an institution of secondary education (high school)" (p. 56).
  • Impact (code-path run at head, 2026, gas): take the household from countable-income Case 24 and set is_in_secondary_school: true in place of is_in_k12_school: true. Countable income is $23,796 (the wages are counted), not $18,300, and ar_liheap is $84, not $107. There is no microsimulation impact: the pinned Populace dataset sets neither flag for anyone aged 18, so the current code and the fix give the same arrays.
  • Note: the prior review's preferred fix named is_in_k12_school. This item corrects that advice.
  • Fix:
    # is_in_k12_school is imputed only through age 17, so an 18-year-old still
    # in high school is captured via is_in_secondary_school.
    high_school_student = (
        person("is_in_secondary_school", period)
        | person("is_in_k12_school", period)
    ) & (age <= p.high_school_student_age_limit)
    • Precedents: mi_ccap_eligible_child.py:32-41, mo_ccs_eligible_child.py:24-31 and sd_cca_eligible_child.py:25-33 use this union. in_eap_income.py:21 and or_liheap_countable_earned_income.py:24-26 read is_in_secondary_school for their student exclusions.
    • Tests: add a Case 24 variant with is_in_secondary_school: true and no is_in_k12_school (expected 18_300). Optionally, set is_in_secondary_school: true on Case 27 (age 19, stays 23_796).
    • A code-path run with this change passes all 83 AR cases and both variants. No parameter changes.
  • Severity: SHOULD. This is a household-level behavior gap with no microsimulation impact. The code validator rated it a suggestion; the regulatory reviewer and the code-path verifier rated it SHOULD, because the standard input gives a result that contradicts section 4.7.

Suggestions

  • G14. Wording and references for the two new parameters and the C1 comment.
    • V/income/ar_liheap_countable_income.py:39-41 cuts the section 4.7 quote short. Add "and applying as the head of household" (p. 56), as P/income/high_school_student_age_limit.yaml:3-4 already does.
    • P/income/full_time_student_age_limit.yaml:16-17 puts two sections in one entry, and its href opens p. 141 only. Split it into two entries: Section 17.0 with #page=141, and Appendix F with #page=159.
    • P/income/high_school_student_age_limit.yaml:17-19: add a p. 141 entry, because the comment at :6-9 relies on that page.
    • In both descriptions (:1), "up to this age" does not say whether the limit is inclusive, and in the first file it attaches to "household member". Suggested text: "Arkansas excludes the earned income of full-time college students who are this age or younger and are dependents of a household member under the Low Income Home Energy Assistance Program." Use the same "this age or younger" wording for high-school students.
    • Optional, at P/income/full_time_student_age_limit.yaml:5-6: say that the inclusive reading matches the IRS student-dependent test ("has not attained the age of 24"), which "listed as dependents" on p. 159 points to.
  • G15. 81 stale is_full_time_student test inputs. No AR formula reads this variable any more. It appears in T/ar_liheap.yaml (29), T/income/ar_liheap_countable_income.yaml (38), T/ar_liheap_household_size.yaml (7) and T/eligibility/ar_liheap_eligible.yaml (7). Remove these inputs. In T/ar_liheap.yaml:559 (Case 18, an 18-year-old non-student), pin the real input with is_in_k12_school: false (and is_in_secondary_school: false after S7). Rule: p. 56.
  • G16. No test derives the dependency proxy.
    • Every C1 case sets is_tax_unit_dependent as an input: T/income/ar_liheap_countable_income.yaml:43,608,640,672,807,839, T/ar_liheap.yaml:590 and T/integration.yaml:134.
    • Code-path runs at head on Case 21's household:
      • with tax_unit_role_input HEAD/DEPENDENT and no dependency input, the result is $19,200, which is correct;
      • with neither roles nor the input, default inference makes the 22-year-old the parent's spouse, and the result is $24,000. p. 159 gives $19,200.
    • The fallback is shared PolicyEngine behavior (is_tax_unit_spouse, tracked in #9868). NY HEAP, IN EAP and NJ LIHEAP behave the same way. The pinned Populace dataset supplies roles for every tax unit.
    • Fix:
      • Add Case 29: Case 21's household with tax_units and tax_unit_role_input HEAD/DEPENDENT, and no is_tax_unit_dependent (expected 19_200).
      • Add a short caveat at V/income/ar_liheap_countable_income.py:38: without supplied roles or this input, age-ordered inference can make a single parent's adult student the spouse (#9868).
      • Do not pin the $24,000 output.
    • Not SHOULD: the test validator proposed SHOULD, but the PR reads the standard variable correctly, and the defect is in a shared variable.
  • G17. Two more C1 boundary tests.
    • A married couple aged 22 and 21, both full-time college students with $15,000 wages each. The expected countable income is 24_000, because head and spouse are not dependents. This test catches a change of the proxy to ~is_tax_unit_head.
    • An 18-year-old full-time college student who is not a dependent. The earnings count (p. 141). This test catches a change of the high-school term to is_full_time_student.
  • G18. The G11 parenthetical is not true for 2026.
    • V/income/ar_liheap_income_limit.py:41-42 says that the per-member amount above size 20 sets the narrowest margin. That is true for 2025 and 2027. In 2026, the narrowest margin is at size 9 in the 150%-of-poverty rows (1.3636, against 1.3646 above size 20).
    • Fix: write "(in 2025 and 2027, the printed per-member amount above size 20 sets the narrowest margin)", or remove the parenthetical.
    • Do not extend the claim past 2027 without a new computation: the fixed $688 approaches 1.29 against later guidelines.
    • Sources: FY2026 chart; 42 U.S.C. 8624(b)(2)(B).
  • G19. Optional documentation.
    • The manual also excludes irregular income up to $90 in three months (p. 162) and odd-job income under $30 in three months (p. 163). The model counts both. Add them to the not-modeled notes in P/income/sources/unearned.yaml:6-15 and P/income/sources/earned.yaml.
    • Name the form version "LIHEAP 9495 R 11/2025" in the application titles at P/income/sources/earned.yaml:30 and P/income/sources/unearned.yaml:63, as in P/income/earned_minimum_age.yaml:18.
    • In T/integration.yaml:172, also cite section 4.8.3 on p. 63. That page has the energy-burden sentence for utilities included in rent.

PDF Audit Summary

Category Count
Documents 5 round-2 manifest documents reused, with no new download. 12 pages were read again as 300-DPI images. Live AEO matrices, the eligibility charts, the R 11/2025 form and the Clearinghouse matrix were checked outside the manifest.
Changed rule items matched 31 of 31 (0 mismatches)
Matrix and chart values in changed tests 61 checked against AEO files, including all 26 FY2025 cells: all match
References (new or changed) 19 checked: 17 correct, 0 wrong, 2 unverifiable (fetch blocked; content corroborated)
In-comment page citations About 95 checked, all correct
Verification-queue items 4, all CONFIRMED: S7; the G16 mechanics (severity SUGGESTION); no microsim reach for S7 or G16; the G11 margin
Confirmed value mismatches 0

Investigated and cleared:

  • 2027 margin below 32% (reference validator): that check used the same-year projected guideline. The repo's floor code (DC, MS, NJ and OR) uses a one-year lag, and with that lag the 2027 minimum is 1.3259. The claim holds.
  • "Any non-head adult is a dependent" (regulatory reviewer): this is not correct. Without roles, the next-oldest adult is inferred as the spouse. This is now part of G16.
  • Microsim reach of S7 and G16: none. The pinned Populace build sets no school flag at age 18, and it supplies tax_unit_role_input for 100% of tax units. policyengine-us-data is archived and is no longer the default.
  • FY2025 gas and propane cells (Cases 17-18), which the PDF audit checked by derivation only: the live AEO FY2025 files confirm all 17 cells.
  • p. 141 "High school students over age eighteen" against the section 4.7 age-18 rule: following section 4.7, the operative income rule, is the better reading. The conflict is recorded in P/income/high_school_student_age_limit.yaml:6-9.
  • Inclusive "up to age 23": the reading is stated and defensible.
  • The full-time-work and emancipation exceptions (p. 56) are not modeled. This is documented, and the manual does not define "full time".
  • Main merge (#10133, #10225, #10279): no AR expected value changes. AR tests set ssi, social_security and medicare_part_b_premium as inputs.
  • The Wayback 2024-12-06 electric matrix and the Clearinghouse 2025 matrix could not be fetched again this round. Their content matches the round-2 downloads.

Validation Summary

Check Result
Regulatory accuracy C1 resolved; the rule matches pp. 56, 141, 158 and 159. 1 new should-address item (S7).
References 0 wrong; no draft-manual URL remains; 2 new URLs not fetched again (content corroborated)
Code patterns No hard-coded values; vectorized; ruff clean; wording nits only (G14)
Test coverage 83 cases in 7 files; 16 changed or new rows recomputed by hand, 0 mismatches; C1 age boundaries pinned; dependency proxy set only as an input (G16)
CI 29/29 pass at f2a1172c0f
Local tests 83/83 pass at PR head (snapshot run)
Microsim reach S7 and G16 do not change microsim output
Federal 110% floor Never binds; minimum margin is 32.6% (2025-2027, lagged guideline)
Main merge No AR value affected; programs.yaml AR entry valid
Changelog Present, top level, added

Review Severity: REQUEST_CHANGES

C1 is fixed. One should-address item (S7) is open: the 18-year-old high-school exclusion does not work with the standard is_in_secondary_school input.

Next Steps

  1. Fix S7: change one expression in V/income/ar_liheap_countable_income.py:49-51 and add one test case.
  2. Optional: G14-G19.

To auto-fix issues: run the fix-pr workflow for this PR.

@DTrim99

DTrim99 commented Oct 20, 2026

Copy link
Copy Markdown
Collaborator

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

PR #9973 (author: hua7450). This round reviews head f2a1172c0f; round 1 reviewed 7e42062309. Four commits and two outside reviews came in between:

  • 7382b864a4, a merge of main at 9560e7f183. It brought in Integrate modeled state unemployment insurance into income flows #9558 (total_unemployment_compensation and its guard) and Document disjoint health premium inputs and correct consumer treatment #10046 (pre_tax_health_insurance_premiums).
  • 1206c14c3f, "Address review round 1 on Arkansas LIHEAP". It answers S1–S4 and G1–G6 and brings the suite to 72 cases.
  • PavelMakarchuk requested changes on 1206c14c3f (2026-10-19). He raised:
    • C1: the full-time-student exclusion was broader than the adopted manual;
    • S5: the PR cited the superseded draft manual;
    • S6: the gift and loan comments were wrong;
    • suggestions G7–G13.
  • 23a055f11a, "Address Pavel's review on Arkansas LIHEAP". It:
    • rewrites the student exclusion with two new parameters (full_time_student_age_limit 23, high_school_student_age_limit 18);
    • moves every manual citation to the adopted 190-page FFY 2025 manual;
    • adds countable Cases 27–28, limit Case 4, matrix Cases 16–18 and a new integration.yaml, for 83 cases in 7 files.
  • f2a1172c0f, a merge of main at 1661d715bd (Apply the federal 110% poverty floor to state LIHEAP programs (DC, MA, MS, NJ, OR) #10279, the shared 110% poverty floor).
  • PavelMakarchuk requested changes again on f2a1172c0f (2026-10-20 19:21 UTC). He marked C1, S5, S6 and G7–G13 resolved, and raised a new should item (S7) and suggestions G14–G19. No author reply or commit has followed.

Neither merge had a hand-resolved conflict, and neither touches an Arkansas LIHEAP file.

Path prefixes, as in round 1:

  • P/ = policyengine_us/parameters/gov/states/ar/ee/aeo/liheap/
  • V/ = policyengine_us/variables/gov/states/ar/ee/aeo/liheap/
  • T/ = policyengine_us/tests/policy/baseline/gov/states/ar/ee/aeo/liheap/
  • "Manual" = the adopted FFY 2025 Arkansas LIHEAP Policy and Procedures Manual (190 pages). Page numbers are file pages.

Line numbers refer to f2a1172c0f.

Summary

Ziming fixed all four round-1 should items:

  • S1. The unearned list reads total_unemployment_compensation. Main's guard passes at the head, and countable Case 26 pins a reported $5,412.
  • S2. All six descriptions use template verbs, and all 21 descriptions end at the program name.
  • S3. Each of the three gaps now fails a test:
    • each of the five sources is positive in its own row of countable Case 26;
    • the bill term is gone, and eligibility Case 7 pins an explicit false;
    • household-size Case 2 asserts the $0 limit.
  • S4. The page lists are added.

Of the six suggestions, G1, G2 (through Pavel's C1), G5 and G6 are fixed; G6's rounding literal is kept, which I accept. G3 is declined and G4 is documented; I accept both, as in #9967–#9972.

Pavel's C1, S5, S6 and G7–G13 are all fixed. I checked the new student rule against the adopted manual's text on pages 56, 141 and 159.

One should item is open: Pavel's S7 from today, which I concur with. The 18-year-old high-school exclusion reads only is_in_k12_school, which defaults to false at 18. It ignores is_in_secondary_school, the repo's input for that status. A caller who sets the standard input gets the student's wages counted, against section 4.7 (page 56). The fix is one expression and one test. Pavel's G14–G19 are open suggestions. I agree with them, except one point in G14: splitting a reference would break CLAUDE.md's one-entry-per-source rule.

There are no new critical or should findings. Two new suggestions:

Batch checks:

I checked every new or changed expectation by hand: 13 new cases, 3 cases with changed values and one added assertion. CI is 29/29 green at the head. The branch is 13 commits ahead of main and 18 behind, and merges cleanly.

Prior findings status

Finding Status Evidence
S1: the unearned list read raw unemployment_compensation, so main's #9558 guard failed after merging Fixed The list. P/income/sources/unearned.yaml:18 reads total_unemployment_compensation, and no Arkansas LIHEAP file reads the raw input. The guard. All four test_unemployment_compensation_readers.py tests pass at the head (Rest shard-1). The case. Countable Case 26 row 1 reports 5,412 (451 × 12), giving 5,412 and MCI 451. Arkansas UI is not modeled, so the total equals the reported amount. The issue. rulespec-us#1538's output and inputs name the total.
S2: six descriptions off the template Fixed The six. max_table_size now says "sets income limits through this household size, with a fixed monthly amount for each additional member". rounding_increment, both source lists, household_size_group and income_band use "uses". interest_disregard takes the optional "this monthly amount of each member's interest". All 21. Every description, including the three new age parameters ("excludes"), ends at "under the Low Income Home Energy Assistance Program."
S3: five sources and two pieces of logic unpinned Fixed (1) Sources. Countable Case 26 gives each source its own unit with a distinct amount: 5,412; 3,000; 1,200 (600 qualified plus 600 non-qualified, through ordinary_dividend_income, which adds both); 6,624; and 1,800. Dropping any entry zeroes its row. (2) Bill term. V/eligibility/ar_liheap_eligible.py:35 reads has_heating_expense alone. Eligibility Case 7 expects [true, false] and [190, 0], and restoring (expense > 0) | would make row 2 true. (3) Size-0 mask. Household-size Case 2 asserts ar_liheap_income_limit: 0; without the mask it would be 28,164.
S4: missing page lists Fixed Plans. The FY2026 unearned title ends "#page 6-7", the FY2025 unearned title "#page 5-7" and the FY2025 earned title "#page 5-6". Manual. The manual entries now cite the adopted manual (Pavel's S5): unearned "#page 155-163,165-168" at #page=155, and earned "#page 158-159,165-166" at #page=158.
G1: say why the "20% OVER BASE" matrices win Fixed The comment. V/payment/ar_liheap_matrix_amount.py:54-60 explains the choice and limits the 1.2× claim to "the 35 rows whose lower bounds run from $0 to $2,250". The references. The tuple adds FY2025 plan p. 9, the December 6, 2024 Wayback capture (id_ form) and the Clearinghouse "2025" matrix. The body. A bullet says the same.
G2: the FY2025 form and the reach of the student rule Fixed (superseded by Pavel's C1) The FY2025 form is cited with an id_ link. The draft-only 4.7.3 sentence is gone. The reach now follows the manual's definition: the $40,000 graduate student I described is counted.
G3: solar and unspecified fuel eligible at $0 Declined (accepted) Documentation. The body and the matrix comment record the gap, with #9754 for UNSPECIFIED. Test. Matrix Case 15 pins $0 for SOLAR and UNSPECIFIED. This matches #9967–#9972. Optional. A final-award case pinning eligible-at-$0, as Oklahoma and Rhode Island added.
G4: FY2027 and pre-FY2025 years Documented (accepted) Notes. The registry note says "other years are unverified". The body records the 2024 contrast ($308 against the FY2024 matrix's $257) and the FY2027 proposal ($70–$665, or $66–$627). Sources. On 2026-10-20 the AEO LIHEAP page still lists only the FY2026 matrices, the FY2025 and FY2026 charts, and the proposed FY2027 plan with AEO's responses. The guessed FY2027 chart and matrix URLs return 404.
G5: the lump-sum wording Fixed Comments. P/income/sources/unearned.yaml:41-49 cites the plans' lottery-only note (p. 7) and the manual's nonrecurring lump-sum exclusion. I confirmed the "Nonrecurring lump sum payments" row on p. 163. Body. The conflict rows match.
G6: hygiene Mostly fixed (literal declined, accepted) Done. The age parameter is income/earned_minimum_age. The fpg_year_lag titles say "reproduced by". "Winter" is gone from the electric, size-group and band titles. Test comments are re-spaced. Internal-material comments now cite the manual and plan. Neither the body nor the issue calls the PR a draft. Declined. The MCI rounding literal stays, which is fair: p. 58 says "Round MONTHLY COUNTABLE INCOME (MCI) to the nearest whole dollar amount", so there is no policy lever.

Pavel's review of 1206c14c3f. Every item is fixed:

Pavel's item Status Evidence
C1: full-time students of any age, with no dependency test Fixed The code. V/income/ar_liheap_countable_income.py:44-56 now excludes earnings only for members under 18, for is_full_time_college_student & is_tax_unit_dependent & age <= 23, and for is_in_k12_school & age <= 18. The manual (adopted text, read this round). p. 141 defines "Full-time Student – a full-time student, up to age 23, who is a dependent of a member of the household and can provide verification that s/he is enrolled for twelve (12) credit hours or more per semester". p. 159 excludes "Income received by full-time college students, up to age 23, who are listed as dependents of a household member". p. 56 covers members "aged 18 and enrolled in an institution of secondary education (high school)". The tests. Countable Cases 2 (15,600) and 23 (24,000) changed. ar_liheap.yaml Case 19 is now [38,400 ×4], [false ×4] and [0 ×4]. Cases 21, 22 and 24 are unchanged, and Cases 27–28 are new.
S5: draft manual cited Fixed Links. No PR file links the draft manual. Anchors I spot-checked in the adopted manual: p. 52 (at least one eligible member); p. 56 (the 18-year-old rule); p. 58 (MCI rounding); p. 59 (4.7.1 child support; 4.7.2 "This includes the Medicare Part B Buy-in premium"); p. 63 (negative self-employment income counted as zero); p. 64 (4.8.3.1–4.8.3.2); p. 141; p. 157 (regular and irregular gifts, capital gains); p. 159; p. 162 ("amount over $200.00"); p. 163 (loans, lump sums); p. 165 ("surviving dependents"). Registry. The note now says the income rules follow the FFY 2025 manual.
S6: gift and loan comments Fixed The comments. P/income/sources/unearned.yaml:6-15 and :33-35 cover regular gifts only (p. 157, which prints "Cash gifts - Regular" and "Cash Gifts - Irregular") and "All loans are excluded as income" (p. 163). They also list the unrepresented sources with pages. The body. The not-modeled table matches.
G7: matrix comment and references Fixed See G1.
G8: id_ Wayback links and form names Fixed Both Wayback hrefs use id_, and the current form is named "LIHEAP 9495 R 11/2025".
G9: citations Fixed Where each sits. Pension "surviving dependents" (p. 165) at unearned.yaml:26-27; plan item 2.3, page 10 at ar_liheap_eligible.py:33; Appendix E (p. 155) in the Case 26 comment; the CSCDC URL in the household-size header.
G10: net-of-expenses wording Fixed ar_liheap_countable_income.py:57-61 and earned.yaml:2-5.
G11: cite the 110% floor Fixed ar_liheap_income_limit.py:39-43. The parenthetical is refined in G18 below.
G12: test gaps Fixed Dividends. Case 26 splits them. Limit. Case 4 checks 196,740. Matrix. Cases 16–18 add 26 FY2025 cells. See Verified for each.
G13: style and integration Fixed integration.yaml (5 cases), person1 names, 38_400 and the inlined alias.

Pavel's review of this head (f2a1172c0f, 2026-10-20). Nothing is addressed yet:

Pavel's item Status Evidence
S7: the 18-year-old high-school exclusion ignores is_in_secondary_school Open; I concur (should) The code. V/income/ar_liheap_countable_income.py:49-51 reads only is_in_k12_school, whose formula returns true for ages 5 to 17. earned_minimum_age already excludes everyone under 18, so the term matters only at 18, and only when a caller overrides that input. The repo's input. is_in_secondary_school ("Is in secondary school (or in an equivalent level of training)") has no formula. Federal TANF demographic eligibility and the merged Oregon LIHEAP and Indiana EAP earnings exclusions read it. The rule. p. 56: "The earned income of household members who are aged 18 and enrolled in an institution of secondary education (high school) is not countable unless working full time or the individual is emancipated and applying as the head of household." Hand trace (from the code, not run). Take countable Case 24's household and set is_in_secondary_school: true in place of is_in_k12_school: true. The senior's wages count: (22,880 + 6,864) × 0.8, MCI 1,983, or 23,796. With natural gas heat the award is $84; the rule gives 18,300 (MCI 1,525) and $107. This matches Pavel's code-path run. Why should. A caller using the standard input gets a result that contradicts section 4.7 in the claimed years. It has no microsimulation effect (Pavel), and the fix is one expression and one test, so it is not critical. Fix. As Pavel proposed: read is_in_secondary_school | is_in_k12_school and add a Case 24 variant. Also update the body's "Student status and dependency" row and #1538's inputs and countable-income definition.
G14: wording and references of the new parameters Open; partly concur The quote. The comment at line 40 stops at "the individual is emancipated"; p. 56 continues "and applying as the head of household". The descriptions. The "up to this age" wording is ambiguous; worth fixing. The references. Do not split P/income/full_time_student_age_limit.yaml's entry in two. CLAUDE.md requires one entry per source document, with the href at the first page and the pages in a quoted title. That is what the file has: "... #page 141,159" at #page=141. For P/income/high_school_student_age_limit.yaml, which leans on p. 141 in lines 6-9, extend the existing title to "... #page 56,141" rather than adding a second entry.
G15: 81 stale is_full_time_student inputs Open; concur The count. 29 + 38 + 7 + 7 = 81 across ar_liheap.yaml, countable income, household size and eligibility. No Arkansas formula reads the variable, so all 81 are unread, including six true values that sit beside the real inputs. Harmless, but misleading. Case 18. Pinning is_in_k12_school: false (and, after S7, is_in_secondary_school: false) would make the case state its real input.
G16: no test derives the dependency proxy Open; concur (suggestion) is_tax_unit_dependent is ~head & ~spouse. Every student case sets it as an input: countable Cases 2, 21–23, 27 and 28, ar_liheap.yaml Case 19 and integration Case 3. A roles-based case and a one-line caveat are reasonable. The age-ordered spouse inference is shared behavior (#9868).
G17: two boundary tests Open; concur The surviving mutations. Replacing the dependency term with ~is_tax_unit_head survives, because no case has a married student couple. Replacing is_in_k12_school with is_full_time_student also survives, because no case has an independent 18-year-old full-time college student; the ar_liheap.yaml Case 19 students are 22–24.
G18: the floor comment's parenthetical Open; concur 2026, with the one-year lag the repo's floor code uses. Size 9 is $7,456 against 1.1 × 59,650 / 12 = $5,467.92, a ratio of 1.3636. The per-member $688 against 1.1 × 5,500 / 12 = $504.17 is 1.3646. So in 2026 the poverty-guideline rows, not the per-member amount, set the narrowest margin. "At least 32%" still holds.
G19: optional documentation Open (optional); concur p. 162 has an "Irregular income" row and p. 163 an "Odd job income" row. The form-version titles and the 4.8.3 citation are polish.

New findings

Critical (must fix)

None.

Should address

None new. Pavel's S7 (above) is the one open should item at this head, and I concur.

Suggestions

1. After #10182, count military SBP survivor annuities through military_retirement_income.

  • Where: P/income/sources/unearned.yaml:25 lists military_retirement_pay, with pension_income at line 24 and survivor_benefits at line 28. The comment at lines 21-23 says military retirement pay is listed separately from pension_income.
  • What changed on main: Wire military retirement pay and survivors into federal and state tax (#10181) #10182 merged on 2026-10-20, after this head's last merge at 1661d715bd.
    • At this head, military_retirement_pay is documented as "The benefits received under a United States military retirement plan, including survivor benefits".
    • On main it is taxable retirement pay of former members, and SBP annuities go in military_retirement_pay_survivors: "Taxable survivor annuity payments received by surviving spouses, dependent children, or other designated annuitants ... (such as the Survivor Benefit Plan (SBP)...)".
    • military_retirement_income adds both. pension_income does not include the new input.
    • Wire military retirement pay and survivors into federal and state tax (#10181) #10182 also moved Arkansas's own income-tax source lists to the combined variable.
  • The rule counts these payments. The PR's own comment at lines 26-27 says the Appendix F Pension row covers payments to a person's "surviving dependents" (p. 165, which I confirmed). Military retirement is counted on the same page.
  • Effect on the merged tree (worked out from the code, not run). A surviving spouse aged 62 has $24,000 a year of SBP annuity entered in military_retirement_pay_survivors. She lives alone, heats with natural gas with a $1,200 bill and has no other income, in 2026:
  • Why a suggestion, not should:
  • Fix, if taken here:
    • Replace the entry with military_retirement_income, and update the lines 21-23 comment.
    • Add a military_retirement_pay_survivors amount to countable Case 11, or add a separate case.
    • Update Resolve US discrepancies against TAXSIM35 for 2021 #1538's countable-income definition and inputs.

2. Consider excluding a dependent high-school student aged 19 to 23 as a "full-time student".

  • Where:
    • V/income/ar_liheap_countable_income.py:49-51 excludes high-school students only through age 18 (high_school_student_age_limit).
    • P/income/high_school_student_age_limit.yaml:6-9 records the choice.
    • Countable Case 27 (line 793) counts a 19-year-old dependent high-school student's wages.
    • The body's "Full-time students" conflict row says the same.
  • The text (adopted manual, read this round):
    • p. 141: "Full-time Student – a full-time student, up to age 23, who is a dependent of a member of the household and can provide verification that s/he is enrolled for twelve (12) credit hours or more per semester. High school students over age eighteen (18) may provide proof of enrollment or report card."
    • p. 56: the earned income of members "aged 18 and enrolled in an institution of secondary education (high school) is not countable unless working full time or the individual is emancipated and applying as the head of household."
  • Why the texts need not conflict:
    • Section 4.7 covers every 18-year-old in high school, dependent or not, with two exceptions. It says nothing about older students.
    • The definition, which the PR already uses to read the application's undefined "full-time student", names high-school students over 18 among full-time students. They prove enrollment instead of credit hours, within the same "up to age 23, who is a dependent" frame.
    • Read together, a dependent high-school student aged 19–23 is a full-time student whose work income the application ("18 and older & not a full-time student") does not request. The PR instead infers from section 4.7's silence that these students' earnings count.
  • Effect (hand-computed from the code). Take Case 27's household with natural gas heat and a bill, in 2026:
    • Head: 23,796 (MCI 1,983): $84.
    • Under this reading: 18,300 (MCI 1,525): $107.
  • Why a suggestion:
    • The PR documents the choice with a reason.
    • Pavel reviewed it and cleared section 4.7 as the better reading.
    • The case is rare, and both readings are defensible.
  • Fix, if taken (with S7, in the same expression): treat (is_in_secondary_school | is_in_k12_school) like is_full_time_college_student in the dependent, age 23 or younger test. Keep the separate age-18 high-school term for non-dependents. Case 27 would become 18,300. Update its comment, the parameter comment, the body row and Resolve US discrepancies against TAXSIM35 for 2021 #1538 interpretation 3(c).

Verified

  • Mutation check (item 13), reasoned from the tests and code at the head:
    • dependent_college_student:
      • is_full_time_college_student. Countable Case 28: a part-time dependent aged 20 is counted (24,000). Dropping the term would give 19,200.
      • is_tax_unit_dependent. Countable Case 2 (15,600) and ar_liheap.yaml Case 19: independent students are counted.
      • age <= 23. Case 22 (age 23, excluded, 19,200) and Case 23 (age 24, counted, 24,000) pin both the value and the <=.
    • high_school_student:
      • is_in_k12_school. Countable Case 24 (18,300) against Cases 4 and 25 (counted). Dropping the input term would exclude every 18-year-old, and dropping the whole term fails Case 24.
      • age <= 18. Case 27 (age 19, counted).
    • Other new or reworked pieces:
      • earned_minimum_age. Countable Cases 3, 19 and 20, and ar_liheap.yaml Case 17.
      • The direct branch, the size-0 mask and the five sources. See S3.
    • Not pinned: the two mutations in Pavel's G17.
    • Unchanged since round 1: the other branches. Round 1 confirmed them by mutation runs.
  • State-gated keys (item 15, NH Add New Hampshire state supplementation for 2026 #10156).
    • No new keys. The three new parameters are scalars, and no new int or enum key was added.
    • Household size. ar_liheap_household_size still enters only bracket lookups through max_(size, 1), smi() and clip(size, 1, 20).
    • Matrix keys. They are always 1–39 and 1–3.
    • Mixed-state test. ar_liheap.yaml Case 5 still runs AR and GA households together.
  • Integrate modeled state unemployment insurance into income flows #9558 (item 11). The guard's four tests pass at the head, and no Arkansas LIHEAP file reads raw unemployment_compensation.
  • Document disjoint health premium inputs and correct consumer treatment #10046 (item 14) and the wage lessons (OK Add Oklahoma state supplementation for 2026 #10165, NH Add New Hampshire state supplementation for 2026 #10156 round 3).
  • Federal 110% floor (42 U.S.C. 8624(b)(2)(B)).
  • IIJA and FY2027 (item 12).
    • IIJA. No supplement, as in round 1.
    • FY2027 sources. The AEO LIHEAP page lists no FY2027 chart or matrix on 2026-10-20, and the Clearinghouse returns 404 for an Arkansas FY2027 plan and matrix.
  • Arkansas SSP (item 17). Not applicable. main has 19 *_ssp variables and none for Arkansas, and SNAP's unearned list has no Arkansas entry.
  • Other main commits.
  • New and changed expectations, checked by hand. The FY2026 limits are 2,347 / 3,070 / 3,792 / 4,514 a month for sizes 1–4, and FY2025 size 2 is 2,944. I read matrix cells from the PR's parameter files, which round 1 compared cell by cell with the AEO PDFs and which are unchanged since.
    • ar_liheap.yaml:
      • Case 19 (changed): 48,000 × 0.8 = 38,400, MCI 3,200 > 2,347, so [false ×4] and [0 ×4]. The limit is 28,164.
      • Cases 17–18 (renamed people; 38_400): 0 against 36,840 gives 308, and 38,400 > 36,840 gives 0. Unchanged.
    • Household-size Case 2 (added output): size 0, so the limit is 0.
    • Eligibility Case 7 (new): 11,440 × 0.8 = 9,152; MCI 762.67 rounds to 763 (9,156). Gas row 730–789, column 1&2: 190. With the flag false: [true, false] and [190, 0].
    • Countable income:
      • Case 2 (changed): (15,000 + 3,000) × 0.8 + 1,200 = 15,600.
      • Case 23 (changed): (24,000 + 6,000) × 0.8 = 24,000.
      • Case 26 (inputs changed): 5,412; 3,000; 600 + 600 = 1,200; MCI 552.47 rounds to 552, or 6,624; 1,800.
      • Case 27 (new): (22,880 + 6,864) × 0.8 = 23,795.20; MCI 1,982.93 rounds to 1,983, or 23,796.
      • Case 28 (new): (24,000 + 6,000) × 0.8 = 24,000.
      • Cases 21, 22 and 24 (comments only): 19,200; 19,200; 18,300.
    • Limit Case 4 (new): (15,019 + 2 × 688) × 12 = 196,740.
    • Matrix Cases 16–18 (new), 26 FY2025 cells:
      • Electric, size 1 at 1,330, 1,450, 1,510, 1,570, 1,630, 1,690, 1,750, 1,870 and 1,990: 95, 88, 84, 80, 78, 74, 71, 66, 62.
      • Natural gas, size 5 at 1,390 to 1,750: 170, 156, 150, 143, 136, 128. Sizes 3 / 5 at 1,870, 1,990, 2,010 and 2,130: 110/121, 103/114, 96/107, 89/100.
      • Propane, size 1 at 1,990, 2,010 and 2,130: 102, 95, 88.
      • The FY2026 values in the comments also match (for example electric 94, 83, 77, 72, 66, 60 ×4).
      • Coverage. The parameter files still hold 63 changed cells (electric 11, natural gas 25, propane 12, fuel oil 11, other 4).
    • integration.yaml (new):
      • Case 1: SSI (994 − 580) × 12 = 4,968; 7,200 + 4,968 = 12,168 (MCI 1,014). Electric row 970–1029: 127.
      • Case 2: 22,880 × 0.8 + 2,400 = 20,704; MCI 1,725.33 rounds to 1,725, or 20,700. The limit is 45,504. Gas row 1690–1749, column 3&4: 124.
      • Case 3: the dependent student's 5,720 is excluded. (22,880 + 11,440) × 0.8 = 27,456 (MCI 2,288). The limit is 54,168. Propane row 2130–2347, column 3&4: 114. Counting the student gives MCI 2,669 and 106, as the comment says.
      • Case 4: 17,160 × 0.8 = 13,728 (MCI 1,144). Unsubsidized heat in rent qualifies with no bill. Gas row 1090–1149: 146.
      • Case 5 (2025): (18,000 − 2,220) + (9,600 − 2,220) + (3,600 − 2,400) = 24,360 (MCI 2,030). The limit is 35,328. FY2025 other row 2010–2129, column 1&2: 68.
  • Inputs not checked. I didn't re-derive these amounts; they are inputs only, and every expectation follows from them:
    • the $11.00 Arkansas minimum wage;
    • the $451 maximum weekly UI benefit;
    • the 30% VA rate of $552.47;
    • the 2026 SSI rate of $994;
    • the 2025 Part B premium of $185.
  • Wiring.
    • Registry. The programs.yaml entry is AR partial, with no verified_years and an updated note, and test_programs_registry passes.
    • Aggregates. No aggregate wiring, which matches every merged LIHEAP state.
    • Gating. defined_for = StateCode.AR is on five variables, and ar_liheap is gated by eligibility.
    • Changelog. changelog.d/ar-liheap.added.md is top level and typed added.
  • Partner tests. The PR touches none, and Household API Partners passes.

Checklist results (LIHEAP wave 2a)

  1. State plan and manual: pass. Matrix, limit and band values are unchanged since round 1. I read the adopted manual's pp. 52, 56, 58-59, 63-64, 141, 157, 159, 162-163 and 165 for the new rule and citations.
  2. Income definition: pass, with S7 open.
  3. Backdating: pass for the claimed years. Earlier years and 2027 are documented, unclaimed estimates (G4), and no FY2027 chart or matrix is published.
  4. Household and arrangement rules: pass. The explicit-false direct branch is now respected and pinned (eligibility Case 7). The other routes are unchanged and pinned.
  5. Tests: pass. 83 cases in 7 files, and every new or changed expectation was checked by hand. Periods are plain. The age edges 17/18, 18/19 and 23/24, and the limit at size 22, are covered.
  6. Descriptions: pass. All 21 follow the template; G14 has a wording nit.
  7. References: pass. The page lists follow CLAUDE.md. Don't split the full_time_student_age_limit entry (G14 note).
  8. Wiring: pass. Registry, no aggregate (as in the siblings), defined_for gating, and no take-up beyond tanf's.
  9. Axiom: valid queued line. Resolve US discrepancies against TAXSIM35 for 2021 #1538 matches the head (see below).
  10. Branch and CI: 29/29 green. A clean merge with main; the siblings conflict only in programs.yaml.
  11. Integrate modeled state unemployment insurance into income flows #9558: fixed. The guard passes.
  12. IIJA / FY2027: not applicable (no supplement). No FY2027 chart or matrix is posted.
  13. Mutation check: pass, except Pavel's G17 mutations.
  14. Document disjoint health premium inputs and correct consumer treatment #10046 health premiums: not applicable. Gross wages, and Part B netting only.
  15. State-gated index defaults: none new, and the mixed AR/GA case still runs.
  16. Wire military retirement pay and survivors into federal and state tax (#10181) #10182 survivor annuities: Suggestion 1.
  17. Merged state SSPs: not applicable. main has no Arkansas state supplement variable.
  • Federal 110% floor: never binds; no floor parameter is needed.

Axiom line assessment

Valid: axiom: TheAxiomFoundation/rulespec-us#1538 queued.

  • Issue state.
    • Resolve US discrepancies against TAXSIM35 for 2021 #1538 is open and labelled pe-parity and enhancement. It was last updated 2026-10-19 21:03 UTC and has no comments.
    • rulespec-us main (5796861e58, 2026-10-20) has no Arkansas LIHEAP module: us-ar/policies/ holds only cms, dhs and income_tax. So queued is still the right form.
    • It records its blockers: sources that need ingest, an unchecked signed release, billed-encoder approval and no reviewed PE revision.
  • Dispatch-ready. It has:
    • module paths with corpus status;
    • the verbatim plan, chart, matrix, manual and application text;
    • required outputs for all six variables;
    • companion tests 1–18, "none is taken from policyengine-us output", mapped to PE cases.
  • Matches the head f2a1172c0f:
    • Cases: 83 cases in 7 files, listed per file.
    • Countable income: a counted worker excludes dependent full-time college students aged 23 or younger and K-12 students aged 18 or younger, and the income includes total_unemployment_compensation.
    • Inputs: they include is_full_time_college_student, is_tax_unit_dependent and is_in_k12_school.
    • Companion tests 13, 15–18 match the new cases.
  • Updates it would need:
    • For S7: add is_in_secondary_school to the inputs and the counted-worker definition.
    • If the suggestions are taken: military_retirement_income, and interpretation 3(c) for dependent high-school students over 18.

CI status

29 pass, 0 pending, 0 failed (run 39324250200 on head f2a1172c0f, pull_request, 2026-10-19 21:02 UTC to 2026-10-20 02:35 UTC). I re-checked gh pr checks 9973 at the end of this review.

  • Quick Feedback ran all seven Arkansas LIHEAP files at the head: 19 + 2 + 7 + 28 + 4 + 5 + 18 = 83 passed.
  • Rest (Python, shard-1) passed:
  • Also passed: Household API Partners, Microsimulation, both Rest jobs, all 11 Baseline shards, all 9 Contrib shards, PR validation, Package and compatibility, and codecov patch and project.
  • Locally: no tests or probes were run. S7 and both suggestions are hand traces of the code.

Branch status

Next steps

  1. S7 (Pavel's, open): read is_in_secondary_school | is_in_k12_school for the 18-year-old high-school exclusion, and add the Case 24 variant.
  2. Optionally:
    • G14–G19, without splitting the full_time_student_age_limit reference;
    • Suggestion 1 (military_retirement_income);
    • Suggestion 2 (dependent high-school students aged 19–23).
  3. Refresh the PR body and rulespec-us#1538, then re-request review.

0 new critical and 0 new should findings, plus 2 new suggestions. Open at this head: 0 critical, 1 should (Pavel's S7, which I concur with) and 8 suggestions (Pavel's G14–G19 and Suggestions 1–2).

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.

Round 2: all four of our round-1 should-address items are fixed, and so are Pavel's C1, S5 and S6. One should-address item is still open: Pavel's S7 from today, which I agree with. The age-18 high-school exclusion reads only is_in_k12_school and ignores the is_in_secondary_school input, so Case 24 with the standard input gives $84 instead of $107. The fix is one expression and one test. Full report, including 8 suggestions, in the comment above.

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 Arkansas LIHEAP regular heating assistance

3 participants