Skip to content

Cap the educator expense deduction per eligible educator (26 U.S.C. 62(a)(2)(D)) - #9833

Merged
MaxGhenis merged 9 commits into
mainfrom
fix-educator-expense-cap
Oct 6, 2026
Merged

MaxGhenis merged 9 commits into
mainfrom
fix-educator-expense-cap

Conversation

@MaxGhenis

@MaxGhenis MaxGhenis commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Summary

gov.irs.ald.deductions listed the raw educator_expense input, and nothing under parameters/gov/irs or variables/gov/irs capped it. Every dollar a filer entered came off AGI. Under 26 U.S.C. 62(a)(2)(D) each eligible educator deducts at most $250, indexed from 2016 under 62(d)(3): $300 for 2022 through 2025 and $350 for 2026. On a joint return each spouse is capped separately.

This PR adds the cap parameter and a capped deduction, educator_expense_ald, and puts it in the ALD list in place of the raw input. After 2026 the cap is projected from the statutory $250 base, as 62(d)(3) computes it.

The law

26 U.S.C. 62(a)(2)(D) (OLRC, via the pinned Axiom corpus row us/statute/26/62, as of Online@119-100):

The deductions allowed by section 162 which consist of expenses, not in excess of $250, paid or incurred by an eligible educator— (i) by reason of the participation of the educator in professional development courses ... and (ii) in connection with books, supplies (other than nonathletic supplies for courses of instruction in health or physical education), computer equipment (including related software and services) and other equipment, and supplementary materials used by the eligible educator in the classroom.

62(d)(1)(A):

the term "eligible educator" means, with respect to any taxable year, an individual who is a kindergarten through grade 12 teacher, instructor, counselor, principal, or aide in a school for at least 900 hours during a school year.

Pub. L. 119-111, division B, §1 (approved September 18, 2026; 140 Stat. 1049) amends 62(d)(1), and the amendments "shall apply to expenses paid or incurred in taxable years beginning after December 31, 2025." It strikes "a kindergarten through grade 12 teacher" and inserts "an early childhood or kindergarten through grade 12 teacher". For early childhood education, "school" now means

any school or childcare facility which— (I) provides educational or childcare services for more than 2 individuals (other than individuals who reside at the school or facility) who have not attained age 6, and (II) operates at the public expense or receives a fee, payment, or grant for providing such services for any of the individuals (regardless of whether such school or facility is operated for profit)

The 900-hour test, the dollar amount and its indexing are unchanged, so both groups have the same cap.

62(d)(3):

In the case of any taxable year beginning after 2015, the $250 amount in subsection (a)(2)(D) shall be increased by an amount equal to— (A) such dollar amount, multiplied by (B) the cost-of-living adjustment determined under section 1(f)(3) for the calendar year in which the taxable year begins, determined by substituting "calendar year 2014" for "calendar year 2016" in subparagraph (A)(ii) thereof. Any increase determined under the preceding sentence shall be rounded to the nearest multiple of $50.

The cap applies per educator, not per return. The Form 1040 instructions for Schedule 1, line 11 (2022, p. 87) say:

If you and your spouse are filing jointly and both of you were eligible educators, the maximum deduction is $600. However, neither spouse can deduct more than $300 of their qualified expenses on line 11.

The 2016 through 2021 instructions say the same with $500 and $250. Pub. L. 107-147 §406 added the deduction for taxable years beginning after 2001. A series of extensions carried it year by year, and Pub. L. 114-113 §104 made it permanent and added (d)(3) (US Code amendment notes, govinfo USCODE-2023).

Parameter values

gov.irs.ald.educator_expense.cap, per eligible educator. Each value was read from the cited PDF; page numbers are PDF pages.

Taxable years Cap Source
2002–2015 $250 26 U.S.C. 62(a)(2)(D)
2016 $250 2016 Form 1040 instructions, line 23 (p. 31). Rev. Proc. 2015-53, the 2016 inflation release, lists no educator amount.
2017 $250 Rev. Proc. 2016-55 §3.12 (p. 14)
2018 $250 Rev. Proc. 2017-58 §3.12 (p. 12). Rev. Proc. 2018-18 (IRB 2018-10) restated the TCJA-affected items and does not mention educators.
2019 $250 Rev. Proc. 2018-57 §3.14 (p. 15)
2020 $250 Rev. Proc. 2019-44 §3.14 (p. 12)
2021 $250 Rev. Proc. 2020-45 §3.14 (p. 12)
2022 $300 Rev. Proc. 2021-45 §3.13 (p. 13)
2023 $300 Rev. Proc. 2022-38 §3.13 (p. 12)
2024 $300 Rev. Proc. 2023-34 §3.13 (p. 11)
2025 $300 Rev. Proc. 2024-40 §2.13 (p. 11)
2026 $350 Rev. Proc. 2025-32 §4.12 (p. 17)
2027 on projected 62(d)(3) from the $250 base, below

