Repository navigation
Estimate society-wide run time by region - #1257
Merged
Merged
Conversation
The progress bar divided elapsed time by 6 minutes for every society-wide run. Production runs between 6 and 13 October 2026 took about 64 s (UK nationwide) and 130 s (US state) on average, so their bar showed about 35% when the result arrived. Durations now come from the report's country and region: UK 110 s, US state 190 s, US congressional district 200 s, and US nationwide 6 minutes (unchanged). The strategy returns the estimate on pending statuses, and the synthetic bar uses it without restarting. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Every v3 report, custom or bill, now opens Validation on three cards: external estimates (the bill's fiscal note, or related published scores, or one line that none exists), data calibration (official totals against PolicyEngine in one aligned table), and baseline comparisons (the scorecard's published measures). Numbers are right-aligned in tabular figures; each row opens its details. The fiscal-note range chip stays in Validation. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
External scores and the scorecard's published measures assume current law. A report compared with another policy now marks both scorecard cards "Not comparable", names what it compares with, and does not ask the scorecard. Data calibration still shows. Reports on current law are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
One small mapping in libs/flagship/billTracker.ts mirrors the bill
tracker: its place names ("Federal"), its bill-number fallback for a
row with no title, its join of research rows to processed_bills
(title number first, then the id; spacing and leading zeros ignored),
and its page for each bill. The feed now carries that page as
trackerUrl, and reads netCost where a row stores no revenue change,
as the tracker does. The stage stays the tracker's own word.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The overview lead links to the bill's page in the bill tracker, beside the bill text. The report URL stays keyed by the tracker's bill id; an upper-case or encoded id opens the same report, and a bill not in the feed links to that bill in the tracker. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
US reforms show a "Bill tracker" button beside "New reform" that opens the tracker's home in a new tab. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The region estimate and the 110 s UK value applied to every society-wide run, so legacy v2 loading bars filled against new durations. The country estimates are back as on main (UK 3 minutes, US 6 minutes), and getDurationForCountry, getDurationForCalcType and the strategy's default output match main again. The region estimate is now opt-in: CalcParams.estimateByRegion (passed through CalcStartConfig and the orchestrator) makes the strategy use getDurationForRegion and return estimatedDurationMs. Only the flagship report run and useBillEconomy set it. The UK region value is a new constant that only getDurationForRegion uses. Also: getDurationForRegion classifies legacy US codes (ca, us-ca, CA-12) through normalizeRegionCode, and useSyntheticProgress syncs the estimate ref in an effect instead of during render. Tests: the default strategy output for UK and US state/district runs keeps 3 and 6 minutes with no estimate attached; the opt-in path per region; the orchestrator leaves params unchanged by default; the status hooks pass the estimate to useSyntheticProgress (the aggregate uses the longest pending one); the v3 callers opt in. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
EmptyState, ErrorState and skeleton placeholders under components/flagship/states, so every v3 surface waits, says "none yet" and fails the same way. ErrorState keeps its retry button busy while a refetch is in flight, so a second click does not stack requests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
While the parameter index loads, placeholders in the shape of the search bar (or of the draft's table) hold its place. If the model's metadata fails, Build says so and asks for it again instead of loading for good. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bills and saved reforms load as placeholder cards in the grid's own tracks. A failed feed or store says so with Try again. No saved reforms offers Build; a search that hides every card offers to clear it, and "No bills match." with "Clear filters" uses the bill feed's wording. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A link that names no report says "Report not found" at once, without retries. A report, simulation or policy that fails to load shows "Could not load the report" with Try again, which asks only for what failed. Until the run starts, a placeholder holds the run card's place. The calculation error now uses the shared ErrorState. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The window card and the overview's summary both say the window could not be calculated, with Try again. The summary drops its progress link while the window has failed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
While the feed loads, a placeholder in the report's shape holds the page. A failed feed says so with Try again; a bill the feed does not carry, or a deployment with no feed, says so with the next step. When the model's metadata fails, the full results say so and ask for it again; a failed full run uses the same error state. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A policy that fails to load only costs the provision detail, so the report keeps showing its run instead of the load error. Try again still asks for it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On a phone the top bar keeps the brand, the draft count and one menu that holds both sections and the website links. The shell's padding is 16px, its height follows the visible screen, and buttons, inputs, selects, tabs, picker buttons and segmented options are at least 40px tall. The side panel plane moves under the content. Wider screens keep today's bar and sizes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Folded, the adjust panel is a bar across the bottom that names it and its count. Open, it fills the screen, and Escape folds it back. Its remove buttons are a fingertip wide. Tablets and desktops keep the spine and the column. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On a narrow table each row puts its new value on a line under the name, with the row's buttons beside it. A breakdown's names wrap and its boxes narrow, the ways to set a value scroll sideways, the add bar asks without the example, and the pickers and popovers fit the screen with fingertip-tall choices. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The tabs keep one line, the place filter and search take their own line under them, and the cards never outgrow the screen. Inputs are 16px on a phone so the browser does not zoom in to type. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Drop this PR's processed_bills join from billFeed; #1264 owns it (processedBillFor), so a bill gets one stage. Titles now come from the research select, which keeps the edits clear of #1264's lines. - Split the tracker links into BillTrackerLink and TrackerHomeButton, so each import sorts away from #1264's and #1252's import edits. - Economic impacts and the validation drift check read netCost when no stateRevenueImpact is stored, as the headline and the tracker do. - The Reforms header wraps on a narrow screen, so "New reform" shows. - trackerPlace falls back to the upper-case code. - Feed and report test data moves into fixtures. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A report or bill feed refetch that fails after the data is in no longer counts as a failed load: the report keeps its run card (not "Could not load the report" or "Report not found"), and the bill grid shows no error above its bills. The run card and its placeholder are each the one live status on the report wait. When metadata fails, the report overview says "Could not load the parameters" with Try again, the same title Build and the bill report now use. Build's table placeholder draws a row per group, as the table does, so breakdown members no longer make it shrink on arrival. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The shell also hosts the legacy v2 pages while the flag is on. Those now keep the classes they had before the phone work (h-screen, 24px padding, no touch-target rule), and only Build, Reforms, a report and a bill report get the phone layout. A test covers both sets of routes. On a phone the open side panel is a modal dialog with a close icon, and the page and top bar under it are inert. A test shows that Escape closes a picker inside the drawer and leaves the drawer open. The state filter's choices and the year list are a fingertip tall, and the filter's search is 16px. The policy tree starts under its close button. The width mock reads em and rem, and throws on a width query it cannot read. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # app/src/components/flagship/report/ReportView.tsx # app/src/tests/unit/components/flagship/report/ReportView.test.tsx # app/src/tests/unit/pages/flagship/Report.test.tsx
ReportValidation now marks external estimates "Not comparable" for a custom baseline, and its own tests cover that case. The note these two tests looked for is gone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # app/src/pages/flagship/BillReport.page.tsx # app/src/pages/flagship/Reforms.page.tsx # app/src/pages/flagship/Report.page.tsx
# Conflicts: # app/src/components/flagship/reform/DraftTable.tsx # app/src/pages/flagship/Reforms.page.tsx
# Conflicts: # app/src/pages/flagship/BillReport.page.tsx
BillReportStatus takes an optional tracker URL and shows it beside "All bills" for a bill the feed does not carry. The bill report passes the tracker page for the bill's id. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
billPlace now calls trackerPlace, so the card and the feed's jurisdiction name a bill's place by one rule. The Reforms search reads the place once, not as both billPlace and the jurisdiction. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # app/src/tests/unit/pages/flagship/Report.test.tsx
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.
The society-wide progress bar divides elapsed time by a fixed duration. While a run is pending, the visible bar (
useSyntheticProgress) uses 6 minutes for every run, UK included;SocietyWideCalcStrategyuses 6 minutes for the US and 3 for the UK. Production runs between 6 and 13 October 2026 were much shorter for UK and US state reports, so their bar showed about 35% when the result arrived.This PR lets app v3 estimate the duration from the report's country and region. Legacy v2 does not change.
v2 impact: none
The region estimate is opt-in. Without it, durations, progress and
CalcStatusobjects are the same as onmain:getDurationForCountry,getDurationForCalcTypeandUK_SOCIETY_WIDE_DURATION_MS(3 minutes) are as onmain.SocietyWideCalcStrategyby default uses the country estimate (UK 3 minutes, US 6 minutes) and sets noestimatedDurationMs.useSyntheticProgresskeeps its 6 minute default when no estimate is given.So v2 loading bars do not change. Tests show the default for UK, US state and US district runs: 3 and 6 minutes, with no estimate attached.
v3 estimates
Only the flagship report run (
Report.page) anduseBillEconomy(bill reports and the reforms page) opt in.Most values use the 90th percentile, so the bar rarely reaches its 95% cap before the result. UK subnational and US place runs have no observed samples, so they use the UK nationwide and US state values.
Changes
calculationDurations.ts: new region constants (US_STATE_…,US_DISTRICT_…,UK_REGION_SOCIETY_WIDE_DURATION_MS) andgetDurationForRegion(countryId, region). It classifies the region throughnormalizeRegionCode, so legacy codes such asca,us-caandCA-12also work. The existing constants and functions are unchanged.CalcParams/CalcStartConfig: optionalestimateByRegion.CalcOrchestratorpasses it through only when it is set.SocietyWideCalcStrategy: withestimateByRegion, estimates from the region and returnsestimatedDurationMson pending statuses.CalcStatus: optionalestimatedDurationMs.useSyntheticProgress: usesestimatedDurationMswhen it is given. It reads the value through a ref (synced in an effect), so the estimate that arrives with the first status does not restart the bar.useCalculationStatus/useAggregatedCalculationStatus: pass the estimate through; the aggregate uses the longest pending estimate.Report.page/useBillEconomy: setestimateByRegion: true.Checks
useSyntheticProgress(the aggregate picks the longest, or none); the v3 callers opt in; the synthetic bar uses the estimate and does not restart when it arrives late.bun run vitest: 4,390 passed, 10 skipped.bun run typecheck, ESLint and Prettier on the changed files: pass.Follow-ups
RunProgresstakesexpectedMs={getDurationForCountry(...)}, which applies only before the first status arrives. It can callgetDurationForRegionin a later change.stage,progressandprogress_maxto the economy response. Once they deploy, the bar can move its time estimate betweenprogressandprogress_max. This PR stays the fallback for responses without those fields.🤖 Generated with Claude Code