Skip to content

Pre-Budget certified release: rebuild on policyengine 6.2.6, model-conditional expected value, dashboard - #30

Merged
vahid-ahmadi merged 58 commits into
model-v2from
prebudget-release-b
Oct 15, 2026
Merged

vahid-ahmadi merged 58 commits into
model-v2from
prebudget-release-b

Conversation

@vahid-ahmadi

@vahid-ahmadi vahid-ahmadi commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Update, 15 Oct: the cross-check now runs on Microcosm's UK release

The 40 paired runs in the 14 Oct update used populace_uk_2023, the June file the repo has labelled "Microcosm". They now use Microcosm's UK national release: microcosm_uk_2024_25.h5 at microcosm-uk-2024-25-national-20261002T230158Z-5c6b3f68 (SHA-256 aa31bdf6…). Everything else stays on the certified 6.2.6 bundle and Enhanced FRS 1.58.0.

  • Registry (datasets.py, config.py). Microcosm is pinned by tag and SHA-256 and is uncertified under 6.2.6, because its release declares compatibility with policyengine-uk 2.100.0 only. Its ageing anchor is 2025, since all 1,168 of its calibration targets have period 2025. populace_uk_2023 stays registered for the pilot scripts.
  • Two fixes in demography.py, please review. Microcosm's person, household and benefit-unit IDs are 64-bit, and policyengine-uk holds them as 32-bit, so they wrap. The order is the same, and no IDs collide after wrapping.
    • The record-order guard now compares IDs in the model's integer type and requires them to stay distinct there (_same_order, with a test).
    • The birthday draw now hashes the IDs the model holds. Hashing the survey's 64-bit IDs gave other birthdays than policyengine-uk's, and 495 records changed State Pension type, so EligibilityChanged refused the run. With the model's IDs, the draw matches policyengine-uk's months_since_last_birthday for every Microcosm record, and it is unchanged on the Enhanced FRS (whose IDs fit in 32 bits).
  • Full rebuild at e089a0f (the cache keys on these files). The Enhanced FRS figures are identical to the 14 Oct build.

Results, 2039-40 (£bn)

Gross Net
Expected saving, Enhanced FRS (headline, unchanged) 11.1 ± 0.1 7.9 ± 0.1
The same 40 paths on Microcosm 12.3 8.4
Microcosm − Enhanced FRS, paired +1.12 (SE 0.01) +0.49 (SE 0.01)
Previously, on populace_uk_2023 +0.73 +0.13

In 2034-35 the paired difference is +0.31 gross and +0.13 net.


Update, 14 Oct: Max's answers applied

  • Provisional under ruling (c), not (b). triple-lock-build --pre-budget --uncertainty-ruling c runs the primary through the model-conditional route, then checks that its path design and specs, and both mean-path specs, are byte-identical to the committed C2 dry run (data/pilot/c2-dry-run). It refuses if they differ or if the dry-run primary fails C2. The file records the dry run's C2 provenance (run_kind: "dry_run", expected_value_authorized: false, provisional: true).
    • I re-ran the C2 dry run on the current code. It reproduces exactly: the same outcome and score table (test A suspended: 4 of 6 terminal, 80% annual) and byte-identical paths.
  • Enhanced FRS 1.58.0 stays primary. The 40 paired Microcosm runs are done (about 8.5 minutes each on my Mac) and included, and the Microcosm skip no longer applies to this release.
  • The Pre-Budget certified release: rebuild on policyengine 6.2.6, model-conditional expected value, dashboard #30 dashboard layout, with:
    • the "provisional" banner and card;
    • the dry-run sentence on the Methodology tab;
    • the ±0.5pp cards kept as sensitivities;
    • no "failed backtest" wording.
  • Results (2039-40, unchanged): expected saving £11.1bn ± 0.1 gross, £7.9bn ± 0.1 net. Microcosm − Enhanced FRS on the same 40 paths: +£0.73bn gross (SE 0.01), +£0.13bn net (SE 0.02).
  • Checks:
    • pytest: 1,684 passed, 0 failed after one stale test fix. test_ageing_validation pinned the pilot's paired draws; it now reads the committed file's draws, and the pilot pins have their own test.
    • check_assumptions.py passes, and the dashboard test, lint and build pass.
    • No record-level keys in the file.
  • Next: once Guard model-v2 binding inputs and build admission #29 lands, rebase this onto model-v2; then merge main into model-v2 and send model-v2: certified bundle, engine port and guarded rehearsal #24 to main.

The original description follows. Where it differs from the update above, the update applies.


