Repository navigation
Compare completed years in the childless EITC age ceiling - #10585
Conversation
IRC 32(c)(1)(A)(ii)(II) requires a childless filer not to have attained age 65 before the close of the year. The parameter holds 64, the highest qualifying completed age, but the test compared the raw age, so a filer aged 64.5 failed. Compare floor(age), as Maine's cohort test already does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Ready for hub review Head: What the item asked, and how it was resolved
Tests (one file per process)
Mutants (each in its own process, code restored after)
Judgment calls
Proposed follow-up issues
Generated by Claude Code |
|
Ready for hub review Independent review, round 1. No earlier The fix is correct and CI at the head is green. I'm asking for two small test and documentation changes (P2) before landing; nothing changes in the formula. FindingsP2-1. The new Python property test restates the formula, and the PR doesn't report its cost
- name: Childless filer aged 64.99 has not attained 65 and meets the age test, 2024
period: 2024
input:
people:
filer:
age: 64.99
is_tax_unit_head: true
ssn_card_type: CITIZEN
employment_income: 8_000
tax_units:
unit:
members: [filer]
filing_status: SINGLE
would_file_taxes_voluntarily: true
takes_up_eitc: true
output:
eitc_demographic_eligible: true
eitc: 612P2-2. No test covers the spouse side of the new comparisonUnder 32(c)(1)(A)(ii)(II), on a joint return either spouse can meet the age test. The code handles this through
- name: Joint filers aged 70 and 64.5 meet the age test through the spouse, 2024
period: 2024
input:
people:
head:
age: 70
is_tax_unit_head: true
ssn_card_type: CITIZEN
employment_income: 8_000
spouse:
age: 64.5
is_tax_unit_spouse: true
ssn_card_type: CITIZEN
tax_units:
unit:
members: [head, spouse]
filing_status: JOINT
would_file_taxes_voluntarily: true
takes_up_eitc: true
marital_units:
mu:
members: [head, spouse]
output:
# Either spouse may meet 32(c)(1)(A)(ii)(II); the spouse's completed age is 64.
eitc_demographic_eligible: true
eitc: 612P3-1. The comment at
|
| Mutant | New YAML (7) | eitc_demographic_eligible.yaml (21) |
Hypothesis (2) | Killed by |
|---|---|---|---|---|
M1 age <= max_age |
2 fail | 21 pass | 1 fail | 64.5 cases (2024 and 2026); property |
M2 age < max_age |
3 fail | 1 fail | 1 fail | 64.0 / 64.5 cases; "Childless 64-year-old"; property |
M3 np.round(age) <= max_age (mine) |
7 pass | 21 pass | 1 fail | property @example 64.99 only (see P2-1) |
| M4 age test on head only (mine) | 7 pass | 21 pass | 2 pass | only test_dependent_elsewhere_head_spouse_swap_invariance.py (see P2-2) |
Merge with #10583
#10583's head has moved from 7d651dee54 to 5d09b58583 since the brief was written. Both heads merge into this PR without conflict. The setup is a head-of-household filer with $8,000 wages and an 8-year-old qualifying child with ssn_card_type: NONE, so eitc_child_count is 0.
| Tree | 2023, filer aged 64.5 | 2023, filer aged 65.5 | 2020, filer aged 64.5 | 2020, filer aged 65.5 |
|---|---|---|---|---|
| main | 0 | 0 | 0 | 0 |
#10583 alone (7d651dee) |
600 | 600 | 0 | 0 |
| this PR alone | 600 | 0 | 538 | 0 |
merge with 7d651dee |
600 | 600 | 538 | 0 |
merge with 5d09b585 |
600 | 600 | 538 | 0 |
What each should get, assuming #10583's reading (ARPA struck former 32(c)(1)(F) from 2021, so a child without an SSN still makes the filer an eligible individual under (c)(1)(A)(i)):
- 2023, either age: the zero-child amount, $600, regardless of age. The merge gives 600 for both, so the two changes compose correctly.
- 2020: the merge keeps this PR's age-only result. At 64.5 that is 538, the same as main gives at whole ages: main pays 538 at 40.0 and 64.0 and 0 at 64.5. So this PR only makes 64.5 match 64.0.
Whether pre-2021 law should pay a filer whose only qualifying child lacks an SSN at all is #10583's question. The answer is the same on main, so it's not this PR's defect.
Checked and sound
-
Bug at main (
origin/main4bfc548d), 2024 single, $8,000:eitcis 612, 0 and 0 at ages 64.0, 64.5 and 65.0; at 64.999 it is 0. -
Same cases at the head: 612, 612 and 0; 612 at 64.999. In 2023: main gives 600, 0 and 0; the head gives 600, 600 and 0.
-
Is
np.floor(age) <= max_ageright? For "not attained age 65" with max = 64,floor(a) <= 64is equivalent toa < 65for every reala. It includes an integer 64 and excludes an integer 65 (both confirmed by run).- The minimum side
age >= min_agematches "attained age 25" exactly, so it doesn't need a floor. - For an integer max,
np.floor(age) <= maxis identical toage < max + 1. Either form would do.
- The minimum side
-
age/max.yaml: 64 from 2013,.infin 2021, 64 from 2022. There are no pre-2013 values.np.floor(80.5) <= infis true; the 2021 run gives 1,224 at both 64.5 and 80.5.- The new description ("completed age is at most this value") is accurate for this variable.
- No reform, contrib parameter or YAML test sets the parameter, so no fractional value exists anywhere (grep of
reforms/,parameters/gov/contrib, tests).
-
The hand values hold, computed from the repo's parameters before reading the YAML:
- 2024: phase-in rate 0.0765, maximum $632, phase-out start $10,330, so 0.0765 × 8,000 = 612.
- 2023: maximum $600, start $9,800, so 600 (612 capped).
- 2021: 1,224 matches the ARPA childless schedule in the parameters.
-
Federal sweep. I grepped every
agecomparison invariables/gov/irs/. Each upper bound is a strict<:- CTC at
ctc_qualifying_child_ignoring_filer_identification.py:31:age < thresholds[-1], where the threshold is 17 (18 in 2021). - CDCC at
cdcc_eligible.py:36:age < child_age, wherechild_ageis 13. - Kiddie tax at
amt_kiddie_tax_applies.py:44,47:age < 19/age < 24, fromgov.irs.dependent.ineligible_age. - The EITC qualifying-child age test runs through
is_qualifying_child_dependent.py:23, alsoage < 19/24. - For "not attained N", a strict
<against N is right for fractional ages. - Every other site is a lower bound
age >= threshold(aged standard deduction, senior deduction, IRA and 401(k) catch-up, Saver's Credit, elderly credit, TCE). For "attained N", that is also right. eitc_demographic_eligiblewas the only wrong federal site, which matches the body.
- CTC at
-
Readers of
eitc_demographic_eligible:eitc_eligiblegets better.dc_eitc_with_qualifying_child.py:35gets better: a DC child without a TIN plus a filer aged 64.5 now gets the federal-like childless amount.- Readers of
eitcthat take a max with a state path don't double-count: COco_eitc.py:91and MEme_eitc.py.
-
State copies. These give the same output on main and at this head, so they go to the follow-up the body already lists:
- NM
nm_eitc_demographic_eligible.py:35; - OK
ok_federal_eitc_demographic_eligible.py:46, frozen at 2020 law; - ME
me_childless_eitc_age_eligible.py:55; - DC
dc_eitc_without_qualifying_child.py:36; - CO
co_eitc.py:49: its ITIN path is still raw-age, butmax_with the now-correct federal EITC improves the result for SSN filers; - MD
federal_eitc_without_age_minimum.py:26: the childless MD credit uses this instead ofeitc, so it stays at 0 at 64.5 on both sides; - WA
wa_working_families_tax_credit.py:74andtools/state_eitc_helpers.py:60, both on frozen 2022 parameters; - IN
in_eitc_eligible.py:47-48, with its own parameter; - plus the NY WFTC reform from P3-2.
None of them reads
eitc_demographic_eligible, so this PR makes no state output worse. The body already carries the limit; it only needs the NY line added. - NM
-
Tests, one process each, all at the head:
eitc_demographic_eligible_fractional_age.yaml: 7 passed;eitc_demographic_eligible.yaml: 21 passed;eitc_eligible.yaml: 11 passed;test_eitc_age_ceiling_completed_years.py: 2 passed;test_me_childless_eitc_age_gate.py: 3 passed;test_me_childless_eitc_age_gate_property.py: 1 passed;test_dependent_elsewhere_head_spouse_swap_invariance.py: 8 passed;earned_income_tax_credit.yaml: 3 passed, run under M4 only (I did not run it at the unmutated head).
-
Hypothesis ranges:
- Ages are drawn from [25, 80] and rounded to 2 decimals, so the 2021 minimum of 19 is never exercised; YAML covers the minimum at 24.5.
- The boundary is reached only through explicit
@examples: 63.99, 64.0, 64.5, 64.99, 65.0 and 65.5. max_examples=10.- The monotonicity test checks the stated claim.
-
CI at
d710b14cab: the "Pull request" run41414877820succeeded. All 31 of its jobs reportsuccess, including Household API Partners, every baseline shard, Microsimulation and the seven Python shards. One earlier run (41407680853) showsskipped; it was from the draft period and doesn't count. -
Scope:
- The PR changes 5 files and none sits under
.github/ortests/policy/baseline/partners/. - The changelog fragment
changelog.d/eitc-age-ceiling-completed-years.fixed.mdis top-level and matches the branch name. - The body has both an
impact:line and anaxiom:line.
- The PR changes 5 files and none sits under
-
Open-PR overlap:
- Searching open PRs for
eitc_demographic_eligiblereturns Let a qualifying child without an SSN establish EITC eligibility from 2021 #10583, Fix EITC eligibility for married separate filers #10307 and Apply Iowa, Kansas, Louisiana and Maryland rules for a filer who can be claimed as a dependent #10045. Fix EITC eligibility for married separate filers #10307 and Apply Iowa, Kansas, Louisiana and Maryland rules for a filer who can be claimed as a dependent #10045 match on text only: their file lists don't includeeitc_demographic_eligible.py. - Searching for
max.yaml, the new YAML file name and the new Python file name returns nothing beyond this PR.
- Searching open PRs for
-
Baseline impact:
- The diff can move a baseline output only for a head or spouse whose
agelies strictly between 64 and 65 in a year with max = 64, and who has no counted qualifying child. - If the enhanced CPS stores whole-year ages, the change can't move any output at baseline.
- The diff can move a baseline output only for a head or spouse whose
What I couldn't check
- Statute text. uscode.house.gov, govinfo.gov, law.cornell.edu and irs.gov were all refused by this session's network proxy, so I couldn't re-read 26 U.S.C. 32(c)(1)(A)(ii)(II), 32(n), 24(c), 21(b) or 152(c)(3) here. The quotations above come from the brief and the code comments, and I haven't verified them against the source. The same goes for former 32(c)(1)(F) (the 2020 row of the Let a qualifying child without an SSN establish EITC eligibility from 2021 #10583 table).
- Population data. I couldn't check whether any dataset (enhanced CPS or another) carries a fractional
age, so the population impact is unverified. The hub'simpact: pending (hub)run should confirm a zero change, or count the units with 64 < age < 65. - rulespec-us#1776, its labels and whether it is dispatch-ready; I can't reach that repo from this session.
- Linux CI time and memory for the new Python file. The figures in P2-1 are local.
Generated by Claude Code
|
Picking this up for the US hub. I'll post a hand-off comment here when it's ready. Generated by Claude Code |
The Python test restated the formula line it checked and only killed the np.round mutant beyond YAML; a 64.99 YAML case covers that. Add joint cases so an age test applied to the head alone fails. Note that the comparison reads age as the age at the close of the taxable year, and apply the same completed-years federal test in Maine's cohort flag so its comment holds (me_eitc unchanged: the max of federal and pro forma). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Ready for hub review Head: Merge. Fast-forwarded to Finding 1. Deleted Finding 2. Added "Joint filers aged 70 and 64.5 meet the age test through the spouse, 2024" (true, 612) and "Joint filers aged 70 and 65 don't meet the age test, 2024" (false, 0) at Finding 3.
Finding 4. Finding 5. The body now adds the NY WFTC reform line ( Tests (one file per process, at the head):
Mutants (each in its own process against the fractional-age YAML; restored after each,
CI. Pull request run 41528556634 at Judgment calls
Proposed follow-up: "Apply completed-years EITC age ceiling in state recomputations". NM, OK, DC, CO, MD, WA, IN and the NY WFTC reform recompute the federal childless ceiling with raw Generated by Claude Code |
The property test's oracle and comment still described the exact-age federal test. Its ages now reach 64.5 and 64.99, and a new YAML case fails if me_childless_eitc_age_eligible.py goes back to the exact age. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
US + core hub merge audit, us#10585 at
|
26 U.S.C. 32(c)(1)(A)(ii)(II) requires a childless filer (or either spouse) to have "attained age 25 but not attained age 65 before the close of the taxable year".
gov.irs.credits.eitc.eligibility.age.maxis 64, the highest completed age that qualifies. Buteitc_demographic_eligibletestedage <= max_age, so a filer aged 64.5, who has not attained 65, failed.Witness at main (
97b6d5135c, 2024, single, $8,000 wages): age 64.0 gives eitc 612; age 64.5 gives 0 (wrong); age 65.0 gives 0.Change
eitc_demographic_eligiblenow testsnp.floor(age) <= max_age, following #10526 for Maine. The minimum side (age >= min_age) already handles fractional ages and is unchanged. The parameter keeps its meaning; only its description was reworded ("completed age is at most this value"). The formula comment now also says it readsageas the age at the close of the taxable year, which the statute's "before the close of the taxable year" requires.me_childless_eitc_age_eligible.py:55applies the same completed-years federal test (np.floor(age) <= federal_age.max(period)), so its comment ("read as in eitc_demographic_eligible") holds.me_eitctakesmax_(eitc, me_pro_forma_childless_eitc). A Maine couple aged 23 and 64.5 with $8,000 wages in 2024 moves to the federal path: against main,eitcgoes from 0 to 612, the cohort flag from true to false and the pro forma credit from 612 to 0, andme_eitcstays 306.me_eitcmoves only whereeitcpays less than the pro forma. Withtakes_up_eitc: false,eitcstays 0 andme_eitcfalls from 306 to 0, the resultme_eitc.yamlalready pins for a federally eligible couple that doesn't take up the credit. Inputs that zeroeitcfor non-filing or a section 911 election fall the same way.Every year of
age/max.yaml:.inf(ARPA 32(n)(2)). Floor of any age is at most inf.Invariant
For each filer and a whole-number maximum m, the age test holds exactly when
min <= age < m + 1, so raising age past the ceiling never passes it again. Withm = .inf(2021) only the minimum binds. The YAML cases pin the boundary at 64.0, 64.5, 64.99 and 65.0.Tests (
eitc_demographic_eligible_fractional_age.yaml)Test counts at the head, one file per process:
eitc_demographic_eligible_fractional_age.yaml10 passed;eitc_demographic_eligible.yaml21;eitc_eligible.yaml11;earned_income_tax_credit.yaml3;me_eitc.yaml27;me_childless_eitc_age_eligible.yaml16;test_me_childless_eitc_age_gate.py3;test_me_childless_eitc_age_gate_property.py1;test_dependent_elsewhere_head_spouse_swap_invariance.py8;test_source_conflicts.py103. All passed.Mutants (one process each, code restored after each; run against
eitc_demographic_eligible_fractional_age.yaml)age <= max_age: killed, 4 failures (64.5 in 2024 and 2026, 64.99, joint 70/64.5).age < max_age: killed, 5 failures (those four plus 64.0).np.round(age) <= max_age: killed, 1 failure (64.99).Sweep
Other
variables/gov/irs/upper bounds compare raw age with a strict<against "under N" / "not attained N", which is right for fractional ages:credits/ctc/maximum/ctc_qualifying_child_ignoring_filer_identification.py:31age < age_limitcredits/cdcc/cdcc_eligible.py:36age < child_age(13)tax/federal_income/alternative_minimum_tax/kiddie_tax/amt_kiddie_tax_applies.py:44,47age < 19/24aged_head,aged_spouse,is_irs_aged, IRA and 401(k) catch-up, savers credit, elderly credit, senior deduction)age >= NNo other federal site was wrong, so
eitc_demographic_eligibleis the only federal fix.Outside
gov/irs: same pattern, likely wrong. These are recomputations of the federal childless EITC age ceiling (or state copies of it) usingage <= 64. Proposed fix:np.floor(age) <= max_age. State law wasn't read here.states/nm/tax/income/credits/eitc/nm_eitc_demographic_eligible.py:35(federal max)states/ok/tax/income/credits/eitc/federal_credit/eligible/ok_federal_eitc_demographic_eligible.py:46states/dc/tax/income/credits/eitc/dc_eitc_without_qualifying_child.py:36states/co/tax/income/credits/eitc/co_eitc.py:49states/md/tax/income/credits/eitc/federal_eitc_without_age_minimum.py(below_max_age)states/wa/tax/income/credits/wa_working_families_tax_credit.py:74andtools/state_eitc_helpers.py:60(frozen federal max)states/in/tax/income/credits/earned_income_credit/in_eitc_eligible.py:47-48(IN max 64)reforms/states/ny/wftc/ny_working_families_tax_credit.py:374((age >= min_age_student) & (age <= max_age), readinggov.irs.credits.eitc.eligibility.age.max)states/mn/tax/income/credits/mn_wfc_eligible.py:23. MN's own maximum; value and law unread, so unclear.Outside
gov/irs: unclear. These are benefit and stateage <= p.<limit>sites whose law wasn't read. Each is right if the parameter is the last qualifying completed age and the law says "N or younger" / "through age N". Each is wrong for fractional ages if the law says "under N" and the parameter is N-1 (then floor). Examples:hhs/medicaid/costs/is_medicaid_slcsp_dependent_child.py:31,aca/slspc/is_aca_family_tier_dependent_child.py:14,aca/eligibility/aca_child_index.py:12,usda/snap/income/snap_excluded_child_earner.py:18,usda/snap/eligibility/work_requirements/is_snap_abawd_exempt.py:75,hhs/medicaid/eligibility/medicaid_work_requirement_eligible.py:105, RI CTC and rebate, VT CTC, CT rebate, DC KCCATC, IN dependent exemption, OR WFHDC, IL HBI, TX FPP and others. The full list:grep -rnE "\bage\w*\s*<=" policyengine_us/variables(63 hits).Impact
impact: none at baseline. The production dataset stores whole-year ages (none of its 166,321 people has a fractional age), so no head or spouse falls strictly between 64 and 65.
axiom: TheAxiomFoundation/rulespec-us#1776 queued
🤖 Generated with Claude Code