Repository navigation
Add Indiana EAP regular heating assistance - #9728
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #9728 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 4 6 +2
Lines 76 115 +39
Branches 2 1 -1
=========================================
+ Hits 76 115 +39
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
…tilities in rent - Count farm, partnership and S corporation, estate, farm rental, strike and military retirement income (manual section 6.1) - Give kerosene no bulk-fuel points (manual sections 1.1 and 8.5) and give other fuels the bulk-fuel points - Treat all utilities in rent as heat in rent as well as electricity in rent - Floor each income source at zero per person - Replace hardcoded month and quarter literals; add income/calculation_months - Add metadata.period to parameters - Add tests for the new sources, fuel points, the single tenant flag, per-source floors and raw-input integration households; send heating_type explicitly in every eligibility or payment case Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Replace the deprecated dividend_income alias. Results are unchanged because the alias only adds ordinary_dividend_income. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Program ReviewPR #9728: Add Indiana EAP regular heating assistance (author: hua7450, head Scope: Indiana LIHEAP, which Indiana runs as the Energy Assistance Program (EAP) through IHCDA. The PR covers the regular heating benefit and the winter electric allowance. Crisis, cooling, weatherization and repair are out of scope. It changes 32 files: 20 parameters, 6 variables, 4 test files (34 cases), a changelog fragment and Path prefixes used below:
Source Documents
The PY2025 manual is not retrievable (404), and no PY2027 manual has been posted. Branch Status
Critical (Must Fix)C1. Periods before 2025-10-01 backfill the FY2026 schedule, which contradicts the official PY2024-25 benefit matrixEach of these parameters has a single
Other places that depend on the backfill:
Sources:
How this was verified:
Impact in period 2025 for a one-person household in a single-family home that pays both bills:
Fix:
C2. 23 of 26
|
| File:line | Anchor | Page that opens | Where the cited value is |
|---|---|---|---|
P/benefit/fuel_points.yaml:37 |
10,71 |
p. 10 (Section 1.1, which has only the kerosene bar) | Manual 8.5, p. 71 (fuel table) |
P/benefit/income/middle_points.yaml:10 |
69,70 |
p. 69 | Manual 8.3, p. 70 (5-point chart) |
P/benefit/income/middle_rate.yaml:10 |
69,70 |
p. 69 | Manual 8.3, p. 70 (30-45% chart) |
P/benefit/income/higher_points.yaml:10 |
69,70 |
p. 69 (only the heat-in-rent rule) | Manual 8.3, p. 70 (2-point chart), plus p. 69 |
P/benefit/vulnerability/points.yaml:10 |
71,72 |
p. 71 (the 8.6 heading) | Manual 8.6, p. 72 ("Award two (2) points") |
V/in_eap.py:15 |
15-page list | p. 10 | Manual 8.11, p. 77 (benefit formula) |
The other 17 comma lists happen to open a usable first page, but they are still invalid and should be split. Recommended single pages:
| File:line | Current | Recommended |
|---|---|---|
P/benefit/dwelling_points.yaml:16 |
70,71 |
#page=71 |
P/benefit/electricity/lower_income.yaml:10 |
72,73 |
#page=72 |
P/benefit/electricity/middle_income.yaml:10 |
72,73 |
#page=72 |
P/benefit/electricity/higher_income.yaml:10 |
72,73 |
#page=72 and #page=73 |
P/benefit/income/lower_points.yaml:10 |
69,70 |
#page=69 |
P/benefit/income/lower_rate.yaml:10 |
69,70 |
#page=69 |
P/benefit/vulnerability/elderly_age.yaml:10 |
26,27,71,72 |
#page=26 and #page=27 |
P/benefit/vulnerability/young_child_age_limit.yaml:10 |
26,71,72 |
#page=26 and #page=27 |
P/eligibility/adult_age.yaml:10 |
47,57,58 |
#page=47, plus #page=29 (see G4) |
P/eligibility/income_limit.yaml:10 |
23,69,70 |
#page=23 |
P/income/calculation_months.yaml:10 |
47,69 |
#page=47 |
P/income/sources.yaml:36 |
47-61 |
separate #page=49, 51, 52, 53, 54, 55, 56 |
V/in_eap_dwelling_type.py:23 |
70,71 |
#page=70 |
V/in_eap_eligible.py:10 |
23,29,... |
#page=23 and #page=29 |
V/in_eap_household_size.py:10 |
23,24,25,29,30 |
#page=23, #page=24 and #page=29 |
V/in_eap_income.py:11 |
47-61 |
split by topic, as for sources.yaml |
V/in_eap_smi.py:12 |
69,70,72,73 |
#page=69 |
Three anchors are already correct: P/benefit/amount_per_point.yaml:10 (#page=77), P/eligibility/minimum_monthly_rent.yaml:10 (#page=32) and P/income/student_age_limit.yaml:10 (#page=58).
Fix: give each page its own - title: / href: entry, and put the manual section number in the title.
Should Address
S1. SSA netting uses the raw reported Part B input instead of the model's computed premium
- Where:
V/in_eap_income.py:40-47. The comment at lines 40-41 says "Only reported Part B premiums are available." - Sources:
- Manual 6.1, p. 55: "The net amount of the Social Security check, after the deduction for Medicare Part B premiums and/or Part D ... is to be used to compute income."
- FFY2026 plan, p. 6 counts Social Security "Excluding MediCare deduction".
- What the code does now:
medicare_part_b_premiums_reportedis a bare input that defaults to 0, and nothing else invariables/reads it. - Why the comment is inaccurate: the model already computes
medicare_part_b_premium(policyengine_us/variables/gov/hhs/medicare/eligibility/part_b/medicare_part_b_premium.py). That variable is the out-of-pocket premium, including IRMAA and net of Medicare Savings Program coverage. It has no dependency onin_eap. - Bias: unless the premium is entered by hand, countable income for each Medicare-enrolled Social Security recipient is overstated by the full premium. At the 2026 standard premium that is $202.90 a month, or $2,434.80 a year, and more with IRMAA. Eligibility and band placement are therefore biased downward.
- The elderly-widow integration case passes only because it hand-enters 2,434.80.
- Fix:
- Read
medicare_part_b_premiumand keep the per-person floor againstsocial_security. - Keep the hand-entered case only as an override test, if at all.
- Add a case where the premium exceeds the benefit, to exercise the floor at
V/in_eap_income.py:43-47.
- Read
S2. survivor_benefits is missing from the countable income sources
- Where:
P/income/sources.yaml:4-29. - Sources:
- Manual 6.1, p. 54: "Life insurance payments issued on a regular basis to a surviving household member should be counted as income." The same page says retirement funds are "also available ... to their surviving spouse and surviving minor children".
- Manual, p. 53 counts the Black Lung survivor benefit.
- FFY2026 plan, p. 6 checks "Retirement / pension benefits" and "Insurance payments made directly to the insured".
- Gap:
survivor_benefits("Survivor benefits other than Social Security survivor benefits") is a separate input frompension_income. The federal TANF source list and several state lists already count it. - Bias: survivors' countable income is understated by the full annual survivor benefit, which biases eligibility and points upward for those households.
- Fix: add
survivor_benefits. Check that it does not double-count withmilitary_retirement_pay, whose documentation says it includes survivor benefits.
S3. Reading receives_ssi for a YEAR period returns only December
- Where:
V/in_eap.py:69. - Cause:
receives_ssiis a MONTH boolean. policyengine-core treats booleans as stocks, so a YEAR request returns the last month. - Effect: a reported SSI recipient whose receipt ends before December loses the disability proxy for vulnerability points. The
ssi > 0term on line 68 sums over the year and is unaffected. - Source: Manual 3.4, p. 26 (the disability benefits that qualify a household as vulnerable).
- Bias: downward, by at most 2 points ($50), and only for households with no other vulnerability factor.
- Fix: use
add(person, period, ["receives_ssi"]) > 0, as inpolicyengine_us/variables/gov/hhs/medicaid/eligibility/categories/is_ssi_recipient_for_medicaid.py:30.
S4. 21 test cases write the period as 2_026 or 2_022
- Where:
T/in_eap.yaml:2,21,40,59,84,102,123,140,157T/in_eap_eligible.yaml:2,18,34,49T/in_eap_income.yaml:2,18,37,56T/integration.yaml:2,20,60,78
- The other 13 cases in these files use
period: 2026, and no other test file in the repo uses an underscored period. - The format parses today only because PyYAML follows YAML 1.1, which allows digit separators. The YAML 1.2 core schema does not.
- Source: repository test convention; there is no regulatory page.
- Fix: write
period: 2026. The2_022case at line 78 is replaced under C1.
S5. Parameter descriptions depart from the template
P/income/sources.yaml:1joins two clauses with a semicolon and includes an implementation note ("Social Security and SSI are handled separately because benefits paid for children also count"). It also does not end with "under the Energy Assistance Program."- Suggested wording: "Indiana uses these income sources to compute countable income for adult members who are not exempt students under the Energy Assistance Program."
- Move the Social Security and SSI note into a YAML comment or the variable.
- 15 of the 20 descriptions use verbs outside the standard list (limits, provides, sets, excludes, deducts, uses):
- "pays":
P/benefit/amount_per_point.yaml:1andP/benefit/electricity/{lower,middle,higher}_income.yaml:1. Use "provides". - "awards":
P/benefit/dwelling_points.yaml:1,P/benefit/fuel_points.yaml:1,P/benefit/income/{lower,middle,higher}_points.yaml:1andP/benefit/vulnerability/points.yaml:1. Use "provides". - "awards ... beginning at / through this age":
P/benefit/vulnerability/elderly_age.yaml:1andP/benefit/vulnerability/young_child_age_limit.yaml:1. Use "sets". - "counts":
P/eligibility/adult_age.yaml:1andP/income/sources.yaml:1. - "requires":
P/eligibility/minimum_monthly_rent.yaml:1. Use "sets".
- "pays":
- Source: repository parameter-description convention; there is no regulatory page.
S6. Missing edge-case tests
Coverage is otherwise strong. The tests check both band boundaries for sizes 1-10, the 60% limit for sizes 1-11, all 11 fuel types and all 3 dwelling types. They also check the vulnerability ages at 59/60 and 5/6, the $12-a-year rent boundary, the maximum and the floor paths, and nine integration cases. These cases are missing:
- (a) Bands above size 10. At size 11 only eligibility is tested (
T/in_eap_eligible.yaml:33-47). Source: Manual 8.3, p. 69 (the method for larger households). At size 11:- SMI = floor(107,555 × 1.47) = 158,105.
- Band 1 three-month ceiling = 11,857. Annual income of 47,428 should give $450, and 47,432 should give $325.
- Band 2 three-month ceiling = 17,786. Annual income of 71,144 should give $325, and 71,148 should give $200.
- (b) Disability proxies (
V/in_eap.py:67-72). Source: Manual 3.4, p. 26.social_security_disability > 0on its own is never tested.receives_ssi: trueon its own is never tested.- There is no negative case. With
is_disabled: truebut no Medicaid, SSI or SSDI, the propane band-1 household atT/in_eap.yaml:101should get $575, not $625.
- (c) Heat in rent, electricity billed separately, rent below $12 a year (
V/in_eap.py:47-49, 93). The expected result is no heating award and only the electric payment, for example $125 in band 1. Source: Manual 4.7, p. 32.
Suggestions
G1. Default inputs bias simulated in_eap, and some fuel mappings have no source
The table gives each default's bias direction and size; no particular values are prescribed.
| Input (default) | Effect | Bias |
|---|---|---|
heating_type (UNSPECIFIED) |
fuel_points = 0 (P/benefit/fuel_points.yaml:3), so heating_burden is false (V/in_eap.py:47-49). Households without heat in rent get no heating award |
Downward, by the whole heating component ($50-$500) |
pre_subsidy_electricity_expense (0) |
No electric payment unless a bill is supplied | Downward, $50-$125 |
heat_expense_included_in_rent (false), tenant_pays_utilities (true) |
Renters whose utilities are included in rent go down the bill-based path with no bill | Downward, up to the $100 in-rent award ($50 in points plus $50 electric) |
in_eap_dwelling_type (SINGLE_FAMILY, V/in_eap_dwelling_type.py:14) |
Apartments and mobile homes get the maximum 3 dwelling points | Upward, at most $50, and only where a heating award is paid |
- The local policyengine-us-data and populace checkouts have no imputation of
heating_typeorheat_expense_included_in_rent. Simulatedin_eapwill therefore be close to $0 or electric-only. Consider saying so in theprograms.yamlnotes and thein_eapdocumentation. - Fuel mappings with no printed matrix value:
- KEROSENE = 0 is supported by Manual 1.1, p. 10.
- OTHER = 6 is inferred from the bulk-fuel list on Manual 8.5, p. 71.
- SOLAR = 0 has no source. It denies the heating award to solar-primary homes, which
heating_expensemodels as grid-tied with electric backup. Document the assumption.
G2. Business, farm and rental income are counted net, but the manual specifies gross
- Where:
V/in_eap_income.py:27-35documents the gap. No gross input exists. - Source: Manual 6.1, p. 51 ("gross income and profits before allowable business expenses") and p. 52 (Schedule C line 5, Schedule E line 3, Schedule F line 9).
- Bias: countable income is understated, which biases eligibility and points upward. Acceptable as documented.
G3. retirement_distributions includes lump-sum and principal withdrawals
- Where:
P/income/sources.yaml:19. - Source: Manual, p. 55 and p. 59 exclude lump-sum pension or retirement payments of contributions and interest. p. 54 says principal "is never considered as income".
- Bias: countable income is overstated, which biases eligibility downward. A comment in the file would help.
G4. eligibility/adult_age does two jobs but its description covers one
P/eligibility/adult_age.yaml:1,10is the income-counting age, cited to p. 47.V/in_eap_eligible.py:22also uses it as the applicant-age test, which is not cited: Manual 4.4, p. 29 ("An applicant must only be eighteen (18) to apply").- Fix: split it into two parameters, or widen the description and add a
#page=29reference.
G5. is_in_k12_school is redundant
- Where:
V/in_eap_income.py:20. - The variable is an age 5-17 imputation, so it is never true for the members aged 18 and over that this test applies to.
- Source: Manual 6.2, p. 57.
G6. In-rent amounts share parameters with the band 3 amounts
P/benefit/income/higher_points.yaml:3(used atV/in_eap.py:53,57) holds both the band 3 points and the heat-in-rent points.P/benefit/electricity/higher_income.yaml:3(used atV/in_eap.py:98,102) holds both the band 3 electric amount and the electricity-in-rent amount.- The heat-in-rent zeros for dwelling and fuel points are literals at
V/in_eap.py:61-62. - The sources print the in-rent values as separate rows: FFY2026 matrix, p. 1, Manual 8.3, p. 69 and Manual 8.7, p. 72. A single parameter cannot represent a year in which the two values differ.
- Consider separate parameters, such as
benefit/income/heat_in_rent_pointsandbenefit/electricity/in_rent.
G7. Draft and cross-PR wording in comments
V/in_eap_smi.py:20-21compares the code with Mississippi's truncation order. That refers toms_liheap, which exists only in open PR Add Mississippi LIHEAP regular heating assistance #9727 and not onmain. Keep the Indiana-only explanation in lines 17-19. Source: Manual 8.3, p. 69.V/in_eap_income.py:33-34says "no new gross inputs ... are introduced in this project". "Are not modeled" is clearer.
G8. A test comment cites the wrong section
T/integration.yaml:173cites "Section 6.2 (page 55)" for the rule that Social Security is counted net of Part B.- The page is right, but the rule is in Section 6.1 (Manual, p. 55). Section 6.2 starts on p. 57.
G9. PR body anchors
- State plan
#page=9,10,11: use#page=8and#page=9. - Matrix
#page=1,2: use#page=1, plus a separate#page=2if the instructions are cited. - Manual: split the 33-page anchor list into single-page links.
G10. Cite the FY2026 matrix as a corroborating reference
- Add FFY2026 matrix, p. 1 to the income-points, electricity, dwelling, fuel and vulnerability parameters. It prints all of them on one page and is what intake workers use.
- Thirteen parameter reference titles also lack a manual section number.
G11. Roommates in the household unit
- Manual 3.2, p. 23 counts roommates as household members "even if they are not related". SPM units separate unrelated roommates.
- The approximation note at
V/in_eap_household_size.py:13-17does not mention roommates. Consider naming them. The bias direction is ambiguous.
G12. spm_unit.any on the citizenship flag
V/in_eap_eligible.py:21can useadd(spm_unit, period, ["is_citizen_or_legal_immigrant"]) > 0, following the repository pattern.- The age comparison on line 22 and the vulnerability test at
V/in_eap.py:73do needspm_unit.any. - Source: Manual 4.4, p. 29.
G13. programs.yaml merge conflicts and ordering
- Where:
policyengine_us/programs.yaml:805, 826-833. - The entry has all 8 fields, and
verified_years: "2026"follows single-year precedent. - Conflicts:
- Add Kansas LIEAP regular heating assistance #9663, Add Kentucky LIHEAP regular heating assistance #9725, Add North Carolina LIEAP regular heating assistance #9726 and Add Mississippi LIHEAP regular heating assistance #9727 edit the same coverage line (L805) and insert at the same anchor after IL (L825).
- Add Nebraska LIHEAP regular heating assistance #9723 appends after TX.
- Whichever of these PRs merges second or later will need a rebase.
- The coverage-line order also differs between the PRs. Agreeing on one order (for example
IL, IN, KS, KY, MS, NC, NE, TX) for both the coverage line and the implementation list would make each rebase a mechanical merge. - Source: Manual 8.11, p. 77 (the regular benefit scope the registry entry describes).
G14. A shared dwelling-type input across the sibling PRs
V/in_eap_dwelling_type.py:4-14adds a state-specific enum. Add Kansas LIEAP regular heating assistance #9663 addsks_liheap_dwelling_typeand Add Nebraska LIHEAP regular heating assistance #9723 addsne_liheap_dwelling_type.- A shared household-level structure-type input, with state enums derived from it, would let microdata populate it once. It would also reduce the SINGLE_FAMILY default bias in G1.
- This is a cross-PR change and does not block this PR.
- Source: Manual 8.4, p. 70.
G15. Changelog wording
- The fragment
changelog.d/in-eap.added.md:1is valid. - Its text describes internals ("with remaining income and administrative gaps documented"). A user-facing line reads better, for example: "Added Indiana Energy Assistance Program (EAP) regular heating assistance and the winter electric allowance."
- Source: Manual 8.11, p. 77.
PDF Audit Summary
| Check | Result |
|---|---|
| FY2026 values (2025-10-01) | 31 scalar entries in 19 files. 26 have a printed source value, and all 26 match the manual and the FFY2026 matrix, p. 1. The other 5 are fuel mappings with no printed value (G1) |
| FY2026 SMI thresholds | 90 of 90 manual cells reproduced (pp. 69-70, 72-73). The size-11 limit of $94,863 follows 45 CFR 96.85 |
| PY2024-25 SMI thresholds | 48 of 48 PY2024-25 matrix cells reproduced |
| Values backfilled to 2025-01-01, checked against the PY2024-25 matrix and FFY2025 plan | 22 comparable entries: 16 match and 6 do not (C1) |
| Mismatches that survive the code-path trace and the 600-dpi re-render | 6, all in C1 |
| FY2026 mismatches | None |
| Income sources list | 22 entries, all countable under manual Section 6.1 and FFY2026 plan pp. 5-7. One omission (S2) and two caveats (G2, G3) |
#page= anchors |
3 of 26 valid. 23 are comma lists, and 6 of those open the wrong page (C2) |
The sources also disagree with each other in places. None of these produces a finding against the PR:
- FFY2026 plan, p. 9 gives the electric benefit as "$50-$100". The manual (p. 72, p. 77) and the FFY2026 matrix pay $125 in band 1, and the PY2027 draft, p. 9 corrects the range to "$50-$125". The PR's $125 is correct.
- The FFY2025 plan, p. 9 lists a $675 maximum, but the PY2024-25 matrix arithmetic gives $525.
- In 28 of the 30 FY2026 cells, the manual's 12-month column is not 4 times its 3-month column. The 12-month cell is floor(SMI × r) and the 3-month cell is floor(SMI × r / 4).
- Some manual text is stale:
- Section 8.3 says "Points range from 2-6" (p. 69), a holdover from PY2025. The chart, Section 8.11 and the FFY2026 matrix all give 9/5/2.
- The Section 8.3 SMI link points to IM 2022-04, but the printed FY2026 four-person SMI of $107,555 matches
gov.hhs.smi.amountfor Indiana on 2025-10-01.
Validation Summary
| Check | Result |
|---|---|
| CI | 37/37 pass |
| Head moved since review | No (c9febf1930) |
| Hard-coded values | None. Formulas use only 0 and MONTHS_IN_YEAR |
| Naming and duplicates | Pass. All names follow in_eap_*, and the shared hhs_smi.smi() helper is reused |
| Aggregation | Pass. The per-source loop must floor each source, so adds cannot be used there |
| Periods | One formula issue (S3) and one test-format issue (S4) |
| Entity levels | Pass |
| Vectorization and microsim safety | Pass. Every HeatingType and dwelling key exists in its enum, and in_eap_smi guards household size 0 |
defined_for |
Pass: in_eap → in_eap_eligible → StateCode.IN |
| References | C2 (anchors), G9 (PR body), G10 (corroboration) |
| Parameter descriptions | S5 |
| Changelog | Valid top-level fragment changelog.d/in-eap.added.md |
| TODO/FIXME | None |
| Test coverage | 34 cases in 4 files. 8 hand calculations match: band 1 and band 2 boundaries for sizes 1-10, 60% limits for sizes 1-10, size 11, a two-earner household of 3, an elderly widow, a disabled worker, and vulnerability counted once. Gaps are listed in S6 |
programs.yaml |
Entry complete. Conflict risk with 5 sibling PRs (G13) |
| Axiom parity line | Present: n/a: rulespec-us does not have this program yet; it should be added as a follow-up. |
Review Severity: REQUEST_CHANGES
2 critical and 6 should-address findings. There are also 15 suggestions.
Next Steps
- C1: add
2024-10-01PY2024-25 entries to the six income-point, electric and fuel-point parameters. Replace the 2022 integration case with a 2025 case against the PY2024-25 matrix, and update the backfill comments. - C2: split every comma-list
#page=anchor into single-pagetitle/hrefentries, fix the six wrong pages, and add section numbers to the titles. - S1-S3: net Social Security using
medicare_part_b_premium, addsurvivor_benefitsto the sources, and readreceives_ssithroughadd(...) > 0. - S4-S5: change the test periods to
2026, and align the parameter descriptions with the template. - S6: add the size-11 band, disability-proxy (including a negative case), heat-in-rent with rent under $12, and Part B floor tests.
- Rebase on
main, coordinate theprograms.yamlordering with Add Kansas LIEAP regular heating assistance #9663, Add Nebraska LIHEAP regular heating assistance #9723, Add Kentucky LIHEAP regular heating assistance #9725, Add North Carolina LIEAP regular heating assistance #9726 and Add Mississippi LIHEAP regular heating assistance #9727, and re-run CI.
DTrim99
left a comment
There was a problem hiding this comment.
Requesting changes per the program review above (#9728 (comment)): 1 critical (each benefit parameter has a single 2025-10-01 entry, so the PY2024-25 period backfills FY2026 values that contradict the official PY2024-25 matrix: income points 9/5 vs 6/4, electric $125/$100 vs $100/$75, fuel points 1 vs 0), plus the should-address items in the report. Run /fix-pr 9728 or address the list.
Add the PY2024-25 values for the income points, electric payments and fuel points that differ from FY2026, and list the fuels that receive the heating award in a parameter so natural gas and electric households are paid in FY2025. Count survivor benefits, drop military retirement pay as a separate source, and count Social Security gross with the Medicare premium deduction left as a documented gap. Use single-page references with section numbers, fix test periods and names, rewrite descriptions, and add size-11, disability, heat-in-rent and FY2025 cases. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
Thanks for the review. Fixes are in Critical
Should-address
Suggestions
|
Program Review — Round 2PR #9728: Add Indiana EAP regular heating assistance (author: hua7450). This round reviews head Path prefixes used below:
Status of Round-1 Findings
Suggestions the author reports as taken, each verified at the new head:
G6 and G14 were not taken. Both were optional, and no change is requested. Value Verification (delta)PY2024-25 values were checked against the PY2024-25 matrix, p. 1 and its instructions, p. 2 (revised 2024-07-24). FY2026 values were checked against the FFY2026 matrix, p. 1 (revised 2025-08-05) and Manual pp. 69-73 and 77. Both matrices were read from the page images.
FY2025 state median income, size 1: floor($103,324 × 0.52) = $53,728. The three-month ceilings are floor($53,728 × 0.075) = $4,029 and floor($53,728 × 0.1125) = $6,044, both matching matrix p. 1. Hand checks of the new and changed tests:
Critical (Must Fix)None. Should Address (remaining)S1. Social Security is counted gross, contrary to Section 6.1, and the reported-premium netting has been removed
Suggestions
Branch and Axiom Status
CI Status35 of 37 checks pass. The two failures are both runner kills unrelated to this PR.
Review Severity: REQUEST_CHANGESThere are 0 critical findings, 1 remaining should-address finding (S1) and 3 suggestions.
|
DTrim99
left a comment
There was a problem hiding this comment.
Round 2 (#9728 (comment)): the critical PY2024-25 backfill and the other should items are resolved. One item remains: Social Security is now counted gross, but Manual 6.1 (p. 55) and the FFY2026 plan (p. 6) use the net check after the Medicare Part B/D deduction. The fix commit removed the reported-premium netting instead of switching to the existing medicare_part_b_premium variable.
…itary retirement pay Manual Section 6.1 counts the Social Security check net of the Medicare Part B premium, so the premium the person pays, from the existing medicare_part_b_premium variable, is subtracted; there is no Part D premium variable. military_retirement_pay is a separate input from the pension inputs that pension_income adds, so it is listed beside pension_income. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…into in-eap # Conflicts: # policyengine_us/programs.yaml
|
Thanks for round 2. Head is now S1, Social Security and the Medicare premium. Fixed with your first option. Suggestion 2, military retirement pay. You are right that Suggestion 3. The companion test pointer in rulespec-us#1468 now reads Suggestion 1. Not taken in this round. Tests were not run locally; CI runs them. |
Program Review — Round 3PR #9728: Add Indiana EAP regular heating assistance (hua7450). This round reviews head Path prefixes (same as earlier rounds):
Scope at this head: 33 files: 21 parameters, 6 variables, 4 test files with 39 cases ( Status of Round-2 Findings
Verification of the Medicare FixYears. The deduction is unconditional, so it applies in period 2025 (FFY2025) and period 2026 (FFY2026). Both plans support that, read from the page images:
No PY2025 manual was found (the analogous IHCDA Variable.
Part D. Section 6.1 names "Part B premiums and/or Part D". Plan-specific Part D premiums have no model variable. The model does have Hand checks (2026 standard premium $202.90 × 12 = $2,434.80; 2026 MSP limit 1.35 × $15,960 / 12 = $1,795.50 a month):
Other existing tests. No other case has a Social Security recipient aged 65 or older:
Their expectations are unaffected. Microsimulation note (informational). Military Retirement Pay
Axiom Issue (rulespec-us#1468)Compared against the structure of #1467:
The issue remains dispatch-ready. Refresh items are in Suggestion 3. Main-Merge Check (#9672, #9671, #9727)
Programs.yaml Merge ResolutionDiffed against the merge base
Regression Pass over the Delta
Critical (Must Fix)None. Should Address (remaining)None. S1 is resolved. SuggestionsNew in this round:
Carried over from round 2, optional:
CI and Branch Status
Review Severity: APPROVE0 critical, 0 should-address and 4 suggestions (3 new, 1 carried over).
|
DTrim99
left a comment
There was a problem hiding this comment.
Round 3 (#9728 (comment)): the Medicare Part B deduction and military retirement pay now match the state sources, the axiom issue is dispatch-ready, and the programs.yaml merge is correct; 0 critical, 0 should. The income lists are self-contained, so main's #9672 (snap_rental_income) does not cause double counting. #9727's merge reopened a programs.yaml conflict with main to resolve before merging.
…into in-eap Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Adds Indiana EAP regular heating assistance using FY2026 rules, with a state-specific dwelling-type input and existing income and utility inputs. In the lowest income band, a household with gas heat and electric service receives $450 in a single-family home, $425 in a mobile home, or $400 in a multi-unit dwelling. A vulnerable single-family household using bulk fuel receives $625. The winter electric allowance is included because manual Section 8.7 ties it to operating the heating system.
Year convention: undated formulas follow the model's existing parameter backfilling. The registry records
verified_years: "2026". FY2025 uses the PY2024-25 benefit matrix for the six values that differ from FY2026 (income points 6 and 4, electric payments $100 and $75, and zero fuel points for natural gas and electric heat); its other values and all earlier years are unverified historical estimates.medicare_part_b_premium, which is zero for a person who is not enrolled and excludes the share a Medicare Savings Program pays; the model has no Part D premium variable, so that part of the deduction is not modeled. Military retirement pay is counted beside pension income, because the two are separate inputs.in_eap_dwelling_typeselectsSINGLE_FAMILY(3 points),MOBILE_HOME(2) orMULTI_UNIT(1). Includes reported pregnancy in household size and vulnerability.Limitations
OTHERfuels receive the bulk-fuel points, and solar heat receives none; both are assumptions the manual does not address.heating_typemust be sent. An unspecified fuel receives no heating award.Regular heating and its winter electric allowance only. Crisis, cooling, weatherization and equipment payments are excluded.
Sources:
Validation: 39 Indiana YAML cases cover annual eligibility and three-month payment boundaries through size 11, dwelling and fuel points, the disability proxies, utility and rent treatment, household composition, income sources and exclusions, and an FY2025 household for each changed value. All 90 printed FY2026 income-table values were reconciled against the manual. CI runs the test suite.
axiom: TheAxiomFoundation/rulespec-us#1468 queued