Skip to content

Add New Mexico LIHEAP regular heating assistance - #10431

Open
hua7450 wants to merge 2 commits into
mainfrom
nm-liheap-wave1d
Open

hua7450 wants to merge 2 commits into
mainfrom
nm-liheap-wave1d

Conversation

@hua7450

@hua7450 hua7450 commented Oct 23, 2026 •

Copy link
Copy Markdown
Collaborator

Adds New Mexico LIHEAP regular heating assistance for FY2026 and FY2027, administered by the Health Care Authority (HCA). New Mexico pays one benefit per federal fiscal year, for heating or cooling, equal to the household's points times the point value ($35 in FY2026, $40 in FY2027). The model counts citizens and qualified noncitizens in household size, prorates an ineligible noncitizen's income by the share of eligible members, tests gross countable income against 150% of the poverty guideline, and scores energy burden (0-3 points, +2 for propane), income (3 points at or below 110% of the guideline, otherwise 2) and vulnerable members (+2 each for a child 5 or younger, a member 60 or older, a disabled member). Benefits range from $70 to $490 in FY2026 and $80 to $560 in FY2027.

Fixes #10421

Regulatory authority

Eligibility

Requirement Source How modeled
New Mexico residence 8.150.410.14 defined_for = StateCode.NM
At least one citizen or qualified noncitizen 8.150.410.13, .15 nm_liheap_household_size sums is_citizen_or_legal_immigrant
Income at or below 150% of the poverty guideline 8.150.100.9 D; plans 2.1; guides 12 x the monthly limit, rounded to the nearest dollar as printed (2025 guideline in FY2026, 2026 in FY2027)
Heating responsibility 8.150.410.9, .11 A heating bill, wood heat (bought or gathered), or heat in rent; subsidized tenants with heat in rent need an out-of-pocket heating cost; NONE ineligible, UNSPECIFIED only with heat in rent

Countable income

Item Source How modeled
Earned income 8.150.520.12 B Wages and net self-employment, each floored at zero, for members over 18
Unearned income 8.150.520.13; FY2026 plan 1.9 All members: gross Social Security (the Medicare premium stays in), SSI, pensions, retirement-account distributions (IRA, 401(k) and 403(b) withdrawals, retirement_distributions), military retirement, railroad, survivor, veterans, disability, workers' compensation, unemployment, general assistance, child support, alimony, interest, dividends, rental, estate and trust income, contributions from family or friends (financial_assistance)
TANF 8.150.520.13 Take-up-gated tanf (New Mexico Works)
Ineligible noncitizens 8.150.520.10 B Income x eligible members / all members
Not counted 8.150.520.8 B, .13 D Lump sums, loans, EITC, SNAP, in-kind and vendor payments

The FY2026 and FY2027 plans' section 1.9 checklists differ from the rule on four items (Social Security net of Medicare, one-time lump sums, cash gifts, an 18-year-old's earnings); the regulation is followed.

Benefit

Factor Points
Energy burden under 6% / 6-10.99% / 11-15.99% / 16% or more 0 / 1 / 2 / 3
Propane +2
Income at or below 110% of the guideline / above 3 / 2
Member 5 or younger; member 60 or older; disabled member (counted members, once each) +2 each
  • Energy burden = monthly heating bill / monthly countable income, with the bill floored at the energy standard allowance ($291 in FY2026, $298 in FY2027). Annual heating cost / 12 stands in for the highest monthly bill of the last 12 months. Cutoffs sit at the printed lower bounds (6%, 11%, 16%). Zero income scores 3 burden points.
  • Heat included in rent and wood the household does not buy earn no burden or propane points (8.150.620.9 A(3)).
  • Three income points at 110%: 8.150.620.9 B NMAC gives three points up to 100% of the guideline, while HCA's FFY2025-FFY2027 guides and the FFY2026 ISD 017 card use 110%; the model follows the guides HCA applies, and the choice is listed in the conflict register backlog (source_conflicts/candidates.yaml, us-nm:liheap-three-income-points).
  • Benefit = points x point value. No bill cap.

Not modeled

Item Source Treatment
Highest monthly bill in the last 12 months Application LHP 602 Annual heating cost / 12 with the allowance floor
30-day income and weekly x4 / biweekly x2 conversion 8.150.520.12 Annual income / 12
TANF-qualified noncitizen detail, SSN requirement 8.150.410.13, .15 is_citizen_or_legal_immigrant approximates
Tribal LIHEAP exclusion, benefit from another grantee 8.150.410.12; 8.150.110.8 D Not represented
Royalties, tribal benefits, real-estate contracts, legal settlements, foster-care funds, AmeriCorps 8.150.520.13; plan 1.9 No existing inputs
Nonrecurring lump-sum retirement-account withdrawals 8.150.520.13 D(3) retirement_distributions does not separate them, so every withdrawal counts as recurring income
Supplemental benefits at the secretary's direction; crisis; weatherization 8.150.110.8 E Out of scope

