Skip to content

Give separate filers the $3,750 Schedule R initial amount - #10578

Merged
MaxGhenis merged 4 commits into
mainfrom
elderly-credit-separate-filer-base
Nov 3, 2026
Merged

MaxGhenis merged 4 commits into
mainfrom
elderly-credit-separate-filer-base

Conversation

@MaxGhenis

@MaxGhenis MaxGhenis commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

Defect

section_22_income picked the Schedule R initial amount with

select([n == 1, n == 2, filing_status == SEPARATE], [one_qualified, two_qualified, separate])

select takes the first true condition, so a married individual filing separately with one qualified individual got $5,000, and one with two qualified members (the filer plus a qualifying dependent) got $7,500 before the under-65 cap. 26 U.S.C. 22(c)(2)(A) gives "$3,750 in the case of a married individual filing a separate return".

The model also never applied 22(e)(1): a married individual on a separate return gets the credit only if the spouses lived apart for the whole year.

Fix

Both changes are in section_22_income.py; elderly_disabled_credit_potential is again rate × section_22_income.

  • The separate-return condition, separate & (n >= 1), comes first in the select, so it wins. It tests n >= 1 rather than n == 1 because qualifies_for_elderly_or_disabled_credit counts every member who is 65 or older or retired on total disability, dependents included, so a separate filer with a qualifying dependent has n = 2.
  • section_22_income is 0 for a separate filer with cohabitating_spouses true. The bar sits in section_22_income, not on the credit, because Michigan's subtraction takes the Schedule R line 19 amount, and a separate filer who lived with the spouse has none: Schedule R gives a separate filer only boxes 8 and 9, and both require that "you lived apart from your spouse for all of" the year. MCL 206.30(1)(f)(v) deducts "the section 22 amount eligible for the … credit", and the 2024 MI-1040 instructions point to "U.S. Form 1040 Schedule R, line 19". cohabitating_spouses is the input taxable_social_security_tier_1 and ira_219g_deductible_limit already use for the "lived apart" tests of 86 and 219(g); it defaults to false, so a separate filer counts as living apart unless the input says otherwise.
  • phase_out.yaml cited "§ 22(c)(3)(D)"; 22(c)(3) has only (A) and (B), and the thresholds and one-half rate are in 22(d). Both references now point at 22(d). Values are unchanged.

Federal results are the same as the earlier head of this PR: the credit was already zero for a separate filer who lived with the spouse.

Other parts of section 22 checked for a separate filer

  • 22(c)(2)(B), the under-65 cap: num_elderly × $5,000 + disability income of members under 65, with dependents left out of num_elderly. A separate filer aged 65 or more gets a $5,000 cap, above $3,750; one under 65 is capped at their disability income.
  • 22(c)(3), nontaxable pensions and social security: subtracted the same way for every filing status.
  • 22(d), the AGI phase-out: $5,000 for SEPARATE, half the excess subtracted.

Changes for separate filers, compared with main (TY2024, Texas, wages only)

Unit main section_22_income this PR
Separate, 67, lived apart, $3,000 wages 5,000 3,750
Separate, 67, lived with spouse, $3,000 wages 5,000 0
Separate, 67, lived apart, dependent aged 80 (two qualified) 5,000 3,750
Separate, 60, not retired on disability (no qualified individual), $2,000 of disability payments 2,000 0

The last row: on main the select fell through to the SEPARATE branch even with no qualifying member, so the unit got $3,750 capped at its $2,000 of disability pay. It is now 0. A separate filer whose only qualifying member is a dependent still gets an initial amount, as on main; see the first follow-up.

Tests

section_22_income.yaml (10 cases, TY2024, Texas):

Case Hand computation section_22_income potential credit
Separate, 67, lived apart, $3,000 wages 3,750; AGI 3,000 < 5,000 3,750 562.50
Separate, 67, lived with spouse 22(e)(1) 0 0 (credit 0)
Separate, 70, lived apart, $6,000 wages, $1,000 social security 3,750 − 1,000 − 0.5 × (6,000 − 5,000) 2,250 337.50
Separate, 60, retired on total disability, $2,000 disability pay min(3,750, 2,000) 2,000 300
Single, 67 5,000; AGI < 7,500 5,000 750
Joint, 67 and 50 5,000; AGI < 10,000 5,000 750
Joint, 67 and 66 7,500 7,500 1,125
Separate, 67, lived apart, dependent aged 80 n = 2, still 3,750; cap 1 × 5,000 3,750 562.50
Joint, 67 and 50, living together 22(e)(1) reaches only separate returns 5,000 750
Separate, 60, not retired on disability, $2,000 of disability payments no qualified individual under 22(b) 0 0

mi_subtractions.yaml, new case: Michigan separate filer, 67, $3,000 wages, lived with spouse. section_22_income 0; tier three standard deduction 20,000 − 5,600 personal exemption = 14,400; mi_subtractions 14,400 (main 19,400; the earlier head of this PR 18,150).

