Skip to content

Add an append-only ONS data vintage store#92

Open
vahid-ahmadi wants to merge 1 commit into
mainfrom
data-vintage-store
Open

Add an append-only ONS data vintage store#92
vahid-ahmadi wants to merge 1 commit into
mainfrom
data-vintage-store

Conversation

@vahid-ahmadi

Copy link
Copy Markdown
Contributor

Why

Everything on the site was pinned to published forecast vintages with no live official data behind it. That meant no way to score a forecast, and no way to tell whether an analysis had used data that existed at the time.

What

data/fetch.py pulls three ONS series and writes a dated snapshot per fetch:

name CDID dataset units
uk_gdp_cvm ABMI QNA £m, chained volume measure
uk_cpi_yoy D7G7 MM23 percent, year-on-year
uk_unemployment_rate MGSX LMS percent

Nothing is ever edited in place. An upstream revision arrives as a new file beside the old one, so revisions stay visible and any past number stays reproducible. forecasts/ records which vintage each score used.

Design decisions worth flagging:

  • A fetch that finds no upstream change writes nothing — otherwise real revisions get buried in a stream of identical daily files.
  • Network failures are reported as failures, never as "no revision". The two must not be confusable.
  • latest/ exists because the site is static under connect-src 'self' — the browser cannot call the ONS, so anything shown on a page has to be baked in at build time.
  • JSON, not Parquet. These series are small; a git-diffable format makes a revision a reviewable diff rather than an opaque binary blob.
  • The scheduled workflow opens a PR rather than pushing. A data revision changes what the site claims and should be seen by a human.

Verified against the live API

285 quarters of GDP to 2026Q1 · 150 of CPI to 2026Q2 (2.8%) · 221 of unemployment to 2026Q1. --check passes; re-running reports unchanged for all three.

Note the ONS API 403s the default urllib user agent and 404s (rather than redirecting) when a series moves topic — both handled, and documented in data/README.md.

🤖 Generated with Claude Code

Everything on the site was pinned to published forecast vintages with no live
official data behind it, so there was no way to score a forecast, and no way to
tell whether an analysis had used data that existed at the time.

data/fetch.py pulls three ONS series (real GDP ABMI, CPI annual rate D7G7,
unemployment rate MGSX) and writes a dated snapshot per fetch. Nothing is ever
edited in place: an upstream revision arrives as a new file beside the old one,
so revisions are visible and any past number stays reproducible.

- A fetch finding no upstream change writes nothing, so real revisions are not
  buried in a stream of identical files. Network failures are reported as
  failures, never as "no revision".
- latest/ is a flattened copy for the page builders. The site is static under a
  CSP with connect-src 'self', so the browser cannot call the ONS; anything
  shown has to be baked in at build time.
- JSON rather than Parquet: these series are small, and a git-diffable format
  makes a revision a reviewable diff instead of an opaque blob.
- fetch-vintages.yml runs weekday mornings after the release window and opens a
  PR rather than pushing.

Verified against the live API: 285 quarters of GDP to 2026Q1, 150 of CPI to
2026Q2 (2.8%), 221 of unemployment to 2026Q1.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 25, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
macromod Building Building Preview Jul 25, 2026 1:22am

Request Review

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.

1 participant