Skip to content

Count SSI, TANF and workers' compensation in Montana's elderly homeowner/renter credit income (MCA 15-30-2337(9)(a)(vi)) - #10144

Merged
MaxGhenis merged 7 commits into
mainfrom
mt-elderly-credit-government-assistance
Oct 13, 2026
Merged

MaxGhenis merged 7 commits into
mainfrom
mt-elderly-credit-government-assistance

Conversation

@MaxGhenis

@MaxGhenis MaxGhenis commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

Montana's elderly homeowner/renter credit counted general_assistance and veterans_benefits but not SSI, TANF, workers' compensation or guaranteed income payments. Since #9915, gross household income sums every household member's income, so a member receiving SSI or TANF should change the claimant's credit; before this PR it didn't.

What the law and forms count

  • MCA 15-30-2337(9)(a) (current; 2009, same text): federal AGI without regard to loss "plus all nontaxable income, including but not limited to: ... (vi) cash public assistance and relief".
  • 2024 and 2025 Schedule 2EC line 16 (2024 PDF p.48, 2025 PDF p.46): "This includes veteran's compensation benefits, supplemental security income (SSI) payments, worker's compensation, and any other government assistance received during the year."
  • 2022 and 2023 instructions, line 8 (2022 PDF p.48, 2023 PDF p.52): "Disability benefits including, but not limited to, veteran's disability, SSI payments, and workers' compensation."
  • 2014, 2016 and 2017 Form 2EC instructions (2014 PDF p.53, 2016 PDF p.74, 2017 PDF p.64): the same disability-benefits item, plus "Cash, public assistance and relief - Do not include LIEAP ... or SNAP".

The statute and every form checked agree, so the sources are added to all three periods of the list (2009, 2017, 2023).

Change

gross_income_sources.yaml gains, in every period:

  • ssi: person-level SSI (monthly, summed over the year).
  • tanf_person: the SPM unit's tanf divided by its size. tanf itself cannot go in this list. The formula's add(person, ...) raises ValueError: You requested to aggregate tanf (defined for spm_units) to people (checked in Core 3.32.15), and a Person adds attribute would instead project the full amount onto every member. SPM units nest in households, so the per capita shares summed over the household count each unit's TANF once, however members are split among tax units. tanf sums every state's program, mt_tanf included.
  • workers_compensation: person-level input.
  • gi_cash_assistance: guaranteed income pilot payments. The model keeps them out of federal AGI (and files them under market_income), and (9)(a) counts all nontaxable income; a government-funded pilot is also "any other government assistance" on line 16.

None of these is in federal AGI (irs_gross_income sources), dependent_gross_income, social_security (which excludes SSI), general_assistance or veterans_benefits, so nothing is counted twice. SNAP and LIEAP stay out (2014–2017 instructions); a case pins SNAP. The references are consolidated to one entry per document.

