Skip to content

Publish Microcosm UK release cuts, open the UK page on the national line, and show local candidates on Staging - #223

Merged
anth-volk merged 7 commits into
mainfrom
uk-release-cuts-calibration-fit
Oct 20, 2026
Merged

anth-volk merged 7 commits into
mainfrom
uk-release-cuts-calibration-fit

Conversation

@juaristi22

@juaristi22 juaristi22 commented Oct 19, 2026 •

Copy link
Copy Markdown
Collaborator

Microcosm UK publishes each dataset as a release line (PolicyEngine/microcosm#823). This PR lets the Calibration fit page show every published cut of a line, including the local-area dense release. It also makes the UK page open on the current national cut instead of the June 2023 Populace build. Finally, it lets the Staging candidates page show the per-target fit of UK local-area candidates again.

Problem

A Microcosm line keeps one release id and one folder, releases/<release id>/. Each cut is an immutable Hugging Face tag, <release id>-<YYYYMMDDTHHMMSSZ>-<attempt>. The national line's current cut is named by latest-national.json. The repository-wide latest.json stays on the June 2023 build.

The publisher assumed that a release id has one commit and that a tag's files sit under releases/<tag>/. It also read only latest.json. As a result:

  • microcosm-uk-2024-25-national is still stored as the 4 Oct cut. Each later cut changed the folder's commit, so UK release reconciliation now stops with "Released dataset … changed".
  • Each cut tag was reported as "Release has no calibration diagnostics". This includes microcosm-uk-2024-25-dense-20261019T000432Z-ee5c2dbe, which exists only as a tag.
  • The UK default stays on the June 2023 build.

Changes

  • A cut tag is its own release build. Its manifest entry uses the tag as releaseId and source ID. A new optional field, releaseDirectory, records the line folder. Readers fetch releases/<releaseDirectory>/ at the entry's commit. Entries without the field read releases/<releaseId>/ as before.
  • Cut verification. A tag counts as a cut only when releases/<release id>/release_manifest.json at that tag names it in build.cut_tag. Any other cut-shaped tag is reported ineligible with a reason, and the run continues.
  • Line folders. A line folder on main is not published again once its cuts are. A build already published from the folder stays pinned at its own commit, so it still audits and repairs. Tags that the manifest already pins at the same commit are not probed again.
  • UK default. The country registration gains pointer_path, which is latest-national.json for the UK. The publisher reads it and checks it: schema_version 1, a line that matches the file name, and a revision that is a cut of release_id. That revision becomes the latest release.
  • Release picker. /api/microcosm/releases adds every published cut beside the folders on main. It labels each cut by line and attempt, for example 2026-10-19 08:33Z · 2024-25-national · 6cba5d71. It hides a line folder unless the latest release still points at it. Each cut's role comes from its own release manifest at its commit, so the dense release keeps the existing "local area · experimental" flag.
  • Pinned source links. The summary's source links and the target investigation packet cite the line folder, at the cut's commit.
  • Upload injection. publishRelease takes an options object, and the manifest store can inject the bundle upload, so the reconciliation test runs without a dry run.
  • Staging page: local candidates. The staged-bundle reader looked only for calibration_diagnostics.json. Microcosm's UK local lane stages its outputs under the dataset's own stem, so its diagnostics arrive as microcosm_uk_2024_25_local.diagnostics.json. Every local candidate since early October therefore showed "has not uploaded calibration diagnostics yet", and staging reconciliation reported them ineligible. The reader now uses calibration_diagnostics.json when the receipt records it. Otherwise it uses the one <dataset>.diagnostics.json that the receipt records. If the receipt records several stem files, or a name that contains a path, the run has no target view. The digest check is unchanged.

US and Belgium have no cut tags and no pointer_path. Their inventory, picker, labels and latest selection are unchanged by construction, and tests check this. The manifest change is one optional entry field. The current reader already accepts and keeps unknown optional fields.

Rollout

The old frontend would read a cut entry from releases/<tag>/ and get a 404. Publishing therefore pauses until the new frontend is deployed:

  1. Before merging, set CALIBRATION_TREE_BUILD_ENABLED=FALSE.
  2. Merge, then wait for Deploy production to succeed.
  3. Re-enable CALIBRATION_TREE_BUILD_ENABLED.
  4. Dispatch Publish calibration tree one run at a time, because the shared slot cancels pending runs:
    • UK manual, dry run. Expect:
      • the national cuts and the dense cut published;
      • the microcosm-uk-2024-25-national folder build complete;
      • latest moves to the cut that latest-national.json names.
    • UK manual, real run.
    • UK staging, to catch up on webhooks skipped while publishing was paused.
    • US and BE manual dry runs, expecting every build complete.
  5. Check that the UK picker lists the cuts and dense, and that the UK default is the current national cut.

The first UK run builds the dense bundle. Locally, from the published files, it took about 2.5 minutes and produced 42 files. The largest file is 16.2 MB raw, against the 100 MB limit. Building the summary for that release took 0.3 seconds.

Related

Validation

  • cd frontend && bun test: 617 pass. New tests:
    • an end-to-end UK reconciliation with a legacy folder entry, two cut tags (one of them tag-only), a stray cut-shaped tag and the line pointer;
    • the pointer's checks;
    • the manifest field;
    • the release locator;
    • inventory merging and cut roles;
    • the investigation packet;
    • the releases route;
    • labels;
    • the staged diagnostics file rule.
  • bun run lint (tsc --noEmit) is clean.
  • bun run build passes.
  • I ran the staged-bundle reader locally against three real UK runs. The 19 Oct local candidate now loads from its stem file. The 19 Sep local candidate and the 19 Oct national attempt load from the same files as before.
  • The hosted Python · dependencies · source APIs check fails here, and it would fail on main too. backend/requirements.lock pins policyengine-us==1.764.6, which has been deleted; Pin .py 6.4.1 instead of the deleted policyengine-us 1.764.6 #222 replaces the pin. This PR changes no Python.

Review fixes (added by @anth-volk, with Claude Code)

Merged main into this branch (649a299, one import-list conflict in latest-artifact.test.ts: both sides kept). That fixes the hosted Python check.

Four fixes for bugs a Codex review of this PR found, one commit each. Each red count is from the new test(s) before the fix; each green count is the whole test file afterwards, rerun after the commit.

  1. --latest checks the pointer's tag against its release manifest (8a01c06). Reconciliation publishes a tag only when releases/<release id>/release_manifest.json at that tag names it in build.cut_tag. --latest skipped that check: given a latest-national.json whose revision is a tag whose manifest names another build, it published that tag and promoted it. readUpstreamLatest now applies the same check before any mode publishes or promotes from the pointer, and requires the tag's files to be under the folder named by the pointer's release_id. Reconciliation passes its manifest, so a tag already pinned there at the same commit is not probed again.
    • Red: 1 of 12 failed. readUpstreamLatest and runPublisher({ country: "uk", mode: "latest" }) accepted the tag.
    • Green: 12 of 12.
  2. The national pointer file is checked even when it names no revision (5fea679). A country whose registration names its own pointer file (the UK's pointer_path) now always gets the schema_version, line and tag checks, and a file without revision is refused. Countries that use latest.json still read release_id alone. The reconciliation metadata test used a UK pointer without a revision, so it now names a published tag of the same folder.
    • Red: 2 of 14 failed ({"schema_version":99,"line":"dense",...} and a pointer with no revision were both accepted).
    • Green: 14 of 14.
  3. A published tag's comparison metadata names the tag (3614ca7). publishRelease copied the diagnostics' release_id, which is the folder name, into index.targetComparison.releaseId, so two builds of one release compared as the same release. A tag published from its folder now records the tag there, as index.build.releaseId already did. A folder release keeps the id its diagnostics carry, so its bytes are unchanged.
    • Red: 1 of 15 failed (comparison metadata named microcosm-uk-2024-25-national and microcosm-uk-2024-25-dense).
    • Green: 15 of 15.
  4. A staged receipt is refused when one of its stem names contains a path (1079fa9). stagedBundleDiagnosticsFile dropped such names before counting, so {local.diagnostics.json, nested/dense.diagnostics.json} returned the first file. The count now includes every stem name, and the single stem file must also be one path segment.
    • Red: 1 of 30 failed.
    • Green: 30 of 30.

Typecheck (tsc --noEmit) is clean after each commit. Only the changed test files were run locally; CI runs the rest.

Tree publishing is paused (CALIBRATION_TREE_BUILD_ENABLED=FALSE, set 2026-10-19) until this stack is deployed, so rollout step 1 is already done.

🤖 Generated with Claude Code

Microcosm publishes a release line (microcosm#823) under a constant release
id: the line's files stay in releases/<release id>/ and each cut is an
immutable tag, <release id>-<YYYYMMDDTHHMMSSZ>-<attempt>. The publisher
treated a release id as one commit, looked for a tag's files under
releases/<tag>/, and took the UK default from latest.json, which stays on the
June 2023 build. The UK national cuts after 4 Oct and the tag-only dense
local-area release therefore never reached the Calibration fit page, and UK
release reconciliation stops with "Released dataset ... changed".

- A cut tag is its own release build. Its manifest entry carries the tag as
  releaseId and the line folder as the new optional releaseDirectory; readers
  fetch releases/<releaseDirectory>/ at the entry's commit. A tag counts as a
  cut only when that folder's release_manifest.json names it as
  build.cut_tag.
- A line folder on main is not published again once its cuts are; a build
  already published from it stays pinned at its own commit.
- The country registration gains pointer_path (UK: latest-national.json).
  Its revision names the cut that becomes the latest release.
- The release picker adds every published cut beside the folders on main,
  labels it by line and attempt, and hides a line folder unless the latest
  release still points at it. Local-area cuts keep the existing flag.
- US and Belgium have no cut tags and no pointer_path, so their inventory,
  picker and latest selection are unchanged.

bun test: 615 pass; tsc --noEmit clean; next build passes.

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

vercel Bot commented Oct 19, 2026 •

Copy link
Copy Markdown

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

Project Deployment Actions Updated
calibration-diagnostics Ready Ready Preview Oct 19, 2026 9:06pm UTC

Request Review

The Staging candidates page reads an unreleased candidate's per-target fit
from its staged bundle, but only from calibration_diagnostics.json.
Microcosm's UK local lane stages its outputs under the dataset's own stem,
so its diagnostics arrive as microcosm_uk_2024_25_local.diagnostics.json and
every local candidate since early October showed "has not uploaded
calibration diagnostics yet"; staging reconciliation reported them
ineligible.

The staged diagnostics file is now calibration_diagnostics.json when the
receipt records it, or else the one <dataset>.diagnostics.json the receipt
records. A receipt recording several stem files, or a name with a path, has
no target view, so nothing is guessed and no recorded name can leave the
staged prefix. The digest check is unchanged.

Checked against the 19 Oct local candidate, the 19 Sep local candidate and
the 19 Oct national attempt: all three now load, the latter two from the
same files as before.

bun test: 617 pass; tsc --noEmit clean; next build passes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@juaristi22 juaristi22 changed the title Publish Microcosm UK release cuts and open the UK page on the national line Publish Microcosm UK release cuts, open the UK page on the national line, and show local candidates on Staging Oct 19, 2026
@juaristi22
juaristi22 requested a review from anth-volk October 19, 2026 11:31
@juaristi22
juaristi22 marked this pull request as ready for review October 19, 2026 12:15
Brings in main's backend/requirements.lock, which pins a published
policyengine-us release and fixes this branch's failing hosted Python
dependency check.

Conflict resolved: frontend/lib/microcosm/latest-artifact.test.ts. Both
sides added a name to the same import list (this branch added
mergeReleaseInventory; main added MAPPED_MEASURE_CONCEPT_VARIABLES). Kept
both, in the list's existing alphabetical order.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
anth-volk added a commit that referenced this pull request Oct 19, 2026
The tree builder is about to move out of the dashboard into its own
package. Its outputs are byte-exact contracts: the index records every
part's raw-JSON SHA-256 and gzip size, build ids derive from the inputs,
and a repair refuses any change to the index digest. So the move has to
be proved to change no byte.

This records, from the builder as it is today, what it writes for
representative inputs built from the fixtures the module tests already
use. The inputs cover US and UK, releases and staging runs (version 1,
version 2, and a staged dataset bundle), Belgium, and a UK release with
reported loss attribution. For each, the record holds every part's path,
raw JSON digest and size, gzip size and deflate-stream digest, plus the
build id. It also records release-to-staging comparison bundles built
through the comparison reader, the explorer's root responses read back
from the stored bytes, and the manifest serialization. The gzip header's
operating-system byte varies by platform, so the header is asserted
separately and the digest covers the stream after it.

A second test drives the publisher's dry-run repair of the recorded US,
UK and Belgium releases against a stubbed Hugging Face repository. The
publisher refuses a rebuilt index whose digest differs, so a successful
repair proves its own reads and hashing reproduce the recorded index.
The stubbed repository serves each country's release pointer at the path
the publisher reads it from: `latest.json`, or `latest-national.json`
for the UK since #223.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
anth-volk added a commit that referenced this pull request Oct 19, 2026
The tree builder and the schema 6 code the dashboard shares with it are
moving to the collector as a Bun worker, and its types and readers will
be published as a package the dashboard imports. That needs the builder
to be one self-contained unit with explicit dependencies and its own
tests. Inside frontend/lib nothing stopped a dashboard-only import from
reaching it.

The package, @policyengine/calibration-tree in frontend/packages/, is
the builder's import closure: the schema 6 types, parsers, serializers
and bundle builder, the comparison builder, Blob I/O behind the existing
injectable client, and the release and staging readers the builder reads
from, including the country registry. Its 30 modules move unchanged
apart from ten import lines that used the dashboard's path alias. Their
tests and fixtures move with them. Next.js routes, the HTTP helpers and
the client hooks stay in the dashboard and import the package through
its subpath exports.

One of the 30 is release-cut.ts, added by #223. It parses the Hugging
Face tag names Microcosm gives each build of a UK release, and
latest-artifact.ts and calibration-tree-manifest.ts import it, so it
moves with them and is exported as release-cut. The dashboard's shared
formatter and the publisher now import it through that export.

Two other additions since this branch began are adjusted to fit. #223's
releases route and its test import the moved modules through the
package. #229's check that the mapped measure concept table matches
integrations/microcosm_policyengine_us/mappings.yaml moves out of the
package's latest-artifact tests into
lib/microcosm/mapped-measure-concept-variables.test.ts, because it reads
a file of this repository that will not move with the package.

A boundary test requires package modules to import only each other,
Node built-ins and declared dependencies (@vercel/blob), and requires
every module to be exported. The package has its own typecheck, chained
into the frontend lint script, so CI runs it without a workflow change.
The readers pass Next.js's fetch cache hint, which Bun ignores; a
declaration seen only by the package's typecheck mirrors Next's.

The golden tests now import the builder through the package and
reproduce the record taken before the move, which moved unchanged. The
workspace sits inside frontend/ because Vercel, CI and the publisher
workflow all install from there. bunfig keeps Bun's hoisted linker so
node_modules keeps its current layout. The former countries path stays
as a re-export for code not yet switched to the package path.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@anth-volk
anth-volk added this pull request to stack #230 October 19, 2026 20:23
anth-volk and others added 4 commits October 20, 2026 01:01
Reconciliation publishes a Microcosm tag only when the release manifest
in its folder at that tag names the tag in build.cut_tag. The --latest
mode skipped that check: given a latest-national.json whose revision is
a tag whose manifest names another build, it published the tag's files
under that tag and promoted it (found by the Codex review of this PR).

readUpstreamLatest now applies the same check to the tag the pointer
names, before any mode publishes or promotes from it, and requires the
tag's files to sit in the folder the pointer's release_id names.
Reconciliation passes its manifest, so a tag already pinned there at the
same commit is not probed again on every run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
readUpstreamLatest checked latest-national.json's schema_version, line
and tag only when the file had a revision. A file without one, for
example {"schema_version":99,"line":"dense","release_id":...}, was read
as a folder release, published at the repository's current commit and
promoted (found by the Codex review of this PR).

A country whose registration names its own pointer file (the UK's
pointer_path) now always gets those checks, and a file without a
revision is refused. Countries on latest.json keep reading release_id
alone. The reconciliation metadata test used a UK pointer without a
revision; it now names a published tag of the same folder.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
publishRelease copied the diagnostics' release_id into the bundle's
comparison metadata. Microcosm's diagnostics name the folder, so a
build published as microcosm-uk-2024-25-national-20261019T083323Z-...
recorded index.build.releaseId as the tag but
index.targetComparison.releaseId as microcosm-uk-2024-25-national, and
a comparison between two builds of that release labelled both sides
the same (found by the Codex review of this PR).

A tag published from its folder now records the tag in both places, as
the release reader already does when it loads one. A folder release
keeps the id its diagnostics carry, so its comparison metadata is
unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
stagedBundleDiagnosticsFile dropped stem names that are not one path
segment before counting them. A receipt recording both
microcosm_uk_2024_25_local.diagnostics.json and
nested/dense.diagnostics.json therefore returned the first file, though
this PR's rule is that a receipt recording several stem files, or a
name containing a path, has no target view (found by the Codex review
of this PR).

The count now includes every stem name, and the one stem file must
also be a single path segment.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
anth-volk added a commit that referenced this pull request Oct 19, 2026
The tree builder is about to move out of the dashboard into its own
package. Its outputs are byte-exact contracts: the index records every
part's raw-JSON SHA-256 and gzip size, build ids derive from the inputs,
and a repair refuses any change to the index digest. So the move has to
be proved to change no byte.

This records, from the builder as it is today, what it writes for
representative inputs built from the fixtures the module tests already
use. The inputs cover US and UK, releases and staging runs (version 1,
version 2, and a staged dataset bundle), Belgium, and a UK release with
reported loss attribution. For each, the record holds every part's path,
raw JSON digest and size, gzip size and deflate-stream digest, plus the
build id. It also records release-to-staging comparison bundles built
through the comparison reader, the explorer's root responses read back
from the stored bytes, and the manifest serialization. The gzip header's
operating-system byte varies by platform, so the header is asserted
separately and the digest covers the stream after it.

A second test drives the publisher's dry-run repair of the recorded US,
UK and Belgium releases against a stubbed Hugging Face repository. The
publisher refuses a rebuilt index whose digest differs, so a successful
repair proves its own reads and hashing reproduce the recorded index.
The stubbed repository serves each country's release pointer at the path
the publisher reads it from: `latest.json`, or `latest-national.json`
for the UK since #223.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
anth-volk added a commit that referenced this pull request Oct 19, 2026
The tree builder and the schema 6 code the dashboard shares with it are
moving to the collector as a Bun worker, and its types and readers will
be published as a package the dashboard imports. That needs the builder
to be one self-contained unit with explicit dependencies and its own
tests. Inside frontend/lib nothing stopped a dashboard-only import from
reaching it.

The package, @policyengine/calibration-tree in frontend/packages/, is
the builder's import closure: the schema 6 types, parsers, serializers
and bundle builder, the comparison builder, Blob I/O behind the existing
injectable client, and the release and staging readers the builder reads
from, including the country registry. Its 30 modules move unchanged
apart from ten import lines that used the dashboard's path alias. Their
tests and fixtures move with them. Next.js routes, the HTTP helpers and
the client hooks stay in the dashboard and import the package through
its subpath exports.

One of the 30 is release-cut.ts, added by #223. It parses the Hugging
Face tag names Microcosm gives each build of a UK release, and
latest-artifact.ts and calibration-tree-manifest.ts import it, so it
moves with them and is exported as release-cut. The dashboard's shared
formatter and the publisher now import it through that export.

Two other additions since this branch began are adjusted to fit. #223's
releases route and its test import the moved modules through the
package. #229's check that the mapped measure concept table matches
integrations/microcosm_policyengine_us/mappings.yaml moves out of the
package's latest-artifact tests into
lib/microcosm/mapped-measure-concept-variables.test.ts, because it reads
a file of this repository that will not move with the package.

A boundary test requires package modules to import only each other,
Node built-ins and declared dependencies (@vercel/blob), and requires
every module to be exported. The package has its own typecheck, chained
into the frontend lint script, so CI runs it without a workflow change.
The readers pass Next.js's fetch cache hint, which Bun ignores; a
declaration seen only by the package's typecheck mirrors Next's.

The golden tests now import the builder through the package and
reproduce the record taken before the move, which moved unchanged. The
workspace sits inside frontend/ because Vercel, CI and the publisher
workflow all install from there. bunfig keeps Bun's hoisted linker so
node_modules keeps its current layout. The former countries path stays
as a re-export for code not yet switched to the package path.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
anth-volk added a commit that referenced this pull request Oct 19, 2026
#223 now checks the UK's latest-national.json whenever the registration
names it: the file must carry schema_version 1, the matching line and a
revision, and the tag it names must be the build its release manifest
names. The golden repair harness served only {release_id}, so the UK
dry-run repair stopped at "latest-national.json has unsupported
schema_version undefined."

For a country registered with its own pointer file, the stubbed
repository now serves a pointer naming a tag of the recorded release at
another commit, with that tag's folder listing and a release manifest
naming the tag. The tag is not among the repository's refs, so the
reconciliation the test checks is unchanged. Countries on latest.json
keep the old pointer. The golden record is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@anth-volk
anth-volk merged commit 50da8c7 into main Oct 20, 2026
5 checks passed
@anth-volk
anth-volk deleted the uk-release-cuts-calibration-fit branch October 20, 2026 13:15
anth-volk added a commit that referenced this pull request Oct 20, 2026
#223 merged into main as 50da8c7, and the rest of stack #230 was rebased
onto it. #239's files are unchanged (753fb5c and 3ca39f3 have the same
tree), so this merge only records the new parent.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
anth-volk added a commit that referenced this pull request Oct 20, 2026
The tree builder is about to move out of the dashboard into its own
package. Its outputs are byte-exact contracts: the index records every
part's raw-JSON SHA-256 and gzip size, build ids derive from the inputs,
and a repair refuses any change to the index digest. So the move has to
be proved to change no byte.

This records, from the builder as it is today, what it writes for
representative inputs built from the fixtures the module tests already
use. The inputs cover US and UK, releases and staging runs (version 1,
version 2, and a staged dataset bundle), Belgium, and a UK release with
reported loss attribution. For each, the record holds every part's path,
raw JSON digest and size, gzip size and deflate-stream digest, plus the
build id. It also records release-to-staging comparison bundles built
through the comparison reader, the explorer's root responses read back
from the stored bytes, and the manifest serialization. The gzip header's
operating-system byte varies by platform, so the header is asserted
separately and the digest covers the stream after it.

A second test drives the publisher's dry-run repair of the recorded US,
UK and Belgium releases against a stubbed Hugging Face repository. The
publisher refuses a rebuilt index whose digest differs, so a successful
repair proves its own reads and hashing reproduce the recorded index.
The stubbed repository serves each country's release pointer at the path
the publisher reads it from: `latest.json`, or `latest-national.json`
for the UK since #223.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
anth-volk added a commit that referenced this pull request Oct 20, 2026
The tree builder and the schema 6 code the dashboard shares with it are
moving to the collector as a Bun worker, and its types and readers will
be published as a package the dashboard imports. That needs the builder
to be one self-contained unit with explicit dependencies and its own
tests. Inside frontend/lib nothing stopped a dashboard-only import from
reaching it.

The package, @policyengine/calibration-tree in frontend/packages/, is
the builder's import closure: the schema 6 types, parsers, serializers
and bundle builder, the comparison builder, Blob I/O behind the existing
injectable client, and the release and staging readers the builder reads
from, including the country registry. Its 30 modules move unchanged
apart from ten import lines that used the dashboard's path alias. Their
tests and fixtures move with them. Next.js routes, the HTTP helpers and
the client hooks stay in the dashboard and import the package through
its subpath exports.

One of the 30 is release-cut.ts, added by #223. It parses the Hugging
Face tag names Microcosm gives each build of a UK release, and
latest-artifact.ts and calibration-tree-manifest.ts import it, so it
moves with them and is exported as release-cut. The dashboard's shared
formatter and the publisher now import it through that export.

Two other additions since this branch began are adjusted to fit. #223's
releases route and its test import the moved modules through the
package. #229's check that the mapped measure concept table matches
integrations/microcosm_policyengine_us/mappings.yaml moves out of the
package's latest-artifact tests into
lib/microcosm/mapped-measure-concept-variables.test.ts, because it reads
a file of this repository that will not move with the package.

A boundary test requires package modules to import only each other,
Node built-ins and declared dependencies (@vercel/blob), and requires
every module to be exported. The package has its own typecheck, chained
into the frontend lint script, so CI runs it without a workflow change.
The readers pass Next.js's fetch cache hint, which Bun ignores; a
declaration seen only by the package's typecheck mirrors Next's.

The golden tests now import the builder through the package and
reproduce the record taken before the move, which moved unchanged. The
workspace sits inside frontend/ because Vercel, CI and the publisher
workflow all install from there. bunfig keeps Bun's hoisted linker so
node_modules keeps its current layout. The former countries path stays
as a re-export for code not yet switched to the package path.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
anth-volk added a commit that referenced this pull request Oct 20, 2026
#223 now checks the UK's latest-national.json whenever the registration
names it: the file must carry schema_version 1, the matching line and a
revision, and the tag it names must be the build its release manifest
names. The golden repair harness served only {release_id}, so the UK
dry-run repair stopped at "latest-national.json has unsupported
schema_version undefined."

For a country registered with its own pointer file, the stubbed
repository now serves a pointer naming a tag of the recorded release at
another commit, with that tag's folder listing and a release manifest
naming the tag. The tag is not among the repository's refs, so the
reconciliation the test checks is unchanged. Countries on latest.json
keep the old pointer. The golden record is unchanged.

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

This branch was successfully deployed

1 active deployment
Preview — 1079fa9f Deployed Oct 19, 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