From 449696c1c57770f0bf6b4fca8f59242e0d3c4d74 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Mon, 12 Oct 2026 06:02:12 -0400 Subject: [PATCH 01/11] Count SSI, TANF and workers' compensation in Montana's elderly credit income MCA 15-30-2337(9)(a) counts all nontaxable income, including (vi) cash public assistance and relief. Schedule 2EC line 16 (2024, 2025) names SSI and workers' compensation, and the 2014-2023 instructions list SSI payments and workers' compensation as disability benefits. Add ssi, tanf_person (the SPM unit's TANF per capita, so the household sum counts it once) and workers_compensation to every period of the gross income sources, with worked Schedule 2EC / Form 2EC cases for 2016-2025. Co-Authored-By: Claude Opus 5.5 --- ...erly-credit-government-assistance.fixed.md | 1 + .../gross_income_sources.yaml | 31 ++ ...r_renter_credit_government_assistance.yaml | 282 ++++++++++++++++++ 3 files changed, 314 insertions(+) create mode 100644 changelog.d/mt-elderly-credit-government-assistance.fixed.md create mode 100644 policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_government_assistance.yaml diff --git a/changelog.d/mt-elderly-credit-government-assistance.fixed.md b/changelog.d/mt-elderly-credit-government-assistance.fixed.md new file mode 100644 index 00000000000..27b553487f9 --- /dev/null +++ b/changelog.d/mt-elderly-credit-government-assistance.fixed.md @@ -0,0 +1 @@ +Montana's elderly homeowner/renter credit now counts SSI, TANF and workers' compensation received by household members in gross household income (MCA 15-30-2337(9)(a)(vi); Schedule 2EC line 16). diff --git a/policyengine_us/parameters/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/gross_income_sources.yaml b/policyengine_us/parameters/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/gross_income_sources.yaml index 7c3c2184cdf..61a193e098d 100644 --- a/policyengine_us/parameters/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/gross_income_sources.yaml +++ b/policyengine_us/parameters/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/gross_income_sources.yaml @@ -26,6 +26,22 @@ metadata: href: https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2024_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=47 - title: 2025 Montana Form 2 instructions, Schedule 2EC, line 8, refundable credits received href: https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2025_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=45 + - title: MCA 15-30-2337(9)(a)(vi), cash public assistance and relief + href: https://mca.legmt.gov/bills/mca/title_0150/chapter_0300/part_0230/section_0370/0150-0300-0230-0370.html + - title: MCA 15-30-2337(9)(a)(vi) as in effect in 2016 (archived) + href: https://web.archive.org/web/20161231130526/http://leg.mt.gov/bills/mca/title_0150/chapter_0300/part_0230/section_0370/0150-0300-0230-0370.html + - title: 2016 Montana Form 2EC instructions, Part II, disability benefits including SSI payments and workers' compensation, and cash public assistance and relief + href: https://taxsim.nber.org/historical_state_tax_forms/MT/2016/Form_2_booklet_2016.pdf#page=74 + - title: 2017 Montana Form 2EC instructions, Part II, disability benefits including SSI payments and workers' compensation, and cash public assistance and relief + href: https://taxsim.nber.org/historical_state_tax_forms/MT/2017/Form%202%202017%20Booklet.pdf#page=64 + - title: 2022 Montana Form 2 instructions, Elderly Homeowner/Renter Credit Schedule, line 8, disability benefits including SSI payments and workers' compensation + href: https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2022_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=48 + - title: 2023 Montana Form 2 instructions, Elderly Homeowner/Renter Credit Schedule, line 8, disability benefits including SSI payments and workers' compensation + href: https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2023_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=52 + - title: 2024 Montana Form 2 instructions, Schedule 2EC, line 16, government assistance + href: https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2024_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=48 + - title: 2025 Montana Form 2 instructions, Schedule 2EC, line 16, government assistance + href: https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2025_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=46 values: 2009-01-01: @@ -43,6 +59,15 @@ values: - child_support_received # § 15-30-2337(9)(a)(iv) – support money - strike_benefits # § 15-30-2337(9)(a)(v) – nontaxable strike benefits - general_assistance # § 15-30-2337(9)(a)(vi) – cash public assistance + # Government assistance (Schedule 2EC line 16 from 2024; "disability + # benefits including ... SSI payments and workers' compensation" and + # "cash public assistance and relief" in earlier instructions). TANF is + # held for the SPM unit; tanf_person is each member's per capita share, + # so the household sum counts the unit's TANF once. LIEAP and SNAP are + # not cash public assistance (2014-2017 Form 2EC instructions). + - ssi + - tanf_person + - workers_compensation # Refundable credits received (2023 schedule line 7, Schedule 2EC line 8 # from 2024): Montana's refundable credits other than this credit, # and this credit as received during the year (ARM 42.4.301(2)(c)). @@ -60,6 +85,9 @@ values: - child_support_received - strike_benefits - general_assistance + - ssi + - tanf_person + - workers_compensation - mt_refundable_credits_before_renter_credit - mt_elderly_homeowner_or_renter_credit_received - mt_elderly_homeowner_or_renter_credit_federal_refundable_credits @@ -76,6 +104,9 @@ values: - child_support_received - strike_benefits - general_assistance + - ssi + - tanf_person + - workers_compensation - mt_refundable_credits_before_renter_credit - mt_elderly_homeowner_or_renter_credit_received - mt_elderly_homeowner_or_renter_credit_federal_refundable_credits diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_government_assistance.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_government_assistance.yaml new file mode 100644 index 00000000000..82bc6942c0f --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_government_assistance.yaml @@ -0,0 +1,282 @@ +# Government assistance in gross household income: SSI, TANF and workers' +# compensation. § 15-30-2337(9)(a) counts "all nontaxable income, including +# but not limited to ... (vi) cash public assistance and relief". 2024 and +# 2025 Schedule 2EC line 16: "This includes veteran's compensation benefits, +# supplemental security income (SSI) payments, worker's compensation, and any +# other government assistance received during the year." The 2014-2023 +# instructions list "Disability benefits including, but not limited to, +# veteran's disability, SSI payments and workers' compensation", and the +# 2014-2017 instructions add "Cash public assistance and relief - Do not +# include LIEAP ... or SNAP". + +- name: 2024 Schedule 2EC worked case, the claimant's SSI counts on line 16 + period: 2024 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + taxable_pension_income: 15_000 + ssi: 6_000 + real_estate_taxes: 1_200 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_name: MT + output: + # Line 5 pensions 15_000; line 16 SSI 6_000; line 18 = 21_000. + mt_elderly_homeowner_or_renter_credit_gross_household_income: 21_000 + # Line 19 12_600; line 20 = 8_400; line 21 = 0.039 (8_000 to 8_999); + # line 22 = 8_400 x 0.039 = 327.60. + mt_elderly_homeowner_or_renter_credit_net_household_income: 327.60 + # Line 23 = 1_200; line 26 = 1_200; line 27 = 1_200 - 327.60 = 872.40; + # line 28 = 872.40 (under 1_150); line 29 = 100%; line 30 = 872.40. + # Without the SSI, line 18 = 15_000, line 22 = 2_400 x 0.006 = 14.40 and + # the credit would be the 1_150 cap. + mt_elderly_homeowner_or_renter_credit: 872.40 + +- name: 2025 Schedule 2EC worked case, a household member's workers' compensation counts on line 17 + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 72 + taxable_pension_income: 18_000 + real_estate_taxes: 1_500 + person2: + age: 45 + workers_compensation: 9_000 + tax_units: + tax_unit1: + members: [person1] + tax_unit2: + members: [person2] + households: + household: + members: [person1, person2] + state_name: MT + output: + # The claimant's adult son lives in the household and files his own + # return. Line 5 pensions 18_000; line 17 his workers' compensation, a + # line 16 item for another member, 9_000; line 18 = 27_000. + mt_elderly_homeowner_or_renter_credit_gross_household_income: [18_000, 9_000] + # Line 20 = 27_000 - 12_600 = 14_400; line 21 = 0.05; line 22 = 720. + mt_elderly_homeowner_or_renter_credit_net_household_income: [720, 0] + # Line 27 = 1_500 - 720 = 780; line 28 = 780; line 29 = 100%; line 30 = + # 780. Without his workers' compensation, line 18 = 18_000, line 22 = + # 5_400 x 0.028 = 151.20 and the credit would be the 1_150 cap. + mt_elderly_homeowner_or_renter_credit: [780, 0] + +- name: 2024 Schedule 2EC worked case, TANF in a shared SPM unit counts once across two returns + period: 2024 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + taxable_pension_income: 20_000 + real_estate_taxes: 1_500 + person2: + age: 30 + person3: + age: 5 + tax_units: + tax_unit1: + members: [person1] + tax_unit2: + members: [person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + tanf: 4_800 + households: + household: + members: [person1, person2, person3] + state_name: MT + output: + # The claimant's daughter and granddaughter live with her; the daughter + # files her own return and receives 4_800 of TANF. Line 5 pensions + # 20_000; line 17 the TANF 4_800; line 18 = 24_800. The model holds TANF + # for the SPM unit and counts each member's per capita share + # (tanf_person, 1_600 each), so the household total counts it once. + mt_elderly_homeowner_or_renter_credit_gross_household_income: [21_600, 1_600, 1_600] + # Line 20 = 24_800 - 12_600 = 12_200; line 21 = 0.05; line 22 = 610. + mt_elderly_homeowner_or_renter_credit_net_household_income: [610, 0, 0] + # Line 27 = 1_500 - 610 = 890; line 28 = 890; line 29 = 100%; line 30 = + # 890. Without the TANF, line 18 = 20_000, line 22 = 7_400 x 0.035 = 259 + # and the credit would be the 1_150 cap. Counting the whole 4_800 for + # each of the three members would give line 18 = 34_400 and a credit of + # 1_500 - 1_090 = 410. + mt_elderly_homeowner_or_renter_credit: [890, 0, 0] + +- name: 2024 Schedule 2EC worked case, Montana TANF paid to a separate SPM unit counts on line 17 + period: 2024 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + taxable_pension_income: 20_000 + real_estate_taxes: 1_500 + person2: + age: 30 + person3: + age: 5 + tax_units: + tax_unit1: + members: [person1] + tax_unit2: + members: [person2, person3] + spm_units: + spm_unit1: + members: [person1] + spm_unit2: + members: [person2, person3] + mt_tanf: 4_800 + households: + household: + members: [person1, person2, person3] + state_name: MT + output: + # The same household with the daughter's family in its own SPM unit and + # the payment entered as Montana TANF (ARM 37.78), which tanf sums with + # the other states' programs. Line 17 = 4_800; line 18 = 24_800. + tanf: [0, 4_800] + mt_elderly_homeowner_or_renter_credit_gross_household_income: [20_000, 2_400, 2_400] + # Line 22 = (24_800 - 12_600) x 0.05 = 610; line 27 = 890; line 30 = 890. + mt_elderly_homeowner_or_renter_credit_net_household_income: [610, 0, 0] + mt_elderly_homeowner_or_renter_credit: [890, 0, 0] + +- name: 2023 Elderly Homeowner/Renter Credit Schedule worked case, workers' compensation and a spouse's SSI count on line 8 + period: 2023 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 66 + taxable_pension_income: 14_000 + workers_compensation: 6_000 + real_estate_taxes: 1_000 + person2: + age: 64 + ssi: 5_000 + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_name: MT + output: + # Joint return. Line 1 federal AGI 14_000; line 8 "Disability benefits + # including, but not limited to, veteran's disability, SSI payments, and + # workers' compensation": 6_000 + 5_000 = 11_000; line 10 = 25_000. + mt_elderly_homeowner_or_renter_credit_gross_household_income: [20_000, 5_000] + # Line 11 12_600; line 12 = 12_400; line 13 = 0.05; line 14 = 620. + mt_elderly_homeowner_or_renter_credit_net_household_income: [620, 0] + # Line 15 = 1_000; line 18 = 1_000; line 19 = 1_000 - 620 = 380; line 20 + # = 380; line 21 = 100%; line 22 = 380. Without either amount, line 10 = + # 14_000, line 12 = 1_400 at a 0 rate and the credit would be 1_000. + mt_elderly_homeowner_or_renter_credit: [380, 0] + +- name: 2017 Form 2EC worked case, a household member's SSI counts in gross household income + period: 2017 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + taxable_pension_income: 15_000 + real_estate_taxes: 1_000 + person2: + age: 40 + # 2017 federal benefit rate: 735 a month. + ssi: 8_820 + tax_units: + tax_unit1: + members: [person1] + tax_unit2: + members: [person2] + households: + household: + members: [person1, person2] + state_name: MT + output: + # The claimant's adult son receives SSI. Gross Household Income + # Worksheet: line 6 pensions 15_000; line 7 income of other household + # members, his SSI 8_820 ("Disability benefits including ... SSI + # payments"); line 8 = 23_820, Form 2EC line 1. + mt_elderly_homeowner_or_renter_credit_gross_household_income: [15_000, 8_820] + # Line 2 6_300; line 3 = 17_520; line 4 = 0.05; line 5 = 876. + mt_elderly_homeowner_or_renter_credit_net_household_income: [876, 0] + # Line 6 = 1_000; line 9 = 1_000; line 10 = 1_000 - 876 = 124; line 11 = + # 124 (under 1_000); line 12 = 100%; line 13 = 124. Without his SSI, line + # 1 = 15_000, line 5 = 8_700 x 0.039 = 339.30 and the credit 660.70. + mt_elderly_homeowner_or_renter_credit: [124, 0] + +- name: 2016 Form 2EC worked case, cash public assistance received by another household member counts + period: 2016 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + taxable_pension_income: 12_000 + real_estate_taxes: 900 + person2: + age: 30 + person3: + age: 5 + tax_units: + tax_unit1: + members: [person1] + tax_unit2: + members: [person2, person3] + spm_units: + spm_unit1: + members: [person1] + spm_unit2: + members: [person2, person3] + tanf: 5_400 + households: + household: + members: [person1, person2, person3] + state_name: MT + output: + # Gross Household Income Worksheet line 7, "Alimony, cash public + # assistance, unemployment", for the daughter's 5_400 of TANF; line 9 = + # 12_000 + 5_400 = 17_400, Form 2EC line 1. + mt_elderly_homeowner_or_renter_credit_gross_household_income: [12_000, 2_700, 2_700] + # Line 2 6_300; line 3 = 11_100; line 4 = 0.048; line 5 = 532.80. + mt_elderly_homeowner_or_renter_credit_net_household_income: [532.80, 0, 0] + # Line 6 = 900; line 10 = 900 - 532.80 = 367.20; line 11 = 367.20; line + # 12 = 100%; line 13 = 367.20. Without the TANF, line 1 = 12_000, line 5 + # = 5_700 x 0.028 = 159.60 and the credit 740.40. + mt_elderly_homeowner_or_renter_credit: [367.20, 0, 0] + +- name: SNAP is not cash public assistance and does not count + period: 2017 + input: + people: + person1: + age: 70 + taxable_pension_income: 15_000 + spm_units: + spm_unit: + members: [person1] + snap: 1_800 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_name: MT + output: + # 2017 Form 2EC instructions: "Cash, public assistance and relief - Do + # not include LIEAP (Low Income Energy Assistance Program) or SNAP". + mt_elderly_homeowner_or_renter_credit_gross_household_income: 15_000 From 50786d8acade21d20adeddc445c45747222309d5 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Mon, 12 Oct 2026 06:09:21 -0400 Subject: [PATCH 02/11] Add property tests for government assistance in Montana's elderly credit For a claimant, another adult and a child in four arrangements (one return or two, one SPM unit or two, and more assistance), gross household income adds every member's SSI and workers' compensation and the TANF once; the credit matches an independent reading of Schedule 2EC lines 18 to 30, does not depend on the arrangement, stays within the cap and never rises with more assistance. Co-Authored-By: Claude Opus 5.5 --- ...mt_elderly_credit_government_assistance.py | 307 ++++++++++++++++++ 1 file changed, 307 insertions(+) create mode 100644 policyengine_us/tests/test_mt_elderly_credit_government_assistance.py diff --git a/policyengine_us/tests/test_mt_elderly_credit_government_assistance.py b/policyengine_us/tests/test_mt_elderly_credit_government_assistance.py new file mode 100644 index 00000000000..6a366428122 --- /dev/null +++ b/policyengine_us/tests/test_mt_elderly_credit_government_assistance.py @@ -0,0 +1,307 @@ +"""Property tests: government assistance in the Montana elderly +homeowner/renter credit. + +MCA 15-30-2337(9)(a) counts "all nontaxable income, including but not +limited to ... (vi) cash public assistance and relief", and (4) counts "all +income received by all individuals of a household". The 2024 Schedule 2EC +line 16 names "supplemental security income (SSI) payments, worker's +compensation, and any other government assistance"; line 17 carries the same +items for the other members of the household. + +The model holds SSI and workers' compensation per person and TANF per SPM +unit, which it spreads over the unit's members (tanf_person). For a claimant +aged 62 or older (taxable pension, SSI, workers' compensation, property tax, +rent) living with another adult (SSI, workers' compensation) and a child, +whose SPM unit receives TANF, in four arrangements: + + A. one return, the other adult and the child the claimant's dependents, and + one SPM unit; + B. two returns (the claimant's, and the other adult's with the child) and + one SPM unit; + C. two returns and two SPM units, the TANF going to the other adult's; + D. as C, with more of one kind of assistance; + +1. The household's gross household income is the pension plus every + member's SSI and workers' compensation plus the TANF, once, in A, B and C. +2. So the claimant's credit is the same in A, B and C, and nobody else + claims. +3. The credit equals an independent reading of Schedule 2EC lines 18 to 30, + is between zero and the cap, and is zero at $45,000 or more (line 29). +4. More assistance never raises the credit (D against C). + +No one has earned income, so no refundable credit enters line 8. The model +computes in single precision, so comparisons allow one cent or eight float32 +spacings at the household's total income, whichever is larger. +""" + +import numpy as np +import pytest + +from policyengine_us import Simulation + +YEAR = 2024 +CAP = 1_150 +INCOME_LIMIT = 45_000 +TOLERANCE = 0.01 +ARRANGEMENTS = "ABCD" +# 2024 Schedule 2EC, line 19. +EXCLUSION = 12_600 +# Household Income Reduction Table (line 21): lower bounds and rates. +REDUCTION_TABLE = [ + (0, 0), + (2_000, 0.006), + (3_000, 0.016), + (4_000, 0.024), + (5_000, 0.028), + (6_000, 0.032), + (7_000, 0.035), + (8_000, 0.039), + (9_000, 0.042), + (10_000, 0.045), + (11_000, 0.048), + (12_000, 0.05), +] +# Credit Multiplier Table (line 29): lower bounds of line 18 and percentages. +MULTIPLIER_TABLE = [ + (0, 1), + (35_000, 0.4), + (37_501, 0.3), + (40_001, 0.2), + (42_501, 0.1), + (45_000, 0), +] +EXTRA_KINDS = ["claimant_ssi", "member_workers_compensation", "tanf"] + + +def amounts(c, arrangement): + """The case's assistance amounts, with D's extra amount added.""" + a = { + "claimant_ssi": c["claimant_ssi"], + "claimant_workers_compensation": c["claimant_workers_compensation"], + "member_ssi": c["member_ssi"], + "member_workers_compensation": c["member_workers_compensation"], + "tanf": c["tanf"], + } + if arrangement == "D": + a[c["extra_kind"]] += c["extra"] + return a + + +def build_situation(cases): + people, tax_units, marital_units, spm_units, families, households = ( + {}, + {}, + {}, + {}, + {}, + {}, + ) + for i, c in enumerate(cases): + for arrangement in ARRANGEMENTS: + key = f"{arrangement}{i}" + a = amounts(c, arrangement) + claimant, member, child = ( + f"claimant_{key}", + f"member_{key}", + f"child_{key}", + ) + people[claimant] = { + "age": {YEAR: c["claimant_age"]}, + "taxable_pension_income": {YEAR: c["pension"]}, + "ssi": {YEAR: a["claimant_ssi"]}, + "workers_compensation": {YEAR: a["claimant_workers_compensation"]}, + "real_estate_taxes": {YEAR: c["property_tax"]}, + "rent": {YEAR: c["rent"]}, + "is_tax_unit_dependent": {YEAR: False}, + } + people[member] = { + "age": {YEAR: c["member_age"]}, + "ssi": {YEAR: a["member_ssi"]}, + "workers_compensation": {YEAR: a["member_workers_compensation"]}, + "is_tax_unit_dependent": {YEAR: arrangement == "A"}, + } + people[child] = { + "age": {YEAR: c["child_age"]}, + "is_tax_unit_dependent": {YEAR: True}, + } + if arrangement == "A": + tax_units[f"tax_unit_{key}"] = {"members": [claimant, member, child]} + else: + tax_units[f"tax_unit_{key}"] = {"members": [claimant]} + tax_units[f"tax_unit_{key}_member"] = {"members": [member, child]} + if arrangement in "AB": + spm_units[f"spm_unit_{key}"] = { + "members": [claimant, member, child], + "tanf": {YEAR: a["tanf"]}, + } + else: + spm_units[f"spm_unit_{key}"] = { + "members": [claimant], + "tanf": {YEAR: 0}, + } + spm_units[f"spm_unit_{key}_member"] = { + "members": [member, child], + "tanf": {YEAR: a["tanf"]}, + } + for person in (claimant, member, child): + marital_units[f"marital_unit_{person}"] = {"members": [person]} + families[f"family_{key}"] = {"members": [claimant, member, child]} + households[f"household_{key}"] = { + "members": [claimant, member, child], + "state_code": {YEAR: "MT"}, + } + return { + "people": people, + "tax_units": tax_units, + "marital_units": marital_units, + "spm_units": spm_units, + "families": families, + "households": households, + } + + +def calculate(cases): + """Household totals of gross household income and the credit, and the + other members' credits, as arrays indexed [arrangement, case].""" + simulation = Simulation(situation=build_situation(cases)) + n, k = len(cases), len(ARRANGEMENTS) + + def by_household(variable): + values = simulation.calculate(variable, YEAR, map_to="household") + return np.asarray(values).reshape(n, k).T + + person_credit = np.asarray( + simulation.calculate("mt_elderly_homeowner_or_renter_credit", YEAR) + ).reshape(n, k, 3) + return { + "gross_household_income": by_household( + "mt_elderly_homeowner_or_renter_credit_gross_household_income" + ), + "credit": by_household("mt_elderly_homeowner_or_renter_credit"), + # The other adult's and the child's credits. + "others_credit": person_credit[:, :, 1:].transpose(1, 0, 2), + } + + +def expected_gross_household_income(c, arrangement): + """2024 Schedule 2EC line 18: line 5 pension and line 16 assistance for + the claimant, line 17 the other members' assistance, the TANF once.""" + return c["pension"] + sum(amounts(c, arrangement).values()) + + +def lookup(table, amount): + rate = 0 + for lower, value in table: + if amount >= lower: + rate = value + return rate + + +def expected_credit(c, gross_household_income): + """2024 Schedule 2EC lines 19 to 30 for a claimant who owns or rents.""" + line_20 = max(gross_household_income - EXCLUSION, 0) + line_22 = line_20 * lookup(REDUCTION_TABLE, line_20) + line_26 = c["property_tax"] + 0.15 * c["rent"] + line_27 = max(line_26 - line_22, 0) + line_28 = min(line_27, CAP) + return line_28 * lookup(MULTIPLIER_TABLE, gross_household_income) + + +def tolerance(amount): + return max(TOLERANCE, 8 * float(np.spacing(np.float32(abs(amount))))) + + +def assert_properties(cases): + result = calculate(cases) + ghi, credit = result["gross_household_income"], result["credit"] + for i, c in enumerate(cases): + for j, arrangement in enumerate(ARRANGEMENTS): + expected = expected_gross_household_income(c, arrangement) + tol = tolerance(expected) + # 1. Every member's assistance counts, the TANF once. + assert ghi[j, i] == pytest.approx(expected, abs=tol), (arrangement, c) + # 3. The schedule, the bounds and the income limit. + assert credit[j, i] == pytest.approx( + expected_credit(c, expected), abs=tol + ), (arrangement, c) + assert -tol <= credit[j, i] <= CAP + tol, (arrangement, c) + if expected >= INCOME_LIMIT: + assert credit[j, i] == 0, (arrangement, c) + # 2. The arrangement does not change the credit, and only the + # claimant claims. + tol = tolerance(expected_gross_household_income(c, "D")) + assert credit[1, i] == pytest.approx(credit[0, i], abs=tol), c + assert credit[2, i] == pytest.approx(credit[0, i], abs=tol), c + assert np.all(result["others_credit"][:, i] == 0), c + # 4. More assistance never raises the credit. + assert credit[3, i] <= credit[2, i] + tol, c + + +def test_worked_example(): + """2024 Schedule 2EC: line 5 pension 20,000; line 16 the claimant's SSI + 3,000; line 17 the other adult's SSI 2,000 and workers' compensation + 1,000 and the TANF 1,800; line 18 = 27,800; line 22 = (27,800 - 12,600) + x 0.05 = 760; line 27 = 1,500 - 760 = 740; line 30 = 740 in A, B and C. + D adds 8,000 of TANF: line 18 = 35,800; line 22 = 1,160; line 27 = 340; + line 29 = 40%; line 30 = 136.""" + case = { + "claimant_age": 70, + "pension": 20_000, + "claimant_ssi": 3_000, + "claimant_workers_compensation": 0, + "property_tax": 1_500, + "rent": 0, + "member_age": 35, + "member_ssi": 2_000, + "member_workers_compensation": 1_000, + "child_age": 6, + "tanf": 1_800, + "extra_kind": "tanf", + "extra": 8_000, + } + result = calculate([case]) + assert result["gross_household_income"][:, 0] == pytest.approx( + [27_800, 27_800, 27_800, 35_800], abs=TOLERANCE + ) + assert result["credit"][:, 0] == pytest.approx( + [740, 740, 740, 136], abs=TOLERANCE + ) + assert_properties([case]) + + +try: + import hypothesis + import hypothesis.strategies as st +except ImportError: # pragma: no cover + hypothesis = None + +if hypothesis is not None: + # Each example builds a Simulation; on a loaded runner input generation + # can trip the too_slow health check, which says nothing about the model. + SLOW = [hypothesis.HealthCheck.too_slow] + + def amount(high): + return st.one_of(st.just(0), st.integers(min_value=1, max_value=high)) + + @st.composite + def case(draw): + return { + "claimant_age": draw(st.integers(min_value=62, max_value=90)), + "pension": draw(amount(40_000)), + "claimant_ssi": draw(amount(12_000)), + "claimant_workers_compensation": draw(amount(15_000)), + "property_tax": draw(st.integers(min_value=0, max_value=4_000)), + "rent": draw(amount(12_000)), + "member_age": draw(st.integers(min_value=18, max_value=61)), + "member_ssi": draw(amount(12_000)), + "member_workers_compensation": draw(amount(15_000)), + "child_age": draw(st.integers(min_value=0, max_value=17)), + "tanf": draw(amount(10_000)), + "extra_kind": draw(st.sampled_from(EXTRA_KINDS)), + "extra": draw(st.integers(min_value=1, max_value=20_000)), + } + + @hypothesis.settings(max_examples=15, deadline=None, suppress_health_check=SLOW) + @hypothesis.given(st.lists(case(), min_size=1, max_size=8)) + def test_properties(cases): + assert_properties(cases) From b662ed12cf0b28e8a50e27e54166fb494add1f66 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Mon, 12 Oct 2026 06:09:40 -0400 Subject: [PATCH 03/11] Format the Montana government assistance property tests Co-Authored-By: Claude Opus 5.5 --- .../tests/test_mt_elderly_credit_government_assistance.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/policyengine_us/tests/test_mt_elderly_credit_government_assistance.py b/policyengine_us/tests/test_mt_elderly_credit_government_assistance.py index 6a366428122..00870adc9cc 100644 --- a/policyengine_us/tests/test_mt_elderly_credit_government_assistance.py +++ b/policyengine_us/tests/test_mt_elderly_credit_government_assistance.py @@ -263,9 +263,7 @@ def test_worked_example(): assert result["gross_household_income"][:, 0] == pytest.approx( [27_800, 27_800, 27_800, 35_800], abs=TOLERANCE ) - assert result["credit"][:, 0] == pytest.approx( - [740, 740, 740, 136], abs=TOLERANCE - ) + assert result["credit"][:, 0] == pytest.approx([740, 740, 740, 136], abs=TOLERANCE) assert_properties([case]) From 8718317e69bcac94882258c103f20a728619ea8e Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Mon, 12 Oct 2026 07:03:14 -0400 Subject: [PATCH 04/11] Pin SSI to zero in Montana elderly credit cases that test other income Gross household income now counts SSI, and the model computes SSI for a claimant aged 65 or older with little income (take-up defaults to true). Three gross household income cases and three property-test builders are about other items, so they now input no SSI; SSI has its own cases in the government assistance tests. Co-Authored-By: Claude Opus 5.5 --- ..._homeowner_or_renter_credit_gross_household_income.yaml | 7 +++++++ .../tests/test_mt_elderly_credit_dependent_deductions.py | 2 ++ .../tests/test_mt_elderly_credit_household_members.py | 3 +++ .../tests/test_mt_elderly_credit_rebate_receipts.py | 2 ++ 4 files changed, 14 insertions(+) diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_gross_household_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_gross_household_income.yaml index ec00f8c2fad..e1ca3dc39ce 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_gross_household_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_gross_household_income.yaml @@ -8,6 +8,9 @@ child_support_received: 3_000 strike_benefits: 2_000 general_assistance: 1_000 + # These amounts would make the model compute SSI, which also counts; + # its own cases are in the government assistance test file. + ssi: 0 tax_units: tax_unit: members: [person1] @@ -117,6 +120,8 @@ people: person1: age: 70 + # No SSI for the claimant, so the case isolates the dependent's income. + ssi: 0 person2: age: 17 employment_income: 25_000 @@ -144,6 +149,8 @@ people: person1: age: 70 + # No SSI for the claimant, so the case isolates the dependent's income. + ssi: 0 person2: age: 16 employment_income: 10_000 diff --git a/policyengine_us/tests/test_mt_elderly_credit_dependent_deductions.py b/policyengine_us/tests/test_mt_elderly_credit_dependent_deductions.py index 90736451eca..819ce2ce5ff 100644 --- a/policyengine_us/tests/test_mt_elderly_credit_dependent_deductions.py +++ b/policyengine_us/tests/test_mt_elderly_credit_dependent_deductions.py @@ -31,6 +31,8 @@ def build_situation(cases, year): "age": {year: 70}, "taxable_pension_income": {year: case["pension"]}, "early_withdrawal_penalty": {year: case["parent_penalty"]}, + # No computed SSI; it has its own tests (government assistance). + "ssi": {year: 0}, "is_tax_unit_dependent": {year: False}, "mt_refundable_credits_before_renter_credit": {year: 0}, "mt_elderly_homeowner_or_renter_credit_received": {year: 0}, diff --git a/policyengine_us/tests/test_mt_elderly_credit_household_members.py b/policyengine_us/tests/test_mt_elderly_credit_household_members.py index d1c1fff15ef..343bd2529a1 100644 --- a/policyengine_us/tests/test_mt_elderly_credit_household_members.py +++ b/policyengine_us/tests/test_mt_elderly_credit_household_members.py @@ -69,6 +69,9 @@ def build_situation(cases): "social_security_retirement": {YEAR: c["claimant_ss"]}, "real_estate_taxes": {YEAR: c["property_tax"]}, "rent": {YEAR: c["rent"]}, + # The model would compute SSI for a claimant with little + # income; SSI has its own tests (government assistance). + "ssi": {YEAR: 0}, } people[member] = { "age": {YEAR: c["member_age"]}, diff --git a/policyengine_us/tests/test_mt_elderly_credit_rebate_receipts.py b/policyengine_us/tests/test_mt_elderly_credit_rebate_receipts.py index 9f44d62671b..09470be0d6f 100644 --- a/policyengine_us/tests/test_mt_elderly_credit_rebate_receipts.py +++ b/policyengine_us/tests/test_mt_elderly_credit_rebate_receipts.py @@ -35,6 +35,8 @@ def build_situation(cases, year, with_receipts): }, "mt_refundable_credits_before_renter_credit": {year: 0}, "mt_elderly_homeowner_or_renter_credit_received": {year: 0}, + # No computed SSI; it has its own tests. + "ssi": {year: 0}, } if arrangement == "C": people[name][ From 87cef23a7db280d1e36c7e40bf4d721c44ec3d7f Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Mon, 12 Oct 2026 07:17:17 -0400 Subject: [PATCH 05/11] Count guaranteed income payments; move the cases to variable-named files Review follow-ups: gi_cash_assistance is outside federal AGI and 15-30-2337(9)(a) counts all nontaxable income (a government-funded pilot is also "any other government assistance" on Schedule 2EC line 16), so it joins every period of the sources. The worked cases move into mt_elderly_homeowner_or_renter_credit.yaml (and the SNAP guard into the gross household income file), with a guaranteed income case, the 2016 worksheet total corrected to line 10 and the references consolidated to one per document, with the 2009 MCA text for the 2009 period. Co-Authored-By: Claude Opus 5.5 --- ...erly-credit-government-assistance.fixed.md | 2 +- .../gross_income_sources.yaml | 50 ++- ...mt_elderly_homeowner_or_renter_credit.yaml | 298 ++++++++++++++++++ ...r_renter_credit_government_assistance.yaml | 282 ----------------- ..._renter_credit_gross_household_income.yaml | 23 ++ ...mt_elderly_credit_government_assistance.py | 34 +- 6 files changed, 370 insertions(+), 319 deletions(-) delete mode 100644 policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_government_assistance.yaml diff --git a/changelog.d/mt-elderly-credit-government-assistance.fixed.md b/changelog.d/mt-elderly-credit-government-assistance.fixed.md index 27b553487f9..5c1b0d95f6f 100644 --- a/changelog.d/mt-elderly-credit-government-assistance.fixed.md +++ b/changelog.d/mt-elderly-credit-government-assistance.fixed.md @@ -1 +1 @@ -Montana's elderly homeowner/renter credit now counts SSI, TANF and workers' compensation received by household members in gross household income (MCA 15-30-2337(9)(a)(vi); Schedule 2EC line 16). +Montana's elderly homeowner/renter credit now counts SSI, TANF, workers' compensation and guaranteed income payments received by household members in gross household income (MCA 15-30-2337(9)(a); Schedule 2EC line 16). diff --git a/policyengine_us/parameters/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/gross_income_sources.yaml b/policyengine_us/parameters/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/gross_income_sources.yaml index 61a193e098d..14a8ead4344 100644 --- a/policyengine_us/parameters/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/gross_income_sources.yaml +++ b/policyengine_us/parameters/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/gross_income_sources.yaml @@ -4,44 +4,32 @@ metadata: period: year label: Montana elderly homeowner or renter credit gross income sources reference: - - title: HB191 (2021), section 1(9), all nontaxable income - href: https://archive.legmt.gov/bills/2021/HB0199/HB0191_X.pdf#page=2 - - title: Montana 2022 Form2 Individual Income Tax Instructions, Page47, Gross Household Income - href: https://revenuefiles.mt.gov/files/Forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2022_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=47 + - title: MCA 15-30-2337(9)(a), all nontaxable income, including (vi) cash public assistance and relief + href: https://mca.legmt.gov/bills/mca/title_0150/chapter_0300/part_0230/section_0370/0150-0300-0230-0370.html + - title: MCA 15-30-2337(9)(a) (2009), the same definition + href: https://archive.legmt.gov/bills/2009/mca/15/30/15-30-2337.htm - title: 2022 Montana Code Annotated, Title 15, Chapter 30, Part 23, 15-30-2337 (9) href: https://law.justia.com/codes/montana/2022/title-15/chapter-30/part-23/section-15-30-2337/ - - title: 2024 Montana Individual Income Tax Return - href: https://revenuefiles.mt.gov/files/Forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2024_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=46 + - title: HB191 (2021), section 1(9), all nontaxable income + href: https://archive.legmt.gov/bills/2021/HB0199/HB0191_X.pdf#page=2 - title: ARM 42.4.301(2) as in effect 8/20/2004 to 11/9/2017 ("elderly homeowner/renter credit refunds received") href: https://rules.mt.gov/api/policy-library-public/collections/aec52c46-128e-4279-9068-8af5d5432d74/policies/c90ea93a-03a2-4605-a0f8-f2f3760198bf/document/788508cc-8418-41c8-926d-3dfb11af3fd6 - title: ARM 42.4.301(2) as in effect 11/10/2017 to 9/6/2024 ("federal refundable credits received" and "any state refundable credits received") href: https://rules.mt.gov/api/policy-library-public/collections/aec52c46-128e-4279-9068-8af5d5432d74/policies/c90ea93a-03a2-4605-a0f8-f2f3760198bf/document/297c7a8d-f6f4-4b70-a7b7-fe1cedee53e7 - title: ARM 42.4.301(2) as in effect from 9/7/2024 ("federal refundable tax credits received" and "any state refundable tax credits received") href: https://rules.mt.gov/api/policy-library-public/collections/aec52c46-128e-4279-9068-8af5d5432d74/policies/c90ea93a-03a2-4605-a0f8-f2f3760198bf/document/768c8344-24ee-4950-9d5e-9d8fc97ec0f7 - - title: 2017 Montana Form 2EC instructions, Gross Household Income Worksheet, item 4 ("Any federal or state refundable credits including the 2EC credit") - href: https://taxsim.nber.org/historical_state_tax_forms/MT/2017/Form%202%202017%20Booklet.pdf#page=65 - - title: 2023 Montana Form 2 instructions, Elderly Homeowner/Renter Credit Schedule, line 7, refundable credits received - href: https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2023_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=51 - - title: 2024 Montana Form 2 instructions, Schedule 2EC, line 8, refundable credits received - href: https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2024_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=47 - - title: 2025 Montana Form 2 instructions, Schedule 2EC, line 8, refundable credits received - href: https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2025_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=45 - - title: MCA 15-30-2337(9)(a)(vi), cash public assistance and relief - href: https://mca.legmt.gov/bills/mca/title_0150/chapter_0300/part_0230/section_0370/0150-0300-0230-0370.html - - title: MCA 15-30-2337(9)(a)(vi) as in effect in 2016 (archived) - href: https://web.archive.org/web/20161231130526/http://leg.mt.gov/bills/mca/title_0150/chapter_0300/part_0230/section_0370/0150-0300-0230-0370.html - - title: 2016 Montana Form 2EC instructions, Part II, disability benefits including SSI payments and workers' compensation, and cash public assistance and relief + - title: 2016 Montana Form 2EC instructions, Part II, disability benefits including SSI payments and workers' compensation, and cash public assistance and relief (PDF p.74) href: https://taxsim.nber.org/historical_state_tax_forms/MT/2016/Form_2_booklet_2016.pdf#page=74 - - title: 2017 Montana Form 2EC instructions, Part II, disability benefits including SSI payments and workers' compensation, and cash public assistance and relief + - title: 2017 Montana Form 2EC instructions, Part II, disability benefits including SSI payments and workers' compensation, and cash public assistance and relief; Gross Household Income Worksheet, items 4 and 5 (PDF pp.64-65) href: https://taxsim.nber.org/historical_state_tax_forms/MT/2017/Form%202%202017%20Booklet.pdf#page=64 - - title: 2022 Montana Form 2 instructions, Elderly Homeowner/Renter Credit Schedule, line 8, disability benefits including SSI payments and workers' compensation - href: https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2022_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=48 - - title: 2023 Montana Form 2 instructions, Elderly Homeowner/Renter Credit Schedule, line 8, disability benefits including SSI payments and workers' compensation - href: https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2023_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=52 - - title: 2024 Montana Form 2 instructions, Schedule 2EC, line 16, government assistance - href: https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2024_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=48 - - title: 2025 Montana Form 2 instructions, Schedule 2EC, line 16, government assistance - href: https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2025_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=46 + - title: 2022 Montana Form 2 instructions, Elderly Homeowner/Renter Credit Schedule, gross household income; line 8, disability benefits including SSI payments and workers' compensation (PDF pp.47-48) + href: https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2022_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=47 + - title: 2023 Montana Form 2 instructions, Elderly Homeowner/Renter Credit Schedule, line 7, refundable credits received; line 8, disability benefits including SSI payments and workers' compensation (PDF pp.51-52) + href: https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2023_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=51 + - title: 2024 Montana Form 2 instructions, Schedule 2EC, gross household income; line 8, refundable credits received; line 16, government assistance (PDF pp.46-48) + href: https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2024_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=46 + - title: 2025 Montana Form 2 instructions, Schedule 2EC, line 8, refundable credits received; line 16, government assistance (PDF pp.45-46) + href: https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2025_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=45 values: 2009-01-01: @@ -68,6 +56,10 @@ values: - ssi - tanf_person - workers_compensation + # Guaranteed income pilot payments are outside federal AGI here, and + # (9)(a) counts all nontaxable income; a government-funded pilot is also + # "any other government assistance" (Schedule 2EC line 16). + - gi_cash_assistance # Refundable credits received (2023 schedule line 7, Schedule 2EC line 8 # from 2024): Montana's refundable credits other than this credit, # and this credit as received during the year (ARM 42.4.301(2)(c)). @@ -88,6 +80,7 @@ values: - ssi - tanf_person - workers_compensation + - gi_cash_assistance - mt_refundable_credits_before_renter_credit - mt_elderly_homeowner_or_renter_credit_received - mt_elderly_homeowner_or_renter_credit_federal_refundable_credits @@ -107,6 +100,7 @@ values: - ssi - tanf_person - workers_compensation + - gi_cash_assistance - mt_refundable_credits_before_renter_credit - mt_elderly_homeowner_or_renter_credit_received - mt_elderly_homeowner_or_renter_credit_federal_refundable_credits diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit.yaml index 472a0218dd0..9b786fcce4f 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit.yaml @@ -327,6 +327,304 @@ mt_elderly_homeowner_or_renter_credit_net_household_income: [870, 0] mt_elderly_homeowner_or_renter_credit: [1_130, 0] +# Government assistance in gross household income. § 15-30-2337(9)(a) +# counts "all nontaxable income, including but not limited to ... (vi) cash +# public assistance and relief". 2024 and 2025 Schedule 2EC line 16 names +# SSI payments, workers' compensation "and any other government assistance"; +# the 2014-2023 instructions list "Disability benefits including, but not +# limited to, veteran's disability, SSI payments and workers' compensation". + +- name: 2024 Schedule 2EC worked case, the claimant's SSI counts on line 16 + period: 2024 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + taxable_pension_income: 15_000 + ssi: 6_000 + real_estate_taxes: 1_200 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_name: MT + output: + # Line 5 pensions 15_000; line 16 SSI 6_000; line 18 = 21_000. + mt_elderly_homeowner_or_renter_credit_gross_household_income: 21_000 + # Line 19 12_600; line 20 = 8_400; line 21 = 0.039 (8_000 to 8_999); + # line 22 = 8_400 x 0.039 = 327.60. + mt_elderly_homeowner_or_renter_credit_net_household_income: 327.60 + # Line 23 = 1_200; line 26 = 1_200; line 27 = 1_200 - 327.60 = 872.40; + # line 28 = 872.40 (under 1_150); line 29 = 100%; line 30 = 872.40. + # Without the SSI, line 18 = 15_000, line 22 = 2_400 x 0.006 = 14.40 and + # the credit would be the 1_150 cap. + mt_elderly_homeowner_or_renter_credit: 872.40 + + +- name: 2025 Schedule 2EC worked case, a household member's workers' compensation counts on line 17 + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 72 + taxable_pension_income: 18_000 + real_estate_taxes: 1_500 + person2: + age: 45 + workers_compensation: 9_000 + tax_units: + tax_unit1: + members: [person1] + tax_unit2: + members: [person2] + households: + household: + members: [person1, person2] + state_name: MT + output: + # The claimant's adult son lives in the household and files his own + # return. Line 5 pensions 18_000; line 17 his workers' compensation, a + # line 16 item for another member, 9_000; line 18 = 27_000. + mt_elderly_homeowner_or_renter_credit_gross_household_income: [18_000, 9_000] + # Line 20 = 27_000 - 12_600 = 14_400; line 21 = 0.05; line 22 = 720. + mt_elderly_homeowner_or_renter_credit_net_household_income: [720, 0] + # Line 27 = 1_500 - 720 = 780; line 28 = 780; line 29 = 100%; line 30 = + # 780. Without his workers' compensation, line 18 = 18_000, line 22 = + # 5_400 x 0.028 = 151.20 and the credit would be the 1_150 cap. + mt_elderly_homeowner_or_renter_credit: [780, 0] + + +- name: 2024 Schedule 2EC worked case, a household member's guaranteed income payments count on line 17 + period: 2024 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + taxable_pension_income: 16_000 + real_estate_taxes: 1_200 + person2: + age: 35 + gi_cash_assistance: 6_000 + tax_units: + tax_unit1: + members: [person1] + tax_unit2: + members: [person2] + households: + household: + members: [person1, person2] + state_name: MT + output: + # The claimant's daughter files her own return and receives 6_000 from a + # guaranteed income pilot, which is outside federal AGI. § 15-30-2337(9)(a) + # counts "all nontaxable income", and line 16 counts "any other + # government assistance". Line 5 = 16_000; line 17 = 6_000; line 18 = + # 22_000. + mt_elderly_homeowner_or_renter_credit_gross_household_income: [16_000, 6_000] + # Line 20 = 9_400; line 21 = 0.042; line 22 = 394.80. + mt_elderly_homeowner_or_renter_credit_net_household_income: [394.80, 0] + # Line 27 = 1_200 - 394.80 = 805.20; line 28 = 805.20; line 29 = 100%; + # line 30 = 805.20. Without the payments, line 18 = 16_000, line 22 = + # 3_400 x 0.016 = 54.40 and the credit 1_145.60. + mt_elderly_homeowner_or_renter_credit: [805.20, 0] + + +- name: 2024 Schedule 2EC worked case, TANF in a shared SPM unit counts once across two returns + period: 2024 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + taxable_pension_income: 20_000 + real_estate_taxes: 1_500 + person2: + age: 30 + person3: + age: 5 + tax_units: + tax_unit1: + members: [person1] + tax_unit2: + members: [person2, person3] + spm_units: + spm_unit: + members: [person1, person2, person3] + tanf: 4_800 + households: + household: + members: [person1, person2, person3] + state_name: MT + output: + # The claimant's daughter and granddaughter live with her; the daughter + # files her own return and receives 4_800 of TANF. Line 5 pensions + # 20_000; line 17 the TANF 4_800; line 18 = 24_800. The model holds TANF + # for the SPM unit and counts each member's per capita share + # (tanf_person, 1_600 each), so the household total counts it once. + mt_elderly_homeowner_or_renter_credit_gross_household_income: [21_600, 1_600, 1_600] + # Line 20 = 24_800 - 12_600 = 12_200; line 21 = 0.05; line 22 = 610. + mt_elderly_homeowner_or_renter_credit_net_household_income: [610, 0, 0] + # Line 27 = 1_500 - 610 = 890; line 28 = 890; line 29 = 100%; line 30 = + # 890. Without the TANF, line 18 = 20_000, line 22 = 7_400 x 0.035 = 259 + # and the credit would be the 1_150 cap. Counting the whole 4_800 for + # each of the three members would give line 18 = 34_400 and a credit of + # 1_500 - 1_090 = 410. + mt_elderly_homeowner_or_renter_credit: [890, 0, 0] + + +- name: 2024 Schedule 2EC worked case, Montana TANF paid to a separate SPM unit counts on line 17 + period: 2024 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + taxable_pension_income: 20_000 + real_estate_taxes: 1_500 + person2: + age: 30 + person3: + age: 5 + tax_units: + tax_unit1: + members: [person1] + tax_unit2: + members: [person2, person3] + spm_units: + spm_unit1: + members: [person1] + spm_unit2: + members: [person2, person3] + mt_tanf: 4_800 + households: + household: + members: [person1, person2, person3] + state_name: MT + output: + # The same household with the daughter's family in its own SPM unit and + # the payment entered as Montana TANF (ARM 37.78), which tanf sums with + # the other states' programs. Line 17 = 4_800; line 18 = 24_800. + tanf: [0, 4_800] + mt_elderly_homeowner_or_renter_credit_gross_household_income: [20_000, 2_400, 2_400] + # Line 22 = (24_800 - 12_600) x 0.05 = 610; line 27 = 890; line 30 = 890. + mt_elderly_homeowner_or_renter_credit_net_household_income: [610, 0, 0] + mt_elderly_homeowner_or_renter_credit: [890, 0, 0] + + +- name: 2023 Elderly Homeowner/Renter Credit Schedule worked case, workers' compensation and a spouse's SSI count on line 8 + period: 2023 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 66 + taxable_pension_income: 14_000 + workers_compensation: 6_000 + real_estate_taxes: 1_000 + person2: + age: 64 + ssi: 5_000 + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_name: MT + output: + # Joint return. Line 1 federal AGI 14_000; line 8 "Disability benefits + # including, but not limited to, veteran's disability, SSI payments, and + # workers' compensation": 6_000 + 5_000 = 11_000; line 10 = 25_000. + mt_elderly_homeowner_or_renter_credit_gross_household_income: [20_000, 5_000] + # Line 11 12_600; line 12 = 12_400; line 13 = 0.05; line 14 = 620. + mt_elderly_homeowner_or_renter_credit_net_household_income: [620, 0] + # Line 15 = 1_000; line 18 = 1_000; line 19 = 1_000 - 620 = 380; line 20 + # = 380; line 21 = 100%; line 22 = 380. Without either amount, line 10 = + # 14_000, line 12 = 1_400 at a 0 rate and the credit would be 1_000. + mt_elderly_homeowner_or_renter_credit: [380, 0] + + +- name: 2017 Form 2EC worked case, a household member's SSI counts in gross household income + period: 2017 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + taxable_pension_income: 15_000 + real_estate_taxes: 1_000 + person2: + age: 40 + # 2017 federal benefit rate: 735 a month. + ssi: 8_820 + tax_units: + tax_unit1: + members: [person1] + tax_unit2: + members: [person2] + households: + household: + members: [person1, person2] + state_name: MT + output: + # The claimant's adult son receives SSI. Gross Household Income + # Worksheet: line 6 pensions 15_000; line 7 income of other household + # members, his SSI 8_820 ("Disability benefits including ... SSI + # payments"); line 8 = 23_820, Form 2EC line 1. + mt_elderly_homeowner_or_renter_credit_gross_household_income: [15_000, 8_820] + # Line 2 6_300; line 3 = 17_520; line 4 = 0.05; line 5 = 876. + mt_elderly_homeowner_or_renter_credit_net_household_income: [876, 0] + # Line 6 = 1_000; line 9 = 1_000; line 10 = 1_000 - 876 = 124; line 11 = + # 124 (under 1_000); line 12 = 100%; line 13 = 124. Without his SSI, line + # 1 = 15_000, line 5 = 8_700 x 0.039 = 339.30 and the credit 660.70. + mt_elderly_homeowner_or_renter_credit: [124, 0] + + +- name: 2016 Form 2EC worked case, cash public assistance received by another household member counts + period: 2016 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + taxable_pension_income: 12_000 + real_estate_taxes: 900 + person2: + age: 30 + person3: + age: 5 + tax_units: + tax_unit1: + members: [person1] + tax_unit2: + members: [person2, person3] + spm_units: + spm_unit1: + members: [person1] + spm_unit2: + members: [person2, person3] + tanf: 5_400 + households: + household: + members: [person1, person2, person3] + state_name: MT + output: + # Gross Household Income Worksheet: line 8 pensions 12_000; the + # daughter's 5_400 of TANF, cash public assistance (line 7), as income of + # another household member (line 9); line 10 = 17_400, Form 2EC line 1. + mt_elderly_homeowner_or_renter_credit_gross_household_income: [12_000, 2_700, 2_700] + # Line 2 6_300; line 3 = 11_100; line 4 = 0.048; line 5 = 532.80. + mt_elderly_homeowner_or_renter_credit_net_household_income: [532.80, 0, 0] + # Line 6 = 900; line 10 = 900 - 532.80 = 367.20; line 11 = 367.20; line + # 12 = 100%; line 13 = 367.20. Without the TANF, line 1 = 12_000, line 5 + # = 5_700 x 0.028 = 159.60 and the credit 740.40. + mt_elderly_homeowner_or_renter_credit: [367.20, 0, 0] + - name: 2024 Schedule 2EC worked case, a dependent's wages move the credit into the 40 percent band period: 2024 absolute_error_margin: 0.01 diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_government_assistance.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_government_assistance.yaml deleted file mode 100644 index 82bc6942c0f..00000000000 --- a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_government_assistance.yaml +++ /dev/null @@ -1,282 +0,0 @@ -# Government assistance in gross household income: SSI, TANF and workers' -# compensation. § 15-30-2337(9)(a) counts "all nontaxable income, including -# but not limited to ... (vi) cash public assistance and relief". 2024 and -# 2025 Schedule 2EC line 16: "This includes veteran's compensation benefits, -# supplemental security income (SSI) payments, worker's compensation, and any -# other government assistance received during the year." The 2014-2023 -# instructions list "Disability benefits including, but not limited to, -# veteran's disability, SSI payments and workers' compensation", and the -# 2014-2017 instructions add "Cash public assistance and relief - Do not -# include LIEAP ... or SNAP". - -- name: 2024 Schedule 2EC worked case, the claimant's SSI counts on line 16 - period: 2024 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 70 - taxable_pension_income: 15_000 - ssi: 6_000 - real_estate_taxes: 1_200 - tax_units: - tax_unit: - members: [person1] - households: - household: - members: [person1] - state_name: MT - output: - # Line 5 pensions 15_000; line 16 SSI 6_000; line 18 = 21_000. - mt_elderly_homeowner_or_renter_credit_gross_household_income: 21_000 - # Line 19 12_600; line 20 = 8_400; line 21 = 0.039 (8_000 to 8_999); - # line 22 = 8_400 x 0.039 = 327.60. - mt_elderly_homeowner_or_renter_credit_net_household_income: 327.60 - # Line 23 = 1_200; line 26 = 1_200; line 27 = 1_200 - 327.60 = 872.40; - # line 28 = 872.40 (under 1_150); line 29 = 100%; line 30 = 872.40. - # Without the SSI, line 18 = 15_000, line 22 = 2_400 x 0.006 = 14.40 and - # the credit would be the 1_150 cap. - mt_elderly_homeowner_or_renter_credit: 872.40 - -- name: 2025 Schedule 2EC worked case, a household member's workers' compensation counts on line 17 - period: 2025 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 72 - taxable_pension_income: 18_000 - real_estate_taxes: 1_500 - person2: - age: 45 - workers_compensation: 9_000 - tax_units: - tax_unit1: - members: [person1] - tax_unit2: - members: [person2] - households: - household: - members: [person1, person2] - state_name: MT - output: - # The claimant's adult son lives in the household and files his own - # return. Line 5 pensions 18_000; line 17 his workers' compensation, a - # line 16 item for another member, 9_000; line 18 = 27_000. - mt_elderly_homeowner_or_renter_credit_gross_household_income: [18_000, 9_000] - # Line 20 = 27_000 - 12_600 = 14_400; line 21 = 0.05; line 22 = 720. - mt_elderly_homeowner_or_renter_credit_net_household_income: [720, 0] - # Line 27 = 1_500 - 720 = 780; line 28 = 780; line 29 = 100%; line 30 = - # 780. Without his workers' compensation, line 18 = 18_000, line 22 = - # 5_400 x 0.028 = 151.20 and the credit would be the 1_150 cap. - mt_elderly_homeowner_or_renter_credit: [780, 0] - -- name: 2024 Schedule 2EC worked case, TANF in a shared SPM unit counts once across two returns - period: 2024 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 70 - taxable_pension_income: 20_000 - real_estate_taxes: 1_500 - person2: - age: 30 - person3: - age: 5 - tax_units: - tax_unit1: - members: [person1] - tax_unit2: - members: [person2, person3] - spm_units: - spm_unit: - members: [person1, person2, person3] - tanf: 4_800 - households: - household: - members: [person1, person2, person3] - state_name: MT - output: - # The claimant's daughter and granddaughter live with her; the daughter - # files her own return and receives 4_800 of TANF. Line 5 pensions - # 20_000; line 17 the TANF 4_800; line 18 = 24_800. The model holds TANF - # for the SPM unit and counts each member's per capita share - # (tanf_person, 1_600 each), so the household total counts it once. - mt_elderly_homeowner_or_renter_credit_gross_household_income: [21_600, 1_600, 1_600] - # Line 20 = 24_800 - 12_600 = 12_200; line 21 = 0.05; line 22 = 610. - mt_elderly_homeowner_or_renter_credit_net_household_income: [610, 0, 0] - # Line 27 = 1_500 - 610 = 890; line 28 = 890; line 29 = 100%; line 30 = - # 890. Without the TANF, line 18 = 20_000, line 22 = 7_400 x 0.035 = 259 - # and the credit would be the 1_150 cap. Counting the whole 4_800 for - # each of the three members would give line 18 = 34_400 and a credit of - # 1_500 - 1_090 = 410. - mt_elderly_homeowner_or_renter_credit: [890, 0, 0] - -- name: 2024 Schedule 2EC worked case, Montana TANF paid to a separate SPM unit counts on line 17 - period: 2024 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 70 - taxable_pension_income: 20_000 - real_estate_taxes: 1_500 - person2: - age: 30 - person3: - age: 5 - tax_units: - tax_unit1: - members: [person1] - tax_unit2: - members: [person2, person3] - spm_units: - spm_unit1: - members: [person1] - spm_unit2: - members: [person2, person3] - mt_tanf: 4_800 - households: - household: - members: [person1, person2, person3] - state_name: MT - output: - # The same household with the daughter's family in its own SPM unit and - # the payment entered as Montana TANF (ARM 37.78), which tanf sums with - # the other states' programs. Line 17 = 4_800; line 18 = 24_800. - tanf: [0, 4_800] - mt_elderly_homeowner_or_renter_credit_gross_household_income: [20_000, 2_400, 2_400] - # Line 22 = (24_800 - 12_600) x 0.05 = 610; line 27 = 890; line 30 = 890. - mt_elderly_homeowner_or_renter_credit_net_household_income: [610, 0, 0] - mt_elderly_homeowner_or_renter_credit: [890, 0, 0] - -- name: 2023 Elderly Homeowner/Renter Credit Schedule worked case, workers' compensation and a spouse's SSI count on line 8 - period: 2023 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 66 - taxable_pension_income: 14_000 - workers_compensation: 6_000 - real_estate_taxes: 1_000 - person2: - age: 64 - ssi: 5_000 - tax_units: - tax_unit: - members: [person1, person2] - households: - household: - members: [person1, person2] - state_name: MT - output: - # Joint return. Line 1 federal AGI 14_000; line 8 "Disability benefits - # including, but not limited to, veteran's disability, SSI payments, and - # workers' compensation": 6_000 + 5_000 = 11_000; line 10 = 25_000. - mt_elderly_homeowner_or_renter_credit_gross_household_income: [20_000, 5_000] - # Line 11 12_600; line 12 = 12_400; line 13 = 0.05; line 14 = 620. - mt_elderly_homeowner_or_renter_credit_net_household_income: [620, 0] - # Line 15 = 1_000; line 18 = 1_000; line 19 = 1_000 - 620 = 380; line 20 - # = 380; line 21 = 100%; line 22 = 380. Without either amount, line 10 = - # 14_000, line 12 = 1_400 at a 0 rate and the credit would be 1_000. - mt_elderly_homeowner_or_renter_credit: [380, 0] - -- name: 2017 Form 2EC worked case, a household member's SSI counts in gross household income - period: 2017 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 70 - taxable_pension_income: 15_000 - real_estate_taxes: 1_000 - person2: - age: 40 - # 2017 federal benefit rate: 735 a month. - ssi: 8_820 - tax_units: - tax_unit1: - members: [person1] - tax_unit2: - members: [person2] - households: - household: - members: [person1, person2] - state_name: MT - output: - # The claimant's adult son receives SSI. Gross Household Income - # Worksheet: line 6 pensions 15_000; line 7 income of other household - # members, his SSI 8_820 ("Disability benefits including ... SSI - # payments"); line 8 = 23_820, Form 2EC line 1. - mt_elderly_homeowner_or_renter_credit_gross_household_income: [15_000, 8_820] - # Line 2 6_300; line 3 = 17_520; line 4 = 0.05; line 5 = 876. - mt_elderly_homeowner_or_renter_credit_net_household_income: [876, 0] - # Line 6 = 1_000; line 9 = 1_000; line 10 = 1_000 - 876 = 124; line 11 = - # 124 (under 1_000); line 12 = 100%; line 13 = 124. Without his SSI, line - # 1 = 15_000, line 5 = 8_700 x 0.039 = 339.30 and the credit 660.70. - mt_elderly_homeowner_or_renter_credit: [124, 0] - -- name: 2016 Form 2EC worked case, cash public assistance received by another household member counts - period: 2016 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 70 - taxable_pension_income: 12_000 - real_estate_taxes: 900 - person2: - age: 30 - person3: - age: 5 - tax_units: - tax_unit1: - members: [person1] - tax_unit2: - members: [person2, person3] - spm_units: - spm_unit1: - members: [person1] - spm_unit2: - members: [person2, person3] - tanf: 5_400 - households: - household: - members: [person1, person2, person3] - state_name: MT - output: - # Gross Household Income Worksheet line 7, "Alimony, cash public - # assistance, unemployment", for the daughter's 5_400 of TANF; line 9 = - # 12_000 + 5_400 = 17_400, Form 2EC line 1. - mt_elderly_homeowner_or_renter_credit_gross_household_income: [12_000, 2_700, 2_700] - # Line 2 6_300; line 3 = 11_100; line 4 = 0.048; line 5 = 532.80. - mt_elderly_homeowner_or_renter_credit_net_household_income: [532.80, 0, 0] - # Line 6 = 900; line 10 = 900 - 532.80 = 367.20; line 11 = 367.20; line - # 12 = 100%; line 13 = 367.20. Without the TANF, line 1 = 12_000, line 5 - # = 5_700 x 0.028 = 159.60 and the credit 740.40. - mt_elderly_homeowner_or_renter_credit: [367.20, 0, 0] - -- name: SNAP is not cash public assistance and does not count - period: 2017 - input: - people: - person1: - age: 70 - taxable_pension_income: 15_000 - spm_units: - spm_unit: - members: [person1] - snap: 1_800 - tax_units: - tax_unit: - members: [person1] - households: - household: - members: [person1] - state_name: MT - output: - # 2017 Form 2EC instructions: "Cash, public assistance and relief - Do - # not include LIEAP (Low Income Energy Assistance Program) or SNAP". - mt_elderly_homeowner_or_renter_credit_gross_household_income: 15_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_gross_household_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_gross_household_income.yaml index e1ca3dc39ce..442caea56f2 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_gross_household_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_gross_household_income.yaml @@ -89,6 +89,29 @@ # income: (20_000 - 12_600) * 0.035 = 259, allocated to the head. mt_elderly_homeowner_or_renter_credit_net_household_income: [259, 0] +- name: SNAP is not cash public assistance and does not count + period: 2017 + input: + people: + person1: + age: 70 + taxable_pension_income: 15_000 + spm_units: + spm_unit: + members: [person1] + snap: 1_800 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_name: MT + output: + # 2017 Form 2EC instructions: "Cash, public assistance and relief - Do + # not include LIEAP (Low Income Energy Assistance Program) or SNAP". + mt_elderly_homeowner_or_renter_credit_gross_household_income: 15_000 + - name: A dependent's wages count in gross household income period: 2024 input: diff --git a/policyengine_us/tests/test_mt_elderly_credit_government_assistance.py b/policyengine_us/tests/test_mt_elderly_credit_government_assistance.py index 00870adc9cc..aaf5fa438f5 100644 --- a/policyengine_us/tests/test_mt_elderly_credit_government_assistance.py +++ b/policyengine_us/tests/test_mt_elderly_credit_government_assistance.py @@ -8,11 +8,12 @@ compensation, and any other government assistance"; line 17 carries the same items for the other members of the household. -The model holds SSI and workers' compensation per person and TANF per SPM -unit, which it spreads over the unit's members (tanf_person). For a claimant -aged 62 or older (taxable pension, SSI, workers' compensation, property tax, -rent) living with another adult (SSI, workers' compensation) and a child, -whose SPM unit receives TANF, in four arrangements: +The model holds SSI, workers' compensation and guaranteed income payments +per person and TANF per SPM unit, which it spreads over the unit's members +(tanf_person). For a claimant aged 62 or older (taxable pension, SSI, +workers' compensation, property tax, rent) living with another adult (SSI, +workers' compensation, guaranteed income payments) and a child, whose SPM +unit receives TANF, in four arrangements: A. one return, the other adult and the child the claimant's dependents, and one SPM unit; @@ -22,7 +23,8 @@ D. as C, with more of one kind of assistance; 1. The household's gross household income is the pension plus every - member's SSI and workers' compensation plus the TANF, once, in A, B and C. + member's SSI, workers' compensation and guaranteed income payments plus + the TANF, once, in A, B and C. 2. So the claimant's credit is the same in A, B and C, and nobody else claims. 3. The credit equals an independent reading of Schedule 2EC lines 18 to 30, @@ -32,6 +34,12 @@ No one has earned income, so no refundable credit enters line 8. The model computes in single precision, so comparisons allow one cent or eight float32 spacings at the household's total income, whichever is larger. + +YAML cases (mt_elderly_homeowner_or_renter_credit.yaml) pin fixed worked +examples. This file adds what they cannot: randomized amounts across +arrangements that must agree, an independent Schedule 2EC reference for the +credit, and monotonicity. Each example is one small Simulation on the shared +tax-benefit system. """ import numpy as np @@ -70,7 +78,12 @@ (42_501, 0.1), (45_000, 0), ] -EXTRA_KINDS = ["claimant_ssi", "member_workers_compensation", "tanf"] +EXTRA_KINDS = [ + "claimant_ssi", + "member_workers_compensation", + "member_gi_cash_assistance", + "tanf", +] def amounts(c, arrangement): @@ -80,6 +93,7 @@ def amounts(c, arrangement): "claimant_workers_compensation": c["claimant_workers_compensation"], "member_ssi": c["member_ssi"], "member_workers_compensation": c["member_workers_compensation"], + "member_gi_cash_assistance": c["member_gi_cash_assistance"], "tanf": c["tanf"], } if arrangement == "D": @@ -118,6 +132,7 @@ def build_situation(cases): "age": {YEAR: c["member_age"]}, "ssi": {YEAR: a["member_ssi"]}, "workers_compensation": {YEAR: a["member_workers_compensation"]}, + "gi_cash_assistance": {YEAR: a["member_gi_cash_assistance"]}, "is_tax_unit_dependent": {YEAR: arrangement == "A"}, } people[child] = { @@ -185,7 +200,8 @@ def by_household(variable): def expected_gross_household_income(c, arrangement): """2024 Schedule 2EC line 18: line 5 pension and line 16 assistance for - the claimant, line 17 the other members' assistance, the TANF once.""" + the claimant, line 17 the other members' assistance and guaranteed income + payments, the TANF once.""" return c["pension"] + sum(amounts(c, arrangement).values()) @@ -254,6 +270,7 @@ def test_worked_example(): "member_age": 35, "member_ssi": 2_000, "member_workers_compensation": 1_000, + "member_gi_cash_assistance": 0, "child_age": 6, "tanf": 1_800, "extra_kind": "tanf", @@ -293,6 +310,7 @@ def case(draw): "member_age": draw(st.integers(min_value=18, max_value=61)), "member_ssi": draw(amount(12_000)), "member_workers_compensation": draw(amount(15_000)), + "member_gi_cash_assistance": draw(amount(12_000)), "child_age": draw(st.integers(min_value=0, max_value=17)), "tanf": draw(amount(10_000)), "extra_kind": draw(st.sampled_from(EXTRA_KINDS)), From fc794353c49a3d7512f5406e4b12e6eeaaa04516 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Mon, 12 Oct 2026 14:20:58 -0400 Subject: [PATCH 06/11] Count disability benefits and unemployment compensation outside federal AGI in Montana's elderly credit income (WIP) Co-Authored-By: Claude Opus 5.5 --- .../gross_income_sources.yaml | 36 +- ...er_credit_disability_and_unemployment.yaml | 335 ++++++++++++++++++ ..._nontaxable_unemployment_compensation.yaml | 190 ++++++++++ ...it_nontaxable_unemployment_compensation.py | 48 +++ 4 files changed, 603 insertions(+), 6 deletions(-) create mode 100644 policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_disability_and_unemployment.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation.yaml create mode 100644 policyengine_us/variables/gov/states/mt/tax/income/credits/mt_elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation.py diff --git a/policyengine_us/parameters/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/gross_income_sources.yaml b/policyengine_us/parameters/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/gross_income_sources.yaml index 14a8ead4344..dee324147e0 100644 --- a/policyengine_us/parameters/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/gross_income_sources.yaml +++ b/policyengine_us/parameters/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/gross_income_sources.yaml @@ -18,17 +18,23 @@ metadata: href: https://rules.mt.gov/api/policy-library-public/collections/aec52c46-128e-4279-9068-8af5d5432d74/policies/c90ea93a-03a2-4605-a0f8-f2f3760198bf/document/297c7a8d-f6f4-4b70-a7b7-fe1cedee53e7 - title: ARM 42.4.301(2) as in effect from 9/7/2024 ("federal refundable tax credits received" and "any state refundable tax credits received") href: https://rules.mt.gov/api/policy-library-public/collections/aec52c46-128e-4279-9068-8af5d5432d74/policies/c90ea93a-03a2-4605-a0f8-f2f3760198bf/document/768c8344-24ee-4950-9d5e-9d8fc97ec0f7 - - title: 2016 Montana Form 2EC instructions, Part II, disability benefits including SSI payments and workers' compensation, and cash public assistance and relief (PDF p.74) + - title: "2014 Montana Form 2EC instructions, Part II, disability benefits including SSI payments and workers' compensation; Income Source Worksheet, line 7, alimony, cash public assistance, unemployment #page 53-54" + href: https://taxsim.nber.org/historical_state_tax_forms/MT/2014/Form_2_booklet_2014.pdf#page=53 + - title: "2016 Montana Form 2EC instructions, Part II, disability benefits including SSI payments and workers' compensation, and cash public assistance and relief; Gross Household Income Worksheet, line 7, alimony, cash public assistance, unemployment #page 74-75" href: https://taxsim.nber.org/historical_state_tax_forms/MT/2016/Form_2_booklet_2016.pdf#page=74 - - title: 2017 Montana Form 2EC instructions, Part II, disability benefits including SSI payments and workers' compensation, and cash public assistance and relief; Gross Household Income Worksheet, items 4 and 5 (PDF pp.64-65) + - title: "2017 Montana Form 2EC instructions, Part II, disability benefits including SSI payments and workers' compensation, and cash public assistance and relief; Gross Household Income Worksheet, items 4 and 5 (alimony, cash public assistance, unemployment) #page 64-65" href: https://taxsim.nber.org/historical_state_tax_forms/MT/2017/Form%202%202017%20Booklet.pdf#page=64 - - title: 2022 Montana Form 2 instructions, Elderly Homeowner/Renter Credit Schedule, gross household income; line 8, disability benefits including SSI payments and workers' compensation (PDF pp.47-48) + - title: 2020 Montana Form 2 instructions, Elderly Homeowner/Renter Credit Schedule, line 1, federal adjusted gross income; line 8, other income not listed above, including disability benefits + href: https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2020_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=45 + - title: 2021 Montana Form 2 instructions, Elderly Homeowner/Renter Credit Schedule, line 8, other income not listed above, including disability benefits + href: https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2021_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=49 + - title: "2022 Montana Form 2 instructions, Elderly Homeowner/Renter Credit Schedule, gross household income; line 8, other income, including disability benefits, SSI payments and workers' compensation #page 47-48" href: https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2022_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=47 - - title: 2023 Montana Form 2 instructions, Elderly Homeowner/Renter Credit Schedule, line 7, refundable credits received; line 8, disability benefits including SSI payments and workers' compensation (PDF pp.51-52) + - title: "2023 Montana Form 2 instructions, Elderly Homeowner/Renter Credit Schedule, line 7, refundable credits received; line 8, other income, including disability benefits, SSI payments and workers' compensation #page 51-52" href: https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2023_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=51 - - title: 2024 Montana Form 2 instructions, Schedule 2EC, gross household income; line 8, refundable credits received; line 16, government assistance (PDF pp.46-48) + - title: "2024 Montana Form 2 instructions, Schedule 2EC, gross household income; line 1, wages; line 8, refundable credits received; line 14, unemployment compensation; line 15, other income; line 16, government assistance #page 46-48" href: https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2024_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=46 - - title: 2025 Montana Form 2 instructions, Schedule 2EC, line 8, refundable credits received; line 16, government assistance (PDF pp.45-46) + - title: "2025 Montana Form 2 instructions, Schedule 2EC, line 8, refundable credits received; line 14, unemployment compensation; line 15, other income; line 16, government assistance #page 45-46" href: https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2025_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=45 values: @@ -60,6 +66,20 @@ values: # (9)(a) counts all nontaxable income; a government-funded pilot is also # "any other government assistance" (Schedule 2EC line 16). - gi_cash_assistance + # Disability benefits from employment other than workers' compensation + # (2014-2023 instructions: "Disability benefits including, but not + # limited to, veteran's disability, SSI payments, and workers' + # compensation"; from 2024, Schedule 2EC line 1 when taxable, as IRS + # Pub. 525 reports them as wages, otherwise line 15). The model leaves + # them out of federal AGI (irs_gross_income) and dependent_gross_income, + # so all of them count here, once. + - disability_benefits + # Unemployment compensation outside federal AGI, such as the 2020 IRC + # 85(c) exclusion (2020 line 8, "all items of income ... not reported on + # lines 1 through 7"; 2014-2017 worksheets, "Alimony, cash public + # assistance, unemployment"; Schedule 2EC line 14 from 2024, the total + # received). + - mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation # Refundable credits received (2023 schedule line 7, Schedule 2EC line 8 # from 2024): Montana's refundable credits other than this credit, # and this credit as received during the year (ARM 42.4.301(2)(c)). @@ -81,6 +101,8 @@ values: - tanf_person - workers_compensation - gi_cash_assistance + - disability_benefits + - mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation - mt_refundable_credits_before_renter_credit - mt_elderly_homeowner_or_renter_credit_received - mt_elderly_homeowner_or_renter_credit_federal_refundable_credits @@ -101,6 +123,8 @@ values: - tanf_person - workers_compensation - gi_cash_assistance + - disability_benefits + - mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation - mt_refundable_credits_before_renter_credit - mt_elderly_homeowner_or_renter_credit_received - mt_elderly_homeowner_or_renter_credit_federal_refundable_credits diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_disability_and_unemployment.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_disability_and_unemployment.yaml new file mode 100644 index 00000000000..16213150c69 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_disability_and_unemployment.yaml @@ -0,0 +1,335 @@ +# Employment disability benefits and unemployment compensation outside +# federal AGI in gross household income. § 15-30-2337(9)(a) counts federal +# AGI "plus all nontaxable income". The 2014-2023 instructions list +# "Disability benefits including, but not limited to, veteran's disability, +# SSI payments, and workers' compensation"; the 2014-2017 worksheets list +# "Alimony, cash public assistance, unemployment"; 2024 Schedule 2EC line 14 +# counts "the total of unemployment compensation received". SSI is pinned to +# zero so that each case tests only the item it names. + +- name: Case 1, 2016 Form 2EC, the claimant's disability benefits count. + period: 2016 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 80 + taxable_pension_income: 12_000 + disability_benefits: 2_500 + rent: 6_000 + ssi: 0 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_name: MT + output: + # Gross Household Income Worksheet: line 8 pensions 12_000; line 9 + # disability benefits 2_500; line 10 = 14_500, Form 2EC line 1. + mt_elderly_homeowner_or_renter_credit_gross_household_income: 14_500 + # Line 2 6_300; line 3 = 8_200; line 4 = 0.039; line 5 = 319.80. + mt_elderly_homeowner_or_renter_credit_net_household_income: 319.80 + # Line 7 rent 6_000; line 8 = 900; line 9 = 900; line 10 = 900 - 319.80 + # = 580.20; line 11 = 580.20; line 12 = 100%; line 13 = 580.20. Without + # the disability benefits, line 1 = 12_000, line 5 = 5_700 x 0.028 = + # 159.60 and the credit would be 740.40. + mt_elderly_homeowner_or_renter_credit: 580.20 + +- name: Case 2, 2017 Form 2EC, a household member's disability benefits count. + period: 2017 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 72 + taxable_pension_income: 15_000 + real_estate_taxes: 1_200 + ssi: 0 + person2: + age: 45 + disability_benefits: 5_000 + ssi: 0 + tax_units: + tax_unit1: + members: [person1] + tax_unit2: + members: [person2] + households: + household: + members: [person1, person2] + state_name: MT + output: + # The claimant's adult son files his own return. Gross Household Income + # Worksheet: line 6 pensions 15_000; line 7 his disability benefits + # 5_000; line 8 = 20_000, Form 2EC line 1. + mt_elderly_homeowner_or_renter_credit_gross_household_income: [15_000, 5_000] + # Line 2 6_300; line 3 = 13_700; line 4 = 0.05; line 5 = 685. + mt_elderly_homeowner_or_renter_credit_net_household_income: [685, 0] + # Line 6 = 1_200; line 9 = 1_200; line 10 = 515; line 11 = 515; line 12 + # = 100%; line 13 = 515. Without his benefits, line 1 = 15_000, line 5 = + # 8_700 x 0.039 = 339.30 and the credit would be 860.70. + mt_elderly_homeowner_or_renter_credit: [515, 0] + +- name: Case 3, 2023 schedule line 8, a spouse's disability benefits count. + period: 2023 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 66 + taxable_pension_income: 18_000 + real_estate_taxes: 1_000 + ssi: 0 + person2: + age: 64 + disability_benefits: 4_000 + ssi: 0 + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_name: MT + output: + # Joint return. Line 1 federal AGI 18_000; line 8 disability benefits + # 4_000; line 10 = 22_000. + mt_elderly_homeowner_or_renter_credit_gross_household_income: [18_000, 4_000] + # Line 11 12_600; line 12 = 9_400; line 13 = 0.042; line 14 = 394.80. + mt_elderly_homeowner_or_renter_credit_net_household_income: [394.80, 0] + # Line 15 = 1_000; line 18 = 1_000; line 19 = 605.20; line 20 = 605.20; + # line 21 = 100%; line 22 = 605.20. Without the benefits, line 10 = + # 18_000, line 14 = 5_400 x 0.028 = 151.20 and the credit would be + # 848.80. + mt_elderly_homeowner_or_renter_credit: [605.20, 0] + +- name: Case 4, 2024 Schedule 2EC line 17, a household member's disability benefits count. + period: 2024 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 75 + taxable_pension_income: 20_000 + rent: 9_600 + ssi: 0 + person2: + age: 45 + disability_benefits: 7_000 + ssi: 0 + tax_units: + tax_unit1: + members: [person1] + tax_unit2: + members: [person2] + households: + household: + members: [person1, person2] + state_name: MT + output: + # The claimant's adult son files his own return. Line 5 pensions 20_000; + # line 17 his disability benefits (line 1 or line 15 items for another + # member) 7_000; line 18 = 27_000. + mt_elderly_homeowner_or_renter_credit_gross_household_income: [20_000, 7_000] + # Line 19 12_600; line 20 = 14_400; line 21 = 0.05; line 22 = 720. + mt_elderly_homeowner_or_renter_credit_net_household_income: [720, 0] + # Line 24 rent 9_600; line 25 = 1_440; line 26 = 1_440; line 27 = 720; + # line 28 = 720; line 29 = 100%; line 30 = 720. Without his benefits, + # line 18 = 20_000, line 22 = 7_400 x 0.035 = 259 and the credit would + # be the 1_150 cap. + mt_elderly_homeowner_or_renter_credit: [720, 0] + +- name: Case 5, 2025 Schedule 2EC, the claimant's own disability benefits count. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 64 + taxable_pension_income: 16_000 + disability_benefits: 6_000 + real_estate_taxes: 1_300 + ssi: 0 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_name: MT + output: + # Line 5 pensions 16_000; line 1 (if taxable, reported as wages) or line + # 15 (if not) disability benefits 6_000; line 18 = 22_000. + mt_elderly_homeowner_or_renter_credit_gross_household_income: 22_000 + # Line 19 12_600; line 20 = 9_400; line 21 = 0.042; line 22 = 394.80. + mt_elderly_homeowner_or_renter_credit_net_household_income: 394.80 + # Line 23 = 1_300; line 26 = 1_300; line 27 = 905.20; line 28 = 905.20; + # line 29 = 100%; line 30 = 905.20. Without the benefits, line 18 = + # 16_000, line 22 = 3_400 x 0.016 = 54.40 and the credit would be the + # 1_150 cap. + mt_elderly_homeowner_or_renter_credit: 905.20 + +- name: Case 6, 2020 schedule line 8, the claimant's unemployment compensation excluded from federal AGI counts. + period: 2020 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 66 + taxable_pension_income: 16_000 + unemployment_compensation: 9_000 + real_estate_taxes: 1_500 + ssi: 0 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_name: MT + output: + # IRC 85(c) excludes the 9_000 from 2020 federal AGI (AGI without it is + # 16_000, under 150_000). Line 1 federal AGI 16_000; line 7 refundable + # credits received, the 2020 recovery rebate credit 1_200 + 600 = 1_800; + # line 8 other income not listed above, the excluded 9_000; line 10 = + # 26_800. + adjusted_gross_income_person: 16_000 + mt_elderly_homeowner_or_renter_credit_federal_refundable_credits: 1_800 + mt_elderly_homeowner_or_renter_credit_gross_household_income: 26_800 + # Line 11 6_300; line 12 = 20_500; line 13 = 0.05; line 14 = 1_025. + mt_elderly_homeowner_or_renter_credit_net_household_income: 1_025 + # Line 15 = 1_500; line 18 = 1_500; line 19 = 475; line 20 = 475; line 21 + # = 100%; line 22 = 475. Without line 8, line 10 = 17_800, line 14 = + # 11_500 x 0.048 = 552 and the credit would be 948. + mt_elderly_homeowner_or_renter_credit: 475 + +- name: Case 7, 2020 schedule line 8, a household member's compensation above the exclusion limit counts in full. + period: 2020 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 72 + taxable_pension_income: 14_000 + rent: 12_000 + ssi: 0 + person2: + age: 40 + unemployment_compensation: 14_000 + ssi: 0 + tax_units: + tax_unit1: + members: [person1] + tax_unit2: + members: [person2] + households: + household: + members: [person1, person2] + state_name: MT + output: + # The claimant's daughter files her own return. Of her 14_000, 10_200 is + # excluded and 14_000 - 10_200 = 3_800 is in her federal AGI. Line 1 + # federal AGI 14_000 + 3_800 = 17_800; line 7 each return's 2020 + # recovery rebate credit, 1_800 + 1_800 = 3_600; line 8 her excluded + # 10_200; line 10 = 31_600. + adjusted_gross_income_person: [14_000, 3_800] + mt_elderly_homeowner_or_renter_credit_gross_household_income: [15_800, 15_800] + # Line 11 6_300; line 12 = 25_300; line 13 = 0.05; line 14 = 1_265. + mt_elderly_homeowner_or_renter_credit_net_household_income: [1_265, 0] + # Line 16 rent 12_000; line 17 = 1_800; line 18 = 1_800; line 19 = 535; + # line 20 = 535; line 21 = 100% (under 35_000); line 22 = 535. Without + # line 8, line 10 = 21_400, line 14 = 15_100 x 0.05 = 755 and the credit + # would be the 1_000 cap. + mt_elderly_homeowner_or_renter_credit: [535, 0] + +- name: Case 8, 2020 a dependent's compensation counts once, in their own gross income. + period: 2020 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + taxable_pension_income: 15_000 + real_estate_taxes: 1_400 + ssi: 0 + person2: + age: 20 + is_full_time_student: true + is_tax_unit_dependent: true + unemployment_compensation: 4_000 + ssi: 0 + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_name: MT + output: + # The claimant's grandson, a student, is her dependent. All of his 4_000 + # is excluded from federal AGI, and his own gross income counts it in + # full, so nothing more is added for it. Line 1 federal AGI 15_000; line + # 7 the recovery rebate credit 1_800; line 8 his 4_000; line 10 = 20_800. + mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation: [0, 0] + mt_elderly_homeowner_or_renter_credit_gross_household_income: [16_800, 4_000] + # Line 12 = 14_500; line 13 = 0.05; line 14 = 725. + mt_elderly_homeowner_or_renter_credit_net_household_income: [725, 0] + # Line 15 = 1_400; line 19 = 675; line 20 = 675; line 22 = 675. + mt_elderly_homeowner_or_renter_credit: [675, 0] + +- name: Case 9, 2021 taxable unemployment compensation counts once, in federal AGI. + period: 2021 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 66 + taxable_pension_income: 16_000 + unemployment_compensation: 9_000 + real_estate_taxes: 1_500 + ssi: 0 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_name: MT + output: + # No exclusion in 2021. Line 1 federal AGI 25_000; line 7 the 2021 + # recovery rebate credit 1_400; line 10 = 26_400. + mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation: 0 + mt_elderly_homeowner_or_renter_credit_gross_household_income: 26_400 + # Line 12 = 20_100; line 13 = 0.05; line 14 = 1_005. + mt_elderly_homeowner_or_renter_credit_net_household_income: 1_005 + # Line 19 = 1_500 - 1_005 = 495; line 20 = 495; line 22 = 495. + mt_elderly_homeowner_or_renter_credit: 495 + +- name: Case 10, 2024 Schedule 2EC line 14, unemployment compensation counts once. + period: 2024 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 68 + taxable_pension_income: 15_000 + unemployment_compensation: 6_000 + real_estate_taxes: 1_200 + ssi: 0 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_name: MT + output: + # Line 5 pensions 15_000; line 14 unemployment compensation 6_000, all + # in federal AGI; line 18 = 21_000. + mt_elderly_homeowner_or_renter_credit_gross_household_income: 21_000 + # Line 20 = 8_400; line 21 = 0.039; line 22 = 327.60. + mt_elderly_homeowner_or_renter_credit_net_household_income: 327.60 + # Line 27 = 1_200 - 327.60 = 872.40; line 28 = 872.40; line 30 = 872.40. + mt_elderly_homeowner_or_renter_credit: 872.40 diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation.yaml new file mode 100644 index 00000000000..4b7e707a426 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation.yaml @@ -0,0 +1,190 @@ +# Unemployment compensation that neither federal AGI nor a dependent's own +# gross income counts. § 15-30-2337(9)(a) adds "all nontaxable income" to +# federal AGI. In 2020, IRC 85(c) excluded up to 10_200 of unemployment +# compensation from gross income when AGI without it was under 150_000. + +- name: Case 1, 2020 compensation under the exclusion limit is all nontaxable. + period: 2020 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 66 + taxable_pension_income: 20_000 + unemployment_compensation: 8_000 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_name: MT + output: + # AGI without the compensation is 20_000, under 150_000, and 8_000 is + # under 10_200, so none of it is in federal AGI. + taxable_unemployment_compensation: 0 + mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation: 8_000 + +- name: Case 2, 2020 compensation above the exclusion limit. + period: 2020 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 66 + taxable_pension_income: 20_000 + unemployment_compensation: 15_000 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_name: MT + output: + # 15_000 - 10_200 = 4_800 is in federal AGI; the excluded 10_200 is not. + taxable_unemployment_compensation: 4_800 + mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation: 10_200 + +- name: Case 3, 2020 income at the 150,000 cutoff gets no exclusion. + period: 2020 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 66 + taxable_pension_income: 150_000 + unemployment_compensation: 8_000 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_name: MT + output: + # AGI without the compensation is 150_000, not less than 150_000, so all + # of it is in federal AGI. + taxable_unemployment_compensation: 8_000 + mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation: 0 + +- name: Case 4, 2021 compensation is all taxable. + period: 2021 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 66 + taxable_pension_income: 20_000 + unemployment_compensation: 8_000 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_name: MT + output: + taxable_unemployment_compensation: 8_000 + mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation: 0 + +- name: Case 5, 2024 compensation is all taxable. + period: 2024 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 66 + taxable_pension_income: 20_000 + unemployment_compensation: 8_000 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_name: MT + output: + taxable_unemployment_compensation: 8_000 + mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation: 0 + +- name: Case 6, 2020 joint return, the spouse who received the compensation. + period: 2020 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 68 + taxable_pension_income: 20_000 + person2: + age: 64 + unemployment_compensation: 12_000 + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_name: MT + output: + # 12_000 - 10_200 = 1_800 is in the spouse's share of federal AGI. + taxable_unemployment_compensation: [0, 1_800] + mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation: [0, 10_200] + +- name: Case 7, 2020 a dependent's compensation is already in their own gross income. + period: 2020 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 68 + taxable_pension_income: 20_000 + person2: + age: 64 + unemployment_compensation: 8_000 + person3: + age: 20 + is_full_time_student: true + is_tax_unit_dependent: true + unemployment_compensation: 4_000 + tax_units: + tax_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_name: MT + output: + # The model applies the tax unit's 10_200 exclusion to the 12_000 its + # members received, including the dependent's, and allocates the taxable + # 1_800 by share: 1_200 to the spouse and 600 to the dependent. + taxable_unemployment_compensation: [0, 1_200, 600] + # The dependent's 4_000 counts in full in their own gross income + # (dependent_gross_income), so none of it is added here. The spouse's + # 8_000 counts as 1_200 in federal AGI plus 6_800 here. + dependent_gross_income: [0, 0, 4_000] + mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation: [0, 6_800, 0] + +- name: Case 8, a person recorded as both a dependent and the head. + period: 2024 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + is_tax_unit_dependent: true + unemployment_compensation: 5_000 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_name: MT + output: + # Federal AGI counts people who are not dependents and + # dependent_gross_income people who are not the head or spouse, so + # neither counts this person's compensation; all of it is added here. + adjusted_gross_income_person: 0 + dependent_gross_income: 0 + mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation: 5_000 diff --git a/policyengine_us/variables/gov/states/mt/tax/income/credits/mt_elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation.py b/policyengine_us/variables/gov/states/mt/tax/income/credits/mt_elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation.py new file mode 100644 index 00000000000..9560c87948e --- /dev/null +++ b/policyengine_us/variables/gov/states/mt/tax/income/credits/mt_elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation.py @@ -0,0 +1,48 @@ +from policyengine_us.model_api import * + + +class mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation( + Variable +): + value_type = float + entity = Person + label = "Montana elderly homeowner/renter credit unemployment compensation outside federal AGI" + documentation = ( + "Unemployment compensation a household member received that neither " + "federal adjusted gross income nor a dependent's own gross income " + "counts, such as the part excluded from 2020 federal gross income " + "under IRC 85(c). It counts in gross household income as nontaxable " + "income." + ) + unit = USD + definition_period = YEAR + defined_for = StateCode.MT + reference = ( + # § 15-30-2337(9)(a): federal adjusted gross income "plus all + # nontaxable income" + "https://mca.legmt.gov/bills/mca/title_0150/chapter_0300/part_0230/section_0370/0150-0300-0230-0370.html", + # IRC 85(c), added by ARPA § 9042: up to $10,200 of 2020 + # unemployment compensation excluded from gross income + "https://www.law.cornell.edu/uscode/text/26/85#c", + # 2020 Form 2 instructions, line 8: "Enter all items of income + # received by the members of the household that were not reported on + # lines 1 through 7" + "https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2020_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=45", + # 2024 Schedule 2EC, line 14: "Enter the total of unemployment + # compensation received during the year" + "https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2024_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=48", + ) + + def formula(person, period, parameters): + # Gross household income counts all the unemployment compensation a + # member received, taxable or not. Federal AGI already counts the + # taxable part of a filer's (irs_gross_income counts people who are + # not dependents), and a dependent's own gross income counts all of a + # dependent's (dependent_gross_income counts people who are not the + # head or spouse, without the IRC 85(c) exclusion). Add the rest. + received = max_(0, person("unemployment_compensation", period)) + is_dependent = person("is_tax_unit_dependent", period) + head_or_spouse = person("is_tax_unit_head_or_spouse", period) + taxable = max_(0, person("taxable_unemployment_compensation", period)) + counted = where(is_dependent, ~head_or_spouse * received, taxable) + return max_(received - counted, 0) From 520fe35ea50b755b59c6e5b2185ee8c29a36d82e Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Mon, 12 Oct 2026 14:24:26 -0400 Subject: [PATCH 07/11] Test the 2020 cutoff above the band the federal test double subtracts; add changelog Co-Authored-By: Claude Opus 5.5 --- .../mt-elderly-credit-disability-unemployment.fixed.md | 1 + ..._renter_credit_nontaxable_unemployment_compensation.yaml | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) create mode 100644 changelog.d/mt-elderly-credit-disability-unemployment.fixed.md diff --git a/changelog.d/mt-elderly-credit-disability-unemployment.fixed.md b/changelog.d/mt-elderly-credit-disability-unemployment.fixed.md new file mode 100644 index 00000000000..00d4cb4a5c6 --- /dev/null +++ b/changelog.d/mt-elderly-credit-disability-unemployment.fixed.md @@ -0,0 +1 @@ +Count employment disability benefits and unemployment compensation excluded from federal AGI (the 2020 IRC 85(c) exclusion) in Montana's elderly homeowner/renter credit gross household income. diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation.yaml index 4b7e707a426..6b8021bb2a4 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation.yaml @@ -46,14 +46,14 @@ taxable_unemployment_compensation: 4_800 mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation: 10_200 -- name: Case 3, 2020 income at the 150,000 cutoff gets no exclusion. +- name: Case 3, 2020 income above the 150,000 cutoff gets no exclusion. period: 2020 absolute_error_margin: 0.01 input: people: person1: age: 66 - taxable_pension_income: 150_000 + taxable_pension_income: 160_000 unemployment_compensation: 8_000 tax_units: tax_unit: @@ -63,7 +63,7 @@ members: [person1] state_name: MT output: - # AGI without the compensation is 150_000, not less than 150_000, so all + # AGI without the compensation is 160_000, not less than 150_000, so all # of it is in federal AGI. taxable_unemployment_compensation: 8_000 mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation: 0 From 02f4fabb258b11a6137bf5df33547cd96d56fb60 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Mon, 12 Oct 2026 14:38:52 -0400 Subject: [PATCH 08/11] Add a grid invariant test: disability benefits and unemployment compensation count once in every arrangement and year Co-Authored-By: Claude Opus 5.5 --- ...est_mt_elderly_credit_nontaxable_income.py | 293 ++++++++++++++++++ 1 file changed, 293 insertions(+) create mode 100644 policyengine_us/tests/test_mt_elderly_credit_nontaxable_income.py diff --git a/policyengine_us/tests/test_mt_elderly_credit_nontaxable_income.py b/policyengine_us/tests/test_mt_elderly_credit_nontaxable_income.py new file mode 100644 index 00000000000..be9b2281fed --- /dev/null +++ b/policyengine_us/tests/test_mt_elderly_credit_nontaxable_income.py @@ -0,0 +1,293 @@ +"""Invariant tests: disability benefits and unemployment compensation in the +Montana elderly homeowner/renter credit. + +MCA 15-30-2337(9)(a) counts federal adjusted gross income "plus all +nontaxable income", and (4) counts "all income received by all individuals +of a household". 2024 Schedule 2EC line 14 counts "the total of unemployment +compensation received during the year"; the 2014-2023 instructions list +disability benefits. The model leaves employment disability benefits out of +federal AGI, and in 2020 IRC 85(c) excluded up to 10_200 of unemployment +compensation from it. Federal AGI counts the taxable part of a filer's +compensation and a dependent's own gross income all of a dependent's. + +For a claimant aged 66 (taxable pension, unemployment compensation, +disability benefits, property tax) living with one other adult (unemployment +compensation, disability benefits), in 2019, 2020, 2021 and 2024, in three +arrangements: + + dependent: one return, the other adult a 20-year-old student dependent; + own_return: two returns, the other adult (45) filing their own; + joint: one joint return, the other adult (60) the claimant's spouse; + +over a grid of amounts that puts the compensation under and over the 10_200 +limit, and income under and over the 150_000 cutoff: + +1. The household's gross household income is the pension plus every + member's unemployment compensation and disability benefits, each once, + plus the refundable credits the household received (read from the model; + no one has earnings, so these are the recovery rebate credits). +2. The credit equals an independent reading of the schedule (standard + exclusion, Household Income Reduction Table, cap, Credit Multiplier + Table), lies between zero and the cap, and is zero at 45_000 or more. +3. More unemployment compensation or disability benefits never raise the + credit while the refundable credits stay the same. + +The YAML cases pin worked examples from each year's form. This test adds +what they cannot: every arrangement and year at once against a reference +written from the statute rather than the model's income paths, so a double +count through federal AGI, dependent_gross_income or the 2020 exclusion +shows up. It builds one vectorized Simulation. +""" + +import gc +import itertools + +import numpy as np +import pytest + +from policyengine_us import Simulation + +YEARS = [2019, 2020, 2021, 2024] +ARRANGEMENTS = ["dependent", "own_return", "joint"] +PENSIONS = [12_000, 160_000] +CLAIMANT_UC = [0, 6_000, 15_000] +MEMBER_UC = [0, 4_000, 12_000] +CLAIMANT_DISABILITY = [0, 3_000] +MEMBER_DISABILITY = [0, 5_000] +PROPERTY_TAX = 1_500 +INCOME_LIMIT = 45_000 +TOLERANCE = 0.01 +# Standard exclusion and cap: $6,300 and $1,000 through 2021; HB 191 (2021) +# raised them to $12,600 and $1,150 from 2022. +EXCLUSION = {2019: 6_300, 2020: 6_300, 2021: 6_300, 2024: 12_600} +CAP = {2019: 1_000, 2020: 1_000, 2021: 1_000, 2024: 1_150} +# Household Income Reduction Table: lower bounds and rates. +REDUCTION_TABLE = [ + (0, 0), + (2_000, 0.006), + (3_000, 0.016), + (4_000, 0.024), + (5_000, 0.028), + (6_000, 0.032), + (7_000, 0.035), + (8_000, 0.039), + (9_000, 0.042), + (10_000, 0.045), + (11_000, 0.048), + (12_000, 0.05), +] +# Credit Multiplier Table: lower bounds of gross household income. +MULTIPLIER_TABLE = [ + (0, 1), + (35_000, 0.4), + (37_501, 0.3), + (40_001, 0.2), + (42_501, 0.1), + (45_000, 0), +] +CASES = [ + dict( + arrangement=arrangement, + pension=pension, + claimant_uc=claimant_uc, + member_uc=member_uc, + claimant_disability=claimant_disability, + member_disability=member_disability, + ) + for ( + arrangement, + pension, + claimant_uc, + member_uc, + claimant_disability, + member_disability, + ) in itertools.product( + ARRANGEMENTS, + PENSIONS, + CLAIMANT_UC, + MEMBER_UC, + CLAIMANT_DISABILITY, + MEMBER_DISABILITY, + ) +] + + +def build_situation(): + def every_year(value): + return {year: value for year in YEARS} + + people, tax_units, marital_units, households = {}, {}, {}, {} + for i, c in enumerate(CASES): + claimant, member = f"claimant_{i}", f"member_{i}" + arrangement = c["arrangement"] + people[claimant] = { + "age": every_year(66), + "taxable_pension_income": every_year(c["pension"]), + "unemployment_compensation": every_year(c["claimant_uc"]), + "disability_benefits": every_year(c["claimant_disability"]), + "real_estate_taxes": every_year(PROPERTY_TAX), + "ssi": every_year(0), + "is_tax_unit_dependent": every_year(False), + } + people[member] = { + "age": every_year( + {"dependent": 20, "own_return": 45, "joint": 60}[arrangement] + ), + "is_full_time_student": every_year(arrangement == "dependent"), + "unemployment_compensation": every_year(c["member_uc"]), + "disability_benefits": every_year(c["member_disability"]), + "ssi": every_year(0), + "is_tax_unit_dependent": every_year(arrangement == "dependent"), + } + if arrangement == "own_return": + tax_units[f"tax_unit_{i}"] = {"members": [claimant]} + tax_units[f"tax_unit_{i}_member"] = {"members": [member]} + else: + tax_units[f"tax_unit_{i}"] = {"members": [claimant, member]} + if arrangement == "joint": + marital_units[f"marital_unit_{i}"] = {"members": [claimant, member]} + else: + marital_units[f"marital_unit_{i}"] = {"members": [claimant]} + marital_units[f"marital_unit_{i}_member"] = {"members": [member]} + households[f"household_{i}"] = { + "members": [claimant, member], + "state_code": every_year("MT"), + } + return { + "people": people, + "tax_units": tax_units, + "marital_units": marital_units, + "households": households, + } + + +@pytest.fixture(scope="module") +def results(): + """Household totals by year: gross household income, the credit, and + the refundable credits received.""" + simulation = Simulation(situation=build_situation()) + + def by_household(variable, year): + return np.asarray(simulation.calculate(variable, year, map_to="household")) + + results = { + year: { + "gross_household_income": by_household( + "mt_elderly_homeowner_or_renter_credit_gross_household_income", + year, + ), + "credit": by_household("mt_elderly_homeowner_or_renter_credit", year), + "refundable_credits": by_household( + "mt_elderly_homeowner_or_renter_credit_federal_refundable_credits", + year, + ) + + by_household("mt_refundable_credits_before_renter_credit", year), + } + for year in YEARS + } + # Keep only the arrays: free the simulation before the rest of the + # process's tests run. + del simulation + gc.collect() + return results + + +def lookup(table, amount): + rate = 0 + for lower, value in table: + if amount >= lower: + rate = value + return rate + + +def expected_credit(year, gross_household_income): + household_income = max(gross_household_income - EXCLUSION[year], 0) + net_household_income = household_income * lookup(REDUCTION_TABLE, household_income) + uncapped = max(PROPERTY_TAX - net_household_income, 0) + return min(uncapped, CAP[year]) * lookup(MULTIPLIER_TABLE, gross_household_income) + + +def tolerance(amount): + return max(TOLERANCE, 8 * float(np.spacing(np.float32(abs(amount))))) + + +@pytest.mark.parametrize("year", YEARS) +def test_each_amount_counts_once(results, year): + r = results[year] + for i, c in enumerate(CASES): + expected = ( + c["pension"] + + c["claimant_uc"] + + c["member_uc"] + + c["claimant_disability"] + + c["member_disability"] + + r["refundable_credits"][i] + ) + assert r["gross_household_income"][i] == pytest.approx( + expected, abs=tolerance(expected) + ), (year, c) + + +@pytest.mark.parametrize("year", YEARS) +def test_credit_follows_the_schedule(results, year): + r = results[year] + for i, c in enumerate(CASES): + ghi = float(r["gross_household_income"][i]) + credit = float(r["credit"][i]) + tol = tolerance(ghi) + assert credit == pytest.approx(expected_credit(year, ghi), abs=tol), ( + year, + c, + ) + assert -tol <= credit <= CAP[year] + tol, (year, c) + if ghi >= INCOME_LIMIT: + assert credit == 0, (year, c) + + +@pytest.mark.parametrize("year", YEARS) +def test_more_income_never_raises_the_credit(results, year): + r = results[year] + index = {tuple(sorted(c.items())): i for i, c in enumerate(CASES)} + axes = { + "claimant_uc": CLAIMANT_UC, + "member_uc": MEMBER_UC, + "claimant_disability": CLAIMANT_DISABILITY, + "member_disability": MEMBER_DISABILITY, + } + compared = 0 + for i, c in enumerate(CASES): + for key, values in axes.items(): + position = values.index(c[key]) + if position + 1 == len(values): + continue + j = index[tuple(sorted({**c, key: values[position + 1]}.items()))] + if r["refundable_credits"][j] != r["refundable_credits"][i]: + continue + compared += 1 + tol = tolerance(r["gross_household_income"][j]) + assert r["credit"][j] <= r["credit"][i] + tol, (year, c, key) + assert compared > 0 + + +def test_worked_example(results): + """2020 Elderly Homeowner/Renter Credit Schedule, own_return arrangement: + the claimant's pension 12_000 and unemployment compensation 6_000, all + excluded from federal AGI; the other adult's 12_000 of compensation, + 1_800 of it in federal AGI; each return's recovery rebate credit 1_800. + Line 1 = 12_000 + 1_800; line 7 = 3_600; line 8 = 6_000 + 10_200; line + 10 = 33_600; line 12 = 27_300; line 14 = 1_365; line 19 = 135; line 22 = + 135 at the 100% multiplier.""" + i = CASES.index( + dict( + arrangement="own_return", + pension=12_000, + claimant_uc=6_000, + member_uc=12_000, + claimant_disability=0, + member_disability=0, + ) + ) + r = results[2020] + assert r["refundable_credits"][i] == pytest.approx(3_600, abs=TOLERANCE) + assert r["gross_household_income"][i] == pytest.approx(33_600, abs=TOLERANCE) + assert r["credit"][i] == pytest.approx(135, abs=TOLERANCE) From f9d8d64b535b8200c8f94dddfe74bd7acb34a9d9 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Mon, 12 Oct 2026 15:37:33 -0400 Subject: [PATCH 09/11] Pin SSI in the one-claimant property test; format reference titles #9900's one-claimant property test (now on main) builds claimants aged 65 or older with little income, for whom the model computes SSI, which gross household income now counts; its reference leaves SSI out, so the builder inputs none. Reference titles follow the repo format: no page in a single-page title, and quoted titles ending in "#page N-M" for several. Co-Authored-By: Claude Opus 5.5 --- .../gross_income_sources.yaml | 12 ++++++------ .../tests/test_mt_elderly_credit_one_claimant.py | 4 ++++ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/policyengine_us/parameters/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/gross_income_sources.yaml b/policyengine_us/parameters/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/gross_income_sources.yaml index 14a8ead4344..fb84aef0128 100644 --- a/policyengine_us/parameters/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/gross_income_sources.yaml +++ b/policyengine_us/parameters/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/gross_income_sources.yaml @@ -18,17 +18,17 @@ metadata: href: https://rules.mt.gov/api/policy-library-public/collections/aec52c46-128e-4279-9068-8af5d5432d74/policies/c90ea93a-03a2-4605-a0f8-f2f3760198bf/document/297c7a8d-f6f4-4b70-a7b7-fe1cedee53e7 - title: ARM 42.4.301(2) as in effect from 9/7/2024 ("federal refundable tax credits received" and "any state refundable tax credits received") href: https://rules.mt.gov/api/policy-library-public/collections/aec52c46-128e-4279-9068-8af5d5432d74/policies/c90ea93a-03a2-4605-a0f8-f2f3760198bf/document/768c8344-24ee-4950-9d5e-9d8fc97ec0f7 - - title: 2016 Montana Form 2EC instructions, Part II, disability benefits including SSI payments and workers' compensation, and cash public assistance and relief (PDF p.74) + - title: 2016 Montana Form 2EC instructions, Part II, disability benefits including SSI payments and workers' compensation, and cash public assistance and relief href: https://taxsim.nber.org/historical_state_tax_forms/MT/2016/Form_2_booklet_2016.pdf#page=74 - - title: 2017 Montana Form 2EC instructions, Part II, disability benefits including SSI payments and workers' compensation, and cash public assistance and relief; Gross Household Income Worksheet, items 4 and 5 (PDF pp.64-65) + - title: "2017 Montana Form 2EC instructions, Part II, disability benefits including SSI payments and workers' compensation, and cash public assistance and relief; Gross Household Income Worksheet, items 4 and 5 #page 64-65" href: https://taxsim.nber.org/historical_state_tax_forms/MT/2017/Form%202%202017%20Booklet.pdf#page=64 - - title: 2022 Montana Form 2 instructions, Elderly Homeowner/Renter Credit Schedule, gross household income; line 8, disability benefits including SSI payments and workers' compensation (PDF pp.47-48) + - title: "2022 Montana Form 2 instructions, Elderly Homeowner/Renter Credit Schedule, gross household income; line 8, disability benefits including SSI payments and workers' compensation #page 47-48" href: https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2022_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=47 - - title: 2023 Montana Form 2 instructions, Elderly Homeowner/Renter Credit Schedule, line 7, refundable credits received; line 8, disability benefits including SSI payments and workers' compensation (PDF pp.51-52) + - title: "2023 Montana Form 2 instructions, Elderly Homeowner/Renter Credit Schedule, line 7, refundable credits received; line 8, disability benefits including SSI payments and workers' compensation #page 51-52" href: https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2023_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=51 - - title: 2024 Montana Form 2 instructions, Schedule 2EC, gross household income; line 8, refundable credits received; line 16, government assistance (PDF pp.46-48) + - title: "2024 Montana Form 2 instructions, Schedule 2EC, gross household income; line 8, refundable credits received; line 16, government assistance #page 46-48" href: https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2024_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=46 - - title: 2025 Montana Form 2 instructions, Schedule 2EC, line 8, refundable credits received; line 16, government assistance (PDF pp.45-46) + - title: "2025 Montana Form 2 instructions, Schedule 2EC, line 8, refundable credits received; line 16, government assistance #page 45-46" href: https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2025_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=45 values: diff --git a/policyengine_us/tests/test_mt_elderly_credit_one_claimant.py b/policyengine_us/tests/test_mt_elderly_credit_one_claimant.py index d1dc874a300..ae224c8dea5 100644 --- a/policyengine_us/tests/test_mt_elderly_credit_one_claimant.py +++ b/policyengine_us/tests/test_mt_elderly_credit_one_claimant.py @@ -68,6 +68,10 @@ def build_situation(households): "taxable_pension_income": {YEAR: adult["pension"]}, "taxable_interest_income": {YEAR: adult["interest"]}, "social_security_retirement": {YEAR: adult["social_security"]}, + # The model would compute SSI for an adult with + # little income; SSI has its own tests (government + # assistance), so the reference leaves it out. + "ssi": {YEAR: 0}, "is_tax_unit_dependent": {YEAR: False}, } unit_members.append(person) From e3c78ee4dd042925acc5cfd0f18fa0055ed7b81f Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Mon, 12 Oct 2026 16:52:46 -0400 Subject: [PATCH 10/11] Name line 5 for disability pensions, describe the add-back's role edge, and test each list period's wiring Co-Authored-By: Claude Opus 5.5 --- .../gross_income_sources.yaml | 9 ++++---- ...er_credit_disability_and_unemployment.yaml | 5 +++-- ..._nontaxable_unemployment_compensation.yaml | 22 +++++++++++++++++++ ...it_nontaxable_unemployment_compensation.py | 8 ++++--- 4 files changed, 35 insertions(+), 9 deletions(-) diff --git a/policyengine_us/parameters/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/gross_income_sources.yaml b/policyengine_us/parameters/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/gross_income_sources.yaml index dee324147e0..b1c5219cc51 100644 --- a/policyengine_us/parameters/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/gross_income_sources.yaml +++ b/policyengine_us/parameters/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/gross_income_sources.yaml @@ -69,10 +69,11 @@ values: # Disability benefits from employment other than workers' compensation # (2014-2023 instructions: "Disability benefits including, but not # limited to, veteran's disability, SSI payments, and workers' - # compensation"; from 2024, Schedule 2EC line 1 when taxable, as IRS - # Pub. 525 reports them as wages, otherwise line 15). The model leaves - # them out of federal AGI (irs_gross_income) and dependent_gross_income, - # so all of them count here, once. + # compensation"; from 2024, Schedule 2EC line 1 for taxable sick pay and + # disability pay reported as wages, line 5 for a disability pension after + # minimum retirement age (IRS Pub. 525), otherwise line 15). The model + # leaves them out of federal AGI (irs_gross_income) and + # dependent_gross_income, so all of them count here, once. - disability_benefits # Unemployment compensation outside federal AGI, such as the 2020 IRC # 85(c) exclusion (2020 line 8, "all items of income ... not reported on diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_disability_and_unemployment.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_disability_and_unemployment.yaml index 16213150c69..dfc3f503924 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_disability_and_unemployment.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_disability_and_unemployment.yaml @@ -160,8 +160,9 @@ members: [person1] state_name: MT output: - # Line 5 pensions 16_000; line 1 (if taxable, reported as wages) or line - # 15 (if not) disability benefits 6_000; line 18 = 22_000. + # Line 5 pensions 16_000; disability benefits 6_000 on line 1 if taxable + # and reported as wages, line 5 if a disability pension after minimum + # retirement age, line 15 if nontaxable; line 18 = 22_000 either way. mt_elderly_homeowner_or_renter_credit_gross_household_income: 22_000 # Line 19 12_600; line 20 = 9_400; line 21 = 0.042; line 22 = 394.80. mt_elderly_homeowner_or_renter_credit_net_household_income: 394.80 diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation.yaml index 6b8021bb2a4..19bfa5303e4 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation.yaml @@ -188,3 +188,25 @@ adjusted_gross_income_person: 0 dependent_gross_income: 0 mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation: 5_000 + # The 2023 list carries it into gross household income. + mt_elderly_homeowner_or_renter_credit_gross_household_income: 5_000 + +- name: Case 9, the same person in 2016 under the 2009 list. + period: 2016 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + is_tax_unit_dependent: true + unemployment_compensation: 5_000 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_name: MT + output: + mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation: 5_000 + mt_elderly_homeowner_or_renter_credit_gross_household_income: 5_000 diff --git a/policyengine_us/variables/gov/states/mt/tax/income/credits/mt_elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation.py b/policyengine_us/variables/gov/states/mt/tax/income/credits/mt_elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation.py index 9560c87948e..2fa0260e413 100644 --- a/policyengine_us/variables/gov/states/mt/tax/income/credits/mt_elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation.py +++ b/policyengine_us/variables/gov/states/mt/tax/income/credits/mt_elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation.py @@ -10,9 +10,11 @@ class mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation documentation = ( "Unemployment compensation a household member received that neither " "federal adjusted gross income nor a dependent's own gross income " - "counts, such as the part excluded from 2020 federal gross income " - "under IRC 85(c). It counts in gross household income as nontaxable " - "income." + "counts. For a filer this is the part excluded from 2020 federal " + "gross income under IRC 85(c), which gross household income counts as " + "nontaxable income. For a person recorded as both a dependent and the " + "head or spouse, whom neither income path counts, it is all of their " + "compensation." ) unit = USD definition_period = YEAR From 32fc16d2929139fd3997833712e63444c58cf141 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Mon, 12 Oct 2026 19:26:21 -0400 Subject: [PATCH 11/11] Rename the add-back to mt_elderly_homeowner_or_renter_credit_unemployment_compensation_addback; supply Case 7's taxable allocation as an input Both review rounds noted that the helper adds more than nontaxable compensation for a person recorded as both a dependent and the head. Case 7 no longer pins the federal exclusion's allocation, which PolicyEngine/policyengine-us#10175 changes. Co-Authored-By: Claude Opus 5.5 --- .../gross_income_sources.yaml | 16 ++++---- ...er_credit_disability_and_unemployment.yaml | 4 +- ...it_unemployment_compensation_addback.yaml} | 38 +++++++++++-------- ...edit_unemployment_compensation_addback.py} | 6 +-- 4 files changed, 34 insertions(+), 30 deletions(-) rename policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/{mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation.yaml => mt_elderly_homeowner_or_renter_credit_unemployment_compensation_addback.yaml} (77%) rename policyengine_us/variables/gov/states/mt/tax/income/credits/mt_elderly_homeowner_or_renter/{mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation.py => mt_elderly_homeowner_or_renter_credit_unemployment_compensation_addback.py} (95%) diff --git a/policyengine_us/parameters/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/gross_income_sources.yaml b/policyengine_us/parameters/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/gross_income_sources.yaml index b1c5219cc51..e58384f3072 100644 --- a/policyengine_us/parameters/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/gross_income_sources.yaml +++ b/policyengine_us/parameters/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/gross_income_sources.yaml @@ -75,12 +75,12 @@ values: # leaves them out of federal AGI (irs_gross_income) and # dependent_gross_income, so all of them count here, once. - disability_benefits - # Unemployment compensation outside federal AGI, such as the 2020 IRC - # 85(c) exclusion (2020 line 8, "all items of income ... not reported on - # lines 1 through 7"; 2014-2017 worksheets, "Alimony, cash public - # assistance, unemployment"; Schedule 2EC line 14 from 2024, the total - # received). - - mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation + # Unemployment compensation that neither federal AGI nor a dependent's + # own gross income counts, such as the 2020 IRC 85(c) exclusion (2020 + # line 8, "all items of income ... not reported on lines 1 through 7"; + # 2014-2017 worksheets, "Alimony, cash public assistance, + # unemployment"; Schedule 2EC line 14 from 2024, the total received). + - mt_elderly_homeowner_or_renter_credit_unemployment_compensation_addback # Refundable credits received (2023 schedule line 7, Schedule 2EC line 8 # from 2024): Montana's refundable credits other than this credit, # and this credit as received during the year (ARM 42.4.301(2)(c)). @@ -103,7 +103,7 @@ values: - workers_compensation - gi_cash_assistance - disability_benefits - - mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation + - mt_elderly_homeowner_or_renter_credit_unemployment_compensation_addback - mt_refundable_credits_before_renter_credit - mt_elderly_homeowner_or_renter_credit_received - mt_elderly_homeowner_or_renter_credit_federal_refundable_credits @@ -125,7 +125,7 @@ values: - workers_compensation - gi_cash_assistance - disability_benefits - - mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation + - mt_elderly_homeowner_or_renter_credit_unemployment_compensation_addback - mt_refundable_credits_before_renter_credit - mt_elderly_homeowner_or_renter_credit_received - mt_elderly_homeowner_or_renter_credit_federal_refundable_credits diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_disability_and_unemployment.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_disability_and_unemployment.yaml index dfc3f503924..9a474ec7a5a 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_disability_and_unemployment.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_disability_and_unemployment.yaml @@ -273,7 +273,7 @@ # is excluded from federal AGI, and his own gross income counts it in # full, so nothing more is added for it. Line 1 federal AGI 15_000; line # 7 the recovery rebate credit 1_800; line 8 his 4_000; line 10 = 20_800. - mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation: [0, 0] + mt_elderly_homeowner_or_renter_credit_unemployment_compensation_addback: [0, 0] mt_elderly_homeowner_or_renter_credit_gross_household_income: [16_800, 4_000] # Line 12 = 14_500; line 13 = 0.05; line 14 = 725. mt_elderly_homeowner_or_renter_credit_net_household_income: [725, 0] @@ -301,7 +301,7 @@ output: # No exclusion in 2021. Line 1 federal AGI 25_000; line 7 the 2021 # recovery rebate credit 1_400; line 10 = 26_400. - mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation: 0 + mt_elderly_homeowner_or_renter_credit_unemployment_compensation_addback: 0 mt_elderly_homeowner_or_renter_credit_gross_household_income: 26_400 # Line 12 = 20_100; line 13 = 0.05; line 14 = 1_005. mt_elderly_homeowner_or_renter_credit_net_household_income: 1_005 diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_unemployment_compensation_addback.yaml similarity index 77% rename from policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation.yaml rename to policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_unemployment_compensation_addback.yaml index 19bfa5303e4..21e4ee2e4f4 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_unemployment_compensation_addback.yaml @@ -23,7 +23,7 @@ # AGI without the compensation is 20_000, under 150_000, and 8_000 is # under 10_200, so none of it is in federal AGI. taxable_unemployment_compensation: 0 - mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation: 8_000 + mt_elderly_homeowner_or_renter_credit_unemployment_compensation_addback: 8_000 - name: Case 2, 2020 compensation above the exclusion limit. period: 2020 @@ -44,7 +44,7 @@ output: # 15_000 - 10_200 = 4_800 is in federal AGI; the excluded 10_200 is not. taxable_unemployment_compensation: 4_800 - mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation: 10_200 + mt_elderly_homeowner_or_renter_credit_unemployment_compensation_addback: 10_200 - name: Case 3, 2020 income above the 150,000 cutoff gets no exclusion. period: 2020 @@ -66,7 +66,7 @@ # AGI without the compensation is 160_000, not less than 150_000, so all # of it is in federal AGI. taxable_unemployment_compensation: 8_000 - mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation: 0 + mt_elderly_homeowner_or_renter_credit_unemployment_compensation_addback: 0 - name: Case 4, 2021 compensation is all taxable. period: 2021 @@ -86,7 +86,7 @@ state_name: MT output: taxable_unemployment_compensation: 8_000 - mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation: 0 + mt_elderly_homeowner_or_renter_credit_unemployment_compensation_addback: 0 - name: Case 5, 2024 compensation is all taxable. period: 2024 @@ -106,7 +106,7 @@ state_name: MT output: taxable_unemployment_compensation: 8_000 - mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation: 0 + mt_elderly_homeowner_or_renter_credit_unemployment_compensation_addback: 0 - name: Case 6, 2020 joint return, the spouse who received the compensation. period: 2020 @@ -129,7 +129,7 @@ output: # 12_000 - 10_200 = 1_800 is in the spouse's share of federal AGI. taxable_unemployment_compensation: [0, 1_800] - mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation: [0, 10_200] + mt_elderly_homeowner_or_renter_credit_unemployment_compensation_addback: [0, 10_200] - name: Case 7, 2020 a dependent's compensation is already in their own gross income. period: 2020 @@ -139,14 +139,17 @@ person1: age: 68 taxable_pension_income: 20_000 + taxable_unemployment_compensation: 0 person2: age: 64 unemployment_compensation: 8_000 + taxable_unemployment_compensation: 1_200 person3: age: 20 is_full_time_student: true is_tax_unit_dependent: true unemployment_compensation: 4_000 + taxable_unemployment_compensation: 600 tax_units: tax_unit: members: [person1, person2, person3] @@ -155,15 +158,18 @@ members: [person1, person2, person3] state_name: MT output: - # The model applies the tax unit's 10_200 exclusion to the 12_000 its - # members received, including the dependent's, and allocates the taxable - # 1_800 by share: 1_200 to the spouse and 600 to the dependent. - taxable_unemployment_compensation: [0, 1_200, 600] - # The dependent's 4_000 counts in full in their own gross income - # (dependent_gross_income), so none of it is added here. The spouse's - # 8_000 counts as 1_200 in federal AGI plus 6_800 here. + # The taxable allocation is an input, so the case does not depend on how + # the federal exclusion is shared. With 1_200 of the spouse's 8_000 and + # 600 of the dependent's 4_000 taxable, the spouse's 8_000 counts as + # 1_200 in federal AGI plus 6_800 here. The dependent's 4_000 counts in + # full in their own gross income (dependent_gross_income), so none of it + # is added here. + adjusted_gross_income_person: [20_000, 1_200, 0] dependent_gross_income: [0, 0, 4_000] - mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation: [0, 6_800, 0] + mt_elderly_homeowner_or_renter_credit_unemployment_compensation_addback: [0, 6_800, 0] + # Each person's compensation once. The head also carries the joint + # return's 2020 recovery rebate credit, 1_200 x 2 + 600 x 2 = 3_600. + mt_elderly_homeowner_or_renter_credit_gross_household_income: [23_600, 8_000, 4_000] - name: Case 8, a person recorded as both a dependent and the head. period: 2024 @@ -187,7 +193,7 @@ # neither counts this person's compensation; all of it is added here. adjusted_gross_income_person: 0 dependent_gross_income: 0 - mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation: 5_000 + mt_elderly_homeowner_or_renter_credit_unemployment_compensation_addback: 5_000 # The 2023 list carries it into gross household income. mt_elderly_homeowner_or_renter_credit_gross_household_income: 5_000 @@ -208,5 +214,5 @@ members: [person1] state_name: MT output: - mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation: 5_000 + mt_elderly_homeowner_or_renter_credit_unemployment_compensation_addback: 5_000 mt_elderly_homeowner_or_renter_credit_gross_household_income: 5_000 diff --git a/policyengine_us/variables/gov/states/mt/tax/income/credits/mt_elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation.py b/policyengine_us/variables/gov/states/mt/tax/income/credits/mt_elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_unemployment_compensation_addback.py similarity index 95% rename from policyengine_us/variables/gov/states/mt/tax/income/credits/mt_elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation.py rename to policyengine_us/variables/gov/states/mt/tax/income/credits/mt_elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_unemployment_compensation_addback.py index 2fa0260e413..407163fa0d5 100644 --- a/policyengine_us/variables/gov/states/mt/tax/income/credits/mt_elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation.py +++ b/policyengine_us/variables/gov/states/mt/tax/income/credits/mt_elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_unemployment_compensation_addback.py @@ -1,12 +1,10 @@ from policyengine_us.model_api import * -class mt_elderly_homeowner_or_renter_credit_nontaxable_unemployment_compensation( - Variable -): +class mt_elderly_homeowner_or_renter_credit_unemployment_compensation_addback(Variable): value_type = float entity = Person - label = "Montana elderly homeowner/renter credit unemployment compensation outside federal AGI" + label = "Montana elderly homeowner/renter credit unemployment compensation add-back" documentation = ( "Unemployment compensation a household member received that neither " "federal adjusted gross income nor a dependent's own gross income "