Heating and cooling share one annual benefit; the model returns it for households with a heating cost or eligible heat in rent. Earlier years are unverified estimates through parameter backfilling.

Microsimulation: heating_type and the per-fuel bills are not in current datasets; callers must supply them.

Test plan

46 YAML cases in 4 files (not re-run locally after the review fixes; CI validates them):

  • limits for sizes 1, 8 and 9 in FY2026 and sizes 8 and 9 in FY2027, size zero, and the exact-limit boundary;

  • countable income: noncitizen proration, an 18- and a 19-year-old, gross Social Security, SSI and contributions, TANF, child support versus capital gains, per-source floors, and IRA withdrawals that put a 68-year-old over the FY2026 limit;

  • every burden-point edge, the allowance floor, zero income, heat in rent, gathered and purchased wood, propane, the 110% income cutoff, each vulnerable group, the 2- and 14-point bounds in FY2026, and the FY2027 $298 allowance and $40 point value.

  • YAML tests with expected values from the rule, plans, guides and cards

  • ruff format

  • Changelog fragment in changelog.d/

  • CI passes

axiom: TheAxiomFoundation/rulespec-us#1892 queued

🤖 Generated with Claude Code

hua7450 and others added 2 commits October 23, 2026 18:11
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	policyengine_us/programs.yaml
@codecov

codecov Bot commented Oct 23, 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 (cb11d7d).
⚠️ Report is 631 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff            @@
##              main    #10431   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files            4         5    +1     
  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.

@DTrim99

DTrim99 commented Oct 26, 2026

Copy link
Copy Markdown
Collaborator

PR Review: Add New Mexico LIHEAP regular heating assistance

PR #10431 (author: hua7450), head cb11d7d132. This is a first review. The PR adds New Mexico's LIHEAP regular benefit (HCA, 8.150 NMAC) for FFY2026 and FFY2027: 15 parameters, 5 variables, 4 test files (46 cases), a programs.yaml entry (state list and coverage line), a source_conflicts/candidates.yaml backlog entry and a changelog fragment. The PR has no comments yet and touches no partner test file.

Path prefixes:

  • P/ = policyengine_us/parameters/gov/states/nm/hca/liheap/
  • V/ = policyengine_us/variables/gov/states/nm/hca/liheap/
  • T/ = policyengine_us/tests/policy/baseline/gov/states/nm/hca/liheap/

Sources read for this review:

Summary

What is right. The published FFY2026 and FFY2027 tables are encoded correctly:

There are no critical findings and four should-address items:

  • S1. Electricity never counts as an energy cost. Eligibility and the energy bill read only the primary heating fuel's bill. New Mexico pays one benefit for heating or cooling, and the household picks any one energy bill, electric included (LHP 602). So two kinds of household get $0 although 8.150.410.9 A–B, 410.11 B(2) and plan item 2.3 make them eligible: a home with no heating that pays an electric bill, and a subsidized tenant whose heat is in the rent but who pays the electric bill. Example: a subsidized tenant with $12,000 of wages and a $90 electric bill gets $0 at the head and $210 under the rule.
  • S2. The 3-point income cutoff follows guidance over the rule. The code uses the guides' 110% cutoff, but 8.150.620.9 B gives three points only up to 100% of the guideline. CONTRIBUTING's statute-first rule calls for the regulation, which is also the reading the PR itself takes for Medicare. The backlog entry says state: ruled with no ruling behind it and lists no PR. Example: $1,400 a month gets $210 at the head and $175 under the rule.
  • S3. Untested income sources. 18 of the 25 income-source entries never take a positive value in any test, and the unearned per-source floor is never exercised.
  • S4. Disability points read only is_disabled. 8.150.620.9 C(3) entitles a household to the points "when one or more members receive disability based income". An SSDI recipient without the flag gets $175 instead of $245.

There are also three suggestions: Item 17 (nm_ssi_state_supplement), recording the four plan-vs-rule income choices in the backlog, and the FY2025 backfill.

