Skip to content

Fix NY CTC surviving-spouse phase-out threshold to $75,000 (2025-2027) - #9425

Merged
DTrim99 merged 2 commits into
PolicyEngine:mainfrom
DTrim99:ny-qss-threshold
Sep 11, 2026
Merged

Fix NY CTC surviving-spouse phase-out threshold to $75,000 (2025-2027)#9425
DTrim99 merged 2 commits into
PolicyEngine:mainfrom
DTrim99:ny-qss-threshold

Conversation

@DTrim99

@DTrim99 DTrim99 commented Sep 9, 2026

Copy link
Copy Markdown
Collaborator

The 2025-2027 Empire State child credit expansion's phase-out threshold for qualified surviving spouses is $75,000, not $110,000.

The enacted S.3009-C print of Tax Law §606(c-1)(1-a)(C) reads: "(I) one hundred ten thousand dollars in the case of married taxpayers filing jointly; (II) seventy-five thousand dollars in the case of a taxpayer filing as single, head of household, or qualified surving [sic] spouse; and (III) fifty-five thousand dollars in the case of a married taxpayer filing a separate return." The 2025 IT-213 instructions confirm: "single, head of household, or qualifying surviving spouse - $75,000" (it213i.pdf).

The parameter matched the bill's original print, which grouped surviving spouses with joint filers at $110,000 (that print also had single at $55,000); the enacted C-print regrouped QSS into the $75,000 tier. Effect of the bug: surviving-spouse filers with AGI between $75k and ~$135k received too generous a credit.

Param-only fix plus the existing QSS phase-out test moved to the correct threshold ($80k AGI → $82.50 phase-out). The targeted phase-out suite passes (20/20).

Found during the Child Poverty Impact Dashboard's pre-launch state display audit.

🤖 Generated with Claude Code

https://claude.ai/code/session_014p5C4W5UC1MvusNZLuzFTf

The enacted S.3009-C print of Tax Law 606(c-1)(1-a)(C) sets the
threshold amounts at $110,000 for married filing jointly only;
$75,000 for single, head of household, OR qualified surviving spouse;
and $55,000 for married filing separately. The parameter encoded the
bill's original print, which grouped surviving spouses with joint
filers at $110,000; the enacted version moved them to the $75,000
group, as the 2025 IT-213 instructions confirm.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014p5C4W5UC1MvusNZLuzFTf
@hua7450

hua7450 commented Sep 10, 2026

Copy link
Copy Markdown
Collaborator

Program review

Base repository: PolicyEngine/policyengine-us
PR number: 9425
Reviewed head SHA: a5b3ac3
Merge base SHA: 42103db
Mode: full
Scope: changed behavior and affected dependencies
Source manifest: /private/tmp/policyengine-command-runs/4e6d8e5f7d3e/pr-9425-review-sources.json
Review status: COMPLETE

Source Documents

Critical

None.

Should Address

