From 2c4d13bef73aabc9835e90cb5290daea7f9252ee Mon Sep 17 00:00:00 2001 From: PavelMakarchuk Date: Fri, 23 Oct 2026 12:52:01 -0400 Subject: [PATCH 1/2] Count military retirement in KS, MS, NC, NJ and NY LIHEAP income The five LIHEAP unearned income lists named neither military retirement input, so a household whose only income was military retirement pay or a Survivor Benefit Plan annuity had $0 of countable income. Each program's rule counts retirement and pension benefits (state plan item 1.9) and its manual counts pensions and annuities with no exclusion for these payments, so add military_retirement_income to each list and test both inputs. Co-Authored-By: Claude Opus 5.5 --- ...ilitary-retirement-ks-ms-nc-nj-ny.fixed.md | 1 + .../dcf/liheap/income/sources/unearned.yaml | 8 +++++++ .../mdhs/liheap/unearned_income_sources.yaml | 7 ++++++ .../ncdhhs/lieap/unearned_income_sources.yaml | 7 ++++++ .../dca/liheap/income/sources/unearned.yaml | 9 ++++++++ .../ny/otda/heap/income/sources/unearned.yaml | 7 ++++++ .../income/ks_liheap_countable_income.yaml | 19 +++++++++++++++ .../ms/mdhs/liheap/ms_liheap_income.yaml | 15 ++++++++++++ .../nc/ncdhhs/lieap/nc_lieap_income.yaml | 23 +++++++++++++++++++ .../nj_liheap_countable_income_person.yaml | 21 +++++++++++++++++ .../heap/income/ny_heap_countable_income.yaml | 18 +++++++++++++++ 11 files changed, 135 insertions(+) create mode 100644 changelog.d/liheap-military-retirement-ks-ms-nc-nj-ny.fixed.md diff --git a/changelog.d/liheap-military-retirement-ks-ms-nc-nj-ny.fixed.md b/changelog.d/liheap-military-retirement-ks-ms-nc-nj-ny.fixed.md new file mode 100644 index 00000000000..02977cdde77 --- /dev/null +++ b/changelog.d/liheap-military-retirement-ks-ms-nc-nj-ny.fixed.md @@ -0,0 +1 @@ +Count military retirement pay and Survivor Benefit Plan annuities as unearned income in the Kansas, Mississippi, North Carolina, New Jersey and New York LIHEAP programs. diff --git a/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/unearned.yaml b/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/unearned.yaml index cee09cb98e1..743f086f04f 100644 --- a/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/unearned.yaml +++ b/policyengine_us/parameters/gov/states/ks/dcf/liheap/income/sources/unearned.yaml @@ -6,7 +6,15 @@ values: # SSA benefits are counted gross, including the Medicare deduction. - social_security - ssi + # Military retirement income (retiree pay plus Survivor Benefit Plan + # annuities) is a separate input from the pension inputs that + # pension_income adds, so both are listed; a household reports the amount + # in one or the other. A military survivor annuity belongs in + # military_retirement_pay_survivors, not survivor_benefits. Plan Section + # 1.9 counts retirement and pension benefits, and KEESM 13361 exempts + # neither. - pension_income + - military_retirement_income - general_assistance - ks_tanf - rental_income diff --git a/policyengine_us/parameters/gov/states/ms/mdhs/liheap/unearned_income_sources.yaml b/policyengine_us/parameters/gov/states/ms/mdhs/liheap/unearned_income_sources.yaml index 1fcef4033a0..527cdab40cc 100644 --- a/policyengine_us/parameters/gov/states/ms/mdhs/liheap/unearned_income_sources.yaml +++ b/policyengine_us/parameters/gov/states/ms/mdhs/liheap/unearned_income_sources.yaml @@ -6,7 +6,14 @@ values: # Rule 6.11 F(3) lists Railroad Retirement benefits. - railroad_benefits - ssi + # Military retirement income (retiree pay plus Survivor Benefit Plan + # annuities) is a separate input from the pension inputs that + # pension_income adds, so both are listed; a household reports the amount + # in one or the other. A military survivor annuity belongs in + # military_retirement_pay_survivors, not survivor_benefits. Rule 6.11 C(8) + # counts retirement benefits and F(2)-(3) count pensions and annuities. - pension_income + - military_retirement_income - retirement_distributions - alimony_income - veterans_benefits diff --git a/policyengine_us/parameters/gov/states/nc/ncdhhs/lieap/unearned_income_sources.yaml b/policyengine_us/parameters/gov/states/nc/ncdhhs/lieap/unearned_income_sources.yaml index b8d1855be8d..2be2907868d 100644 --- a/policyengine_us/parameters/gov/states/nc/ncdhhs/lieap/unearned_income_sources.yaml +++ b/policyengine_us/parameters/gov/states/nc/ncdhhs/lieap/unearned_income_sources.yaml @@ -20,6 +20,13 @@ values: - pension_income # "Retirement Benefits" (page 18). - retirement_distributions + # "Retirement Benefits" (page 18) covers plans set up by the government, + # with "Pensions" (page 16) and "Annuities" (page 3). Military retirement + # income (retiree pay plus Survivor Benefit Plan annuities) is a separate + # input from the pension inputs that pension_income adds; a household + # reports the amount in one or the other. A military survivor annuity + # belongs in military_retirement_pay_survivors, not survivor_benefits. + - military_retirement_income # "Annuities" (page 3) and "Pensions" (page 16): survivor benefits other # than Social Security. - survivor_benefits diff --git a/policyengine_us/parameters/gov/states/nj/dca/liheap/income/sources/unearned.yaml b/policyengine_us/parameters/gov/states/nj/dca/liheap/income/sources/unearned.yaml index 785f8560178..368a146692a 100644 --- a/policyengine_us/parameters/gov/states/nj/dca/liheap/income/sources/unearned.yaml +++ b/policyengine_us/parameters/gov/states/nj/dca/liheap/income/sources/unearned.yaml @@ -9,6 +9,15 @@ values: - strike_benefits - ssi - pension_income + # Military retirement income (retiree pay plus Survivor Benefit Plan + # annuities) is a separate input from the pension inputs that pension_income + # adds; a household reports the amount in one or the other. Handbook 2.3.D + # counts pensions and annuities. The Department of Defense, not the VA, pays + # both, and plan 1.9 (page 7) names the excluded veterans' item "Veterans + # Administration (VA) benefits", so 2.3.E.10 does not reach them. A military + # survivor annuity belongs in military_retirement_pay_survivors, not + # survivor_benefits. + - military_retirement_income # Handbook 2.3.D counts pensions and annuities; 2.3.E.10 excludes veterans' # benefits, but VA survivor payments cannot be separated and count here. - survivor_benefits diff --git a/policyengine_us/parameters/gov/states/ny/otda/heap/income/sources/unearned.yaml b/policyengine_us/parameters/gov/states/ny/otda/heap/income/sources/unearned.yaml index 0750ab33c66..001a7047e37 100644 --- a/policyengine_us/parameters/gov/states/ny/otda/heap/income/sources/unearned.yaml +++ b/policyengine_us/parameters/gov/states/ny/otda/heap/income/sources/unearned.yaml @@ -14,6 +14,13 @@ values: # insurance and annuities; veterans' survivor benefits under D.12(a)(12). - survivor_benefits - pension_income + # Military retirement income (retiree pay plus Survivor Benefit Plan + # annuities) is a separate input from the pension inputs that pension_income + # adds; a household reports the amount in one or the other. D.12(a)(13) + # counts pensions and (14) annuities, and D.13 excludes neither. A military + # survivor annuity belongs in military_retirement_pay_survivors, not + # survivor_benefits. + - military_retirement_income - retirement_distributions - alimony_income - child_support_received diff --git a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_income.yaml index e297250172a..fbe4cebd86c 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ks/dcf/liheap/income/ks_liheap_countable_income.yaml @@ -267,3 +267,22 @@ ks_liheap_countable_unearned_income: 6_000 # 0 earned income + 6,000 unearned income = 6,000. ks_liheap_countable_income: 6_000 + +- name: Case 12, military retirement pay and a Survivor Benefit Plan annuity are counted as unearned income. + # Two one-person households aged 70. Plan Section 1.9 counts retirement and + # pension benefits; KEESM 13360 counts "most other income" and 13361 exempts + # neither. Household 1: 24,000 military retirement pay. Household 2: 9,600 + # Survivor Benefit Plan annuity (800 a month). + period: 2026 + absolute_error_margin: 0.01 + input: + state_code: [KS, KS] + age: [70, 70] + military_retirement_pay: [24_000, 0] + military_retirement_pay_survivors: [0, 9_600] + ssi: [0, 0] + ks_tanf: [0, 0] + output: + ks_liheap_countable_unearned_income: [24_000, 9_600] + # 0 earned income + unearned income. + ks_liheap_countable_income: [24_000, 9_600] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ms/mdhs/liheap/ms_liheap_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ms/mdhs/liheap/ms_liheap_income.yaml index a2323f7e1c9..277ce225676 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ms/mdhs/liheap/ms_liheap_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ms/mdhs/liheap/ms_liheap_income.yaml @@ -229,3 +229,18 @@ output: total_unemployment_compensation: 6_000 ms_liheap_income: 6_000 + +- name: Case 10, military retirement pay and a Survivor Benefit Plan annuity count as unearned income. + # Two one-person households aged 70. Rule 6.11 C(8) (manual PDF page 29) + # counts retirement benefits and F(2)-(3) (page 31) count pensions and + # annuities. Household 1: 24,000 military retirement pay. Household 2: 9,600 + # Survivor Benefit Plan annuity (800 a month). + period: 2026 + input: + state_code: [MS, MS] + age: [70, 70] + military_retirement_pay: [24_000, 0] + military_retirement_pay_survivors: [0, 9_600] + ssi: [0, 0] + output: + ms_liheap_income: [24_000, 9_600] diff --git a/policyengine_us/tests/policy/baseline/gov/states/nc/ncdhhs/lieap/nc_lieap_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/nc/ncdhhs/lieap/nc_lieap_income.yaml index 690b146bbb4..5979e8211bb 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nc/ncdhhs/lieap/nc_lieap_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nc/ncdhhs/lieap/nc_lieap_income.yaml @@ -342,3 +342,26 @@ # "Unemployment" (FNS 300.02 chart, page 24) has no work deduction. nc_lieap_gross_income_person: 6_000 absolute_error_margin: 0.01 + +- name: Case 14, military retirement pay and a Survivor Benefit Plan annuity count as unearned income. + # Two one-person households aged 70. FNS 300.02 chart rows "Pensions" (page + # 16), "Retirement Benefits" (page 18) and "Annuities" (page 3) are + # unearned income. Household 1: 24,000 military retirement pay. Household 2: + # 9,600 Survivor Benefit Plan annuity (800 a month). + period: 2026 + input: + state_code: [NC, NC] + age: [70, 70] + military_retirement_pay: [24_000, 0] + military_retirement_pay_survivors: [0, 9_600] + ssi: [0, 0] + social_security: [0, 0] + tanf: [0, 0] + childcare_expenses: [0, 0] + output: + nc_lieap_earned_income: [0, 0] + nc_lieap_gross_income_person: [24_000, 9_600] + # EP-300.09 B.3 (page 13): an $85 monthly medical deduction at age 60 or + # older, 85 * 12 = 1,020. 24,000 - 1,020 = 22,980; 9,600 - 1,020 = 8,580. + nc_lieap_income: [22_980, 8_580] + absolute_error_margin: 0.01 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/dca/liheap/income/nj_liheap_countable_income_person.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/dca/liheap/income/nj_liheap_countable_income_person.yaml index 8e50492f0f5..83f0b3a17e0 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nj/dca/liheap/income/nj_liheap_countable_income_person.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/dca/liheap/income/nj_liheap_countable_income_person.yaml @@ -210,3 +210,24 @@ output: total_unemployment_compensation: 6_000 nj_liheap_countable_income_person: 6_000 + +- name: Case 9, military retirement pay and a Survivor Benefit Plan annuity count as unearned income. + # Two one-person households aged 70. Handbook 2.3.D (page 8) counts pensions + # and annuities; the Department of Defense pays both, so the 2.3.E.10 + # veterans' benefits exclusion does not apply. Household 1: 24,000 military + # retirement pay. Household 2: 9,600 Survivor Benefit Plan annuity (800 a + # month). + period: 2026 + absolute_error_margin: 0.01 + input: + state_code: [NJ, NJ] + age: [70, 70] + military_retirement_pay: [24_000, 0] + military_retirement_pay_survivors: [0, 9_600] + social_security: [0, 0] + ssi: [0, 0] + tanf: [0, 0] + output: + nj_liheap_countable_income_person: [24_000, 9_600] + # 2,000 and 800 a month are whole dollars, so rounding changes nothing. + nj_liheap_countable_income: [24_000, 9_600] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ny/otda/heap/income/ny_heap_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ny/otda/heap/income/ny_heap_countable_income.yaml index 46fbe0227e8..451c622d78e 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ny/otda/heap/income/ny_heap_countable_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ny/otda/heap/income/ny_heap_countable_income.yaml @@ -186,3 +186,21 @@ output: total_unemployment_compensation: 7_982 ny_heap_countable_income: 7_980 + +- name: Case 8, military retirement pay and a Survivor Benefit Plan annuity count as unearned income. + # Two one-person households aged 70. Chapter 8 D.12(a)(13) pensions and (14) + # payments from annuities (page 38); D.13 excludes neither. Household 1: + # 24,000 military retirement pay. Household 2: 9,600 Survivor Benefit Plan + # annuity (800 a month). + period: 2026 + absolute_error_margin: 0.01 + input: + state_code: [NY, NY] + age: [70, 70] + military_retirement_pay: [24_000, 0] + military_retirement_pay_survivors: [0, 9_600] + ssi: [0, 0] + output: + # D.14(c): floor(24,000 / 12) = 2,000 and floor(9,600 / 12) = 800 a month, + # annualized 24,000 and 9,600. + ny_heap_countable_income: [24_000, 9_600] From ebccea124b6742f24e7fcfd305167b03668b6a31 Mon Sep 17 00:00:00 2001 From: PavelMakarchuk Date: Fri, 23 Oct 2026 15:38:03 -0400 Subject: [PATCH 2/2] Cite EP-300.09 B.4 for the NC medical deduction in the new test Co-Authored-By: Claude Opus 5.5 --- .../baseline/gov/states/nc/ncdhhs/lieap/nc_lieap_income.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/policyengine_us/tests/policy/baseline/gov/states/nc/ncdhhs/lieap/nc_lieap_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/nc/ncdhhs/lieap/nc_lieap_income.yaml index 5979e8211bb..c3ba16862cf 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nc/ncdhhs/lieap/nc_lieap_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nc/ncdhhs/lieap/nc_lieap_income.yaml @@ -361,7 +361,7 @@ output: nc_lieap_earned_income: [0, 0] nc_lieap_gross_income_person: [24_000, 9_600] - # EP-300.09 B.3 (page 13): an $85 monthly medical deduction at age 60 or + # EP-300.09 B.4 (page 13): an $85 monthly medical deduction at age 60 or # older, 85 * 12 = 1,020. 24,000 - 1,020 = 22,980; 9,600 - 1,020 = 8,580. nc_lieap_income: [22_980, 8_580] absolute_error_margin: 0.01