Repository navigation
Conversation
42 U.S.C. 1382a(a)(2)(B) and 20 CFR 416.1121(a) count railroad retirement annuities as unearned income, but the SSI unearned income list omitted railroad_benefits, so an aged railroad annuitant received the full federal benefit. Add it to paragraph (a) with statute and POMS SI 00830.225 references, add SSI tests for a reduced and a zero benefit, and update an NH fuel assistance comment that described the gap. Fixes #10533 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Relabel railroad_benefits, give it a USD unit and document that it holds gross Railroad Retirement Board payments before Medicare premiums or other withholding. Note in the California 250% Working Disabled Program exempt list that railroad disability annuities cannot be separated from other railroad payments, so they now count (follow-up issue 10540). Correct the 2027 Medicare Savings Program limit in the NH fuel assistance test comments to about 1,848 a month. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PavelMakarchuk
left a comment
There was a problem hiding this comment.
Program Review
PR #10534, "Count railroad retirement annuities as SSI unearned income" (hua7450). Round 1.
IDs: C = critical, SA = should address, G = suggestion.
Source Documents
- Reviewed head SHA: 8e96a5b
- Mode: full (round 1)
- 42 U.S.C. 1382a(a)(2)(B): unearned income includes "railroad retirement annuities and pensions". The
#a_2_Banchor resolves. - 20 CFR 416.1121(a): periodic payments include "railroad retirement annuities".
- 20 CFR 416.1123(b)(2): amounts withheld "to make any other payment such as payment of your Medicare premiums" still count. So SSA counts the gross amount, as for Social Security.
- POMS SI 00830.225 (TN 237, effective 09/10/2024): B.1 "Payments made by RRB are unearned income." B.2 counts the SMI premium deducted. B.3 counts the annuity "before the collection of any obligations". The section makes no split between Tier I and Tier II.
- 20 CFR 416.1124 and the Subpart K appendix: I found no exclusion for any RRB payment. That includes the supplemental annuity and the vested dual benefit.
- LA County DPSS, 250% WDP: "Federal, State and private disability income" is exempt. Only SSDI stays exempt after it converts to retirement. This matches the PR's WDP NOTE.
- 9 CCR 2503-5 3.520.785(B)(5), file page 69: Colorado OAP counts "Railroad retirement payments, such as sick pay, annuities, pensions, and unemployment insurance benefits, which are paid by the Railroad Retirement Board".
- 7 CFR 273.9(b)(2)(ii): SNAP counts "Annuities; pensions; retirement ... benefits". 24 CFR 5.609(a)(1): HUD counts "All amounts, not specifically excluded".
- RRB News Release 25-8: the average regular employee annuity rises "to $3,636" in January 2026. This confirms the test comment. I could not open the RRB Quarterly Benefit Statistics page (404), so I did not check the $893.35 divorced spouse figure. The test value does not depend on it.
- policyengine-us-data
datasets/cps/cps.pyanddatasets/puf/puf.py: neither has a "railroad" term. CPS pensions (PNSN_VAL + ANN_VAL) go to the pension variables. Sorailroad_benefitsis 0 in microdata and does not overlappension_income. In the model,social_securityandpension_incomedo not addrailroad_benefits, so the SSI list does not count the same dollars twice.
Branch Status
- The PR is 2 commits ahead and 2 behind
main(73f6376).git merge-treeagainst main is clean. - CI passed: 33 of 33 checks. The last check finished at 12:08pm EDT on October 29. There are no reviews or comments yet.
- Main gained Iowa State Supplementary Assistance (#8017) after the PR base. It reads
ssi_unearned_incomeandssi_countable_income. On a scratch tree of main plus this PR, the Iowahhsfolder, the SSI folder and every railroad test file pass (1,340 passed). - #10532 (farm and partnership SSI earnings): a text conflict in
tests/.../gov/ssa/ssi/ssi.yaml, because both PRs append cases after the last case. Keep both blocks. The code does not interact (#10532 changes the earned side). - #10382 (SSI interest and dividend exclusion): adds a second dated list,
2004-07-01, tounearned.yaml, and that list has norailroad_benefits. In my three-way merge ofunearned.yaml, the value lists merge cleanly and only thereferenceblock conflicts. The risk is that whoever merges second resolves only the reference conflict. Then the 2005+ list silently dropsrailroad_benefits. This PR's 2026 tests would catch that in CI. The fix is to addrailroad_benefitsto the 2004-07-01 list as part of the second merge. - #10332: it has no text conflict with this PR's files. Its conflicts with main are in its own files.
Findings
Critical
None.
Should address
SA1. Colorado OAP now pays more to a railroad annuitant, because its own income list omits railroad_benefits.
- Where:
policyengine_us/parameters/gov/states/co/ssa/oap/income/sources/unearned.yaml(not in the diff). It is read byco_oap_unearned_incomeand thenco_oap_own_countable_income. - Evidence:
co_oappays the grant standard less SSI andco_oap_countable_income($1,032 a month in 2026). The OAP list hassocial_securityandpension_incomebut notrailroad_benefits, against 3.520.785(B)(5). Before this PR, the overstated SSI ($994 a month) stood in for the annuity. Now SSI correctly falls, and OAP adds nothing for the annuity. Take a 70-year-old in Colorado with $6,000 a year of railroad income in 2026.co_oapgoes from $2,268 to $6,216. The same $6,000 as Social Security gives $2,268. The PR body lists "CO OAP deeming" as a program that now counts railroad annuities. That is true for a dependent child's income inco_oap_deemed_income, which reads the SSI list, but it is not true for the client's or the spouse's own income. - Fix: add
railroad_benefitsto the OAP unearned list. Cite 3.520.785(B)(5) at#page=69. Add aco_oapcase: age 70,railroad_benefits: 6_000, expectedco_oap: 2_268.
Suggestions
G1. Say where railroad unemployment and sickness benefits go.
- Where:
policyengine_us/variables/household/income/person/retirement/railroad_benefits.py. - Evidence: the new label is "Railroad Retirement Board benefits". POMS SI 00830.225 A.4 says RRB also pays unemployment, sickness and strike benefits. The documentation lists only annuities, and NH FAP and AR LIHEAP net the Part B premium from this input, which only fits annuities.
- Fix: add a sentence that says Railroad Unemployment Insurance Act benefits go in
unemployment_compensation(or in whichever input you intend), not here.
G2. Fix the label of the variable that the new test covers.
- Where:
policyengine_us/variables/gov/ssa/ssi/eligibility/income/ssi_unearned_income.py,label = "SSI earned income". This is older than the PR. - Fix: change it to
"SSI unearned income".
G3. For an aged, blind or disabled railroad annuitant, the annuity now drops out of household net income, SNAP income and HUD income. The PR body does not say so.
-
Where:
gov/household/household_benefits.yamlandspm_unit_benefits(neither hasrailroad_benefits, and neither doesmarket_income_sources.yaml),gov/usda/snap/income/sources/unearned.yamlandgov/hud/annual_income/sources/unearned.yaml. My scan found 34 parameter lists that countssiandsocial_securitybut notrailroad_benefits. -
Evidence: these omissions are older than this PR. But the inflated SSI used to stand in for the missing annuity, and this PR removes that. I probed Texas, age 70, rent $9,600, 2026:
Case SSI SNAP hud_annual_incomehousehold_net_income$6,000 railroad, before 11,928 2,244 11,928 14,823 $6,000 railroad, after 6,168 3,600 6,168 10,419 $6,000 Social Security 6,168 2,136 12,168 14,955 $37,000 railroad, before 11,928 2,244 n/a 14,823 $37,000 railroad, after 0 3,600 n/a 4,251 $37,000 Social Security 0 0 n/a 37,000 The PR body's own example, a $37,000 annuitant, now shows $4,251 of net income and the maximum SNAP benefit. 7 CFR 273.9(b)(2)(ii) and 24 CFR 5.609(a)(1) count the annuity.
-
Why a suggestion: the lists are older than this PR and are not in its files, and no dataset fills
railroad_benefits, so the microsimulation does not change. A tracked follow-up is enough for this PR. -
Fix: open a follow-up issue that lists the 34 lists. Link it from a NOTE in
unearned.yaml, and state the net income and SNAP effect in "Who this affects". If you prefer to fix it here, addrailroad_benefitsnext tosocial_securityinhousehold_benefitsandspm_unit_benefits, and add it to the SNAP and HUD unearned lists, with one test each.
Downstream effects
These are probe values for 2026, age 70, $6,000 a year of railroad income, before and after the PR. In every output except co_oap, I got the same result when I entered the same dollars as social_security_retirement. So the railroad annuity now follows the model's existing Social Security path.
- Federal SSI:
ssigoes from 11,928 to 6,168 ((500 − 20) × 12 = 5,760 of countable income). This is correct. - Spousal deeming: take a 70-year-old with a 60-year-old spouse who has $30,000 of railroad income.
ssi_unearned_income_deemed_from_ineligible_spousegoes from 0 to 30,000, andssigoes from 11,928 to 0. This is correct (20 CFR 416.1161). - MSP:
msp_countable_incomeequals SSI countable income. At $37,000,msp_eligiblechanges from true to false andmedicare_part_b_premiumfrom 0 to 2,434.80. This is correct. - State supplements: CT SSP countable income +240, NH SSP 324 → 84, MN MSA 972 → 0, SD SSP 180 → 0, WY SSP 240 → 0, OR SSP countable income +240. CA SSP ($4,425.72), OK SSP ($480), VT AABD ($668.16) and WI SSP ($1,072.40) do not change. Each result equals the Social Security result. I did not re-audit those programs' own rules.
- CO OAP: 2,268 → 6,216. This is wrong, see SA1.
- CA WDP: for a disabled worker aged 40 with $20,000 of earnings and $12,000 of railroad income,
ca_wdp_countable_incomegoes from 9,490 to 21,370 and the person stays eligible. The NOTE and #10540 document the over-count of disability annuities. LA County supports the NOTE. A documented limitation with a tracked issue is acceptable. - SNAP, HUD and household net income: these go the wrong way for SSI-eligible annuitants, see G3.
- NH FAP: Cases 28 and 32 keep their expected values. The model's 2027 first-person FPG is 16,426.79, so the QI limit is 16,426.79 × 1.35 / 12 = 1,848.01 a month. MSP countable income is 1,480, and $20,000 of assets is above $9,950, so the premium of 2,434.80 stays. The old "about 1,838" was wrong, and the PR's 1,848 is right.
- Partner contract tests: no file under
policyengine_us/tests/policy/baseline/partners/setsrailroad_benefits. The input defaults to 0, so no partner output changes. I did not run them. - Microsimulation: none, because no dataset fills
railroad_benefits.
Tests run
policyengine-core test policyengine_us/tests/policy/baseline/gov/ssa/ssiat head: 246 passed.- All 39 YAML files that set
railroad_benefits(37 existing and 2 changed) at head: 652 passed. - Dependent folders at head: Medicare, Medicaid income, CA WDP, CO SSA, CT SSP, MN MSA, NC SA, NH SSP, OH RSS, OK SSP, OR SSP, SD SSP, VA AG, VT AABD, WI SSP, WY SSP and NH FAP. Result: 1,533 passed.
- Scratch tree of main 73f6376 plus the PR patch: the IA
hhsfolder, the SSI folder and the railroad test files. Result: 1,340 passed. - Non-functional test check: I ran the head's
ssi.yamlandssi_unearned_income.yamlagainst the pre-PR package. The 3 new cases fail and the 7 old cases pass. - Hand checks: FBR $994 × 12 = 11,928, and the general exclusion is $20 (both read from the model).
- Case 1: (900 − 20) × 12 = 10,560, and 11,928 − 10,560 = 1,368.
- Case 2: 43,632 / 12 = 3,636; (3,636 − 20) × 12 = 43,392; 11,928 − 43,392 = −31,464, so SSI is 0.
- Unearned case: 10,800 → 10,800.
- All three match.
- References: the three hrefs return 200 and support the rule. The USC anchor
#a_2_Bexists. The parameter's 1975-01-01 start is right, because the statute has always listed railroad annuities.
Verdict
REQUEST_CHANGES: the SSI change, the references and the tests are correct. But Colorado OAP now overpays a railroad annuitant, because its own income list omits the annuity. Open item: SA1. G3 (net income, SNAP and HUD) needs only a tracked follow-up.
Add railroad_benefits to the Colorado Old Age Pension unearned income list (9 CCR 2503-5 3.520.785(B)(5)) with a co_oap test, so the lower SSI no longer raises the OAP grant. Document where Railroad Unemployment Insurance Act benefits are reported, fix the ssi_unearned_income label, and note in the SSI list that household net income, SNAP, HUD and other program lists do not yet count railroad_benefits (issue 10551). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Thanks, Pavel. Round 1 is addressed in c8a1d69:
|
Fixes #10533
What and why
The federal Supplemental Security Income (SSI) unearned income list,
gov.ssa.ssi.income.sources.unearned, omittedrailroad_benefits. Neithersocial_securitynorpension_incomeincludes it, so the model paid SSI as if a railroad annuitant had no income. A 70-year-old whose only income was a $37,000 Railroad Retirement annuity received the full 2026 federal benefit of $11,928 (994 x 12). Missouri LIHEAP PR 10438 exposed the gap.This PR adds
railroad_benefitsto paragraph (a) of the list ("annuities, pensions, and other periodic payments"):railroad_benefitsinput.The parameter now cites the statute and the POMS section next to the existing 20 CFR 416.1121 reference. The
railroad_benefitsinput gets a corrected label ("Railroad Retirement Board benefits"), a USD unit, and documentation stating that it holds gross annual payments before Medicare premiums or other withholding, with Railroad Unemployment Insurance Act unemployment and sickness benefits reported inunemployment_compensationanddisability_benefits.ssi_unearned_incomegets its correct label ("SSI unearned income").Who this affects
Every variable that reads
ssi_unearned_incomeor the source list now counts railroad annuities:ssi_countable_income,uncapped_ssi,ssi, and spousal and parental deeming.msp_countable_income), which uses SSI income methodology, and through itmedicare_part_b_premium.railroad_benefits. 9 CCR 2503-5 3.520.785(B)(5) counts "Railroad retirement payments, such as sick pay, annuities, pensions, and unemployment insurance benefits, which are paid by the Railroad Retirement Board". Without this, the lower SSI would raise the OAP grant, for example from $2,268 to $6,216 a year for a 70-year-old with $6,000 of railroad income.ssi > 0) and programs that countssias income see lower SSI for aged, blind or disabled railroad annuitants.Household net income, SNAP, HUD annual income and other program income lists (34 lists in all) count
ssiandsocial_securitybut notrailroad_benefits. For an SSI-eligible railroad annuitant, the higher SSI used to stand in for the missing annuity. With SSI now correct, the annuity drops out of those totals: a 70-year-old Texan with a $37,000 annuity shows $4,251 of household net income and the maximum SNAP benefit. The omission predates this PR for annuitants who are not SSI-eligible. A NOTE in the SSI list records it, and #10551 tracks addingrailroad_benefitsto those lists.California's 250% Working Disabled Program exempts disability income until it converts to retirement income. It now counts every railroad payment, including Railroad Retirement disability annuities, because the input does not separate them from age, spouse or survivor annuities. Before this PR, the program counted no railroad payment at all. A NOTE in the program's exempt-income list records the limitation, and #10540 tracks the fix.
No microdata pipeline in policyengine-us-data or Microcosm populates
railroad_benefits, so the input stays 0 in microsimulation and the change affects household calculations only. I did not run a microsimulation.Test plan
New cases, with values hand-derived from the 2026 federal benefit rate of $994 a month and the $20 general income exclusion:
ssa/ssi/income/ssi_unearned_income.yamlssa/ssi/ssi.yamlssa/ssi/ssi.yamlstates/co/ssa/oap/co_oap.yamlExisting tests: 37 YAML files set
railroad_benefits. For each case, I checked whether a person with railroad income is aged, blind or disabled and whether the asserted outputs depend on SSI or the Medicare Savings Program. No expected value changes:ssias an input: AL, AR, AZ, GA, MS and SD LIHEAP, NH Fuel Assistance, and the PA property tax or rent rebate.medicare_part_b_premiumas an input.social_security, which those cases leave at 0.policyengine_us/tests/policy/baseline/partners/setsrailroad_benefits.Merge order: #10382 adds a 2004-07-01 version of the SSI unearned list without
railroad_benefits. Whichever of the two PRs merges second must addrailroad_benefitsto that version; the 2026 SSI tests here fail if it is missed.make formatchangelog.d/axiom: TheAxiomFoundation/rulespec-us#1967 queued
🤖 Generated with Claude Code