Projection. 62(d)(3) increases the $250 amount itself, not the last published cap, and rounds the increase to the nearest multiple of $50. After 2026, extend_educator_expense_cap in parameters/uprating_extensions.py computes each year that way: $250 plus $250 × get_irs_cola(parameters, year, 2014), with the increase rounded to the nearest $50. get_irs_cola is the repo's 1(f)(3) cost-of-living adjustment, and 2014 is the base year 62(d)(3) substitutes for 2016. This is how extend_dependent_standard_deduction_parameters already projects the 63(c)(5) limits from their statutory bases. The published values for 2002–2026 stay in the YAML and take precedence. On the repo's CPI series the same computation reproduces every published cap from 2016 to 2026. It is also the formula rulespec-us encodes in eligible_educator_expense_cap_after_inflation_adjustment: base + floor(base × COLA / 50 + ½) × 50.

2027–2029 2030–2031 2032–2035 2036–2038 2039–2040 2075 2100
Round 1 (uprating the rounded $350) $350 $400 $400 $450 $450 $900 $1,500
This branch (62(d)(3) from $250) $350 $350 $400 $400 $450 $850 $1,400

The increase is $120.06 in 2031 and $127.32 in 2032, within $5 of the $125 rounding point, so a CPI forecast update can move that step by a year.

