#806 / #812 delivered the UK national line's inspect lane: assemble a certified cut, publish with --no-latest under an immutable per-cut tag (microcosm-uk-2024-25-national-<YYYYMMDDTHHMMSSZ>-<uuid8>), and adjudicate it on the dashboard via the release list / ?release=. Promotion — moving latest.json — is structurally refused there (publish_release rejects a pointer move for any tag that is not the release id itself), because the current pointer and loader contracts cannot express it. This issue is the design and implementation that lifts that refusal.
Why promotion cannot work today
The 2026-08-27 ruling makes the national release id constant across cuts; run identity lives in the per-cut tags and the Logbook chain. Two contracts still assume id == tag:
- The pointer cannot name a cut.
latest_pointer_payload carries only {schema_version, release_id, updated_at, paths} (release.py). A promoted pointer could say the current release is microcosm-uk-2024-25-national but not which cut that means.
- The certified loader follows the id as a tag.
loader.py fetches release_manifest.json at revision=pointer.release_id — an immutable tag named exactly the release id, which the national line never mints (and must not: minted once at cut 1 it would pin cut 1 forever) — and separately hard-asserts the default artifact's revision == release_id, which per-cut revisions fail by design.
The dashboard itself would survive a pointer move (it reads releases/<id>/ paths off main, which always hold the current cut); every certified consumer would break.
Design decisions this issue owns
- Pointer shape: add a
tag/revision field naming the current cut (bumps LATEST_POINTER_SCHEMA_VERSION; the reader refuses unknown versions, so microcosm-data consumers, the dashboard, and the pe certification path upgrade in lockstep) — versus teaching the loader to read the manifest from main and trust its per-cut revision + sha pins (no schema bump, different immutability trust model).
- Repo pointer semantics:
latest.json is repo-global, and policyengine/populace-uk-private currently serves the June 2023 release to certified consumers. Promoting the national line re-points what "current" means for the whole repo: one shared pointer, per-line pointers, or separate repos is an adjudication, not a refactor.
- Registry entry for the national line (the registry today has only
(uk, 2023) → populace_uk_2023.h5), so pe can load what the pointer names.
- Lift the interim refusal: replace
publish_release's per-cut-tag pointer refusal with whatever the new contract permits, keeping the fail-closed default for tags the pointer cannot express.
Riding along
- The constant-named staging branch
release-staging/microcosm-uk-2024-25-national strands when tag creation 409s mid-publish and blocks the retry until deleted by hand; a per-attempt staging branch name removes the recurrence.
Acceptance
- A promoted national cut resolves end-to-end: pointer → current cut → certified loader fetches the manifest and artifacts at an immutable ref and verifies their digests.
- Certified consumers of the 2023 line keep working through the transition, per the repo-semantics ruling.
- The inspect lane is unchanged:
--no-latest publishes still work identically, and promotion of a tag the pointer cannot express still refuses.
Out of scope
#806 / #812 delivered the UK national line's inspect lane: assemble a certified cut, publish with
--no-latestunder an immutable per-cut tag (microcosm-uk-2024-25-national-<YYYYMMDDTHHMMSSZ>-<uuid8>), and adjudicate it on the dashboard via the release list /?release=. Promotion — movinglatest.json— is structurally refused there (publish_releaserejects a pointer move for any tag that is not the release id itself), because the current pointer and loader contracts cannot express it. This issue is the design and implementation that lifts that refusal.Why promotion cannot work today
The 2026-08-27 ruling makes the national release id constant across cuts; run identity lives in the per-cut tags and the Logbook chain. Two contracts still assume id == tag:
latest_pointer_payloadcarries only{schema_version, release_id, updated_at, paths}(release.py). A promoted pointer could say the current release ismicrocosm-uk-2024-25-nationalbut not which cut that means.loader.pyfetchesrelease_manifest.jsonatrevision=pointer.release_id— an immutable tag named exactly the release id, which the national line never mints (and must not: minted once at cut 1 it would pin cut 1 forever) — and separately hard-asserts the default artifact'srevision == release_id, which per-cut revisions fail by design.The dashboard itself would survive a pointer move (it reads
releases/<id>/paths off main, which always hold the current cut); every certified consumer would break.Design decisions this issue owns
tag/revisionfield naming the current cut (bumpsLATEST_POINTER_SCHEMA_VERSION; the reader refuses unknown versions, so microcosm-data consumers, the dashboard, and the pe certification path upgrade in lockstep) — versus teaching the loader to read the manifest from main and trust its per-cut revision + sha pins (no schema bump, different immutability trust model).latest.jsonis repo-global, andpolicyengine/populace-uk-privatecurrently serves the June 2023 release to certified consumers. Promoting the national line re-points what "current" means for the whole repo: one shared pointer, per-line pointers, or separate repos is an adjudication, not a refactor.(uk, 2023) → populace_uk_2023.h5), so pe can load what the pointer names.publish_release's per-cut-tag pointer refusal with whatever the new contract permits, keeping the fail-closed default for tags the pointer cannot express.Riding along
release-staging/microcosm-uk-2024-25-nationalstrands when tag creation 409s mid-publish and blocks the retry until deleted by hand; a per-attempt staging branch name removes the recurrence.Acceptance
--no-latestpublishes still work identically, and promotion of a tag the pointer cannot express still refuses.Out of scope
uk_target_fitadjudication line (UK WAS stage: split private pension wealth out of corporate_wealth (uk-data#452 M2) #750 et al.) — a shippable certification is a precondition for having anything to promote.