Skip to content

Extend Maine's childless EITC expansion to 2021 students aged 19 to 23 - #10526

Merged
MaxGhenis merged 5 commits into
mainfrom
me-childless-eitc-student-age-gate
Oct 29, 2026
Merged

MaxGhenis merged 5 commits into
mainfrom
me-childless-eitc-student-age-gate

Conversation

@MaxGhenis

@MaxGhenis MaxGhenis commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

Status: ready for review. Round 1 of the independent review (GPT-6.1 Sol) asked for changes, and the second commit makes them: the fractional-age bound, a statutory test oracle with fixed witnesses, disclosure of the mixed-age couple change, the source-conflict candidate, and the test costs below. Round 2 confirmed those and found no new calculation defect. It asked for the register entry and the code marker in this PR; Source conflict below explains why they follow the merge, and this head adds the source captures and fixes the citations it flagged. Round 3 approved this head (6f22e592b4). The 2026 default-dataset impact run (10526-impact) ran on this head and found no change (see Impact).

36 M.R.S. 5219-S(6) adds a childless individual to Maine's "eligible individual" when that individual:

is at least 18 years of age and has not attained 25 years of age before the close of the taxable year and who also meets the qualifications under Section 32(c)(1)(A)(ii)(I) and (III) of the Code.

5219-S(5) computes that individual's credit "in the same manner as it would be calculated if that individual were eligible for a federal earned income credit".

The bug

me_childless_eitc_age_eligible ended Maine's added cohort at the federal non-student minimum age (gov.irs.credits.eitc.eligibility.age.min). For 2021, 26 U.S.C. 32(n)(1)(B) set that minimum at 19, "in the case of a specified student …, age 24". A 2021 full-time student aged 19 to 23 therefore failed the federal age test and also fell outside Maine's cohort, and got no Maine credit.

2021, Maine, single, $5,000 of wages, on main:

Age Student eitc me_childless_eitc_age_eligible me_pro_forma_childless_eitc me_eitc
22 no 765 false 0 153
22 yes 0 false 0 0

The law gives the student $153. 32(n)(3)-(4) set the 2021 childless credit at 15.3% of the first $9,820 of earned income, so $5,000 earns $765 as if eligible. 5219-S(1) pays 20% "for taxable years beginning after December 31, 2020 and before January 1, 2022". Main gave $0 to students aged 19, 22 and 23 in the same run; ages 18 and 24, and all non-students, were already right.

The fix

me_childless_eitc_age_eligible now holds when all of these are true:

  • the tax unit has no qualifying child;
  • the filer or, on a joint return, either spouse is at least 18 and has not attained 25;
  • no filer or spouse meets the federal age test of 32(c)(1)(A)(ii)(II).

The federal test reads min, min_student and max exactly as eitc_demographic_eligible does: 19, 24 for a student and no maximum in 2021, and 25 to 64 otherwise. Maine's upper bound used to come from the federal minimum. It is now its own parameter, gov.states.me.tax.income.credits.eitc.eligibility.age.max = 24, compared in completed years: "has not attained 25" holds until the 25th birthday, so a filer aged 24.5 is in the range. (Main's age < 25 admitted 24.5 as well; the first head of this PR compared age <= 24 and lost it, which the review caught.)

No filer gets both credits. me_eitc takes max_(eitc, me_pro_forma_childless_eitc) times the Maine rate, which already ruled out double counting. After this change the two never overlap. The pro forma is zero outside the cohort (defined_for). Inside it, a childless filer and spouse both fail the federal age test, so eitc_demographic_eligible, and with it eitc, is zero. The me_eitc comment now says so. me_pro_forma_childless_eitc is unchanged.

Other years: mixed-age couples move to the federal path. 2020 and 2022 onward have the same federal minimum for students and non-students (25), so for single filers the cohort is the same as on main. One group changes: a joint couple where one spouse is 18 to 24 and the other meets the federal age test (for example 22 and 30).

  • Law. That couple is an eligible individual under 32(c)(1) already: on a joint return the age test passes if either spouse meets it. 5219-S(1-A) pays such a couple "50% of the federal earned income credit for the same taxable year". 5219-S(5) computes the credit of any childless eligible individual under 25 "as if that individual were eligible for a federal earned income credit"; for a couple that is federally eligible, that is the federal credit. MRS's 2024 worksheet takes line 1 from the federal credit claimed ("the amount from federal Form 1040, line 27"), and its special instructions route to a pro forma only "certain taxpayers who are not able to claim the federal EIC".
  • Amount. The same: the pro forma and the federal credit compute the same 32(b) amount for this couple. So the statute does not decide between the two paths; the model's participation convention does.
  • Take-up. Here the model changes. The federal path applies takes_up_eitc, as it does for every federally eligible filer; the pro forma applies none. So a mixed couple that does not take up the federal EITC now gets no Maine credit (YAML case: 2025, 22 and 30, takes_up_eitc: false, $0; main gave $191.25). It now matches every other federally eligible Maine filer. This is a modelling choice for consistency, not something the statute requires: the statute does not speak to take-up. Whether the state-only paths (this pro forma, Maryland's, New Jersey's age path) should apply take-up too is a cross-state methodology question, queued for a decision; this PR does not change it.