What changes

  • New parameter gov.irs.ald.educator_expense.cap, with the values above.
  • New extend_educator_expense_cap in parameters/uprating_extensions.py writes the caps for 2027 on, as described under Projection. set_all_uprating_parameters calls it after the Chained CPI-U extension, as it calls the dependent standard deduction extension. cap.yaml keeps uprating: gov.irs.uprating with nearest $50 rounding to describe the index; the computed values supersede it, as they do for the dependent standard deduction.
  • New educator_expense_ald_person (Person) = min(max(0, educator_expense), cap). This is each person's own amount, as on their own return; a dependent's is computed too.
  • New educator_expense_ald (TaxUnit) = the sum of educator_expense_ald_person over the head and spouse. It uses tax_unit_non_dep_sum, the same is_tax_unit_dependent mask irs_gross_income uses, so a dependent's deduction leaves the filer's return exactly when their income does.
  • gov.irs.ald.deductions: educator_expense → educator_expense_ald in all four periods.
  • dependent_taxable_ss_magi: maps educator_expense_ald to educator_expense_ald_person, the dependent's own capped amount. It was the raw input.
  • medicaid_adjusted_gross_income_person: maps educator_expense_ald to educator_expense_ald_person in TAX_UNIT_AGI_ALDS_WITH_PERSON_LEVEL_EQUIVALENTS, beside the self-employment and alimony deductions. Keep dependents' above-the-line deductions off the filer's AGI #9801 made that a map and attributes each entry with person_share_of_tax_unit_amount. A dependent keeps their own capped amount, and the head and spouse each get their own whenever those sum to educator_expense_ald, which they always do unless it is an input or a reform changes it; then the two shares are scaled to it. On main, the head's and spouse's raw expenses are pooled and split 50/50 on a joint return, and a dependent's raw expenses reduce their own Medicaid AGI uncapped.
  • educator_expense input: its documentation now says what it is (an eligible educator's unreimbursed qualified expenses, entered in full) and cites 62(a)(2)(D), (d)(1) and Pub. L. 119-111. It says kindergarten through grade 12 educators qualify in every year and early childhood educators from 2026, and that the model takes any positive amount as an eligible educator's, so an early childhood educator's expenses belong only in 2026 and later. educator_expense_ald_person says the same.
  • Docs: the ALD README table gains 62(a)(2)(D). The Ohio comment no longer says the federal cap is "currently $300".

Readers of the ALD list, checked

These take the capped tax-unit amount with no edit:

  • above_the_line_deductions (adds the list);
  • taxable_ss_magi and taxable_uc_agi (add over the list);
  • ma_part_b_agi, which takes the list less Massachusetts' disallowed items;
  • adjusted_gross_income_person and student_loan_interest_ald_magi, which split non-person ALDs between head and spouse as before;
  • mo_adjusted_gross_income (the remainder after the self-employment ALDs).

tools/default_uprating.py keeps uprating the raw input. tests/core/test_ald_determinism.py uses educator_expense only as a synthetic name in a made-up list, so it is unchanged.

State treatments

  • Massachusetts conforms to the capped amount. 2024 Form 1 instructions, Schedule Y, line 9a (p. 20): "Enter the sum of the amounts reported on U.S. Form 1040, Schedule 1, line 11 (Educator expenses), ...". MA reads the federal list through ma_part_b_agi, so it now takes the capped amount, which is what line 11 holds.
  • Ohio and Virginia keep their own inputs, unchanged. oh_educator_expense_deduction_person (ORC 5747.01(A)(31), expenses above the federal amount) and va_educator_expenses (Va. Code 58.1-322.03, expenses not claimed federally) are separate inputs. Ohio's deduction list does not include the federal item, and neither state reads educator_expense.
  • States that start from federal AGI inherit the cap, which is what Schedule 1, line 11 carries.
  • California does not conform, before or after this PR. The 2024 Schedule CA (540) instructions, line 11: "California law does not conform to federal law regarding educator expenses. Enter the amount from line 11, column A on line 11, column B." The model has no CA add-back. CA was off by the raw expense and is now off by the capped amount. That is a separate fix, listed under follow-ups.

Interaction with #9801

#9801 (keep dependents' above-the-line deductions off the filer's AGI) merged first, as 1f9d85aafc. It sums person-level ALDs over non-dependents and puts a dependent's person-level deductions on the dependent's own Medicaid AGI. This branch merges main (b372bf24b0, then ce79d1ed5e for #9609 and #9722), so this PR lands second:

  • educator_expense_ald is tax-unit level and already leaves dependents out, so Keep dependents' above-the-line deductions off the filer's AGI #9801's tax_unit_non_dep_add takes it as is.
  • Merge conflict, resolved. Keep dependents' above-the-line deductions off the filer's AGI #9801 replaced the Medicaid AGI person-level list with a map from each tax-unit deduction to its person-level amount, attributed with person_share_of_tax_unit_amount. This branch had added educator_expense_ald_person to the old list. The resolution keeps Keep dependents' above-the-line deductions off the filer's AGI #9801's map and adds "educator_expense_ald": "educator_expense_ald_person" to it (described under What changes). Both Medicaid educator cases fail without that entry: with it removed, the dependent's AGI is 5,000 instead of 4,700, because the dependent's own capped amount is never subtracted (evidence/r2/finish-yaml-medicaid-educator-without-map-entry.txt).
  • The dependent's own capped amount reaches dependent_taxable_ss_magi through educator_expense_ald_person; that file merged without a conflict. Keep dependents' above-the-line deductions off the filer's AGI #9801's Case 3 (a dependent's $300 of 2025 educator expenses reduces the dependent's Medicaid AGI to 4,100) passes on this head.
  • Keep dependents' above-the-line deductions off the filer's AGI #9801's invariant test. Its PERSON_DEDUCTIONS built the reference ALD sum from the raw educator_expense, and its 2020 draws go up to $300, above 2020's $250 cap. This branch changes that entry to educator_expense_ald_person and keeps the raw input in DEPENDENT_DEDUCTION_INPUTS. On this head, with the entry still raw, both 2020 tests fail (test_dependent_deductions_stay_off_the_filers_return_2020 and test_seeded_population[2020]). With the edit, all 9 tests in the file pass.
  • This branch also adds educator_expense_ald to that test's AGGREGATES. The harness then checks that dependents' educator expenses never change it, and that it equals the numpy sum of the head's and spouse's educator_expense_ald_person.

Invariants

These hold for every input. The Hypothesis test checks them on drawn batches (2021, 2022, 2025, 2026) and on a seeded population of 200 tax units:

  1. Bound. 0 ≤ educator_expense_ald ≤ cap × (number of head and spouse with expenses) ≤ 2 × cap. It is also never more than the head's and spouse's expenses.
  2. Differential. educator_expense_ald = Σ over head and spouse of min(expenses, cap), computed in numpy with the caps taken from the Rev. Procs., not from the model. educator_expense_ald_person = min(expenses, cap) for everyone, dependents included.
  3. Monotone. Raising any member's expenses never lowers educator_expense_ald and never raises AGI.
  4. Dependents. Raising only dependents' expenses changes neither.
  5. Accounting. With wages the only income, AGI = wages of head and spouse − educator_expense_ald.
  6. No change below the cap. Units without dependents whose expenses are all at or below the cap keep the old deduction. The at- and below-cap YAML cases pass on main and on this branch.
  7. Projection. For every year from 2027 to 2100 the cap equals $250 plus $250 × get_irs_cola(year, 2014) rounded to the nearest $50, and is a multiple of $50. The values in cap.yaml (2002–2026) are what the parameter returns for those years. test_uprating_extensions.py checks both on the model's parameters, and checks on the repo's CPI path that the cap never falls from one year to the next. A unit test with a made-up CPI series checks the extension's rounding in both directions and that it keeps an encoded year.

Tests

Run by the build and the hub, one process at a time, with the worktree's own .venv (CPython 3.13, policyengine-core 3.32.15):

main (4613f8c792) this branch (f25432710e)
educator_expense_ald.yaml (13 cases) 13 failed (the variable doesn't exist) 13 passed
Existing educator outputs (13 cases, new variable stripped) 9 failed, 4 passed —
Dependent MAGI and Medicaid AGI educator cases 2 failed, 4 passed 6 passed
test_educator_expense_cap_invariants.py (Hypothesis) 5 failed 5 passed

Other folders on this branch: the ALD folder 92 passed; social security 24; Medicaid income 67; OH 163, VA 214, MA 116 and MO 235. tests/code_health passed 136. In test_ald_determinism.py, 8 tests passed and one hit a subprocess timeout under host load; it passed when the hub re-ran it alone (64 s).

Round 2, on this head (ce79d1ed5e, main merged in). Each line below is one process, run in sequence with CPython 3.13.9 and policyengine-core 3.32.15. Logs are in evidence/r2/finish-*.txt.

Result
ALD folder (now with #9801's dependent cases) 102 passed
educator_expense_ald.yaml, including the 2030 projected-cap case 14 passed (in the ALD folder)
Medicaid educator YAML, including the new input case 2 passed; both fail with the map entry removed
Medicaid income folder 71 passed
Social Security folder 24 passed
test_educator_expense_cap_invariants.py 5 passed
test_uprating_extensions.py, including the 4 projection tests 26 passed
#9801's test_dependent_above_the_line_deductions_invariants.py 9 passed; 2 fail (the 2020 tests) without the PERSON_DEDUCTIONS edit
tests/code_health, one process per file 144 passed. After the second merge, the three reference URL files (including #9609's new test_reference_urls.py) were rerun: 97 passed
tests/test_programs_registry.py (#9722) 638 passed, 10 skipped
ruff format --check . and ruff check . (ruff 0.15.5, from uv.lock) clean

Round 2's projection, fail-before. At f25432710e, the 2030 YAML case fails with educator_expense_ald_person at 400 rather than 350. The statutory projection test also fails, first at 2030 with 400 rather than 350 (evidence/r2/fix-r1-before-*.txt).

The merged tree's cap matches round 2's pre-merge values in every year compared, 2002–2040 plus 2050, 2075, 2100 and 2150 (evidence/r2/finish-cap-values-merged.json).

Microsimulation impact: current figures (hub, after merge): the real microsim against this PR's own base

This PR was merged with its 2024 and 2026 figures measured against main from before #9801, and the 2030 run still missing. These are the runs that measure it against the PR's actual merge base, post-#9801 main bab1a47c60, compared with the merged head ce79d1ed5e.

Setup:

  • Default dataset populace_us_2024.h5@populace-us-2024-spm-20260909.
  • Hub runner (lockrun.sh, run.py, compare.py), one run per side, matched record by record.
Year Above-the-line deductions AGI Federal income tax State income tax Household net income Tax units changed (weighted)
2026 −$67.6M +$68.2M +$12.4M +$2.0M −$14.6M 1.45M (706 records)
2030 −$146.9M +$148.2M +$27.8M +$5.1M −$33.3M 1.63M (765 records)

What these figures reflect:

  • The educator deduction is capped per person at the statutory amount.
  • From 2027, projected caps are rounded from the 2014-base COLA, giving $350 in 2030 rather than round 1's $400.
  • Dependents' expenses are already off the filer's return on this base (Keep dependents' above-the-line deductions off the filer's AGI #9801), so they aren't part of these figures.

educator_expense_ald itself isn't compared, because the base build doesn't produce that array under the same name. The deduction change shows up in above_the_line_deductions.

The 2030 branch run completed every output (log ends DONE educap-p 2030). Its wrapper reported rc 145 because the run was paused during a host hold, so the comparison was run separately on the saved arrays.

Evidence: ~/reviews/us-hub/educator-cap/evidence/r2/hub_compare_{2026,2030}.json.

Microsimulation impact (as originally merged)

Default dataset (populace_us_2024.h5@populace-us-2024-spm-20260909), policyengine-core 3.32.15, through the hub runner. Each figure compares two real runs on the same records: main and this branch, one run each.

2030, against current main

2030 is the first year round 2's projection changes the cap: $350, where round 1 had $400. Main is bab1a47c60 and this branch is ce79d1ed5e.

Not run in this round. Both runs waited on the hub runner from 06:06 to 08:07 EDT and never got the shared heavy lock: about a dozen other runs were queued and the host load average was above 100. The job withdrew them before either started, so no 2030 figure is reported here. evidence/r2/finish_impact_2030.sh runs the pair (main bab1a47c60 against ce79d1ed5e) and the record-by-record comparison when the lock allows. Until then, the projected-year change is the parameter itself: the cap is $350 in 2030 under this branch, where round 1 had $400, and the YAML case "2030, the projected cap is still $350" pins it for a single filer.

2024 and 2026, round 1, against main before #9801

Round 2 changes only the projected caps, from 2027 on. Every value from 2002 to 2026 is the same at f25432710e and at this head (both trees' cap parameter compared year by year), so round 2 does not move these results and they were not rerun.

They compare f25432710e with main at 4613f8c792, before #9801 merged. That main deducted a tax unit dependent's raw educator expenses on the filer's return. In the data, dependents' expenses come to $22.1M (weighted) in 2024 and $24.9M in 2026, from 145 records. Removing them from the filer's return is part of these changes. Current main already does that, through #9801, so against current main the changes would be smaller. No run against current main was made in this round. educator_expense itself is unchanged: $0.92bn in 2024 and $1.04bn in 2026.

Weighted change from main 2024 2026
above_the_line_deductions −$105.2M (827 tax units, 1.78M weighted) −$92.5M (802 tax units, 1.71M weighted)
adjusted_gross_income +$105.9M +$93.0M
income_tax +$17.7M (780 tax units) +$15.1M (748 tax units)
state_income_tax +$3.4M (560 tax units) +$2.7M (547 tax units)

AGI rises slightly more than deductions fall, because AGI feeds other parts of the calculation, such as the taxable share of Social Security.

Not in this PR

  • California add-back (Schedule CA (540), line 11, quoted above).
  • 26 U.S.C. 67(b)(13) and (g). The current Code makes educator expenses, defined without the dollar limit and including interscholastic sports administrators and coaches, an itemized deduction that is not a miscellaneous itemized deduction. The model has no such deduction. Expenses above the cap now go undeducted for itemizers, as they would on a return that never claimed them under 67(b)(13).
  • 62(d)(2) coordination. The deduction counts only expenses above the amounts excludable under §§135, 529(c)(1) and 530(d)(2). The model has no input for that overlap.
  • Eligible educator status is not an input: the role, the 900 hours, and from 2026 whether an early childhood educator's school or childcare facility qualifies. A positive educator_expense is taken to belong to an eligible educator, as before. Kindergarten through grade 12 and early childhood educators have the same cap, so the formula needs no split. For 2025 and earlier it would also deduct an early childhood educator's expenses if they were entered; the input's documentation says to enter them only from 2026.

Round 2

The independent review of f25432710e requested changes. This round answers it:

axiom: us:statutes/26/62#eligible_educator_expenses_allowable_above_the_line encoded-correct | TheAxiomFoundation/rulespec-us#1497 queued (Pub. L. 119-111 early childhood educators, TY2026 on; blocked on the pinned corpus, whose §62 text predates the amendment). rulespec-us us/statutes/26/62.yaml encodes the per-educator min(expenses − 62(d)(2) coordination amount, cap), the 900-hour definition, and the 62(d)(3) cap formula with rounding to the nearest $50. The companion test eligible_educator_expense_deduction_applies_cap_and_coordination (us/statutes/26/62.test.yaml) exercises it: $400 of expenses less $60 coordination, capped at $300 for a COLA of 0.2. The cost-of-living adjustment is an input there, so the Rev. Proc. year values are not RuleSpec atoms; the published 2026 figure is $350 (Rev. Proc. 2025-32 §4.12).

🤖 Generated with Claude Code

MaxGhenis and others added 4 commits October 5, 2026 15:30
YAML cases at, below and above the cap for 2021 ($250), 2022 and 2025
($300) and 2026 ($350); joint returns with one and two educators; a
dependent's expenses. A Hypothesis property checks the bound, a numpy
differential, monotonicity and the AGI identity.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…)(2)(D))

gov.irs.ald.deductions listed the raw educator_expense input, so the
federal deduction was uncapped. Add gov.irs.ald.educator_expense.cap with
each year's IRS value ($250 for 2002-2021, $300 for 2022-2025, $350 for
2026 per Rev. Proc. 2025-32 sec. 4.12), uprated after 2026 to the nearest
$50 as 62(d)(3) rounds. educator_expense_ald_person caps each person's
own expenses; educator_expense_ald adds the head's and spouse's amounts
and replaces the raw input in the ALD list. A dependent's own capped
amount feeds dependent_taxable_ss_magi and the dependent's Medicaid AGI.

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

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A member flagged as a tax unit dependent has their income left off the
filer's return by irs_gross_income, which masks on is_tax_unit_dependent;
mask their deduction the same way (tax_unit_non_dep_sum, as #9801 does
for the other person-level deductions). Make the dependent test case's
roles explicit.

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

codecov Bot commented Oct 6, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 96.11%. Comparing base (909176a) to head (f254327).
⚠️ Report is 211 commits behind head on main.

Additional details and impacted files
@@             Coverage Diff             @@
##              main    #9833      +/-   ##
===========================================
- Coverage   100.00%   96.11%   -3.89%     
===========================================
  Files            4        6       +2     
  Lines           76      103      +27     
  Branches         2        5       +3     
===========================================
+ Hits            76       99      +23     
- Misses           0        2       +2     
- Partials         0        2       +2     
Flag Coverage Δ
unittests 96.11% <100.00%> (-3.89%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

MaxGhenis and others added 5 commits October 5, 2026 23:12
… 62(d)(3))

Core's metadata uprating chained from the rounded 2026 value ($350), which
put the projected cap at $400 in 2030-2031. 62(d)(3) indexes the $250
amount with a 2014 base year and rounds the increase to the nearest $50, so
on the repo's CPI the cap stays $350 through 2031 and reaches $400 in 2032.

extend_educator_expense_cap computes each year after the last published
value from the statute, with get_irs_cola(parameters, year, 2014), as the
dependent standard deduction extension does. The published 2002-2026 values
stay explicit and take precedence.

Tests: the 62(d)(3) computation reproduces every published cap from 2016 to
2026; projected years 2027-2100 equal it, are multiples of $50 and never
fall; a synthetic index pins nearest rounding in both directions; and a
2030 YAML case expects $350.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…9-111)

Pub. L. 119-111, division B, section 1, adds early childhood educators to
the 62(d)(1) eligible educator definition for expenses paid or incurred in
taxable years beginning after 2025. The model has no educator-status input
and takes any positive educator_expense as an eligible educator's, so the
input's documentation now gives the effective-year split, and both groups
share the same cap.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#9801 (keep dependents' above-the-line deductions off the filer's AGI) has
landed, so this PR lands second.

- medicaid_adjusted_gross_income_person: main now maps each tax-unit
  deduction to its person-level amount and attributes it with
  person_share_of_tax_unit_amount. educator_expense_ald joins that map as
  educator_expense_ald_person. The helper keeps a dependent's own amount
  and gives the head and spouse their own amounts whenever those sum to the
  tax-unit amount, which educator_expense_ald always does unless it is an
  input or a reform changes it.
- test_dependent_above_the_line_deductions_invariants.py: PERSON_DEDUCTIONS
  builds the reference deduction sum from educator_expense_ald_person, the
  capped amount, instead of the raw educator_expense. Its 2020 draws reach
  $300, above 2020's $250 cap. DEPENDENT_DEDUCTION_INPUTS keeps the raw
  input.

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

test_dependent_above_the_line_deductions_invariants.py now lists
educator_expense_ald among its AGGREGATES, so the harness checks that a
dependent's educator expenses never change the filer's educator_expense_ald
and that it equals the numpy sum of the head's and spouse's
educator_expense_ald_person.

A Medicaid AGI case supplies educator_expense_ald directly, at 250 against
own amounts of 300 and 200, so person_share_of_tax_unit_amount scales the
head's and spouse's shares to 150 and 100 while the dependent keeps their own
300. Without the educator entry in the Medicaid map this case and the
existing one both fail.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Brings in #9609 (fused reference URLs) and #9722 (LIHEAP registry). No
conflicts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaxGhenis
MaxGhenis merged commit b79705b into main Oct 6, 2026
35 checks passed
@MaxGhenis

Copy link
Copy Markdown
Contributor Author

US + core hub merge audit, us#9833 at ce79d1ed5e8eed5c328750d60b55a106ba57ebb6 (squash)

  • Review: independent GPT-6.1 Sol review (Subfleet, --tier hard), APPROVE at ce79d1e with no P1–P3 findings and METHODOLOGY_CHOICE no.
    • It confirms that round 1's P2 (projected caps rounded from the wrong base) and P3 (early-childhood docs) are fixed.
    • It confirms the Keep dependents' above-the-line deductions off the filer's AGI #9801 integration: the Medicaid person-deduction map entry and the invariant-test edits.
    • It hand-checked the caps against §62(d)(3), Rev. Proc. 2025-32 §4.12 and the Schedule 1 instructions.
  • Gates checked live at merge:
    • gh pr checks exits 0;
    • MERGEABLE;
    • not a draft;
    • no CHANGES_REQUESTED review;
    • head pinned with --match-head-commit.
  • Impact: real 2024/2026 microsims are in the body. They are measured against main before Keep dependents' above-the-line deductions off the filer's AGI #9801, and the body says so. Current main already removes dependents' educator expenses, so the true change is smaller.
    • The hub is running 2030 and a fresh 2026 pair against the merge base bab1a47c60.
    • It will post them here and update the body.
    • This is a bug fix (statutory cap and rounding), so it lands on the gates whatever the size.
  • --admin: used only because a required approving review is the sole block.
  • Follow-up: rulespec-us#1497 (Pub. L. 119-111 early-childhood amendment) remains queued with the encoder.

@MaxGhenis
MaxGhenis deleted the fix-educator-expense-cap branch October 6, 2026 13:46
@MaxGhenis

Copy link
Copy Markdown
Contributor Author

Impact update (hub, after merge): the real microsim against this PR's own base

This PR was merged with its 2024 and 2026 figures measured against main from before #9801, and the 2030 run still missing. These are the runs that measure it against the PR's actual merge base, post-#9801 main bab1a47c60, compared with the merged head ce79d1ed5e.

Setup:

  • Default dataset populace_us_2024.h5@populace-us-2024-spm-20260909.
  • Hub runner (lockrun.sh, run.py, compare.py), one run per side, matched record by record.
Year Above-the-line deductions AGI Federal income tax State income tax Household net income Tax units changed (weighted)
2026 −$67.6M +$68.2M +$12.4M +$2.0M −$14.6M 1.45M (706 records)
2030 −$146.9M +$148.2M +$27.8M +$5.1M −$33.3M 1.63M (765 records)

What these figures reflect:

  • The educator deduction is capped per person at the statutory amount.
  • From 2027, projected caps are rounded from the 2014-base COLA, giving $350 in 2030 rather than round 1's $400.
  • Dependents' expenses are already off the filer's return on this base (Keep dependents' above-the-line deductions off the filer's AGI #9801), so they aren't part of these figures.

educator_expense_ald itself isn't compared, because the base build doesn't produce that array under the same name. The deduction change shows up in above_the_line_deductions.

The 2030 branch run completed every output (log ends DONE educap-p 2030). Its wrapper reported rc 145 because the run was paused during a host hold, so the comparison was run separately on the saved arrays.

Evidence: ~/reviews/us-hub/educator-cap/evidence/r2/hub_compare_{2026,2030}.json.

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