Repository navigation
Description
The model takes military retired pay and military survivor annuities in two inputs, military_retirement_pay and military_retirement_pay_survivors, and sums them in military_retirement_income. It builds pension_income from the taxable and tax-exempt pension inputs alone, so pension_income holds no military retired pay. At main, 54 benefit income lists name pension_income (one names taxable_pension_income) and leave out military_retirement_income. In each of those programs the model counts a government employee or private pension and drops the same amount of military retired pay.
Another 75 benefit lists name both, among them SNAP, SSI and most LIHEAP lists. The default dataset fills neither military input, so the model drops nothing from default microsimulation results. It undercounts income in household calculations that enter military retired pay.
Five households
We entered each household below for 2026 twice: once with military retired pay and once with the same amount as a private pension.
| Program | Household | With military retired pay | With a private pension |
|---|---|---|---|
| CSFP | Ohio couple aged 67 and 65, $30,000 of Social Security and $45,000 of retired pay | 138.6% of the poverty guideline; $651 for each spouse | 346.6%; $0 |
| WIC | Idaho parent aged 42 with $60,000, child aged 2 | countable income $3,708; $723.73 of WIC for the child | $60,000; $0 |
| HUD | Ohio tenant aged 50 with $30,000, in assisted housing | annual income $0; total tenant payment $25 a year | $30,000; $9,000 |
| Head Start | Ohio parent aged 30 with $60,000, child aged 4 | gross income $0; child eligible | $60,000; not eligible |
| North Dakota TANF | parent aged 40 with $24,000, child aged 8 | $739 in January | $0 |
For example, the model reads CSFP income from the school meals list, counts only the couple's Social Security and places them under CSFP's 150% limit. It gives both spouses CSFP in 46 states and DC. In Illinois, Kansas and Massachusetts the model also tests the county, and in Texas it applies the state's own income test.
The WIC family's $3,708 comes from twelve months of Idaho's $309 TANF grant, which the model also pays them. The model builds Idaho's TANF income on the federal TANF unearned list, where it also leaves the pay out. For the HUD tenant, the model cuts the payment to its minimum rent, which it sets at $25 a year, though HUD sets minimum rent by the month in 24 CFR 5.630(a).
What the agencies count
- USDA counts "Government civilian employee or military retirement or pensions or veterans' payments" as WIC income in 7 CFR 246.7(d)(2)(ii)(G).
- USDA counts "gross income before deductions for such items as income taxes" for CSFP in 7 CFR 247.9(d)(1). It lets states exclude a military housing allowance and in-kind benefits in (d)(2), and it names no retired pay among the statutory exclusions in (d)(3).
- HUD counts "All amounts, not specifically excluded in paragraph (b) of this section, received from all sources" in 24 CFR 5.609(a)(1). In paragraph (b)(11), HUD excludes special pay for hostile fire, and it names no military retired pay among the exclusions in (b).
- HHS counts "pension or annuity payments, gifts that exceed the threshold for taxable income, and military income" for Head Start in 45 CFR 1305.2.
- North Dakota counts "Monthly or regular payments from annuities, pensions and other retirement plans" in its TANF manual, 400-19-55-20-15.
- USDA counts "government civilian employee or military retirement, or pensions or veterans payments" for school meals in item 9 of its 2026-27 income notice. We raised the school meals list in The model counts educational assistance in school meal income, subtracts business losses and leaves out alimony, workers' compensation and other income USDA counts #10801.
Where the model drops it
- The model sums each list with
addsoradd(): WIC inwic_countable_income.py, HUD inhud_unearned_income.py, Head Start inhead_start_gross_income.pyand TANF intanf_gross_unearned_income.py. - The model divides school meal income by the poverty guideline in
school_meal_fpg_ratio.pyand tests that ratio against CSFP's 150% limit incommodity_supplemental_food_program_eligible.py. - In 37 states the model builds TANF income on
tanf_gross_unearned_income, Idaho among them (id_tafi_countable_unearned_income.py).
The 54 lists
The model stores two dated blocks for California CARE/FERA and for Louisiana child care, and all four leave the pay out.
Federal programs
| Program | List, at the pension line |
|---|---|
| WIC | usda/wic/income/sources.yaml L16 |
School meals, and CSFP through school_meal_fpg_ratio (school meals: #10801) |
usda/school_meals/income/sources.yaml L17 |
| HUD annual income | hud/annual_income/sources/unearned.yaml L4 |
| Head Start | hhs/head_start/income/sources.yaml L11 |
TANF unearned income (tanf_gross_unearned_income, read by 37 states' TANF code) |
hhs/tanf/cash/income/sources/unearned.yaml L13 |
State and county cash assistance
| Program | List, at the pension line |
|---|---|
| Colorado TANF | states/co/cdhs/tanf/income/unearned.yaml L10 |
| Colorado Old Age Pension | states/co/ssa/oap/income/sources/unearned.yaml L10 |
| DC TANF | states/dc/dhs/tanf/income/sources/unearned.yaml L11 |
| Maine TANF | states/me/dhhs/tanf/income/sources/unearned.yaml L17 |
| Massachusetts Transitional Cash Assistance Program | states/ma/dta/tcap/gross_income/unearned.yaml L9 |
| Minnesota MFIP | states/mn/dcyf/mfip/income/sources/unearned.yaml L14 |
| Montana TANF | states/mt/dhs/tanf/income/sources/unearned.yaml L7 |
| North Carolina TANF | states/nc/ncdhhs/tanf/income/unearned.yaml L11 |
| North Dakota TANF | states/nd/dhs/tanf/income/sources/unearned.yaml L14 |
| South Carolina TANF | states/sc/tanf/income/unearned/sources.yaml L11 |
| Wyoming POWER | states/wy/dfs/power/income/sources/unearned.yaml L14 |
| Marin County General Relief | local/ca/marin/general_relief/income_sources.yaml L16 |
| Orange County General Relief | local/ca/oc/general_relief/income/sources/unearned.yaml L11 |
| San Bernardino County General Relief | local/ca/sbd/general_relief/income/sources/unearned.yaml L20 |
| San Francisco CAAP | local/ca/sf/caap/countable_income/sources/unearned.yaml L7 |
| San Mateo County General Assistance | local/ca/smc/general_assistance/income/sources.yaml L13 |
Santa Clara County General Assistance (taxable_pension_income) |
local/ca/scc/general_assistance/countable_income/unearned_sources.yaml L11 |
Child care and early childhood
| Program | List, at the pension line |
|---|---|
| Alabama CCSP | states/al/dhr/ccsp/income/countable_income/sources.yaml L8 |
| Alaska CCAP | states/ak/dpa/ccap/income/countable_income/unearned_sources.yaml L17 |
| Arizona CCAP | states/az/hhs/ccap/income/countable_income/sources.yaml L13 |
| California child care | states/ca/cdss/child_care/income/sources.yaml L21 |
| Connecticut Care 4 Kids | states/ct/oec/c4k/income/unearned_sources.yaml L5 |
| Georgia CAPS | states/ga/decal/caps/income/countable_income/sources.yaml L14 |
| Illinois CCAP | states/il/dhs/ccap/income/countable_income/sources.yaml L11 |
| Illinois ISBE early childhood programs | states/il/isbe/income/countable_sources.yaml L11 |
| Iowa CCA | states/ia/hhs/cca/income/countable_income/unearned_sources.yaml L6 |
| Louisiana CCAP | states/la/ldoe/ccap/income/unearned_sources.yaml L7, L20 |
| Mississippi CCPP | states/ms/dhs/ccpp/income/countable_income/unearned_sources.yaml L10 |
| Montana Best Beginnings | states/mt/dphhs/ccap/income/countable_income/sources.yaml L16 |
| New Hampshire Child Care Scholarship | states/nh/dhhs/ccap/income/countable_income/sources.yaml L11 |
| New Jersey CCAP | states/nj/njdhs/ccap/income/countable_income/unearned_sources.yaml L11 |
| North Carolina Subsidized Child Care | states/nc/ncdhhs/scca/income/sources.yaml L8 |
| North Dakota CCAP | states/nd/dhs/ccap/income/sources.yaml L18 |
| Oklahoma Child Care Subsidy | states/ok/dhs/ccs/income/sources.yaml L28 |
| South Carolina Child Care Scholarship | states/sc/dss/ccap/income/countable_income/sources.yaml L9 |
| South Dakota CCA | states/sd/dss/cca/income/sources.yaml L16 |
| Texas Child Care Services | states/tx/twc/ccs/income/sources.yaml L10 |
| Utah CCAP | states/ut/dwf/ccap/income/sources/unearned.yaml L34 |
| Virginia CCSP | states/va/dss/ccsp/income/countable_income/unearned_sources.yaml L6 |
| Wisconsin Shares | states/wi/dcf/shares/income/sources.yaml L35 |
| Wyoming child care | states/wy/dfs/ccap/income/countable_income/sources.yaml L20 |
Energy, health and tax relief
| Program | List, at the pension line |
|---|---|
| California CARE and FERA | states/ca/cpuc/income_sources.yaml L80, L122 |
| Los Angeles EZ-SAVE | local/ca/la/dwp/ez_save/income_sources.yaml L23 |
| Riverside County LIHEAP | local/ca/riv/cap/liheap/countable_income/sources.yaml L9 |
| Riverside County SHARE | local/ca/riv/cap/share/countable_income/sources.yaml L9 |
| Texas CEAP | states/tx/tdhca/ceap/income/sources.yaml L20 |
| Texas Family Planning Program | states/tx/fpp/income/sources/unearned.yaml L6 |
| Mississippi Working Disabled Medicaid | states/ms/dom/wd/eligibility/income/sources/unearned.yaml L4 |
| Denver property tax relief | local/co/denver/dhs/property_tax_relief/income_sources.yaml L10 |
Outside these benefit lists, the model also leaves the pay out of Michigan's household resources list, which it reads for the home heating credit and the homestead property tax credit. Michigan defines that income in MCL 206.510(1) as "the sum of federal adjusted gross income as defined in the internal revenue code plus all income specifically excluded or exempt".
Related work
- In Correct countable income for school meals #10873 we add
military_retirement_incometo the school meals list for The model counts educational assistance in school meal income, subtracts business losses and leaves out alimony, workers' compensation and other income USDA counts #10801. At its head, a590e46, we also move CSFP onto a newgov/usda/csfp/income/sources.yamland a Texas copy, and we listpension_incomethere withoutmilitary_retirement_income. - Since Wire military retirement pay and survivors into federal and state tax (#10181) #10182, the model counts military retired pay in gross income, market income, SNAP and SSI, and keeps it out of
pension_income. Since Count military SBP annuities in state benefit income lists #10317 and Count military retirement in KS, MS, NC, NJ and NY LIHEAP income #10409, it readsmilitary_retirement_incomein other state lists. - In Count railroad retirement benefits as income in state and county benefit programs #10764 we add
railroad_benefitsto 36 of the files in the table.
Possible fix
Add military_retirement_income beside pension_income in each list, as in the SNAP and SSI lists, after checking each state's rule for an exclusion. If the model folded it into pension_income, it would count the pay twice in market income and in the 75 benefit lists that already name both.
Reproduction
Script and output at 935b24f
from policyengine_us import Simulation
YEAR = 2026
JANUARY = f"{YEAR}-01"
STATES = (
"AL AK AZ AR CA CO CT DE DC FL GA HI ID IL IN IA KS KY LA ME MD MA MI MN MS MO "
"MT NE NV NH NJ NM NY NC ND OH OK OR PA RI SC SD TN TX UT VT VA WA WV WI WY"
).split()
SOURCES = ["military_retirement_pay", "taxable_private_pension_income"]
def simulate(households):
"""Each household is (state, {person: inputs}, SPM unit inputs)."""
s = {
key: {}
for key in [
"people",
"families",
"tax_units",
"spm_units",
"marital_units",
"households",
]
}
for i, (state, people, spm_inputs) in enumerate(households):
names = [f"{name}_{i}" for name in people]
for pid, inputs in zip(names, people.values()):
s["people"][pid] = {k: {YEAR: v} for k, v in inputs.items()}
adults = [pid for pid in names if s["people"][pid]["age"][YEAR] >= 18]
s["families"][f"family_{i}"] = {"members": names}
s["tax_units"][f"tax_unit_{i}"] = {"members": names}
s["spm_units"][f"spm_unit_{i}"] = {
"members": names,
**{k: {YEAR: v} for k, v in spm_inputs.items()},
}
s["marital_units"][f"marital_unit_{i}"] = {"members": adults}
for pid in names:
if pid not in adults:
s["marital_units"][f"marital_unit_{pid}"] = {"members": [pid]}
s["households"][f"household_{i}"] = {
"members": names,
"state_code": {YEAR: state},
}
return Simulation(situation=s)
# One household per income source: index 0 holds military retired pay and
# index 1 holds the same amount as a private pension.
print("WIC: Idaho parent aged 42 with $60,000 of retired pay, child aged 2")
sim = simulate(
[("ID", {"parent": {"age": 42, src: 60_000}, "child": {"age": 2}}, {}) for src in SOURCES]
)
income = sim.calculate("wic_countable_income", YEAR)
tanf = sim.calculate("tanf", YEAR)
limit = sim.calculate("wic_income_limit", JANUARY)
meets = sim.calculate("meets_wic_income_test", JANUARY)
categorical = sim.calculate("meets_wic_categorical_eligibility", JANUARY)
wic_january = sim.calculate("wic", JANUARY)
wic_year = sim.calculate("wic", YEAR)
for j, src in enumerate(SOURCES):
child = 2 * j + 1
print(
f" {src}: countable income {income[j]:,.0f} (of which TANF {tanf[j]:,.0f}), "
f"limit {limit[j]:,.0f}, "
f"meets income test {bool(meets[j])}, child categorically eligible "
f"{bool(categorical[child])}, child WIC {wic_january[child]:,.2f} in January "
f"and {wic_year[child]:,.2f} in {YEAR}"
)
print("HUD: Ohio tenant aged 50 with $30,000 of retired pay and $12,000 of rent, in assisted housing")
sim = simulate(
[
(
"OH",
{"tenant": {"age": 50, src: 30_000, "pre_subsidy_rent": 12_000}},
{"receives_housing_assistance": True},
)
for src in SOURCES
]
)
for variable in ["hud_annual_income", "hud_adjusted_income", "hud_ttp"]:
values = sim.calculate(variable, YEAR)
print(f" {variable}: " + ", ".join(f"{src} {v:,.2f}" for src, v in zip(SOURCES, values)))
print("Head Start: Ohio parent aged 30 with $60,000 of retired pay, child aged 4")
sim = simulate(
[("OH", {"parent": {"age": 30, src: 60_000}, "child": {"age": 4}}, {}) for src in SOURCES]
)
gross = sim.calculate("head_start_gross_income", YEAR)
fpg = sim.calculate("spm_unit_fpg", YEAR)
income_eligible = sim.calculate("is_head_start_income_eligible", YEAR)
eligible = sim.calculate("is_head_start_eligible", YEAR)
for j, src in enumerate(SOURCES):
child = 2 * j + 1
print(
f" {src}: gross income {gross[j]:,.0f}, poverty guideline {fpg[j]:,.0f}, "
f"child income eligible {bool(income_eligible[child])}, child eligible {bool(eligible[child])}"
)
print("North Dakota TANF: parent aged 40 with $24,000 of retired pay, child aged 8")
sim = simulate(
[("ND", {"parent": {"age": 40, src: 24_000}, "child": {"age": 8}}, {}) for src in SOURCES]
)
unearned = sim.calculate("nd_tanf_gross_unearned_income", JANUARY)
tanf = sim.calculate("nd_tanf", JANUARY)
for j, src in enumerate(SOURCES):
print(
f" {src}: parent's gross unearned income in January {unearned[2 * j]:,.2f}, "
f"TANF in January {tanf[j]:,.2f}"
)
print("CSFP: couple aged 67 and 65 with $30,000 of Social Security and $45,000 of retired pay")
for src in SOURCES:
sim = simulate(
[
(
state,
{
"head": {"age": 67, "social_security_retirement": 30_000, src: 45_000},
"spouse": {"age": 65},
},
{},
)
for state in STATES
]
)
csfp = sim.calculate("commodity_supplemental_food_program", YEAR)
ratio = sim.calculate("school_meal_fpg_ratio", YEAR)
countable = sim.calculate("school_meal_countable_income", YEAR)
oh = STATES.index("OH")
both = [state for k, state in enumerate(STATES) if csfp[2 * k] > 0 and csfp[2 * k + 1] > 0]
print(
f" {src}: Ohio countable income {countable[oh]:,.0f}, income-to-poverty ratio "
f"{ratio[oh]:.3f}, CSFP {csfp[2 * oh]:,.0f} and {csfp[2 * oh + 1]:,.0f}; "
f"both spouses get CSFP in {len(both)} of {len(STATES)} states; "
f"neither or one in {sorted(set(STATES) - set(both))}"
)WIC: Idaho parent aged 42 with $60,000 of retired pay, child aged 2
military_retirement_pay: countable income 3,708 (of which TANF 3,708), limit 39,128, meets income test True, child categorically eligible True, child WIC 59.80 in January and 723.73 in 2026
taxable_private_pension_income: countable income 60,000 (of which TANF 0), limit 39,128, meets income test False, child categorically eligible False, child WIC 0.00 in January and 0.00 in 2026
HUD: Ohio tenant aged 50 with $30,000 of retired pay and $12,000 of rent, in assisted housing
hud_annual_income: military_retirement_pay 0.00, taxable_private_pension_income 30,000.00
hud_adjusted_income: military_retirement_pay 0.00, taxable_private_pension_income 30,000.00
hud_ttp: military_retirement_pay 25.00, taxable_private_pension_income 9,000.00
Head Start: Ohio parent aged 30 with $60,000 of retired pay, child aged 4
military_retirement_pay: gross income 0, poverty guideline 21,640, child income eligible True, child eligible True
taxable_private_pension_income: gross income 60,000, poverty guideline 21,640, child income eligible False, child eligible False
North Dakota TANF: parent aged 40 with $24,000 of retired pay, child aged 8
military_retirement_pay: parent's gross unearned income in January 0.00, TANF in January 739.00
taxable_private_pension_income: parent's gross unearned income in January 2,000.00, TANF in January 0.00
CSFP: couple aged 67 and 65 with $30,000 of Social Security and $45,000 of retired pay
military_retirement_pay: Ohio countable income 30,000, income-to-poverty ratio 1.386, CSFP 651 and 651; both spouses get CSFP in 47 of 51 states; neither or one in ['IL', 'KS', 'MA', 'TX']
taxable_private_pension_income: Ohio countable income 75,000, income-to-poverty ratio 3.466, CSFP 0 and 0; both spouses get CSFP in 0 of 51 states; neither or one in ['AK', 'AL', 'AR', 'AZ', 'CA', 'CO', 'CT', 'DC', 'DE', 'FL', 'GA', 'HI', 'IA', 'ID', 'IL', 'IN', 'KS', 'KY', 'LA', 'MA', 'MD', 'ME', 'MI', 'MN', 'MO', 'MS', 'MT', 'NC', 'ND', 'NE', 'NH', 'NJ', 'NM', 'NV', 'NY', 'OH', 'OK', 'OR', 'PA', 'RI', 'SC', 'SD', 'TN', 'TX', 'UT', 'VA', 'VT', 'WA', 'WI', 'WV', 'WY']
Activity