PolicyEngine / PolicyEngine/calibration-diagnostics

Expand JCT target coverage: JCX-45-25 vintage + RCC-relevant lines (CTC/EITC/CDCC/ALD/OBBBA)

Open
#33 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
0
Forks
4
Avg merge
1d 9h
Merged PRs (30d)
13

Description

Context

We just finished a scoring validation pass on the 9 refundable-credit-conversion repeal toggles (CTC, EITC, CDCC, standard deduction, itemized, ALD, OBBBA bundle, §199A QBI, head-of-household) against JCT JCX-45-25 and JCX-22-25R. We pulled the populace-us release on Hugging Face (populace-us-2024-f0d2ef6-09292aa0d5db-20260617T032307Z) hoping the target surface could anchor the validation, and ran into two issues worth raising here.

What the target surface covers today

Family n targets Vintage Lines
jct 5 JCX-48-24 (CY2024) SALT, mortgage interest, charitable, medical, §199A QBI
irs_soi 4,748 TY2020/2022 Income components, EITC/CTC/ACTC/QBI deduction lines, filing-status slices
cbo 5 Feb 2026 AGI projections by source
state_income_tax, ssa, cms_*, tanf, snap 339 various not RCC-relevant

Issue 1 — JCT family uses JCX-48-24, not JCX-45-25

The latest JCT tax-expenditure document is JCX-45-25 (Estimates of Federal Tax Expenditures for Fiscal Years 2025-2029, Dec 2025). The repo's jct family still anchors on the earlier JCX-48-24 at CY2024. The two disagree on every line (different fiscal-year window, post-OBBBA mortgage interest is $53.0B in JCX-45-25 vs $24.8B in JCX-48-24, etc.), and downstream consumers validating against the newer vintage end up double-checking which JCT cell they're matching against.

Proposal: load JCX-45-25 alongside JCX-48-24 (or replace it). FY2026 and FY2027 are the cells we need most for OBBBA-era scoring.

Issue 2 — Five-line jct family is too narrow for tax-expenditure validation

Today the JCT family covers SALT, mortgage interest, charitable, medical, and §199A. For RCC validation we hit gaps on:

Toggle Why no benchmark
CTC no CTC/ACTC line in jct family
EITC no EITC line in jct family
CDCC no §21 / §129 line
Standard deduction JCT excludes from tax-expenditure framing
ALD (above-the-line) no traditional IRA, HSA, student loan, SE-health, SE-pension, educator
OBBBA bundle no tip exclusion, overtime exclusion, senior bonus, SALT cap raise

Proposal: add JCT tax-expenditure lines for at least the refundable credits (CTC/ACTC, EITC, CDCC) and above-the-line deductions JCT does score (traditional IRA, SE-pension, SE-health, HSA, SLID, educator). For OBBBA, the natural source is JCX-22-25R (Estimated Revenue Effects of the OBBBA) — that's the document we used in PR #48.

Issue 3 — Residuals on the 5 JCT lines we do have are eye-catching

name target final_estimate relative_error
jct...salt_deduction.revenue_loss $21.7B $5.9B -72.7%
jct...medical_expense_deduction.revenue_loss $11.4B $0.6B -94.8%
jct...charitable_deduction.revenue_loss $60.4B $32.5B -46.1%
jct...deductible_mortgage_interest.revenue_loss $24.8B $11.4B -54.1%
jct...qualified_business_income_deduction.revenue_loss $63.1B $11.8B -81.2%

(Aggregate fit is 94.65% within 10%, so these tax-expenditure lines are sitting in the long tail.) Interestingly the toggle revenue impact in PE-US comes out reasonably close to JCX-45-25 on these (e.g. QBI -19%), suggesting microsim formulas are compensating for the under-represented base. Worth a separate look at whether these targets are getting enough calibration pressure.

What this would enable

With JCX-45-25 + CTC/EITC/CDCC/ALD/OBBBA lines loaded, the surface becomes a one-stop validation source for the RCC project (and any subsequent reform-modeling work scoring against JCT). Today we hand-transcribe ~25 JCT cells per validation run; tomorrow we could join PE-US output against a single JSON.

Cross-reference

  • PolicyEngine/refundable-credit-conversion#48 — the validation effort that surfaced these gaps
  • scripts/scoring_validation/comparison.csv (in that PR) — column populace_calibration_residual now reports the 5 existing JCT residuals plus SOI residuals for CTC/EITC/QBI
  • scripts/scoring_validation/pull_calibration_residuals.py — pulls the residuals from this surface

Happy to write up the JCX-45-25 table parsing if it helps.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with scripts/scoring_validation/pull_calibration_residuals.py and scripts/scoring_validation/comparison.csv, then review the existing jct target surface against PR #48 and the JCX documents named here. Add JCX-45-25 coverage and the proposed CTC/ACTC, EITC, CDCC, above-the-line, and OBBBA lines, preserving or intentionally replacing JCX-48-24. Done means the targets are available in one JSON surface and residual comparisons no longer require hand-transcription.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
data, testing-qa
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.