test_elderly_disabled_credit_invariants.py: a Hypothesis differential test over batches of eight mixed units (single, joint, separate, head of household; with or without a dependent who can qualify by age; living together or apart), plus one fixed batch that always runs:

  1. for every status but separate, section_22_income equals the formula on main, frozen as a reference function (I ran it against main's model locally and it matched);
  2. for a separate filer, it equals the closed form of 22(c)-(e), counting qualifying members as the model does (dependents included): 0 if the spouses lived together; otherwise min($3,750 if any member qualifies, the 22(c)(2)(B) cap) less nontaxable pensions and social security, less half of AGI over $5,000, floored at 0;
  3. a separate filer's amount never exceeds $3,750.

Mutants, each in its own process, code restored after: >= 1 → == 1; the 22(e)(1) bar removed; the bar applied to every status (separate & dropped). Each fails at least one YAML case and the Python test.

Effect on other programs

Readers of section_22_income and elderly_disabled_credit outside the credit itself:

  • Michigan subtraction (gov/states/mi/tax/income/subtractions.yaml) lists section_22_income. A separate filer's subtraction falls from $5,000 to $3,750 when the spouses lived apart, and to 0 when they lived together (TY2024, $3,000 wages: 19,400 on main → 14,400).
  • Michigan interest, dividends and capital gains deduction (mi_interest_dividends_capital_gains_deduction) subtracts elderly_disabled_credit from the deduction's maximum. A lower federal credit raises the remaining maximum for a separate filer who qualifies for that deduction.
  • Nebraska ne_elderly_disabled_credit is min(elderly_disabled_credit, income_tax_before_credits). TY2024 separate filer, 67, $9,000 wages, itemizing: 450 on main → 262.50 when the spouses lived apart, 0 when they lived together.
  • Vermont vt_elderly_or_disabled_credit is 24% of the federal credit. Same unit: 108 on main → 63 apart, 0 together.
  • Federal credit ordering: elderly_disabled_credit sits in non_refundable.yaml and in the preceding_credits lists of the CTC limit, the education credits, the retirement saving credit, the residential clean energy, energy efficient home improvement and clean vehicle credits. A smaller elderly credit leaves more liability for those later credits. Two contributed reforms (congress/afa/afa_other_dependent_credit.py, crfb/non_refundable_ss_credit.py) list it the same way.

Follow-ups (same on main)

  • Count only the head and spouse in section_22_income. 22(c)(2)(A) sets the initial amount by the filer and, on a joint return, the spouse, while qualifies_for_elderly_or_disabled_credit counts every member. So a dependent can raise the amount (a single 64-year-old retired on disability, with $10,000 of disability pay and a dependent aged 80, gets 6,250 where the statute gives 3,750), zero it (a single 67-year-old with dependents aged 80 and 85 gets 0 where it gives 5,000), or create one for a filer who doesn't qualify.
  • Michigan's interest, dividends and capital gains maximum: MCL 206.30(1)(p) reduces it by "a deduction claimed under subdivision (f)(i), (ii), (iv), or (v)", and (f)(v) is the section 22 amount, while mi_interest_dividends_capital_gains_deduction subtracts the 15% credit.

impact: we estimate that no tax or benefit moves in 2026. Section 22 income falls $78.7 million on 25 records of the default dataset (62,957 weighted tax units), and their potential elderly and disabled credit falls $11.8 million. All 25 file separately, and each one's initial amount falls from $5,000 to $3,750. No record gets the credit itself on either side, since no record with a potential credit has income tax left for it to offset. Federal and state income tax, benefits and household net income don't move.

axiom: TheAxiomFoundation/rulespec-us#1982 queued

🤖 Generated with Claude Code

section_22_income's select checked one qualified individual before the
separate-return condition, so a married individual filing separately got
$5,000 instead of the $3,750 that 22(c)(2)(A)(iii) sets. Check the
separate return first. Also allow the credit on a separate return only
when the spouses lived apart all year (22(e)(1)), using the existing
cohabitating_spouses input.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…dit limit

A Hypothesis test runs batches of mixed tax units and checks that a
separate filer's section 22 amount never exceeds $3,750 and that the
credit never exceeds the Schedule R credit limit or tax before credits.
Restoring main's select order makes the first property fail.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaxGhenis

Copy link
Copy Markdown
Contributor Author

Ready for hub review

Head: 5fd88537b0a735b36001d1b3c945b38f88218575 (draft)

What the item asked, and how I resolved it

  • Reproduce at main: done. TY2024, one person aged 67, $3,000 wages, TX, SEPARATE: main gives section_22_income 5,000 and potential credit 750; this branch gives 3,750 and 562.50.
  • Fix: policyengine_us/variables/gov/irs/credits/elderly_and_disabled/section_22_income.py:21-38. The separate-return condition separate & (n >= 1) comes first in the select.
  • 22(e)(1): main did not enforce it. Now enforced at elderly_disabled_credit_potential.py:19-24 with the existing cohabitating_spouses input, the one taxable_social_security_tier_1 and ira_219g_deductible_limit use for separate filers who lived apart. It defaults to false, so a separate filer counts as living apart unless the input says otherwise.
  • 22(d) separate threshold: phase_out.yaml has $5,000 for SEPARATE. I could not read the statute, so the value and the reference are unchanged. The reference title says "22(c)(3)(D)"; the AGI limit may be 22(d) instead (unverified).
  • 22(c)(3) and the under-65 cap: both apply to a separate filer the same way. The cap is num_elderly x 5,000 + under-65 disability income, above 3,750 for a filer 65 or older and equal to disability income for one under 65. YAML cases cover both.

Tests (one process per file)

  • New tests/policy/baseline/gov/irs/credits/elderly_and_disabled/section_22_income.yaml: 7 passed. The PR body has the hand computations for each case.
  • New tests/core/test_elderly_disabled_credit_invariants.py (Hypothesis, 10 examples x 8 mixed units): 1 passed, 20 s.
  • Existing: elderly_and_disabled/integration.yaml 1, permanent_disability_retirement_pay.yaml 6, credits/credit_limit_order.yaml 8, ne_elderly_disabled_credit.yaml 2, vt_elderly_or_disabled_credit.yaml 1: all pass.
  • code_health/test_source_conflicts.py: 103 passed.

Mutants (not committed; code restored after each)

  • Main's select order: 3 of the 7 new YAML cases fail, and property 1 fails (assert on section_22[separate] <= 3750).
  • 22(e)(1) check removed: the lived-together case fails (1 of 7).

CI: not run, because the PR is a draft.

Judgment calls

  • I put 22(e)(1) on elderly_disabled_credit_potential, not on section_22_income, because Michigan's subtraction list (parameters/gov/states/mi/tax/income/subtractions.yaml) reads section_22_income. The initial-amount fix still lowers a Michigan separate filer's subtraction from 5,000 to 3,750.
  • The statute was out of reach (law.cornell.edu, uscode.house.gov, govinfo and irs.gov all returned 403). The only quote in the PR is the brief's 22(c)(2)(A) text. The 22(e)(1) rule follows the brief's paraphrase (unverified).
  • Axiom line: the brief asked for axiom: (hub files pe-parity before review), and Item 2 of the same brief says a reviewer has ruled that form invalid. I wrote axiom: needed (CLAUDE.md's form for when the author can't do the Axiom work). The hub should replace it.
  • The API rewrote the body's closing line into the standard "Generated by Claude Code" footer.

Proposed follow-ups

  • Count only the head and spouse as qualified individuals for the elderly or disabled credit. section_22_income counts every tax-unit member 65 or older, dependents included. It also sums every member's pensions and disability income, so an elderly dependent can raise a filer's initial amount and cap.
  • Check Michigan's use of section_22_income as a subtraction. mi/tax/income/subtractions.yaml lists the federal section 22 amount as Schedule 1 line 22. The line should be checked against the MI-1040 Schedule 1, because a credit base used as an income subtraction looks wrong.
  • Confirm the elderly credit phase-out reference. phase_out.yaml cites 22(c)(3)(D) for the AGI thresholds. Check whether 22(d) is the right cite.

Generated by Claude Code

@MaxGhenis

Copy link
Copy Markdown
Contributor Author

Picking this up for the US hub. I'll post a hand-off comment here when it's ready.


Generated by Claude Code

Michigan's subtraction reads section_22_income, the Schedule R line 19
amount. A separate filer who lived with the spouse can check neither
box 8 nor box 9 and has no line 19 amount, so the bar belongs on the
amount itself, not on the credit. The potential credit is again
rate x section_22_income; federal results are unchanged.

Also: explain why the separate condition tests n >= 1 (dependents can
qualify), point the phase-out references at 22(d), fix the Schedule R
line in the YAML header, add YAML cases for a qualifying dependent, a
cohabiting joint return and a Michigan separate filer, and replace the
credit-limit property, which could not fail, with a differential test
against main's formula and the statute's closed form.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LwQq6GnTUicNF8teuGcift
@MaxGhenis

MaxGhenis commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor Author

Ready for hub review

Head: 137446fdafc39c56eb97a88d7f4983f65048e601 (one commit on top of 5fd88537b0a735b36001d1b3c945b38f88218575; nobody else had pushed since).

What the item asked for, and where

  1. Bar moved into section_22_income. section_22_income.py:75-85 returns 0 when separate & cohabitating_spouses; the comment cites 22(e)(1) and Schedule R boxes 8 and 9. elderly_disabled_credit_potential.py:14-16 is again p.rate * section_22_income, with a one-line pointer to where the bar now sits. Federal results are unchanged from the previous head (the credit was already 0 for these units).

  2. YAML.

    • Case 2 (section_22_income.yaml:28-51) now expects section_22_income: 0.
    • Michigan case in mi_subtractions.yaml:174-201 (it belongs with Michigan's subtractions): TY2024 separate filer, 67, $3,000 wages, cohabitating_spouses: true. Hand: born 1957, so tier three; 20,000 base − 5,600 personal exemption = mi_standard_deduction 14,400; section_22_income 0; mi_subtractions 14,400. That is 3,750 below the previous head's 18,150 (and 5,000 below main's 19,400).
    • Separate, 67, dependent aged 80 (section_22_income.yaml:170-195): 3,750 (n = 2; cap 1 × 5,000 because dependents are left out of num_elderly). Main gives 5,000.
    • Joint, 67 and 50, cohabitating_spouses: true (section_22_income.yaml:197-220): 5,000, potential credit 750.
  3. Comment on >= 1 at section_22_income.py:25-30: says qualifies_for_elderly_or_disabled_credit isn't limited to the head and spouse (I read eligibility.py: age ≥ 65 or retired on total disability, any member), so a separate filer with a qualifying dependent counts two.

  4. phase_out.yaml:26-27, 34-35 now cite "26 U.S. Code § 22(d)" / #d. Values unchanged.

  5. section_22_income.yaml:1 now says Schedule R line 19.

  6. Hypothesis (test_elderly_disabled_credit_invariants.py): the credit ≤ credit limit and credit ≤ tax-before-credits asserts are gone (both follow from min_). New test test_section_22_amount_against_reference_formulas:

    • non-separate units equal pre_change_section_22, main's select order frozen in numpy;
    • separate units equal statute_separate_section_22: 0 if lived together, else max(0, min(3,750 if n ≥ 1 else 0, cap) − nontaxable pensions and social security − 0.5 × max(0, AGI − 5,000));
    • plus ≤ 3,750 and ≥ 0.
      Units can carry a dependent (none / 65-90 / 10-64), so separate units reach n = 2. Both reference functions take the cap, nontaxable amounts and AGI from the simulation, so only the section 22 step is reimplemented.
      Judgment call: with random draws alone the == 1 mutant survived two of three fresh runs (10 examples × 8 units rarely produced a low-income separate filer with an elderly dependent). I added a fixed @example batch of eight units (separate with an elderly dependent, lived apart and together; separate lived together; separate with no qualified individual and disability pay; joint, single and head of household living together; joint with an elderly dependent) so every mutant is caught on every run. I also ran the frozen reference against main's model (PYTHONPATH to a main worktree, separate-filer asserts disabled): it passed, so the reference matches main for non-separate units.
  7. Mutants (each in its own process; file restored and cmp-checked after each):

    Mutant section_22_income.yaml mi_subtractions.yaml Python test (fresh .hypothesis)
    >= 1 → == 1 1 failed / 8 passed 6 passed failed (:200, the ≤ 3,750 assert)
    bar removed (return amount) 1 failed / 8 passed 1 failed / 5 passed failed (:207, statute form)
    bar on every status (separate & dropped) 1 failed / 8 passed 6 passed failed (:204, pre-change form)
  8. PR body updated through REST and read back: placement reasoning corrected; the two further separate-filer changes added; "Effect on other programs" lists every reader I found; axiom: TheAxiomFoundation/rulespec-us#1982 queued and impact: the hub will measure kept.

  9. Tests run (one file per process), all at the new head's code:

    File Result
    irs/.../elderly_and_disabled/section_22_income.yaml 9 passed
    irs/.../elderly_and_disabled/integration.yaml 1 passed
    irs/.../elderly_and_disabled/permanent_disability_retirement_pay.yaml 6 passed
    irs/credits/credit_limit_order.yaml 8 passed
    mi/tax/income/mi_subtractions.yaml 6 passed
    mi/tax/income/mi_taxable_income.yaml 2 passed
    mi/tax/income/mi_income_tax_before_non_refundable_credits.yaml 3 passed
    mi/tax/income/mi_income_tax_before_refundable_credits.yaml 2 passed
    mi/tax/income/integration.yaml 6 passed
    mi/tax/income/deductions/integration.yaml 3 passed
    mi/.../mi_interest_dividends_capital_gains_deduction.yaml 6 passed
    ne/.../ne_elderly_disabled_credit.yaml 2 passed
    vt/.../vt_elderly_or_disabled_credit.yaml 1 passed
    tests/core/test_elderly_disabled_credit_invariants.py 1 passed
    tests/code_health/test_source_conflicts.py 103 passed

    No full suites or microsimulations.

Values (TY2024, wages only, age 67, separate, itemizing, $9,000 wages)

main this head, lived apart this head, lived together
section_22_income 3,000 1,750 0
elderly_disabled_credit 450 262.50 0
Nebraska ne_elderly_disabled_credit 450 262.50 0
Vermont vt_elderly_or_disabled_credit (24%) 108 63 0
Michigan mi_subtractions 17,400 16,150 14,400

The reviewer's numbers for Nebraska and Vermont match.

Two more separate-filer changes against main, checked at this head: separate filer plus a dependent aged 80, 5,000 → 3,750; separate filer aged 60, not retired on disability, $2,000 of disability payments, 2,000 → 0.

Readers of section_22_income and elderly_disabled_credit

Found by grepping .py and .yaml outside tests:

  • section_22_income: only elderly_disabled_credit_potential and Michigan's subtractions.yaml (2017 and 2026 lists). No other reader.
  • elderly_disabled_credit: Nebraska and Vermont credits (above); mi_interest_dividends_capital_gains_deduction (subtracts the credit from the deduction's maximum, so a lower credit raises the maximum for a separate filer whose older spouse was born before the eligibility year); federal non_refundable.yaml and the preceding_credits lists (CTC limit, AOC, LLC, retirement saving, residential clean energy, energy efficient home improvement, new and used clean vehicle); reforms congress/afa/afa_other_dependent_credit.py and crfb/non_refundable_ss_credit.py. None of these changes relative to the previous head, since the federal credit is unchanged; all of them change relative to main for separate filers.

Judgment calls and unverified points

  • Sources. This VM got 403 for law.cornell.edu, irs.gov, uscode.house.gov and govinfo.gov. Quotes in code and PR text come from the brief (Schedule R boxes 8/9, MCL 206.30(1)(f)(v), MI-1040 line 19 pointer) or the PR's earlier body (22(c)(2)(A)). Unverified paraphrases the reviewer should check: 22(e)(1)'s lived-apart condition; 22(c)(2)(A) giving an initial amount only when a qualified individual is present (the basis for the 2,000 → 0 row); 22(c)(3) having only (A) and (B), with the thresholds and one-half rate in 22(d).
  • The >= 1 comment says the unit "would otherwise fall through to $7,500"; that branch is then capped by 22(c)(2)(B), which is why the dependent case gives 5,000 on main, not 7,500.
  • subtractions.yaml still comments section_22_income # Line 22. Left as is because I couldn't confirm which form's line it refers to.
  • Also pushed the same commit to this session's working branch claude/separate-filer-bar-elderly-credit-duk0o1; the PR branch is the one that matters.

CI

Pull request run at 137446fd: https://github.com/PolicyEngine/policyengine-us/actions/runs/41471141121, completed: success. All 34 jobs succeeded, including PR validation (lint and changelog), Package and compatibility, Household API Partners, every Baseline, Contrib and Python shard, and Microsimulation. The run finished at 16:27 UTC; this section was updated in place after the hand-off was first posted.

Proposed follow-up

  • Michigan interest and dividend deduction: reduce by the section 22 amount, not the credit? mi_interest_dividends_capital_gains_deduction subtracts elderly_disabled_credit (15% of the amount, after the tax limit). Its own comment says "Amount used for the federal credit"; if MCL 206.30(1)(p) and the MI-1040 mean Schedule R line 19, the reduction is understated. Unverified; needs the statute and form text.

Generated by Claude Code

@MaxGhenis

Copy link
Copy Markdown
Contributor Author

Ready for hub review
VERDICT: APPROVE
137446f
METHODOLOGY_CHOICE: no

Review of #10578, round 2

The head is still 137446fd, one commit on top of round 1's 5fd88537. Every round 1 request is addressed:

  • The 22(e)(1) bar now sits in section_22_income, so Michigan's subtraction sees it.
  • The two surviving mutants are now killed.
  • The phase_out.yaml citation and the Schedule R line number are fixed.
  • The always-true property is replaced with a differential test.

Federal results match the previous head. Run 41471141121 at this head finished with all 34 jobs successful.

I found no P1 or P2 problems. Below are four P3s (two documentation overclaims, one test gap and one stray branch) and three follow-ups that behave the same on main.

Sources. I couldn't confirm any legal source from this VM. law.cornell.edu, uscode.house.gov, govinfo.gov, irs.gov, legislature.mi.gov and michigan.gov all returned a proxy 403 or DNS failure, through both curl and the fetch tool. So every statement below about what 26 USC 22, Schedule R or MCL 206.30 says is a paraphrase I haven't verified. The hub should check those texts before landing (see "What I couldn't check").

Findings

P3-1. The test and its docstring call the separate-filer reference "the statute's closed form", but it reuses the model's count of qualified individuals, dependents included

  • Where: policyengine_us/tests/core/test_elderly_disabled_credit_invariants.py:8-12 (docstring item 3) and :140-145 (statute_separate_section_22).
  • The problem: n comes from reduction_and_cap_inputs, which sums elderly | disabled over every member, dependents included. That is exactly what the model does (eligibility.py, qualifies_for_elderly_or_disabled_credit).
    • Under 22(b) (unverified paraphrase), a qualified individual is the taxpayer, or the spouse on a joint return.
    • So the reference shares the model's dependent-counting behavior and can't detect it.
  • Witness: I ran a real Simulation at head and at main, TY2024, Texas. The unit is a separate filer aged 60, not retired on disability, with $2,000 of disability pay (as wages), a dependent aged 80, and living apart.
    • section_22_income is 2,000 at head and 2,000 at main.
    • Under the 22(b) reading, nobody on this return is a qualified individual, so the amount is 0.
    • The reference function also gives 2,000, so the test passes.
  • Replacement, docstring lines 8-12:
3. For a separate filer it equals the closed form of 22(c)-(e) with the
   model's count of qualifying members (which, like the model, includes
   dependents): zero if the spouses lived together at any time in the
   year (22(e)(1)); otherwise min($3,750 if any member qualifies, the
   22(c)(2)(B) cap), less nontaxable pensions and social security
   (22(c)(3)), less half of AGI over $5,000 (22(d)), floored at zero.

Docstring line of statute_separate_section_22: """26 U.S.C. 22(c)-(e) for a married individual filing separately, counting qualifying members as the model does (dependents included)."""

P3-2. The body's "2,000 → 0" row is stated more broadly than the code delivers, and no YAML case pins it

  • Where: the PR body, "Changes for separate filers" row 4 and the paragraph under it ("22(c)(2)(A) gives an initial amount only to a qualified individual, so it is now 0").
  • The problem: The row is right as written: the same filer with no dependent gets 2,000 at main and 0 at head, which I confirmed. But the paragraph says why in general terms. Add an elderly dependent and the amount stays 2,000 (the witness in P3-1), because separate & (n >= 1) counts the dependent.
  • Test gap: No YAML case covers this row. My mutant M4 drops the n >= 1 guard, and only the Python test's fixed @example batch kills it. section_22_income.yaml passes 9 of 9 under M4.
  • Replacement for the body paragraph: The last row: on main the select fell through to the SEPARATE branch even with no qualifying member, so the unit got $3,750 capped at its $2,000 of disability pay. It is now 0. A separate filer whose only qualifying member is a dependent still gets an initial amount, as on main; see the follow-up on counting dependents.
  • Optional YAML case for section_22_income.yaml:
    - name: A separate filer with no qualifying member has no initial amount.
      period: 2024
      input:
        people:
          head:
            age: 60
            employment_income: 2_000
            total_disability_payments: 2_000
        tax_units:
          tax_unit:
            members: [head]
            filing_status: SEPARATE
            cohabitating_spouses: false
        households:
          household:
            members: [head]
            state_code: TX
      output:
        # Under 65 and not retired on total disability: n = 0, initial 0.
        section_22_income: 0
    I ran this unit through Simulation and got 0 at head and 2,000 at main.

P3-3. A second branch carries the head commit

  • gh api repos/PolicyEngine/policyengine-us/branches/claude/separate-filer-bar-elderly-credit-duk0o1 --jq .commit.sha returns 137446fdafc39c56eb97a88d7f4983f65048e601.
  • So the PR branch isn't the only one that carries the head. This is harmless: the CI run is on elderly-credit-separate-filer-base (head_branch of run 41471141121), and no other PR uses the side branch.
  • The hub can delete the side branch after landing.

P3-4. A stale line comment in Michigan's subtraction list (not in the diff)

  • policyengine_us/parameters/gov/states/mi/tax/income/subtractions.yaml:8,21 still has section_22_income # Line 22.
  • The hand-off left it alone because the line number couldn't be confirmed. I couldn't reach the 2024 MI-1040 either.
  • This is metadata only. A follow-up should set it from the form.

The brief's questions

The placement and the Michigan case.

  • section_22_income.py:83-85 returns where(separate & lived_together, 0, amount), and elderly_disabled_credit_potential is p.rate * section_22_income.

  • The Michigan case at mi_subtractions.yaml:174-201 has a separate filer aged 67, $3,000 of wages and cohabitating_spouses: true. Rerun at head and at main:

    main head
    section_22_income 5,000 0
    mi_standard_deduction 14,400 14,400
    mi_subtractions 19,400 14,400
    mi_income_tax −59.59 −59.59
    • The same filer living apart gets 18,150 at head (3,750 + 14,400).
    • The 14,400 is 20,000 − 5,600 as the code computes it (tier three, born 1957). I couldn't check the tier three amount or the subtraction itself against MCL 206.30 because the source was unreachable.
    • The PR's reading is that Michigan subtracts the Schedule R line 19 amount. It follows the quotes round 1 fetched, but I couldn't refetch them.
    • Michigan tax doesn't move in this case, because taxable income is 0 either way.

Readers at head. I grepped .py and .yaml outside tests.

  • section_22_income:
    • elderly_disabled_credit_potential;
    • Michigan subtractions.yaml (the 2017 and 2026 lists).
    • Nothing else reads it.
  • elderly_disabled_credit:
    • ne_elderly_disabled_credit;
    • vt_elderly_or_disabled_credit;
    • mi_interest_dividends_capital_gains_deduction;
    • federal non_refundable.yaml;
    • the preceding_credits lists for the CTC limit, AOC, LLC, retirement saving, residential clean energy, energy efficient home improvement, and new and used clean vehicles;
    • the reforms congress/afa/afa_other_dependent_credit.py and crfb/non_refundable_ss_credit.py.

Every one of these changes for some separate filers compared with main. None changes compared with the previous head except Michigan's subtraction.

Reader values I reran (TY2024, separate, 67, itemizing, $9,000 wages):

main head, apart head, together
section_22_income 3,000 1,750 0
elderly_disabled_credit 450 262.50 0
Nebraska ne_elderly_disabled_credit 450 262.50 not run
Vermont vt_elderly_or_disabled_credit 108 63 0

These match the hand-off.

Counting qualified individuals. Separate filers count a dependent toward the initial amount at head, and so do single, head of household and joint filers. Witnesses, all identical at main and head:

Unit (TY2024, TX) main head 22(b) reading (unverified)
Single, 64, retired on total disability, $10,000 disability pay, dependent 80 6,250 6,250 3,750 (5,000 initial, less 0.5 × (10,000 − 7,500))
Single, 67, dependents 80 and 85 0 0 5,000
Joint, 67 and 66, dependent 80 0 0 7,500
Separate, 60, not disabled, $2,000 disability pay, dependent 80 2,000 2,000 0
Head of household, same 2,000 2,000 0
  • In the first row, n = 2 selects 7,500, and the cap, 0 × 5,000 + 10,000, doesn't bind. The model overpays.
  • For separate filers this PR doesn't make any case worse: the separate initial amount fell from 5,000 or 7,500 to 3,750. Treat it as a follow-up.

The 2,000 → 0 row.

  • At head a separate filer aged 60, not retired on disability, with $2,000 of disability pay gets 0; at main, 2,000. The same filer flagged retired_on_total_disability gets 2,000 at both.
  • I couldn't fetch 22(b) or (c)(2) to confirm from the text that such a filer isn't a qualified individual. The model's own rule, age >= 65 | retired_on_total_disability, matches the PR's description of the statute.

Tests.

  • Neither reference function passes trivially:
    • pre_change_section_22 alone kills M3 (:204).
    • statute_separate_section_22 kills M2, M4 and M5 (:207).
  • The frozen pre_change_section_22 matches main for every non-separate unit. I ran the PR's test file against main's package with the two separate-filer asserts replaced by pass and max_examples=60:
    • 60 passing, 0 failing, plus the fixed batch;
    • the import path was confirmed as main's tree.
  • At head, the test as committed passes (1 passed). It also passes with max_examples=60.
  • The YAML cases assert exact values, not bounds.

Mutants. Each mutant ran in its own process on a scratch worktree, which I restored and confirmed clean (git status empty) after each one. The Python runs started with a fresh .hypothesis directory.

Mutant (section_22_income.py) Source section_22_income.yaml mi_subtractions.yaml Python test
M1 >= 1 → == 1 hand-off 1 failed / 8 passed 6 passed failed :200
M2 return amount (bar removed) hand-off 1 failed / 8 passed 1 failed / 5 passed failed :207
M3 where(lived_together, 0, amount) (bar on every status) hand-off 1 failed / 8 passed 6 passed failed :204
M4 separate & (n >= 1) → separate mine 9 passed 6 passed failed :207 (diff 2,000)
M5 bar only when n == 1 mine 9 passed 6 passed failed :207 (diff 3,750)

All five are killed. M4 and M5 are killed only by the fixed @example batch.

The Michigan interest and dividend follow-up.

  • mi_interest_dividends_capital_gains_deduction.py:42-47 lowers the deduction's maximum by elderly_disabled_credit. Its own comment says "Amount used for the federal credit".

  • I couldn't fetch MCL 206.30(1)(p) or the MI-1040.

  • Witness (TY2024, MI, separate, 80, itemizing, $14,000 of interest, −$6,000 of self-employment income, AGI 8,000, living apart):

    main head
    section_22_income 3,500 2,250
    elderly_disabled_credit 525 337.50
    Deduction 13,749 13,936.50
    mi_taxable_income 0 0
    • If (1)(p) means the section 22 amount, the deduction should be 14,274 − 2,250 = 12,024. Head sits 187.50 further from that than main.
    • When the spouses lived together, head reduces by 0, as main should under either reading.
  • I don't count this as this PR's defect, for two reasons:

    • It turns on an unverified reading.
    • It can't move Michigan tax for a separate filer. A positive credit needs AGI below 12,500. The reduction binds only when the deduction exceeds 14,274 − 562.50 = 13,711.50, which is above AGI. So mi_taxable_income is 0 either way, as in the witness.

Docs and body.

  • impact: the hub will measure and axiom: TheAxiomFoundation/rulespec-us#1982 queued are both present.
  • I checked these body claims against code and runs, and they hold:
    • cohabitating_spouses is read by taxable_social_security_tier_1 and ira_219g_deductible_limit;
    • all four rows of the separate-filer table;
    • the Nebraska and Vermont values;
    • the reader list;
    • the 9-case YAML table.
  • The exceptions are P3-1 and P3-2.

Can baseline outputs move? Yes.

  • For separate filers in the microdata, section_22_income falls from 5,000 to 3,750. A separate filer under 65 who isn't flagged as retired on disability falls to 0 as well.
  • Through Michigan's subtraction, that can move mi_subtractions, and possibly mi_income_tax.
  • The federal credit moves only for separate filers whose tax isn't already zero, such as itemizers.
  • cohabitating_spouses defaults to false, so the 22(e)(1) bar shouldn't fire in microdata unless the data sets it.
  • Population check for the hub:
    • count separate tax units with section_22_income > 0 by state, at main and at head;
    • compare mi_income_tax and federal elderly_disabled_credit totals.

Scope and overlap.

CI.

  • Run 41471141121 (pull_request, elderly-credit-separate-filer-base, 137446fd) completed with conclusion success: 34 of 34 jobs succeeded, with none cancelled or skipped.
  • The commit's check runs are 34, all success.
  • The PR's mergeable state is blocked, waiting for review, not a conflict.

Checked and sound

The defect at main. A separate filer aged 67 with $3,000 of wages gets 5,000 at main and 3,750 at head. Living together gives 5,000 at main and 0 at head.

The rule by hand, before I read the code: 3,750 initial; the cap is 1 × 5,000 for an elderly non-dependent; minus nontaxable pensions and social security; minus half of AGI over 5,000; 0 if they lived together. The head code applies this in every year (the parameters run from 2010), for separate returns only, at TaxUnit level. Other statuses are unchanged, as the main-reference run above shows.

Test files, one per process at head:

File Result
section_22_income.yaml 9 passed
mi_subtractions.yaml 6 passed
elderly integration.yaml 1 passed
permanent_disability_retirement_pay.yaml 6 passed
ne_elderly_disabled_credit.yaml 2 passed
vt_elderly_or_disabled_credit.yaml 1 passed
mi_interest_dividends_capital_gains_deduction.yaml 6 passed
test_elderly_disabled_credit_invariants.py 1 passed

Citations. phase_out.yaml now points to 22(d) (#d), and the values are unchanged. The YAML header now says Schedule R line 19.

What I couldn't check

  • Every legal source. I couldn't reach 26 USC 22 (b), (c)(2), (c)(3), (d) or (e)(1), Schedule R 2024 or its instructions (boxes 8 and 9, line 19), MCL 206.30(1)(f)(v) or (1)(p), or the 2024 MI-1040. Proxy or DNS refusals blocked law.cornell.edu, uscode.house.gov, govinfo.gov, irs.gov, legislature.mi.gov and michigan.gov. These rest on paraphrase or on round 1's fetched quotes:
    • the code comment's quote "you lived apart from your spouse for all of";
    • the PR's 22(c)(2)(A)(iii) quote;
    • Michigan's line 19 pointer;
    • the 22(b) reading behind P3-1 and the follow-ups.
  • The tier three standard deduction amount (20,000 less 5,600) against Michigan law. I confirmed only that the code produces 14,400.
  • Microdata impact. I didn't check whether microdata sets cohabitating_spouses, separate_filer_itemizes or retired_on_total_disability for separate filers. That needs the hub's data.

Follow-ups (same on main)

  1. Count only the head and spouse as qualified individuals in section_22_income. num_qualifying_individuals sums every member, so a dependent can raise the initial amount (single disabled filer with an elderly dependent: 6,250 where 3,750 is due), zero it (n = 3 falls to the default 0), or create one (a separate filer whose only qualifying member is a dependent). Witnesses are in the table above.
  2. Michigan interest and dividend deduction: reduce the maximum by the section 22 amount rather than the credit? This needs MCL 206.30(1)(p) and the MI-1040 Schedule 1 worksheet text. The witness is above. Federal changes like this PR's can't move Michigan tax through this reader for separate filers.
  3. Michigan subtractions.yaml line comments: set the section_22_income line number from the current MI-1040 Schedule 1.

Generated by Claude Code

Only the Python test's fixed batch killed the mutant that drops the n >= 1 guard, so a YAML case now does too. The separate-filer reference also counts qualifying members as the model does, dependents included, so it can't be "the statute's closed form" on that point; the docstrings now say so.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaxGhenis

Copy link
Copy Markdown
Contributor Author

Hub impact pair, progress

The base side of the impact pair for this PR has finished; the head side runs next.

  • base 97b6d5135cdc1cc7997c72ce23bd70033365da58 (merge base of the head with main)
  • head ac9f82a13e10f3e18d2f3fb4861d338c59be049f
  • dataset hf://datasets/policyengine/populace-us/populace_us_2024.h5@populace-us-2024-spm-20260909; the local file's SHA-256 6496cc4393d4d3c6574f76eca231de5898c803b9067645591fd5c4d3e65aee84 matches DEFAULT_DATASET_SHA256
  • year 2026, 8 household chunks through calculate_chunked from Add household-chunked microsimulation calculations #10561 (c545c47877)
  • 57,240 households (124,557,999 weighted) and 79,729 tax units (165,382,512 weighted)
  • base: wall time 11:26.33 for the whole process (/usr/bin/time), 10.9 min of it from the calculate_chunked call to the written tables; maximum resident set size 3.62 GiB (3,800,080 KB), exit status 0
Variable Base weighted sum (USD)
section_22_income 14,646,812,533
elderly_disabled_credit_potential 2,197,021,901
elderly_disabled_credit 0
mi_subtractions 104,227,298,654
mi_income_tax 13,368,314,227
mi_interest_dividends_capital_gains_deduction 29,083,843
ne_elderly_disabled_credit 0
ne_income_tax 2,976,276,185
vt_elderly_or_disabled_credit 0
vt_income_tax 1,450,474,523
income_tax 2,595,105,852,714
state_income_tax 578,044,599,347
household_net_income 17,161,528,033,453
household_benefits 2,059,893,797,416

Generated by Claude Code

@MaxGhenis

Copy link
Copy Markdown
Contributor Author

Ready for hub review
IMPACT PAIR: differs
head ac9f82a
base 97b6d51

  • dataset hf://datasets/policyengine/populace-us/populace_us_2024.h5@populace-us-2024-spm-20260909; the local file's SHA-256 6496cc4393d4d3c6574f76eca231de5898c803b9067645591fd5c4d3e65aee84 matches DEFAULT_DATASET_SHA256
  • year 2026, 8 household chunks through calculate_chunked from Add household-chunked microsimulation calculations #10561 (c545c47877), the same chunks on both sides
  • 57,240 households (124,557,999 weighted) and 79,729 tax units (165,382,512 weighted), the same rows and weights on both sides
Variable Base sum Head sum Change Rows that differ Weighted rows up Weighted rows down Largest absolute difference
section_22_income 14,646,812,533 14,568,116,752 -78,695,781 25 0 62,957 1,250.00
elderly_disabled_credit_potential 2,197,021,901 2,185,217,533 -11,804,367 25 0 62,957 187.50
elderly_disabled_credit 0 0 0 0 0 0 0.00
mi_subtractions 104,227,298,654 104,227,298,654 0 0 0 0 0.00
mi_income_tax 13,368,314,227 13,368,314,227 0 0 0 0 0.00
mi_interest_dividends_capital_gains_deduction 29,083,843 29,083,843 0 0 0 0 0.00
ne_elderly_disabled_credit 0 0 0 0 0 0 0.00
ne_income_tax 2,976,276,185 2,976,276,185 0 0 0 0 0.00
vt_elderly_or_disabled_credit 0 0 0 0 0 0 0.00
vt_income_tax 1,450,474,523 1,450,474,523 0 0 0 0 0.00
income_tax 2,595,105,852,714 2,595,105,852,714 0 0 0 0 0.00
state_income_tax 578,044,599,347 578,044,599,347 0 0 0 0 0.00
household_net_income 17,161,528,033,453 17,161,528,033,453 0 0 0 0 0.00
household_benefits 2,059,893,797,416 2,059,893,797,416 0 0 0 0 0.00

The sums use the simulation weights, and the up and down columns add the weights of the rows that rose or fell. I rounded each figure to the dollar on its own, so Change can differ by $1 from Head sum minus Base sum.

Wall time and memory:

  • base: wall time 11:26.33 for the whole process (/usr/bin/time), 10.9 min of it from the calculate_chunked call to the written tables; maximum resident set size 3.62 GiB (3,800,080 KiB), exit status 0
  • head: wall time 11:14.90 for the whole process (/usr/bin/time), 10.7 min of it from the calculate_chunked call to the written tables; maximum resident set size 3.62 GiB (3,799,644 KiB), exit status 0

Which variables move. Two variables move: section_22_income and elderly_disabled_credit_potential. In each, the same 25 tax units (62,957 weighted) fall and none rise. The other 12 match on every row.

  • section_22_income falls by $78.7 million. 17 units fall from $5,000 to $3,750, and 7 more fall by $1,250 from amounts between $2,045 and $4,288. One of those 7 falls by $1,249.9999, a float32 rounding. One unit falls from $431.33 to $0.
  • elderly_disabled_credit_potential falls by $11.8 million, 15% of the section_22_income change, on the same 25 units.
  • elderly_disabled_credit, ne_elderly_disabled_credit and vt_elderly_or_disabled_credit are $0 for every tax unit on both sides.
  • Every tax-unit row that differs in any variable also differs in section_22_income. No household row differs.
  • None of the 25 units lives in Michigan (FIPS 26), Nebraska (31) or Vermont (50), going by the dataset's state_fips. Seven records hold all but 0.44 of the 62,957 weight, in five states: Florida 20,470, California 15,521, Missouri 15,217, Louisiana 7,958 and Mississippi 3,791. The other 18 records weigh 0.195 or less each and add 14 more states.

Why they differ. The diff changes one formula, section_22_income. Its other changes are a changelog fragment, three test files, and reference metadata: section_22_income's own reference, the two citations in phase_out.yaml (values unchanged), and the reference and a comment in elderly_disabled_credit_potential. The formula change applies only when filing_status is SEPARATE:

  • a separate filer with one or two qualifying members now gets the amount.separate initial amount, $3,750, where the base select gave $5,000 for one and $7,500 for two (with three or more, both sides give $3,750);
  • a separate filer with no qualifying member now gets an initial amount of $0, where the base fell through to $3,750;
  • a separate filer's final section_22_income is $0 when cohabitating_spouses is true (22(e)(1)).

For every other filing status the head formula returns the base value, and for a separate filer the head amount is never above the base amount. No other formula or parameter value changes, so every other output can move only through section_22_income; in this run only elderly_disabled_credit_potential did.

By the dataset's inputs, all 25 moved units fall under the first case.

  • Each unit's head has is_separated true and is aged 66 to 85 in the dataset.
  • The head is the unit's only qualifying member: 22 units have one person, and the other 3 add a dependent aged 34, 53 or 55.
  • Neither retired_on_total_disability nor cohabitating_spouses is in the dataset or has a formula, so both are false for every unit, and the 22(e)(1) bar moved nothing.
  • Each moved unit's initial amount falls from $5,000 to $3,750. The unit that falls from $431.33 to $0 has reductions of $4,568.67, more than the new $3,750.
  • The three two-person units carry filing_status_input = HEAD_OF_HOUSEHOLD in the dataset; they hold 22,755 of the 62,957 weight. No model variable reads that column. Only a separate filer's section_22_income can change, so the model files all 25 units as separate.

Dropped variables. None. All 14 exist on both sides on the same entity (12 on tax_unit, 2 on household) and are numeric, and the helper's population-aggregate guard rejected none of them. pair_side.py passes dataset_end_year to Microsimulation, and both sides accepted it. Both sides peaked at 3.62 GiB, far under the 14 GB at which the hub reruns a pair with 16 chunks.

Commands. I ran these from an empty work directory. pair_side.py and compare.py are the hub's impact-pair scripts, unchanged.

curl -sI https://huggingface.co/api/datasets/policyengine/populace-us | head -1
git clone https://github.com/PolicyEngine/policyengine-us.git pe && cd pe
git fetch origin pull/10578/head:pr-10578 pull/10561/head:pr-10561
HEAD_SHA=$(git rev-parse pr-10578); BASE_SHA=$(git merge-base origin/main $HEAD_SHA); echo $HEAD_SHA $BASE_SHA
git worktree add --detach ../head $HEAD_SHA
git worktree add --detach ../base $BASE_SHA
git show pr-10561:policyengine_us/tools/calculate_chunked.py > ../calculate_chunked.py
git diff $BASE_SHA $HEAD_SHA -- pyproject.toml uv.lock   # empty, so one environment serves both sides
cd ../head && pip install uv 2>/dev/null; uv sync          # CPython 3.14.6, policyengine-core 3.33.2
apt-get install -y -q time || (apt-get update -q && apt-get install -y -q time)   # the VM had no /usr/bin/time
# Download the dataset once, through the model's own resolver.
PYTHONPATH=$PWD /usr/bin/time -v .venv/bin/python -c "from policyengine_us.system import _resolve_dataset_path, DEFAULT_DATASET; p = _resolve_dataset_path(DEFAULT_DATASET); print(p)" > ../download.log 2> ../download.err
sha256sum <the printed file>   # before the runs, and again between the two sides

cd ../pe; mkdir -p ../out
H=$PWD/../calculate_chunked.py; PY=$PWD/../head/.venv/bin/python
export OMP_NUM_THREADS=4 OPENBLAS_NUM_THREADS=4 MKL_NUM_THREADS=4
PYTHONPATH=$PWD/../base /usr/bin/time -v $PY ../pair_side.py $H 8 2026 ../out/base > ../out/base.log 2> ../out/base.err
PYTHONPATH=$PWD/../head /usr/bin/time -v $PY ../pair_side.py $H 8 2026 ../out/head > ../out/head.log 2> ../out/head.err
$PY ../compare.py ../out/base ../out/head ../out/compare.json

I ran the two sides one at a time. A small wrapper script ran each side's lines above and recorded the side's PID, start and end times and exit status. I detached the wrapper with setsid nohup, so that a timeout in my session's tools could not stop the run. No other job ran during either side; a sampler ran pgrep and ps once a minute to record memory. Each side's summary.json names the package it imported: base/policyengine_us on the base side and head/policyengine_us on the head side.

Other checks, outside the pair itself:

  • Before the runs, a short script imported each tree and confirmed each of the 14 variables' entity and value type.
  • A smoke run tested the pipeline on both sides, with the same helper and variables on every 50th household (1,145 households, 2 chunks). These results do not include it.
  • After the runs, a script read both sides' tables and the dataset's person, tax unit and household tables. It traced the moved rows, their states and their inputs, as reported above.
compare.json
{
 "household_net_income": {
  "entity": "household",
  "base_sum": 17161528033453.125,
  "head_sum": 17161528033453.125,
  "change": 0.0,
  "records_changed": 0,
  "weighted_changed": 0.0,
  "weighted_up": 0.0,
  "weighted_down": 0.0,
  "largest_abs": 0.0,
  "rows": []
 },
 "household_benefits": {
  "entity": "household",
  "base_sum": 2059893797415.6846,
  "head_sum": 2059893797415.6846,
  "change": 0.0,
  "records_changed": 0,
  "weighted_changed": 0.0,
  "weighted_up": 0.0,
  "weighted_down": 0.0,
  "largest_abs": 0.0,
  "rows": []
 },
 "section_22_income": {
  "entity": "tax_unit",
  "base_sum": 14646812532.989056,
  "head_sum": 14568116751.890999,
  "change": -78695781.0980568,
  "records_changed": 25,
  "weighted_changed": 62956.63145736675,
  "weighted_up": 0.0,
  "weighted_down": 62956.63145736675,
  "largest_abs": 1250.0,
  "rows": [
   {
    "id": 1221609,
    "base": 5000.0,
    "head": 3750.0
   },
   {
    "id": 1218439,
    "base": 5000.0,
    "head": 3750.0
   },
   {
    "id": 1215840,
    "base": 5000.0,
    "head": 3750.0
   },
   {
    "id": 1212417,
    "base": 3298.20703125,
    "head": 2048.20703125
   },
   {
    "id": 1168291,
    "base": 3328.9921875,
    "head": 2078.9921875
   }
  ]
 },
 "elderly_disabled_credit_potential": {
  "entity": "tax_unit",
  "base_sum": 2197021900.5709934,
  "head_sum": 2185217533.2551312,
  "change": -11804367.315862179,
  "records_changed": 25,
  "weighted_changed": 62956.63145736675,
  "weighted_up": 0.0,
  "weighted_down": 62956.63145736675,
  "largest_abs": 187.50003051757812,
  "rows": [
   {
    "id": 1158929,
    "base": 643.23095703125,
    "head": 455.7309265136719
   },
   {
    "id": 1037137,
    "base": 405.4091491699219,
    "head": 217.9091339111328
   },
   {
    "id": 1215840,
    "base": 750.0,
    "head": 562.5
   },
   {
    "id": 1221609,
    "base": 750.0,
    "head": 562.5
   },
   {
    "id": 1212417,
    "base": 494.7310791015625,
    "head": 307.2310791015625
   }
  ]
 },
 "elderly_disabled_credit": {
  "entity": "tax_unit",
  "base_sum": 0.0,
  "head_sum": 0.0,
  "change": 0.0,
  "records_changed": 0,
  "weighted_changed": 0.0,
  "weighted_up": 0.0,
  "weighted_down": 0.0,
  "largest_abs": 0.0,
  "rows": []
 },
 "mi_subtractions": {
  "entity": "tax_unit",
  "base_sum": 104227298654.38034,
  "head_sum": 104227298654.38034,
  "change": 0.0,
  "records_changed": 0,
  "weighted_changed": 0.0,
  "weighted_up": 0.0,
  "weighted_down": 0.0,
  "largest_abs": 0.0,
  "rows": []
 },
 "mi_income_tax": {
  "entity": "tax_unit",
  "base_sum": 13368314227.229733,
  "head_sum": 13368314227.229733,
  "change": 0.0,
  "records_changed": 0,
  "weighted_changed": 0.0,
  "weighted_up": 0.0,
  "weighted_down": 0.0,
  "largest_abs": 0.0,
  "rows": []
 },
 "mi_interest_dividends_capital_gains_deduction": {
  "entity": "tax_unit",
  "base_sum": 29083842.520729866,
  "head_sum": 29083842.520729866,
  "change": 0.0,
  "records_changed": 0,
  "weighted_changed": 0.0,
  "weighted_up": 0.0,
  "weighted_down": 0.0,
  "largest_abs": 0.0,
  "rows": []
 },
 "ne_elderly_disabled_credit": {
  "entity": "tax_unit",
  "base_sum": 0.0,
  "head_sum": 0.0,
  "change": 0.0,
  "records_changed": 0,
  "weighted_changed": 0.0,
  "weighted_up": 0.0,
  "weighted_down": 0.0,
  "largest_abs": 0.0,
  "rows": []
 },
 "ne_income_tax": {
  "entity": "tax_unit",
  "base_sum": 2976276185.1876755,
  "head_sum": 2976276185.1876755,
  "change": 0.0,
  "records_changed": 0,
  "weighted_changed": 0.0,
  "weighted_up": 0.0,
  "weighted_down": 0.0,
  "largest_abs": 0.0,
  "rows": []
 },
 "vt_elderly_or_disabled_credit": {
  "entity": "tax_unit",
  "base_sum": 0.0,
  "head_sum": 0.0,
  "change": 0.0,
  "records_changed": 0,
  "weighted_changed": 0.0,
  "weighted_up": 0.0,
  "weighted_down": 0.0,
  "largest_abs": 0.0,
  "rows": []
 },
 "vt_income_tax": {
  "entity": "tax_unit",
  "base_sum": 1450474522.7552946,
  "head_sum": 1450474522.7552946,
  "change": 0.0,
  "records_changed": 0,
  "weighted_changed": 0.0,
  "weighted_up": 0.0,
  "weighted_down": 0.0,
  "largest_abs": 0.0,
  "rows": []
 },
 "income_tax": {
  "entity": "tax_unit",
  "base_sum": 2595105852713.508,
  "head_sum": 2595105852713.508,
  "change": 0.0,
  "records_changed": 0,
  "weighted_changed": 0.0,
  "weighted_up": 0.0,
  "weighted_down": 0.0,
  "largest_abs": 0.0,
  "rows": []
 },
 "state_income_tax": {
  "entity": "tax_unit",
  "base_sum": 578044599346.724,
  "head_sum": 578044599346.724,
  "change": 0.0,
  "records_changed": 0,
  "weighted_changed": 0.0,
  "weighted_up": 0.0,
  "weighted_down": 0.0,
  "largest_abs": 0.0,
  "rows": []
 }
}

Generated by Claude Code

@MaxGhenis
MaxGhenis merged commit 9b18b2a into main Nov 3, 2026
34 checks passed
@MaxGhenis

Copy link
Copy Markdown
Contributor Author

US + core hub merge audit, us#10578 at ac9f82a13e10f3e18d2f3fb4861d338c59be049f (squash): Give separate filers the $3,750 Schedule R initial amount.

  • Review: Cloud review r2 (Opus 5.5, independent) approved 137446fdaf with four P3 notes. In ac9f82a13e the hub added the reviewer's YAML case for a separate filer with no qualifying member and the reviewer's docstring (P3-1, P3-2), and it replaced the body paragraph the reviewer flagged in P3-2. The hub changed no formula. After landing, it deletes the side branch the reviewer found in P3-3 and logs P3-4's Michigan line comment as a follow-up.
  • Gates checked live at merge:
    • gh pr checks exits 0;
    • the latest Pull request run at the head concluded success;
    • MERGEABLE;
    • not a draft;
    • no reviewer's latest review requests changes;
    • the semantic-overlap guard;
    • head pinned.
  • Impact (hub full-file microsimulation, merge base 97b6d5135c against this head, in the description): 2026: section_22_income -78.7M (25 records); elderly_disabled_credit_potential -11.8M (25 records). No tax, benefit or household_net_income value moves.
  • Axiom: [pe-parity] Add separate-filer companions for §22 and check the pre-2026 versions (PE-US PR 10578) TheAxiomFoundation/rulespec-us#1982 queued

@MaxGhenis
MaxGhenis deleted the elderly-credit-separate-filer-base branch November 3, 2026 05:59
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.

2 participants