@MaxGhenis this PR collects all of our pre-Budget work on top of model-v2 (merged up to bf0e6ee): a certified rebuild, its results and the dashboard changes. Nothing is merged. Below: what we did, the decisions that are yours, and the runs still to do.

Supersedes #27 and #28; this branch contains both, so they can be closed once this one is settled.

What we did

  • Certified rebuild on my Mac. Built with policyengine 6.2.6 (pe-uk 2.125.1, core 3.33.0) on Enhanced FRS 1.58.0. The bundle and Housing Benefit passport preflights both passed. The build ran from a clean tree.
    • 161 primary-path runs, plus 322 earnings ±0.5pp mean-path runs, the central path, the OBR wedge, the history replays and Microcosm coverage.
    • Inputs: OBR March 2026, with August 2026 CPI as April 2027's CPI leg (provisional).
  • model-v2: certified bundle, engine port and guarded rehearsal #24's CI fix (from Fix #24 CI: render the HB passport footnote from the renderer #27). The renderer now renders the HB passport footnote. Your bf0e6ee fixed the same files, so the merge keeps your version.
  • --pre-budget release mode (from Pre-Budget release mode: scenarios-only certified build, clearly labelled #28):
    • writes a release block and shows a dashboard banner;
    • records your ruling (c) and says it is "not a new d955 ruling";
    • certified provenance is checked against the recorded bundle;
    • an end-to-end assembly test covers the pre-Budget path.
  • Ruling (b) under --pre-budget: shows a model-conditional expected value now. The banner says the primary failed C1, and that the binding C2 score and a new release follow the 28 Oct Budget.
  • Microcosm paired subsample skipped in this release only (pre_budget and ruling == "b"). It is recorded as expected_value.paired_sensitivity.status: "omitted". The normal and binding builds are unchanged, and a test covers that.
  • Dashboard:
    • Budget impact leads with the distribution across paths, labelled model-conditional, beside the scenario envelope (cards plus a new dot chart, not a distribution);
    • the scenario section is no longer duplicated;
    • no "unavailable" boxes;
    • expected-value wording kept out of the scenarios-only view.
  • Tests follow the file. Historical publication pins now come from archived pilot bytes (tests/fixtures/historical-publication/). Assumptions tests follow the recorded population treatment.
  • Checks:
    • full pytest: 1,682 passed, 0 failed;
    • check_assumptions.py: passes;
    • dashboard: test, lint and build pass;
    • no record ids, weights, single-record figures or counts of 1–9;
    • Burnham ≤ triple lock on every path, and net ≤ gross.

Results (UK, £bn, 2039-40, gross / net)

Gross Net
Expected saving, model-conditional (160 paths) 11.1 ± 0.1 7.9 ± 0.1
Middle 80% of paths 3.9 to 18.9 2.7 to 13.4
Central forecast 0.9 0.6
Triple lock at the OBR's long-term rate 10.3 7.3
Earnings −0.5pp from 2031 10.4 ± 0.5 7.4 ± 0.4
Earnings +0.5pp from 2031 11.0 ± 0.5 7.7 ± 0.4

Against the uncertified pilot (E both, kept), central gross is −1.3% and net is +7.3%. Most of that comes from the HB passport fix and the 1.58.0 Housing Benefit and Pension Credit data. GB coverage against DWP: pension-age HB is now +3–11% (pilot +71–86%), and PC claims +13–40% (pilot +30–63%). The State Pension bill is about 15% below DWP.

Decisions for you

Method

  • Publishing (b) before the Budget. Your recorded ruling is (c): an expected value only if the primary passes C2 on the 28 Oct inputs. This PR shows a model-conditional expected value now, clearly labelled, and a new release follows the Budget. OK, or should the pre-Budget release be scenarios only (ruling a, which this branch also supports)?
  • Skipping the Microcosm cross-check in this interim release. OK, or run the 40 paired runs first (see below)?
  • Microcosm or Enhanced FRS as the primary dataset. Should the published numbers be on Microcosm rather than the Enhanced FRS? Our understanding is that 6.2.6 certifies Enhanced FRS 1.58.0 and REBUILD treats Microcosm as an uncertified sensitivity, so we kept the Enhanced FRS. If PolicyEngine is moving to Microcosm as the default, the primary would switch, at about 32 GB and 20 minutes per run (roughly 54 hours for 161 runs on one worker).

Dashboard

  • Which dashboard ships: this branch's Budget impact tab (distribution plus envelope plus dot chart), or your model-v2 layout. With this file, your getExpectedValue returns null because it requires the Microcosm sensitivity estimates, so the summary and the expected saving show "unavailable". With the scenarios-only file, it renders the envelope block twice.
  • The earnings ±0.5pp cards are path-set averages, so they sit close to the expected value. Keep them, or show only the central and OBR-wedge scenarios?
  • Banner wording: the "28 October" date is in the component and in pipeline constants.

Code

Runs still to do

  • 40 Microcosm paired runs for the dataset cross-check (about 20 minutes and 32 GB each; about 13 hours on one worker). Every other job is cached. After that, rebuild with ruling (b) and the cross-check, or with (c) after the Budget.
  • Binding C2 score on the 28 Oct inputs: September CPI (21 Oct), May–July AWE, and the OBR Budget means. Then the certified rebuild under (c), with either an expected value beside the envelope or scenarios only.
  • The version bridge split (bundle → data → passport) for the pilot-to-certified change, if your Part J import doesn't already cover this head.

🤖 Generated with Claude Code

vahid-ahmadi and others added 11 commits October 12, 2026 13:02
b31137e corrected the [^hb-gc-passport] footnote in
docs/pilot/E-fiscal-tables.md and docs/MODEL_V2_PILOT.md by hand, but
HB_GC_CAVEAT still carried the old wording, so the renderer no longer
reproduced the committed tables and both footnote tests failed. Take the
committed text as the source of truth, update the two asserted strings,
and re-render: the output equals the committed file byte for byte. No
number changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A certified-bundle build records certified: true (datasets.provenance), so
the results and scenario provenance tests asserted the wrong thing: they
required certified is False. They now check the flag against what the build
recorded: true only with the registry's certification_bundle for the dataset
and matching model/core versions; false, with the uncertified reason and no
bundle, for the historical pilot. A unit test exercises both branches, since
the committed files predate the model key.

The dashboard's replication line no longer assumes an uncertified pair: it
names the certifying policyengine.py bundle when the file says certified.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
triple-lock-build --pre-budget --uncertainty-ruling a writes an interim
certified file on today's committed inputs and says so:

- a top-level release block (also in provenance): stage pre-budget, the
  OBR March 2026 forecast, April 2027's provisional August 2026 CPI leg,
  the expected value withheld until the binding C2 score on the 28 October
  2026 Budget inputs, and Max's recorded d955 ruling (c);
- uncertainty_ruling and the mean-path provenance keep ruling a (the
  scenario-only execution, no requested_ruling) and add release_stage,
  interim and recorded_ruling c: an interim release under (c), not a new
  d955 ruling;
- expected_value_omission.reason reads "Withheld pending the post-Budget
  binding score", not "d955 scenario-envelope ruling", and the assumptions
  strip quotes it.

--pre-budget refuses any ruling but a (CLI and pipeline.build, before any
job), --scenario, --mean-path-scenarios and --uncertainty-handoff, and
refuses once CPI_PERIOD or the central forecast no longer describe the
pre-Budget inputs, so the label cannot go stale.

The dashboard shows a pre-Budget banner while release.stage is pre-budget,
and the scenario envelope no longer says the recorded ruling omits an
expected value in that case. RESULTS_SCHEMA.md documents release; REBUILD.md
adds the interim step before the binding rebuild. A results-file check
verifies the labels whenever a file carries a release block.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Drives pipeline.build with --pre-budget on the adapter's fake-engine handoff
fixture. Only PolicyEngine- and git-bound steps are stubbed; EV.build, the
mean paths, coverage, redaction, assumptions and benchmarks run for real,
and the post-build verifiers from test_results accept the file. An assembly
error on this path can no longer first appear after the build's model jobs.
Also covers the unlabelled direct-(a) shape and every --pre-budget refusal.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
After the post-Budget inputs are committed (CPI_PERIOD 2026 SEP) and before
the binding rebuild replaces it, a committed pre-Budget file must fail only
the documented stale-results test. The results check now reads the file's own
release block; the assembly test still proves the build derives it from
config. RESULTS_SCHEMA.md lists provenance.release.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Dashboard: a scenarios-only file (ruling a, no expected value) now leads the
Budget impact tab with one scenario-envelope headline read from the file: the
central forecast, the OBR wedge, the paired +/-0.5pp earnings mean paths
(2034-35 and 2039-40, gross and net) and the April 2017 replay, with a
drop-down line on the earnings asymmetry when the paired differences show it.
The envelope is no longer rendered twice, Methodology no longer prints
"unavailable", and the intro, backtest note, limitations and path text keep
expected-value wording out of a scenarios-only release.

Tests: pytest branches on the file's own state. The historical-publication
proof and the historical estimator run on the pilot's exact pinned bytes
(archived under tests/fixtures/historical-publication once a certified build
replaces them); the paired-ageing tests read the paired draws from the same
historical file when the committed one omits an expected value; assumptions
tests follow the population treatment the runs record; a weight key may hold
a label or a check, never a number.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
triple-lock-build --pre-budget now accepts --uncertainty-ruling b as well as a.
Under (b) the release block says the expected value is shown as model-conditional:
the primary forecast model failed the pre-registered C1 screen, and the binding C2
score and a new release follow the 28 October Budget. The recorded ruling stays (c);
interim: true; not a new d955 ruling.

Only in this pre-Budget (b) build, expected_value.build skips the 40-slot paired
Microcosm subsample and records the omission (release.paired_sensitivity,
expected_value.paired_sensitivity). Every other build, including the binding (c)
build, still runs it; expected_value.build refuses to omit it for any other ruling.
The assumptions strip says the Microcosm cross-check comes with the post-Budget
release. Same 160-slot design and cached runs as the (a) build: 0 new jobs.

Dashboard: with a pre-Budget (b) file the Budget impact tab leads with the
distribution across the simulated paths (expected saving ± its Monte Carlo error,
middle 80%, spread strips and the yearly spread chart, labelled model-conditional),
then the scenario envelope and its dot chart. The central forecast appears once
(scenario card), the Microcosm comparison box is dropped, and the banner explains
the model-conditional label.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…he Microcosm cross-check

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…cted value

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
's renderer fix

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vercel

vercel Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
uk-triple-lock Ready Ready Preview Oct 15, 2026 2:47pm UTC

Request Review

vahid-ahmadi and others added 3 commits October 13, 2026 17:42
…own paths

Max on #30 (13 Oct): show the distribution and expected value as provisional under the recorded ruling (c), not (b): the
original primary passes the pre-registered C2 screen in the dry run on current data (test A suspended: 4 of 6 terminal,
80% annual). triple-lock-build --pre-budget --uncertainty-ruling c runs the primary through the model-conditional route,
checks its path design and specs and both mean-path specs are byte-identical to data/pilot/c2-dry-run, and records the
dry run's C2 provenance (run_kind dry_run, expected_value_authorized false) with provisional labels. The paired Microcosm
cross-check runs in full. Dashboard: provisional banner and card, dry-run sentence on the Methodology tab, no repeated
envelope. Tests and REBUILD/RESULTS_SCHEMA updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The provisional (c) file carries the 40 paired runs on the C2 dry run's design, which has an explicit identical-rates
stratum; the pilot's pinned draws move to their own test.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…Microcosm cross-check

triple-lock-build --pre-budget --uncertainty-ruling c on policyengine 6.2.6 / Enhanced FRS 1.58.0, the 40 paired
Microcosm runs included. Expected saving unchanged at £11.1bn gross / £7.9bn net in 2039-40; on the same 40 paths
Microcosm gives £0.7bn more gross and £0.1bn more net.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
vahid-ahmadi and others added 5 commits October 14, 2026 14:14
…2023

The sensitivity dataset was populace_uk_2023 (June 2026), labelled Microcosm.
Pin Microcosm's UK national release instead: microcosm_uk_2024_25.h5 at
microcosm-uk-2024-25-national-20261002T230158Z-5c6b3f68 (sha256 aa31bdf6...),
uncertified under the 6.2.6 bundle (built with policyengine-uk 2.100.0). Its
calibration targets are all for 2025, so it anchors ageing in 2025.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Microcosm's 64-bit ids arrive wrapped to 32 bits in policyengine-uk, so the
record-order guard failed although the order is the same. Compare in the
model's type and require the ids to stay distinct there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Upstream's birthday draw hashes policyengine-uk's person ids. Microcosm's
64-bit ids arrive wrapped to 32 bits, so hashing the survey's ids gave other
birthdays and 495 records changed State Pension type. With the model's ids
the draw matches policyengine-uk's months_since_last_birthday for every
record on Microcosm, and is unchanged on the Enhanced FRS.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Built at e089a0f: Enhanced FRS figures are unchanged; the 40 paired runs now
use microcosm_uk_2024_25 instead of populace_uk_2023.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaxGhenis

Copy link
Copy Markdown
Contributor

UK hub FYI for the pre-Budget release: the uk-data age top code, and a change coming in the next uk-data batch.

  • The data: uk-data 1.58.1 (enhanced_frs_2024_25.h5, sha256 056e80fd…) has no record over 80. FRS adult ages are top-coded at 80, so 7,718 person records (3.59m people at 2024 weights) sit at exactly 80.
  • This repo already handles it. src/triple_lock/demography.py gives top-coded records a represented age from 80 to 105+ by a deterministic draw on the anchor year's ONS single-age shares, in every treatment except legacy. So the projections do depend on ages over 80, but through that stated method.
    • Check that the published text says the over-80 age split comes from ONS shares, not from the survey.
    • Check that any legacy-treatment figures don't appear without that caveat.
  • Coming in the next uk-data batch (Max's go, before 29 Oct): the national and regional ONS age targets will merge their top bands into one open-ended 80+ band per sex, because the data can't meet the 85–90 targets (uk-data #593). That changes the calibrated 80+ weights, which this repo's anchor-year weights inherit. A release certified on 1.58.1 stays valid as it is, but a rebuild on the next data release will move the 80+ cells.

vahid-ahmadi and others added 6 commits October 15, 2026 14:54
- Drop the Microcosm cross-check from every tab (it stays in results.json)
  and the pre-Budget banner (its release block stays in the file).
- Shorten the intro and the text on every tab; How to read these figures
  is four lines, including that ages above the top code of 80 are spread
  by ONS shares.
- The scenario envelope is one table: Scenarios and sensitivities.
- Households with lower income -> Households worse off.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…f share as 100 squares

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…io bars

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…art, paths guide, one-switch rule chart, collapsible replay, Methodology tables in dropdowns and grouped limitations

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…urce links, joined explainers, one switchable chart and new headline cards on Forecast paths, clearer path picker, 'current law' label

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every link in the dashboard's content is underlined (main a); the On this tab
navigation and the site header and footer are not. The replication line now
names only the policyengine.py version, falling back to the model and data
when no version is recorded.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
vahid-ahmadi and others added 20 commits October 15, 2026 15:39
…ath, sources as short points, styled hover tips on the headline cards, leads that say what each part shows

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- SERIES in lib/colors.js gives each concept one colour on every tab: triple
  lock darkest teal, Burnham plan mid teal, gross dark / net light teal,
  earnings dark teal, CPI amber, 2.5% floor pale grey, bands, average,
  median, OBR central, offsets, highlight, error. A test fails on raw hex.
- Methodology in four sections: How we model it, What we use, Our
  assumptions, Limitations (one scannable list); groups-of-paths and
  best-distribution dropdowns and Full wording removed.
- How our costing compares and If the plan had started earlier are one-box
  collapsible sections (CollapsibleSection), opened by their links.
- Pension amounts and gaps per year (formatAnnualFromWeekly, x52 as
  policyengine-uk's WEEKS_IN_YEAR); started-earlier pension as a
  comparison card.
- Header and page title name the Burnham plan vs the triple lock.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ecile ticks 1-10

Example pensioners: pensioner buttons, three cards (State Pension under
each rule, income change with what made up the lower pension, share made
up from unrounded figures), and one panel switching between an item-by-
item waterfall and each year, with The numbers and How to read this as
joined footers. The by-group table moves into its chart's panel as The
numbers; income deciles show 1-10 with one axis label.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tral note, DWP first, neutral wording

The headline card shows the expected saving without the Monte Carlo error in
the value and notes that it is provisional until the Budget; the note on why
the OBR central forecast saves little sits under the yearly chart; the
comparison panel opens on DWP; scenario names and the earnings-shift note
come from the file.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… household and triple-lock tabs

- The four example paths have the same names on every tab; the
  Distributional tab opens on the OBR central forecast and labels its
  figures 'on this path'.
- How the triple lock works comes second.
- 'Years the rules differ' becomes 'Pension below the triple lock'.
- Plain, neutral wording: no 'ratchet', 'losing' or code words; one
  phrasing for the Housing Benefit and council tax reduction caveat.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…parison titles, 'points' not 'pp', plain past-forecast test

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ll on phones

BoxTitle gives each chart or table box its title and one line saying what
it shows, and a test fails if a box heading lacks one. The site header
hides two nav links below the small breakpoint so the page fits 390px.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ets from the path's rows; no year-by-year table on Forecast paths

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… the household figures are calculated; one header layout for every chart box

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rd; its notes as five bullets with the replayed-vs-paid list

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Root cause: the chart used ChartFrame's grow mode (left from its old
card layout), which set only a min-height, so the 100%-height chart
measured 0 tall inside the panel and drew nothing. ChartFrame now always
sets an explicit height, and a test clicks every view switch on every tab
and checks each chart frame has one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…the line where it matters

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…wn; headline card with one detail line, the error on hover and a short Budget note

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ette test also blocks raw primary colours on data marks

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-earlier box; the selected path's line moves into 'What each path is'

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
vahid-ahmadi and others added 4 commits October 15, 2026 16:39
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ged)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch was successfully deployed

1 active deployment
Preview — e3cf173c Deployed Oct 15, 2026 by vercel[bot]
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