Tests

YAML (49 cases in the three Maine EITC files, all pass):

  • me_eitc.yaml: a 2021 grid at ages 18, 19, 22, 23 and 24, student and not, with $5,000 of wages. Every case checks the cohort flag, eitc, the pro forma and me_eitc = 153: filers who fail the federal age test take the pro forma at 765, and the rest take the federal credit at 765. Fractional ages: 2025 aged 24.5 (pro forma, $191.25), 2025 aged 25 (federal, $191.25), 2021 student aged 23.5 and non-student aged 18.5 (pro forma, $153). Also 2025 cases: a student aged 22, a couple aged 22 and 30 (federal path, with and without take-up) and a couple aged 22 and 66 (pro forma).
  • me_childless_eitc_age_eligible.yaml: 2021 joint returns (student 22 with non-student 22; students 22 and 20; student 22 with a spouse aged 70, since 2021 had no federal maximum), a 2021 student aged 25, a 2025 student aged 24, 2025 couples aged 22/30, 22/66 and 17/66, and dependents aged 30 and 20 whose ages count for neither test.

Expectations come from 32(b), 32(n) and 5219-S(1)/(1-A), not from the engine: 15.3% × $5,000 = $765 and 20% of it = $153 for 2021, and 7.65% × $5,000 = $382.50 and 50% of it = $191.25 for 2025.

Mutations. Each mutant, applied alone, against the two YAML files and me_pro_forma_childless_eitc.yaml (49 cases) and, for four of them, the Python invariant tests:

Mutation YAML cases failed (of 49) Python tests failed (of 4)
Restore main's gate (cohort ends at the federal non-student minimum) 8: the 2021 students aged 19, 22, 23 and 23.5; the 2021 student couple aged 22 and 20; the 2025 couple aged 22 and 30 (three cases) 4
Compare the exact age with 24 (the first head of this PR) 1: the 2025 filer aged 24.5 3 (all but the 2021 grid, where 24.5 meets the federal test)
Drop the student minimum 5: the 2021 students aged 19, 22, 23 and 23.5, and the 2021 student couple aged 22 and 20 not run
Drop the federal maximum 2: the 2025 couple aged 22 and 66 (both files) not run
Drop Maine's upper bound of 24 3: singles aged 65 and 70, and a filer aged 66 with a dependent aged 20 not run
Count dependents in Maine's range 1: a filer aged 66 with a dependent aged 20 not run
Count dependents in the federal age test 1: a filer aged 20 with a dependent aged 30 not run
Drop the federal age test 10: the 2021 non-students aged 19 to 24, the 2021 student aged 24, the 2021 couples where one spouse meets the federal test, and the 2025 couple aged 22 and 30 (three cases) 4
me_eitc pays nothing 22 4 (round 1 found the Hypothesis test let this through; the witnesses now catch it)
me_eitc: add the federal credit and the pro forma instead of taking the larger 0, as intended. The two paths never overlap, so the sum and the larger agree; invariant 4 checks that directly not run

The Python runs used --hypothesis-seed=1; each failing run took about 6 minutes, most of it Hypothesis shrinking.

Invariants (tests/test_me_childless_eitc_age_gate.py, grid; …_property.py, Hypothesis). Each batch runs three times: as is; under a reform that removes the federal age test (minimums 0, maximum 200), so that every household is federally age-eligible and nothing else changes; and with every student flag cleared. Households vary ages 18 to 80 (mostly 18 to 24, plus 18.5, 23.5, 24.5 and 24.99), students, single and joint, children, wages, unemployment compensation, interest above and below the investment-income limit, SSN status and claimability.

  1. Twin equality (the requested property). A household with a filer or spouse at least 18 and under 25, or one that meets the federal age test, gets the same me_eitc as its twin without the federal age test. So a filer who fails only the age test gets what an otherwise identical federally eligible filer gets, and one who also fails another requirement gets nothing either way.
  2. Student status never changes me_eitc.
  3. The cohort equals an oracle written from the statute's ages (no qualifying child, a filer or spouse with 18 ≤ age < 25, neither meeting 25 to 64, or 19/24 and no maximum in 2021). For childless households with no claimable filer, it also equals "a filer or spouse in Maine's range" and "not eitc_demographic_eligible" (a differential check against the federal code).
  4. One path only: the cohort never overlaps eitc_eligible, eitc is zero in the cohort, the pro forma is zero outside it, and me_eitc equals the statutory rate times eitc plus the pro forma.
  5. A childless household with no one in Maine's range that fails the federal age test gets nothing.
  6. Witnesses. Every batch, grid or Hypothesis, also runs four fixed childless households with $5,000 of wages (a student aged 22, a filer aged 24.5, couples aged 30/22 and 70/22), checks each one's cohort flag by year, and checks me_eitc against the statutes: the Maine rate times the 32(b) phase-in rate times $5,000 ($95.625 in 2020, $153 in 2021, $191.25 from 2022). A filer aged 17, head by input, gets $0 while the twin without the age test gets the same statutory amount. So no check can pass on an empty mask or a credit of zero everywhere. In 2021 every generated filer is at least 18 and meets some age rule, so invariant 5's mask is empty there; the separate age-17 witness covers that exclusion in every year.