Status.

  • CI: 29 pass and 3 skipping, with none failed. All 46 New Mexico cases passed in states-shard-2.
  • Branch: 2 commits ahead of main and 39 behind. It merges cleanly.
  • Siblings: this PR adds NM to the LIHEAP coverage line, so it conflicts with most open LIHEAP siblings in programs.yaml only (branch note).

Critical (must fix)

None.

Should address

S1. Electricity never counts as an energy cost, so cooling-only households and subsidized heat-in-rent tenants who pay their own electric bill get $0

  • Where:
    • V/eligibility/nm_liheap_eligible.py:37 excludes NONE outright (fuel_qualifies).
    • Lines 46-47 accept a subsidized heat-in-rent household only if heating_expense > 0.
    • Line 51 accepts others only through has_heating_expense or wood.
    • heating_expense is "the fuel bill matching the household's primary heating type". pre_subsidy_electricity_expense therefore never counts unless electricity is the heating fuel.
    • V/nm_liheap.py:36, 43-44, 52-53 take the energy bill from heating_expense as well, and give no energy points with heat in rent.
  • Sources:
    • An energy cost may be a cooling cost. 8.150.410.9 A: "To be eligible for LIHEAP benefits, the household must incur an energy cost. ... The energy cost may be for a cooling cost." It counts secondary cooling, "the use of energy to operate portable fans, ceiling fans ...". 410.9 B: "Electricity to ignite a gas or steam furnace is the most common example of an allowable secondary heat source".
    • Subsidized tenants. 8.150.410.11 B(2): "Households receiving subsidized rent assistance who receive a subsidy for utilities but who incur an additional out-of-pocket expense for utilities are eligible for LIHEAP". FY2026 plan item 2.3 (p. 9): "Households that receive a utility subsidy but still have out-of-pocket utility costs (e.g., electricity, gas) are eligible for LIHEAP."
    • One benefit, one chosen bill. 8.150.110.8 D: "Each eligible household will be issued one benefit each federal fiscal year." LHP 602 asks "Do you need LIHEAP for: Heating or Cooling" (p. 2). It then says "Please choose one heating or cooling energy bill that you want help with", listing Electric among the bills, and asks for that bill's "highest monthly bill in the last 12 months" (p. 3).
    • Energy points need a direct cost. 8.150.620.9 A gives energy points "for households that have a direct cost for heating or cooling expenses".
  • Effect (hand-traced from the code, 2026, a single adult aged 40 with $12,000 of wages, $1,000 a month, and a $1,080 electric bill):
    • (a) Subsidized tenant, gas heat in the rent, pays the electric bill. Head: heating_expense is the gas bill, 0, so rent_responsible is false and the result is $0. Rule: eligible under B(2). The electric bill is a direct cost outside the rent, so max(90, 291) / 1,000 = 29.1% gives 3 energy points, plus 3 income points: 6 × $35 = $210. Even with the PR's no-energy-points reading for heat in rent, it is $105.
    • (b) No heating (NONE), pays electricity for cooling. Head: fuel_qualifies is false, so $0. Rule: eligible under 410.9 A, and the application's Cooling box gives the same 6 points, $210.
    • (c) Unsubsidized, gas heat in the rent, pays the electric bill. Head: eligible, but with no energy points, so 3 points and $105. Rule: the household picks its electric bill, so 6 points and $210.
  • What the PR says. The body and the Axiom issue (interpretations 11 and 13) scope this out: "the model returns it for households with a heating cost or eligible heat in rent". But New Mexico has no separate cooling component. nm_liheap is the state's whole regular benefit, so the scope line produces wrong $0 awards in the claimed years. The Arizona sibling (Add Arizona LIHEAP Standard benefit #10293, same wave) faces the same one-benefit design. Its az_liheap_energy_cost adds pre_subsidy_electricity_expense, and it keeps NONE eligible "because the benefit covers cooling".
  • Tests: eligibility Cases 3, 7, 8 and 11 have no electric bill, so they stay correct after a fix. No case sets an electric bill beside a non-electric heating fuel.
  • Severity: should. This is a wrong result in a claimed year with existing inputs, which the wave rates should (Add Rhode Island LIHEAP regular heating assistance #9972 S2).
  • Fix:
    • Add an energy-cost measure: the household's direct bills, meaning the heating fuel's bill when heat is not in the rent, plus pre_subsidy_electricity_expense.
    • Use any positive direct bill for responsibility, including B(2). Drop the NONE exclusion when an electric bill exists.
    • Score the burden from the larger direct bill (the household chooses one bill), floored at the allowance. Deny energy points only when no direct bill exists (all utilities in the rent) or for gathered wood. Give propane points only when the propane bill is the bill used.
    • Add cases (a)–(c), and update the body, the variable comments, the registry note and Axiom interpretations 11 and 13.

S2. The 3-point income cutoff follows the guides (110%) over 8.150.620.9 B (100%), and the backlog entry claims a ruling that has not been made

  • Where:
    • P/payment/income_points/low_income_fpg_rate.yaml:10 sets 1.1.
    • The comment at lines 2-5 says the regulation gives "three points up to 100% of the guideline" and that HCA's guides "use 110%, which is followed".
    • source_conflicts/candidates.yaml:4107-4136 (us-nm:liheap-three-income-points) has follows: unknown, prs: [] and state: ruled, with the note "PE-US follows the guides, which HCA applies".
  • Sources:
    • The regulation. 8.150.620.9 B: "(1) Three points - income is zero to one hundred percent of the FPG (2) Two points - income is one hundred to one hundred fifty percent of the FPG". Its example: "if the total monthly income is sixty percent of the FPG, the household will receive three income points."
    • The guidance. The FFY2026 guide's 3-point column ($1,435 for one person) and the FFY2027 guidelines ("Income at or below 110%: +3 pts") both use 110%. So does the FY2026 ISD 017 card ("110% FPG or Below, Receives 3 Points", p. 1).
    • The plans. Neither plan states an income-point cutoff; I searched both for it.
    • The secretary's power. 8.150.620.10 C lets the secretary adjust "the point value for energy cost points, income points, ... or any of their parts". The PR's own note reads that as not reaching the cutoff.
  • The project rule. CONTRIBUTING "Source conflicts" (2026-10-20) says: "When a statute conflicts with a form, instructions, a manual or stated agency practice, follow the statute", and "Regulations are law".
    • The backlog's own legend describes conflicting-source as "against the statute; the 2026-10-19 rule calls for a model change", and ruled as "PolicyEngine has picked".
    • Other ruled entries cite a project-lead ruling ("The October 2026 ruling ..."). This one cites none, and it is the only LIHEAP candidate marked ruled. The other entries also list their PR under prs.
    • The PR applies the rule elsewhere. It follows 8.150.520.13 B over plan item 1.9 for Medicare. The wave did the same in Oklahoma (Add Oklahoma LIHEAP regular heating assistance #9970 S2), where the OAC's gross test was followed over the same plan checkbox.
  • Effect (2026, a single adult aged 40 with $16,800 of wages, $1,400 a month or 107% of the guideline, and a $900 gas bill):
    • Head: 291 / 1,400 = 20.8% gives 3 energy points, and $1,400 ≤ $1,435 gives 3 income points: 6 × $35 = $210.
    • Rule: $1,400 is above 100% ($1,304.17), so 2 income points: 5 × $35 = $175.
    • Reach. Every household between 100% and 110% of the guideline: $35 in FFY2026 and $40 in FFY2027.
  • Severity: should. Authoritative sources conflict, and the PR's choice departs from the project's rule.
  • Fix: I recommend (a).
    • (a) Follow the regulation. Set low_income_fpg_rate to 1. The size-1 cutoff becomes round(15,650 / 12) = $1,304; the card's SNAP-rounded 100% column prints $1,305. Update Cases 11–12 and the comments. Record the guides' 110% as the other reading, and set the candidate to state: unreviewed with prs: [#10431].
    • (b) Keep 110%. Take the 8.150.620.10 C argument to the project lead. Until a ruling exists, set state: open, list the PR, and say in the body that the choice departs from the statute-first rule pending that ruling.
    • Either way, update Axiom interpretation 1.

S3. 18 of the 25 income-source entries, and the unearned per-source floor, have no test that would fail if they were dropped

  • Where: P/income/sources/earned.yaml (5 entries), P/income/sources/unearned.yaml (20 entries) and V/income/nm_liheap_countable_income.py:33.
  • Untested entries. No case gives these a positive value:
    • Earned: self_employment_income (only −$5,000 in countable Case 7, which floors to 0, so dropping the entry changes nothing), sstb_self_employment_income, farm_operations_income and partnership_s_corp_income.
    • Unearned: pension_income, military_retirement_income, railroad_benefits, survivor_benefits, veterans_benefits, disability_benefits, workers_compensation, total_unemployment_compensation, general_assistance, alimony_income, ordinary_dividend_income, rental_income, farm_rent_income and estate_income.
  • Tested entries: wages, Social Security, SSI, retirement distributions, child support, interest and financial_assistance, plus tanf.
  • The unearned floor. No case has a negative unearned source, such as a rental, farm-rent or estate loss, so removing max_ at line 33 fails nothing. That floor is what keeps a rental loss from offsetting wages (the wave's rental-loss item). The body's "per-source floors" claim rests on the earned floor alone.
  • Smaller point. Eligibility Cases 3 (NONE) and 4 (UNSPECIFIED, heat not in rent) pass without fuel_qualifies (line 37), because heating_expense is 0 for both, so has_heating_expense already fails. Only NONE with heat in the rent reaches that clause. S1's fix changes this logic anyway.
  • Severity: should, as in Add Virginia EAP Fuel Assistance (LIHEAP regular heating) #10303 S4 and Add Alabama LIHEAP regular heating assistance #9967 S3 (the mutation rule).
  • Fix: add one countable-income case that gives every listed source a distinct positive amount, including reported unemployment and military_retirement_pay_survivors. Add a case with wages and a rental loss that expects the wages alone. Re-pin self_employment_income with a positive profit.

S4. Disability points read only is_disabled, but receipt of disability-based income alone entitles the household

  • Where: V/nm_liheap.py:106, disabled = spm_unit.any(counted & person("is_disabled", period)). The comment at line 99 says "is_disabled stands in for disability-based income or a doctor's statement".
  • Sources:
    • The regulation. 8.150.620.9 C(3): "When one or more members receive disability based income, the household is entitled to the points. A doctor's statement of current disability will be required ... if the disabled member does not receive disability-based income."
    • FY2027 plan item 2.3 (p. 8): "Households automatically qualify for these points when a member receives disability-based income such as Social Security Disability Insurance (SSDI) or Supplemental Security Income (SSI)." The FY2026 plan (p. 10) says the same.
  • Effect (2026, age 45, $18,000 of social_security_disability, is_disabled unset, $900 gas bill):
    • Head: 291 / 1,500 = 19.4% gives 3 energy points and $1,500 > $1,435 gives 2 income points, for 5 points and $175.
    • Rule: SSDI is disability-based income, so +2: 7 points and $245.
    • Microsimulation. Benefit receipt and the survey disability flag do not fully overlap.
  • Severity: should, as in Add Oklahoma LIHEAP regular heating assistance #9970 S3 (Oklahoma's medical deduction read is_disabled instead of the benefit-receipt test the rule adopts). The Virginia sibling (Add Virginia EAP Fuel Assistance (LIHEAP regular heating) #10303) uses the broader test.
  • Fix:
    • Use is_disabled | (social_security_disability > 0) | ((ssi > 0 | receives_ssi) & is_ssi_disabled), as va_eap_disabled does. Do not use is_usda_disabled, which also counts aged SSI.
    • Add an SSDI case without is_disabled, and update Axiom interpretation 10.

Suggestions

G1. Count the New Mexico SSI state supplement (nm_ssi_state_supplement, checklist item 17).

  • What exists on main. main has nm_ssi_state_supplement ($100 a month for SSI recipients in adult residential care, 8.106.500 NMAC). It is in SNAP's unearned list and in household_state_benefits. The LIHEAP unearned list has ssi but not the supplement. The Axiom issue (interpretation 8) records that it is left out.
  • The rule counts it. 8.150.520.13 A counts entitlement and assistance payments, and plan item 1.9 checks SSI.
  • Example (hand trace, 2026). A resident aged 65 earns $700 a month and documents a heating cost, which 8.150.410.16 requires of facility residents. SSI is 994 − (700 − 20 − 65) / 2 = $686.50 a month.
    • Head: 8,400 + 8,238 = 16,638 a year, or $1,386.50 a month: 3 + 3 + 2 (age) = 8 points, $280.
    • With the supplement: +$1,200 gives $1,486.50 a month, which is above $1,435: 7 points, $245.
  • Why only a suggestion. Facility residents rarely have their own heating cost, and the wave rates this item a suggestion.
  • Fix: add nm_ssi_state_supplement beside ssi.

G2. Record the four plan-vs-rule income choices in the backlog.

  • The choices. The comment at P/income/sources/unearned.yaml and the body document four places where the PR follows 8.150.520 over plan item 1.9:
    • Social Security gross (the plan checks "Excluding MediCare deduction");
    • lump sums excluded;
    • cash contributions counted;
    • an 18-year-old's earnings excluded.
  • Why record them. These are the right choices under the statute-first rule. But CONTRIBUTING says every such conflict is recorded, and comparable LIHEAP choices are already on main as candidates: us-ok:liheap-medicare-premium-income-test, us-pa:liheap-railroad-retirement-medicare-premium, us-sd:liheap-cash-gifts and us-al:liheap-lump-sums-and-refunds.
  • Fix: add one or two us-nm:liheap-... candidates, with prs listing this PR.

G3. The FY2025 backfill (unclaimed and documented, as in NJ S3).

  • What carries back. All parameters start 2025-10-01, so period 2025 uses FFY2026 values on the 2024 guideline.
  • What matches. The FY2025 plan confirms 150% (item 2.1) and $70–$490, which is $35 a point (item 2.6).
  • What differs. The Axiom issue reports that the FFY2025 guide printed a $283 allowance and a size-1 limit of $1,882, against the model's $1,883. I could not retrieve that guide.
  • Fix: if 2025 is wanted, add 2024-10-01 entries from that guide. Otherwise keep the body note; the registry claims only 2026–2027.

Verified correct

Values against sources:

  • Income limit (8.150.100.9 D; plan 2.1, 150%, FY2026 p. 9 and FY2027 p. 8):
    • FFY2026 (2025 guideline, 15,650 + 5,500): 1,956, 2,644, 3,331, 4,019, 4,706, 5,394, 6,081 and 6,769 match the guide and the ISD 017 card.
    • FFY2027 (15,960 + 5,680): 1,995, 2,705, 3,415, 4,125, 4,835, 5,545, 6,255 and 6,965 match.
    • Sizes 9 and up. The guides print an "each +" increment: $688 against 687.5 in FFY2026, so size 9 is $7,457 by increment and $7,456 by rate. The PR follows plan 2.1's 150% and documents the $1 difference, which is consistent with the statute-first rule.
  • The lag. fpg_year_lag 1 matches IM 2025-02 Attachment 2 ("mandatory use in FY26 LIHEAP", p. 1).
  • Federal 110% floor. 12 × round(1.5g / 12) ≥ 1.5g − 6, far above 1.1g; for size 1, $23,472 against $17,215. The floor never binds.
  • Income-point cutoffs at 110%: 1,435 / 1,939 / 2,443 / 2,947 / 3,451 / 3,955 / 4,460 / 4,964 (FFY2026) and 1,463 / 1,984 / 2,504 / 3,025 / 3,546 / 4,066 / 4,587 / 5,108 (FFY2027) match the printed columns. The choice of 110% is S2.
  • Points:
    • burden bands 0 / 1 / 2 / 3 at 6%, 11% and 16% (8.150.620.9 A(1); plan p. 10; both guides);
    • +2 for propane (A(2));
    • none with utilities in the rent or for gathered wood (A(3));
    • the allowance $291 (FFY2026 guide; ISD 017 FY2026 p. 1) and $298 (FFY2027 guidelines; ISD 017 FY2027 p. 1);
    • income 3 / 2 (B);
    • +2 each for 60 or older, 5 or younger and disabled, once per group (C).
    • The lower-inclusive cutoffs and the zero-income top band are documented readings (Axiom interpretation 2).
  • Point value: $35 (FFY2026 guide; card; plan 2.6, $70–$490, p. 10) and $40 (FFY2027 guidelines; FY2027 plan 2.6, $80–$560, p. 9). The maximum is 3 + 2 + 3 + 6 = 14 points. There is no bill cap.
  • Eligibility:
    • no categorical eligibility (8.150.100.9 C; plan 1.4 "No", p. 5);
    • no assets test (8.150.510.8; plan 2.3);
    • at least one citizen or qualified noncitizen, with size counting only those members (8.150.410.13, .15);
    • gathered wood (410.9 C);
    • heat in unsubsidized rent (410.11 A(2));
    • subsidized B(1)–(5), apart from S1.
  • Countable income:
    • gross income before deductions (8.150.520.12);
    • earnings of members over 18, with an 18-year-old excluded (520.12 B);
    • unearned income of all members;
    • net self-employment, floored per source (520.9 C);
    • contributions from family or friends (520.13 C);
    • TANF once at the unit through the take-up-gated tanf, which includes nm_works;
    • noncitizen proration, income × eligible / all members (520.10 B).
    • Capital gains are not counted, and strike pay is not counted (plan box unchecked).
  • Social Security gross is correct here. 8.150.520.13 B: "In the case of OASDI benefits, the gross amount of the benefit includes the amount deducted for the medicare premium". Plan 1.9 checks "Excluding MediCare deduction" in both FY2026 (p. 6) and FY2027 (p. 6). The binding rule wins under the statute-first rule and the Oklahoma precedent, so this is not the wave's Medicare should item. Part A does not arise. Recording the choice is G2.
  • Documented limitations, accepted: the tribal-LIHEAP exclusion (8.150.410.12 A; no input for tribe or tribal administration), a benefit from another grantee, facility residents and homeless applicants, the highest-bill measure (annual / 12), the 30-day income window, lump-sum retirement withdrawals and supplemental benefits.

Hand-checked expectations (16). All are 2026 unless noted, at $35 a point, with the 291 allowance and the size-1 limit 1,956 / cutoff 1,435:

  • Eligibility Cases 1–2: 23,472 = 12 × 1,956 is eligible; 23,473 is not.
  • Income limit Cases 2–6: size 8, 54,150 × 0.125 = 6,768.75, so 6,769 × 12 = 81,228. Size 9 gives 7,456.25, so 89,472. 2027 size 8: 55,720 × 0.125 = 6,965, so 83,580. 2027 size 9: 61,400 × 0.125 = 7,675, so 92,100, which equals 6,965 + 710. Size 0 gives 0.
  • Countable Case 1: 24,960 + 18,000 × 2/3 = 36,960.
  • Countable Case 2: 24,960 + 6,000 + 200 = 31,160; the 18-year-old's $4,000 is excluded.
  • Countable Cases 3, 4 and 7: 24,000 (gross; the premium input is ignored), 11,928 + 1,200 = 13,128, and 24,960 + 0 + 300 = 25,260.
  • nm_liheap.yaml Case 1: 3,492 / 21,825 = 0.16 exactly (one division in float64) gives 3, plus 2 income: $175. Case 2 (21,826, 0.15999) gives $140.
  • Case 3 (size 3, propane $330 a month): 330 / 3,000 = 0.11 gives 2, propane +2, and 3,000 > 2,443 gives 2: $210. Case 4 (3,001) gives $175.
  • Cases 5–6 (size 6): 291 / 4,850 = 0.06 gives 1, and 4,850 > 3,955 gives 2: $105. 4,851 gives 0 and the minimum, $70.
  • Cases 7–10: zero income gives 3 + 3, $210. Propane with heat in rent gives 0 + 3, $105. Gathered wood gives $105. Bought wood gives max(50, 291) / 1,000 = 0.291, so 3 + 3, $210.
  • Cases 11–12: 17,220 / 12 = 1,435 gives 3 income points, $210; 1,435.08 gives 2, $175.
  • Cases 13–16: age 5 (size 2, 2,080 > 1,939) gives 2 + 2 + 2, $210. Ages 6 and 59 give $140. Age 60 gives 3 + 2 + 2, $245. Disabled with SSDI 18,000 gives 3 + 2 + 2, $245.
  • Case 17: size 1, the undocumented 65-year-old adds no age points: 3 + 2, $175.
  • Case 18 (size 4): 291 / 1,200 gives 3, propane +2, and 1,200 ≤ 2,947 gives 3. Vulnerable: children (once), 62 and disabled, 6. Total 14, $490.
  • Case 20 (2027): 3,576 / 22,350 = 0.16 gives 3, and 1,862.50 > 1,463 gives 2: 5 × $40 = $200.
  • Case 21: 14,400 + 10,000 taxable_ira_distributions (in retirement_distributions) = 24,400, above 23,472, so $0. Without the withdrawals, 3 + 3 + 2 = 8 points, $280, as the comment says.
  • Case count: 12 + 6 + 7 + 21 = 46, as the body says.

Batch checks:

Wiring and housekeeping:

  • Registry. The NM entry sits between NJ and NY, and NM is added to the coverage line. test_programs_registry passed.
  • Aggregates and take-up. There is no aggregate wiring, which matches every merged LIHEAP state. There is no take-up beyond tanf's.
  • Gating. defined_for = StateCode.NM is on 4 variables, and nm_liheap is gated by nm_liheap_eligible.
  • Changelog. changelog.d/nm-liheap-wave1d.added.md is top level and typed added.
  • Descriptions (item 6): all 15 end "under the Low Income Home Energy Assistance Program." with nothing after it, and the verbs match the wave 2b siblings.
  • References (item 7):
    • The plan anchors show their values: FY2026 pp. 5, 6, 9 and 10; FY2027 pp. 5, 8 and 9.
    • The guides are one-page files, and the cards cite p. 1.
    • Multi-page titles use the quoted #page 5-6 / #page 9-10 form, and variables use # PDF pages comments.

Checklist results (LIHEAP batch):

  1. State plan and manual: every published cell matches. The 110% choice is S2.
  2. Income definition: pass. Wages count gross, Social Security counts gross per 8.150.520.13 B, losses are floored per source, and income is annual / 12. The disability-income points are S4.
  3. Backdating: pass for 2026–2027. 2025 is a documented, unclaimed backfill (G3).
  4. Household and arrangement rules: cooling-only households and electric bills are S1. Every other branch is tested.
  5. Tests: 46 cases, 16 hand-checked, all periods plain. Source coverage is S3.
  6. Descriptions: pass.
  7. References: pass.
  8. Wiring: pass.
  9. Axiom: valid (Add CO TANF Pregnancy Allotment #1892).
  10. Branch and CI: a clean merge with main; 29 pass and 3 skipping.
  11. Integrate modeled state unemployment insurance into income flows #9558: pass (unpinned, S3).
  12. IIJA / FY2027: not applicable / FY2027 encoded.
  13. Mutation check: 18 source entries and the unearned floor are unpinned (S3).
  14. Document disjoint health premium inputs and correct consumer treatment #10046: not applicable.
  15. State-gated index defaults: safe.
  16. Wire military retirement pay and survivors into federal and state tax (#10181) #10182 / Count military SBP annuities in state benefit income lists #10317: pass.
  17. Merged state SSPs: nm_ssi_state_supplement is missing (G1).

Axiom line assessment

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

  • State: OPEN, labelled pe-parity, created 2026-10-23 22:16 UTC.
  • It matches the head. It names head cb11d7d132 and merge base 6a92d6a983. It lists the 15 parameters (5 earned and 20 unearned sources), the 5 variables and the 46 cases by file. Its required outputs (limit, countable income, eligibility, the four point factors and the benefit) describe the head's code.
  • It is dispatch-ready in the rulespec-us#1467 format:
    • proposed us-nm/ module paths, with corpus status per source;
    • verbatim text of 8.150.100, 110, 410, 510, 520 and 620, the plans' items (with box states read from page images), both guides, both cards and LHP 602;
    • 13 companion tests derived from the sources, not from PE output;
    • 14 interpretations, including the 110% conflict, cooling-only scope and the SSP omission;
    • its blockers: sources missing from the corpus, an unchecked signed release, billed-run approval and no reviewed oracle revision.
  • Note. Fixes for S1, S2 and S4 change interpretations 1, 10, 11 and 13 and the eligibility, energy-points and vulnerable-points outputs. Update the issue with the head that resolves them.

CI status

29 pass, 3 skipping, 0 failed. Run 40032562409 tested head cb11d7d132 (pull_request, started 2026-10-23 22:14 UTC, after #10287 and the 2026-10-21 cutoff). The three skipping entries are the parent workflows of an earlier run, 40032348799, that did not execute. I re-checked gh pr checks 10431 at the end of this review.

  • New Mexico tests. States-shard-2, batch 9/14 (states/nm), ran all 4 files: 12 + 6 + 7 + 21 = 46 passed.
  • Guards (Rest shard-1):
    • the four test_unemployment_compensation_readers.py tests;
    • the four test_military_retirement_readers.py tests;
    • the test_source_conflicts.py tests, including the ratchet and the three candidate checks;
    • test_members_are_state_gated;
    • test_programs_registry.
  • Also passing: Microsimulation, Household API Partners, PR validation, Package and compatibility, Quick Feedback, codecov, and every baseline and contrib shard.
  • Known main-caused failure: not applicable.
  • Locally: I ran no tests or model probes. The S1–S4 and G1 examples are hand traces of the code at the head. The only local script was the static comment-pattern scan above.

Branch status

0 critical, 4 should and 3 suggestions are open at this head.

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.

Every FFY2026/27 limit, cutoff, point band, allowance and point value matches the guides, ISD 017 and the plans, and Social Security counts gross per 8.150.520.13 B. All 16 expectations hand-check, the guards pass on the merged tree, and rulespec-us#1892 is valid. Four should-address items: (1) electricity never counts as an energy cost, so cooling-only households and subsidized tenants who pay the electric bill get $0 (8.150.410.9 A; $0 vs $210); (2) the 3-point cutoff follows the guides' 110% over 8.150.620.9 B's 100%, against statute-first, and the candidate is marked 'ruled' with no ruling; (3) 18 of 25 income sources are never positive in a test; (4) disability points read only is_disabled, though SSDI or disabled SSI alone qualifies under 620.9 C(3). Three suggestions. Full report 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 New Mexico LIHEAP regular heating assistance

2 participants