A1 — Phase-out rounds partial $1,000 increments UP; Form IT-213 and the statute round DOWN (unchanged code, reachable through this parameter) — SHOULD ADDRESS (OPEN)

  • File: policyengine_us/variables/gov/states/ny/tax/income/credits/ctc/ny_ctc_post_2024_phase_out.py:22–26 (excess_increments = (excess_income + increment - 1) // increment, comment "Round up to nearest increment").
  • Trigger: TY2025, NY, filing_status SURVIVING_SPOUSE (any status behaves the same), one qualifying child age 2, federal AGI $80,999.
  • Expected: Form IT-213 (2025) line 6 "Enter your federal adjusted gross income rounded down to the nearest $1,000" → $80,000; line 7 = $80,000 − $75,000 = $5,000; line 8 = ×1.65% = $82.50 phase-out; credit $917.50. IT-213-I line 6 instruction: "Round down the amount from Form IT-201, line 19 to the nearest $1,000 … For example, decrease $35,999 to $35,000." Statute §606(c-1)(1-a)(C) says "for each one thousand dollars by which … exceeds" with no "or fraction thereof" (contrast IRC §24(b)(1)), consistent with the form.
  • Observed (code trace): excess $5,999 → (5,999 + 999) // 1,000 = 6 increments → $99.00 phase-out; credit $901.00.
  • Impact: every post-2024 filer in the phase-out range whose FAGI is not an exact multiple of $1,000 above the threshold loses up to $16.50 of credit; at the top of the range the credit is zeroed one increment early. Not introduced by this diff (pre-existing formula), and the moved test does not codify it (exact multiple). Severity per rubric: rounding defect with bounded (≤ $16.50) per-unit impact and no eligibility change → SHOULD ADDRESS. Evidence: pr-9425-sources/it213_fill_in.txt lines 25–34; it213i.txt line 13; assembly extract printed p.18 lines 34–43.
  • Fix shape (untested suggestion): excess_increments = excess_income // increment (or floor FAGI to $1,000 before subtracting, which is equivalent because all thresholds are $1,000 multiples), plus one test at a non-round AGI.

Coordinator assessment: Coordinator note: pre-existing formula defect in ny_ctc_post_2024_phase_out.py:24, not introduced by this PR; the moved QSS test sits on an exact $1,000 multiple so it neither codifies nor exercises it. The code reviewer's boundary diagnostic (75,001 → $16.50) is the same behavior observed at runtime. Fix belongs in a follow-up or, if the author prefers, this PR (excess_income // increment + one non-round AGI test).

A2 — SHOULD ADDRESS: no QSS boundary or end-to-end ny_ctc coverage for the corrected tier (OPEN)

  • Location: policyengine_us/tests/policy/baseline/gov/states/ny/tax/income/credits/ny_ctc_post_2024_phase_out.yaml:171-190 (only QSS case); ny_ctc.yaml and ny_ctc_post_2024.yaml have SINGLE/JOINT 2025 cases only.
  • Trigger: QSS filer, 2025, AGI exactly $75,000 / $75,001; and any QSS case asserting the final ny_ctc.
  • Expected vs observed: the existing SINGLE cases cover the exact-threshold edge (75,000 → 0; 75,999 → 16.5) and ny_ctc: 917.5 at 80k, but for SURVIVING_SPOUSE the suite asserts only the intermediate ny_ctc_post_2024_phase_out at one point ($80k). Because the whole point of the PR is that QSS now shares the SINGLE tier rather than JOINT, a QSS case at exactly $75,000 (→ 0) and $75,001 (→ 16.5) plus one ny_ctc assertion (80k → 917.5) would pin the corrected tier against a future regression (e.g. a re-grouping of QSS back to 110k would still pass the current test only if AGI were ≤ 110k … it would in fact fail at 80k, so the risk is limited to the boundary itself). 2028 sunset is covered for SINGLE only (SURVIVING_SPOUSE 2028 value is 0 like the other tiers; diagnostic confirms 2028 QSS phase_out = 0).
  • Evidence: diagnostic run (exploratory, not a test assertion) at /tmp/policyengine-command-runs/4e6d8e5f7d3e/pr-9425-review-code-diag.log, script .../scratchpad/qss_diag.py, QSS derived from is_surviving_spouse: true + age-2 child, NY, adjusted_gross_income input:
    • 2025 AGI 75,000 → phase_out 0.00, ny_ctc 1,000.00, ny_refundable_credits 1,000.00
    • 2025 AGI 75,001 → 16.50 / 983.50 / 983.50
    • 2025 AGI 76,000 → 16.50 / 983.50 / 983.50
    • 2025 AGI 80,000 → 82.50 / 917.50 / 917.50
    • 2028 AGI 80,000 → 0.00 (post-2024 rules off; ny_ctc 247.50 comes from the pre-2024 33%-of-federal path, not in scope)
      All values match the hand derivation above; no defect. Missing coverage is not evidence of incorrect behavior — severity SHOULD ADDRESS per rubric. Suggested addition (append at end of the phase-out file, and one case in ny_ctc.yaml): QSS at 75_000 → 0, 75_001 → 16.5; QSS 80_000 → ny_ctc: 917.5.
  • Why this diff: the PR changes which tier QSS uses; the boundary of that tier is the changed behavior.

Suggestions

S1 — IT-201-I reference page does not contain the cited values — SUGGESTION (OPEN)

  • File: threshold.yaml:32–33 (2025 Form IT-201-I Instructions, it201i.pdf#page=26); the same href appears in the untouched sibling files rate.yaml, increment.yaml (#page=26) and amount.yaml, in_effect.yaml (#page=25).
  • Observed: the PDF currently at that URL is IT-201-I (2025); physical page 26 is "Exemption types by code" and page 25 ends at "Line 84". The Empire State child credit instruction (Line 63) is on physical page 19 and only refers the reader to Form IT-213; no threshold amounts appear anywhere in IT-201-I.
  • Suggest citing the document that actually states the tiers: https://www.tax.ny.gov/pdf/current_forms/it/it213i.pdf (2 pages; tiers on page 1 — use #page=1 or no fragment) and/or Form IT-213 line 7, and dropping or re-paging the IT-201-I entry. Note current_forms URLs are overwritten each filing season; an archived-year URL would be more stable. Documentation only; no behavior impact.

S2 — Reference title embeds dollar amounts — SUGGESTION (optional) (OPEN)

  • File: threshold.yaml:30. The reworded title is accurate today but hard-codes "$110,000 joint; $75,000 …; $55,000 separate" in a title that propagates to all five filing-status children; if any tier is later amended the title goes stale. Skill convention is the section path in the title (New York Senate Bill S.3009-C (Chapter 59 of 2025), Part C § 2, Tax Law § 606(c-1)(1-a)(C)), with values living in values. Optional.

Coordinator assessment: Code reviewer (code-2) raised the same point independently and adds that sibling files phase_out/rate.yaml and phase_out/increment.yaml still carry the older "Part C, Section 2, …" title, so the titles are now inconsistent across the phase_out folder. Deduplicated here.

Evidence Gaps

No material gaps reported.

Notes

  • Changed value verified: $75,000 for qualified surviving spouse (TY2025–2027) matches enacted S.3009-C (Chapter 59 of 2025) §606(c-1)(1-a)(C), the 2025 IT-213 instructions (page 1) and Form IT-213 line 7; sibling tiers ($110k joint, $75k single/HoH, $55k separate) and the 2025-01-01/2028-01-01 keys also match the statute. The PR body's print-history account (original print grouped QSS at $110k) is corroborated by the original-print text.
  • Code path verified: threshold[filing_status] is indexed by the tax unit's own FilingStatus enum (no JOINT remap); the moved test at $80k AGI derives to $82.50 from both the statute steps and the code; final ny_ctc for a 2025 QSS filer at $80k is $917.50 (diagnostic), so the fix reaches the household outcome. The old expectation (115k) would fail under the fix, so the moved test genuinely exercises the corrected tier.
  • No partner contract test or other baseline test pins a NY surviving-spouse CTC case; no contrib reform reads this parameter. No partner-facing change.
  • Non-material evidence limitation: consolidated Tax Law §606 on nysenate.gov returned a 403 bot challenge on both routes, so a post-Chapter-59 amendment for TY2026–2027 was not ruled out from the consolidated text; the enacted bill text (two hosts) and the Department's 2025 form/instructions establish the reviewed value.
  • Interpretation of the argument local: treated as --local (display only). PR identity taken from the checkout branch pr/DTrim99/9425.
  • Timing: the code role's single 540-second bounded test invocation covered a directory-wide selection and timed out after the changed files had fully passed; 70 collected cases in unrelated NY CTC files were NOT RUN locally and rely on green CI at the same SHA.

Validation Summary

Local tests (snapshot at a5b3ac3, one bounded invocation, log pr-9425-review-tests.log): 46 passed, 0 failed, 70 NOT RUN (540s bound reached). Changed file ny_ctc_post_2024_phase_out.yaml 20/20 passed; ny_ctc_post_2024.yaml 10/10 passed; ny_ctc.yaml 16 passed before the bound. QSS end-to-end diagnostic (exploratory, log pr-9425-review-code-diag.log): 75,000 → $0 / 75,001 → $16.50 / 80,000 → $82.50 phase-out, ny_ctc $917.50. Remote CI at a5b3ac3: all 31 checks pass (incl. Household API Partners, Lint, changelog). Sources: 8 fetch attempts over 7 URLs, 6 originals registered and checksum-validated (check_source_manifest: 6 validated / 0 rejected), 1 URL unobtainable (nysenate TAX/606, 403 both routes), 0 page renders (text layers unambiguous). Agents: 2 review-worker roles, no adjudication. Snapshot worktree removed after role completion.

Timing

setup seconds: 48.00s; scope seconds: 60.00s; parallel review seconds: 744.00s; policy role seconds: 316.00s; code role seconds: 721.00s; adjudication seconds: 0.00s; consolidation cleanup seconds: 58.00s; elapsed seconds: 885.00s

Review Severity

COMMENT. Open findings: 0 critical, 2 should address, 2 suggestions.

@hua7450 hua7450 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved — review-program: COMPLETE, 0 critical. The $75,000 surviving-spouse tier is confirmed against the enacted S.3009-C print and 2025 IT-213; code path and moved test verified. Remaining should-address items (pre-existing round-up in the phase-out formula, QSS boundary coverage) are non-blocking and noted in the review comment above.

…QSS tests

Rounds partial $1,000 phase-out increments down per Form IT-213 line 6,
repoints IT-201-I references to the IT-213-I instructions across the
post-2024 CTC parameters, uses section-path reference titles, and adds
QSS boundary, round-down, and end-to-end test cases.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LqCGPgxDukji8Bhs57c5rH
@DTrim99

DTrim99 commented Sep 10, 2026

Copy link
Copy Markdown
Collaborator Author

Fixes applied from @hua7450's review

  • A1 — round-down fix: Partial $1,000 phase-out increments are now rounded down per Form IT-213 line 6. Verified against IT-213-I page 1 ("round down to the nearest $1,000").
  • A2 — tests added: Added phase-out boundary and round-down cases (75,000 → 0; 75,001 → 0; 76,000 → 16.50; 80,999 → 82.50) and an end-to-end case (80,000 → $917.50). Note: the review's suggested 75,001 → 16.50 expectation is inconsistent with round-down (75,001 rounds down to 75,000 = 0 increments), so the first-increment assertion was placed at 76,000 instead.
  • S1 — references repointed: IT-201-I references replaced with IT-213-I across the threshold, rate, increment, amount, and in_effect parameters.
  • S2 — reference titles: Now use section-path titles.

Tests: 101 passing across the six affected NY CTC files.

@codecov

codecov Bot commented Sep 10, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (f9b5549) to head (7dbccab).
⚠️ Report is 55 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff            @@
##              main     #9425   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files            2         1    -1     
  Lines           20        24    +4     
=========================================
+ Hits            20        24    +4     
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.

@DTrim99
DTrim99 merged commit d8f06f3 into PolicyEngine:main Sep 11, 2026
33 checks passed
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