Implement Nebraska State Supplementary Payment (SSP)#8235
Conversation
…Engine#8234) Implements Aid to the Aged, Blind, or Disabled — Payment, Nebraska's state-administered fill-the-gap supplement to federal SSI. - 6 variables: ne_aabd, ne_aabd_eligible, ne_aabd_standard_of_need, ne_aabd_living_arrangement, ne_aabd_alternate_living_arrangement, ne_aabd_couple_rate_applies - 4 parameters: independent SoN by household size, shelter allowances (single/multiple), 7-value alternate living standard - 3 effective-date tiers: 2015-01-01, 2017-01-01, 2021-01-01 (frozen) - Couple treatment: joint 2-person standard split 50/50 for Independent; alternate-living couples treated as two individuals per SSA 2011 footnote - 34 tests pass (integration + 2 unit test files) - Wired into spm_unit_benefits, household_state_benefits, programs.yaml
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #8235 +/- ##
===========================================
- Coverage 100.00% 94.69% -5.31%
===========================================
Files 3 7 +4
Lines 63 113 +50
Branches 0 2 +2
===========================================
+ Hits 63 107 +44
- Misses 0 6 +6
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
…hors - Rename GROUP_HOME_DISABLED → GROUP_HOME_CHILDREN: enum values ($801/$803/$862) match the "Licensed Group Home for Children or Child Caring Agency" line in 469-000-211, not the "Center for the Developmentally Disabled" line. - Document NAC line → enum mapping in BOARD_AND_ROOM and ASSISTED_LIVING_FACILITY enum descriptions (rate-equivalent arrangements collapsed by intentional design). - Add #page=126 to Title-469-Complete.pdf references in ne_aabd.py and ne_aabd_eligible.py (section 3-006.01A1 — payment calculation). - Add #page=130 to Title-469-Complete.pdf reference in ne_aabd_couple_rate_applies.py (section 3-006.02B3a(1) — couple budgeting). All 34 tests pass.
PavelMakarchuk
left a comment
There was a problem hiding this comment.
Program Review — PR #8235 (Nebraska AABD-PMT / State Supplementary Payment)
Source Documents
- PDF 1: 469 NAC 469-000-211 — Standard of Need (current, eff. 2021-01-01) (1 page)
- PDF 2: SSA 2011 SSI State Assistance — Nebraska (3 pages, via Wayback)
- PDF 3: 469 NAC 469-000-207 — SSI FBR (1 page)
- PDF 4: Title 469 NAC Complete (147 pages)
- PDF 5: 469-000-211 eff. 2017-01-01 (Wayback)
- PDF 6: 469-000-211 eff. 2015-01-01 (Wayback)
- Statute: Neb. Rev. Stat. § 68-1001 / § 68-1005
- Year: 2015-2025 (three effective-date tiers)
- Scope: PR changes only
Critical (Must Fix)
C1. ne_aabd income_excess uses federal SSI countable-income definition with disregards that NAC 3-006.01A explicitly forbids
- Files:
/Users/pavelmakarchuk/policyengine-us/policyengine_us/variables/gov/states/ne/dhhs/aabd/ne_aabd.py(lines 25–29)- Path:
ne_aabd→uncapped_ssi→ssi_countable_income(applies $20 general, $65 earned, 50% earned disregards plus ISM/PMV and deeming).
- Regulatory citation: 469 NAC 3-006.01A (Title-469-Complete.pdf, lines 5458–5481) enumerates the closed list of available net income: (a) non-spouse Essential Person income, (b) VA Aid & Attendance, (c) income allocated from another assistance unit, (d) ineligible-spouse income not used by SSI — and explicitly states "This income is not allowed the $20 general income disregard."
- Code-path verification: CONFIRMED (
/tmp/review-program-codepath-2.md). For SSI-only householdsincome_excess == 0and the bug is invisible. It bites materially for:- SSI recipients with earned income (federal disregards understate countable income vs NAC → over-pays supplement)
- Recipients with VA Aid & Attendance (NAC denies the $20 disregard; code applies it)
- Households with non-spouse Essential Persons (NAC counts their income; code ignores it entirely)
- Joint-claim couples with deemed ineligible-spouse income
- ISM/PMV-affected recipients
- Suggested fix: introduce
ne_aabd_countable_incomesumming only (a)–(d) with no $20 disregard, subtract from requirements first, then subtract the FBR (matches the NAC's two-step order — see C2 below for the order-of-operations sub-issue). - Anchor:
Title-469-Complete.pdf#page=126.
C2. ne_aabd_alternate_living_arrangement declared YEAR while every downstream consumer is MONTH
- File:
/Users/pavelmakarchuk/policyengine-us/policyengine_us/variables/gov/states/ne/dhhs/aabd/ne_aabd_alternate_living_arrangement.py(line 11) —definition_period = YEAR. - Consumers (
ne_aabd_living_arrangement.py:42reads viaperson.this_year; the outer variable isMONTH); downstreamne_aabd_standard_of_need,ne_aabd_couple_rate_applies,ne_aabdare allMONTH. - Regulatory citation: 469 NAC 3-006.02B5 contemplates monthly entry/exit from care facilities; the NE budget is computed monthly.
- Effect: a user cannot model someone who is
ASSISTED_LIVING_FACILITYfor half the year andINDEPENDENTfor the other half — the year-scoped input resolves to one value for the entire year, preventing mid-year transitions. - Suggested fix: switch
definition_periodtoMONTHto match the monthly budgeting cadence and align all dependents.
Should Address
S1. ne_aabd_eligible uses ssi > 0, excluding 1619(b) recipients and grandfathered non-SSI AABD pathway
- File:
/Users/pavelmakarchuk/policyengine-us/policyengine_us/variables/gov/states/ne/dhhs/aabd/ne_aabd_eligible.py(line 21). ssi(YEAR) multiplies bytakes_up_ssi_if_eligible, which is assigned at microdata-build time. A fully SSI-eligible person flagged non-takeup yieldsssi == 0and thereforene_aabd_eligible == false.- Also excludes 1619(b) SSI recipients (zero cash but Medicaid-eligible — NAC lines 656, 672–673, 5440–5441) and grandfathered non-SSI recipients listed in 469 NAC 3-006.01 / SSA PDF Table 2 note ("Includes certain grandfathered, non-SSI recipients who meet state eligibility criteria").
- Reference pattern: AL / ME / MA SSP variables gate on
uncapped_ssi > 0(oris_ssi_eligible). - Citation: 469 NAC 2-010 + 3-006.01A.
S2. Order of operations in fill-the-gap conflates two NAC steps
- File:
/Users/pavelmakarchuk/policyengine-us/policyengine_us/variables/gov/states/ne/dhhs/aabd/ne_aabd.py(returnsmax_(0, standard_of_need - federal_ssi - income_excess)). - Citation: 469 NAC 3-006.01A specifies (1) requirements − available net income → "budgetary need", then (2) subtract FBR (3-006.01A1). Repo collapses both into a single floor; for borderline cases the determination diverges from the NAC's "deny at step 1 if income ≥ requirements".
- Closely related to C1's fix path.
S3. Parameter description includes forbidden phrase "by household size" and redundant "monthly"
- Files:
/Users/pavelmakarchuk/policyengine-us/policyengine_us/parameters/gov/states/ne/dhhs/aabd/standard_of_need/independent.yaml(line 1) — drop "by household size" (evident frombreakdown)- All four parameter files (
alternate_living_standard.yaml,shelter_allowance/single.yaml,shelter_allowance/multiple.yaml,standard_of_need/independent.yaml) — drop redundant "monthly" (evident fromperiod: month).
- Skill rules:
policyengine-parameter-patternsexplicitly forbids both.
S4. Family-size 3+ values in standard_of_need/independent.yaml are dead code
- File:
/Users/pavelmakarchuk/policyengine-us/policyengine_us/parameters/gov/states/ne/dhhs/aabd/standard_of_need/independent.yaml(sizes 3–10). ne_aabd_standard_of_need.pyhard-codesindependent_size = where(couple_applies, 2, 1); sizes ≥3 are never indexed.- Either:
- implement Essential Person inclusion (469 NAC 3-006.02 / 3-006.02B2) so the larger SoN brackets apply, or
- prune sizes 3–10 from the parameter file with a comment that EP inclusion is deferred.
S5. Missing statute citation (Neb. Rev. Stat. § 68-1001 / § 68-1005)
- No parameter file or variable
referencetuple cites the statutory authority. Add a 4th tuple entry tone_aabd_eligible.pyandne_aabd.py:"https://nebraskalegislature.gov/laws/statutes.php?statute=68-1005"
S6. Title-469 #page=130 anchor on ne_aabd_couple_rate_applies.py should be #page=129
- File:
/Users/pavelmakarchuk/policyengine-us/policyengine_us/variables/gov/states/ne/dhhs/aabd/ne_aabd_couple_rate_applies.py. - Page 129 carries the heading
3-006.02B3a(1) Spouse on AABD or SDPand the "payment is divided equally" rule the code comment cites. Page 130 is the(1)(a)Living Independently subsection. Either change anchor to#page=129or change cited section to3-006.02B3a(1)(a).
S7. Missing 2017 reference on shelter allowance parameter files
shelter_allowance/single.yamlandmultiple.yamlonly reference the 2021 and 2015 versions. Values ($281 / $349) are unchanged through 2017, but the 2017 manual letter should be cited as continuing evidence (Wayback URL).
S8. Three alternate-living rates (BOARD_AND_ROOM, ASSISTED_LIVING_WAIVER, GROUP_HOME_CHILDREN) lack numeric verification in tests
ne_aabd_living_arrangement.yamlCases 5–7 only assert the enum propagates; they never verifyne_aabd_standard_of_needorne_aabddollar amounts at those arrangements. 3 of 7 alternate-living rates have zero numeric coverage.
S9. 2015-tier values never directly tested
- Earliest test period is
2016-01(Case 8a), which resolves to the 2015 tier — but no test setsperiod: 2015-01literally. None of the distinct 2015-tier alternate-living rates ($50 LTC, $865 AFH, $737 BR, $1,175 ALF, $733 ALW, $801 GHC) are exercised.
S10. ssi_claim_is_joint = False with both-SSI-eligible + both-INDEPENDENT branch untested
ne_aabd_couple_rate_appliestruth table has 8 input combinations; this single AND-gate branch (joint_claim=F, both_eligible=T, both_independent=T) is not exercised.
S11. Unlicensed board-and-room couple sub-case not separately handled
- Citation: 469 NAC 3-006.02B3a(1)(b). Code treats every alternate-living person as a standalone individual; this matches SSA 2011 footnote a for licensed alternate living but is too coarse for the unlicensed board-and-room couple sub-case (single combined budget).
S12. Missing dedicated unit-test YAML for ne_aabd_standard_of_need.py, ne_aabd_couple_rate_applies.py, and ne_aabd.py
- All three have conditional/branching logic but are only exercised via integration tests. Per
policyengine-testing-patterns, dedicated unit-test files would make the regression surface explicit (income_excess in particular).
S13. Redundant title formatting 469 NAC 469-000-211 in all four parameter files
469-000-211is the document number within Title 469 NAC; the leading469 NACduplicates the prefix. UseTitle 469 NAC § 469-000-211or similar.
Suggestions
G1. ne_aabd_standard_of_need.py line 39 — independent_total / 2 → independent_total / marital_unit.nb_persons()
- Magic number
2is acceptable per code-style skill ("basic math") butnb_persons()would be more vectorization-correct and self-documenting.
G2. ne_aabd_living_arrangement could be YEAR
- Formula only accesses YEAR inputs (
ssi_federal_living_arrangement,ne_aabd_alternate_living_arrangement); declaring it YEAR would be cheaper and aligned. (Decision interacts with C2.)
G3. ne_aabd.py local variable federal_ssi = ssi_amount_if_eligible — rename for clarity
- Returns the post-VTR / post-Code-D amount. Renaming to
effective_federal_paymentand adding a comment that NAC intends the adjusted FBR (which is what the code uses, and is regulation-consistent in both directions) would prevent confusion.
G4. ne_aabd_alternate_living_arrangement.py lacks docstring explaining why it exists separately from ne_aabd_living_arrangement
- The split (input enum vs derived enum that overlays federal Code D) is correct but unobvious; add a short comment.
G5. Living arrangement enum collapses 9 NAC categories to 7
- Reasonable for now; consider a comment near the enum (not only in the PR description) noting the collapse for future maintainers.
G6. verified_years: "2015-2025" in programs.yaml may overstate verification
- 2018–2020 has no published manual letter; the PR assumes the 2017 rates carried through. Consider
"2015-2017, 2021-2025"or document the assumption.
G7. INDEPENDENT: 0 / NONE: 0 entries in alternate_living_standard.yaml are sentinels
- Only read on the false branch of
where. Either drop them or refactor toselect(...)to avoid the unused parameter rows.
G8. Manual Letter number for 2021 tier not stated in reference
- Historical references cite "Manual Letter #1-2017" / "#74-2014"; the 2021 reference does not. Adding the Manual Letter number (likely #41-2020 or #1-2021) would symmetrize the citation block.
G9. Deferred features (intentional)
- SSI service-animal $50 maintenance allowance (469 NAC 3-004.03)
- Essential Person inclusion (469 NAC 3-006.02 / 3-006.02B2) — would unlock SoN sizes 3–10
- Pro-ration for spouse on ADC/RRP (469 NAC 3-006.02B3a(2)(a))
- Pro-ration for shared housing with self-supporting roommates (469 NAC 3-006.02B4a)
- Three-month continuous LTC budgeting override (469 NAC 3-006.01A2) — time-history rule, single-period architecture limitation
- SSI referral amounts and standalone PNA $64 parameter
G10. Inline-comment-heavy style
- Per code-style skill, multi-line regulatory explanations belong in
referenceURLs and PR description rather than inline. Borderline — current comments document non-obvious modeling choices (e.g., the income_excess rationale, theis_ssi_eligiblechoice to avoid circularity); kept-or-trimmed at author discretion.
G11. Integration test numbering gaps (Case 9 → 11, Case 17 → 19)
- Either renumber for continuity or add the missing cases.
Investigated and Cleared
Circular dependency ne_aabd ↔ ssi via housing_cost → rent → housing_assistance → hud_annual_income — REJECTED
- Initial regulatory review (C1 in
/tmp/review-program-regulatory.md) flagged a cycle:ne_aabd_standard_of_need→housing_cost→rent→housing_assistance→hud_hap→hud_annual_income→ssi→ ... →ne_aabd. - Code-path verification (
/tmp/review-program-codepath-1.md) traced every edge and confirmed: nothing in the SSI subtree readshousing_cost,housing_assistance,hud_annual_income,spm_unit_benefits, orne_aabd. SSI is a source relative to this subgraph; the chain is a deep one-way DAG that terminates inside SSI's earned/unearned income inputs. - The only external reference to
ne_aabdisspm_unit_benefits.py:32, which is a terminal sink (not consumed by SSI or HUD). - Verdict: No cycle. The reviewer correctly identified a long dependency chain but missed that it never closes.
PDF Audit Summary
| Category | Count |
|---|---|
| Confirmed correct values | 50 (all SoN, alternate-living, shelter caps across 2015/2017/2021 tiers) |
| Mismatches (code-path confirmed) | 1 (income_excess) |
| Mismatches rejected (code-path cleared) | 1 (circular dependency — C1) |
| Unmodeled items (intentional deferrals OK) | 4-5 (1619(b), grandfathered AABD, service animal, EP additional persons, etc.) |
Validation Summary
| Check | Result |
|---|---|
| Regulatory Accuracy | 1 critical + 5 should |
| Reference Quality | 0 critical + 5 should |
| Code Patterns | 0 critical + 2 should |
| Test Coverage | 0 critical + 5 should |
| PDF Value Audit | 0 mismatches / 50 confirmed |
| CI Status | 24/25 passing — only codecov/project harmless |
Review Severity: REQUEST_CHANGES
Reason: income_excess uses the wrong income-disregard semantics for households with earned income, VA A&A, ISM, parental deeming, or a non-spouse EP — over-pays in those cases. Period mismatch on ne_aabd_alternate_living_arrangement (YEAR while inputs are MONTH) prevents mid-year transitions. Both have concrete fixes.
Next Steps
To auto-fix issues: /fix-pr 8235
C1: drop inert income_excess from ne_aabd; document NAC 3-006.01A closed list (EP income, VA A&A, allocated income, residual deeming) as unmodeled. C2: switch ne_aabd_alternate_living_arrangement to MONTH to match downstream consumers; update ne_aabd_living_arrangement consumer call to use period instead of period.this_year. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Thanks for the thorough review, Pavel. Want to push back on C1's severity. You're right that 469 NAC 3-006.01A enumerates a closed list of "available net income" and explicitly forbids the $20 disregard — verified against
For any person where So the five scenarios listed don't fire in practice:
So I'd suggest downgrading C1 from "Critical" to "Should — document modeling limitation". Happy to be overruled if I'm missing a case. |
Summary
Implements Nebraska's State Supplementary Payment — Aid to the Aged, Blind, or Disabled — Payment (AABD-PMT) — a state-administered, state-funded "fill-the-gap" supplement that brings SSI recipients up to a living-arrangement-specific standard of need.
Closes #8234
Regulatory Authority
Program Overview
Eligibility
ssi > 0(already impliesis_ssi_eligible+ federal income test + takeup)defined_for = StateCode.NEssi > 0ssi > 0ssi > 0max_(0, total_budget − uncapped_ssi)Benefit Amounts (469 NAC 469-000-211 — https://dhhs.ne.gov/Documents/469-000-211.pdf)
Independent Standard of Need (added to actual shelter expense, capped at max shelter allowance)
Max Shelter Allowance (Independent only, frozen since 2015)
Alternate-Living Standards (monthly; PNA $64 embedded)
The 9 living arrangements in 469-000-211 collapse to 7 distinct alternate-living rate values plus an
INDEPENDENTandNONEenum entry. Rates that always co-move (Board & Room, Boarding Home, Drug Treatment Center; Assisted Living Facility and Mental Health Center; Center for Developmentally Disabled and Boarding Home) share enum values.Couple treatment: Joint 2-person Independent standard of need split 50/50 between spouses living together. Couples in any alternate-living arrangement are treated as two individuals (per SSA 2011 PDF Table 1 footnote a: "Couples are treated as two individuals starting with the month after leaving an independent living arrangement" — https://www.ssa.gov/policy/docs/progdesc/ssi_st_asst/2011/ne.pdf#page=2).
Personal Needs Allowance: $64 PNA is embedded in all alternate-living standards (matches NAC structure). Long-Term Care = $60 because Medicaid covers the PNA in those settings.
No federal Code B / ISM tier: Per SSA 2011 PDF page 1, "Persons living in the household of another receive the same state supplement as those living independently." Nebraska pays the Independent standard regardless of household-of-another status.
COLA: No automatic indexing. Standards frozen at 2021 values since 2021-01-01 through at least 2025.
Couple gating
A combined 2-person Independent budget is used only when all three conditions are met:
ssi_claim_is_joint(joint SSI claim)Otherwise, each spouse's AABD payment is computed individually (per SSA 2011 footnote a).
Not Modeled (by design)
Files
Plumbing updated:
policyengine_us/variables/household/income/spm_unit/spm_unit_benefits.py,policyengine_us/parameters/gov/household/state_benefits/household_state_benefits.yaml, andpolicyengine_us/programs.yaml.Note on naming: Variable prefix is
ne_aabd_*(matching Nebraska's official program name "Aid to the Aged, Blind, or Disabled"), not the genericne_ssp_*convention used in some other states.Historical Notes
Verification TODO
Test plan
ne_aabd_eligible.yaml,ne_aabd_living_arrangement.yaml, andintegration.yaml(includes new $0 / below-cap / at-cap / above-cap shelter scenarios for the actual-shelter-capped-at-max behavior)