Because the model computes SSI for anyone 65 or older with little income (take-up defaults to true), existing cases built on such claimants now see that SSI. Three gross household income cases and four property-test builders (household_members, dependent_deductions, rebate_receipts, and #9900's one_claimant) test other items, so they now input ssi: 0; SSI has its own cases.

Circular dependencies

The new path is the MT credit → gross household income → ssi / tanf_person → tanf → every state's TANF program. In a microsimulation each state's formula runs for its own records. No TANF or SSI parameter list or formula names an income tax, refundable credit or net income variable. The only paths back to Montana tax run through behavioral responses: SSI or a state's TANF reads earnings and hours that labor-supply responses adjust, and South Carolina TANF counts capital_gains, which capital-gains responses adjust. Both responses return 0 without a reform (labor_supply_behavioral_response.py, capital_gains_responses.py), labor supply also has a re-entry guard, and their measurements run in cloned branches with the responses neutralized (behavioral_response_measurements.py). The 10% microsim screen and the full 2026 pair ran every state without error.

Tests

In mt_elderly_homeowner_or_renter_credit.yaml, worked line by line from each year's schedule. The 8 new cases fail on main's parameter; all 36 cases in the file pass:

Case TY Credit, main → this PR
Claimant's SSI 6,000, line 16 2024 1,150 → 872.40
Son's workers' compensation 9,000, line 17 2025 1,150 → 780
Daughter's guaranteed income payments 6,000, line 17 2024 1,145.60 → 805.20
Daughter's family's TANF 4,800, shared SPM unit, two returns (once, not per member) 2024 1,150 → 890
Same, mt_tanf paid to a separate SPM unit 2024 1,150 → 890
Workers' compensation 6,000 and a spouse's SSI 5,000, 2023 line 8 2023 1,000 → 380
Son's SSI 8,820, 2017 Form 2EC 2017 660.70 → 124
Daughter's family's TANF 5,400, 2016 Form 2EC worksheet 2016 740.40 → 367.20

mt_elderly_homeowner_or_renter_credit_gross_household_income.yaml adds the SNAP guard (unchanged on both).

test_mt_elderly_credit_government_assistance.py (Hypothesis, plus a worked example that fails on main) covers what fixed YAML cases cannot: randomized amounts across arrangements that must agree, a check against an independent Schedule 2EC reference, and monotonicity. Invariants, for a claimant 62 or older, another adult and a child, in four arrangements (one return or two, one SPM unit or two, and one with extra assistance):

  1. Household gross household income = pension + every member's SSI, workers' compensation and guaranteed income payments + the TANF, once, in every arrangement.
  2. The credit is the same in every arrangement, and only the claimant claims.
  3. The credit equals an independent implementation of Schedule 2EC lines 19–30 from the form's tables, lies in [0, 1,150], and is 0 at 45,000 or more.
  4. More assistance never raises the credit.

Cost. The file runs in the Rest job's remaining pytest group (REST_PYTHON_GROUPS in the Makefile). On main's last Rest run with the timing artifact (run 38206682508, main 63cb12b), that group took 28:15.90 wall clock with 14,639,084 KB max RSS (rest-python-remaining-resources.txt). Its sibling Montana property tests took 0.8–10.7 s each. Local (macOS, load ~54, not Linux CI): the new file takes 9.5 s in pytest (28.7 s with model import) and peaks at 1.39 GB RSS, against 9.4 s and 1.44 GB for its sibling test_mt_elderly_credit_household_members.py measured the same way. It runs 15 Hypothesis examples, each one small Simulation on the shared system, and keeps nothing resident. This PR's Rest artifact will give the Linux figure; its incremental effect on the group's peak RSS is not measured separately. The ssi: 0 pins don't change the other files' setup.

Local runs at f9d8d64 (after merging main 3d908a6) pass: the whole gov/states/mt folder and Montana contrib via test_batched.py --workers 1, the state roll-up files, the code-health reference and person-adds checks, and every test_mt_elderly_credit_*.py. Logs: ~/reviews/mt-ehrc-government-assistance-2026-10/tests.log.

Impact (2026, full-file pair)

Full-file microsimulation on the default dataset (populace_us_2024), head f9d8d64 against its merge base with main, 3d908a6, run once in the hub impact pipeline (~/reviews/us-hub/fixes/10144-impact/compare.2026.json). Sums are weighted.

Variable Base This PR Change Records changed
mt_elderly_homeowner_or_renter_credit $7.45M $6.35M −$1.10M 1 (2,126 weighted households; at most $516)
mt_elderly_homeowner_or_renter_credit_gross_household_income $69.60B $69.85B +$251M 20 people
mt_elderly_homeowner_or_renter_credit_net_household_income $1.441B $1.450B +$8.3M 10 people
mt_income_tax, state_income_tax +$1.10M 1
household_net_income −$1.10M 1
income_tax, household_benefits, ssi, tanf_person, workers_compensation 0 0

gi_cash_assistance is zero for every record in the dataset, so it moves nothing here. Gross household income rises for 20 people, but only one household's credit changes; the run keeps no record-level detail to say why the others do not move. A run at b662ed1 (before gi_cash_assistance and the merge with main) gave the same figures.

Review

GPT-6.1 Sol reviewed this in two rounds. Round 1 (b662ed1) asked for variable-named YAML files, cost documentation, gi_cash_assistance, the guarded-path and Core wording, one reference per document and the 2016 worksheet line number. Round 2 (87cef23) confirmed those, found no modelling defect, and asked for this documentation, the Axiom comment and the reference-title format. Round 3 (f9d8d64) approved, with one wording nit on the dependency paragraph, applied above. Reports: ~/reviews/mt-ehrc-government-assistance-2026-10/review/.

Related

axiom: TheAxiomFoundation/rulespec-us#1512 queued (extension comment)

🤖 Generated with Claude Code

MaxGhenis and others added 5 commits October 12, 2026 06:02
… 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 <noreply@anthropic.com>
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 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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 <noreply@anthropic.com>
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 <noreply@anthropic.com>
#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 <noreply@anthropic.com>
MaxGhenis added a commit that referenced this pull request Oct 12, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaxGhenis
MaxGhenis marked this pull request as ready for review October 13, 2026 00:22
@MaxGhenis

Copy link
Copy Markdown
Contributor Author

Hand-off to the US + core hub (session local_f4c453d7-4f7f-4968-89d8-0ff409e79b84).

@MaxGhenis
MaxGhenis merged commit 7b7b418 into main Oct 13, 2026
33 checks passed
@MaxGhenis

Copy link
Copy Markdown
Contributor Author

US + core hub merge audit, us#10144 at f9d8d64b535b8200c8f94dddfe74bd7acb34a9d9 (squash): Count SSI, TANF and workers' compensation in Montana's elderly homeowner/renter credit income (MCA 15-30-2337(9)(a)(vi)).

@MaxGhenis
MaxGhenis deleted the mt-elderly-credit-government-assistance branch October 13, 2026 02:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant