Repository navigation
Validation: baseline comparisons for the programs the reform changes - #1274
Merged
Merged
Conversation
Baseline comparisons listed every scorecard claim whose program variable the reform reached within six formula steps, so a CDCC change (report 4332) also showed the refundable CTC, the saver's credit and the Maryland and South Carolina EITCs. A comparison now shows only when it measures a program the reform changes (named in a changed parameter's path, or in a variable that reads that parameter directly) and only in the report's jurisdiction: a nationwide report keeps national comparisons and a state's only when the reform changes that state's rules; a state report keeps that state's and the national ones. When none applies, one plain line says so. The rule is one pure function, relevantComparisons. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every baseline row read "Period not recorded separately" under the PolicyEngine value, and claims without a time basis read "time basis not recorded". A period now shows only when the scorecard records it; an unknown one leaves the cell with just its value. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Only the card header linked to the scorecard, and it opened the comparison table, while most baseline claims are listed in the scorecard's claims registry. Each row now links to the view that lists it: published claims to ?view=validation (with &country= outside the US), comparison-table rows to ?view=scorecard. The scorecard's URL has no address for a single entry, so this is the closest link it supports. The Treasury source also reads by name. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
The data calibration card listed every target whose variables the reform reached within six formula steps, so a CDCC change (report 4332) showed the CTC and refundable CTC targets. Calibration matches now pass the same relevantComparisons rule as baseline comparisons: a target counts when the model variables it measures are a program the reform changes, in the report's geography. A match left with no target drops, and an empty card says so in one line. Names now compare without the words that only qualify a program (refundable, enrolled, eligible, the tax_unit entity) on both sides, so medicaid_enrolled is Medicaid and income_tax stays income tax rather than any path with "income" in it. ACA, education credit and LIHEAP targets get aliases to the names their parameters use. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Target column showed dashboard ids such as
"irs_soi.ty2022.historic_table_2.us.all.ctc_amount@2024", and groups
read as raw variable names ("Ctc limiting tax liability"). A target now
reads as the quantity it measures and the slice of its table ("Amount",
"Claims", "Returns · 18k to 19k · no qualifying children"); the id stays
as the button's tooltip and as "Target id" in its details. A group reads
as our copy, else the model's own variable label, else its name in words
with acronyms ("CTC limiting tax liability"). The calibration route now
passes the dashboard's measure id and breakdown for this.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… changes The scorecard track record kept every program whose comparison rows were computed from a reached variable, so the validation pin and the run's "scorecard programs found" stage counted programs the change only echoes into (an EITC reform also pinned the refundable CTC). The track record now applies relevantComparisons at its source, so the pin, the stages and the baseline card agree. Its rows are all national, so the report's region does not narrow them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 14, 2026
This was referenced Oct 15, 2026
anth-volk
added a commit
that referenced
this pull request
Oct 15, 2026
…audit and report re-runs Brought over from main: the v3 audit fixes (#1273, #1274, #1277, #1278, #1280, #1281, #1283, #1284, #1285), run progress from the API, a report that opens from its stored output and records a failed run, a wait for the reform policy, the report year switcher and All years view (#1292), dated edits in the adjust panel (#1294), each country's own draft, and Your reforms' read-only reform detail with a parameters table, "View results", "Re-run" and the delete prompt (#1288), with the other merged fixes (#1289, #1290, #1293, #1295, #1296). How the conflicts were resolved: - Report page: a link is still a saved report's ID, read through the credential-free shared-report route, with the v1 report's number only without accounts. The v1 report it names (the shared row's legacy_report_id) gets main's run lifecycle: stored output, recorded failures, the household guard, the wait for the reform policy (for any link that resolved), the unknown-baseline state and the year switcher. - Reforms page and ReformReports: main's read-only detail, parameters table, delete prompt, View results and Re-run, on this session's stores and session-scoped query keys. "View results", "Open" and "View full impact report" go to reportLink(report), never the v1 report's number. The detail keeps this branch's guards: a reform whose changes did not load cannot run and says so, a reform that changes nothing cannot run, and the run sends what Build would. A record without a year reads it from the API's record. - Build's run bar: still "Save and run", which saves first and runs nothing when the save fails; it now saves only the values that differ from current law, leaves a reused reform (and its name) as it is, and names a budget window's years. A new reform has nothing to save when nothing differs. - Adjust panel: main's dated edits, budget window and unknown-baseline guard on this session's reform store; recompute still waits until a value differs from current law. - draftReform: loadProvisionsIntoDraft takes both the saved reform it edits and main's window and source. - Tests: main's run-hook tests sit beside this branch's store tests; the run bar test that ran a report after a failed save is dropped, as a failed save runs nothing here. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This branch was successfully deployed
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.
Summary
The "Baseline comparisons" card in the v3 report validation listed comparisons the reform does not change, every row read "Period not recorded separately", and no row linked to its own place on the scorecard.
Report 4332 shows the problem. It is a nationwide 2026 report with one change:
gov.irs.credits.cdcc.eligibility.max(the CDCC's cap on qualifying people) goes from 2 to 4. The card listed six rows: the refundable CTC, two CDCC rows, the Maryland EITC, the saver's credit and the South Carolina EITC. All six matched only because their program variable is somewhere among the 216 variables the reform reaches within six formula steps. For example,sc_eitcis reached throughsc_cdccandmd_eitcthroughmd_agi. With this PR, the card shows only the two national CDCC rows (US Treasury and IRS SOI).What changed
Only the programs the reform changes (
libs/flagship/comparisonRelevance.ts, a pure functionrelevantComparisons). A comparison counts when its program is named in a changed parameter's path or in a variable that reads that parameter directly. The direct readers come from the existingparameterDependenciesmap. The last path segment is ignored because it names a setting, not a program (…min_children_for_ss_taxes_minus_eitcis a CTC rule). Qualifiers likerefundable/nonare dropped, sorefundable_ctcandnon_refundable_ctcboth count as the CTC. A short alias table covers scorecard ids that are not model names (co_fac,wa_wftc,wi_eic, …). City and territory parameters match no federal or state program.Jurisdiction. A nationwide report keeps national comparisons, plus a state's comparisons only when the reform changes that state's own rules (for example a DC SNAP minimum shows DC SNAP rows). A state or congressional-district report keeps that state's comparisons and the national comparisons of the federal programs the reform changes. Other states never show.
Empty case. When nothing applies, the card shows one line: "No scorecard comparison measures the programs this reform changes." Loose matches no longer appear as rows.
Per-row scorecard links. Each row now has a "View in scorecard" link to the scorecard view that lists the entry:
https://www.policyengine.org/scorecard?view=validation. Outside the US, the link adds&country=xx.?view=scorecard.The scorecard's URL state carries only
viewandcountry(seeapp/src/urlState.tsin policyengine-scorecard). It has no address for a single entry, so this is the closest link it supports.Periods. A period shows only when the scorecard records it. "Period not recorded separately" and "time basis not recorded" are gone.
ReportValidationtakes the report'sregion, whichReportViewalready has.Data calibration uses the same rule. A calibration target counts when the model variables it measures (
policyengine_variables) are a program the reform changes, in the report's geography. A group with no target left drops out. An empty card shows one line: "No calibration target measures the programs this reform changes." For report 4332, the CTC and refundable CTC targets drop, so the card shows that line.Calibration targets read by name. The Target column showed raw dashboard ids, such as
irs_soi.ty2022.historic_table_2.us.all.ctc_amount@2024./api/calibration-targetsnow also passes the dashboard'ssource_measure_idandbreakdown.Name matching. Both sides of a match now drop words that only qualify a program (refundable, enrolled, eligible, the
tax_unitentity). Somedicaid_enrolledcounts as Medicaid.income_taxmatches only income tax, not any path that contains "income". Aliases cover the ACA, education credit and LIHEAP targets.Validation pin and run stages. The scorecard track record now applies the rule at its source. The pin (
trackRecordPrograms), the "scorecard programs found" stage and the baseline card now use the same programs.v2 impact
None. Every changed file is under
components/flagship,libs/flagshipor their tests, and only the v3 report and bill-report pages import them. The only API change adds two fields to the v3/api/calibration-targetsresponse.Tests
comparisonRelevance.test.tscovers these cases:ValidationPanel.test.tsxandReportValidation.test.tsxrender a 4332-like fixture (the six real claims and the traced readers of the CDCC path). They check that only the two CDCC rows show, that each links to?view=validation, that no "not recorded" text shows, and that unrelated claims give the one-line empty state.ScorecardComparisons.test.tsxchecks the per-row links (US, UK, comparison table) and that periods show only when recorded.modelValidation.test.tschecksscorecardEntryUrl.calibrationMatching.test.tscovers these cases:CalibrationMatches.test.tsxchecks the one-line empty state, the readable target names with the raw id as the tooltip and in the details, and the group heading for a raw variable name.modelValidation.test.tschecks that an EITC reform's track record no longer includes the refundable CTC.app/:bun run typecheckpasses.eslint --max-warnings 0andprettier --checkpass on the changed files.bun run vitestpasses: 424 files, 4863 tests, 10 skipped.Base branch
This PR targets
fix/v3-overlaps(#1273), the top of the open stack of validation PRs. Retarget it tomainafter #1273 merges.🤖 Generated with Claude Code