Skip to content

Score OBBBA reform validation stacked (match JCT) - #185

Merged
PavelMakarchuk merged 1 commit into
mainfrom
obbba-stacked-scoring
Jun 25, 2026
Merged

Score OBBBA reform validation stacked (match JCT)#185
PavelMakarchuk merged 1 commit into
mainfrom
obbba-stacked-scoring

Conversation

@PavelMakarchuk

Copy link
Copy Markdown
Contributor

Problem

The reform-validation page showed populace far off JCT on the OBBBA provisions — and the divergence was worst exactly on the provisions that interact most (standard deduction, personal-exemption termination). Root cause: each provision was scored standalone, against a baseline where every other OBBBA provision is reverted, then just that one added back. So each line was measured "as if it were the only provision in the bill."

JCT's JCX-35-25 lines instead stack — each is the incremental effect given the lines above it — so they sum to the bill total. Comparing standalone lines to stacked lines is apples-to-oranges.

The diagnostic on the released populace_us_2024.h5 made it unambiguous:

income-tax effect, 2026
populace true total (full OBBBA vs pre-OBBBA) −351B
JCT (sum of JCX lines) −321B
sum of populace standalone per-line effects −222B

The model's aggregate is within ~9% of JCT — but the standalone lines don't even sum to populace's own total (−222B vs −351B), because interactions are mis-attributed. The worst case: standalone personal-exemption repeal +228B vs JCT +110B, because measured alone it ignores the bill's standard-deduction increase that absorbs much of that revenue.

Fix

stacked_obbba_effects() enacts the provisions one at a time in JCX order on the pre-OBBBA baseline and scores each as the incremental change. The per-line effects now telescope to the true total, and align far better with JCT per line (verified — standard deduction −167B→−131B vs JCT −92B; personal exemption +228B→+149B vs +110B; QBI −53B→−48B vs −44B). Falls back to isolated scoring only if the OBBBA group spans multiple measures/periods.

Tests

test_obbba_components_score_stacked_in_jcx_order checks that the second provision is scored against the post-first-provision state (not pre-OBBBA) and that the line effects telescope to the total.

The released release's dashboard data is being refreshed with the stacked numbers separately (committed override in calibration-diagnostics).

🤖 Generated with Claude Code

Each OBBBA provision was scored standalone — against a baseline where
every other OBBBA provision is reverted — so each was measured as if it
were the only provision in the bill. JCT's JCX-35-25 lines instead stack
(each incremental given the lines above it), so they sum to the bill
total. Comparing standalone lines to stacked lines is apples-to-oranges
and badly overstated the interacting provisions (e.g. standalone
personal-exemption repeal +228B vs JCT +110B, because it ignored the
bill's standard-deduction increase that absorbs that revenue).

Score the provisions cumulatively in JCX order instead: enact them one
at a time on the pre-OBBBA baseline and take each line's incremental
effect. The per-line effects now telescope to the true total OBBBA
effect and align far better with JCT per line. Falls back to isolated
scoring only if the OBBBA group spans multiple measures/periods.

Verified on the released populace_us_2024.h5: aggregate OBBBA effect
(~-351B) already matched JCT's total (~-321B) within ~9%; this fixes the
per-line attribution.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@PavelMakarchuk
PavelMakarchuk merged commit 03daf42 into main Jun 25, 2026
4 checks passed
@PavelMakarchuk
PavelMakarchuk deleted the obbba-stacked-scoring branch June 25, 2026 21:04
PavelMakarchuk added a commit that referenced this pull request Jul 1, 2026
…ding stacking (#246)

The estate exemption is scored on estate_tax (#182) — estate tax is not
a component of income_tax, so measuring it on income_tax is a structural
zero. But stacked_obbba_effects required a single (budget_measure,
period) across ALL provisions and otherwise fell back to isolated
scoring for everything — so since #185 landed on top of #182, a real
build would silently not stack at all.

Stack per (measure, period) group instead: the income-tax provisions
keep their JCX-order cumulative stack, the estate provision scores
within its own group (single member = enacted alone), and the shared
pre-OBBBA baseline still merges every revert so each group is scored in
whole-bill context. Cross-group interactions are nil by construction
since the measures are disjoint taxes. Removes the now-dead isolated
fallback, documents the estate survey-data caveat, and adds a
mixed-measure regression test that would KeyError on any isolated
fallback.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
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