Repository navigation
Extend Maine's childless EITC expansion to 2021 students aged 19 to 23 - #10526
Merged
Merged
Conversation
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>
…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
marked this pull request as ready for review
October 29, 2026 05:19
Codecov Report✅ All modified and coverable lines are covered by tests. 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
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
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>
Contributor
Author
|
Merge audit. Admin squash-merged as 48a0943 at the reviewed head
Follow-ups:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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:
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_eligibleended 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:
eitcme_childless_eitc_age_eligibleme_pro_forma_childless_eitcme_eitcThe 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_eligiblenow holds when all of these are true:The federal test reads
min,min_studentandmaxexactly aseitc_demographic_eligibledoes: 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'sage < 25admitted 24.5 as well; the first head of this PR comparedage <= 24and lost it, which the review caught.)No filer gets both credits.
me_eitctakesmax_(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, soeitc_demographic_eligible, and with iteitc, is zero. Theme_eitccomment now says so.me_pro_forma_childless_eitcis 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).
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 andme_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:me_eitcpays nothingme_eitc: add the federal credit and the pro forma instead of taking the largerThe 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.me_eitcas 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.me_eitc.eitc_demographic_eligible" (a differential check against the federal code).eitc_eligible,eitcis zero in the cohort, the pro forma is zero outside it, andme_eitcequals the statutory rate timeseitcplus the pro forma.me_eitcagainst 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):code_health/test_source_conflicts.pypasses (103).ruff format --checkandruff checkpass.CI cost. Neither module existed before, so they add their whole cost. Both fall in the Rest Python
remaininggroup. 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 inremaining. They add about a minute and one reformedCountryTaxBenefitSystem, 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_DATASETis the single-year filepopulace_us_2024.h5.Microsimulationextends it forward only (extend_single_year_datasetbuilds 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 ineitc,me_eitc,me_childless_eitc_age_eligible,me_pro_forma_childless_eitc,state_income_tax,income_tax,household_net_incomeorhousehold_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 < 25already 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:
Here: the candidate
us-me:childless-eitc-age-cap(ruled, statute) insource_conflicts/candidates.yaml, and pdftotext captures of both agency sources insource_conflicts/sources/us-me/, so the register entry can pin them by a commit on main.After merge: the register entry in rulespec-us
known-source-conflicts.yaml, then a PE-US PR that adds the# Source conflict us-me:childless-eitc-age-capmarker, bumpspin.yamland deletes the candidate. That order is forced:pending_texts, pinned to a capture by PE-US commit. rulespec-us's provenance check (tools/pin_runner.py,tools/source_conflicts.py) accepts only commits reachable from PE-US main, and PE-US squash-merges, so no commit on this branch qualifies. The same holds for the implementation and its pinning tests; until then an open PR can only be listed underproposed.test_source_conflicts.pyfails on a marker whose entry is not in the vendored register or does not list the marked file among its implementations, and CONTRIBUTING.md refreshes the vendored copy from rulespec-us main (a project rule; the updater script itself accepts any commit).Earlier rulings followed the same order: Decide CA Premium Subsidy eligibility on the exact FPL ratio and adopt the Final 2027 design #10305 and Limit Hawaii, Vermont and Kentucky TANF dependent care deductions to the care their rules allow #10254 merged with
candidates.yamlentries, and captures, register entries and markers have come in their own PRs (Capture sources for eight source-conflict register entries; pin Hawaii's claimable filer #10399, Mark nine source conflicts now in the shared register #10441, Vendor the source-conflict register at rulespec-us ad03b325 #10445). The YAML cases at 65 and 70 and the Python oracle can pin the implementation when the entry lands.Limitations and interactions
is_full_time_studentfor the federal student minimum, and does not model 32(n)(1)(B)(iii) (qualified former foster or homeless youth, minimum age 18). Neither changes the Maine credit for anyone aged 18 to 24: a misclassified filer moves between the federal path and the pro forma at the same amount, except for take-up.eitc_demographic_eligiblecompares the exact age with the federal maximum of 64, so a filer aged 64.5, who has not attained 65, fails the federal test. That is outside this PR; the property test avoids ages between 64 and 65.me_pro_forma_childless_eitc.pyand its YAML. This PR touches neither file, so the two should not conflict.me_childless_eitc_age_eligible.py(the child count,me_eitc_child_count) andme_eitc.py(the federal amount,me_federal_eitc_without_ssn_requirement, which keeps the federal age test). The two compose; whichever lands second keeps both. It must also move this PR's invariant 4 and its child count to those variables, because the grid includes filers without an SSN, whom Apply the Maryland and Maine EITC waivers of the 32(m) SSN requirement #10527 pays from 2021. Apply the Maryland and Maine EITC waivers of the 32(m) SSN requirement #10527's owner has the details.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