Checks 1 and 2 hold because every household takes up the EITC: without take-up the federal path pays nothing and the pro forma still pays (see Take-up above). Also held fixed because the pro forma does not model them yet (unchanged here): separate returns (#10307) and section 911 claims (#10525).

Runs. On head c07147b64c, local macOS, Python 3.13, on a loaded shared host (not Linux CI):

  • YAML: the 49 cases in the three Maine EITC files, the 195-case Maine credits tree and the 679-case Maine tree all pass (Maine tree: 107 s wall, 6.9 GB peak RSS).
  • Python: the two new modules pass 4 tests in 74 s wall (57 s inside pytest), 2.70 GB peak RSS, run alone. code_health/test_source_conflicts.py passes (103). ruff format --check and ruff check pass.

CI cost. Neither module existed before, so they add their whole cost. Both fall in the Rest Python remaining group. Main's latest push run (40753949728) measured that group at 18:04 and 8.0 GB peak RSS on Linux CI, below the Makefile's ~10 GB per-process target; remaining-heavy (10.5 GB) is already above it, so the modules stay in remaining. They add about a minute and one reformed CountryTaxBenefitSystem, which they release at module teardown, so it does not stay resident for later modules. The shard planner reads past timings, so the PR adds no runner or matrix entry.

Why Python and not only YAML. The requested property compares each household with an otherwise identical twin under a reform that removes the federal age test, across thousands of generated households and five years. YAML cannot run a reformed twin or generate households. Every amount the YAML can pin is in YAML.

Impact

The default dataset cannot measure 2021. DEFAULT_DATASET is the single-year file populace_us_2024.h5. Microsimulation extends it forward only (extend_single_year_dataset builds each year from the base year 2024 to the end year), so it has no 2021 records. The 2021 student fix, the main change here, therefore has no microsimulation estimate.

2026: no change. The run compared main (c55b806) with this head (6f22e59) on the default dataset. No record changed in eitc, me_eitc, me_childless_eitc_age_eligible, me_pro_forma_childless_eitc, state_income_tax, income_tax, household_net_income or household_benefits. Both give Maine EITC of $56.1 million, a pro forma childless credit of $9.4 million, and a cohort of about 60,180 weighted tax units.

In 2026 this PR's cohort differs from main's only for a childless joint return that pairs a spouse aged 18 to 24 with one aged 25 to 64 (main's age < 25 already admitted fractional ages below 25), so the dataset holds no such Maine return. Where one exists, its Maine credit changes only if its federal credit falls below the pro forma: main paid it the larger of the two, and this PR pays the federal credit. That happens when the couple does not take up the EITC, does not file, or fails another federal rule the pro forma does not apply.

Source conflict

MRS's 2024 EITC worksheet tells the filer to answer the federal age question "Yes" "if you (or your spouse, if married) were at least 18 years of age", with no upper bound, and the 2025 Form 1040ME instructions (Schedule A line 4) say "Taxpayers at least age 18". 5219-S(6) stops at 25. A 2024 or 2025 single filer aged 66 with $5,000 of wages gets $0 under the statute and $191.25 under the worksheet. This PR follows the statute (the 2025 YAML cases at 65 and 70 pin it, and so does the Python test's statutory oracle). The conflict was already in the code on main (age < 25); this PR makes the cap its own parameter.

What this PR records, and what follows the merge:

Limitations and interactions

Axiom parity

  • axiom: us-me/statute/36/5219-S rulespec-us#1964 queued (extended with 2021 student and mixed-age companion cases in this comment). Add miscellaneous income #1964's design (output 3 takes the as-if amount when output 1 holds and the federal determination does not) already gets these cases right, but every companion case ran in TY2025. Add MD AGI subtraction for pension income #1651 owns the corpus repair and 5219-S(1)'s 2021 rate, which these cases need. A follow-up comment adds the fractional-age cases (24.5 in 2025, a 23.5-year-old student in 2021) and the worksheet's age-cap conflict.

🤖 Generated with Claude Code

36 M.R.S. 5219-S(6) adds childless filers aged 18 to 24 to Maine's eligible
individuals. The cohort flag stopped at the federal non-student minimum age, so
in 2021 (minimum 19, or 24 for a student under 26 U.S.C. 32(n)(1)) a full-time
student aged 19-23 failed the federal test yet fell outside Maine's cohort and
got no Maine credit. The flag now covers ages 18-24 whenever no filer or spouse
meets the federal age test, with Maine's own upper bound as a parameter.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
YAML: a 2021 grid at ages 18, 19, 22, 23 and 24, student and not, checking
the cohort flag, federal EITC, pro forma and Maine EITC; 2025 student, mixed-
age couple (with and without take-up) and both-ineligible couple cases; and
joint-return and dependent edge cases for the flag.

Invariants (grid and Hypothesis): a household with a filer or spouse aged
18-24 gets the same Maine credit as its twin with the federal age test removed;
student status never changes the Maine credit; the cohort matches an oracle
from the statute's ages and the federal eitc_demographic_eligible; the federal
path and the pro forma never overlap.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis and others added 2 commits October 29, 2026 00:42
…tests

5219-S(6) covers a filer who "has not attained 25", so a filer aged 24.5 is
in the range; the gate now compares completed years with the maximum of 24.
The invariant tests take the statutory range as their oracle, add fractional
ages, and run fixed witnesses whose Maine credit comes from the statutes
(including a filer aged 17, head by input), so no check passes on empty
masks or on a zero credit. Records the worksheet's open-ended "at least 18"
as a source-conflict candidate (statute followed), dedupes the new
parameter's references, and discloses the mixed-age couple change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Rest Python remaining group runs other modules in the same process, so
the cached system without the federal age test should not stay resident.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaxGhenis
MaxGhenis marked this pull request as ready for review October 29, 2026 05:19
@codecov

codecov Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

Codecov Report

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

Additional details and impacted files
@@            Coverage Diff            @@
##              main    #10526   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files            4         2    -2     
  Lines           76        35   -41     
  Branches         2         0    -2     
=========================================
- Hits            76        35   -41     
Flag Coverage Δ
unittests 100.00% <100.00%> (ø)

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.

Adds pdftotext captures of MRS's 2024 EITC worksheet and page 10 of the 2025
Form 1040ME instructions under source_conflicts/sources/us-me/, so the
us-me:childless-eitc-age-cap register entry can pin them once this lands.
The refundable Maine EITC is Schedule A line 4, not line 2 (child care), in
the candidate entry and in the minimum-age parameter's reference.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaxGhenis
MaxGhenis merged commit 48a0943 into main Oct 29, 2026
35 checks passed
@MaxGhenis
MaxGhenis deleted the me-childless-eitc-student-age-gate branch October 29, 2026 07:39
@MaxGhenis

Copy link
Copy Markdown
Contributor Author

Merge audit. Admin squash-merged as 48a0943 at the reviewed head 6f22e592b4, with --match-head-commit. The only block was the required approving review.

  • Independent review: GPT-6.1 Sol, three rounds. Round 1 requested changes (fractional-age bound, test oracle, disclosure); the second and third commits addressed them. Round 2 found no calculation defect and asked for the register entry and marker in this PR. Round 3 accepted the post-merge order in Source conflict and approved 6f22e592b4.
  • CI: all 35 checks passed on that head (gh pr checks exit 0), re-checked right before the merge. No review requested changes.
  • Impact: 2021 is outside the default dataset. 2026 shows no change in any measured variable (see Impact).

Follow-ups:

  1. Register us-me:childless-eitc-age-cap in rulespec-us known-source-conflicts.yaml. Its implementation is 48a0943, pinned by the YAML cases "2025 childless single aged 70 outside the expansion gets no credit" and "Childless single aged 65 is outside the added cohort". Its pending_texts are the two captures in source_conflicts/sources/us-me/.
  2. A PE-US PR then adds the # Source conflict us-me:childless-eitc-age-cap marker, bumps the pin and deletes the candidate.
  3. Apply the federal EITC qualifications to Maryland, Maine and New Jersey EITC recomputations #10525 and Apply the Maryland and Maine EITC waivers of the 32(m) SSN requirement #10527 overlap this change in the Maine EITC files. Apply the Maryland and Maine EITC waivers of the 32(m) SSN requirement #10527's owner has the details.

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