You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The UK side of the dashboard (/populace with the UK toggle) renders visibly worse than the US side: a blank calibration map when any geography option is selected, empty Geography/Level columns and filters, a per-family fit table with one target per row, "—" KPI cards, and an empty loss-trajectory section. We investigated where the UK data actually comes from and why its shape differs from the US. Root cause splits in two: the UK release artifacts are produced by a bespoke, uncommitted pipeline whose logging structure doesn't match the US, and, independently, a handful of dashboard bugs that bite the UK regardless of logging.
Primary fix: migrate UK dataset production fully to populace
policyengine-uk-data is legacy for publishing (its CI only uploads enhanced-FRS artifacts to policyengine-uk-data-private; see populace#144 / populace#41), but it still supplies the UK target surface: the ons/..., slc/..., obr/... target names come from policyengine_uk_data/targets/, pinned as target_registry.version = "policyengine-uk-data-dd68c73".
The UK diagnostics writer is not committed anywhere. The US has a canonical writer (packages/populace-calibrate/src/populace/calibrate/diagnostics.py, now schema v4, contract-enforced at publish time by contract.py). The UK's calibration_diagnostics.json / build_manifest.json were written by a local harness on the build machine: org-wide code search finds zero hits for its distinctive strings (pre_calibration, uk_surface_candidate, calibrated_households, release_surface, …), and the SHAs embedded in the UK release ids (dd68c73, 4aa4b14, 72aeefc) resolve to no commit on any PolicyEngine remote — the builds are unauditable and would fail today's publish contract.
Because of that, the UK artifact is structurally leaner than the US one, and the dashboard has nothing to read for whole sections:
Proposed migration (so the UK publishes the same structure as the US and the dashboard needs no UK special-casing):
Port the UK target surface from policyengine_uk_data/targets/ into a populace.calibrate.TargetRegistry (declarative TargetSpecs with value/se/citation/family/metadata) — populace#147 already tracks this. Per-row metadata/registry and a content-addressed registry version then come for free.
Run the UK solve through populace.calibrate.solve.calibrate (or wrap the existing solver to return a CalibrationResult) and write diagnostics with write_calibration_diagnostics(...) — yielding numeric per-epoch loss_trajectory, n_records/n_nonzero, initial_loss/final_loss/fraction_within_10pct, real solver options, and skipped, with zero UK-specific code.
Move the surface-comparison inputs (candidate_surface/reference_surface/max_abs_relative_error_gate) out of options into the diagnostics build block and build_manifest.gates (the committed export_surface/target_surface gates from populace#39), alongside a target_compilation gate.
Commit and push a UK build driver (a tools/build_uk_release.py sibling of build_us_fiscal_refresh_release.py) and build from pushed commits, keeping publishing on populace-publish-release --repo-id policyengine/populace-uk-private so the schema-v4 contract is enforced for the UK exactly as for the US.
Also important: dashboard bugs independent of logging
These bite the UK today regardless of the artifact structure, and are needed for full dashboard operability. We're fixing these dashboard-side now (the migration above is the eventual upstream fix):
Calibration-map geography filter hardcodes US levels (National / State / Congressional district). UK rows have no matching level, so selecting any option blanks the map; the selection also went stale across country switches. Fix open: Make the calibration-map geography filter data-driven (fixes blank UK map) #69 (data-driven levels from the release, select hidden when a release has no levels).
Target-name parsing only understands US naming (FIPS/state patterns in frontend/lib/populace/latest-artifact.ts). UK names like ons/west_midlands_age_80_89 and ons/household_land_value/LONDON fall through with empty geography/level/breakdown and no facets — blank Geography columns, no Geography/Level filters, a per-family fit table of singletons (138 "families" for 149 targets), and a fragmented treemap (region and age band stay baked into the variable name). Needs a UK-aware parser (region + age-band extraction, national/region levels).
Loss-trajectory shape mismatch: the loader casts loss_trajectory to number[]; the UK's object-shaped checkpoints render as an empty "Loss trajectory" section instead of a before/after readout.
"Calibration details" panel renders empty for UK: the options grid only knows US solver keys, and the "Declared/compiled/dropped" line shows em-dashes when gates.target_compilation is absent.
KPI cards show "—" for derivable stats: "Within 10% of target" can be computed from the target rows (the targets page already does; UK is at ~98%), and "Records kept" could fall back to options.calibrated_households.
/api/populace/target-investigation ignores country — investigating a UK target queries the US dataset.
Cosmetic: the sidebar labels the UK dataset policyengine/populace-uk while the data is read from policyengine/populace-uk-private.
Items 2–7 are dashboard-side and don't depend on the migration; items 3–5 become moot once the UK artifact matches the US schema, but graceful degradation is still worth having for older releases.
The UK side of the dashboard (
/populacewith the UK toggle) renders visibly worse than the US side: a blank calibration map when any geography option is selected, empty Geography/Level columns and filters, a per-family fit table with one target per row, "—" KPI cards, and an empty loss-trajectory section. We investigated where the UK data actually comes from and why its shape differs from the US. Root cause splits in two: the UK release artifacts are produced by a bespoke, uncommitted pipeline whose logging structure doesn't match the US, and, independently, a handful of dashboard bugs that bite the UK regardless of logging.Primary fix: migrate UK dataset production fully to populace
Who publishes what today (investigated 2026-07-03 against
PolicyEngine/populace@2c93936andPolicyEngine/policyengine-uk-data@6a0acf9):policyengine/populace-uk-privateon HF is published byPolicyEngine/populace—publish_release()inpackages/populace-data/src/populace/data/release.pyvia thepopulace-publish-releaseCLI /tools/publish_release.sh, run manually (no publishing CI). The UK dataset is registered inpackages/populace-data/src/populace/data/registry.py#L98-L109.policyengine-uk-datais legacy for publishing (its CI only uploads enhanced-FRS artifacts topolicyengine-uk-data-private; see populace#144 / populace#41), but it still supplies the UK target surface: theons/...,slc/...,obr/...target names come frompolicyengine_uk_data/targets/, pinned astarget_registry.version = "policyengine-uk-data-dd68c73".packages/populace-calibrate/src/populace/calibrate/diagnostics.py, now schema v4, contract-enforced at publish time bycontract.py). The UK'scalibration_diagnostics.json/build_manifest.jsonwere written by a local harness on the build machine: org-wide code search finds zero hits for its distinctive strings (pre_calibration,uk_surface_candidate,calibrated_households,release_surface, …), and the SHAs embedded in the UK release ids (dd68c73,4aa4b14,72aeefc) resolve to no commit on any PolicyEngine remote — the builds are unauditable and would fail today's publish contract.Because of that, the UK artifact is structurally leaner than the US one, and the dashboard has nothing to read for whole sections:
populace.calibrate.diagnostics)metadata(ledger_* fields,source_measure_id,base_variables)nullon every rowregistry(family, se, notes)nulln_records,n_nonzeroinitial_loss,final_loss,fraction_within_10pctloss_trajectory[{step: "pre_calibration", relative_loss}, …]optionscalibrated_households,candidate_surface,reference_surface,max_abs_relative_error_gate,year)build_manifest.gatescalibration,target_compilation,target_profile_coverage, …exported_nonzero,parity,release_surfaceTargetRegistryProposed migration (so the UK publishes the same structure as the US and the dashboard needs no UK special-casing):
policyengine_uk_data/targets/into apopulace.calibrate.TargetRegistry(declarativeTargetSpecs with value/se/citation/family/metadata) — populace#147 already tracks this. Per-rowmetadata/registryand a content-addressed registry version then come for free.populace.calibrate.solve.calibrate(or wrap the existing solver to return aCalibrationResult) and write diagnostics withwrite_calibration_diagnostics(...)— yielding numeric per-epochloss_trajectory,n_records/n_nonzero,initial_loss/final_loss/fraction_within_10pct, real solveroptions, andskipped, with zero UK-specific code.candidate_surface/reference_surface/max_abs_relative_error_gate) out ofoptionsinto the diagnosticsbuildblock andbuild_manifest.gates(the committedexport_surface/target_surfacegates from populace#39), alongside atarget_compilationgate.tools/build_uk_release.pysibling ofbuild_us_fiscal_refresh_release.py) and build from pushed commits, keeping publishing onpopulace-publish-release --repo-id policyengine/populace-uk-privateso the schema-v4 contract is enforced for the UK exactly as for the US.Also important: dashboard bugs independent of logging
These bite the UK today regardless of the artifact structure, and are needed for full dashboard operability. We're fixing these dashboard-side now (the migration above is the eventual upstream fix):
frontend/lib/populace/latest-artifact.ts). UK names likeons/west_midlands_age_80_89andons/household_land_value/LONDONfall through with emptygeography/level/breakdownand no facets — blank Geography columns, no Geography/Level filters, a per-family fit table of singletons (138 "families" for 149 targets), and a fragmented treemap (region and age band stay baked into the variable name). Needs a UK-aware parser (region + age-band extraction,national/regionlevels).loss_trajectorytonumber[]; the UK's object-shaped checkpoints render as an empty "Loss trajectory" section instead of a before/after readout.gates.target_compilationis absent.options.calibrated_households./api/populace/target-investigationignorescountry— investigating a UK target queries the US dataset.policyengine/populace-ukwhile the data is read frompolicyengine/populace-uk-private.Items 2–7 are dashboard-side and don't depend on the migration; items 3–5 become moot once the UK artifact matches the US schema, but graceful degradation is still worth having for older releases.
🤖 Generated with Claude Code