Skip to content

Dashboard plumbing for the UK national line: release-dir assembly, id-keyed contract coverage, inspect-before-promote #806

Description

@juaristi22

#757 (#787, #793) completed the UK national line's release evidence: the seam writes calibration_diagnostics.json (shared schema 6 + uk_diagnostics) and its signed battery, the spine build runs its own battery, and tools/certify_uk_release_cut.py composes the three scoped reports into release_certification.json — the only artifact that may carry a UK shippability verdict. The dashboard already reads the UK: the calibration-diagnostics COUNTRY_REGISTRY entry resolves policyengine/populace-uk-private through latest.json.

Two gaps remain between a certified candidate and the dashboard: nothing assembles a publishable release directory, and the national release id escapes the contract's UK-keyed checks. This issue covers that plumbing, so that when a cut clears uk_target_fit (the 13-cell adjudication in #750 / #792), publishing is mechanical.

A. Release-directory assembler

required_release_files("microcosm-uk-2024-25-national") demands:

build_manifest.json, release_manifest.json, calibration_diagnostics.json, release_certification.json

The UK chain produces the last two. No UK tool writes the two manifests — every release_manifest.json producer on main is US, and #787 retired the June driver that owned UK packaging.

Needed: an assembler (tools/assemble_uk_release_dir.py, or a final mode on certify_uk_release_cut.py) that marshals existing evidence into releases/microcosm-uk-2024-25-national/:

  • Identity: UKReleaseIdentity.as_release_manifest_fields() (uk_runtime/release_identity.py) already emits country, tier, n_records, build_id — the manifest assembler was its declared consumer.
  • Gates / provenance: the certification carries the gate census and the closed identity join (spine report → sidecar → build record → diagnostics → candidate bytes); the seam's build record and the spine sidecar carry the pins, seeds, vintages, and rules-engine version for build_manifest.runtime / dataset.
  • Self-check: the assembler calls validate_release_dir on its own output (_check_build_manifest contract.py:799, _check_release_manifest :987, _check_cross_manifest_consistency :4871), so a bad directory refuses at assembly, not at publish.

B. Id-keyed contract coverage for the national id

microcosm-uk-2024-25-national (ruling 2026-08-27) drops the populace-uk- prefix, so it matches neither _is_uk_exact_k_release_id nor startswith("populace-uk-"). Two checks silently no-op for it — the green-by-absence class the #793 review round closed one layer down:

  1. The contract skips _check_uk_calibration_diagnostics (contract.py:3903, :4320 gate on the exact-k predicate) — the entire uk_diagnostics validation: ESS fraction, weight concentration, zero-weight strata, geography pass rates. Exactly what the dashboard renders; the certification's field set does not cover it.
  2. The contract skips the policyengine-uk model pin: _expected_model_package (:1416) returns None for the id, so neither build_manifest.runtime (:846) nor release_manifest.build.built_with_model_package (:1028) gets checked.

Fix: a _is_uk_release_id() helper covering all three shapes (exact-k, June legacy, national) for the diagnostics and model-package branches. Keep the terminal-gate-report branches exact-k-scoped — the certification already pins the part reports by digest.

C. Two-step publish: inspect in the dashboard, then promote

The publish layer already supports a staged decision; document it as the operator flow and close the tag gap below.

  1. Inspectpython -m microcosm.data.publish_cli releases/microcosm-uk-2024-25-national --repo-id policyengine/populace-uk-private --artifact-root <dir> --no-latest --tag-name <per-cut>. Validates the full contract, commits the files under releases/<id>/, creates the immutable tag — moves no pointer, fires no Slack alert. The dashboard lists releases from the HF tree (releases?recursive=true), not the pointer, so the candidate renders via ?country=uk&release=microcosm-uk-2024-25-national while the current release stays put. (--tag-only commits nothing to main, so the dashboard cannot see it — not this flow.)
  2. Adjudicate in the release summary, target browser, and compare views.
  3. Promote or walk away — re-run publish without --no-latest to move latest.json and fire SLACK_WEBHOOK_POPULACE_UK. Declining a cut = never promoting.

Two constraints:

  • Per-cut tag names. create_tag defaults the tag to the release id, and the national id is constant across cuts — the second cut's publish collides with the first cut's immutable tag. Adopt a convention (e.g. microcosm-uk-2024-25-national-<build_id>) and record the tag in the build record so Hub history stays joinable to the Logbook chain. Successive cuts overwrite releases/<id>/ on main — intended; history lives in tags and the Logbook.
  • Only certified candidates are inspectable. publish_release validates before any upload and recomputes shippability from the certification parts — a blocked candidate uploads nothing. The EVIDENCE tier is US-scoped; for blocked UK cuts the review surface stays local. Extending it is out of scope here.

D. Deployment checklist

  • HF token with write access to policyengine/populace-uk-private where publish runs; MICROCOSM_UK_TERMINAL_GATE_SIGNING_KEY for the cut.
  • SLACK_WEBHOOK_POPULACE_UK set (missing webhook warns, never fails; fires only on promotion).
  • HF_TOKEN on the dashboard deployment (private repo; reads go through the server).
  • The first promotion creates latest.json — nothing to pre-seed. Until then the UK default view has no current release; inspect publishes render through the release list / ?release=.

Acceptance

  • Assembling a certified candidate yields a directory that passes validate_release_dir under microcosm-uk-2024-25-national, including the re-armed checks from B.
  • A --no-latest publish appears in the dashboard release list and renders in the summary, target, and compare views under ?country=uk, with latest.json untouched and no alert.
  • Promotion moves the pointer, fires the alert, and the default UK view resolves the release — no dashboard-side changes anywhere in the flow.
  • A second cut publishes under the same release id with a distinct tag.

Out of scope

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions